[Scummvm-cvs-logs] SF.net SVN: scummvm:[42704] scummvm/trunk/graphics/video/coktelvideo

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Fri Jul 24 23:29:41 CEST 2009


Revision: 42704
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42704&view=rev
Author:   drmccoy
Date:     2009-07-24 21:29:41 +0000 (Fri, 24 Jul 2009)

Log Message:
-----------
Adding support for ADPCM sound data (yet another IMA ADPCM variant). What we've called ADPCM before is more like DPCM

Modified Paths:
--------------
    scummvm/trunk/graphics/video/coktelvideo/coktelvideo.cpp
    scummvm/trunk/graphics/video/coktelvideo/coktelvideo.h

Modified: scummvm/trunk/graphics/video/coktelvideo/coktelvideo.cpp
===================================================================
--- scummvm/trunk/graphics/video/coktelvideo/coktelvideo.cpp	2009-07-24 20:45:42 UTC (rev 42703)
+++ scummvm/trunk/graphics/video/coktelvideo/coktelvideo.cpp	2009-07-24 21:29:41 UTC (rev 42704)
@@ -45,25 +45,26 @@
 
 	_stream = &stream;
 
-	// Version
-	uint16 handle = _stream->readUint16LE();
+	uint16 handle;
+
+	handle   = _stream->readUint16LE();
 	_version = _stream->readByte();
 
 	// Version checking
 	if ((handle != 0) || (_version < 2)) {
-		warning("IMD Version incorrect (%d,%X)", handle, _version);
+		warning("Imd::load(): Version incorrect (%d,%X)", handle, _version);
 		unload();
 		return false;
 	}
 
 	// Rest header
-	_features = _stream->readByte();
-	_framesCount = _stream->readUint16LE();
-	_x = _stream->readSint16LE();
-	_y = _stream->readSint16LE();
-	_width = _stream->readSint16LE();
-	_height = _stream->readSint16LE();
-	_flags = _stream->readUint16LE();
+	_features      = _stream->readByte();
+	_framesCount   = _stream->readUint16LE();
+	_x             = _stream->readSint16LE();
+	_y             = _stream->readSint16LE();
+	_width         = _stream->readSint16LE();
+	_height        = _stream->readSint16LE();
+	_flags         = _stream->readUint16LE();
 	_firstFramePos = _stream->readUint16LE();
 
 	// IMDs always have video
@@ -83,9 +84,9 @@
 			return false;
 		}
 		if (_stdX != 0) {
-			_stdX = _stream->readSint16LE();
-			_stdY = _stream->readSint16LE();
-			_stdWidth = _stream->readSint16LE();
+			_stdX      = _stream->readSint16LE();
+			_stdY      = _stream->readSint16LE();
+			_stdWidth  = _stream->readSint16LE();
 			_stdHeight = _stream->readSint16LE();
 			_features |= kFeaturesStdCoords;
 		} else
@@ -111,8 +112,8 @@
 
 	// Sound
 	if (_features & kFeaturesSound) {
-		_soundFreq = _stream->readSint16LE();
-		_soundSliceSize = _stream->readSint16LE();
+		_soundFreq        = _stream->readSint16LE();
+		_soundSliceSize   = _stream->readSint16LE();
 		_soundSlicesCount = _stream->readSint16LE();
 
 		if (_soundFreq < 0)
@@ -122,7 +123,7 @@
 			_soundSlicesCount = -_soundSlicesCount - 1;
 
 		if (_soundSlicesCount > 40) {
-			warning("IMD: More than 40 sound slices found (%d)", _soundSlicesCount);
+			warning("Imd::load(): More than 40 sound slices found (%d)", _soundSlicesCount);
 			unload();
 			return false;
 		}
@@ -132,7 +133,7 @@
 		_frameLength = _soundSliceLength >> 16;
 
 		_soundStage = 1;
-		_hasSound = true;
+		_hasSound   = true;
 
 		_audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
 	} else
@@ -165,9 +166,9 @@
 		_frameCoords = new Coord[_framesCount];
 		assert(_frameCoords);
 		for (int i = 0; i < _framesCount; i++) {
-			_frameCoords[i].left = _stream->readSint16LE();
-			_frameCoords[i].top = _stream->readSint16LE();
-			_frameCoords[i].right = _stream->readSint16LE();
+			_frameCoords[i].left   = _stream->readSint16LE();
+			_frameCoords[i].top    = _stream->readSint16LE();
+			_frameCoords[i].right  = _stream->readSint16LE();
 			_frameCoords[i].bottom = _stream->readSint16LE();
 		}
 	}
@@ -194,7 +195,7 @@
 	if (frameRate == 0)
 		frameRate = 1;
 
-	_frameRate = frameRate;
+	_frameRate   = frameRate;
 	_frameLength = 1000 / _frameRate;
 }
 
@@ -212,11 +213,11 @@
 		for (int i = 0; i < _framesCount; i++) {
 			if (_frameCoords[i].left != -1) {
 				if (x >= 0) {
-					_frameCoords[i].left = _frameCoords[i].left - _x + x;
+					_frameCoords[i].left  = _frameCoords[i].left  - _x + x;
 					_frameCoords[i].right = _frameCoords[i].right - _x + x;
 				}
 				if (y >= 0) {
-					_frameCoords[i].top = _frameCoords[i].top - _y + y;
+					_frameCoords[i].top    = _frameCoords[i].top    - _y + y;
 					_frameCoords[i].bottom = _frameCoords[i].bottom - _y + y;
 				}
 			}
@@ -233,8 +234,8 @@
 	deleteVidMem();
 
 	_hasOwnVidMem = false;
-	_vidMem = vidMem;
-	_vidMemWidth = width;
+	_vidMem       = vidMem;
+	_vidMemWidth  = width;
 	_vidMemHeight = height;
 }
 
