From 2e9bae44c5f80fe18aa0545b6c868682c380497c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 7 Jan 2010 16:08:41 +0000 Subject: Let ADPCM streams subclass RewindableAudioStreams and thus allow them to be looped with the new looping code. svn-id: r47127 --- sound/adpcm.cpp | 34 +++++++++++++++------------------- sound/adpcm.h | 36 +++++++++++++++++------------------- sound/wave.cpp | 19 +++++++++++++++---- 3 files changed, 47 insertions(+), 42 deletions(-) (limited to 'sound') diff --git a/sound/adpcm.cpp b/sound/adpcm.cpp index 68ce9fafb0..ef8bb50c98 100644 --- a/sound/adpcm.cpp +++ b/sound/adpcm.cpp @@ -31,7 +31,7 @@ namespace Audio { -class ADPCMInputStream : public AudioStream { +class ADPCMInputStream : public RewindableAudioStream { private: Common::SeekableReadStream *_stream; bool _disposeAfterUse; @@ -45,8 +45,6 @@ private: uint16 _chunkData; int _blockLen; int _rate; - uint _numLoops; - uint _curLoop; struct ADPCMChannelStatus { byte predictor; @@ -84,7 +82,7 @@ private: int16 decodeTinsel(int16, double); public: - ADPCMInputStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels = 2, uint32 blockAlign = 0, uint numLoops = 1); + ADPCMInputStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign); ~ADPCMInputStream(); int readBuffer(int16 *buffer, const int numSamples); @@ -102,6 +100,8 @@ public: bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); } bool isStereo() const { return _channels == 2; } int getRate() const { return _rate; } + + bool rewind(); }; // Routines to convert 12 bit linear samples to the @@ -114,8 +114,8 @@ public: // In addition, also MS IMA ADPCM is supported. See // . -ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign, uint numLoops) - : _stream(stream), _disposeAfterUse(disposeAfterUse), _channels(channels), _type(type), _blockAlign(blockAlign), _rate(rate), _numLoops(numLoops) { +ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign) + : _stream(stream), _disposeAfterUse(disposeAfterUse), _channels(channels), _type(type), _blockAlign(blockAlign), _rate(rate) { if (type == kADPCMMSIma && blockAlign == 0) error("ADPCMInputStream(): blockAlign isn't specified for MS IMA ADPCM"); @@ -138,7 +138,6 @@ ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, bool disp _startpos = stream->pos(); _endpos = _startpos + size; - _curLoop = 0; reset(); } @@ -156,6 +155,13 @@ void ADPCMInputStream::reset() { _chunkPos = 0; } +bool ADPCMInputStream::rewind() { + // TODO: Error checking. + reset(); + _stream->seek(_startpos); + return true; +} + int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) { int samplesDecoded = 0; switch (_type) { @@ -191,16 +197,6 @@ int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) { break; } - // Loop if necessary - if (samplesDecoded < numSamples || _stream->pos() == _endpos) { - _curLoop++; - if (_numLoops == 0 || _curLoop < _numLoops) { - reset(); - _stream->seek(_startpos); - return samplesDecoded + readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); - } - } - return samplesDecoded; } @@ -624,8 +620,8 @@ int16 ADPCMInputStream::decodeTinsel(int16 code, double eVal) { return (int16) CLIP(sample, -32768.0, 32767.0); } -AudioStream *makeADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign, uint numLoops) { - return new ADPCMInputStream(stream, disposeAfterUse, size, type, rate, channels, blockAlign, numLoops); +RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign) { + return new ADPCMInputStream(stream, disposeAfterUse, size, type, rate, channels, blockAlign); } } // End of namespace Audio diff --git a/sound/adpcm.h b/sound/adpcm.h index 48d003ae78..46ccb582c3 100644 --- a/sound/adpcm.h +++ b/sound/adpcm.h @@ -42,6 +42,7 @@ namespace Audio { class AudioStream; +class RewindableAudioStream; // There are several types of ADPCM encoding, only some are supported here // For all the different encodings, refer to: @@ -61,27 +62,24 @@ enum typesADPCM { /** * Takes an input stream containing ADPCM compressed sound data and creates - * an AudioStream from that. + * an RewindableAudioStream from that. * - * @param stream the SeekableReadStream from which to read the ADPCM data - * @param disposeAfterUse whether to delete the stream after use - * @param size how many bytes to read from the stream (0 = all) - * @param type the compression type used - * @param rate the sampling rate (default = 22050) - * @param channels the number of channels (default = 2) - * @param blockAlign block alignment ??? (default = 0) - * @param numLoop how many types the sounds should loop, 0 for infinite loop (default = 1) - * @return a new AudioStream, or NULL, if an error occured + * @param stream the SeekableReadStream from which to read the ADPCM data + * @param disposeAfterUse whether to delete the stream after use + * @param size how many bytes to read from the stream (0 = all) + * @param type the compression type used + * @param rate the sampling rate + * @param channels the number of channels + * @param blockAlign block alignment ??? + * @return a new RewindableAudioStream, or NULL, if an error occured */ -AudioStream *makeADPCMStream( - Common::SeekableReadStream *stream, - bool disposeAfterUse, - uint32 size, - typesADPCM type, - int rate = 22050, - int channels = 2, - uint32 blockAlign = 0, - uint numLoops = 1); +RewindableAudioStream *makeADPCMStream( + Common::SeekableReadStream *stream, + bool disposeAfterUse, + uint32 size, typesADPCM type, + int rate = 22050, + int channels = 2, + uint32 blockAlign = 0); } // End of namespace Audio diff --git a/sound/wave.cpp b/sound/wave.cpp index 49189f3ea3..67aa7daa54 100644 --- a/sound/wave.cpp +++ b/sound/wave.cpp @@ -173,10 +173,21 @@ AudioStream *makeWAVStream(Common::SeekableReadStream *stream, bool disposeAfter return 0; } - if (type == 17) // MS IMA ADPCM - return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMSIma, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign, loop ? 0 : 1); - else if (type == 2) // MS ADPCM - return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMS, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign, loop ? 0 : 1); + if (type == 17) { // MS IMA ADPCM + RewindableAudioStream *adpcm = makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMSIma, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign); + + if (loop) + return new LoopingAudioStream(adpcm, 0); + else + return adpcm; + } else if (type == 2) { // MS ADPCM + RewindableAudioStream *adpcm = makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMS, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign); + + if (loop) + return new LoopingAudioStream(adpcm, 0); + else + return adpcm; + } // Raw PCM. Just read everything at once. // TODO: More elegant would be to wrap the stream. -- cgit v1.2.3