diff options
author | Johannes Schickel | 2010-01-10 15:20:14 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-01-10 15:20:14 +0000 |
commit | 6ca0570fe3bb3f3765677ff8cd3f9e0cbf062d6b (patch) | |
tree | 732a2cc846d6f70dd2c42b0dc0cd52d45de34bb2 | |
parent | bda3fc940c3ecca011b04a32fb20970f53f49d1c (diff) | |
download | scummvm-rg350-6ca0570fe3bb3f3765677ff8cd3f9e0cbf062d6b.tar.gz scummvm-rg350-6ca0570fe3bb3f3765677ff8cd3f9e0cbf062d6b.tar.bz2 scummvm-rg350-6ca0570fe3bb3f3765677ff8cd3f9e0cbf062d6b.zip |
- Add a SubLoopingAudioStream, which loops a nested part of a stream and thus features the same looping capabilites as LinearMemoryStream and LinearDiskStream.
- Remove custom looping code from LinearMemoryStream and LinearDiskStream.
- Adapt various client code to the changes.
svn-id: r47226
-rw-r--r-- | engines/kyra/sound.cpp | 4 | ||||
-rw-r--r-- | engines/saga/music.cpp | 16 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 7 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 3 | ||||
-rw-r--r-- | engines/tucker/sequences.cpp | 2 | ||||
-rw-r--r-- | sound/aiff.cpp | 2 | ||||
-rw-r--r-- | sound/audiostream.cpp | 207 | ||||
-rw-r--r-- | sound/audiostream.h | 46 | ||||
-rw-r--r-- | sound/voc.cpp | 40 | ||||
-rw-r--r-- | sound/voc.h | 7 | ||||
-rw-r--r-- | sound/wave.cpp | 2 |
11 files changed, 243 insertions, 93 deletions
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 4049d2b456..b97d367206 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -244,9 +244,9 @@ namespace { Audio::SeekableAudioStream *makeVOCStream(Common::SeekableReadStream *stream, bool disposeAfterUse) { #ifdef STREAM_AUDIO_FROM_DISK - Audio::SeekableAudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED, 0, 0, disposeAfterUse); + Audio::SeekableAudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED, disposeAfterUse); #else - Audio::SeekableAudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED); + Audio::SeekableAudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED, false); if (disposeAfterUse) delete stream; diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index a5c28c213e..7fe8c0dbb2 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -292,7 +292,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) { loopStart = 0; // Fix ITE sunstatm/sunspot score if (resourceId == MUSIC_SUNSPOT) - loopStart = 4 * 18727; + loopStart = 18727; // Digital music ResourceData *resData = _digitalMusicContext->getResourceData(resourceId - 9); @@ -311,7 +311,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) { Audio::LinearDiskStreamAudioBlock audioBlocks[1]; audioBlocks[0].pos = 0; audioBlocks[0].len = resData->size / 2; // 16-bit sound - audioStream = Audio::makeLinearDiskStream(musicStream, audioBlocks, 1, 11025, musicFlags, false, loopStart, 0); + audioStream = Audio::makeLinearDiskStream(musicStream, audioBlocks, 1, 11025, musicFlags, false); } else { // Read compressed header to determine compression type musicFile->seek((uint32)resData->offset, SEEK_SET); @@ -337,8 +337,16 @@ void Music::play(uint32 resourceId, MusicFlags flags) { if (audioStream) { debug(2, "Playing digitized music"); - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, - Audio::makeLoopingAudioStream(audioStream, (flags == MUSIC_LOOP ? 0 : 1))); + if (loopStart) { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, + new Audio::SubLoopingAudioStream(audioStream, + (flags == MUSIC_LOOP ? 0 : 1), + Audio::Timestamp(0, loopStart, audioStream->getRate()), + audioStream->getLength())); + } else { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, + Audio::makeLoopingAudioStream(audioStream, (flags == MUSIC_LOOP ? 0 : 1))); + } _digitalMusic = true; return; } diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 5a4f7aeafc..4011aa9fa3 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -243,10 +243,9 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 } } - if (data) { - audioStream = Audio::makeLinearInputStream(data, size, _audioRate, - flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - } + if (data) + audioStream = Audio::makeLinearInputStream(data, size, _audioRate, flags | Audio::Mixer::FLAG_AUTOFREE); + if (audioStream) { *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; return audioStream; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 1bb4fa883f..4b452aad56 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -303,8 +303,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { if (track->digitalChannelNr != -1) { byte *channelData = track->channels[track->digitalChannelNr].data; delete pSnd->pStreamAud; - pSnd->pStreamAud = Audio::makeLinearInputStream(channelData, track->digitalSampleSize, track->digitalSampleRate, - Audio::Mixer::FLAG_UNSIGNED, 0, 0); + pSnd->pStreamAud = Audio::makeLinearInputStream(channelData, track->digitalSampleSize, track->digitalSampleRate, Audio::Mixer::FLAG_UNSIGNED); delete pSnd->pLoopStream; pSnd->pLoopStream = 0; pSnd->soundType = Audio::Mixer::kSFXSoundType; diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index cae0f527c2..204913addf 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -598,7 +598,7 @@ Audio::RewindableAudioStream *AnimationSequencePlayer::loadSound(int index, Anim uint8 *sampleData = (uint8 *)malloc(size); if (sampleData) { f.read(sampleData, size); - stream = Audio::makeLinearInputStream(sampleData, size, rate, flags, 0, 0); + stream = Audio::makeLinearInputStream(sampleData, size, rate, flags); } } break; diff --git a/sound/aiff.cpp b/sound/aiff.cpp index 69fb806420..6ac9a45372 100644 --- a/sound/aiff.cpp +++ b/sound/aiff.cpp @@ -174,7 +174,7 @@ SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream) { // Since we allocated our own buffer for the data, we must set the autofree flag. flags |= Audio::Mixer::FLAG_AUTOFREE; - return makeLinearInputStream(data, size, rate, flags, 0, 0); + return makeLinearInputStream(data, size, rate, flags); } } // End of namespace Audio diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index 72f01b35d1..6d72b83dd1 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -162,6 +162,59 @@ AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start } #pragma mark - +#pragma mark --- SubLoopingAudioStream --- +#pragma mark - + +SubLoopingAudioStream::SubLoopingAudioStream(SeekableAudioStream *stream, + uint loops, + const Timestamp loopStart, + const Timestamp loopEnd, + bool disposeAfterUse) + : _parent(stream), _disposeAfterUse(disposeAfterUse), _loops(loops), + _pos(0, getRate() * (isStereo() ? 2 : 1)), + _loopStart(loopStart.convertToFramerate(getRate() * (isStereo() ? 2 : 1))), + _loopEnd(loopEnd.convertToFramerate(getRate() * (isStereo() ? 2 : 1))), + _done(false) { + if (!_parent->rewind()) + _done = true; +} + +SubLoopingAudioStream::~SubLoopingAudioStream() { + if (_disposeAfterUse) + delete _parent; +} + +int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { + int framesLeft = MIN(_loopEnd.frameDiff(_pos), numSamples); + int framesRead = _parent->readBuffer(buffer, framesLeft); + _pos = _pos.addFrames(framesRead); + + if (framesLeft < numSamples || framesRead < framesLeft) { + if (_loops != 0) { + --_loops; + if (!_loops) { + _done = true; + return framesRead; + } + } + + if (!_parent->seek(_loopStart)) { + _done = true; + return framesRead; + } + + _pos = _loopStart; + framesLeft = numSamples - framesLeft; + framesRead += _parent->readBuffer(buffer + framesRead, framesLeft); + + if (_parent->endOfStream()) + _done = true; + } + + return framesRead; +} + +#pragma mark - #pragma mark --- SubSeekableAudioStream --- #pragma mark - @@ -226,36 +279,23 @@ class LinearMemoryStream : public SeekableAudioStream { protected: const byte *_ptr; const byte *_end; - const byte *_loopPtr; - const byte *_loopEnd; const int _rate; const byte *_origPtr; const bool _disposeAfterUse; const Timestamp _playtime; - uint _numLoops; ///< Number of loops to play - uint _numPlayedLoops; ///< Number of loops which have been played - public: - LinearMemoryStream(int rate, const byte *ptr, uint len, uint loopOffset, uint loopLen, bool autoFreeMemory) - : _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0), _rate(rate), _disposeAfterUse(autoFreeMemory), + LinearMemoryStream(int rate, const byte *ptr, uint len, bool autoFreeMemory) + : _ptr(ptr), _end(ptr+len), _rate(rate), _origPtr(ptr), + _disposeAfterUse(autoFreeMemory), _playtime(0, len / (is16Bit ? 2 : 1) / (stereo ? 2 : 1), rate) { - - if (loopLen) { - _numLoops = 0; - _loopPtr = _ptr + loopOffset; - _loopEnd = _loopPtr + loopLen; - } else { - _numLoops = 1; - } - _numPlayedLoops = 0; - - _origPtr = ptr; } + virtual ~LinearMemoryStream() { if (_disposeAfterUse) free(const_cast<byte *>(_origPtr)); } + int readBuffer(int16 *buffer, const int numSamples); bool isStereo() const { return stereo; } @@ -276,14 +316,6 @@ int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buf *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); _ptr += (is16Bit ? 2 : 1); } while (--len); - // Loop, if looping was specified - // TODO: Handle non-infinite loops - if (_loopPtr && _ptr >= _end) { - _ptr = _loopPtr; - _end = _loopEnd; - - _numPlayedLoops++; - } } return numSamples-samples; } @@ -339,17 +371,10 @@ protected: LinearDiskStreamAudioBlock *_audioBlock; ///< Audio block list int _audioBlockCount; ///< Number of blocks in _audioBlock int _currentBlock; ///< Current audio block number - - int _beginLoop; ///< Loop start parameter - int _endLoop; ///< Loop end parameter, currently not implemented - bool _loop; ///< Determines if the stream should be looped when it finishes - uint _numLoops; ///< Number of loops to play - uint _numPlayedLoops; ///< Number of loops which have been played - public: - LinearDiskStream(int rate, uint beginLoop, uint endLoop, bool disposeStream, Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, uint numBlocks, bool loop) - : _rate(rate), _playtime(0, rate), _stream(stream), _beginLoop(beginLoop), _endLoop(endLoop), _disposeAfterUse(disposeStream), - _audioBlockCount(numBlocks), _loop(loop), _numLoops(loop ? 0 : 1), _numPlayedLoops(0) { + LinearDiskStream(int rate, bool disposeStream, Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, uint numBlocks) + : _rate(rate), _playtime(0, rate), _stream(stream), _disposeAfterUse(disposeStream), + _audioBlockCount(numBlocks) { assert(numBlocks > 0); @@ -442,22 +467,12 @@ int LinearDiskStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffe _bufferLeft = readAmount; _diskLeft -= readAmount; _ptr = (byte *)_buffer; - _filePos += readAmount * (is16Bit? 2: 1); + _filePos += readAmount * (is16Bit ? 2 : 1); // Set this flag now we've used the file, it restores it's // original position. restoreFilePosition = true; } - - // Looping - if (_diskLeft == 0 && _loop) { - // Reset the stream - _currentBlock = 0; - _filePos = _audioBlock[_currentBlock].pos + _beginLoop; - _diskLeft = _audioBlock[_currentBlock].len; - - _numPlayedLoops++; - } } // In case calling code relies on the position of this stream staying @@ -496,7 +511,7 @@ bool LinearDiskStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp & } else { const uint32 offset = seekSample - curSample; - _filePos = _audioBlock[_currentBlock].pos + offset * (is16Bit? 2: 1); + _filePos = _audioBlock[_currentBlock].pos + offset * (is16Bit ? 2 : 1); _diskLeft = _audioBlock[_currentBlock].len - offset; return true; @@ -519,36 +534,24 @@ bool LinearDiskStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp & #define MAKE_LINEAR(STEREO, UNSIGNED) \ if (is16Bit) { \ if (isLE) \ - return new LinearMemoryStream<STEREO, true, UNSIGNED, true>(rate, ptr, len, loopOffset, loopLen, autoFree); \ + return new LinearMemoryStream<STEREO, true, UNSIGNED, true>(rate, ptr, len, autoFree); \ else \ - return new LinearMemoryStream<STEREO, true, UNSIGNED, false>(rate, ptr, len, loopOffset, loopLen, autoFree); \ + return new LinearMemoryStream<STEREO, true, UNSIGNED, false>(rate, ptr, len, autoFree); \ } else \ - return new LinearMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, loopOffset, loopLen, autoFree) + return new LinearMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, autoFree) -SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, byte flags, uint loopStart, uint loopEnd) { +SeekableAudioStream *makeLinearInputStream(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 bool autoFree = (flags & Mixer::FLAG_AUTOFREE) != 0; - - uint loopOffset = 0, loopLen = 0; - if (flags & Mixer::FLAG_LOOP) { - 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((len & 3) == 0 && (loopLen & 3) == 0); + assert((len & 3) == 0); } else if (is16Bit || isStereo) { - assert((len & 1) == 0 && (loopLen & 1) == 0); + assert((len & 1) == 0); } if (isStereo) { @@ -567,25 +570,55 @@ SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate } +AudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, + byte flags, uint loopStart, uint loopEnd) { + SeekableAudioStream *stream = makeLinearInputStream(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 & 3) == 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 LinearDiskStream<STEREO, true, UNSIGNED, true>(rate, loopStart, loopEnd, takeOwnership, stream, block, numBlocks, loop); \ + return new LinearDiskStream<STEREO, true, UNSIGNED, true>(rate, takeOwnership, stream, block, numBlocks); \ else \ - return new LinearDiskStream<STEREO, true, UNSIGNED, false>(rate, loopStart, loopEnd, takeOwnership, stream, block, numBlocks, loop); \ + return new LinearDiskStream<STEREO, true, UNSIGNED, false>(rate, takeOwnership, stream, block, numBlocks); \ } else \ - return new LinearDiskStream<STEREO, false, UNSIGNED, false>(rate, loopStart, loopEnd, takeOwnership, stream, block, numBlocks, loop) + return new LinearDiskStream<STEREO, false, UNSIGNED, false>(rate, takeOwnership, stream, block, numBlocks) -SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, int numBlocks, int rate, byte flags, bool takeOwnership, uint loopStart, uint loopEnd) { +SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, int numBlocks, int rate, byte flags, bool takeOwnership) { 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 bool loop = (flags & Mixer::FLAG_LOOP) != 0; if (isStereo) { if (isUnsigned) { @@ -602,7 +635,39 @@ SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, Li } } +AudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, + int numBlocks, int rate, byte flags, bool disposeStream, uint loopStart, uint loopEnd) { + SeekableAudioStream *s = makeLinearDiskStream(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 --- diff --git a/sound/audiostream.h b/sound/audiostream.h index 817cd36f95..003fef64f7 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -216,6 +216,42 @@ public: AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops); /** + * A looping audio stream, which features looping of a nested part of the + * stream. + * + * NOTE: + * Currently this implementation stops after the nested loop finished + * playback. + * + * IMPORTANT: + * This might be merged with SubSeekableAudioStream for playback purposes. + * (After extending it to accept a start time). + */ +class SubLoopingAudioStream : public AudioStream { +public: + SubLoopingAudioStream(SeekableAudioStream *stream, uint loops, + const Timestamp loopStart, + const Timestamp loopEnd, + bool disposeAfterUse = true); + ~SubLoopingAudioStream(); + + int readBuffer(int16 *buffer, const int numSamples); + bool endOfData() const { return _done; } + + bool isStereo() const { return _parent->isStereo(); } + int getRate() const { return _parent->getRate(); } +private: + SeekableAudioStream *_parent; + bool _disposeAfterUse; + + uint _loops; + Timestamp _pos; + Timestamp _loopStart, _loopEnd; + + bool _done; +}; + +/** * A SubSeekableAudioStream provides access to a SeekableAudioStream * just in the range [start, end). * The same caveats apply to SubSeekableAudioStream as do to SeekableAudioStream. @@ -259,6 +295,8 @@ private: Timestamp _pos, _length; }; +SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, byte flags); + /** * Factory function for a raw linear AudioStream, which will simply treat all * data in the buffer described by ptr and len as raw sample data in the @@ -267,8 +305,8 @@ private: * signed native endian). Optionally supports (infinite) looping of a portion * of the data. */ -SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, - byte flags, uint loopStart, uint loopEnd); +AudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, + byte flags, uint loopStart, uint loopEnd); /** @@ -279,6 +317,8 @@ struct LinearDiskStreamAudioBlock { int32 len; ///< Length of the block (in samples) }; +SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, + int numBlocks, int rate, byte flags, bool disposeStream); /** * Factory function for a Linear Disk Stream. This can stream linear (PCM) @@ -286,7 +326,7 @@ struct LinearDiskStreamAudioBlock { * LinearDiskStreamAudioBlock which defines the start position and length of * each block of uncompressed audio in the stream. */ -SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, +AudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, int numBlocks, int rate, byte flags, bool disposeStream, uint loopStart, uint loopEnd); class QueuingAudioStream : public Audio::AudioStream { diff --git a/sound/voc.cpp b/sound/voc.cpp index 1c268c0260..79a64769f7 100644 --- a/sound/voc.cpp +++ b/sound/voc.cpp @@ -298,7 +298,7 @@ int parseVOCFormat(Common::SeekableReadStream& stream, LinearDiskStreamAudioBloc return currentBlock; } -SeekableAudioStream *makeVOCDiskStream(Common::SeekableReadStream &stream, byte flags, bool takeOwnership) { +AudioStream *makeVOCDiskStream(Common::SeekableReadStream &stream, byte flags, bool takeOwnership) { const int MAX_AUDIO_BLOCKS = 256; LinearDiskStreamAudioBlock *block = new LinearDiskStreamAudioBlock[MAX_AUDIO_BLOCKS]; @@ -317,11 +317,31 @@ SeekableAudioStream *makeVOCDiskStream(Common::SeekableReadStream &stream, byte return audioStream; } - + +SeekableAudioStream *makeVOCDiskStreamNoLoop(Common::SeekableReadStream &stream, byte flags, bool takeOwnership) { + const int MAX_AUDIO_BLOCKS = 256; + + LinearDiskStreamAudioBlock *block = new LinearDiskStreamAudioBlock[MAX_AUDIO_BLOCKS]; + int rate, loops, begin_loop, end_loop; + + int numBlocks = parseVOCFormat(stream, block, rate, loops, begin_loop, end_loop); + + SeekableAudioStream *audioStream = 0; + + // Create an audiostream from the data. Note the numBlocks may be 0, + // e.g. when invalid data is encountered. See bug #2890038. + if (numBlocks) + audioStream = makeLinearDiskStream(&stream, block, numBlocks, rate, flags, takeOwnership); + + delete[] block; + + return audioStream; +} + #endif -SeekableAudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags, uint loopStart, uint loopEnd, bool takeOwnershipOfStream) { +AudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags, uint loopStart, uint loopEnd, bool takeOwnershipOfStream) { #ifdef STREAM_AUDIO_FROM_DISK return makeVOCDiskStream(stream, flags, takeOwnershipOfStream); #else @@ -336,5 +356,19 @@ SeekableAudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flag #endif } +SeekableAudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags, bool takeOwnershipOfStream) { +#ifdef STREAM_AUDIO_FROM_DISK + return makeVOCDiskStreamNoLoop(stream, flags, takeOwnershipOfStream); +#else + int size, rate; + + byte *data = loadVOCFromStream(stream, size, rate); + + if (!data) + return 0; + + return makeLinearInputStream(data, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE); +#endif +} } // End of namespace Audio diff --git a/sound/voc.h b/sound/voc.h index 44bef758f3..e16d8169f9 100644 --- a/sound/voc.h +++ b/sound/voc.h @@ -93,7 +93,12 @@ extern byte *loadVOCFromStream(Common::ReadStream &stream, int &size, int &rate) * * This function uses loadVOCFromStream() internally. */ -SeekableAudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags = 0, uint loopStart = 0, uint loopEnd = 0, bool takeOwnershipOfStream = false); +AudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags = 0, uint loopStart = 0, uint loopEnd = 0, bool takeOwnershipOfStream = false); + +/** + * This does not use any of the looping features from VOC files! + */ +SeekableAudioStream *makeVOCStream(Common::SeekableReadStream &stream, byte flags, bool takeOwnershipOfStream); } // End of namespace Audio diff --git a/sound/wave.cpp b/sound/wave.cpp index a625d18d90..e1a466393f 100644 --- a/sound/wave.cpp +++ b/sound/wave.cpp @@ -190,7 +190,7 @@ RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, bool di // Since we allocated our own buffer for the data, we must set the autofree flag. flags |= Audio::Mixer::FLAG_AUTOFREE; - return makeLinearInputStream(data, size, rate, flags, 0, 0); + return makeLinearInputStream(data, size, rate, flags); } } // End of namespace Audio |