[Scummvm-git-logs] scummvm master -> 17b4a5a08803e5c3aec55382424ec91ef5ed27e5

sev- sev at scummvm.org
Sun Mar 14 18:10:39 UTC 2021


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:
17b4a5a088 SCUMM: FT: improve and fix iMUSE Digital


Commit: 17b4a5a08803e5c3aec55382424ec91ef5ed27e5
    https://github.com/scummvm/scummvm/commit/17b4a5a08803e5c3aec55382424ec91ef5ed27e5
Author: Andrea Boscarino (andrea.boscarino at studio.unibo.it)
Date: 2021-03-14T19:10:37+01:00

Commit Message:
SCUMM: FT: improve and fix iMUSE Digital

Changed paths:
    engines/scumm/imuse_digi/dimuse.cpp
    engines/scumm/imuse_digi/dimuse.h
    engines/scumm/imuse_digi/dimuse_track.cpp
    engines/scumm/imuse_digi/dimuse_track.h


diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index d85348af4d..62b3ec7adf 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -52,6 +52,8 @@ IMuseDigital::IMuseDigital(ScummEngine_v7 *scumm, Audio::Mixer *mixer, int fps)
 	_sound = new ImuseDigiSndMgr(_vm);
 	assert(_sound);
 	_callbackFps = fps;
+	if (_vm->_game.id == GID_FT)
+		_callbackFps *= 2;
 	resetState();
 	for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) {
 		_track[l] = new Track;
@@ -183,6 +185,8 @@ void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
 			}
 
 			if (_vm->_game.id == GID_CMI) {
+				track->gainRedFadeDest = 127 * 290;
+
 				if (track->soundId / 1000 == 1) { // State
 					for (int ll = 0; _comiStateMusicTable[ll].soundId != -1; ll++) {
 						if ((_comiStateMusicTable[ll].soundId == track->soundId)) {
@@ -200,6 +204,10 @@ void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
 				}
 			}
 
+			if (_vm->_game.id == GID_FT) {
+				track->gainRedFadeDest = 127 * 180;
+			}
+
 			track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);
 			track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion);
 			int bits = _sound->getBits(track->soundDesc);
@@ -278,7 +286,7 @@ void IMuseDigital::runScheduledCrossfades() {
 
 			newTrack->dataOffset = _scheduledCrossfades[l].destDataOffset;
 			oldTrack->alreadyCrossfading = true; // We set this so to avoid duplicate crossfades
-			handleComiFadeOut(oldTrack, _scheduledCrossfades[l].fadeDelay);
+			handleFadeOut(oldTrack, _scheduledCrossfades[l].fadeDelay);
 		}
 	}
 }
