aboutsummaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
authorD G Turner2012-12-10 16:29:16 +0000
committerD G Turner2012-12-10 16:29:16 +0000
commit62d87e30f4dcdd78dc43747a5cdb1cc450bf4d3b (patch)
tree8207560d7628b3f0902e1b67b8cf032ddba7ac98 /audio
parentb532a81b42bce16838347aa560138da1b15418e5 (diff)
downloadscummvm-rg350-62d87e30f4dcdd78dc43747a5cdb1cc450bf4d3b.tar.gz
scummvm-rg350-62d87e30f4dcdd78dc43747a5cdb1cc450bf4d3b.tar.bz2
scummvm-rg350-62d87e30f4dcdd78dc43747a5cdb1cc450bf4d3b.zip
AUDIO: Fix MS ADPCM to work with Mono streams using odd sized buffers.
Diffstat (limited to 'audio')
-rw-r--r--audio/decoders/adpcm.cpp55
-rw-r--r--audio/decoders/adpcm_intern.h7
2 files changed, 35 insertions, 27 deletions
diff --git a/audio/decoders/adpcm.cpp b/audio/decoders/adpcm.cpp
index 2fe509e1f3..f069ee3417 100644
--- a/audio/decoders/adpcm.cpp
+++ b/audio/decoders/adpcm.cpp
@@ -268,7 +268,6 @@ static const int MSADPCMAdaptationTable[] = {
768, 614, 512, 409, 307, 230, 230, 230
};
-
int16 MS_ADPCMStream::decodeMS(ADPCMChannelStatus *c, byte code) {
int32 predictor;
@@ -290,40 +289,42 @@ int16 MS_ADPCMStream::decodeMS(ADPCMChannelStatus *c, byte code) {
int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
- int i = 0;
-
- samples = 0;
+ int i;
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- // read block header
- for (i = 0; i < _channels; i++) {
- _status.ch[i].predictor = CLIP(_stream->readByte(), (byte)0, (byte)6);
- _status.ch[i].coeff1 = MSADPCMAdaptCoeff1[_status.ch[i].predictor];
- _status.ch[i].coeff2 = MSADPCMAdaptCoeff2[_status.ch[i].predictor];
- }
+ for (samples = 0; samples < numSamples && !endOfData(); samples++) {
+ if (_decodedSampleCount == 0) {
+ if (_blockPos[0] == _blockAlign) {
+ // read block header
+ for (i = 0; i < _channels; i++) {
+ _status.ch[i].predictor = CLIP(_stream->readByte(), (byte)0, (byte)6);
+ _status.ch[i].coeff1 = MSADPCMAdaptCoeff1[_status.ch[i].predictor];
+ _status.ch[i].coeff2 = MSADPCMAdaptCoeff2[_status.ch[i].predictor];
+ }
- for (i = 0; i < _channels; i++)
- _status.ch[i].delta = _stream->readSint16LE();
+ for (i = 0; i < _channels; i++)
+ _status.ch[i].delta = _stream->readSint16LE();
- for (i = 0; i < _channels; i++)
- _status.ch[i].sample1 = _stream->readSint16LE();
+ for (i = 0; i < _channels; i++)
+ _status.ch[i].sample1 = _stream->readSint16LE();
- for (i = 0; i < _channels; i++)
- buffer[samples++] = _status.ch[i].sample2 = _stream->readSint16LE();
+ for (i = 0; i < _channels; i++)
+ _decodedSamples[_decodedSampleCount++] = _status.ch[i].sample2 = _stream->readSint16LE();
- for (i = 0; i < _channels; i++)
- buffer[samples++] = _status.ch[i].sample1;
+ for (i = 0; i < _channels; i++)
+ _decodedSamples[_decodedSampleCount++] = _status.ch[i].sample1;
- _blockPos[0] = _channels * 7;
+ _blockPos[0] = _channels * 7;
+ } else {
+ data = _stream->readByte();
+ _blockPos[0]++;
+ _decodedSamples[_decodedSampleCount++] = decodeMS(&_status.ch[0], (data >> 4) & 0x0f);
+ _decodedSamples[_decodedSampleCount++] = decodeMS(&_status.ch[_channels - 1], data & 0x0f);
+ }
}
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- _blockPos[0]++;
- buffer[samples] = decodeMS(&_status.ch[0], (data >> 4) & 0x0f);
- buffer[samples + 1] = decodeMS(&_status.ch[_channels - 1], data & 0x0f);
- }
+ // (1 - (count - 1)) ensures that _decodedSamples acts as a FIFO of depth 2
+ buffer[samples] = _decodedSamples[1 - (_decodedSampleCount - 1)];
+ _decodedSampleCount--;
}
return samples;
diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h
index 3b8d8c74d0..66a1aa605f 100644
--- a/audio/decoders/adpcm_intern.h
+++ b/audio/decoders/adpcm_intern.h
@@ -206,12 +206,19 @@ public:
if (blockAlign == 0)
error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
memset(&_status, 0, sizeof(_status));
+ _decodedSampleCount = 0;
}
+ virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
+
virtual int readBuffer(int16 *buffer, const int numSamples);
protected:
int16 decodeMS(ADPCMChannelStatus *c, byte);
+
+private:
+ uint8 _decodedSampleCount;
+ int16 _decodedSamples[4];
};
// Duck DK3 IMA ADPCM Decoder