[Scummvm-cvs-logs] SF.net SVN: scummvm: [28383] scummvm/trunk/engines/gob

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Wed Aug 1 14:24:05 CEST 2007


Revision: 28383
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28383&view=rev
Author:   drmccoy
Date:     2007-08-01 05:24:04 -0700 (Wed, 01 Aug 2007)

Log Message:
-----------
Support for (still a bit glitchy) 16bit sound

Modified Paths:
--------------
    scummvm/trunk/engines/gob/coktelvideo.cpp
    scummvm/trunk/engines/gob/coktelvideo.h

Modified: scummvm/trunk/engines/gob/coktelvideo.cpp
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.cpp	2007-08-01 09:08:27 UTC (rev 28382)
+++ scummvm/trunk/engines/gob/coktelvideo.cpp	2007-08-01 12:24:04 UTC (rev 28383)
@@ -109,7 +109,7 @@
 	// Sound
 	if (_features & kFeaturesSound) {
 		_soundFreq = _stream->readSint16LE();
-		_soundSliceSize = _stream->readUint16LE();
+		_soundSliceSize = _stream->readSint16LE();
 		_soundSlicesCount = _stream->readSint16LE();
 
 		if (_soundFreq < 0)
@@ -540,6 +540,7 @@
 				assert(soundBuf);
 
 				memset(soundBuf, 0, _soundSliceSize);
+
 				_audioStream->queueBuffer(soundBuf, _soundSliceSize);
 			}
 		}
@@ -819,6 +820,22 @@
 	}
 }
 
+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,
+	0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+	0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+	0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+	0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+	0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+	0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+	0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+	0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+	0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+	0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
+
 Vmd::Vmd() {
 	clear(false);
 }
@@ -880,7 +897,7 @@
 	}
 
 	_soundFreq = _stream->readSint16LE();
-	_soundSliceSize = _stream->readUint16LE();
+	_soundSliceSize = _stream->readSint16LE();
 	_soundSlicesCount = _stream->readSint16LE();
 	_soundFlags = _stream->readUint16LE();
 	_hasSound = (_soundFreq != 0);
@@ -888,11 +905,26 @@
 	if (_hasSound) {
 		_features |= kFeaturesSound;
 
-		_soundSliceLength = (uint16) (1000.0 / ((double) _soundFreq / (double) _soundSliceSize));
+		_soundStereo = (_soundFlags & 0x8000) ? 1 : ((_soundFlags & 0x200) ? 2 : 0);
+		if (_soundStereo > 0) {
+			warning("TODO: VMD stereo");
+			unload();
+			return false;
+		}
+
+		if (_soundSliceSize < 0) {
+			_soundBytesPerSample = 2;
+			_soundSliceSize = -_soundSliceSize;
+		}
+
+		_soundSliceLength = (uint16) (1000.0 /
+				((double) _soundFreq / (double) _soundSliceSize));
+
 		_frameLength = _soundSliceLength;
 
 		_soundStage = 1;
-		_audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
+		_audioStream = Audio::makeAppendableAudioStream(_soundFreq,
+				(_soundBytesPerSample == 2) ? Audio::Mixer::FLAG_16BITS : 0);
 	} else
 		_frameLength = 1000 / 12; // 12 FPS for a video without sound
 
@@ -1004,8 +1036,12 @@
 	}
 
 	_hasVideo = true;
+
 	_partsPerFrame = 0;
 	_frames = 0;
