diff options
| author | Max Horn | 2007-02-28 14:48:26 +0000 | 
|---|---|---|
| committer | Max Horn | 2007-02-28 14:48:26 +0000 | 
| commit | 8c8abca6f80fc63b5c11fa43319cdf56b4845660 (patch) | |
| tree | ec031a874e67c92d3640824c2ee9816b5b6cab90 | |
| parent | dea688d0f5303e552bff8ff22798719d92ed53c1 (diff) | |
| download | scummvm-rg350-8c8abca6f80fc63b5c11fa43319cdf56b4845660.tar.gz scummvm-rg350-8c8abca6f80fc63b5c11fa43319cdf56b4845660.tar.bz2 scummvm-rg350-8c8abca6f80fc63b5c11fa43319cdf56b4845660.zip  | |
Changed the AppendableAudioStream code to use a queue of buffers, instead of a fixed size wrap-around memory buffer (this reduces memory usage in some cases by 500-700k, while actually being more flexible)
svn-id: r25909
| -rw-r--r-- | engines/kyra/vqa.cpp | 33 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse.cpp | 9 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_sndmgr.cpp | 4 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_track.cpp | 6 | ||||
| -rw-r--r-- | engines/scumm/smush/smush_mixer.cpp | 10 | ||||
| -rw-r--r-- | engines/scumm/smush/smush_player.cpp | 8 | ||||
| -rw-r--r-- | engines/sword1/sound.cpp | 6 | ||||
| -rw-r--r-- | sound/audiostream.cpp | 114 | ||||
| -rw-r--r-- | sound/audiostream.h | 32 | 
9 files changed, 127 insertions, 95 deletions
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 3660bcf217..603b67221b 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -268,8 +268,8 @@ bool VQAMovie::open(const char *filename) {  			_numPartialCodeBooks = 0;  			if (_header.flags & 1) { -				// A 2-second buffer ought to be enough -				_stream = Audio::makeAppendableAudioStream(_header.freq, Audio::Mixer::FLAG_UNSIGNED, 2 * _header.freq * _header.channels); +				// TODO/FIXME: Shouldn't we set FLAG_STEREO if _header.channels == 2 (wonders Fingolfin) +				_stream = Audio::makeAppendableAudioStream(_header.freq, Audio::Mixer::FLAG_UNSIGNED);  			} else {  				_stream = NULL;  			} @@ -399,9 +399,10 @@ void VQAMovie::displayFrame(uint frameNum) {  		switch (tag) {  		case MKID_BE('SND0'):	// Uncompressed sound  			foundSound = true; -			inbuf = (byte *)allocBuffer(0, size); +			inbuf = new byte[size];  			_file.read(inbuf, size); -			_stream->append(inbuf, size); +			assert(_stream); +			_stream->queueBuffer(inbuf, size);  			break;  		case MKID_BE('SND1'):	// Compressed sound, almost like AUD @@ -409,15 +410,18 @@ void VQAMovie::displayFrame(uint frameNum) {  			outsize = _file.readUint16LE();  			insize = _file.readUint16LE(); -			inbuf = (byte *)allocBuffer(0, insize); +			inbuf = new byte[insize];  			_file.read(inbuf, insize);  			if (insize == outsize) { -				_stream->append(inbuf, insize); +				assert(_stream); +				_stream->queueBuffer(inbuf, insize);  			} else { -				outbuf = (byte *)allocBuffer(1, outsize); +				outbuf = new byte[outsize];  				decodeSND1(inbuf, insize, outbuf, outsize); -				_stream->append(outbuf, outsize); +				assert(_stream); +				_stream->queueBuffer(outbuf, outsize); +				delete[] inbuf;  			}  			break; @@ -589,24 +593,25 @@ void VQAMovie::play() {  			switch (tag) {  			case MKID_BE('SND0'):	// Uncompressed sound -				inbuf = (byte *)allocBuffer(0, size); +				inbuf = new byte[size];  				_file.read(inbuf, size); -				_stream->append(inbuf, size); +				_stream->queueBuffer(inbuf, size);  				break;  			case MKID_BE('SND1'):	// Compressed sound  				outsize = _file.readUint16LE();  				insize = _file.readUint16LE(); -				inbuf = (byte *)allocBuffer(0, insize); +				inbuf = new byte[insize];  				_file.read(inbuf, insize);  				if (insize == outsize) { -					_stream->append(inbuf, insize); +					_stream->queueBuffer(inbuf, insize);  				} else { -					outbuf = (byte *)allocBuffer(1, outsize); +					outbuf = new byte[outsize];  					decodeSND1(inbuf, insize, outbuf, outsize); -					_stream->append(outbuf, outsize); +					_stream->queueBuffer(outbuf, outsize); +					delete[] inbuf;  				}  				break; diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 7e70268b12..c249dd57a9 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -188,9 +188,8 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {  				track->mixerFlags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;  #endif -			int32 streamBufferSize = track->iteration;  			track->stream2 = NULL; -			track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize); +			track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags);  			const int pan = (track->pan != 64) ? 2 * track->pan - 127 : 0;  			const int vol = track->vol / 1000; @@ -324,10 +323,10 @@ void IMuseDigital::callback() {  					if (_mixer->isReady()) {  						_mixer->setChannelVolume(track->handle, vol);  						_mixer->setChannelBalance(track->handle, pan); -						track->stream->append(data, result); +						track->stream->queueBuffer(data, result);  						track->regionOffset += result; -					} -					free(data); +					} else +						delete[] data;  					if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {  						switchToNextRegion(track); diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp index 2b88f37b17..5c7fa5b613 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -583,11 +583,11 @@ int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, b  	if ((soundHandle->bundle) && (!soundHandle->compressed)) {  		size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);  	} else if (soundHandle->resPtr) { -		*buf = (byte *)malloc(size); +		*buf = new byte[size];  		assert(*buf);  		memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);  	} else if ((soundHandle->bundle) && (soundHandle->compressed)) { -		*buf = (byte *)malloc(size); +		*buf = new byte[size];  		assert(*buf);  		char fileName[24];  		sprintf(fileName, "%s_reg%03d", soundHandle->name, region); diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp index 37ae22f47f..6acb2a0318 100644 --- a/engines/scumm/imuse_digi/dimuse_track.cpp +++ b/engines/scumm/imuse_digi/dimuse_track.cpp @@ -176,9 +176,8 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,  			type = Audio::Mixer::kMusicSoundType;  		// setup 1 second stream wrapped buffer -		int32 streamBufferSize = track->iteration;  		track->stream2 = NULL; -		track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize); +		track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags);  		_mixer->playInputStream(type, &track->handle, track->stream, -1, vol, pan, false);  		track->started = true;  	} @@ -356,8 +355,7 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDel  		type = Audio::Mixer::kMusicSoundType;  	// setup 1 second stream wrapped buffer -	int32 streamBufferSize = fadeTrack->iteration; -	fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags, streamBufferSize); +	fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags);  	_mixer->playInputStream(type, &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);  	fadeTrack->started = true;  	fadeTrack->used = true; diff --git a/engines/scumm/smush/smush_mixer.cpp b/engines/scumm/smush/smush_mixer.cpp index 9e6631a365..e29a921224 100644 --- a/engines/scumm/smush/smush_mixer.cpp +++ b/engines/scumm/smush/smush_mixer.cpp @@ -105,6 +105,7 @@ bool SmushMixer::handleFrame() {  				_channels[i].chan->getParameters(stereo, is_16bit, vol, pan); +				// Grab the audio data from the channel  				int32 size = _channels[i].chan->getAvailableSoundDataSize();  				byte *data = _channels[i].chan->getSoundData(); @@ -116,15 +117,16 @@ bool SmushMixer::handleFrame() {  				}  				if (_mixer->isReady()) { +					// Stream the data  					if (!_channels[i].stream) { -						_channels[i].stream = Audio::makeAppendableAudioStream(_channels[i].chan->getRate(), flags, 500000); +						_channels[i].stream = Audio::makeAppendableAudioStream(_channels[i].chan->getRate(), flags);  						_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_channels[i].handle, _channels[i].stream);  					}  					_mixer->setChannelVolume(_channels[i].handle, vol);  					_mixer->setChannelBalance(_channels[i].handle, pan); -					_channels[i].stream->append(data, size); -				} -				delete[] data; +					_channels[i].stream->queueBuffer(data, size);	// The stream will free the buffer for us +				} else +					delete[] data;  			}  		}  	} diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index d4b3352be4..3310415f30 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -462,7 +462,7 @@ void SmushPlayer::handleIACT(Chunk &b) {  			c->checkParameters(index, nbframes, size, track_flags, unknown);  		c->appendData(b, bsize);  	} else { -		byte output_data[4096]; +		// TODO: Move this code into another SmushChannel subclass?  		byte *src = (byte *)malloc(bsize);  		b.read(src, bsize);  		byte *d_src = src; @@ -477,6 +477,8 @@ void SmushPlayer::handleIACT(Chunk &b) {  					_IACTpos += bsize;  					bsize = 0;  				} else { +					byte *output_data = new byte[4096]; +  					memcpy(_IACToutput + _IACTpos, d_src, len);  					byte *dst = output_data;  					byte *d_src2 = _IACToutput; @@ -507,10 +509,10 @@ void SmushPlayer::handleIACT(Chunk &b) {  					} while (--count);  					if (!_IACTstream) { -						_IACTstream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_STEREO | Audio::Mixer::FLAG_16BITS, 900000); +						_IACTstream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_STEREO | Audio::Mixer::FLAG_16BITS);  						_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_IACTchannel, _IACTstream);  					} -					_IACTstream->append(output_data, 0x1000); +					_IACTstream->queueBuffer(output_data, 0x1000);  					bsize -= len;  					d_src += len; diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp index fd0a37003e..6c255cb4ce 100644 --- a/engines/sword1/sound.cpp +++ b/engines/sword1/sound.cpp @@ -382,10 +382,8 @@ void Sound::initCowSystem(void) {  }  void Sound::closeCowSystem(void) { -	if (_cowFile.isOpen()) -		_cowFile.close(); -	if (_cowHeader) -		free(_cowHeader); +	_cowFile.close(); +	free(_cowHeader);  	_cowHeader = NULL;  	_currentCowFile = 0;  } diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index d3c0e2e745..54b0221199 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -23,6 +23,7 @@  #include "common/stdafx.h"  #include "common/endian.h"  #include "common/file.h" +#include "common/list.h"  #include "common/util.h"  #include "sound/audiostream.h" @@ -128,7 +129,6 @@ protected:  	const int _rate;  	const byte *_origPtr; -	inline bool eosIntern() const	{ return _ptr >= _end; };  public:  	LinearMemoryStream(int rate, const byte *ptr, uint len, uint loopOffset, uint loopLen, bool autoFreeMemory)  		: _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0), _rate(rate) { @@ -154,7 +154,7 @@ public:  	int readBuffer(int16 *buffer, const int numSamples);  	bool isStereo() const		{ return stereo; } -	bool endOfData() const		{ return eosIntern(); } +	bool endOfData() const		{ return _ptr >= _end; }  	int getRate() const			{ return _rate; }  }; @@ -162,7 +162,7 @@ public:  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>  int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {  	int samples = 0; -	while (samples < numSamples && !eosIntern()) { +	while (samples < numSamples && _ptr < _end) {  		const int len = MIN(numSamples, samples + (int)(_end - _ptr) / (is16Bit ? 2 : 1));  		while (samples < len) {  			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); @@ -170,7 +170,7 @@ int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buf  			samples++;  		}  		// Loop, if looping was specified -		if (_loopPtr && eosIntern()) { +		if (_loopPtr && _ptr >= _end) {  			_ptr = _loopPtr;  			_end = _loopEnd;  		} @@ -228,6 +228,10 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32  #pragma mark --- Appendable audio stream ---  #pragma mark - +struct Buffer { +	byte *start; +	byte *end; +};  /**   * Wrapped memory stream. @@ -235,18 +239,22 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>  class AppendableMemoryStream : public AppendableAudioStream {  protected: + +	// A mutex to avoid access problems (causing e.g. corruption of +	// the linked list) in thread aware environments.  	Common::Mutex _mutex; -	byte *_bufferStart; -	byte *_bufferEnd; -	byte *_pos; -	byte *_end; +	// List of all queueud buffers	 +	Common::List<Buffer> _bufferQueue; + +	// Position in the front buffer, if any  	bool _finalized;  	const int _rate; +	byte *_pos; -	inline bool eosIntern() const { return _end == _pos; }; +	inline bool eosIntern() const { return _bufferQueue.empty(); };  public: -	AppendableMemoryStream(int rate, uint bufferSize); +	AppendableMemoryStream(int rate);  	~AppendableMemoryStream();  	int readBuffer(int16 *buffer, const int numSamples); @@ -256,30 +264,22 @@ public:  	int getRate() const			{ return _rate; } -	void append(const byte *data, uint32 len); +	void queueBuffer(byte *data, uint32 size);  	void finish()				{ _finalized = true; }  };  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::AppendableMemoryStream(int rate, uint bufferSize) - : _finalized(false), _rate(rate) { - -	// Verify the buffer size is sane -	if (is16Bit && stereo) -		assert((bufferSize & 3) == 0); -	else if (is16Bit || stereo) -		assert((bufferSize & 1) == 0); - -	_bufferStart = (byte *)malloc(bufferSize); -	assert(_bufferStart != NULL); +AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::AppendableMemoryStream(int rate) + : _finalized(false), _rate(rate), _pos(0) { -	_pos = _end = _bufferStart; -	_bufferEnd = _bufferStart + bufferSize;  }  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>  AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::~AppendableMemoryStream() { -	free(_bufferStart); +	// Clear the queue +	Common::List<Buffer>::iterator iter; +	for (iter = _bufferQueue.begin(); iter != _bufferQueue.end(); ++iter) +		delete[] iter->start;  }  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> @@ -288,12 +288,19 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16  	int samples = 0;  	while (samples < numSamples && !eosIntern()) { -		// Wrap around? -		if (_pos >= _bufferEnd) -			_pos = _pos - (_bufferEnd - _bufferStart); +		Buffer buf = *_bufferQueue.begin(); +		if (_pos == 0) +			_pos = buf.start; + +		assert(buf.start <= _pos && _pos <= buf.end); +		const int samplesLeftInCurBuffer = buf.end - _pos; +		if (samplesLeftInCurBuffer == 0) { +			_bufferQueue.erase(_bufferQueue.begin()); +			_pos = 0; +			continue; +		} -		const byte *endMarker = (_pos > _end) ? _bufferEnd : _end; -		const int len = MIN(numSamples, samples + (int)(endMarker - _pos) / (is16Bit ? 2 : 1)); +		const int len = MIN(numSamples, samples + samplesLeftInCurBuffer / (is16Bit ? 2 : 1));  		while (samples < len) {  			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _pos, isLE);  			_pos += (is16Bit ? 2 : 1); @@ -305,50 +312,45 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16  }  template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -void AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::append(const byte *data, uint32 len) { +void AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::queueBuffer(byte *data, uint32 size) {  	Common::StackLock lock(_mutex);  	// Verify the buffer size is sane  	if (is16Bit && stereo) -		assert((len & 3) == 0); +		assert((size & 3) == 0);  	else if (is16Bit || stereo) -		assert((len & 1) == 0); +		assert((size & 1) == 0);  	// Verify that the stream has not yet been finalized (by a call to finish())  	assert(!_finalized); -	if (_end + len > _bufferEnd) { -		// Wrap-around case -		uint32 size_to_end_of_buffer = _bufferEnd - _end; -		len -= size_to_end_of_buffer; -		if ((_end < _pos) || (_bufferStart + len >= _pos)) { -			debug(2, "AppendableMemoryStream: buffer overflow (A)"); -			return; -		} -		memcpy(_end, data, size_to_end_of_buffer); -		memcpy(_bufferStart, data + size_to_end_of_buffer, len); -		_end = _bufferStart + len; -	} else { -		if ((_end < _pos) && (_end + len >= _pos)) { -			debug(2, "AppendableMemoryStream: buffer overflow (B)"); -			return; -		} -		memcpy(_end, data, len); -		_end += len; -	} +	// Queue the buffer +	Buffer buf = {data, data+size}; +	_bufferQueue.push_back(buf); + + +#if 0 +	// Output some stats +	uint totalSize = 0; +	Common::List<Buffer>::iterator iter; +	for (iter = _bufferQueue.begin(); iter != _bufferQueue.end(); ++iter) +		totalSize += iter->end - iter->start; +	printf("AppendableMemoryStream::queueBuffer: added a %d byte buf, a total of %d bytes are queued\n", +				size, totalSize); +#endif  }  #define MAKE_WRAPPED(STEREO, UNSIGNED) \  		if (is16Bit) { \  			if (isLE) \ -				return new AppendableMemoryStream<STEREO, true, UNSIGNED, true>(rate, len); \ +				return new AppendableMemoryStream<STEREO, true, UNSIGNED, true>(rate); \  			else  \ -				return new AppendableMemoryStream<STEREO, true, UNSIGNED, false>(rate, len); \ +				return new AppendableMemoryStream<STEREO, true, UNSIGNED, false>(rate); \  		} else \ -			return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate, len) +			return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate) -AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len) { +AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags) {  	const bool isStereo = (_flags & Audio::Mixer::FLAG_STEREO) != 0;  	const bool is16Bit = (_flags & Audio::Mixer::FLAG_16BITS) != 0;  	const bool isUnsigned = (_flags & Audio::Mixer::FLAG_UNSIGNED) != 0; diff --git a/sound/audiostream.h b/sound/audiostream.h index b76f2f9cd2..499fb782ab 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -31,7 +31,8 @@  namespace Audio {  /** - * Generic input stream for the resampling code. + * Generic audio input stream. Subclasses of this are used to feed arbitrary + * sampled audio data into ScummVM's audio mixer.   */  class AudioStream {  public: @@ -89,6 +90,13 @@ public:  	static AudioStream* openStreamFile(const char *filename);  }; +/** + * Factory function for a raw linear AudioStream, which will simply treat all data + * in the buffer described by ptr and len as raw sample data in the specified + * format. It will then simply pass this data directly to the mixer, after converting + * it to the sample format used by the mixer (i.e. 16 bit signed native endian). + * Optionally supports (infinite) looping of a portion of the data. + */  AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen);  /** @@ -97,11 +105,29 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32   */  class AppendableAudioStream : public Audio::AudioStream {  public: -	virtual void append(const byte *data, uint32 len) = 0; +	 +	/** +	 * Queue another audio data buffer for playback. The stream +	 * will playback all queued buffers, in the order they were +	 * queued. After all data contained in them has been played, +	 * the buffer will be delete[]'d (so make sure to allocate them +	 * with new[], not with malloc). +	 */ +	virtual void queueBuffer(byte *data, uint32 size) = 0; +	 +	/** +	 * Mark the stream as finished, that is, signal that no further data +	 * will be appended to it. Only after this has been done can the +	 * AppendableAudioStream ever 'end' ( +	 */  	virtual void finish() = 0;  }; -AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len); +/** + * Factory function for an AppendableAudioStream. The rate and flags + * parameters are analog to those used in makeLinearInputStream. + */ +AppendableAudioStream *makeAppendableAudioStream(int rate, byte flags);  } // End of namespace Audio  | 
