diff options
| -rw-r--r-- | engines/kyra/sound_towns.cpp | 1 | ||||
| -rw-r--r-- | engines/made/resource.cpp | 1 | ||||
| -rw-r--r-- | engines/mohawk/sound.cpp | 1 | ||||
| -rw-r--r-- | engines/mohawk/video/qt_player.cpp | 1 | ||||
| -rw-r--r-- | engines/parallaction/sound_br.cpp | 1 | ||||
| -rw-r--r-- | engines/parallaction/sound_ns.cpp | 1 | ||||
| -rw-r--r-- | engines/saga/music.cpp | 1 | ||||
| -rw-r--r-- | engines/sci/sound/audio.cpp | 1 | ||||
| -rw-r--r-- | engines/sci/sound/iterator/iterator.cpp | 1 | ||||
| -rw-r--r-- | engines/sci/sound/music.cpp | 1 | ||||
| -rw-r--r-- | engines/sci/sound/seq/instrument-map.cpp | 1 | ||||
| -rw-r--r-- | engines/scumm/he/cup_player_he.cpp | 1 | ||||
| -rw-r--r-- | engines/scumm/player_mod.cpp | 1 | ||||
| -rw-r--r-- | engines/scumm/player_pce.cpp | 1 | ||||
| -rw-r--r-- | engines/tucker/sequences.cpp | 1 | ||||
| -rw-r--r-- | sound/aiff.cpp | 1 | ||||
| -rw-r--r-- | sound/audiostream.cpp | 428 | ||||
| -rw-r--r-- | sound/audiostream.h | 70 | ||||
| -rw-r--r-- | sound/iff_sound.cpp | 1 | ||||
| -rw-r--r-- | sound/mixer.cpp | 1 | ||||
| -rw-r--r-- | sound/module.mk | 1 | ||||
| -rw-r--r-- | sound/raw.cpp | 463 | ||||
| -rw-r--r-- | sound/raw.h | 108 | ||||
| -rw-r--r-- | sound/shorten.cpp | 1 | ||||
| -rw-r--r-- | sound/voc.cpp | 1 | ||||
| -rw-r--r-- | sound/wave.cpp | 1 | 
26 files changed, 600 insertions, 491 deletions
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 2c42e7fb2b..b4da44df6a 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -30,6 +30,7 @@  #include "sound/audiocd.h"  #include "sound/audiostream.h" +#include "sound/raw.h"  #include "common/util.h" diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index 2913d23b27..335634598a 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -25,6 +25,7 @@  #include "common/endian.h"  #include "sound/mixer.h" +#include "sound/raw.h"  #include "made/resource.h"  #include "made/graphics.h" diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index db40555dc9..1c70972b0a 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -29,6 +29,7 @@  #include "sound/audiostream.h"  #include "sound/mp3.h" +#include "sound/raw.h"  #include "sound/wave.h" diff --git a/engines/mohawk/video/qt_player.cpp b/engines/mohawk/video/qt_player.cpp index 2cb1ed364c..50928a0aac 100644 --- a/engines/mohawk/video/qt_player.cpp +++ b/engines/mohawk/video/qt_player.cpp @@ -40,6 +40,7 @@  // Audio codecs  #include "sound/adpcm.h" +#include "sound/raw.h"  #include "mohawk/video/qdm2.h"  // Video codecs diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp index 003861d501..1441a313bc 100644 --- a/engines/parallaction/sound_br.cpp +++ b/engines/parallaction/sound_br.cpp @@ -31,6 +31,7 @@  #include "sound/mididrv.h"  #include "sound/midiparser.h"  #include "sound/mods/protracker.h" +#include "sound/raw.h"  #include "parallaction/disk.h"  #include "parallaction/parallaction.h" diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp index 7bd9970c64..e9215cf117 100644 --- a/engines/parallaction/sound_ns.cpp +++ b/engines/parallaction/sound_ns.cpp @@ -30,6 +30,7 @@  #include "sound/mixer.h"  #include "sound/midiparser.h"  #include "sound/mods/protracker.h" +#include "sound/raw.h"  #include "parallaction/sound.h"  #include "parallaction/parallaction.h" diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 32f2a3d1a4..bd089f1b38 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -33,6 +33,7 @@  #include "sound/audiostream.h"  #include "sound/mididrv.h"  #include "sound/midiparser.h" +#include "sound/raw.h"  #include "common/config-manager.h"  #include "common/file.h" diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 5771debd60..e43d7d001f 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -32,6 +32,7 @@  #include "sound/audiostream.h"  #include "sound/audiocd.h" +#include "sound/raw.h"  #include "sound/wave.h"  namespace Sci { diff --git a/engines/sci/sound/iterator/iterator.cpp b/engines/sci/sound/iterator/iterator.cpp index 513e74325c..232a40f121 100644 --- a/engines/sci/sound/iterator/iterator.cpp +++ b/engines/sci/sound/iterator/iterator.cpp @@ -36,6 +36,7 @@  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  namespace Sci { diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index bea15ca900..8a99c34076 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -24,6 +24,7 @@   */  #include "sound/audiostream.h" +#include "sound/raw.h"  #include "common/config-manager.h"  #include "sci/sci.h" diff --git a/engines/sci/sound/seq/instrument-map.cpp b/engines/sci/sound/seq/instrument-map.cpp index 2f1fdb2532..0390e86d32 100644 --- a/engines/sci/sound/seq/instrument-map.cpp +++ b/engines/sci/sound/seq/instrument-map.cpp @@ -24,6 +24,7 @@   */  #include "common/scummsys.h" +#include "common/endian.h"  #include "sci/sound/softseq/mididriver.h"  #include "sci/sound/seq/instrument-map.h" diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp index 25baa24bde..dc4eafe56b 100644 --- a/engines/scumm/he/cup_player_he.cpp +++ b/engines/scumm/he/cup_player_he.cpp @@ -28,6 +28,7 @@  #include "common/system.h"  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  #include "scumm/scumm.h"  #include "scumm/util.h"  #include "scumm/he/intern_he.h" diff --git a/engines/scumm/player_mod.cpp b/engines/scumm/player_mod.cpp index 1b18b8f58f..6495da6d48 100644 --- a/engines/scumm/player_mod.cpp +++ b/engines/scumm/player_mod.cpp @@ -27,6 +27,7 @@  #include "scumm/player_mod.h"  #include "sound/mixer.h"  #include "sound/rate.h" +#include "sound/raw.h"  namespace Scumm { diff --git a/engines/scumm/player_pce.cpp b/engines/scumm/player_pce.cpp index 5e8a0cdca5..bd0a358c3e 100644 --- a/engines/scumm/player_pce.cpp +++ b/engines/scumm/player_pce.cpp @@ -33,6 +33,7 @@  #include <math.h>  #include "player_pce.h" +#include "common/endian.h"  // PCE sound engine is only used by Loom, which requires 16bit color support  #ifdef USE_RGB_COLOR diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index d991a6e3de..16dba3e346 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -26,6 +26,7 @@  #include "common/system.h"  #include "sound/audiostream.h" +#include "sound/raw.h"  #include "sound/wave.h"  #include "tucker/tucker.h" diff --git a/sound/aiff.cpp b/sound/aiff.cpp index 884a2382b6..b1f00c714e 100644 --- a/sound/aiff.cpp +++ b/sound/aiff.cpp @@ -38,6 +38,7 @@  #include "sound/aiff.h"  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  namespace Audio { diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index 578a4a78c0..2f7be667b7 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -30,19 +30,11 @@  #include "common/util.h"  #include "sound/audiostream.h" +#include "sound/flac.h"  #include "sound/mixer.h"  #include "sound/mp3.h" +#include "sound/raw.h"  #include "sound/vorbis.h" -#include "sound/flac.h" - - -// This used to be an inline template function, but -// buggy template function handling in MSVC6 forced -// us to go with the macro approach. So far this is -// the only template function that MSVC6 seemed to -// compile incorrectly. Knock on wood. -#define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE) \ -	((is16Bit ? (isLE ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0))  namespace Audio { @@ -256,424 +248,16 @@ bool SubSeekableAudioStream::seek(const Timestamp &where) {  }  #pragma mark - -#pragma mark --- RawMemoryStream --- -#pragma mark - - -uint32 calculateSampleOffset(const Timestamp &where, int rate) { -	return where.convertToFramerate(rate).totalNumberOfFrames(); -} - -/** - * A simple raw audio stream, purely memory based. It operates on a single - * block of data, which is passed to it upon creation. - * Optionally supports looping the sound. - * - * Design note: This code tries to be as efficient as possible (without - * resorting to assembly, that is). To this end, it is written as a template - * class. This way the compiler can create optimized code for each special - * case. This results in a total of 12 versions of the code being generated. - */ -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -class RawMemoryStream : public SeekableAudioStream { -protected: -	const byte *_ptr; -	const byte *_end; -	const int _rate; -	const byte *_origPtr; -	const DisposeAfterUse::Flag _disposeAfterUse; -	const Timestamp _playtime; - -public: -	RawMemoryStream(int rate, const byte *ptr, uint len, DisposeAfterUse::Flag autoFreeMemory) -	    : _ptr(ptr), _end(ptr+len), _rate(rate), _origPtr(ptr), -	      _disposeAfterUse(autoFreeMemory), -	      _playtime(0, len / (is16Bit ? 2 : 1) / (stereo ? 2 : 1), rate) { -	} - -	virtual ~RawMemoryStream() { -		if (_disposeAfterUse == DisposeAfterUse::YES) -			free(const_cast<byte *>(_origPtr)); -	} - -	int readBuffer(int16 *buffer, const int numSamples); - -	bool isStereo() const			{ return stereo; } -	bool endOfData() const			{ return _ptr >= _end; } - -	int getRate() const				{ return _rate; } -	bool seek(const Timestamp &where); -	Timestamp getLength() const { return _playtime; } -}; - -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -int RawMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { -	int samples = numSamples; -	while (samples > 0 && _ptr < _end) { -		int len = MIN(samples, (int)(_end - _ptr) / (is16Bit ? 2 : 1)); -		samples -= len; -		do { -			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); -			_ptr += (is16Bit ? 2 : 1); -		} while (--len); -	} -	return numSamples-samples; -} - -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -bool RawMemoryStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp &where) { -	const uint8 *ptr = _origPtr + calculateSampleOffset(where, getRate()) * (is16Bit ? 2 : 1) * (stereo ? 2 : 1); -	if (ptr > _end) { -		_ptr = _end; -		return false; -	} else if (ptr == _end) { -		_ptr = _end; -		return true; -	} else { -		_ptr = ptr; -		return true; -	} -} - -#pragma mark - -#pragma mark --- RawDiskStream --- -#pragma mark - - - - -/** - *  RawDiskStream.  This can stream raw PCM audio data from disk.  The - *  function takes an pointer to an array of RawDiskStreamAudioBlock which defines the - *  start position and length of each block of uncompressed audio in the stream. - */ -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -class RawDiskStream : public SeekableAudioStream { - -// Allow backends to override buffer size -#ifdef CUSTOM_AUDIO_BUFFER_SIZE -	static const int32 BUFFER_SIZE = CUSTOM_AUDIO_BUFFER_SIZE; -#else -	static const int32 BUFFER_SIZE = 16384; -#endif - -protected: -	byte* _buffer;			///< Streaming buffer -	const byte *_ptr;		///< Pointer to current position in stream buffer -	const int _rate;		///< Sample rate of stream - -	Timestamp _playtime;	///< Calculated total play time -	Common::SeekableReadStream *_stream;	///< Stream to read data from -	int32 _filePos;			///< Current position in stream -	int32 _diskLeft;		///< Samples left in stream in current block not yet read to buffer -	int32 _bufferLeft;		///< Samples left in buffer in current block -	const DisposeAfterUse::Flag _disposeAfterUse;		///< Indicates whether the stream object should be deleted when this RawDiskStream is destructed - -	RawDiskStreamAudioBlock *_audioBlock;	///< Audio block list -	const int _audioBlockCount;		///< Number of blocks in _audioBlock -	int _currentBlock;		///< Current audio block number -public: -	RawDiskStream(int rate, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, uint numBlocks) -		: _rate(rate), _playtime(0, rate), _stream(stream), _disposeAfterUse(disposeStream), -		  _audioBlockCount(numBlocks) { - -		assert(numBlocks > 0); - -		// Allocate streaming buffer -		if (is16Bit) { -			_buffer = (byte *)malloc(BUFFER_SIZE * sizeof(int16)); -		} else { -			_buffer = (byte *)malloc(BUFFER_SIZE * sizeof(byte)); -		} - -		_ptr = _buffer; -		_bufferLeft = 0; - -		// Copy audio block data to our buffer -		// TODO: Replace this with a Common::Array or Common::List to -		// make it a little friendlier. -		_audioBlock = new RawDiskStreamAudioBlock[numBlocks]; -		memcpy(_audioBlock, block, numBlocks * sizeof(RawDiskStreamAudioBlock)); - -		// Set current buffer state, playing first block -		_currentBlock = 0; -		_filePos = _audioBlock[_currentBlock].pos; -		_diskLeft = _audioBlock[_currentBlock].len; - -		// Add up length of all blocks in order to caluclate total play time -		int len = 0; -		for (int r = 0; r < _audioBlockCount; r++) { -			len += _audioBlock[r].len; -		} -		_playtime = Timestamp(0, len / (is16Bit ? 2 : 1) / (stereo ? 2 : 1), rate); -	} - - -	virtual ~RawDiskStream() { -		if (_disposeAfterUse == DisposeAfterUse::YES) { -			delete _stream; -		} - -		delete[] _audioBlock; -		free(_buffer); -	} -	int readBuffer(int16 *buffer, const int numSamples); - -	bool isStereo() const			{ return stereo; } -	bool endOfData() const			{ return (_currentBlock == _audioBlockCount - 1) && (_diskLeft == 0) && (_bufferLeft == 0); } - -	int getRate() const			{ return _rate; } -	Timestamp getLength() const { return _playtime; } - -	bool seek(const Timestamp &where); -}; - -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -int RawDiskStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { -	int oldPos = _stream->pos(); -	bool restoreFilePosition = false; - -	int samples = numSamples; - -	while (samples > 0 && ((_diskLeft > 0 || _bufferLeft > 0) || (_currentBlock != _audioBlockCount - 1))  ) { -		// Output samples in the buffer to the output -		int len = MIN<int>(samples, _bufferLeft); -		samples -= len; -		_bufferLeft -= len; - -		while (len > 0) { -			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); -			_ptr += (is16Bit ? 2 : 1); -			len--; -		} - -		// Have we now finished this block?  If so, read the next block -		if ((_bufferLeft == 0) && (_diskLeft == 0) && (_currentBlock != _audioBlockCount - 1)) { -			// Next block -			_currentBlock++; - -			_filePos = _audioBlock[_currentBlock].pos; -			_diskLeft = _audioBlock[_currentBlock].len; -		} -			 -		// Now read more data from disk if there is more to be read -		if ((_bufferLeft == 0) && (_diskLeft > 0)) { -			int32 readAmount = MIN(_diskLeft, BUFFER_SIZE); - -			_stream->seek(_filePos, SEEK_SET); -			_stream->read(_buffer, readAmount * (is16Bit? 2: 1)); - -			// Amount of data in buffer is now the amount read in, and -			// the amount left to read on disk is decreased by the same amount -			_bufferLeft = readAmount; -			_diskLeft -= readAmount; -			_ptr = (byte *)_buffer; -			_filePos += readAmount * (is16Bit ? 2 : 1); - -			// Set this flag now we've used the file, it restores it's -			// original position. -			restoreFilePosition = true; -		} -	} - -	// In case calling code relies on the position of this stream staying  -	// constant, I restore the location if I've changed it.  This is probably -	// not necessary. -	if (restoreFilePosition) { -		_stream->seek(oldPos, SEEK_SET); -	} - -	return numSamples - samples; -} - -template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> -bool RawDiskStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp &where) { -	const uint32 seekSample = calculateSampleOffset(where, getRate()) * (stereo ? 2 : 1); -	uint32 curSample = 0; - -	// Search for the disk block in which the specific sample is placed -	_currentBlock = 0; -	while (_currentBlock < _audioBlockCount) { -		uint32 nextBlockSample = curSample + _audioBlock[_currentBlock].len; - -		if (nextBlockSample > seekSample) -			break; - -		curSample = nextBlockSample; -		++_currentBlock; -	} - -	_filePos = 0; -	_diskLeft = 0; -	_bufferLeft = 0; - -	if (_currentBlock == _audioBlockCount) { -		return ((seekSample - curSample) == (uint32)_audioBlock[_currentBlock - 1].len); -	} else { -		const uint32 offset = seekSample - curSample; - -		_filePos = _audioBlock[_currentBlock].pos + offset * (is16Bit ? 2 : 1); -		_diskLeft = _audioBlock[_currentBlock].len - offset; - -		return true; -	} -} - -#pragma mark - -#pragma mark --- Input stream factory --- +#pragma mark --- Queueing audio stream ---  #pragma mark - -/* In the following, we use preprocessor / macro tricks to simplify the code - * which instantiates the input streams. We used to use template functions for - * this, but MSVC6 / EVC 3-4 (used for WinCE builds) are extremely buggy when it - * comes to this feature of C++... so as a compromise we use macros to cut down - * on the (source) code duplication a bit. - * So while normally macro tricks are said to make maintenance harder, in this - * particular case it should actually help it :-) - */ - -#define MAKE_LINEAR(STEREO, UNSIGNED) \ -		if (is16Bit) { \ -			if (isLE) \ -				return new RawMemoryStream<STEREO, true, UNSIGNED, true>(rate, ptr, len, autoFree); \ -			else  \ -				return new RawMemoryStream<STEREO, true, UNSIGNED, false>(rate, ptr, len, autoFree); \ -		} else \ -			return new RawMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, autoFree) - -SeekableAudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, byte flags) { -	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; -	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; -	const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0; -	const bool isLE       = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0; -	const DisposeAfterUse::Flag autoFree   = (flags & Mixer::FLAG_AUTOFREE) != 0 ? DisposeAfterUse::YES : DisposeAfterUse::NO; - -	// Verify the buffer sizes are sane -	if (is16Bit && isStereo) { -		assert((len & 3) == 0); -	} else if (is16Bit || isStereo) { -		assert((len & 1) == 0); -	} -	if (isStereo) { -		if (isUnsigned) { -			MAKE_LINEAR(true, true); -		} else { -			MAKE_LINEAR(true, false); -		} -	} else { -		if (isUnsigned) { -			MAKE_LINEAR(false, true); -		} else { -			MAKE_LINEAR(false, false); -		} -	} +void QueuingAudioStream::queueBuffer(byte *data, uint32 size, byte flags) { +	AudioStream *stream = makeRawMemoryStream(data, size, getRate(), flags, 0, 0); +	queueAudioStream(stream, DisposeAfterUse::YES);  } -AudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, -                                   byte flags, uint loopStart, uint loopEnd) { -	SeekableAudioStream *stream = makeRawMemoryStream(ptr, len, rate, flags); - -	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; -	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; -	const bool isLooping  = (flags & Mixer::FLAG_LOOP) != 0; - -	if (isLooping) { -		uint loopOffset = 0, loopLen = 0; -		if (loopEnd == 0) -			loopEnd = len; -		assert(loopStart <= loopEnd); -		assert(loopEnd <= len); - -		loopOffset = loopStart; -		loopLen = loopEnd - loopStart; - -		// Verify the buffer sizes are sane -		if (is16Bit && isStereo) -			assert((loopLen & 3) == 0 && (loopStart & 3) == 0 && (loopEnd & 3) == 0); -		else if (is16Bit || isStereo) -			assert((loopLen & 1) == 0 && (loopStart & 1) == 0 && (loopEnd & 1) == 0); - -		const uint32 extRate = stream->getRate() * (is16Bit ? 2 : 1) * (isStereo ? 2 : 1); - -		return new SubLoopingAudioStream(stream, 0, Timestamp(0, loopStart, extRate), Timestamp(0, loopEnd, extRate)); -	} else { -		return stream; -	} -} - - - -#define MAKE_LINEAR_DISK(STEREO, UNSIGNED) \ -		if (is16Bit) { \ -			if (isLE) \ -				return new RawDiskStream<STEREO, true, UNSIGNED, true>(rate, disposeStream, stream, block, numBlocks); \ -			else  \ -				return new RawDiskStream<STEREO, true, UNSIGNED, false>(rate, disposeStream, stream, block, numBlocks); \ -		} else \ -			return new RawDiskStream<STEREO, false, UNSIGNED, false>(rate, disposeStream, stream, block, numBlocks) - - -SeekableAudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, int numBlocks, -					int rate, byte flags, DisposeAfterUse::Flag disposeStream) { -	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; -	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; -	const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0; -	const bool isLE       = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0; - -	if (isStereo) { -		if (isUnsigned) { -			MAKE_LINEAR_DISK(true, true); -		} else { -			MAKE_LINEAR_DISK(true, false); -		} -	} else { -		if (isUnsigned) { -			MAKE_LINEAR_DISK(false, true); -		} else { -			MAKE_LINEAR_DISK(false, false); -		} -	} -} - -AudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, -		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream, uint loopStart, uint loopEnd) { -	SeekableAudioStream *s = makeRawDiskStream(stream, block, numBlocks, rate, flags, disposeStream); - -	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; -	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; -	const bool isLooping  = (flags & Mixer::FLAG_LOOP) != 0; - -	if (isLooping) { -		uint loopOffset = 0, loopLen = 0; -		const uint len = s->getLength().totalNumberOfFrames() / (is16Bit ? 2 : 1) / (isStereo ? 2 : 1); - -		if (loopEnd == 0) -			loopEnd = len; -		assert(loopStart <= loopEnd); -		assert(loopEnd <= len); - -		loopOffset = loopStart; -		loopLen = loopEnd - loopStart; - -		// Verify the buffer sizes are sane -		if (is16Bit && isStereo) -			assert((loopLen & 3) == 0 && (loopStart & 3) == 0 && (loopEnd & 3) == 0); -		else if (is16Bit || isStereo) -			assert((loopLen & 1) == 0 && (loopStart & 1) == 0 && (loopEnd & 3) == 0); - -		const uint32 extRate = s->getRate() * (is16Bit ? 2 : 1) * (isStereo ? 2 : 1); - -		return new SubLoopingAudioStream(s, 0, Timestamp(0, loopStart, extRate), Timestamp(0, loopEnd, extRate)); -	} else { -		return s; -	} -} - -#pragma mark - -#pragma mark --- Queueing audio stream --- -#pragma mark - - -  class QueuingAudioStreamImpl : public QueuingAudioStream {  private:  	/** diff --git a/sound/audiostream.h b/sound/audiostream.h index e04ed265ab..5ce026b3d7 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -28,7 +28,6 @@  #include "common/util.h"  #include "common/scummsys.h" -#include "common/stream.h"  #include "common/types.h"  #include "sound/timestamp.h" @@ -297,70 +296,6 @@ private:  	Timestamp _pos;  }; -/** - * Creates a audio stream, which plays the given raw data. - * - * @param ptr Data - * @param len Length of the data (in bytes!) - * @param rate The sample rate of the data. - * @param flags Flags combination. - * @see Mixer::RawFlags - * @return The new SeekableAudioStream (or 0 on failure). - */ -SeekableAudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, byte flags); - -/** - * NOTE: - * This API is considered deprecated. - * - * Factory function for a raw PCM 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 *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, -                                   byte flags, uint loopStart, uint loopEnd); - - -/** - * Struct used to define the audio data to be played by a RawDiskStream. - */ -struct RawDiskStreamAudioBlock { -	int32 pos;		///< Position in stream of the block -	int32 len;		///< Length of the block (in samples) -}; - -/** - * Creates a audio stream, which plays from given stream. - * - * @param stream Stream to play from - * @param block Pointer to an RawDiskStreamAudioBlock array - * @see RawDiskStreamAudioBlock - * @param numBlocks Number of blocks. - * @param rate The rate  - * @param len Length of the data (in bytes!) - * @param flags Flags combination. - * @see Mixer::RawFlags - * @param disposeStream Whether the "stream" object should be destroyed after playback. - * @return The new SeekableAudioStream (or 0 on failure). - */ -SeekableAudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, -		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream); - -/** - * NOTE: - * This API is considered deprecated. - * - * Factory function for a Raw Disk Stream.  This can stream raw PCM - * audio data from disk. The function takes an pointer to an array of - * RawDiskStreamAudioBlock which defines the start position and length of - * each block of uncompressed audio in the stream. - */ -AudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, -		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream, uint loopStart, uint loopEnd); -  class QueuingAudioStream : public Audio::AudioStream {  public: @@ -380,10 +315,7 @@ public:  	 * the buffer will be delete[]'d (so make sure to allocate them  	 * with new[], not with malloc).  	 */ -	void queueBuffer(byte *data, uint32 size, byte flags) { -		AudioStream *stream = makeRawMemoryStream(data, size, getRate(), flags, 0, 0); -		queueAudioStream(stream, DisposeAfterUse::YES); -	} +	void queueBuffer(byte *data, uint32 size, byte flags);  	/**  	 * Mark the stream as finished, that is, signal that no further data diff --git a/sound/iff_sound.cpp b/sound/iff_sound.cpp index d0e96fa9ee..a78fe97288 100644 --- a/sound/iff_sound.cpp +++ b/sound/iff_sound.cpp @@ -26,6 +26,7 @@  #include "sound/iff_sound.h"  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  #include "common/func.h"  namespace Audio { diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 40af73b3c5..a3aaa19e8f 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -30,6 +30,7 @@  #include "sound/rate.h"  #include "sound/audiostream.h"  #include "sound/timestamp.h" +#include "sound/raw.h"  namespace Audio { diff --git a/sound/module.mk b/sound/module.mk index e994959e17..e21f242974 100644 --- a/sound/module.mk +++ b/sound/module.mk @@ -17,6 +17,7 @@ MODULE_OBJS := \  	mpu401.o \  	musicplugin.o \  	null.o \ +	raw.o \  	shorten.o \  	timestamp.o \  	vag.o \ diff --git a/sound/raw.cpp b/sound/raw.cpp new file mode 100644 index 0000000000..84627d0ff0 --- /dev/null +++ b/sound/raw.cpp @@ -0,0 +1,463 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" +#include "common/stream.h" + +#include "sound/audiostream.h" +#include "sound/mixer.h" +#include "sound/raw.h" + +namespace Audio { + +// This used to be an inline template function, but +// buggy template function handling in MSVC6 forced +// us to go with the macro approach. So far this is +// the only template function that MSVC6 seemed to +// compile incorrectly. Knock on wood. +#define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE) \ +	((is16Bit ? (isLE ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0)) + + +// TODO: Get rid of this +uint32 calculateSampleOffset(const Timestamp &where, int rate) { +	return where.convertToFramerate(rate).totalNumberOfFrames(); +} + + + +#pragma mark - +#pragma mark --- RawMemoryStream --- +#pragma mark - + +/** + * A simple raw audio stream, purely memory based. It operates on a single + * block of data, which is passed to it upon creation. + * Optionally supports looping the sound. + * + * Design note: This code tries to be as efficient as possible (without + * resorting to assembly, that is). To this end, it is written as a template + * class. This way the compiler can create optimized code for each special + * case. This results in a total of 12 versions of the code being generated. + */ +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +class RawMemoryStream : public SeekableAudioStream { +protected: +	const byte *_ptr; +	const byte *_end; +	const int _rate; +	const byte *_origPtr; +	const DisposeAfterUse::Flag _disposeAfterUse; +	const Timestamp _playtime; + +public: +	RawMemoryStream(int rate, const byte *ptr, uint len, DisposeAfterUse::Flag autoFreeMemory) +	    : _ptr(ptr), _end(ptr+len), _rate(rate), _origPtr(ptr), +	      _disposeAfterUse(autoFreeMemory), +	      _playtime(0, len / (is16Bit ? 2 : 1) / (stereo ? 2 : 1), rate) { +	} + +	virtual ~RawMemoryStream() { +		if (_disposeAfterUse == DisposeAfterUse::YES) +			free(const_cast<byte *>(_origPtr)); +	} + +	int readBuffer(int16 *buffer, const int numSamples); + +	bool isStereo() const			{ return stereo; } +	bool endOfData() const			{ return _ptr >= _end; } + +	int getRate() const				{ return _rate; } +	bool seek(const Timestamp &where); +	Timestamp getLength() const { return _playtime; } +}; + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +int RawMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { +	int samples = numSamples; +	while (samples > 0 && _ptr < _end) { +		int len = MIN(samples, (int)(_end - _ptr) / (is16Bit ? 2 : 1)); +		samples -= len; +		do { +			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); +			_ptr += (is16Bit ? 2 : 1); +		} while (--len); +	} +	return numSamples-samples; +} + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +bool RawMemoryStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp &where) { +	const uint8 *ptr = _origPtr + calculateSampleOffset(where, getRate()) * (is16Bit ? 2 : 1) * (stereo ? 2 : 1); +	if (ptr > _end) { +		_ptr = _end; +		return false; +	} else if (ptr == _end) { +		_ptr = _end; +		return true; +	} else { +		_ptr = ptr; +		return true; +	} +} + +#pragma mark - +#pragma mark --- RawDiskStream --- +#pragma mark - + + + +/** + *  RawDiskStream.  This can stream raw PCM audio data from disk.  The + *  function takes an pointer to an array of RawDiskStreamAudioBlock which defines the + *  start position and length of each block of uncompressed audio in the stream. + */ +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +class RawDiskStream : public SeekableAudioStream { + +// Allow backends to override buffer size +#ifdef CUSTOM_AUDIO_BUFFER_SIZE +	static const int32 BUFFER_SIZE = CUSTOM_AUDIO_BUFFER_SIZE; +#else +	static const int32 BUFFER_SIZE = 16384; +#endif + +protected: +	byte* _buffer;			///< Streaming buffer +	const byte *_ptr;		///< Pointer to current position in stream buffer +	const int _rate;		///< Sample rate of stream + +	Timestamp _playtime;	///< Calculated total play time +	Common::SeekableReadStream *_stream;	///< Stream to read data from +	int32 _filePos;			///< Current position in stream +	int32 _diskLeft;		///< Samples left in stream in current block not yet read to buffer +	int32 _bufferLeft;		///< Samples left in buffer in current block +	const DisposeAfterUse::Flag _disposeAfterUse;		///< Indicates whether the stream object should be deleted when this RawDiskStream is destructed + +	RawDiskStreamAudioBlock *_audioBlock;	///< Audio block list +	const int _audioBlockCount;		///< Number of blocks in _audioBlock +	int _currentBlock;		///< Current audio block number +public: +	RawDiskStream(int rate, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, uint numBlocks) +		: _rate(rate), _playtime(0, rate), _stream(stream), _disposeAfterUse(disposeStream), +		  _audioBlockCount(numBlocks) { + +		assert(numBlocks > 0); + +		// Allocate streaming buffer +		if (is16Bit) { +			_buffer = (byte *)malloc(BUFFER_SIZE * sizeof(int16)); +		} else { +			_buffer = (byte *)malloc(BUFFER_SIZE * sizeof(byte)); +		} + +		_ptr = _buffer; +		_bufferLeft = 0; + +		// Copy audio block data to our buffer +		// TODO: Replace this with a Common::Array or Common::List to +		// make it a little friendlier. +		_audioBlock = new RawDiskStreamAudioBlock[numBlocks]; +		memcpy(_audioBlock, block, numBlocks * sizeof(RawDiskStreamAudioBlock)); + +		// Set current buffer state, playing first block +		_currentBlock = 0; +		_filePos = _audioBlock[_currentBlock].pos; +		_diskLeft = _audioBlock[_currentBlock].len; + +		// Add up length of all blocks in order to caluclate total play time +		int len = 0; +		for (int r = 0; r < _audioBlockCount; r++) { +			len += _audioBlock[r].len; +		} +		_playtime = Timestamp(0, len / (is16Bit ? 2 : 1) / (stereo ? 2 : 1), rate); +	} + + +	virtual ~RawDiskStream() { +		if (_disposeAfterUse == DisposeAfterUse::YES) { +			delete _stream; +		} + +		delete[] _audioBlock; +		free(_buffer); +	} +	int readBuffer(int16 *buffer, const int numSamples); + +	bool isStereo() const			{ return stereo; } +	bool endOfData() const			{ return (_currentBlock == _audioBlockCount - 1) && (_diskLeft == 0) && (_bufferLeft == 0); } + +	int getRate() const			{ return _rate; } +	Timestamp getLength() const { return _playtime; } + +	bool seek(const Timestamp &where); +}; + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +int RawDiskStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { +	int oldPos = _stream->pos(); +	bool restoreFilePosition = false; + +	int samples = numSamples; + +	while (samples > 0 && ((_diskLeft > 0 || _bufferLeft > 0) || (_currentBlock != _audioBlockCount - 1))  ) { +		// Output samples in the buffer to the output +		int len = MIN<int>(samples, _bufferLeft); +		samples -= len; +		_bufferLeft -= len; + +		while (len > 0) { +			*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); +			_ptr += (is16Bit ? 2 : 1); +			len--; +		} + +		// Have we now finished this block?  If so, read the next block +		if ((_bufferLeft == 0) && (_diskLeft == 0) && (_currentBlock != _audioBlockCount - 1)) { +			// Next block +			_currentBlock++; + +			_filePos = _audioBlock[_currentBlock].pos; +			_diskLeft = _audioBlock[_currentBlock].len; +		} +			 +		// Now read more data from disk if there is more to be read +		if ((_bufferLeft == 0) && (_diskLeft > 0)) { +			int32 readAmount = MIN(_diskLeft, BUFFER_SIZE); + +			_stream->seek(_filePos, SEEK_SET); +			_stream->read(_buffer, readAmount * (is16Bit? 2: 1)); + +			// Amount of data in buffer is now the amount read in, and +			// the amount left to read on disk is decreased by the same amount +			_bufferLeft = readAmount; +			_diskLeft -= readAmount; +			_ptr = (byte *)_buffer; +			_filePos += readAmount * (is16Bit ? 2 : 1); + +			// Set this flag now we've used the file, it restores it's +			// original position. +			restoreFilePosition = true; +		} +	} + +	// In case calling code relies on the position of this stream staying  +	// constant, I restore the location if I've changed it.  This is probably +	// not necessary. +	if (restoreFilePosition) { +		_stream->seek(oldPos, SEEK_SET); +	} + +	return numSamples - samples; +} + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +bool RawDiskStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp &where) { +	const uint32 seekSample = calculateSampleOffset(where, getRate()) * (stereo ? 2 : 1); +	uint32 curSample = 0; + +	// Search for the disk block in which the specific sample is placed +	_currentBlock = 0; +	while (_currentBlock < _audioBlockCount) { +		uint32 nextBlockSample = curSample + _audioBlock[_currentBlock].len; + +		if (nextBlockSample > seekSample) +			break; + +		curSample = nextBlockSample; +		++_currentBlock; +	} + +	_filePos = 0; +	_diskLeft = 0; +	_bufferLeft = 0; + +	if (_currentBlock == _audioBlockCount) { +		return ((seekSample - curSample) == (uint32)_audioBlock[_currentBlock - 1].len); +	} else { +		const uint32 offset = seekSample - curSample; + +		_filePos = _audioBlock[_currentBlock].pos + offset * (is16Bit ? 2 : 1); +		_diskLeft = _audioBlock[_currentBlock].len - offset; + +		return true; +	} +} + +#pragma mark - +#pragma mark --- Raw stream factories --- +#pragma mark - + +/* In the following, we use preprocessor / macro tricks to simplify the code + * which instantiates the input streams. We used to use template functions for + * this, but MSVC6 / EVC 3-4 (used for WinCE builds) are extremely buggy when it + * comes to this feature of C++... so as a compromise we use macros to cut down + * on the (source) code duplication a bit. + * So while normally macro tricks are said to make maintenance harder, in this + * particular case it should actually help it :-) + */ + +#define MAKE_LINEAR(STEREO, UNSIGNED) \ +		if (is16Bit) { \ +			if (isLE) \ +				return new RawMemoryStream<STEREO, true, UNSIGNED, true>(rate, ptr, len, autoFree); \ +			else  \ +				return new RawMemoryStream<STEREO, true, UNSIGNED, false>(rate, ptr, len, autoFree); \ +		} else \ +			return new RawMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, autoFree) + +SeekableAudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, byte flags) { +	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; +	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; +	const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0; +	const bool isLE       = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0; +	const DisposeAfterUse::Flag autoFree   = (flags & Mixer::FLAG_AUTOFREE) != 0 ? DisposeAfterUse::YES : DisposeAfterUse::NO; + +	// Verify the buffer sizes are sane +	if (is16Bit && isStereo) { +		assert((len & 3) == 0); +	} else if (is16Bit || isStereo) { +		assert((len & 1) == 0); +	} + +	if (isStereo) { +		if (isUnsigned) { +			MAKE_LINEAR(true, true); +		} else { +			MAKE_LINEAR(true, false); +		} +	} else { +		if (isUnsigned) { +			MAKE_LINEAR(false, true); +		} else { +			MAKE_LINEAR(false, false); +		} +	} +} + + +AudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, +                                   byte flags, uint loopStart, uint loopEnd) { +	SeekableAudioStream *stream = makeRawMemoryStream(ptr, len, rate, flags); + +	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; +	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; +	const bool isLooping  = (flags & Mixer::FLAG_LOOP) != 0; + +	if (isLooping) { +		uint loopOffset = 0, loopLen = 0; +		if (loopEnd == 0) +			loopEnd = len; +		assert(loopStart <= loopEnd); +		assert(loopEnd <= len); + +		loopOffset = loopStart; +		loopLen = loopEnd - loopStart; + +		// Verify the buffer sizes are sane +		if (is16Bit && isStereo) +			assert((loopLen & 3) == 0 && (loopStart & 3) == 0 && (loopEnd & 3) == 0); +		else if (is16Bit || isStereo) +			assert((loopLen & 1) == 0 && (loopStart & 1) == 0 && (loopEnd & 1) == 0); + +		const uint32 extRate = stream->getRate() * (is16Bit ? 2 : 1) * (isStereo ? 2 : 1); + +		return new SubLoopingAudioStream(stream, 0, Timestamp(0, loopStart, extRate), Timestamp(0, loopEnd, extRate)); +	} else { +		return stream; +	} +} + + + +#define MAKE_LINEAR_DISK(STEREO, UNSIGNED) \ +		if (is16Bit) { \ +			if (isLE) \ +				return new RawDiskStream<STEREO, true, UNSIGNED, true>(rate, disposeStream, stream, block, numBlocks); \ +			else  \ +				return new RawDiskStream<STEREO, true, UNSIGNED, false>(rate, disposeStream, stream, block, numBlocks); \ +		} else \ +			return new RawDiskStream<STEREO, false, UNSIGNED, false>(rate, disposeStream, stream, block, numBlocks) + + +SeekableAudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, int numBlocks, +					int rate, byte flags, DisposeAfterUse::Flag disposeStream) { +	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; +	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; +	const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0; +	const bool isLE       = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0; + +	if (isStereo) { +		if (isUnsigned) { +			MAKE_LINEAR_DISK(true, true); +		} else { +			MAKE_LINEAR_DISK(true, false); +		} +	} else { +		if (isUnsigned) { +			MAKE_LINEAR_DISK(false, true); +		} else { +			MAKE_LINEAR_DISK(false, false); +		} +	} +} + +AudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, +		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream, uint loopStart, uint loopEnd) { +	SeekableAudioStream *s = makeRawDiskStream(stream, block, numBlocks, rate, flags, disposeStream); + +	const bool isStereo   = (flags & Mixer::FLAG_STEREO) != 0; +	const bool is16Bit    = (flags & Mixer::FLAG_16BITS) != 0; +	const bool isLooping  = (flags & Mixer::FLAG_LOOP) != 0; + +	if (isLooping) { +		uint loopOffset = 0, loopLen = 0; +		const uint len = s->getLength().totalNumberOfFrames() / (is16Bit ? 2 : 1) / (isStereo ? 2 : 1); + +		if (loopEnd == 0) +			loopEnd = len; +		assert(loopStart <= loopEnd); +		assert(loopEnd <= len); + +		loopOffset = loopStart; +		loopLen = loopEnd - loopStart; + +		// Verify the buffer sizes are sane +		if (is16Bit && isStereo) +			assert((loopLen & 3) == 0 && (loopStart & 3) == 0 && (loopEnd & 3) == 0); +		else if (is16Bit || isStereo) +			assert((loopLen & 1) == 0 && (loopStart & 1) == 0 && (loopEnd & 3) == 0); + +		const uint32 extRate = s->getRate() * (is16Bit ? 2 : 1) * (isStereo ? 2 : 1); + +		return new SubLoopingAudioStream(s, 0, Timestamp(0, loopStart, extRate), Timestamp(0, loopEnd, extRate)); +	} else { +		return s; +	} +} + + + +} // End of namespace Audio diff --git a/sound/raw.h b/sound/raw.h new file mode 100644 index 0000000000..c06eea35d2 --- /dev/null +++ b/sound/raw.h @@ -0,0 +1,108 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SOUND_RAW_H +#define SOUND_RAW_H + +#include "common/scummsys.h" +#include "common/types.h" + + +namespace Common { class SeekableReadStream; } + + +namespace Audio { + +class AudioStream; +class SeekableAudioStream; + +/** + * Creates a audio stream, which plays the given raw data. + * + * @param ptr Data + * @param len Length of the data (in bytes!) + * @param rate The sample rate of the data. + * @param flags Flags combination. + * @see Mixer::RawFlags + * @return The new SeekableAudioStream (or 0 on failure). + */ +SeekableAudioStream *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, byte flags); + +/** + * NOTE: + * This API is considered deprecated. + * + * Factory function for a raw PCM 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 *makeRawMemoryStream(const byte *ptr, uint32 len, int rate, +                                   byte flags, uint loopStart, uint loopEnd); + + +/** + * Struct used to define the audio data to be played by a RawDiskStream. + */ +struct RawDiskStreamAudioBlock { +	int32 pos;		///< Position in stream of the block +	int32 len;		///< Length of the block (in samples) +}; + +/** + * Creates a audio stream, which plays from given stream. + * + * @param stream Stream to play from + * @param block Pointer to an RawDiskStreamAudioBlock array + * @see RawDiskStreamAudioBlock + * @param numBlocks Number of blocks. + * @param rate The rate  + * @param len Length of the data (in bytes!) + * @param flags Flags combination. + * @see Mixer::RawFlags + * @param disposeStream Whether the "stream" object should be destroyed after playback. + * @return The new SeekableAudioStream (or 0 on failure). + */ +SeekableAudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, +		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream); + +/** + * NOTE: + * This API is considered deprecated. + * + * Factory function for a Raw Disk Stream.  This can stream raw PCM + * audio data from disk. The function takes an pointer to an array of + * RawDiskStreamAudioBlock which defines the start position and length of + * each block of uncompressed audio in the stream. + */ +AudioStream *makeRawDiskStream(Common::SeekableReadStream *stream, RawDiskStreamAudioBlock *block, +		int numBlocks, int rate, byte flags, DisposeAfterUse::Flag disposeStream, uint loopStart, uint loopEnd); + + +} // End of namespace Audio + +#endif diff --git a/sound/shorten.cpp b/sound/shorten.cpp index 5f4fcab5b4..fa62080c9c 100644 --- a/sound/shorten.cpp +++ b/sound/shorten.cpp @@ -38,6 +38,7 @@  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  namespace Audio { diff --git a/sound/voc.cpp b/sound/voc.cpp index 9eae18b5dd..7a9a5e8b1b 100644 --- a/sound/voc.cpp +++ b/sound/voc.cpp @@ -30,6 +30,7 @@  #include "sound/audiostream.h"  #include "sound/mixer.h" +#include "sound/raw.h"  #include "sound/voc.h" diff --git a/sound/wave.cpp b/sound/wave.cpp index 673467628c..d299128762 100644 --- a/sound/wave.cpp +++ b/sound/wave.cpp @@ -31,6 +31,7 @@  #include "sound/mixer.h"  #include "sound/wave.h"  #include "sound/adpcm.h" +#include "sound/raw.h"  namespace Audio {  | 
