[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