@@ -244,8 +245,8 @@
 	if ((_width > 0) && (_height > 0)) {
 		setXY(0, 0);
 		_hasOwnVidMem = true;
-		_vidMem = new byte[_width * _height];
-		_vidMemWidth = _width;
+		_vidMem       = new byte[_width * _height];
+		_vidMemWidth  = _width;
 		_vidMemHeight = _height;
 	}
 }
@@ -269,7 +270,7 @@
 			delete _audioStream;
 
 		_audioStream = 0;
-		_soundStage = 0;
+		_soundStage  = 0;
 	}
 	_soundEnabled = false;
 	_mixer = 0;
@@ -313,7 +314,7 @@
 		for (int i = ((frame > _curFrame) ? _curFrame : 0); i <= frame; i++)
 			processFrame(i);
 	} else
-		error("Frame %d is not directly accessible", frame);
+		error("Imd::seekFrame(): Frame %d is not directly accessible", frame);
 
 	// Seek
 	_stream->seek(framePos);
@@ -403,8 +404,9 @@
 	}
 
 	_hasOwnVidMem = false;
-	_vidMem = 0;
-	_vidMemWidth = _vidMemHeight = 0;
+	_vidMem       = 0;
+	_vidMemWidth  = 0;
+	_vidMemHeight = 0;
 }
 
 void Imd::clear(bool del) {
@@ -419,39 +421,41 @@
 
 	_stream = 0;
 
-	_version = 0;
+	_version  = 0;
 	_features = 0;
-	_flags = 0;
-	_x = _y = _width = _height = 0;
+	_flags    = 0;
+
+	_x    = _y    = _width    = _height    = 0;
 	_stdX = _stdY = _stdWidth = _stdHeight = 0;
+
 	_framesCount = _curFrame = 0;
-	_framesPos = 0;
+
+	_framesPos     = 0;
 	_firstFramePos = 0;
-	_frameCoords = 0;
+	_frameCoords   = 0;
 
 	_frameDataSize = _vidBufferSize = 0;
-	_frameData = _vidBuffer = 0;
-	_frameDataLen = 0;
+	_frameData     = _vidBuffer     = 0;
+	_frameDataLen  = 0;
 
 	memset(_palette, 0, 768);
 
 	deleteVidMem(del);
 
-	_hasSound = false;
+	_hasSound     = false;
 	_soundEnabled = false;
-	_soundStage = 0;
-	_skipFrames = 0;
+	_soundStage   = 0;
+	_skipFrames   = 0;
 
-	_soundFlags = 0;
-	_soundFreq = 0;
-	_soundSliceSize = 0;
+	_soundFlags       = 0;
+	_soundFreq        = 0;
+	_soundSliceSize   = 0;
 	_soundSlicesCount = 0;
 	_soundSliceLength = 0;
+	_audioStream      = 0;
 
-	_audioStream = 0;
-
-	_frameRate = 12;
-	_frameLength = 0;
+	_frameRate     = 12;
+	_frameLength   = 0;
 	_lastFrameTime = 0;
 }
 
@@ -474,25 +478,25 @@
 	if (!_vidMem)
 		setVideoMemory();
 
