[Scummvm-git-logs] scummvm master -> 05cae5caf4c8682a50c00e23709d055f3ceee4d6

bluegr noreply at scummvm.org
Tue Jan 7 01:38:31 UTC 2025


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:
05cae5caf4 SCUMM: More cleanup and fixes for the MI1SE audio code


Commit: 05cae5caf4c8682a50c00e23709d055f3ceee4d6
    https://github.com/scummvm/scummvm/commit/05cae5caf4c8682a50c00e23709d055f3ceee4d6
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2025-01-07T03:38:03+02:00

Commit Message:
SCUMM: More cleanup and fixes for the MI1SE audio code

Changed paths:
    engines/scumm/script_v5.cpp
    engines/scumm/scumm.h
    engines/scumm/sound.cpp
    engines/scumm/sound.h
    engines/scumm/soundse.cpp
    engines/scumm/soundse.h
    engines/scumm/string.cpp


diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 32581a8eafe..1932c53489e 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -1944,12 +1944,13 @@ void ScummEngine_v5::o5_pickupObject() {
 
 // Inject the speech from the SE version in the classic one, for MI1SE.
 void ScummEngine_v5::injectMISESpeech() {
-	if (_game.id == GID_MONKEY && (_game.features & GF_DOUBLEFINE_PAK) && _sound->useRemasteredAudio()) {
-		_currentScriptSavedForSpeechMI = vm.slot[_currentScript].number;
+	if (_sound->shouldInjectMISEAudio()) {
+		int32 currentScript = vm.slot[_currentScript].number;
+		int32 currentScriptOffset;
 		uint16 localScriptOffset;
 
-		if (_currentScriptSavedForSpeechMI >= _numGlobalScripts) {
-			int16 localScriptNumber = _currentScriptSavedForSpeechMI - _numGlobalScripts;
+		if (currentScript >= _numGlobalScripts) {
+			int16 localScriptNumber = currentScript - _numGlobalScripts;
 			if (localScriptNumber > 56)
 				localScriptOffset = 0;
 			else
@@ -1958,8 +1959,8 @@ void ScummEngine_v5::injectMISESpeech() {
 			localScriptOffset = 8;
 		}
 
-		_currentScriptOffsetSavedForSpeechMI = vm.slot[_currentScript].offs - localScriptOffset;
-		_currentSpeechIndexMI = 0;
+		currentScriptOffset = vm.slot[_currentScript].offs - localScriptOffset;
+		_sound->setupMISEAudioParams(currentScript, currentScriptOffset);
 	}
 }
 
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 4ef6a75a38f..6cd834dc465 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -887,11 +887,6 @@ public:
 
 	int _NESStartStrip = 0;
 
-	/* MI SE injected speech */
-	int32 _currentScriptSavedForSpeechMI = 0;
-	int32 _currentScriptOffsetSavedForSpeechMI = 0;
-	int32 _currentSpeechIndexMI = 0;
-
 protected:
 	int _curPalIndex = 0;
 
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 2255fae9706..8cdd7e6adf0 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -610,11 +610,11 @@ void Sound::startTalkSound(uint32 offset, uint32 length, int mode, Audio::SoundH
 			}
 		}
 		return;
-	} else if ((_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) && (_vm->_game.features & GF_DOUBLEFINE_PAK) && _useRemasteredAudio) {
+	} else if (shouldInjectMISEAudio()) {
 		// MI1 and MI2 SE
 		if (_soundSE && !_soundsPaused && _mixer->isReady()) {
 			Audio::AudioStream *input = _soundSE->getAudioStream(
-				_currentMISpeechIndex,
+				offset,
 				mode == DIGI_SND_MODE_SFX ? kSoundSETypeSFX : kSoundSETypeSpeech);
 
 			_digiSndMode |= mode;
@@ -625,8 +625,6 @@ void Sound::startTalkSound(uint32 offset, uint32 length, int mode, Audio::SoundH
 				else
 					_mixer->playStream(Audio::Mixer::kSpeechSoundType, handle, input, id);
 			}
-
-			_vm->_currentSpeechIndexMI++;
 		}
 
 		return;
@@ -761,6 +759,7 @@ void Sound::startTalkSound(uint32 offset, uint32 length, int mode, Audio::SoundH
 			if (mode == 2 && _vm->_game.id == GID_INDY4 && offset == 0x76ccbd4 && _vm->enhancementEnabled(kEnhGameBreakingBugFixes))
 				input = checkForBrokenIndy4Sample(file.release(), offset);
 
+			// Play remastered audio for DOTT
 			if (!input && _soundSE && _useRemasteredAudio) {
 				input = _soundSE->getAudioStream(
 					origOffset,
@@ -2193,16 +2192,27 @@ void Sound::updateMusicTimer() {
 	}
 }
 
-void Sound::startRemasteredSpeech(const char *msgString, uint16 roomNumber, uint16 actorTalking, uint16 currentScriptNum, uint16 currentScriptOffset, uint16 numWaits) {
+void Sound::startRemasteredSpeech(const char *msgString, uint16 roomNumber, uint16 actorTalking, uint16 numWaits) {
 	// Crudely adapted from the disasm of MI1SE...
 	// TODO: Apply the various speech-line substitutions performed per-game
 
-	int32 soundIndex = _soundSE->handleRemasteredSpeech(msgString, nullptr, roomNumber, actorTalking, currentScriptNum, currentScriptOffset, numWaits);
+	int32 soundIndex = _soundSE->handleRemasteredSpeech(
+		msgString,
+		nullptr,
+		roomNumber,
+		actorTalking,
+		numWaits
+	);
 
 	if (soundIndex >= 0) {
-		_currentMISpeechIndex = soundIndex;
-		talkSound(0, 0, DIGI_SND_MODE_TALKIE);
+		talkSound(soundIndex, 0, DIGI_SND_MODE_TALKIE);
 	}
 }
 
+bool Sound::shouldInjectMISEAudio() const {
+	return (_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) &&
+		   (_vm->_game.features & GF_DOUBLEFINE_PAK) &&
+		   _useRemasteredAudio;
+}
+
 } // End of namespace Scumm
diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h
index cd44f1f3280..34d0957db2e 100644
--- a/engines/scumm/sound.h
+++ b/engines/scumm/sound.h
@@ -103,8 +103,6 @@ protected:
 	SoundSE *_soundSE = nullptr;
 	bool _useRemasteredAudio = false;
 
-	int32 _currentMISpeechIndex = -1;
-
 public:
 	Audio::SoundHandle *_talkChannelHandle;	// Handle of mixer channel actor is talking on
 
@@ -152,8 +150,8 @@ public:
 
 	void updateMusicTimer();
 
-	bool useRemasteredAudio() const { return _useRemasteredAudio; }
-	void startRemasteredSpeech(const char *msgString, uint16 roomNumber, uint16 actorTalking, uint16 currentScriptNum, uint16 currentScriptOffset, uint16 numWaits);
+	bool shouldInjectMISEAudio() const;
+	void startRemasteredSpeech(const char *msgString, uint16 roomNumber, uint16 actorTalking, uint16 numWaits);
 
 	// TODO: Duplicate this in Sound as well?
 	bool isRolandLoom() const { return _soundCD->isRolandLoom(); }
@@ -173,6 +171,10 @@ public:
 		_soundCD->restoreCDAudioAfterLoad(info);
 	}
 
+	void setupMISEAudioParams(int32 scriptNum, int32 scriptOffset) {
+		_soundSE->setupMISEAudioParams(scriptNum, scriptOffset);
+	}
+
 protected:
 	void setupSfxFile();
 	bool isSfxFinished() const;
diff --git a/engines/scumm/soundse.cpp b/engines/scumm/soundse.cpp
index d812da0a13a..644259317e3 100644
--- a/engines/scumm/soundse.cpp
+++ b/engines/scumm/soundse.cpp
@@ -50,12 +50,13 @@ void SoundSE::initSoundFiles() {
 		_musicFilename = "MusicOriginal.xwb";
 		//_musicFilename = "MusicNew.xwb";	// TODO: allow toggle between original and new music
 		indexXWBFile(_musicFilename, &_musicEntries);
-		_sfxFilename = "SFXOriginal.xwb";
+		//_sfxFilename = "SFXOriginal.xwb";
 		//_sfxFilename = "SFXNew.xwb";	// TODO: allow toggle between original and new SFX
-		indexXWBFile(_sfxFilename, &_sfxEntries);
+		//indexXWBFile(_sfxFilename, &_sfxEntries);
 		_speechFilename = "Speech.xwb";
 		indexXWBFile(_speechFilename, &_speechEntries);
-		// TODO: iMUSEClient_Commentary.fsb
+		// TODO: ambience.xwb
+		// TODO: roomsfx.xwb
 		break;
 	case GID_TENTACLE:
 		initAudioMappingDOTTAndFT();
@@ -91,10 +92,8 @@ void SoundSE::initSoundFiles() {
 }
 
 Audio::SeekableAudioStream *SoundSE::getXWBTrack(int track) {
-	// TODO: Enable once WMA audio is implemented.
-	// Also, some of the PCM music tracks are not playing correctly
-	// (e.g. the act 1 track)
-	return nullptr;
+	if (track < 0 || track >= _musicEntries.size())
+		return nullptr;
 
 	Common::File *cdAudioFile = new Common::File();
 
@@ -105,14 +104,14 @@ Audio::SeekableAudioStream *SoundSE::getXWBTrack(int track) {
 
 	AudioEntry entry = _musicEntries[track];
 
-	auto subStream = new Common::SeekableSubReadStream(
+	Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(
 		cdAudioFile,
 		entry.offset,
 		entry.offset + entry.length,
 		DisposeAfterUse::YES
 	);
 
-	return createSoundStream(subStream, entry);
+	return createSoundStream(subStream, entry, DisposeAfterUse::YES);
 }
 
 #define WARN_AND_RETURN_XWB(message)          \
@@ -184,7 +183,21 @@ void SoundSE::indexXWBFile(const Common::String &filename, AudioIndex *audioInde
 		audioIndex->push_back(entry);
 	}
 
-	const uint32 nameOffset = segments[kXWBSegmentEntryNames].offset;
+	uint32 nameOffset = segments[kXWBSegmentEntryNames].offset;
+	uint32 nameLen = 64;
+
+#if 0
+	if (_vm->_game.id == GID_MONKEY2) {
+		f->close();
+
+		// The audio file names of Monkey Island 2 SE are placed in a separate file
+		// TODO: These are read in the wrong order
+		f->open(Common::Path("speechcues.xsb"));
+		f->skip(42);
+		nameOffset = f->readUint32LE();
+		nameLen = Common::String::npos;
+	}
+#endif
 
 	if (!nameOffset)
 		WARN_AND_RETURN_XWB("XWB file does not contain audio file names")
@@ -192,7 +205,7 @@ void SoundSE::indexXWBFile(const Common::String &filename, AudioIndex *audioInde
 	f->seek(nameOffset);
 
 	for (uint32 i = 0; i < entryCount; i++) {
-		Common::String name = f->readString(0, 64);
+		Common::String name = f->readString(0, nameLen);
 		name.toLowercase();
 
 		(*audioIndex)[i].name = name;
@@ -506,7 +519,7 @@ void SoundSE::initAudioMappingDOTTAndFT() {
 	delete f;
 }
 
-Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry) {
+Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry, DisposeAfterUse::Flag disposeAfterUse) {
 	switch (entry.codec) {
 	case kXWBCodecPCM: {
 		byte flags = Audio::FLAG_LITTLE_ENDIAN;
@@ -514,7 +527,7 @@ Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadSt
 			flags |= Audio::FLAG_16BITS;
 		if (entry.channels == 2)
 			flags |= Audio::FLAG_STEREO;
-		return Audio::makeRawStream(stream, entry.rate, flags, DisposeAfterUse::YES);
+		return Audio::makeRawStream(stream, entry.rate, flags, disposeAfterUse);
 	}
 	case kXWBCodecXMA:
 		// Unused in MI1SE and MI2SE
@@ -523,7 +536,7 @@ Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadSt
 		const uint32 blockAlign = (entry.align + 22) * entry.channels;
 		return Audio::makeADPCMStream(
 			stream,
-			DisposeAfterUse::YES,
+			disposeAfterUse,
 			entry.length,
 			Audio::kADPCMMS,
 			entry.rate,
@@ -548,7 +561,7 @@ Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadSt
 #ifdef USE_MAD
 		return Audio::makeMP3Stream(
 			stream,
-			DisposeAfterUse::YES
+			disposeAfterUse
 		);
 #else
 		warning("createSoundStream: MP3 codec is not built in");
@@ -573,27 +586,27 @@ int32 SoundSE::getSoundIndexFromOffset(uint32 offset) {
 	return -1;
 }
 
-SoundSE::AudioEntryMI *SoundSE::getAppropriateSpeechCue(const char *msgString, const char *speechFilenameSubstitution,
+int32 SoundSE::getAppropriateSpeechCue(const char *msgString, const char *speechFilenameSubstitution,
 											   uint16 roomNumber, uint16 actorTalking, uint16 scriptNum, uint16 scriptOffset, uint16 numWaits) {
 	uint32 hash;
 	AudioEntryMI *curAudioEntry;
 	uint16 script;
 	int32 currentScore;
 	int32 bestScore;
-	int bestScoreIdx;
+	int32 bestScoreIdx;
 	uint32 tmpHash;
 
 	hash = calculateStringHash(msgString);
 
 	tmpHash = hash;
 	if (!hash)
-		return nullptr;
+		return -1;
 
 	bestScore = 0x40000000; // This is the score that we have to minimize...
 	bestScoreIdx = -1;
 
 	if (_audioEntriesMI.empty())
-		return nullptr;
+		return -1;
 
 	for (uint curEntryIdx = 0; curEntryIdx < _audioEntriesMI.size(); curEntryIdx++) {
 		curAudioEntry = &_audioEntriesMI[curEntryIdx];
@@ -626,47 +639,42 @@ SoundSE::AudioEntryMI *SoundSE::getAppropriateSpeechCue(const char *msgString, c
 			}
 			if (currentScore < bestScore) {
 				bestScore = currentScore;
-				bestScoreIdx = (int)curEntryIdx;
+				bestScoreIdx = (int32)curEntryIdx;
 			}
 		}
 
 		hash = tmpHash;
 	}
-	if (bestScoreIdx == -1)
-		return nullptr;
-	else
-		return &_audioEntriesMI[bestScoreIdx];
+
+	return bestScoreIdx;
 }
 
 Audio::AudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType type) {
 	Common::SeekableReadStream *stream;
 	Common::String audioFileName;
-	AudioIndex &audioEntries = _musicEntries;
-	int32 soundIndex = 0;
+	AudioEntry audioEntry = {};
+	int32 soundIndex = getSoundIndexFromOffset(offset);
+
+	if (soundIndex == -1) {
+		warning("getAudioStream: sound index not found for offset %d", offset);
+		return nullptr;
+	}
 
 	switch (type) {
 	case kSoundSETypeMusic:
 		audioFileName = _musicFilename;
-		audioEntries = _musicEntries;
-		soundIndex = getSoundIndexFromOffset(offset);
+		audioEntry = _musicEntries[soundIndex];
 		break;
 	case kSoundSETypeSpeech:
 		audioFileName = _speechFilename;
-		audioEntries = _speechEntries;
-		soundIndex = getSoundIndexFromOffset(offset);
+		audioEntry = _speechEntries[soundIndex];
 		break;
 	case kSoundSETypeSFX:
 		audioFileName = _sfxFilename;
-		audioEntries = _sfxEntries;
-		soundIndex = getSoundIndexFromOffset(offset);
+		audioEntry = _sfxEntries[soundIndex];
 		break;
 	}
 
-	if (soundIndex == -1) {
-		warning("getAudioStream: sound index not found for offset %d", offset);
-		return nullptr;
-	}
-
 	if (_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) {
 		Common::File *audioFile = new Common::File();
 		stream = audioFile;
@@ -683,7 +691,6 @@ Audio::AudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType type) {
 		}
 	}
 
-	AudioEntry audioEntry = audioEntries[soundIndex];
 	Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(
 		stream,
 		audioEntry.offset,
@@ -691,7 +698,7 @@ Audio::AudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType type) {
 		DisposeAfterUse::YES
 	);
 
-	return createSoundStream(subStream, audioEntry);
+	return createSoundStream(subStream, audioEntry, DisposeAfterUse::YES);
 }
 
 Common::String calculateCurrentString(const char *msgString) {
@@ -781,20 +788,21 @@ Common::String calculateCurrentString(const char *msgString) {
 }
 
 int32 SoundSE::handleRemasteredSpeech(const char *msgString, const char *speechFilenameSubstitution,
-								     uint16 roomNumber, uint16 actorTalking, uint16 scriptNum, uint16 scriptOffset, uint16 numWaits) {
+								     uint16 roomNumber, uint16 actorTalking, uint16 numWaits) {
 
 	// Get the string without the various control codes and special characters...
 	Common::String currentString = calculateCurrentString(msgString);
-	const AudioEntryMI *entry = getAppropriateSpeechCue(
+	const int32 entryIndex = getAppropriateSpeechCue(
 		currentString.c_str(),
 		speechFilenameSubstitution,
 		roomNumber, actorTalking,
-		scriptNum,
-		scriptOffset,
+		(uint16)_currentScriptSavedForSpeechMI,
+		(uint16)_currentScriptOffsetSavedForSpeechMI,
 		numWaits
 	);
 
-	if (entry) {
+	if (entryIndex > 0 && entryIndex <= _audioEntriesMI.size()) {
+		const AudioEntryMI *entry = &_audioEntriesMI[entryIndex];
 		//debug("Selected entry: %s (%s)", entry->textEnglish.c_str(), entry->speechFile.c_str());
 		return _nameToIndex[entry->speechFile];
 	}
diff --git a/engines/scumm/soundse.h b/engines/scumm/soundse.h
index e6a6ed8769b..9ae8a0642a4 100644
--- a/engines/scumm/soundse.h
+++ b/engines/scumm/soundse.h
@@ -80,11 +80,9 @@ public:
 								const char *speechFilenameSubstitution,
 								uint16 roomNumber,
 								uint16 actorTalking,
-								uint16 scriptNum,
-								uint16 scriptOffset,
 								uint16 numWaits);
 
-	AudioEntryMI *getAppropriateSpeechCue(const char *msgString,
+	int32 getAppropriateSpeechCue(const char *msgString,
 										  const char *speechFilenameSubstitution,
 										  uint16 roomNumber,
 										  uint16 actorTalking,
@@ -92,6 +90,11 @@ public:
 										  uint16 scriptOffset,
 										  uint16 numWaits);
 
+	void setupMISEAudioParams(int32 scriptNum, int32 scriptOffset) {
+		_currentScriptSavedForSpeechMI = scriptNum;
+		_currentScriptOffsetSavedForSpeechMI = scriptOffset;
+	}
+
 private:
 	enum AudioCodec {
 		kXWBCodecPCM = 0,
@@ -139,6 +142,10 @@ private:
 	typedef Common::Array<AudioEntryMI> AudioIndexMI;
 	AudioIndexMI _audioEntriesMI;
 
+	/* MI SE injected speech */
+	int32 _currentScriptSavedForSpeechMI = 0;
+	int32 _currentScriptOffsetSavedForSpeechMI = 0;
+
 	int32 getSoundIndexFromOffset(uint32 offset);
 
 	void initAudioMappingMI();
@@ -151,7 +158,7 @@ private:
 	// Index FSB audio files - used in DOTT and FT
 	void indexFSBFile(const Common::String &filename, AudioIndex *audioIndex);
 
-	Audio::SeekableAudioStream *createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry);
+	Audio::SeekableAudioStream *createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry, DisposeAfterUse::Flag disposeAfterUse);
 };
 
 
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index cb0ba8b2afc..804785badcf 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1114,7 +1114,7 @@ void ScummEngine::displayDialog() {
 	if (_isRTL)
 		fakeBidiString(_charsetBuffer + _charsetBufPos, true, sizeof(_charsetBuffer) - _charsetBufPos);
 
-	if ((_game.features & GF_DOUBLEFINE_PAK) && (_game.id == GID_MONKEY || _game.id == GID_MONKEY2) && _sound->useRemasteredAudio()) {
+	if (_sound->shouldInjectMISEAudio()) {
 		int numberOfWaits = countNumberOfWaits();
 		int32 currentActor = VAR_TALK_ACTOR != 0xFF ? VAR(VAR_TALK_ACTOR) : 0;
 
@@ -1123,8 +1123,6 @@ void ScummEngine::displayDialog() {
 			(const char *)&_charsetBuffer[_charsetBufPos],
 			(uint16)_currentRoom,
 			(uint16)currentActor,
-			(uint16)_currentScriptSavedForSpeechMI,
-			(uint16)_currentScriptOffsetSavedForSpeechMI,
 			(uint16)numberOfWaits);
 	}
 




More information about the Scummvm-git-logs mailing list