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 { |