-	state.left = _x;
-	state.top = _y;
-	state.right = _width + state.left - 1;
-	state.bottom = _height + state.top - 1;
+	state.left   = _x;
+	state.top    = _y;
+	state.right  = _width  + state.left - 1;
+	state.bottom = _height + state.top  - 1;
 
 	do {
 		if (frame != 0) {
 			if (_stdX != -1) {
-				state.left = _stdX;
-				state.top = _stdY;
-				state.right = _stdWidth + state.left - 1;
-				state.bottom = _stdHeight + state.top - 1;
+				state.left   = _stdX;
+				state.top    = _stdY;
+				state.right  = _stdWidth  + state.left - 1;
+				state.bottom = _stdHeight + state.top  - 1;
 				state.flags |= kStateStdCoords;
 			}
 			if (_frameCoords &&
 					(_frameCoords[frame].left != -1)) {
-				state.left = _frameCoords[frame].left;
-				state.top = _frameCoords[frame].top;
-				state.right = _frameCoords[frame].right;
+				state.left   = _frameCoords[frame].left;
+				state.top    = _frameCoords[frame].top;
+				state.right  = _frameCoords[frame].right;
 				state.bottom = _frameCoords[frame].bottom;
 				state.flags |= kStateFrameCoords;
 			}
@@ -525,8 +529,8 @@
 		if (_soundStage != 0) {
 			byte *soundBuf;
 
-			// Next sound slice data
 			if (cmd == 0xFF00) {
+				// Next sound slice data
 
 				if (!hasNextCmd && _soundEnabled) {
 					soundBuf = new byte[_soundSliceSize];
@@ -540,8 +544,9 @@
 
 				cmd = _stream->readUint16LE();
 
-			// Initial sound data (all slices)
 			} else if (cmd == 0xFF01) {
+				// Initial sound data (all slices)
+
 				int dataLength = _soundSliceSize * _soundSlicesCount;
 
 				if (!hasNextCmd && _soundEnabled) {
@@ -560,8 +565,9 @@
 
 				cmd = _stream->readUint16LE();
 
-			// Empty sound slice
 			} else if (!hasNextCmd && (_soundEnabled)) {
+				// Empty sound slice
+
 				soundBuf = new byte[_soundSliceSize];
 				assert(soundBuf);
 
@@ -602,13 +608,13 @@
 			_frameDataLen = cmd + 2;
 
 			if (_vidMemWidth <= state.right) {
-				state.left = 0;
+				state.left   = 0;
 				state.right -= state.left;
 			}
 			if (_vidMemWidth <= state.right)
 				state.right = _vidMemWidth - 1;
 			if (_vidMemHeight <= state.bottom) {
-				state.top = 0;
+				state.top     = 0;
 				state.bottom -= state.top;
 			}
 			if (_vidMemHeight <= state.bottom)
@@ -642,7 +648,7 @@
 		_audioStream->finish();
 		_mixer->stopHandle(_audioHandle);
 		_audioStream = 0;
-		_soundStage = 0;
+		_soundStage  = 0;
 	}
 
 	_lastFrameTime = g_system->getMillis();
@@ -654,12 +660,15 @@
 		return 0;
 
 	uint32 retVal = 0;
-	int16 width = right - left + 1;
-	int16 height = bottom - top + 1;
-	int16 sW = _vidMemWidth;
-	byte *dataPtr = _frameData;
+
+	int16 width  = right  - left + 1;
+	int16 height = bottom - top  + 1;
+	int16 sW     = _vidMemWidth;
+
+	byte *dataPtr   = _frameData;
 	byte *imdVidMem = _vidMem + sW * top + left;
 	byte *srcPtr;
+
 	uint8 type = *dataPtr++;
 
 	if (type & 0x10) { // Palette data
@@ -691,7 +700,7 @@
 	if (type == 2) { // Whole block
 		for (int i = 0; i < height; i++) {
 			memcpy(imdVidMem, srcPtr, width);
-			srcPtr += width;
+			srcPtr    += width;
 			imdVidMem += sW;
 		}
 	} else if (type == 1) { // Sparse block
@@ -705,16 +714,16 @@
 					memcpy(imdVidMem, srcPtr, pixCount);
 
 					pixWritten += pixCount;
-					imdVidMem += pixCount;
-					srcPtr += pixCount;
+					imdVidMem  += pixCount;
+					srcPtr     += pixCount;
 				} else { // "Hole"
-					pixCount = (pixCount + 1) % 256;
+					pixCount    = (pixCount + 1) % 256;
 					pixWritten += pixCount;
-					imdVidMem += pixCount;
+					imdVidMem  += pixCount;
 				}
 			}
 			imdVidMemBak += sW;
-			imdVidMem = imdVidMemBak;
+			imdVidMem     = imdVidMemBak;
 		}
 	} else if (type == 0x42) { // Whole quarter-wide block
 		for (int i = 0; i < height; i++) {
@@ -724,7 +733,7 @@
 				memset(imdVidMem, *srcPtr, 4);
 
 			imdVidMemBak += sW;
-			imdVidMem = imdVidMemBak;
+			imdVidMem     = imdVidMemBak;
 		}
 	} else if ((type & 0xF) == 2) { // Whole half-high block
 		for (; height > 1; height -= 2, imdVidMem += sW + sW, srcPtr += width) {
@@ -745,16 +754,16 @@
 					memcpy(imdVidMem + sW, srcPtr, pixCount);
 
 					pixWritten += pixCount;
-					imdVidMem += pixCount;
-					srcPtr += pixCount;
+					imdVidMem  += pixCount;
+					srcPtr     += pixCount;
 				} else { // "Hole"
-					pixCount = (pixCount + 1) % 256;
+					pixCount    = (pixCount + 1) % 256;
 					pixWritten += pixCount;
-					imdVidMem += pixCount;
+					imdVidMem  += pixCount;
 				}
 			}
 			imdVidMemBak += sW + sW;
-			imdVidMem = imdVidMemBak;
+			imdVidMem     = imdVidMemBak;
 		}
 	}
 
@@ -848,7 +857,7 @@
 	}
 }
 
