[Scummvm-git-logs] scummvm master -> 6271f8e0aaf226b54b0ae4b36cef4c8d562bde34

bluegr noreply at scummvm.org
Fri Jan 10 16:33:49 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:
6271f8e0aa SCUMM: Map SE ambience and commentary. Also, refactor the SE audio code


Commit: 6271f8e0aaf226b54b0ae4b36cef4c8d562bde34
    https://github.com/scummvm/scummvm/commit/6271f8e0aaf226b54b0ae4b36cef4c8d562bde34
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2025-01-10T18:33:19+02:00

Commit Message:
SCUMM: Map SE ambience and commentary. Also, refactor the SE audio code

Changed paths:
    engines/scumm/soundse.cpp
    engines/scumm/soundse.h


diff --git a/engines/scumm/soundse.cpp b/engines/scumm/soundse.cpp
index 2b9972ca2de..3c7c70a03ea 100644
--- a/engines/scumm/soundse.cpp
+++ b/engines/scumm/soundse.cpp
@@ -45,58 +45,28 @@ SoundSE::SoundSE(ScummEngine *parent, Audio::Mixer *mixer)
 void SoundSE::initSoundFiles() {
 	switch (_vm->_game.id) {
 	case GID_MONKEY:
-		initAudioMappingMI();
-		_musicFilename = "MusicOriginal.xwb";
-		//_musicFilename = "MusicNew.xwb";	// TODO: allow toggle between original and new music
-		indexXWBFile(_musicFilename, &_musicEntries);
-		//_sfxFilename = "SFXOriginal.xwb";
-		//_sfxFilename = "SFXNew.xwb";	// TODO: allow toggle between original and new SFX
-		//indexXWBFile(_sfxFilename, &_sfxEntries);
-		_speechFilename = "Speech.xwb";
-		indexXWBFile(_speechFilename, &_speechEntries);
-		// TODO: ambience.xwb
-		// TODO: roomsfx.xwb
-		break;
 	case GID_MONKEY2:
 		initAudioMappingMI();
-		_musicFilename = "MusicOriginal.xwb";
-		//_musicFilename = "MusicNew.xwb";	// TODO: allow toggle between original and new music
-		indexXWBFile(_musicFilename, &_musicEntries);
-		indexXSBFile("musiccuesoriginal.xsb", &_musicEntries);
-		//_sfxFilename = "SFXOriginal.xwb";
-		//_sfxFilename = "SFXNew.xwb";	// TODO: allow toggle between original and new SFX
-		// indexXWBFile(_sfxFilename, &_sfxEntries);
-		_speechFilename = "Speech.xwb";
-		indexXWBFile(_speechFilename, &_speechEntries);
-		indexXSBFile("speechcues.xsb", &_speechEntries);
-		// TODO: ambience.xwb
-		// TODO: commentary.xwb
-		// TODO: patch.xwb
+		indexXWBFile(kSoundSETypeMusic);
+		indexXWBFile(kSoundSETypeSFX);
+		indexXWBFile(kSoundSETypeSpeech);
+		indexXWBFile(kSoundSETypeAmbience);
+
+		if (_vm->_game.id == GID_MONKEY2) {
+			indexXWBFile(kSoundSETypeCommentary);
+			// TODO: indexXWBFile for patch.xwb
+			indexSpeechXSBFile();
+		}
 		break;
-	case GID_TENTACLE:
-		initAudioMappingDOTTAndFT();
-		_musicFilename = "iMUSEClient_Music.fsb";
-		indexFSBFile(_musicFilename, &_musicEntries);
-		_sfxFilename = "iMUSEClient_SFX.fsb";
-		indexFSBFile(_sfxFilename, &_sfxEntries);
-		_speechFilename = "iMUSEClient_VO.fsb";
-		indexFSBFile(_speechFilename, &_speechEntries);
-		// TODO: iMUSEClient_Commentary.fsb
 
-		// Clear the original offset map, as we no longer need it
-		_nameToOffsetDOTTAndFT.clear();
-		break;
+	case GID_TENTACLE:
 	case GID_FT:
 		initAudioMappingDOTTAndFT();
-		_musicFilename = "iMUSEClient_Music.fsb";
-		indexFSBFile(_musicFilename, &_musicEntries);
-		_sfxFilename = "iMUSEClient_SFX_INMEMORY.fsb";
-		indexFSBFile(_sfxFilename, &_sfxEntries);
-		_speechFilename = "iMUSEClient_SPEECH.fsb";
-		indexFSBFile(_speechFilename, &_speechEntries);
-		// TODO: iMUSEClient_SFX_STREAMING.fsb
-		// TODO: iMUSEClient_UI.fsb
-		// TODO: iMUSEClient_Commentary.fsb
+		indexFSBFile(kSoundSETypeMusic);
+		indexFSBFile(kSoundSETypeSFX);
+		indexFSBFile(kSoundSETypeSpeech);
+		indexFSBFile(kSoundSETypeCommentary);
+		// TODO: iMUSEClient_SFX_STREAMING.fsb for FT
 
 		// Clear the original offset map, as we no longer need it
 		_nameToOffsetDOTTAndFT.clear();
@@ -109,12 +79,11 @@ void SoundSE::initSoundFiles() {
 #define WARN_AND_RETURN_XWB(message)          \
 	{                                         \
 		warning("indexXWBFile: %s", message); \
-		f->close();                           \
 		delete f;                             \
 		return;                               \
 	}
 
-void SoundSE::indexXWBFile(const Common::String &filename, AudioIndex *audioIndex) {
+void SoundSE::indexXWBFile(SoundSEType type) {
 	// This implementation is based off unxwb: https://github.com/mariodon/unxwb/
 	// as well as xwbdump: https://raw.githubusercontent.com/wiki/Microsoft/DirectXTK/xwbdump.cpp
 	// Only the parts that apply to the Special Editions of
@@ -126,8 +95,10 @@ void SoundSE::indexXWBFile(const Common::String &filename, AudioIndex *audioInde
 	};
 	SegmentData segments[5] = {};
 
-	Common::File *f = new Common::File();
-	f->open(Common::Path(filename));
+	AudioIndex *audioIndex = getAudioEntries(type);
+	Common::SeekableReadStream *f = getAudioFile(type);
+	if (!f)
+		return;
 
 	const uint32 magic = f->readUint32BE();
 	const uint32 version = f->readUint32LE();
@@ -189,29 +160,25 @@ void SoundSE::indexXWBFile(const Common::String &filename, AudioIndex *audioInde
 		}
 	}
 
-	f->close();
 	delete f;
 }
 
 #undef WARN_AND_RETURN_XWB
 
-#define WARN_AND_RETURN_XSB(message)          \
-	{                                         \
-		warning("indexXSBFile: %s", message); \
-		f->close();                           \
-		delete f;                             \
-		return;                               \
-	}
-
-void SoundSE::indexXSBFile(const Common::String &filename, AudioIndex *audioIndex) {
+void SoundSE::indexSpeechXSBFile() {
 	Common::List<uint16> speechIndices;
 
-	Common::File *f = new Common::File();
-	f->open(Common::Path(filename));
+	AudioIndex *audioIndex = getAudioEntries(kSoundSETypeSpeech);
+	Common::SeekableReadStream *f = getAudioFile("speechcues.xsb");
+	if (!f)
+		return;
 
 	const uint32 magic = f->readUint32BE();
-	if (magic != MKTAG('S', 'D', 'B', 'K'))
-		WARN_AND_RETURN_XSB("Invalid XSB file")
+	if (magic != MKTAG('S', 'D', 'B', 'K')) {
+		warning("Invalid XSB file");
+		delete f;
+		return;
+	}
 
 	f->skip(15);
 	const uint32 entryCount = f->readUint32LE();
@@ -235,38 +202,33 @@ void SoundSE::indexXSBFile(const Common::String &filename, AudioIndex *audioInde
 		Common::String name = f->readString(0);
 		name.toLowercase();
 
-		if (/*index >= 0 && */index < (*audioIndex).size()) {
+		if (index < (*audioIndex).size()) {
 			(*audioIndex)[index].name = name;
 			_nameToIndex[name] = index;
 		}
 	}
 
-	f->close();
 	delete f;
 }
 
-#undef WARN_AND_RETURN_XSB
-
-#define WARN_AND_RETURN_FSB(message)          \
-	{                                         \
-		warning("indexFSBFile: %s", message); \
-		f->close();                           \
-		delete f;                             \
-		return;                               \
-	}
-
 #define GET_FSB5_OFFSET(X) ((((X) >> (uint64)7) << (uint64)5) & (((uint64)1 << (uint64)32) - 1))
 
-void SoundSE::indexFSBFile(const Common::String &filename, AudioIndex *audioIndex) {
+void SoundSE::indexFSBFile(SoundSEType type) {
 	// Based off DoubleFine Explorer: https://github.com/bgbennyboy/DoubleFine-Explorer/blob/master/uDFExplorer_FSBManager.pas
 	// and fsbext: https://aluigi.altervista.org/search.php?src=fsbext
-	ScummPAKFile *f = new ScummPAKFile(_vm);
-	_vm->openFile(*f, Common::Path(filename));
+
+	AudioIndex *audioIndex = getAudioEntries(type);
+	Common::SeekableReadStream *f = getAudioFile(type);
+	if (!f)
+		return;
 
 	const uint32 headerSize = 60; // 4 * 7 + 8 + 16 + 8
 	const uint32 magic = f->readUint32BE();
-	if (magic != MKTAG('F', 'S', 'B', '5'))
-		WARN_AND_RETURN_FSB("Invalid FSB file")
+	if (magic != MKTAG('F', 'S', 'B', '5')) {
+		warning("Invalid FSB file");
+		delete f;
+		return;
+	}
 
 	/*const uint32 version = */f->readUint32LE();
 	const uint32 sampleCount = f->readUint32LE();
@@ -368,12 +330,10 @@ void SoundSE::indexFSBFile(const Common::String &filename, AudioIndex *audioInde
 		//debug("indexFSBFile: %s -> offset %d, index %d", name.c_str(), origOffset, i);
 	}
 
-	f->close();
 	delete f;
 }
 
 #undef GET_FSB5_OFFSET
-#undef WARN_AND_RETURN_FSB
 
 static int32 calculateStringHash(const char *input) {
 	int32 hash = 0;
@@ -485,11 +445,9 @@ static int32 calculateStringSimilarity(const char *str1, const char *str2) {
 }
 
 void SoundSE::initAudioMappingMI() {
-	Common::File *f = new Common::File();
-	if (!f->open(Common::Path("speech.info"))) {
-		delete f;
+	Common::SeekableReadStream *f = getAudioFile("speech.info");
+	if (!f)
 		return;
-	}
 
 	_audioEntriesMI.clear();
 
@@ -522,13 +480,13 @@ void SoundSE::initAudioMappingMI() {
 		_audioEntriesMI.emplace_back(entry);
 	} while (!f->eos());
 
-	f->close();
 	delete f;
 }
 
 void SoundSE::initAudioMappingDOTTAndFT() {
-	ScummPAKFile *f = new ScummPAKFile(_vm);
-	_vm->openFile(*f, Common::Path("audiomapping.info"));
+	Common::SeekableReadStream *f = getAudioFile("audiomapping.info");
+	if (!f)
+		return;
 
 	do {
 		const uint32 origOffset = f->readUint32LE();
@@ -544,10 +502,84 @@ void SoundSE::initAudioMappingDOTTAndFT() {
 		_nameToOffsetDOTTAndFT[name] = origOffset;
 	} while (!f->eos());
 
-	f->close();
 	delete f;
 }
 
+Common::String SoundSE::getAudioFilename(SoundSEType type) {
+	const bool isMonkey = _vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2;
+	const bool isTentacle = _vm->_game.id == GID_TENTACLE;
+	const bool isFT = _vm->_game.id == GID_FT;
+
+	switch (type) {
+	case kSoundSETypeMusic:
+	case kSoundSETypeCDAudio:
+		return isMonkey ? "MusicOriginal.xwb" : "iMUSEClient_Music.fsb";
+	case kSoundSETypeSpeech:
+		if (isMonkey)
+			return "Speech.xwb";
+		else if (isTentacle)
+			return "iMUSEClient_VO.fsb";
+		else if (isFT)
+			return "iMUSEClient_SPEECH.fsb";
+	case kSoundSETypeSFX:
+		if (isMonkey)
+			return "SFXOriginal.xwb";
+		else if (isTentacle)
+			return "iMUSEClient_SFX.fsb";
+		else if (isFT)
+			return "iMUSEClient_SFX_INMEMORY.fsb";
+	case kSoundSETypeAmbience:
+		return "Ambience.xwb";
+	case kSoundSETypeCommentary:
+		return isMonkey ? "commentary.xwb" : "iMUSEClient_Commentary.fsb";
+	default:
+		error("getAudioFilename: unknown SoundSEType %d", type);
+	}
+}
+
+Common::SeekableReadStream *SoundSE::getAudioFile(SoundSEType type) {
+	Common::String audioFileName = getAudioFilename(type);
+	return getAudioFile(audioFileName);
+}
+
+Common::SeekableReadStream *SoundSE::getAudioFile(const Common::String &filename) {
+	if (_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) {
+		Common::File *audioFile = new Common::File();
+		if (!audioFile->open(Common::Path(filename))) {
+			warning("getAudioFile: failed to open %s", filename.c_str());
+			delete audioFile;
+			return nullptr;
+		}
+		return audioFile;
+	} else {
+		ScummPAKFile *audioFile = new ScummPAKFile(_vm);
+		if (!_vm->openFile(*audioFile, Common::Path(filename))) {
+			warning("getAudioFile: failed to open %s", filename.c_str());
+			delete audioFile;
+			return nullptr;
+		}
+		return audioFile;
+	}
+}
+
+SoundSE::AudioIndex *SoundSE::getAudioEntries(SoundSEType type) {
+	switch (type) {
+	case kSoundSETypeMusic:
+	case kSoundSETypeCDAudio:
+		return &_musicEntries;
+	case kSoundSETypeSpeech:
+		return &_speechEntries;
+	case kSoundSETypeSFX:
+		return &_sfxEntries;
+	case kSoundSETypeAmbience:
+		return &_ambienceEntries;
+	case kSoundSETypeCommentary:
+		return &_commentaryEntries;
+	default:
+		error("getAudioEntries: unknown SoundSEType %d", type);
+	}
+}
+
 Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry, DisposeAfterUse::Flag disposeAfterUse) {
 	switch (entry.codec) {
 	case kXWBCodecPCM: {
@@ -605,11 +637,8 @@ Audio::SeekableAudioStream *SoundSE::createSoundStream(Common::SeekableSubReadSt
 int32 SoundSE::getSoundIndexFromOffset(uint32 offset) {
 	if (_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) {
 		return offset;
-	} else if (_vm->_game.id == GID_TENTACLE) {
-		if (_offsetToIndexDOTTAndFT.contains(offset))
-			return _offsetToIndexDOTTAndFT[offset];
-		else
-			return -1;
+	} else if (_vm->_game.id == GID_TENTACLE || _vm->_game.id == GID_FT) {
+		return (_offsetToIndexDOTTAndFT.contains(offset)) ? (int32)_offsetToIndexDOTTAndFT[offset] : -1;
 	}
 
 	return -1;
@@ -617,24 +646,15 @@ int32 SoundSE::getSoundIndexFromOffset(uint32 offset) {
 
 int32 SoundSE::getAppropriateSpeechCue(const char *msgString, const char *speechFilenameSubstitution,
 											   uint16 roomNumber, uint16 actorTalking, uint16 scriptNum, uint16 scriptOffset, uint16 numWaits) {
-	uint32 hash;
+	uint32 hash = calculateStringHash(msgString);
+	uint32 tmpHash = hash;
 	AudioEntryMI *curAudioEntry;
 	uint16 script;
 	int32 currentScore;
-	int32 bestScore;
-	int32 bestScoreIdx;
-	uint32 tmpHash;
-
-	hash = calculateStringHash(msgString);
-
-	tmpHash = hash;
-	if (!hash)
-		return -1;
-
-	bestScore = 0x40000000; // This is the score that we have to minimize...
-	bestScoreIdx = -1;
+	int32 bestScore = 0x40000000; // This is the score that we have to minimize...
+	int32 bestScoreIdx = -1;
 
-	if (_audioEntriesMI.empty())
+	if (!hash || _audioEntriesMI.empty())
 		return -1;
 
 	for (uint curEntryIdx = 0; curEntryIdx < _audioEntriesMI.size(); curEntryIdx++) {
@@ -679,9 +699,9 @@ int32 SoundSE::getAppropriateSpeechCue(const char *msgString, const char *speech
 }
 
 Audio::SeekableAudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType type) {
-	Common::SeekableReadStream *stream;
-	Common::String audioFileName;
+	AudioIndex *audioIndex = getAudioEntries(type);
 	AudioEntry audioEntry = {};
+
 	int32 soundIndex = (type != kSoundSETypeCDAudio) ? getSoundIndexFromOffset(offset) : (int32)offset;
 
 	if (soundIndex == -1) {
@@ -689,40 +709,14 @@ Audio::SeekableAudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType t
 		return nullptr;
 	}
 
-	switch (type) {
-	case kSoundSETypeMusic:
-	case kSoundSETypeCDAudio:
-		audioFileName = _musicFilename;
-		audioEntry = _musicEntries[soundIndex];
-		break;
-	case kSoundSETypeSpeech:
-		audioFileName = _speechFilename;
-		audioEntry = _speechEntries[soundIndex];
-		break;
-	case kSoundSETypeSFX:
-		audioFileName = _sfxFilename;
-		audioEntry = _sfxEntries[soundIndex];
-		break;
-	}
+	audioEntry = (*audioIndex)[soundIndex];
 
-	if (_vm->_game.id == GID_MONKEY || _vm->_game.id == GID_MONKEY2) {
-		Common::File *audioFile = new Common::File();
-		stream = audioFile;
-		if (!audioFile->open(Common::Path(audioFileName))) {
-			delete audioFile;
-			return nullptr;
-		}
-	} else {
-		ScummPAKFile *audioFile = new ScummPAKFile(_vm);
-		stream = audioFile;
-		if (!_vm->openFile(*audioFile, Common::Path(audioFileName))) {
-			delete audioFile;
-			return nullptr;
-		}
-	}
+	Common::SeekableReadStream *f = getAudioFile(type);
+	if (!f)
+		return nullptr;
 
 	Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(
-		stream,
+		f,
 		audioEntry.offset,
 		audioEntry.offset + audioEntry.length,
 		DisposeAfterUse::YES
@@ -732,15 +726,13 @@ Audio::SeekableAudioStream *SoundSE::getAudioStream(uint32 offset, SoundSEType t
 }
 
 Common::String calculateCurrentString(const char *msgString) {
-	char currentChar;
+	char currentChar = *msgString;
 	bool shouldContinue = true;
 	char messageBuffer[512];
 	char *outMsgBuffer = messageBuffer;
 
 	memset(messageBuffer, 0, sizeof(messageBuffer));
 
-	currentChar = *msgString;
-
 	// Handle empty string case
 	if (msgString[0] == '\0') {
 		messageBuffer[0] = 0;
diff --git a/engines/scumm/soundse.h b/engines/scumm/soundse.h
index e74f637cf99..f3dce042425 100644
--- a/engines/scumm/soundse.h
+++ b/engines/scumm/soundse.h
@@ -40,9 +40,11 @@ class ScummEngine;
 
 enum SoundSEType {
 	kSoundSETypeMusic,
+	kSoundSETypeCDAudio,
 	kSoundSETypeSpeech,
 	kSoundSETypeSFX,
-	kSoundSETypeCDAudio
+	kSoundSETypeAmbience,
+	kSoundSETypeCommentary
 };
 
 class SoundSE {
@@ -124,11 +126,10 @@ private:
 	NameToIndexMap _nameToIndex;
 
 	AudioIndex _musicEntries;
-	Common::String _musicFilename;
 	AudioIndex _speechEntries;
-	Common::String _speechFilename;
 	AudioIndex _sfxEntries;
-	Common::String _sfxFilename;
+	AudioIndex _ambienceEntries;
+	AudioIndex _commentaryEntries;
 
 	typedef Common::Array<AudioEntryMI> AudioIndexMI;
 	AudioIndexMI _audioEntriesMI;
@@ -151,11 +152,16 @@ private:
 	void initSoundFiles();
 
 	// Index XWB audio files and XSB cue files - used in MI1SE and MI2SE
-	void indexXWBFile(const Common::String &filename, AudioIndex *audioIndex);
-	void indexXSBFile(const Common::String &filename, AudioIndex *audioIndex);
+	void indexXWBFile(SoundSEType type);
+	void indexSpeechXSBFile();
 
 	// Index FSB audio files - used in DOTT and FT
-	void indexFSBFile(const Common::String &filename, AudioIndex *audioIndex);
+	void indexFSBFile(SoundSEType type);
+
+	Common::String getAudioFilename(SoundSEType type);
+	Common::SeekableReadStream *getAudioFile(const Common::String &filename);
+	Common::SeekableReadStream *getAudioFile(SoundSEType type);
+	AudioIndex *getAudioEntries(SoundSEType type);
 
 	Audio::SeekableAudioStream *createSoundStream(Common::SeekableSubReadStream *stream, AudioEntry entry, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
 };




More information about the Scummvm-git-logs mailing list