@@ -288,7 +296,7 @@ void IMuseDigital::callback() {
 	runScheduledCrossfades();
 	_speechIsPlaying = false;
 	// Check for any track playing a speech line
-	if (_vm->_game.id == GID_CMI) {
+	if (_vm->_game.id != GID_DIG) {
 		for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
 			if (_track[l]->used && _track[l]->soundId == kTalkSoundID) {
 				// Set flag and break
@@ -312,69 +320,64 @@ void IMuseDigital::callback() {
 			if (_pause)
 				return;
 
+			// Fades and crossfades handling
 			if (track->volFadeUsed) {
-				if (_vm->_game.id == GID_CMI) {
-					if (track->vol == track->volFadeDest) // Sanity check
-						track->volFadeUsed = false;
-
-					if (track->volFadeStep < 0) { // Fade out
-						if (track->vol > track->volFadeDest) {
+				if (track->vol == track->volFadeDest) // Sanity check (needed for some edge cases in COMI, FT and DIG)
+					track->volFadeUsed = false;
+				if (track->volFadeStep < 0) { // Fade out
+					if (track->vol > track->volFadeDest) {
+						// COMI uses non-linear fade curves
+						if (_vm->_game.id == GID_CMI) {
 							int tempVolume = transformVolumeEqualPowToLinear(track->vol, 1); // Equal power to linear...
 							tempVolume += track->volFadeStep; // Remove step...
 							track->vol = transformVolumeLinearToEqualPow(tempVolume, 1); // Linear to equal power...
-
-							if (track->vol <= track->volFadeDest) {
-								track->vol = track->volFadeDest;
-								track->volFadeUsed = false;
-								flushTrack(track);
-								continue;
-							}
-							if (track->vol == 0) {
-								// Fade out complete -> remove this track
+						} else {
+							track->vol += track->volFadeStep; // Remove step...
+						}
+						if (track->vol <= track->volFadeDest) {
+							track->vol = track->volFadeDest;
+							track->volFadeUsed = false;
+							// In COMI we flush the track if we've faded out to the destination volume;
+							// this is because there are no situations in which there is a fade out to a
+							// non-zero volume, so this will always mean that we can free the track.
+							// This is not true in Full Throttle, for example, so we have to make this distinction.
+							if (_vm->_game.id == GID_CMI) {
 								flushTrack(track);
 								continue;
 							}
 						}
-					} else if (track->volFadeStep > 0) { // Fade in
-						if (track->vol < track->volFadeDest) {
+						if (track->vol == 0) {
+							// Fade out complete -> remove this track
+							flushTrack(track);
+							continue;
+						}
+					}
+				} else if (track->volFadeStep > 0) { // Fade in
+					if (track->vol < track->volFadeDest) {
+						// Again, COMI uses non-linear fade curves
+						// Curiously, FT uses a different curve for fade-ins
+						if (_vm->_game.id == GID_CMI) {
 							int tempVolume = transformVolumeEqualPowToLinear(track->vol, 1); // Equal power to linear...
 							tempVolume += track->volFadeStep; // Add step...
 							track->vol = transformVolumeLinearToEqualPow(tempVolume, 1); // Linear to equal power...
-							if (track->vol >= track->volFadeDest) {
-								track->vol = track->volFadeDest;
-								track->volFadeUsed = false;
-							}
-						}
-					}
-				} else {
-					if (track->volFadeStep < 0) {
-						if (track->vol > track->volFadeDest) {
-							track->vol += track->volFadeStep; 
-							if (track->vol < track->volFadeDest) {
-								track->vol = track->volFadeDest;
-								track->volFadeUsed = false;
-							}
-							if (track->vol == 0) {
-								// Fade out complete -> remove this track
-								flushTrack(track);
-								continue;
-							}
+						} else if (_vm->_game.id == GID_FT) {
+							int tempVolume = transformVolumeEqualPowToLinear(track->vol, 6); // Equal power to linear...
+							tempVolume += (track->volFadeStep); // Add step...
+							track->vol = transformVolumeLinearToEqualPow(tempVolume, 6); // Linear to equal power...
+						} else {
+							track->vol += track->volFadeStep; // Add step...
 						}
-					} else if (track->volFadeStep > 0) {
-						if (track->vol < track->volFadeDest) {
-							track->vol += track->volFadeStep;
-							if (track->vol > track->volFadeDest) {
-								track->vol = track->volFadeDest;
-								track->volFadeUsed = false;
-							}
+						if (track->vol >= track->volFadeDest) {
+							track->vol = track->volFadeDest;
+							track->volFadeUsed = false;
 						}
 					}
 				}
  				debug(5, "Fade: sound(%d), Vol(%d) in track(%d)", track->soundId, track->vol / 1000, track->trackId);
 			}
 
-			// Music gain reduction during speech
-			if (_vm->_game.id == GID_CMI && track->volGroupId == IMUSE_VOLGRP_MUSIC) {
+			// Music gain reduction during speech (used, at the moment, on FT and COMI)
+			if (_vm->_game.id != GID_DIG && track->volGroupId == IMUSE_VOLGRP_MUSIC) {
 				if (_speechIsPlaying) {
 					// Check if we have to fade down or the reduction volume is already at the right value
 					if (track->gainReduction >= track->gainRedFadeDest) {
@@ -510,23 +513,40 @@ void IMuseDigital::callback() {
 			if (_mixer->isReady()) {
 				int effVol = track->getVol();
 				int effPan = track->getPan();
-				if (_vm->_game.id == GID_CMI && track->volGroupId == IMUSE_VOLGRP_MUSIC) {
-					effVol -= track->gainReduction / 1000;
-					if (effVol < 0) // In case a music crossfading happens during gain reduction...
-						effVol = 0;
-					effVol = int(round(effVol * 1.9)); // Adjust default music mix for COMI
-				} else if (_vm->_game.id == GID_CMI && track->volGroupId == IMUSE_VOLGRP_VOICE) {
-					// Just in case the speakingActor is not being set...
-					// This allows for a fallback to pan = 64 (center) and volume = 127 (full)
-					if (track->speakingActor != nullptr) {
-						effVol = track->speakingActor->_talkVolume;
-						// Even though we fixed this in IMuseDigital::setVolume(),
-						// some sounds might be started without even calling that function
-						if (effVol > 127)
-							effVol /= 2;
-						effVol = int(round(effVol * 1.04));
-						effPan = (track->speakingActor->_talkPan != 64) ? 2 * track->speakingActor->_talkPan - 127 : 0;
+				if (_vm->_game.id == GID_CMI) {
+					// Adjust audio mix for The Curse of Monkey Island
+					if (track->volGroupId == IMUSE_VOLGRP_MUSIC) {
+						effVol -= track->gainReduction / 1000;
+						if (effVol < 0) // In case a music crossfading happens during gain reduction...
+							effVol = 0;
+						effVol = int(round(effVol * 1.9)); // Adjust default music mix for COMI
+					} else if (track->volGroupId == IMUSE_VOLGRP_VOICE) {
+						// Just in case the speakingActor is not being set...
+						// This allows for a fallback to pan = 64 (center) and volume = 127 (full)
+						if (track->speakingActor != nullptr) {
+							effVol = track->speakingActor->_talkVolume;
+							// Even though we fixed this in IMuseDigital::setVolume(),
+							// some sounds might be started without even calling that function
+							if (effVol > 127)
+								effVol /= 2;
+							effVol = int(round(effVol * 1.04));
+							effPan = (track->speakingActor->_talkPan != 64) ? 2 * track->speakingActor->_talkPan - 127 : 0;
+						}
 					}
+				} else if (_vm->_game.id == GID_FT) {
+					// Adjust audio mix for Full Throttle
+					// (this affects music and sfx only, speech volume mix
+					// is changed accordingly in IMuseDigital::startSound()
+					// since that's the only handle we have for speech)
+					if (track->volGroupId == IMUSE_VOLGRP_MUSIC) {
+						// Gain reduction
+						effVol -= track->gainReduction / 1000;
+						if (effVol < 0) // In case a music crossfading happens during gain reduction...
+							effVol = 0;
+						effVol = int(round(effVol * 1.5));
+					} else {
+						effVol = int(round(effVol * 1.1));
+					}					
 				}
 				_mixer->setChannelVolume(track->mixChanHandle, effVol);
 				_mixer->setChannelBalance(track->mixChanHandle, effPan);
@@ -575,7 +595,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {
 				debug(5, "SwToNeReg(trackId:%d) - trigger %s reached", track->trackId, _triggerParams.marker);
 				debug(5, "SwToNeReg(trackId:%d) - exit current region %d", track->trackId, track->curRegion);
 				debug(5, "SwToNeReg(trackId:%d) - call handleComiFadeOut(delay:%d)", track->trackId, _triggerParams.fadeOutDelay);
-				handleComiFadeOut(track, _triggerParams.fadeOutDelay);
+				handleFadeOut(track, _triggerParams.fadeOutDelay);
 				track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion);
 				track->regionOffset = 0;
 				debug(5, "SwToNeReg(trackId:%d)-sound(%d) select region %d, curHookId: %d", track->trackId, track->soundId, track->curRegion, track->curHookId);
diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h
index 9f255f882a..29be9e901c 100644
--- a/engines/scumm/imuse_digi/dimuse.h
+++ b/engines/scumm/imuse_digi/dimuse.h
@@ -118,7 +118,7 @@ private:
 	void setTrigger(TriggerParams *trigger);
 	void setHookIdForMusic(int hookId);
 	Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
-	Track *handleComiFadeOut(Track *track, int fadeDelay);
+	Track *handleFadeOut(Track *track, int fadeDelay);
 	int transformVolumeLinearToEqualPow(int volume, int mode);
 	int transformVolumeEqualPowToLinear(int volume, int mode);
 	
diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp
index e571fffa69..3869d087d3 100644
--- a/engines/scumm/imuse_digi/dimuse_track.cpp
+++ b/engines/scumm/imuse_digi/dimuse_track.cpp
@@ -84,6 +84,39 @@ int IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
 	Common::StackLock lock(_mutex, "IMuseDigital::startSound()");
 	debug(5, "IMuseDigital::startSound(%d) - begin func", soundId);
 
+	bool forceFadeIn = false;
+	if (_vm->_game.id == GID_FT && volGroupId == IMUSE_VOLGRP_MUSIC) {
+		// First of all we check if there's another track playing the target soundId
+		int alreadyPlayingTrackId = -1;
+		for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+			if (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC && _track[l]->used) {
+				forceFadeIn = true;
+				if (_track[l]->soundId == soundId) {
+					alreadyPlayingTrackId = l;
+					break;
+				}
+			}
+		}
+		// If the current music state corresponds to the same soundId 
+		// we're trying to play, we just adjust its volume to the new one.
+		// Otherwise... just flush the old track and start the new one
+		if (alreadyPlayingTrackId != -1) {
+			if (getSoundIdByName(_ftStateMusicTable[_curMusicState].audioName) == soundId) {
+				Track *alreadyPlayingTrack = _track[alreadyPlayingTrackId];
+				alreadyPlayingTrack->volFadeDelay = 60;
+				alreadyPlayingTrack->volFadeDest = volume * 1000;
+				alreadyPlayingTrack->volFadeStep = (alreadyPlayingTrack->volFadeDest - alreadyPlayingTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * alreadyPlayingTrack->volFadeDelay);
+				alreadyPlayingTrack->volFadeUsed = true;
+				alreadyPlayingTrack->toBeRemoved = false;
+				return alreadyPlayingTrackId;
+			} else {
+				flushTrack(_track[alreadyPlayingTrackId]);
+			}
+		}
+	} else if (_vm->_game.id == GID_CMI) {
+		forceFadeIn = true;
+	}
+
 	int l = allocSlot(priority);
 	if (l == -1) {
 		warning("IMuseDigital::startSound() Can't start sound - no free slots");
@@ -106,7 +139,12 @@ int IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
 	track->soundType = soundType;
 	track->trackId = l;
 
-	if (_vm->_game.id == GID_CMI) {
+	if (_vm->_game.id == GID_FT) {
+		// Tweak the default gain reduction to about 2 dB
+		track->gainRedFadeDest = 127 * 180;
+	} else if (_vm->_game.id == GID_CMI) {
+		// Tweak the default gain reduction to about 4 dB
+		track->gainRedFadeDest = 127 * 290;
 		if (track->soundId / 1000 == 1) { // State
 			for (l = 0; _comiStateMusicTable[l].soundId != -1; l++) {
 				if ((_comiStateMusicTable[l].soundId == track->soundId)) {
@@ -129,7 +167,11 @@ int IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
 	track->souStreamUsed = (input != 0);
 
 	if (track->souStreamUsed) {
-		_mixer->playStream(track->getType(), &track->mixChanHandle, input, -1, track->getVol(), track->getPan());
+		int effVol = track->getVol();
+		if (_vm->_game.id == GID_FT) {
+			effVol = int(round(effVol * 1.3));
+		}
+		_mixer->playStream(track->getType(), &track->mixChanHandle, input, -1, effVol, track->getPan());
 	} else {
 		strcpy(track->soundName, soundName);
 		track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, -1);
@@ -198,7 +240,7 @@ int IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
 				track->regionOffset -= track->regionOffset >= (track->feedSize / _callbackFps) ? (track->feedSize / _callbackFps) : 0;
 			}
 		}
-		if (_vm->_game.id == GID_CMI && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+		if (_vm->_game.id != GID_DIG && (track->volGroupId == IMUSE_VOLGRP_MUSIC) && forceFadeIn) {
 			// Fade in the new track
 			track->vol = 0;
 			track->volFadeDelay = fadeDelay;
@@ -341,7 +383,7 @@ void IMuseDigital::fadeOutMusicAndStartNew(int fadeDelay, const char *filename,
 			if (_vm->_game.id == GID_CMI) {
 				track->volFadeDelay = fadeDelay;
 				startMusicWithOtherPos(filename, soundId, 0, 127, track);
-				handleComiFadeOut(track, fadeDelay);
+				handleFadeOut(track, fadeDelay);
 			} else {
 				startMusicWithOtherPos(filename, soundId, 0, 127, track);
 				cloneToFadeOutTrack(track, fadeDelay);
@@ -360,8 +402,8 @@ void IMuseDigital::fadeOutMusic(int fadeDelay) {
 		Track *track = _track[l];
 		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
 			debug(5, "IMuseDigital::fadeOutMusic(fade:%d, sound:%d)", fadeDelay, track->soundId);
-			if (_vm->_game.id == GID_CMI) {
-				handleComiFadeOut(track, fadeDelay);
+			if (_vm->_game.id == GID_CMI || _vm->_game.id == GID_FT) {
+				handleFadeOut(track, fadeDelay);
 			} else {
 				cloneToFadeOutTrack(track, fadeDelay);
 				flushTrack(track);
@@ -393,7 +435,7 @@ void IMuseDigital::setTrigger(TriggerParams *trigger) {
 	_triggerUsed = true;
 }
 
-Track *IMuseDigital::handleComiFadeOut(Track *track, int fadeDelay) {
+Track *IMuseDigital::handleFadeOut(Track *track, int fadeDelay) {
 	track->volFadeDelay = fadeDelay != 0 ? fadeDelay : 60;
 	track->volFadeDest = 0;
 	track->volFadeStep = (track->volFadeDest - track->vol) * 60 * (1000 / _callbackFps) / (1000 * track->volFadeDelay);
@@ -480,6 +522,9 @@ int IMuseDigital::transformVolumeLinearToEqualPow(int volume, int mode) {
 		case 5:  // Logarithmic 3
 			eqPowValue = 1 + 0.7 * log10(mappedValue);
 			break;
+		case 6:  // Quadratic
+			eqPowValue = mappedValue * mappedValue;
+			break;
 		default: // Fallback to linear
 			eqPowValue = mappedValue;
 			break;
@@ -522,6 +567,9 @@ int IMuseDigital::transformVolumeEqualPowToLinear(int volume, int mode) {
 		case 5:  // Logarithmic 3
 			linearValue = 0.0372759 * pow(M_E, 3.28941 * mappedValue);
 			break;
+		case 6:  // Quadratic
+			linearValue = sqrt(mappedValue);
+			break;
 		default: // Fallback to linear
 			linearValue = mappedValue;
 			break;
diff --git a/engines/scumm/imuse_digi/dimuse_track.h b/engines/scumm/imuse_digi/dimuse_track.h
index 5b8f10af17..5d65fd969f 100644
--- a/engines/scumm/imuse_digi/dimuse_track.h
+++ b/engines/scumm/imuse_digi/dimuse_track.h
@@ -92,7 +92,7 @@ struct Track {
 		volFadeDelay = 0;
 		volFadeUsed = false;
 		gainReduction = 0;
-		gainRedFadeDest = 127 * 290; // About 4 dB of gain reduction
+		gainRedFadeDest = 0;
 		gainRedFadeUsed = false;
 		alreadyCrossfading = false;
 		loopShiftType = 0; 




More information about the Scummvm-git-logs mailing list