-const uint16 Vmd::_tableADPCM[128] = {
+const uint16 Vmd::_tableDPCM[128] = {
 	0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
 	0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
 	0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
@@ -864,6 +873,26 @@
 	0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
 };
 
+const int32 Vmd::_tableADPCM[] = {
+			7,     8,     9,    10,    11,    12,    13,    14,
+		 16,    17,    19,    21,    23,    25,    28,    31,
+		 34,    37,    41,    45,    50,    55,    60,    66,
+		 73,    80,    88,    97,   107,   118,   130,   143,
+		157,   173,   190,   209,   230,   253,   279,   307,
+		337,   371,   408,   449,   494,   544,   598,   658,
+		724,   796,   876,   963,  1060,  1166,  1282,  1411,
+	 1552,  1707,  1878,  2066,  2272,  2499,  2749,  3024,
+	 3327,  3660,  4026,  4428,  4871,  5358,  5894,  6484,
+	 7132,  7845,  8630,  9493, 10442, 11487, 12635, 13899,
+	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
+	32767,     0
+};
+
+const int32 Vmd::_tableADPCMStep[] = {
+	-1, -1, -1, -1, 2,  4,  6,  8,
+	-1, -1, -1, -1, 2,  4,  6,  8
+};
+
 Vmd::Vmd(Graphics::PaletteLUT *palLUT) : _palLUT(palLUT) {
 	clear(false);
 }
@@ -877,40 +906,40 @@
 
 	_stream = &stream;
 
-	uint16 headerLength = _stream->readUint16LE();
-	uint16 handle = _stream->readUint16LE();
-	_version = _stream->readUint16LE();
+	uint16 headerLength;
+	uint16 handle;
 
+	headerLength = _stream->readUint16LE();
+	handle       = _stream->readUint16LE();
+	_version     = _stream->readUint16LE();
+
 	if (!(_version & 2))
 		_features |= kFeaturesPalette;
 	else
 		_features |= kFeaturesFullColor;
 
-	// 0x4 (4)
-
 	// Version checking
 	if (headerLength != 814) {
-		warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+		warning("Vmd::load(): Version incorrect (%d, %d, %d)", headerLength, handle, _version);
 		unload();
 		return false;
 	}
 
 	_framesCount = _stream->readUint16LE();
 
-	// 0x6 (6)
-
-	_x = _stream->readSint16LE();
-	_y = _stream->readSint16LE();
-	_width = _stream->readSint16LE();
+	_x      = _stream->readSint16LE();
+	_y      = _stream->readSint16LE();
+	_width  = _stream->readSint16LE();
 	_height = _stream->readSint16LE();
 
-	// 0xE (14)
+	if ((_width != 0) && (_height != 0)) {
 
-	if ((_width != 0) && (_height != 0)) {
 		_hasVideo = true;
 		_features |= kFeaturesVideo;
+
 		if (_features & kFeaturesFullColor)
 			_codecIndeo3 = new Indeo3(_width, _height, _palLUT);
+
 	} else
 		_hasVideo = false;
 
@@ -922,7 +951,7 @@
 	}
 
 	if (handle > 2) {
-		warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+		warning("Vmd::load(): Version incorrect (%d, %d, %d)", headerLength, handle, _version);
 		unload();
 		return false;
 	}
@@ -930,7 +959,7 @@
 	_bytesPerPixel = handle + 1;
 
 	if (_bytesPerPixel > 1) {
-		_features |= kFeaturesFullColor;
+		_features |=  kFeaturesFullColor;
 		_features &= ~kFeaturesPalette;
 	}
 
@@ -940,12 +969,8 @@
 	_firstFramePos = _stream->readUint32LE();
 	_stream->skip(4); // Unknown
 
-	// 0x1A (26)
-
 	_stream->read((byte *) _palette, 768);
 
-	// 0x31A (794)
-
 	_frameDataSize = _stream->readUint32LE();
 	_vidBufferSize = _stream->readUint32LE();
 
@@ -957,7 +982,7 @@
 	} else
 		_externalCodec = false;
 
-	_preScaleX = 1;
+	_preScaleX  = 1;
 	_postScaleX = 1;
 
 	if (_externalCodec)
@@ -970,10 +995,10 @@
 		_blitMode = n - 1;
 
 		if (_bytesPerPixel == 2) {
-			_preScaleX = n;
+			_preScaleX  = n;
 			_postScaleX = 1;
 		} else if (_bytesPerPixel == 3) {
-			_preScaleX = 1;
+			_preScaleX  = 1;
 			_postScaleX = n;
 		}
 
@@ -984,8 +1009,6 @@
 	if (!_externalCodec && !(_flags & 0x1000))
 			_scaleExternalX = _bytesPerPixel;
 
