[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