aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/adpcm.cpp56
-rw-r--r--sound/adpcm.h7
-rw-r--r--sound/wave.cpp5
-rw-r--r--sound/wave.h2
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);