-	// 0x322 (802)
-
 	if (_hasVideo) {
 		if ((_frameDataSize == 0) || (_frameDataSize > 1048576))
 			_frameDataSize = _width * _height + 1000;
@@ -1009,27 +1032,41 @@
 	if (_externalCodec && _codecIndeo3)
 		_features |= kFeaturesSupportsDouble;
 
-	_soundFreq = _stream->readSint16LE();
-	_soundSliceSize = _stream->readSint16LE();
+	_soundFreq        = _stream->readSint16LE();
+	_soundSliceSize   = _stream->readSint16LE();
 	_soundSlicesCount = _stream->readSint16LE();
-	_soundFlags = _stream->readUint16LE();
+	_soundFlags       = _stream->readUint16LE();
+
 	_hasSound = (_soundFreq != 0);
 
-	// 0x32A (810)
-
 	if (_hasSound) {
 		_features |= kFeaturesSound;
 
 		_soundStereo = (_soundFlags & 0x8000) ? 1 : ((_soundFlags & 0x200) ? 2 : 0);
 		if (_soundStereo > 0) {
-			warning("TODO: VMD stereo");
+			warning("Vmd::load(): TODO: Stereo sound");
 			unload();
 			return false;
 		}
 
 		if (_soundSliceSize < 0) {
 			_soundBytesPerSample = 2;
-			_soundSliceSize = -_soundSliceSize;
+			_soundSliceSize      = -_soundSliceSize;
+
+			if (_soundFlags & 0x10) {
+				_audioFormat     = kAudioFormat16bitADPCM;
+				_soundHeaderSize = 3;
+				_soundDataSize   = _soundSliceSize >> 1;
+			} else {
+				_audioFormat     = kAudioFormat16bitDPCM;
+				_soundHeaderSize = 1;
+				_soundDataSize   = _soundSliceSize;
+			}
+		} else {
+			_soundBytesPerSample = 1;
+			_audioFormat         = kAudioFormat8bitDirect;
+			_soundHeaderSize     = 0;
+			_soundDataSize       = _soundSliceSize;
 		}
 
 		_soundSliceLength = (uint32) (((double) (1000 << 16)) /
@@ -1053,14 +1090,15 @@
 		_stream->skip(2); // Unknown
 		_frames[i].offset = _stream->readUint32LE();
 	}
+
 	for (uint16 i = 0; i < _framesCount; i++) {
 		bool separator = false;
 
 		for (uint16 j = 0; j < _partsPerFrame; j++) {
 
-			_frames[i].parts[j].type = (PartType) _stream->readByte();
+			_frames[i].parts[j].type    = (PartType) _stream->readByte();
 			_frames[i].parts[j].field_1 = _stream->readByte();
-			_frames[i].parts[j].size = _stream->readUint32LE();
+			_frames[i].parts[j].size    = _stream->readUint32LE();
 
 			if (_frames[i].parts[j].type == kPartTypeAudio) {
 
@@ -1069,12 +1107,12 @@
 
 			} else if (_frames[i].parts[j].type == kPartTypeVideo) {
 
-				_frames[i].parts[j].left = _stream->readUint16LE();
-				_frames[i].parts[j].top = _stream->readUint16LE();
-				_frames[i].parts[j].right = _stream->readUint16LE();
-				_frames[i].parts[j].bottom = _stream->readUint16LE();
+				_frames[i].parts[j].left    = _stream->readUint16LE();
+				_frames[i].parts[j].top     = _stream->readUint16LE();
+				_frames[i].parts[j].right   = _stream->readUint16LE();
+				_frames[i].parts[j].bottom  = _stream->readUint16LE();
 				_frames[i].parts[j].field_E = _stream->readByte();
-				_frames[i].parts[j].flags = _stream->readByte();
+				_frames[i].parts[j].flags   = _stream->readByte();
 
 			} else if (_frames[i].parts[j].type == kPartTypeExtraData) {
 				if (!separator)
@@ -1111,9 +1149,10 @@
 			if (_frames[i].parts[j].type == kPartTypeExtraData) {
 				ExtraData data;
 
-				data.offset = _stream->pos() + 20;
-				data.size = _frames[i].parts[j].size;
+				data.offset   = _stream->pos() + 20;
+				data.size     = _frames[i].parts[j].size;
 				data.realSize = _stream->readUint32LE();
+
 				_stream->read(data.name, 16);
 				data.name[15] = '\0';
 
@@ -1150,11 +1189,11 @@
 
 			if (_frames[i].parts[j].type == kPartTypeVideo) {
 				if (x >= 0) {
-					_frames[i].parts[j].left = _frames[i].parts[j].left - _x + x;
+					_frames[i].parts[j].left  = _frames[i].parts[j].left  - _x + x;
 					_frames[i].parts[j].right = _frames[i].parts[j].right - _x + x;
 				}
 				if (y >= 0) {
-					_frames[i].parts[j].top = _frames[i].parts[j].top - _y + y;
+					_frames[i].parts[j].top    = _frames[i].parts[j].top    - _y + y;
 					_frames[i].parts[j].bottom = _frames[i].parts[j].bottom - _y + y;
 				}
 			}
@@ -1252,16 +1291,19 @@
 	_extraData.clear();
 
 	_soundBytesPerSample = 1;
-	_soundStereo = 0;
+	_soundStereo         = 0;
+	_soundHeaderSize     = 0;
+	_soundDataSize       = 0;
+	_audioFormat         = kAudioFormat8bitDirect;
 
-	_externalCodec = false;
-	_doubleMode = false;
-	_blitMode = 0;
-	_bytesPerPixel = 1;
-	_preScaleX = 1;
-	_postScaleX = 1;
+	_externalCodec  = false;
+	_doubleMode     = false;
+	_blitMode       = 0;
+	_bytesPerPixel  = 1;
+	_preScaleX      = 1;
+	_postScaleX     = 1;
 	_scaleExternalX = 1;
-	_vidMemBuffer = 0;
+	_vidMemBuffer   = 0;
 }
 
 CoktelVideo::State Vmd::processFrame(uint16 frame) {
@@ -1271,9 +1313,9 @@
 	seekFrame(frame);
 
 	state.flags |= kStateNoVideoData;
-	state.left = 0x7FFF;
-	state.top = 0x7FFF;
-	state.right = 0;
+	state.left   = 0x7FFF;
+	state.top    = 0x7FFF;
+	state.right  = 0;
 	state.bottom = 0;
 
 	if (!_vidMem)
@@ -1312,7 +1354,7 @@
 			} else if (part.flags == 3) {
 
 				if (_soundEnabled) {
-					emptySoundSlice(_soundSliceSize * _soundBytesPerSample);
+					emptySoundSlice(_soundDataSize * _soundBytesPerSample);
 
 					if (_soundStage == 1)
 						startSound = true;
@@ -1320,12 +1362,12 @@
 
 				_stream->skip(part.size);
 			} else {
-				warning("Unknown sound part type %d", part.flags);
+				warning("Vmd::processFrame(): Unknown sound type %d", part.flags);
 				_stream->skip(part.size);
 			}
 
 		} else if ((part.type == kPartTypeVideo) && !_hasVideo) {
-			warning("Header claims there's no video, but video frame part found");
+			warning("Vmd::processFrame(): Header claims there's no video, but video found");
 		} else if ((part.type == kPartTypeVideo) && _hasVideo) {
 			state.flags &= ~kStateNoVideoData;
 
@@ -1360,12 +1402,17 @@
 				state.bottom = MAX(state.bottom, b);
 			}
 
-		} else if (part.type == 4) {
+		} else if (part.type == kPartTypeSeparator) {
+		} else if (part.type == kPartTypeExtraData) {
+			_stream->skip(part.size);
+		} else if (part.type == kPartType4) {
 			// Unknown
 			_stream->skip(part.size);
+		} else if (part.type == kPartTypeSpeech) {
+			// Always triggers when speech starts
+			_stream->skip(part.size);
 		} else {
-			// Unknow type
-//			warning("Unknown frame part type %d, size %d (%d of %d)", part.type, part.size, i + 1, _partsPerFrame);
+			warning("Vmd::processFrame(): Unknown frame part type %d, size %d (%d of %d)", part.type, part.size, i + 1, _partsPerFrame);
 		}
 	}
 
@@ -1379,7 +1426,7 @@
 		_audioStream->finish();
 		_mixer->stopHandle(_audioHandle);
 		_audioStream = 0;
-		_soundStage = 0;
+		_soundStage  = 0;
 	}
 
 	// If these are still 0x7FFF, no video data has been processed
@@ -1421,19 +1468,20 @@
 	if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0))
 		return 0;
 
