diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/adpcm.cpp | 56 | ||||
-rw-r--r-- | sound/adpcm.h | 7 | ||||
-rw-r--r-- | sound/wave.cpp | 5 | ||||
-rw-r--r-- | sound/wave.h | 2 |
4 files changed, 43 insertions, 27 deletions
diff --git a/sound/adpcm.cpp b/sound/adpcm.cpp index b38cadd733..ea771cb4c8 100644 --- a/sound/adpcm.cpp +++ b/sound/adpcm.cpp @@ -30,12 +30,15 @@ // // In addition, also IMA ADPCM is supported. -ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels) - : _stream(stream), _channels(channels), _type(type) { +ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels, uint32 blockAlign) + : _stream(stream), _channels(channels), _type(type), _blockAlign(blockAlign) { _status.last = 0; _status.stepIndex = 0; _endpos = stream->pos() + size; + + if (type == kADPCMIma && blockAlign == 0) + error("ADPCMInputStream(): blockAlign isn't specifiled for MS ADPCM IMA"); } int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) { @@ -62,12 +65,10 @@ int ADPCMInputStream::readBufferOKI(int16 *buffer, const int numSamples) { assert(numSamples % 2 == 0); - // Since we process high and low nibbles separately never check buffer end - // on low nibble for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples += 2) { data = _stream->readByte(); - buffer[samples] = decodeOKI((data >> 4) & 0x0f); - buffer[samples + 1] = decodeOKI(data & 0x0f); + buffer[samples] = TO_LE_16(decodeOKI((data >> 4) & 0x0f)); + buffer[samples + 1] = TO_LE_16(decodeOKI(data & 0x0f)); } return samples; } @@ -76,15 +77,25 @@ int ADPCMInputStream::readBufferOKI(int16 *buffer, const int numSamples) { int ADPCMInputStream::readBufferMSIMA1(int16 *buffer, const int numSamples) { int samples; byte data; + int blockLen; + int i; assert(numSamples % 2 == 0); - // Since we process high and low nibbles separately never check buffer end - // on low nibble - for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples += 2) { - data = _stream->readByte(); - buffer[samples] = decodeMSIMA(data & 0x0f); - buffer[samples + 1] = decodeMSIMA((data >> 4) & 0x0f); + samples = 0; + + while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) { + // read block header + _status.last = _stream->readSint16LE(); + _status.stepIndex = _stream->readSint16LE(); + + blockLen = MIN(_endpos - _stream->pos(), _blockAlign - 4); + + for (i = 0; i < blockLen && !_stream->eos() && _stream->pos() < _endpos; i++, samples += 2) { + data = _stream->readByte(); + buffer[samples] = TO_LE_16(decodeMSIMA(data & 0x0f)); + buffer[samples + 1] = TO_LE_16(decodeMSIMA((data >> 4) & 0x0f)); + } } return samples; } @@ -103,7 +114,7 @@ int ADPCMInputStream::readBufferMSIMA2(int16 *buffer, const int numSamples) { for (nibble = 0; nibble < 8; nibble++) { byte k = ((data & 0xf0000000) >> 28); - buffer[samples + channel + nibble * 2] = decodeMSIMA(k); + buffer[samples + channel + nibble * 2] = TO_LE_16(decodeMSIMA(k)); data <<= 4; } } @@ -181,22 +192,23 @@ int16 ADPCMInputStream::decodeMSIMA(byte code) { int32 diff, E, SS, samp; SS = imaStepTable[_status.stepIndex]; - E = SS/8; - if (code & 0x01) - E += SS/4; - if (code & 0x02) - E += SS/2; + E = SS >> 3; if (code & 0x04) E += SS; + if (code & 0x02) + E += SS >> 1; + if (code & 0x01) + E += SS >> 2; diff = (code & 0x08) ? -E : E; samp = _status.last + diff; - if (samp < -32768) - samp = -32768; - else if (samp > 32767) - samp = 32767; + if (samp < -0x8000) + samp = -0x8000; + else if (samp > 0x7fff) + samp = 0x7fff; _status.last = samp; + _status.stepIndex += stepAdjust(code); if (_status.stepIndex < 0) _status.stepIndex = 0; diff --git a/sound/adpcm.h b/sound/adpcm.h index d26a2ccceb..8f957a224a 100644 --- a/sound/adpcm.h +++ b/sound/adpcm.h @@ -43,10 +43,11 @@ private: uint32 _endpos; int _channels; typesADPCM _type; + uint32 _blockAlign; struct adpcmStatus { - int16 last; - int16 stepIndex; + int32 last; + int32 stepIndex; } _status; int16 stepAdjust(byte); @@ -54,7 +55,7 @@ private: int16 decodeMSIMA(byte); public: - ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels = 2); + ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels = 2, uint32 blockAlign = 0); ~ADPCMInputStream() {}; int readBuffer(int16 *buffer, const int numSamples); diff --git a/sound/wave.cpp b/sound/wave.cpp index 1bc71a4297..0fed68d74a 100644 --- a/sound/wave.cpp +++ b/sound/wave.cpp @@ -28,7 +28,7 @@ #include "sound/wave.h" #include "sound/adpcm.h" -bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType) { +bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) { const uint32 initialPos = stream.pos(); byte buf[4+1]; @@ -79,6 +79,9 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, if (wavType != 0) *wavType = type; + + if (blockAlign_ != 0) + *blockAlign_ = blockAlign; #if 0 printf("WAVE information:\n"); printf(" total size: %d\n", wavLength); diff --git a/sound/wave.h b/sound/wave.h index bd80d29b86..5eba702baf 100644 --- a/sound/wave.h +++ b/sound/wave.h @@ -34,7 +34,7 @@ namespace Common { class SeekableReadStream; } * all information about the data necessary for playback. * Currently this only support uncompressed raw PCM data. */ -extern bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType = 0); +extern bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType = 0, int *blockAlign = 0); AudioStream *makeWAVStream(Common::SeekableReadStream &stream); |