aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2005-09-17 10:58:01 +0000
committerMax Horn2005-09-17 10:58:01 +0000
commit114efafe7ddd972ccec842f6b12f48260e3aa3bd (patch)
tree7f825029425cc86e8c10cbed5c87e9c829adf3cb
parent17b70ae5158b09ea5467559f658098111029d9ec (diff)
downloadscummvm-rg350-114efafe7ddd972ccec842f6b12f48260e3aa3bd.tar.gz
scummvm-rg350-114efafe7ddd972ccec842f6b12f48260e3aa3bd.tar.bz2
scummvm-rg350-114efafe7ddd972ccec842f6b12f48260e3aa3bd.zip
Cleaned up the ADPCM code
svn-id: r18840
-rw-r--r--sound/adpcm.cpp94
-rw-r--r--sound/adpcm.h3
2 files changed, 41 insertions, 56 deletions
diff --git a/sound/adpcm.cpp b/sound/adpcm.cpp
index 17454118a6..80bbbe4fdc 100644
--- a/sound/adpcm.cpp
+++ b/sound/adpcm.cpp
@@ -31,11 +31,12 @@
// See also <http://www.comptek.ru/telephony/tnotes/tt1-13.html>
//
// In addition, also IMA ADPCM is supported.
+template <typesADPCM TYPE>
class ADPCMInputStream : public AudioStream {
private:
bool _evenPos;
+ byte _lastByte;
Common::SeekableReadStream *_stream;
- typesADPCM _type;
uint32 _endpos;
struct adpcmStatus {
@@ -44,14 +45,10 @@ private:
} _status;
int16 stepAdjust(byte);
- int16 okiADPCMDecode(byte);
- int16 imaADPCMDecode(byte);
-
- int readOkiBuffer(int16 *buffer, const int numSamples);
- int readIMABuffer(int16 *buffer, const int numSamples);
+ int16 decode(byte);
public:
- ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type);
+ ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size);
~ADPCMInputStream() {};
int readBuffer(int16 *buffer, const int numSamples);
@@ -62,56 +59,25 @@ public:
};
-ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type)
- : _stream(stream), _evenPos(true), _type(type) {
+template <typesADPCM TYPE>
+ADPCMInputStream<TYPE>::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size)
+ : _stream(stream), _evenPos(true) {
_status.last = 0;
_status.stepIndex = 0;
_endpos = stream->pos() + size;
}
-int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) {
- switch (_type) {
- case kADPCMOki:
- return readOkiBuffer(buffer, numSamples);
- break;
- case kADPCMIma:
- return readIMABuffer(buffer, numSamples);
- break;
- default:
- error("Unsupported ADPCM encoding");
- break;
- }
- return 0;
-}
-
-int ADPCMInputStream::readOkiBuffer(int16 *buffer, const int numSamples) {
- int samples;
-
- for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples++) {
- // * 16 effectively converts 12-bit input to 16-bit output
- if (_evenPos) {
- buffer[samples] = okiADPCMDecode((_stream->readByte() >> 4) & 0x0f) * 16;
- // Rewind back so we will reget byte later
- _stream->seek(-1, SEEK_CUR);
- } else {
- buffer[samples] = okiADPCMDecode(_stream->readByte() & 0x0f) * 16;
- }
- _evenPos = !_evenPos;
- }
- return samples;
-}
-
-int ADPCMInputStream::readIMABuffer(int16 *buffer, const int numSamples) {
+template <typesADPCM TYPE>
+int ADPCMInputStream<TYPE>::readBuffer(int16 *buffer, const int numSamples) {
int samples;
for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples++) {
if (_evenPos) {
- buffer[samples] = imaADPCMDecode((_stream->readByte() >> 4) & 0x0f);
- // Rewind back so we will reget byte later
- _stream->seek(-1, SEEK_CUR);
+ _lastByte = _stream->readByte();
+ buffer[samples] = decode((_lastByte >> 4) & 0x0f);
} else {
- buffer[samples] = imaADPCMDecode(_stream->readByte() & 0x0f);
+ buffer[samples] = decode(_lastByte & 0x0f);
}
_evenPos = !_evenPos;
}
@@ -119,7 +85,8 @@ int ADPCMInputStream::readIMABuffer(int16 *buffer, const int numSamples) {
}
// adjust the step for use on the next sample.
-int16 ADPCMInputStream::stepAdjust(byte code) {
+template <typesADPCM TYPE>
+int16 ADPCMInputStream<TYPE>::stepAdjust(byte code) {
static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
return adjusts[code & 0x07];
@@ -136,7 +103,8 @@ static const int16 okiStepSize[49] = {
};
// Decode Linear to ADPCM
-int16 ADPCMInputStream::okiADPCMDecode(byte code) {
+template <>
+int16 ADPCMInputStream<kADPCMOki>::decode(byte code) {
int16 diff, E, SS, samp;
SS = okiStepSize[_status.stepIndex];
@@ -163,13 +131,8 @@ int16 ADPCMInputStream::okiADPCMDecode(byte code) {
if (_status.stepIndex > 48)
_status.stepIndex = 48;
- return samp;
-}
-
-AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type) {
- AudioStream *audioStream = new ADPCMInputStream(&stream, size, type);
-
- return audioStream;
+ // * 16 effectively converts 12-bit input to 16-bit output
+ return samp * 16;
}
@@ -188,7 +151,8 @@ static const uint16 imaStepTable[89] = {
32767
};
-int16 ADPCMInputStream::imaADPCMDecode(byte code) {
+template <>
+int16 ADPCMInputStream<kADPCMIma>::decode(byte code) {
int32 diff, E, SS, samp;
SS = imaStepTable[_status.stepIndex];
@@ -216,3 +180,21 @@ int16 ADPCMInputStream::imaADPCMDecode(byte code) {
return samp;
}
+
+AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type) {
+ AudioStream *audioStream;
+
+ switch (type) {
+ case kADPCMOki:
+ audioStream = new ADPCMInputStream<kADPCMOki>(&stream, size);
+ break;
+ case kADPCMIma:
+ audioStream = new ADPCMInputStream<kADPCMIma>(&stream, size);
+ break;
+ default:
+ error("Unsupported ADPCM encoding");
+ break;
+ }
+
+ return audioStream;
+}
diff --git a/sound/adpcm.h b/sound/adpcm.h
index 1994164b67..a852266ae8 100644
--- a/sound/adpcm.h
+++ b/sound/adpcm.h
@@ -32,6 +32,9 @@ enum typesADPCM {
kADPCMIma
};
+// TODO: Switch from a SeekableReadStream to a plain ReadStream. This requires
+// some internal refactoring but is definitely possible and will increase the
+// flexibility of this code.
AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type);
#endif