-	int16 width = right - left + 1;
-	int16 height = bottom - top + 1;
-	int16 sW = _vidMemWidth;
-	int16 sH = _vidMemHeight;
+	int16 width  = right  - left + 1;
+	int16 height = bottom - top  + 1;
+	int16 sW     = _vidMemWidth;
+	int16 sH     = _vidMemHeight;
 	uint32 dataLen = _frameDataLen;
-	byte *dataPtr = _frameData;
+
+	byte *dataPtr   = _frameData;
 	byte *imdVidMem = _vidMem + sW * top + left;
 	byte *srcPtr;
-	uint8 type;
 
 	if ((width < 0) || (height < 0))
 		return 1;
 
+	uint8 type;
 	byte *dest = imdVidMem;
 
 	if (Indeo3::isIndeo3(dataPtr, dataLen)) {
@@ -1444,12 +1492,12 @@
 					width * (_doubleMode ? 2 : 1), height * (_doubleMode ? 2 : 1)))
 			return 0;
 
-		type = 2;
+		type   = 2;
 		srcPtr = _vidBuffer;
-		width = _width * (_doubleMode ? 2 : 1);
+		width  = _width  * (_doubleMode ? 2 : 1);
 		height = _height * (_doubleMode ? 2 : 1);
-		right = left + width - 1;
-		bottom = top + height - 1;
+		right  = left + width  - 1;
+		bottom = top  + height - 1;
 
 	} else {
 
@@ -1458,8 +1506,8 @@
 			return 0;
 		}
 
-		type = *dataPtr++;
-		srcPtr = dataPtr;
+		type   = *dataPtr++;
+		srcPtr =  dataPtr;
 
 		if (_blitMode > 0) {
 			dest = _vidMemBuffer + postScaleX(_width) * (top - _y) + postScaleX((left - _x));
@@ -1495,12 +1543,12 @@
 					memcpy(dest, srcPtr, pixCount);
 
 					pixWritten += pixCount;
-					dest += pixCount;
-					srcPtr += pixCount;
+					dest       += pixCount;
+					srcPtr     += pixCount;
 				} else { // "Hole"
-					pixCount = (pixCount + 1) % 256;
+					pixCount    = (pixCount + 1) % 256;
 					pixWritten += pixCount;
-					dest += pixCount;
+					dest       += pixCount;
 				}
 			}
 			destBak += sW;
@@ -1516,7 +1564,7 @@
 					dest[j] = srcPtr[j];
 
 			srcPtr += postScaleX(width);
-			dest += sW;
+			dest   += sW;
 		}
 
 	} else if (type == 3) { // RLE block
@@ -1531,14 +1579,14 @@
 
 					if (*srcPtr != 0xFF) { // Normal copy
 						memcpy(dest, srcPtr, pixCount);
-						dest += pixCount;
+						dest   += pixCount;
 						srcPtr += pixCount;
 					} else
 						deRLE(srcPtr, dest, pixCount);
 
 					pixWritten += pixCount;
 				} else { // "Hole"
-					dest += pixCount + 1;
+					dest       += pixCount + 1;
 					pixWritten += pixCount + 1;
 				}
 
@@ -1554,7 +1602,7 @@
 				memset(dest, *srcPtr, 4);
 
 			destBak += sW;
-			dest = destBak;
+			dest     = destBak;
 		}
 	} else if ((type & 0xF) == 2) { // Whole half-high block
 		for (; height > 1; height -= 2, dest += sW + sW, srcPtr += width) {
@@ -1575,16 +1623,16 @@
 					memcpy(dest + sW, srcPtr, pixCount);
 
 					pixWritten += pixCount;
-					dest += pixCount;
-					srcPtr += pixCount;
+					dest       += pixCount;
+					srcPtr     += pixCount;
 				} else { // "Hole"
-					pixCount = (pixCount + 1) % 256;
+					pixCount    = (pixCount + 1) % 256;
 					pixWritten += pixCount;
-					dest += pixCount;
+					dest       += pixCount;
 				}
 			}
 			destBak += sW + sW;
-			dest = destBak;
+			dest     = destBak;
 		}
 	}
 
