[Scummvm-cvs-logs] SF.net SVN: scummvm:[54204] scummvm/trunk/sound/decoders
mthreepwood at users.sourceforge.net
mthreepwood at users.sourceforge.net
Thu Nov 11 18:04:07 CET 2010
Revision: 54204
http://scummvm.svn.sourceforge.net/scummvm/?rev=54204&view=rev
Author: mthreepwood
Date: 2010-11-11 17:04:07 +0000 (Thu, 11 Nov 2010)
Log Message:
-----------
SOUND: Add DK3 IMA ADPCM decoder for duck videos
Modified Paths:
--------------
scummvm/trunk/sound/decoders/adpcm.cpp
scummvm/trunk/sound/decoders/adpcm.h
Modified: scummvm/trunk/sound/decoders/adpcm.cpp
===================================================================
--- scummvm/trunk/sound/decoders/adpcm.cpp 2010-11-11 16:44:28 UTC (rev 54203)
+++ scummvm/trunk/sound/decoders/adpcm.cpp 2010-11-11 17:04:07 UTC (rev 54204)
@@ -691,7 +691,97 @@
#pragma mark -
+// Duck DK3 IMA ADPCM Decoder
+// Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
+class DK3_ADPCMStream : public Ima_ADPCMStream {
+protected:
+
+ void reset() {
+ Ima_ADPCMStream::reset();
+ _topNibble = false;
+ }
+
+public:
+ DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+
+ // DK3 only works as a stereo stream
+ assert(channels == 2);
+ _topNibble = false;
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+private:
+ byte _nibble, _lastByte;
+ bool _topNibble;
+};
+
+#define DK3_READ_NIBBLE() \
+do { \
+ if (_topNibble) { \
+ _nibble = _lastByte >> 4; \
+ _topNibble = false; \
+ } else { \
+ if (_stream->pos() >= _endpos) \
+ break; \
+ if ((_stream->pos() % _blockAlign) == 0) \
+ continue; \
+ _lastByte = _stream->readByte(); \
+ _nibble = _lastByte & 0xf; \
+ _topNibble = true; \
+ } \
+} while (0)
+
+
+int DK3_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples = 0;
+
+ assert((numSamples % 4) == 0);
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ if ((_stream->pos() % _blockAlign) == 0) {
+ _stream->readUint16LE(); // Unknown
+ uint16 rate = _stream->readUint16LE(); // Copy of rate
+ _stream->skip(6); // Unknown
+ // Get predictor for both sum/diff channels
+ _status.ima_ch[0].last = _stream->readSint16LE();
+ _status.ima_ch[1].last = _stream->readSint16LE();
+ // Get index for both sum/diff channels
+ _status.ima_ch[0].stepIndex = _stream->readByte();
+ _status.ima_ch[1].stepIndex = _stream->readByte();
+
+ if (_stream->eos())
+ break;
+
+ // Sanity check
+ assert(rate == getRate());
+ }
+
+ DK3_READ_NIBBLE();
+ decodeIMA(_nibble, 0);
+
+ DK3_READ_NIBBLE();
+ decodeIMA(_nibble, 1);
+
+ buffer[samples++] = _status.ima_ch[0].last + _status.ima_ch[1].last;
+ buffer[samples++] = _status.ima_ch[0].last - _status.ima_ch[1].last;
+
+ DK3_READ_NIBBLE();
+ decodeIMA(_nibble, 0);
+
+ buffer[samples++] = _status.ima_ch[0].last + _status.ima_ch[1].last;
+ buffer[samples++] = _status.ima_ch[0].last - _status.ima_ch[1].last;
+ }
+
+ return samples;
+}
+
+
+#pragma mark -
+
+
// adjust the step for use on the next sample.
int16 ADPCMStream::stepAdjust(byte code) {
static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
@@ -750,6 +840,8 @@
return new Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMApple:
return new Apple_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
+ case kADPCMDK3:
+ return new DK3_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
default:
error("Unsupported ADPCM encoding");
break;
Modified: scummvm/trunk/sound/decoders/adpcm.h
===================================================================
--- scummvm/trunk/sound/decoders/adpcm.h 2010-11-11 16:44:28 UTC (rev 54203)
+++ scummvm/trunk/sound/decoders/adpcm.h 2010-11-11 17:04:07 UTC (rev 54204)
@@ -58,7 +58,8 @@
kADPCMTinsel6, // 6-bit ADPCM used by the Tinsel engine
kADPCMTinsel8, // 8-bit ADPCM used by the Tinsel engine
kADPCMIma, // Standard IMA ADPCM
- kADPCMApple // Apple QuickTime IMA ADPCM
+ kADPCMApple, // Apple QuickTime IMA ADPCM
+ kADPCMDK3 // Duck DK3 IMA ADPCM
};
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list