[Scummvm-git-logs] scummvm master -> 1ae637fb5732304f1ba650a944c92ecf05981ea5

bluegr noreply at scummvm.org
Mon May 23 20:22:22 UTC 2022


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1ae637fb57 SCUMM: Lip syncing fixes for some HE games.


Commit: 1ae637fb5732304f1ba650a944c92ecf05981ea5
    https://github.com/scummvm/scummvm/commit/1ae637fb5732304f1ba650a944c92ecf05981ea5
Author: Stephen Robinson (sblazerobinson at gmail.com)
Date: 2022-05-23T23:22:18+03:00

Commit Message:
SCUMM: Lip syncing fixes for some HE games.

Backyard Baseball 2003 was missing dialog which was lip-synced to
animation. This was due to it using the WAV block alignment as a count
of bytes per sample. This is not true for the IMA ADPCM format used for
speech in Backyard Baseball 2003.

Changed paths:
    audio/decoders/wave.cpp
    audio/decoders/wave.h
    engines/scumm/he/sound_he.cpp


diff --git a/audio/decoders/wave.cpp b/audio/decoders/wave.cpp
index 8569319a1d0..1da5f9bdb57 100644
--- a/audio/decoders/wave.cpp
+++ b/audio/decoders/wave.cpp
@@ -34,7 +34,7 @@
 
 namespace Audio {
 
-bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
+bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_, int *samplesPerBlock_) {
 	const int32 initialPos = stream.pos();
 	byte buf[4+1];
 
@@ -73,6 +73,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
 		warning("getWavInfo: 'fmt' header is too short");
 		return false;
 	}
+	uint32 fmtRemaining = fmtLength;
 
 	// Next comes the "type" field of the fmt header. Some typical
 	// values for it:
@@ -88,13 +89,32 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
 	uint16 blockAlign = stream.readUint16LE();	// == NumChannels * BitsPerSample/8
 	uint16 bitsPerSample = stream.readUint16LE();	// 8, 16 ...
 	// 8 bit data is unsigned, 16 bit data signed
-
+	fmtRemaining -= 16;
+
+	uint16 samplesPerBlock = 1;
+	if (type == kWaveFormatMSADPCM) {
+		// TODO: There is a samplesPerBlock in this header. It should be parsed and the below warning removed.
+		// (NB: The FMT header for MSADPCM has different information from the MSIMAADPCM)
+		warning("getWavInfo: 'fmt' header not parsed in entirety for MSADPCM");
+	} else if (type == kWaveFormatMSIMAADPCM) {
+		if (fmtRemaining != 4) {
+			// A valid IMA ADPCM fmt chunk is always 20 bytes long
+			warning("getWavInfo: 'fmt' header is wrong length for IMA ADPCM");
+			return false;
+		}
+		stream.readUint16LE(); // cbSize
+		samplesPerBlock = stream.readUint16LE();
+		fmtRemaining -= 4;
+	}
 
 	if (wavType != nullptr)
 		*wavType = type;
 
 	if (blockAlign_ != nullptr)
 		*blockAlign_ = blockAlign;
+
+	if (samplesPerBlock_ != nullptr)
+		*samplesPerBlock_ = samplesPerBlock;
 #if 0
 	debug("WAVE information:");
 	debug("  total size: %d", wavLength);
@@ -124,7 +144,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
 
 	if (type == kWaveFormatMP3) {
 		bitsPerSample = 8;
-	} else if (type != kWaveFormatMSADPCM) {
+	} else if (type != kWaveFormatMSADPCM && type != kWaveFormatMSIMAADPCM) {
 		if (blockAlign != numChannels * bitsPerSample / 8) {
 			debug(0, "getWavInfo: blockAlign is invalid");
 		}
@@ -162,7 +182,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
 	// 'data' chunk.
 
 	// Skip over the rest of the fmt chunk.
-	int offset = fmtLength - 16;
+	int offset = fmtRemaining;
 
 	do {
 		stream.seek(offset, SEEK_CUR);
diff --git a/audio/decoders/wave.h b/audio/decoders/wave.h
index 41ae780d773..72c99c91d93 100644
--- a/audio/decoders/wave.h
+++ b/audio/decoders/wave.h
@@ -74,7 +74,8 @@ extern bool loadWAVFromStream(
 	int &rate,
 	byte &flags,
 	uint16 *wavType = 0,
-	int *blockAlign = 0);
+	int *blockAlign = 0,
+	int *samplesPerBlock = 0);
 
 /**
  * Try to load a WAVE from the given seekable stream and create an AudioStream
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 3c1360b2c2a..9e3b3e8c454 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -600,6 +600,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
 	if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F') || READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) {
 		uint16 compType;
 		int blockAlign;
+		int samplesPerBlock;
 		int codeOffs = -1;
 
 		priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18);
@@ -623,7 +624,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
 		size = READ_LE_UINT32(ptr + 4);
 		Common::MemoryReadStream memStream(ptr, size);
 
-		if (!Audio::loadWAVFromStream(memStream, size, rate, flags, &compType, &blockAlign)) {
+		if (!Audio::loadWAVFromStream(memStream, size, rate, flags, &compType, &blockAlign, &samplesPerBlock)) {
 			error("playHESound: Not a valid WAV file (%d)", soundID);
 		}
 
@@ -649,12 +650,16 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
 
 		_mixer->stopHandle(_heSoundChannels[heChannel]);
 		if (compType == 17) {
-			Audio::AudioStream *voxStream = Audio::makeADPCMStream(&memStream, DisposeAfterUse::NO, size, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
+			int nChan = (flags & Audio::FLAG_STEREO) ? 2 : 1;
+			Audio::AudioStream *voxStream = Audio::makeADPCMStream(&memStream, DisposeAfterUse::NO, size, Audio::kADPCMMSIma, rate, nChan, blockAlign);
 
 			// FIXME: Get rid of this crude hack to turn a ADPCM stream into a raw stream.
 			// It seems it is only there to allow looping -- if that is true, we certainly
 			// can do without it, using a LoopingAudioStream.
 
+			if (_heChannel[heChannel].timer)
+				_heChannel[heChannel].timer = size / nChan * samplesPerBlock / blockAlign * 1000 / rate;
+
 			byte *sound = (byte *)malloc(size * 4);
 			/* On systems where it matters, malloc will return
 			 * even addresses, so the use of (void *) in the
@@ -664,10 +669,6 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
 			size *= 2; // 16bits.
 			delete voxStream;
 
-			_heChannel[heChannel].rate = rate;
-			if (_heChannel[heChannel].timer)
-				_heChannel[heChannel].timer = size * 1000 / (rate * blockAlign);
-
 			// makeADPCMStream returns a stream in native endianness, but RawMemoryStream
 			// defaults to big endian. If we're on a little endian system, set the LE flag.
 #ifdef SCUMM_LITTLE_ENDIAN




More information about the Scummvm-git-logs mailing list