aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2010-01-31 02:14:11 +0000
committerMax Horn2010-01-31 02:14:11 +0000
commit20f8503c23e89a8db14a5cca9feef92bfc5079d2 (patch)
tree8c3c4ab48dae027a6930b84dc8839c327d93b23c /sound
parent7f2f9a811743cabd8c07c9a0dc961140569c8071 (diff)
downloadscummvm-rg350-20f8503c23e89a8db14a5cca9feef92bfc5079d2.tar.gz
scummvm-rg350-20f8503c23e89a8db14a5cca9feef92bfc5079d2.tar.bz2
scummvm-rg350-20f8503c23e89a8db14a5cca9feef92bfc5079d2.zip
Further OOify the ADPCM code
svn-id: r47740
Diffstat (limited to 'sound')
-rw-r--r--sound/decoders/adpcm.cpp113
1 files changed, 73 insertions, 40 deletions
diff --git a/sound/decoders/adpcm.cpp b/sound/decoders/adpcm.cpp
index 53e335e074..943b1ff7d8 100644
--- a/sound/decoders/adpcm.cpp
+++ b/sound/decoders/adpcm.cpp
@@ -40,42 +40,18 @@ protected:
const int _channels;
const uint32 _blockAlign;
uint32 _blockPos[2];
- uint8 _chunkPos;
- uint16 _chunkData;
- int _blockLen;
const int _rate;
- struct ADPCMChannelStatus {
- byte predictor;
- int16 delta;
- int16 coeff1;
- int16 coeff2;
- int16 sample1;
- int16 sample2;
- };
-
struct {
// OKI/IMA
struct {
int32 last;
int32 stepIndex;
} ima_ch[2];
-
- // Apple QuickTime IMA ADPCM
- int32 streamPos[2];
-
- // MS ADPCM
- ADPCMChannelStatus ch[2];
-
- // Tinsel
- double predictor;
- double K0, K1;
- double d0, d1;
} _status;
- void reset();
+ virtual void reset();
int16 stepAdjust(byte);
- int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
public:
ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
@@ -117,11 +93,7 @@ ADPCMStream::~ADPCMStream() {
void ADPCMStream::reset() {
memset(&_status, 0, sizeof(_status));
- _blockLen = 0;
_blockPos[0] = _blockPos[1] = _blockAlign; // To make sure first header is read
- _status.streamPos[0] = 0;
- _status.streamPos[1] = _blockAlign;
- _chunkPos = 0;
}
bool ADPCMStream::rewind() {
@@ -193,9 +165,14 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {
class Ima_ADPCMStream : public ADPCMStream {
+protected:
+ int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
+
public:
Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ memset(&_status, 0, sizeof(_status));
+ }
virtual int readBuffer(int16 *buffer, const int numSamples);
};
@@ -217,12 +194,26 @@ int Ima_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
#pragma mark -
-class Apple_ADPCMStream : public ADPCMStream {
+class Apple_ADPCMStream : public Ima_ADPCMStream {
+protected:
+ // Apple QuickTime IMA ADPCM
+ int32 _streamPos[2];
+
+ void reset() {
+ Ima_ADPCMStream::reset();
+ _streamPos[0] = 0;
+ _streamPos[1] = _blockAlign;
+ }
+
public:
Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ _streamPos[0] = 0;
+ _streamPos[1] = _blockAlign;
+ }
virtual int readBuffer(int16 *buffer, const int numSamples);
+
};
int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
@@ -240,7 +231,7 @@ int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int chanSamples = numSamples / _channels;
for (int i = 0; i < _channels; i++) {
- _stream->seek(_status.streamPos[i]);
+ _stream->seek(_streamPos[i]);
while ((samples[i] < chanSamples) &&
// Last byte read and a new one needed
@@ -289,7 +280,7 @@ int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
// Since the channels are interleaved, skip the next block
_stream->skip(MIN<uint32>(_blockAlign, _endpos - _stream->pos()));
- _status.streamPos[i] = _stream->pos();
+ _streamPos[i] = _stream->pos();
}
}
@@ -299,10 +290,10 @@ int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
#pragma mark -
-class MSIma_ADPCMStream : public ADPCMStream {
+class MSIma_ADPCMStream : public Ima_ADPCMStream {
public:
MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
if (blockAlign == 0)
error("ADPCMStream(): blockAlign isn't specified for MS IMA ADPCM");
}
@@ -391,6 +382,26 @@ static const int MSADPCMAdaptationTable[] = {
class MS_ADPCMStream : public ADPCMStream {
+protected:
+ struct ADPCMChannelStatus {
+ byte predictor;
+ int16 delta;
+ int16 coeff1;
+ int16 coeff2;
+ int16 sample1;
+ int16 sample2;
+ };
+
+ struct {
+ // MS ADPCM
+ ADPCMChannelStatus ch[2];
+ } _status;
+
+ void reset() {
+ ADPCMStream::reset();
+ memset(&_status, 0, sizeof(_status));
+ }
+
public:
MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
: ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
@@ -470,6 +481,22 @@ int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
class Tinsel_ADPCMStream : public ADPCMStream {
+protected:
+ struct {
+ // Tinsel
+ double predictor;
+ double K0, K1;
+ double d0, d1;
+ } _status;
+
+ void reset() {
+ ADPCMStream::reset();
+ memset(&_status, 0, sizeof(_status));
+ }
+
+ int16 decodeTinsel(int16, double);
+ void readBufferTinselHeader();
+
public:
Tinsel_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
: ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
@@ -482,9 +509,6 @@ public:
}
- int16 decodeTinsel(int16, double);
-
- void readBufferTinselHeader();
};
static const double TinselFilterTable[4][2] = {
@@ -566,6 +590,15 @@ int Tinsel4_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
}
class Tinsel6_ADPCMStream : public Tinsel_ADPCMStream {
+protected:
+ uint8 _chunkPos;
+ uint16 _chunkData;
+
+ void reset() {
+ ADPCMStream::reset();
+ _chunkPos = 0;
+ }
+
public:
Tinsel6_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
: Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
@@ -674,7 +707,7 @@ static const uint16 imaStepTable[89] = {
32767
};
-int16 ADPCMStream::decodeIMA(byte code, int channel) {
+int16 Ima_ADPCMStream::decodeIMA(byte code, int channel) {
int32 E = (2 * (code & 0x7) + 1) * imaStepTable[_status.ima_ch[channel].stepIndex] / 8;
int32 diff = (code & 0x08) ? -E : E;
int32 samp = CLIP<int32>(_status.ima_ch[channel].last + diff, -32768, 32767);