[Scummvm-cvs-logs] CVS: scummvm/sound adpcm.cpp,1.11,1.12 adpcm.h,1.6,1.7 wave.cpp,1.10,1.11 wave.h,1.5,1.6

Eugene Sandulenko sev at users.sourceforge.net
Thu Oct 20 19:01:13 CEST 2005


Update of /cvsroot/scummvm/scummvm/sound
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30371/sound

Modified Files:
	adpcm.cpp adpcm.h wave.cpp wave.h 
Log Message:
Fix MS IMA ADPCM decoder. I like Microsoft so much for reinventing another
standard.


Index: adpcm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/adpcm.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- adpcm.cpp	19 Oct 2005 04:59:18 -0000	1.11
+++ adpcm.cpp	21 Oct 2005 02:00:12 -0000	1.12
@@ -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 @@
 
 	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::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 @@
 			
 			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 @@
 	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;

Index: adpcm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/adpcm.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- adpcm.h	19 Oct 2005 04:59:18 -0000	1.6
+++ adpcm.h	21 Oct 2005 02:00:12 -0000	1.7
@@ -43,10 +43,11 @@
 	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 @@
 	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);

Index: wave.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/wave.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- wave.cpp	19 Oct 2005 04:59:18 -0000	1.10
+++ wave.cpp	21 Oct 2005 02:00:12 -0000	1.11
@@ -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 @@
 
 	if (wavType != 0)
 		*wavType = type;
+
+	if (blockAlign_ != 0)
+		*blockAlign_ = blockAlign;
 #if 0
 	printf("WAVE information:\n");
 	printf("  total size: %d\n", wavLength);

Index: wave.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/wave.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- wave.h	18 Oct 2005 01:30:23 -0000	1.5
+++ wave.h	21 Oct 2005 02:00:12 -0000	1.6
@@ -34,7 +34,7 @@
  * 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);
 





More information about the Scummvm-git-logs mailing list