@@ -1675,90 +1723,195 @@
 
 		dither->nextLine();
 		dest += _vidMemWidth;
-		src += 3 * srcPitch;
+		src  += 3 * srcPitch;
 	}
 
 	delete dither;
 }
 
-void Vmd::emptySoundSlice(uint32 size) {
+byte *Vmd::deDPCM(const byte *data, uint32 &size, int32 init) {
+	if (!data || (size == 0))
+		return 0;
+
+	uint32 inSize  = size;
+	uint32 outSize = size * 2;
+
+	byte *sound = new byte[outSize];
+
+	int16 *out = (int16 *) sound;
+
+	while (inSize-- > 0) {
+		if (*data & 0x80)
+			init -= _tableDPCM[*data++ & 0x7F];
+		else
+			init += _tableDPCM[*data++];
+
+		init   = CLIP<int32>(init, -32768, 32767);
+		*out++ = TO_BE_16(init);
+	}
+
+	size = outSize;
+	return sound;
+}
+
+// Yet another IMA ADPCM variant
+byte *Vmd::deADPCM(const byte *data, uint32 &size, int32 init, int32 index) {
+	if (!data || (size == 0))
+		return 0;
+
+	uint32 outSize = size * 4;
+
+	byte  *sound = new byte[outSize];
+	int16 *out   = (int16 *) sound;
+
+	index = CLIP<int32>(index, 0, 88);
+
+	int32 predictor = _tableADPCM[index];
+
+	uint32 dataByte = 0;
+	bool newByte = true;
+
+	size *= 2;
+	while (size -- > 0) {
+		byte code = 0;
+
+		if (newByte) {
+			dataByte = *data++;
+			code = (dataByte >> 4) & 0xF;
+		} else
+			code = dataByte & 0xF;
+
+		newByte = !newByte;
+
+		index += _tableADPCMStep[code];
+		index  = CLIP<int32>(index, 0, 88);
+
+		int32 value = predictor / 8;
+
+		if (code & 4)
+			value += predictor;
+		if (code & 2)
+			value += predictor / 2;
+		if (code & 1)
+			value += predictor / 4;
+
+		if (code & 8)
+			init -= value;
+		else
+			init += value;
+
+		init = CLIP<int32>(init, -32768, 32767);
+
+		predictor = _tableADPCM[index];
+
+		*out++ = TO_BE_16(init);
+	}
+
+	size = outSize;
+	return sound;
+}
+
+byte *Vmd::soundEmpty(uint32 &size) {
 	if (!_audioStream)
-		return;
+		return 0;
 
 	byte *soundBuf = new byte[size];
-	assert(soundBuf);
-
 	memset(soundBuf, 0, size);
 
-	_audioStream->queueBuffer(soundBuf, size);
+	return soundBuf;
 }
 
-void Vmd::soundSlice8bit(uint32 size) {
-	if (!_audioStream)
-		return;
+byte *Vmd::sound8bitDirect(uint32 &size) {
+	if (!_audioStream) {
+		_stream->skip(size);
+		return 0;
+	}
 
 	byte *soundBuf = new byte[size];
-	assert(soundBuf);
-
 	_stream->read(soundBuf, size);
 	unsignedToSigned(soundBuf, size);
 
-	_audioStream->queueBuffer(soundBuf, size);
+	return soundBuf;
 }
 
-void Vmd::soundSlice16bit(uint32 size, int16 &init) {
-	if (!_audioStream)
-		return;
+byte *Vmd::sound16bitDPCM(uint32 &size) {
+	if (!_audioStream) {
+		_stream->skip(size);
+		return 0;
+	}
 
-	byte *dataBuf = new byte[size];
-	byte *soundBuf = new byte[size * 2];
+	int32 init = _stream->readSint16LE();
+	size -= 2;
 
-	_stream->read(dataBuf, size);
-	deADPCM(soundBuf, dataBuf, init, size);
-	_audioStream->queueBuffer(soundBuf, size * 2);
+	byte *data  = new byte[size];
+	byte *sound = 0;
 
-	delete[] dataBuf;
+	if (_stream->read(data, size) == size)
+		sound = deDPCM(data, size, init);
+
+	delete[] data;
+
+	return sound;
 }
 
-void Vmd::filledSoundSlice(uint32 size) {
-	if (_soundBytesPerSample == 1) {
-		soundSlice8bit(size);
-	} else if (_soundBytesPerSample == 2) {
-		int16 init = _stream->readSint16LE();
-		soundSlice16bit(size - 2, init);
+byte *Vmd::sound16bitADPCM(uint32 &size) {
+	if (!_audioStream) {
+		_stream->skip(size);
+		return 0;
 	}
+
+	int32 init = _stream->readSint16LE();
+	size -= 2;
+
+	int32 v28 = _stream->readByte();
+	size--;
+
+	byte *data  = new byte[size];
+	byte *sound = 0;
+
+	if (_stream->read(data, size) == size)
+		sound = deADPCM(data, size, init, v28);
+
+	delete[] data;
+
+	return sound;
 }
 
+void Vmd::emptySoundSlice(uint32 size) {
+	byte *sound = soundEmpty(size);
+
+	if (sound)
+		_audioStream->queueBuffer(sound, size);
+}
+
+void Vmd::filledSoundSlice(uint32 size) {
+	byte *sound = 0;
+	if (_audioFormat == kAudioFormat8bitDirect)
+		sound = sound8bitDirect(size);
+	else if (_audioFormat == kAudioFormat16bitDPCM)
+		sound = sound16bitDPCM(size);
+	else if (_audioFormat == kAudioFormat16bitADPCM)
+		sound = sound16bitADPCM(size);
+
+	if (sound)
+		_audioStream->queueBuffer(sound, size);
+}
+
 void Vmd::filledSoundSlices(uint32 size, uint32 mask) {
 	int n = MIN<int>(_soundSlicesCount - 1, 31);
 	for (int i = 0; i < n; i++) {
 
 		if (mask & 1)
-			emptySoundSlice(_soundSliceSize * _soundBytesPerSample);
+			emptySoundSlice(_soundDataSize * _soundBytesPerSample);
 		else
-			filledSoundSlice(_soundSliceSize + 1);
+			filledSoundSlice(_soundDataSize + _soundHeaderSize);
 
 		mask >>= 1;
 	}
 	if (_soundSlicesCount > 32)
-		filledSoundSlice((_soundSlicesCount - 32) * _soundSliceSize);
+		filledSoundSlice((_soundSlicesCount - 32) * _soundDataSize + _soundHeaderSize);
 }
 
-void Vmd::deADPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) {
-	int16 *out = (int16 *) soundBuf;
-
-	int32 s = init;
-	for (uint32 i = 0; i < n; i++) {
-		if (dataBuf[i] & 0x80)
-			s -= _tableADPCM[dataBuf[i] & 0x7F];
-		else
-			s += _tableADPCM[dataBuf[i]];
-
-		s = CLIP<int32>(s, -32768, 32767);
-		*out++ = TO_BE_16(s);
-	}
-}
-
 bool Vmd::getAnchor(int16 frame, uint16 partType,
 		int16 &x, int16 &y, int16 &width, int16 &height) {
 
@@ -1789,9 +1942,9 @@
 	}
 
 	_stream->skip(5);
-	x = _stream->readSint16LE();
-	y = _stream->readSint16LE();
-	width = _stream->readSint16LE() - x + 1;
+	x      = _stream->readSint16LE();
+	y      = _stream->readSint16LE();
+	width  = _stream->readSint16LE() - x + 1;
 	height = _stream->readSint16LE() - y + 1;
 
 	_stream->seek(pos);

Modified: scummvm/trunk/graphics/video/coktelvideo/coktelvideo.h
===================================================================
--- scummvm/trunk/graphics/video/coktelvideo/coktelvideo.h	2009-07-24 20:45:42 UTC (rev 42703)
+++ scummvm/trunk/graphics/video/coktelvideo/coktelvideo.h	2009-07-24 21:29:41 UTC (rev 42704)
@@ -335,16 +335,26 @@
 protected:
 	enum PartType {
 		kPartTypeSeparator = 0,
-		kPartTypeAudio = 1,
-		kPartTypeVideo = 2,
-		kPartTypeExtraData = 3
+		kPartTypeAudio     = 1,
+		kPartTypeVideo     = 2,
+		kPartTypeExtraData = 3,
+		kPartType4         = 4,
+		kPartTypeSpeech    = 5
 	};
+
+	enum AudioFormat {
+		kAudioFormat8bitDirect = 0,
+		kAudioFormat16bitDPCM  = 1,
+		kAudioFormat16bitADPCM = 2
+	};
+
 	struct ExtraData {
 		char name[16];
 		uint32 offset;
 		uint32 size;
 		uint32 realSize;
 	} PACKED_STRUCT;
+
 	struct Part {
 		PartType type;
 		byte field_1;
@@ -356,6 +366,7 @@
 		int16 bottom;
 		byte flags;
 	} PACKED_STRUCT;
+
 	struct Frame {
 		uint32 offset;
 		Part *parts;
@@ -364,7 +375,9 @@
 		~Frame() { delete[] parts; }
 	} PACKED_STRUCT;
 
-	static const uint16 _tableADPCM[128];
+	static const uint16 _tableDPCM[128];
+	static const int32  _tableADPCM[];
+	static const int32  _tableADPCMStep[];
 
 	bool _hasVideo;
 
@@ -374,8 +387,11 @@
 
 	Common::Array<ExtraData> _extraData;
 
-	byte _soundBytesPerSample;
-	byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+	byte   _soundBytesPerSample;
+	byte   _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+	uint32 _soundHeaderSize;
+	uint32 _soundDataSize;
+	AudioFormat _audioFormat;
 
 	bool _externalCodec;
 	byte _blitMode;
@@ -404,12 +420,17 @@
 	void blit16(byte *dest, byte *src, int16 srcPitch, int16 width, int16 height);
 	void blit24(byte *dest, byte *src, int16 srcPitch, int16 width, int16 height);
 
+	byte *deDPCM(const byte *data, uint32 &size, int32 init);
+	byte *deADPCM(const byte *data, uint32 &size, int32 init, int32 v28);
+
+	byte *soundEmpty(uint32 &size);
+	byte *sound8bitDirect(uint32 &size);
+	byte *sound16bitDPCM(uint32 &size);
+	byte *sound16bitADPCM(uint32 &size);
+
 	void emptySoundSlice(uint32 size);
-	void soundSlice8bit(uint32 size);
-	void soundSlice16bit(uint32 size, int16 &init);
 	void filledSoundSlice(uint32 size);
 	void filledSoundSlices(uint32 size, uint32 mask);
-	void deADPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n);
 };
 
 } // End of namespace Graphics


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