diff options
| author | Torbjörn Andersson | 2004-01-01 15:22:15 +0000 | 
|---|---|---|
| committer | Torbjörn Andersson | 2004-01-01 15:22:15 +0000 | 
| commit | 18f8916c3aef4b0dec659a0c053517bb9c7aa880 (patch) | |
| tree | 16240c407a58b01362e039b4141006dc1d49d369 /sword1 | |
| parent | 033a847e7769ce46a13fbcdd58230d22623600f7 (diff) | |
| download | scummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.tar.gz scummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.tar.bz2 scummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.zip  | |
Rewrote the music code. It now follows the same basic idea as the one in
BS2, which has worked pretty well so far. I haven't implemented pausing and
volume since the code I replaced didn't have it either, as far as I could
tell.
svn-id: r12070
Diffstat (limited to 'sword1')
| -rw-r--r-- | sword1/control.cpp | 1 | ||||
| -rw-r--r-- | sword1/music.cpp | 269 | ||||
| -rw-r--r-- | sword1/music.h | 44 | ||||
| -rw-r--r-- | sword1/sword1.cpp | 2 | 
4 files changed, 142 insertions, 174 deletions
diff --git a/sword1/control.cpp b/sword1/control.cpp index e4f7a28797..1216220aea 100644 --- a/sword1/control.cpp +++ b/sword1/control.cpp @@ -231,7 +231,6 @@ uint8 SwordControl::runPanel(void) {  	_music->startMusic(61, 1);  	do { -		_music->stream();  		if (newMode) {  			mode = newMode;  			fullRefresh = true; diff --git a/sword1/music.cpp b/sword1/music.cpp index 4f76dc21db..e4dfa33d84 100644 --- a/sword1/music.cpp +++ b/sword1/music.cpp @@ -19,192 +19,149 @@   *   */ -// todo: add fadeout, crossfading. -// this code always loops. make it depend on _loopFlag -  #include "stdafx.h"  #include "music.h"  #include "sound/mixer.h"  #include "common/util.h"  #include "common/file.h" +// This means fading takes about half a second. This may need some tuning... +#define FADE_SAMPLES 5512 + +// These functions are only called from SwordMusic, so I'm just going to +// assume that if locking is needed it has already been taken care of. + +void SwordMusicHandle::fadeDown() { +	if (_fading < 0) +		_fading = -_fading; +	else if (_fading == 0) +		_fading = FADE_SAMPLES; +} + +void SwordMusicHandle::fadeUp() { +	if (_fading > 0) +		_fading = -_fading; +	else if (_fading == 0) +		_fading = -FADE_SAMPLES; +} + +bool SwordMusicHandle::endOfData() const { +	return !streaming(); +} + +int SwordMusicHandle::readBuffer(int16 *buffer, const int numSamples) { +	int samples; +	for (samples = 0; samples < numSamples && !endOfData(); samples++) +		*buffer++ = read(); +	return samples; +} + +int16 SwordMusicHandle::read() { +	if (!streaming()) +		return 0; +	int16 sample = _file.readUint16LE(); +	if (_file.ioFailed()) { +		if (!_looping) { +			stop(); +			return 0; +		} +		_file.clearIOFailed(); +		_file.seek(WAVEHEADERSIZE); +		sample = _file.readUint16LE(); +	} +	if (_fading > 0) { +		if (--_fading == 0) { +			_looping = false; +			_file.close(); +		} +		sample = (sample * _fading) / FADE_SAMPLES; +	} else if (_fading < 0) { +		_fading++; +		sample = (sample * (FADE_SAMPLES + _fading)) / FADE_SAMPLES; +	} +	return sample; +} + +bool SwordMusicHandle::play(const char *filename, bool loop) { +	uint8 wavHeader[WAVEHEADERSIZE]; +	stop(); +	_file.open(filename); +	if (!_file.isOpen()) +		return false; +	_file.read(wavHeader, WAVEHEADERSIZE); +	_stereo = (READ_LE_UINT16(wavHeader + 0x16) == 2); +	_rate = READ_LE_UINT16(wavHeader + 0x18); +	_looping = loop; +	fadeUp(); +	return true; +} + +void SwordMusicHandle::stop() { +	if (_file.isOpen()) +		_file.close(); +	_fading = 0; +	_looping = false; +} +  SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {  	_system = system;  	_mixer = pMixer;  	_mixer->setupPremix(passMixerFunc, this); -	_fading = false; -	_playing = false; -	_loop = false;  	_mutex = _system->create_mutex(); -	_fadeSmpInBuf = _fadeBufPos = _waveSize = _wavePos = _bufPos = _smpInBuf = 0; -	assert(_mixer->getOutputRate() == 22050); -	_fadeBuf = NULL; -	_musicBuf = NULL; +	_converter[0] = NULL; +	_converter[1] = NULL;  }  SwordMusic::~SwordMusic() {  	_mixer->setupPremix(0, 0); +	delete _converter[0]; +	delete _converter[1];  }  void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {  	((SwordMusic*)param)->mixer(buf, len);  } -void SwordMusic::mixTo(int16 *src, int16 *dst, uint32 len) { -	if (!_playing) -		memset(dst, 0, len * 8); -	if (!_fading) { // no fading, simply copy it over -		for (uint32 cnt = 0; cnt < len; cnt++) -			dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] = -			dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = (int16)READ_LE_UINT16(src + cnt); -	} else { -		if (_fadeBuf) { // do a cross fade -			for (uint32 cnt = 0; cnt < len; cnt++) { -				int16 resVal = ((int16)READ_LE_UINT16(_fadeBuf + _fadeBufPos) * _fadeVal) >> 15; -				resVal += ((int16)READ_LE_UINT16(src + cnt) * (32768 - _fadeVal)) >> 15; -				dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] = -				dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = resVal; -				_fadeVal--; -				_fadeBufPos++; -				_fadeSmpInBuf--; -			} -			if ((!_fadeVal) || (!_fadeSmpInBuf)) { -				free(_fadeBuf); -				_fadeBuf = NULL; -				_fading = false; -			} -			if (_fadeBufPos == BUFSIZE) -				_fadeBufPos = 0; -		} else { // simple fadeout -			for (uint32 cnt = 0; cnt < len; cnt++) { -				dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] = -				dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] =  -				((int16)READ_LE_UINT16(src + cnt) * _fadeVal) >> 15; -				_fadeVal--; -			} -			if ((!_fadeVal) || (!_smpInBuf)) { -				_fading = _playing = false; -				free(_musicBuf); -				_musicBuf = NULL; -			} -		} -	} -} -  void SwordMusic::mixer(int16 *buf, uint32 len) { -	if (!_playing) { -		memset(buf, 0, 2 * len * sizeof(int16)); -		return; -	} -	uint32 remain = 0;	 -	if (_smpInBuf < (len >> 1)) { -		if (_loop) -			return; -		remain = (len >> 1) - _smpInBuf; -		len = _smpInBuf << 1; -	} -	_system->lock_mutex(_mutex); -	len >>= 1; -	while (len) { -		uint32 length = len; -		length = MIN(length, BUFSIZE - _bufPos); -		if (_fading && _fadeBuf) { -			length = MIN(length, (uint32)_fadeVal); -			length = MIN(length, _fadeSmpInBuf); -			length = MIN(length, BUFSIZE - _fadeBufPos); -		} -		mixTo(_musicBuf + _bufPos, buf, length); -		len -= length; -		buf += 4 * length; -		_bufPos += length; -		_smpInBuf -= length; -		if (_bufPos == BUFSIZE) -			_bufPos = 0; -	} -	if (remain) { -		memset(buf, 0, remain * 8); -		_playing = false; -	} -	_system->unlock_mutex(_mutex); -} - -void SwordMusic::stream(void) { -	// make sure we've got enough samples in buffer. -	if ((_smpInBuf < 4 * SAMPLERATE) && _playing && _musicFile.isOpen()) { -		_system->lock_mutex(_mutex); -		uint32 loadTotal = BUFSIZE - _smpInBuf; -		while (uint32 doLoad = loadTotal) { -			if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal) -				doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE; -			doLoad = MIN(doLoad, _waveSize - _wavePos); -			 -			int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE); -			_musicFile.read(dest, doLoad * 2); -			_wavePos += doLoad; -			if (_wavePos == _waveSize) { -				if (_loop) { -					_wavePos = 0; -					_musicFile.seek(WAVEHEADERSIZE); -				} else -					loadTotal = doLoad; -			} -			loadTotal -= doLoad; -			_smpInBuf += doLoad; +	Common::StackLock lock(_mutex); +	for (int i = 0; i < ARRAYSIZE(_handles); i++) { +		if (_handles[i].streaming() && _converter[i]) { +			st_volume_t vol = 255; +			_converter[i]->flow(_handles[i], buf, len, vol, vol);  		} -		_system->unlock_mutex(_mutex);  	}  }  void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) { -	_system->lock_mutex(_mutex); -	_loop = (loopFlag > 0); -	if (tuneId) {		 -		if (_musicFile.isOpen()) -			_musicFile.close(); +	Common::StackLock lock(_mutex); +	if (strlen(_tuneList[tuneId]) > 0) { +		int newStream = 0; +		if (_handles[0].streaming() && _handles[1].streaming()) { +			// If both handles are playing, stop the one that's +			// fading down. +			if (_handles[0].fading() > 0) +				_handles[0].stop(); +			else +				_handles[1].stop(); +		} +		if (_handles[0].streaming()) { +			_handles[0].fadeDown(); +			newStream = 1; +		} else if (_handles[1].streaming()) { +			_handles[1].fadeDown(); +			newStream = 0; +		}  		char fName[20];  		sprintf(fName, "music/%s.wav", _tuneList[tuneId]); -		_musicFile.open(fName); -		if (_musicFile.isOpen()) { -			if (_playing) { // do a cross fade -				_fadeBuf = _musicBuf; -				_fadeBufPos = _bufPos; -				_fadeSmpInBuf = _smpInBuf; -				_fading = true; -				_fadeVal = 32768; -			} else -				_fading = false; -			_musicBuf = (int16*)malloc(BUFSIZE * 2); - -			_musicFile.seek(0x28); -			_waveSize = _musicFile.readUint32LE() / 2; -			_wavePos = 0; -			_smpInBuf = 0; -			_bufPos = 0; -			_playing = true; -		} else { -			_fading = true; -			_fadeVal = 32768; -			if (_fadeBuf) { -				free(_fadeBuf); -				_fadeBuf = NULL; -			} -		} -	} else { -		if (_playing) -			fadeDown(); -		if (_musicFile.isOpen()) -			_musicFile.close(); +		_handles[newStream].play(fName, loopFlag); +		delete _converter[newStream]; +		_converter[newStream] = makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);  	} -	_system->unlock_mutex(_mutex); -	stream();  } -void SwordMusic::fadeDown(void) { -	_fadeVal = 32768; -	_fading = true; -	if (_fadeBuf) { -		free(_fadeBuf); -		_fadeBuf = NULL; -	} +void SwordMusic::fadeDown() { +	Common::StackLock lock(_mutex); +	for (int i = 0; i < ARRAYSIZE(_handles); i++) +		if (_handles[i].streaming()) +			_handles[i].fadeDown();  } - diff --git a/sword1/music.h b/sword1/music.h index 1b98239e76..7820efec3e 100644 --- a/sword1/music.h +++ b/sword1/music.h @@ -25,39 +25,53 @@  #include "scummsys.h"  #include "common/system.h"  #include "common/file.h" +#include "sound/audiostream.h" +#include "sound/rate.h" +  #define TOTAL_TUNES 270 -#define SAMPLERATE 11025 -#define BUFSIZE (6 * SAMPLERATE)  #define WAVEHEADERSIZE 0x2C  class SoundMixer; +class SwordMusicHandle : public AudioInputStream { +private: +	File _file; +	bool _looping; +	int32 _fading; +	int _rate; +	bool _stereo; +public: +	SwordMusicHandle() : _looping(false), _fading(0) {} +	virtual int readBuffer(int16 *buffer, const int numSamples); +	int16 read(); +	bool play(const char *filename, bool loop); +	void stop(); +	void fadeUp(); +	void fadeDown(); +	bool streaming() const { return _file.isOpen(); } +	int32 fading() { return _fading; } +	bool endOfData() const; +	bool endOfStream() const { return false; } +	bool isStereo() const { return _stereo; } +	int getRate() const { return _rate; } +}; +  class SwordMusic {  public:  	SwordMusic(OSystem *system, SoundMixer *pMixer);  	~SwordMusic(); -	void stream(void);  	void startMusic(int32 tuneId, int32 loopFlag); -	void fadeDown(void); +	void fadeDown();  private: -	File _musicFile; +	SwordMusicHandle _handles[2]; +	RateConverter *_converter[2];  	OSystem *_system;  	SoundMixer *_mixer; -	bool _fading; -	uint16 _fadeVal; -	bool _playing; -	bool _loop;  	OSystem::MutexRef _mutex;  	static void passMixerFunc(void *param, int16 *buf, uint len); -	void mixTo(int16 *src, int16 *dst, uint32 len);  	void mixer(int16 *buf, uint32 len);  	static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp -	uint32 _waveSize, _wavePos; -	int16 *_musicBuf; // samples for 6 seconds -	uint32 _bufPos, _smpInBuf; -	int16 *_fadeBuf; -	uint32 _fadeBufPos, _fadeSmpInBuf;  };  #endif // BSMUSIC_H diff --git a/sword1/sword1.cpp b/sword1/sword1.cpp index 19bbe51a03..5360910410 100644 --- a/sword1/sword1.cpp +++ b/sword1/sword1.cpp @@ -1116,7 +1116,6 @@ uint8 SwordEngine::mainLoop(void) {  		SwordLogic::_scriptVars[SCREEN] = SwordLogic::_scriptVars[NEW_SCREEN];  		do { -			_music->stream();  			uint32 frameTime = _system->get_msecs();  			_logic->engine();  			_logic->updateScreenParams(); // sets scrolling @@ -1154,7 +1153,6 @@ uint8 SwordEngine::mainLoop(void) {  		if ((retCode == 0) && (SwordLogic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade) {  			_screen->fadeDownPalette();  			while (_screen->stillFading()) { -				_music->stream();  				_screen->updateScreen();  				delay(1000/12);  			}  | 