+
+	_soundBytesPerSample = 1;
+	_soundStereo = 0;
 }
 
 CoktelVideo::State Vmd::processFrame(uint16 frame) {
@@ -1027,39 +1063,23 @@
 		Part &part = _frames[frame].parts[i];
 
 		if (part.type == kPartTypeAudio) {
-			byte *soundBuf;
-
 			// Next sound slice data
 			if (part.flags == 1) {
 
-				if (_soundEnabled) {
-					soundBuf = new byte[part.size];
-					assert(soundBuf);
-
-					_stream->read(soundBuf, part.size);
-					unsignedToSigned(soundBuf, part.size);
-
-					_audioStream->queueBuffer(soundBuf, part.size);
-				} else
+				if (_soundEnabled)
+					filledSoundSlice(part.size);
+				else
 					_stream->skip(part.size);
 
 			// Initial sound data (all slices)
 			} else if (part.flags == 2) {
 
 				if (_soundEnabled) {
-					_stream->skip(4); // Unknown
+					uint32 mask = _stream->readUint32LE();
+					filledSoundSlices(part.size - 4, mask);
 
-					soundBuf = new byte[part.size - 4];
-					assert(soundBuf);
-
-					_stream->read(soundBuf, part.size - 4);
-					unsignedToSigned(soundBuf, part.size - 4);
-
-					_audioStream->queueBuffer(soundBuf, part.size - 4);
-
-					if (_soundStage == 1) {
+					if (_soundStage == 1)
 						startSound = true;
-					}
 
 				} else
 					_stream->skip(part.size);
@@ -1067,15 +1087,11 @@
 			// Empty sound slice
 			} else if (part.flags == 3) {
 
-				if (_soundEnabled && (part.size > 0)) {
-					soundBuf = new byte[part.size];
-					assert(soundBuf);
+				if (_soundEnabled && (part.size > 0))
+					emptySoundSlice(part.size);
+				else
+					_stream->skip(part.size);
 
-					memset(soundBuf, 0, part.size);
-
-					_audioStream->queueBuffer(soundBuf, part.size);
-				} else
-					_stream->skip(part.size);
 			}
 
 		} else if (part.type == kPartTypeVideo) {
@@ -1194,4 +1210,78 @@
 	return 1;
 }
 
+void Vmd::emptySoundSlice(uint32 size) {
+	byte *soundBuf = new byte[size];
+	assert(soundBuf);
+
+	memset(soundBuf, 0, size);
+
+	_audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice8bit(uint32 size) {
+	byte *soundBuf = new byte[size];
+	assert(soundBuf);
+
+	_stream->read(soundBuf, size);
+	unsignedToSigned(soundBuf, size);
+
+	_audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice16bit(uint32 size, int16 &init) {
+	byte *dataBuf = new byte[size];
+	byte *soundBuf = new byte[size * 2];
+
+	_stream->read(dataBuf, size);
+	deDPCM(soundBuf, dataBuf, init, size);
+	_audioStream->queueBuffer(soundBuf, size * 2);
+
+	delete[] dataBuf;
+}
+
+void Vmd::filledSoundSlice(uint32 size) {
+	if (_soundBytesPerSample == 1) {
+		soundSlice8bit(size);
+	} else if (_soundBytesPerSample == 2) {
+		int16 init = _stream->readSint16LE();
+		soundSlice16bit(size - 1, init);
+	}
+}
+
+void Vmd::filledSoundSlices(uint32 size, uint32 mask) {
+	if (_soundBytesPerSample == 1) {
+		soundSlice8bit(size);
+		return;
+	}
+
+	for (int i = 0; i < (_soundSlicesCount - 1); i++) {
+
+		if (mask & 1)
+			emptySoundSlice(_soundSliceSize * 2);
+		else {
+			int16 init = _stream->readSint16LE();
+			soundSlice16bit(_soundSliceSize, init);
+		}
+
+		mask >>= 1;
+	}
+
+}
+
+void Vmd::deDPCM(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 -= _tableDPCM[dataBuf[i] & 0x7F];
+		else
+			s += _tableDPCM[dataBuf[i]];
+
+		s = CLIP(s, -32768, 32767);
+		*out++ = TO_BE_16(s);
+	}
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/coktelvideo.h
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.h	2007-08-01 09:08:27 UTC (rev 28382)
+++ scummvm/trunk/engines/gob/coktelvideo.h	2007-08-01 12:24:04 UTC (rev 28383)
@@ -225,7 +225,7 @@
 
 	uint16 _soundFlags;
 	int16 _soundFreq;
-	uint16 _soundSliceSize;
+	int16 _soundSliceSize;
 	int16 _soundSlicesCount;
 	uint16 _soundSliceLength;
 
@@ -285,14 +285,27 @@
 		~Frame() { delete[] parts; }
 	} PACKED_STRUCT;
 
+	static const uint16 _tableDPCM[128];
+
 	bool _hasVideo;
+
 	uint16 _partsPerFrame;
 	Frame *_frames;
 
+	byte _soundBytesPerSample;
+	byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+
 	void clear(bool del = true);
 
 	State processFrame(uint16 frame);
 	uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom);
+
+	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 deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n);
 };
 
 } // End of namespace Gob


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