[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