From e3393c1beada62354c20316966989352b58f5989 Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Tue, 24 Dec 2024 22:36:31 -0500 Subject: [PATCH] adjust-audio-volume adjustments Make some modifications to the adjust-audio-volume infrastructure: 1. Add an `aav_volume` array for ease of access to all three volume variables. Refactor `snd_adjust_audio_volume()` to use this array to avoid duplicating code. 2. Move `update_looping_sound_volumes()` to be handled in parallel with `audiostream_set_volume_all()`, and for the same reason: avoid setting the sound volume for every looping sound on every frame if the volume has not changed. 3. If the volume is to be adjusted immediately, apply the relevant changes without waiting for `snd_do_frame()` to be called on the next frame. Resolves #6291. 4. Fix some edge cases in `adjust_volume_on_frame()`. --- code/sound/sound.cpp | 90 +++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 52 deletions(-) diff --git a/code/sound/sound.cpp b/code/sound/sound.cpp index cae5f3af439..67a98006a21 100644 --- a/code/sound/sound.cpp +++ b/code/sound/sound.cpp @@ -117,10 +117,13 @@ SCP_list currentlyLoopingSoundInfos; SCP_list currentlyLooping3dSoundInfos; //For the adjust-audio-volume sexp -float aav_voice_volume = 1.0f; float aav_music_volume = 1.0f; +float aav_voice_volume = 1.0f; float aav_effect_volume = 1.0f; +// these must correspond to the order of the AAV_ #defines +static float* aav_volume[] = { &aav_music_volume, &aav_voice_volume, &aav_effect_volume }; + struct aav { float start_volume; float delta; @@ -1548,20 +1551,16 @@ int sound_env_supported() return ds_eax_is_inited(); } +void adjust_volume_on_frame(float* volume_now, aav* data); + // Called once per game frame // - -void adjust_volume_on_frame(float* volume_now, aav* data); -void update_looping_sound_volumes(SCP_list& looping_sounds); void snd_do_frame() { adjust_volume_on_frame(&aav_music_volume, &aav_data[AAV_MUSIC]); adjust_volume_on_frame(&aav_voice_volume, &aav_data[AAV_VOICE]); adjust_volume_on_frame(&aav_effect_volume, &aav_data[AAV_EFFECTS]); - update_looping_sound_volumes(currentlyLoopingSoundInfos); - update_looping_sound_volumes(currentlyLooping3dSoundInfos); - ds_do_frame(); } @@ -1574,40 +1573,25 @@ void update_looping_sound_volumes(SCP_list &looping_sounds) } } -void snd_adjust_audio_volume(int type, float percent, int time) +void snd_adjust_audio_volume(int aav_type, float percent, int delta_time) { - Assert( type >= 0 && type < 3 ); - - if ( type >= 0 && type < 3 ) { - switch (type) { - case AAV_MUSIC: - aav_data[type].start_volume = aav_music_volume; - if (percent < aav_music_volume) - aav_data[type].delta = (aav_music_volume - percent) * -1.0f; - else - aav_data[type].delta = percent - aav_music_volume; - break; - case AAV_VOICE: - aav_data[type].start_volume = aav_voice_volume; - if (percent < aav_voice_volume) - aav_data[type].delta = (aav_voice_volume - percent) * -1.0f; - else - aav_data[type].delta = percent - aav_voice_volume; - break; - case AAV_EFFECTS: - aav_data[type].start_volume = aav_effect_volume; - if (percent < aav_effect_volume) - aav_data[type].delta = (aav_effect_volume - percent) * -1.0f; - else - aav_data[type].delta = percent - aav_effect_volume; - break; - default: - Int3(); - } + Assertion(aav_type >= 0 && aav_type <= 2, "aav_type is out of range!"); + if (aav_type < 0 || aav_type > 2) + return; - aav_data[type].delta_time = time; - aav_data[type].start_time = (f2fl(Missiontime) * 1000); - } + aav_data[aav_type].start_volume = *aav_volume[aav_type]; + if (percent < *aav_volume[aav_type]) + aav_data[aav_type].delta = (*aav_volume[aav_type] - percent) * -1.0f; + else + aav_data[aav_type].delta = percent - *aav_volume[aav_type]; + + aav_data[aav_type].delta_time = delta_time; + aav_data[aav_type].start_time = f2fl(Missiontime) * MILLISECONDS_PER_SECOND; + + + // if the delta_time is 0 [immediate], make the relevant updates without waiting for the next frame's snd_do_frame() + if (delta_time <= 0) + adjust_volume_on_frame(aav_volume[aav_type], &aav_data[aav_type]); } void adjust_volume_on_frame(float* volume_now, aav* data) @@ -1619,29 +1603,31 @@ void adjust_volume_on_frame(float* volume_now, aav* data) if (*volume_now == (data->start_volume + data->delta)) return; - float msMissiontime = (f2fl(Missiontime) * 1000); - - if ( msMissiontime > ( data->start_time + data->delta_time) ) { - *volume_now = data->start_volume + data->delta; - return; - } + float msMissiontime = f2fl(Missiontime) * MILLISECONDS_PER_SECOND; - float done = 0.0f; //How much change do we need? - if (data->delta_time == 0) - done = 1.0f; + //if immediate, or if the time has elapsed, use the target volume + if (data->delta_time <= 0 || msMissiontime >= (data->start_time + data->delta_time)) + *volume_now = data->start_volume + data->delta; else - done =(float) (msMissiontime - data->start_time)/data->delta_time; + { + float done = (msMissiontime - data->start_time) / data->delta_time; - //apply change - *volume_now = data->start_volume + (data->delta * done); - CLAMP(*volume_now, 0.0f, 1.0f); + //apply change + *volume_now = data->start_volume + (data->delta * done); + CLAMP(*volume_now, 0.0f, 1.0f); + } // if setting music volume, trigger volume change in playing tracks // done here in order to avoid setting music volume in every frame regardless if it changed or not if (&aav_music_volume == volume_now) { audiostream_set_volume_all(Master_event_music_volume * aav_music_volume, ASF_EVENTMUSIC); } + // for similar reasons, if setting effects volume, trigger volume change here + else if (&aav_effect_volume == volume_now) { + update_looping_sound_volumes(currentlyLoopingSoundInfos); + update_looping_sound_volumes(currentlyLooping3dSoundInfos); + } } void snd_aav_init()