From 99868d5897c0131e03b948c710f1b69869a9a8b9 Mon Sep 17 00:00:00 2001 From: Alayan <25536748+Alayan-stk-2@users.noreply.github.com> Date: Wed, 8 May 2024 17:21:39 +0200 Subject: [PATCH] Fix #5026 The SFX manager and SFXOpenAL would check if SFXs are enabled before pausing (looping) sound effects, so disabling SFXs in the options would fail to stop looping SFxs. Furthermore, 'OnSoundEnabledBack' would pause all looping SFXs. This commit checks for the pause status of the World (if applicable) to decide if the looping SFXs should be immediately resumed (networking) or not (real pause). Also clean some comments and move some code around. This patch doesn't address sound resuming when going from the pause menu to the options in networked mode, whereas it doesn't in a normal race. This is what caused the bug to trigger in the first place, but it's very minor by itself and the design of the SFX code could have triggered other future issues too. --- src/audio/dummy_sfx.hpp | 2 +- src/audio/sfx_base.hpp | 2 +- src/audio/sfx_manager.cpp | 47 +++++++++++++++++++++------------------ src/audio/sfx_openal.cpp | 10 ++++++--- src/audio/sfx_openal.hpp | 2 +- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/audio/dummy_sfx.hpp b/src/audio/dummy_sfx.hpp index f5d598abb..76aa4c481 100644 --- a/src/audio/dummy_sfx.hpp +++ b/src/audio/dummy_sfx.hpp @@ -64,7 +64,7 @@ public: virtual void setMasterVolume(float gain) OVERRIDE {} virtual void reallySetMasterVolumeNow(float gain) OVERRIDE {} virtual SFXStatus getStatus() OVERRIDE { return SFX_STOPPED; } - virtual void onSoundEnabledBack() OVERRIDE {} + virtual void onSoundEnabledBack(bool resume_later) OVERRIDE {} virtual void setRolloff(float rolloff) OVERRIDE {} virtual SFXBuffer* getBuffer() const OVERRIDE { return NULL; } diff --git a/src/audio/sfx_base.hpp b/src/audio/sfx_base.hpp index 6e18774f1..0f6e984a2 100644 --- a/src/audio/sfx_base.hpp +++ b/src/audio/sfx_base.hpp @@ -80,7 +80,7 @@ public: virtual void reallySetVolume(float gain) = 0; virtual void setMasterVolume(float gain) = 0; virtual void reallySetMasterVolumeNow(float gain) = 0; - virtual void onSoundEnabledBack() = 0; + virtual void onSoundEnabledBack(bool resume_later)= 0; virtual void setRolloff(float rolloff) = 0; virtual SFXBuffer* getBuffer() const = 0; virtual SFXStatus getStatus() = 0; diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index 0d7fbdcb4..0a58eecfb 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -22,6 +22,7 @@ #include "audio/sfx_buffer.hpp" #include "config/user_config.hpp" #include "io/file_manager.hpp" +#include "modes/world.hpp" #include "race/race_manager.hpp" #include "states_screens/state_manager.hpp" #include "utils/stk_process.hpp" @@ -336,7 +337,7 @@ void SFXManager::stopThread() } // stopThread //---------------------------------------------------------------------------- -/** This loops runs in a different threads, and starts sfx to be played. +/** This loops runs in a different thread, and starts playing sfx. * This can sometimes take up to 5 ms, so it needs to be handled in a thread * in order to avoid rendering delays. * \param obj A pointer to the SFX singleton. @@ -513,25 +514,18 @@ void SFXManager::toggleSound(const bool on) reallyResumeAllNow(); m_all_sfx.lock(); const int sfx_amount = (int)m_all_sfx.getData().size(); + bool resume_later = false; + if (World::getWorld() != NULL) + resume_later = (World::getWorld()->getPhase() == World::IN_GAME_MENU_PHASE); for (int n=0; nonSoundEnabledBack(); + // This also pauses sound effects + m_all_sfx.getData()[n]->onSoundEnabledBack(resume_later); } m_all_sfx.unlock(); } else { - // First stop all sfx that are not looped - const int sfx_amount = (int)m_all_sfx.getData().size(); - m_all_sfx.lock(); - for (int i=0; iisLooped()) - { - m_all_sfx.getData()[i]->reallyStopNow(); - } - } - m_all_sfx.unlock(); pauseAll(); } } // toggleSound @@ -898,20 +892,29 @@ void SFXManager::deleteSFX(SFXBase *sfx) } // deleteSFX //---------------------------------------------------------------------------- -/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's - * otherwise not possible to determine which SFX must be resumed (i.e. were - * actually playing at the time pause was called). +/** Request the pausing of all SFXs. Non-looping SFXs are finished, + * since it's otherwise not possible to determine which SFXs must be resumed + * (i.e. were actually playing at the time pause was called). */ void SFXManager::pauseAll() { - if (!sfxAllowed()) return; + // First stop all sfx that are not looped + const int sfx_amount = (int)m_all_sfx.getData().size(); + m_all_sfx.lock(); + for (int i=0; iisLooped()) + { + m_all_sfx.getData()[i]->reallyStopNow(); + } + } + m_all_sfx.unlock(); + queue(SFX_PAUSE_ALL); } // pauseAll //---------------------------------------------------------------------------- -/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's - * otherwise not possible to determine which SFX must be resumed (i.e. were - * actually playing at the time pause was called. +/** Actually pauses the SFXs. */ void SFXManager::reallyPauseAllNow() { @@ -922,7 +925,7 @@ void SFXManager::reallyPauseAllNow() (*i)->reallyPauseNow(); } // for i in m_all_sfx m_all_sfx.unlock(); -} // pauseAll +} // reallyPauseAllNow //---------------------------------------------------------------------------- /** Resumes all paused SFXs. If sound is disabled, does nothing. @@ -950,7 +953,7 @@ void SFXManager::reallyResumeAllNow() (*i)->reallyResumeNow(); } // for i in m_all_sfx m_all_sfx.unlock(); -} // resumeAll +} // reallyResumeAllNow //----------------------------------------------------------------------------- /** Returns whether or not an openal error has occurred. If so, an error diff --git a/src/audio/sfx_openal.cpp b/src/audio/sfx_openal.cpp index d7a8a3497..fa3163077 100644 --- a/src/audio/sfx_openal.cpp +++ b/src/audio/sfx_openal.cpp @@ -262,10 +262,11 @@ void SFXOpenAL::reallySetLoop(bool status) //----------------------------------------------------------------------------- /** Queues a stop for this effect to the sound manager. + * Stopping MUST be allowed when SFX are disabled */ void SFXOpenAL::stop() { - if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return; + if (m_status == SFX_UNKNOWN) return; SFXManager::get()->queue(SFXManager::SFX_STOP, this); } // stop @@ -295,12 +296,13 @@ void SFXOpenAL::pause() //----------------------------------------------------------------------------- /** Pauses a SFX that's currently played. Nothing happens it the effect is * currently not being played. + * Pausing MUST be allowed when SFX are disabled */ void SFXOpenAL::reallyPauseNow() { // Need to be tested again here, since this function can be called // from pauseAll, and we have to make sure to only pause playing sfx. - if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return; + if (m_status != SFX_PLAYING) return; m_status = SFX_PAUSED; alSourcePause(m_sound_source); SFXManager::checkError("pausing"); @@ -513,7 +515,7 @@ void SFXOpenAL::deleteSFX() //----------------------------------------------------------------------------- -void SFXOpenAL::onSoundEnabledBack() +void SFXOpenAL::onSoundEnabledBack(bool resume_later) { if (m_loop) { @@ -525,6 +527,8 @@ void SFXOpenAL::onSoundEnabledBack() pause(); alSourcef(m_sound_source, AL_GAIN, (m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain); + if (!resume_later) + play(); } } } // onSoundEnabledBack diff --git a/src/audio/sfx_openal.hpp b/src/audio/sfx_openal.hpp index a6634d93c..6d4fd713a 100644 --- a/src/audio/sfx_openal.hpp +++ b/src/audio/sfx_openal.hpp @@ -103,7 +103,7 @@ public: virtual void reallySetVolume(float volume) OVERRIDE; virtual void setMasterVolume(float volume) OVERRIDE; virtual void reallySetMasterVolumeNow(float volue) OVERRIDE; - virtual void onSoundEnabledBack() OVERRIDE; + virtual void onSoundEnabledBack(bool resume_later) OVERRIDE; virtual void setRolloff(float rolloff) OVERRIDE; // ------------------------------------------------------------------------ /** Returns if this sfx is looped or not. */