From 5eb95bbc43dfdf487e45706392b8869a059036c6 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Sun, 1 Feb 2026 22:49:17 +0100 Subject: [PATCH 1/2] refactor(audio): Generalize mute/unmute --- Core/GameEngine/Include/Common/GameAudio.h | 17 ++++++++++++--- .../Source/Common/Audio/GameAudio.cpp | 21 ++++++++++++++----- Generals/Code/Main/WinMain.cpp | 4 ++-- GeneralsMD/Code/Main/WinMain.cpp | 4 ++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Core/GameEngine/Include/Common/GameAudio.h b/Core/GameEngine/Include/Common/GameAudio.h index afa29245bb8..1eb2effe17e 100644 --- a/Core/GameEngine/Include/Common/GameAudio.h +++ b/Core/GameEngine/Include/Common/GameAudio.h @@ -131,6 +131,17 @@ enum class AudioManager : public SubsystemInterface { public: + typedef UnsignedInt MuteAudioReasonInt; + + enum MuteAudioReason + { + MuteAudioReason_WindowFocus, + + MuteAudioReason_Count + }; + + static const char *const MuteAudioReasonNames[]; + AudioManager(); virtual ~AudioManager(); #if defined(RTS_DEBUG) @@ -149,9 +160,8 @@ class AudioManager : public SubsystemInterface virtual void resumeAudio( AudioAffect which ) = 0; virtual void pauseAmbient( Bool shouldPause ) = 0; - // for focus issues - virtual void loseFocus( void ); - virtual void regainFocus( void ); + void muteAudio( MuteAudioReason reason ); + void unmuteAudio( MuteAudioReason reason ); // control for AudioEventsRTS virtual AudioHandle addAudioEvent( const AudioEventRTS *eventToAdd ); ///< Add an audio event (event must be declared in an INI file) @@ -361,6 +371,7 @@ class AudioManager : public SubsystemInterface NUM_VOLUME_TYPES }; Real *m_savedValues; + MuteAudioReasonInt m_muteReasonBits; // Group of 8 Bool m_speechOn : 1; diff --git a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp index 6f9e83de8f6..f673e3a0eb9 100644 --- a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp @@ -139,6 +139,10 @@ static const FieldParse audioSettingsFieldParseTable[] = // Singleton TheAudio ///////////////////////////////////////////////////////////////////////////// AudioManager *TheAudio = nullptr; +const char *const AudioManager::MuteAudioReasonNames[] = +{ + "MuteAudioReason_WindowFocus", +}; // AudioManager Device Independent functions ////////////////////////////////////////////////////// AudioManager::AudioManager() : @@ -152,6 +156,8 @@ AudioManager::AudioManager() : m_hardwareAccel(FALSE), m_musicPlayingFromCD(FALSE) { + static_assert(ARRAY_SIZE(AudioManager::MuteAudioReasonNames) == MuteAudioReason_Count, "Incorrect array size"); + m_adjustedVolumes.clear(); m_audioRequests.clear(); m_listenerPosition.zero(); @@ -171,6 +177,7 @@ AudioManager::AudioManager() : m_miscAudio = NEW MiscAudio; m_silentAudioEvent = NEW AudioEventRTS; m_savedValues = nullptr; + m_muteReasonBits = 0; m_disallowSpeech = FALSE; } @@ -1103,12 +1110,14 @@ void AudioManager::releaseAudioEventRTS( AudioEventRTS *&eventToRelease ) } //------------------------------------------------------------------------------------------------- -void AudioManager::loseFocus( void ) +void AudioManager::muteAudio( MuteAudioReason reason ) { + m_muteReasonBits |= 1u << reason; + if (m_savedValues) return; - // In this case, make all the audio go silent. + // Make all the audio go silent. m_savedValues = NEW Real[NUM_VOLUME_TYPES]; m_savedValues[VOLUME_TYPE_MUSIC] = m_systemMusicVolume; m_savedValues[VOLUME_TYPE_SOUND] = m_systemSoundVolume; @@ -1120,12 +1129,14 @@ void AudioManager::loseFocus( void ) } //------------------------------------------------------------------------------------------------- -void AudioManager::regainFocus( void ) +void AudioManager::unmuteAudio( MuteAudioReason reason ) { - if (!m_savedValues) + m_muteReasonBits &= ~(1u << reason); + + if (m_muteReasonBits != 0 || !m_savedValues) return; - // We got focus back. Restore the previous audio values. + // Restore the previous audio values. setVolume(m_savedValues[VOLUME_TYPE_MUSIC], (AudioAffect) (AudioAffect_Music | AudioAffect_SystemSetting)); setVolume(m_savedValues[VOLUME_TYPE_SOUND], (AudioAffect) (AudioAffect_Sound | AudioAffect_SystemSetting)); setVolume(m_savedValues[VOLUME_TYPE_SOUND3D], (AudioAffect) (AudioAffect_Sound3D | AudioAffect_SystemSetting)); diff --git a/Generals/Code/Main/WinMain.cpp b/Generals/Code/Main/WinMain.cpp index 528b09dbdf5..0a5eafa787d 100644 --- a/Generals/Code/Main/WinMain.cpp +++ b/Generals/Code/Main/WinMain.cpp @@ -464,12 +464,12 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, if( active == WA_INACTIVE ) { if (TheAudio) - TheAudio->loseFocus(); + TheAudio->muteAudio(AudioManager::MuteAudioReason_WindowFocus); } else { if (TheAudio) - TheAudio->regainFocus(); + TheAudio->unmuteAudio(AudioManager::MuteAudioReason_WindowFocus); // Cursor can only be captured after one of the activation events. if (TheMouse) diff --git a/GeneralsMD/Code/Main/WinMain.cpp b/GeneralsMD/Code/Main/WinMain.cpp index c26688a081b..7868dd0901d 100644 --- a/GeneralsMD/Code/Main/WinMain.cpp +++ b/GeneralsMD/Code/Main/WinMain.cpp @@ -486,12 +486,12 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, if( active == WA_INACTIVE ) { if (TheAudio) - TheAudio->loseFocus(); + TheAudio->muteAudio(AudioManager::MuteAudioReason_WindowFocus); } else { if (TheAudio) - TheAudio->regainFocus(); + TheAudio->unmuteAudio(AudioManager::MuteAudioReason_WindowFocus); // Cursor can only be captured after one of the activation events. if (TheMouse) From 724ea718bce3556acc4549b602f1bebeed669380 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:12:26 +0100 Subject: [PATCH 2/2] Apply review feedback --- Core/GameEngine/Include/Common/GameAudio.h | 2 +- Core/GameEngine/Source/Common/Audio/GameAudio.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/GameEngine/Include/Common/GameAudio.h b/Core/GameEngine/Include/Common/GameAudio.h index 1eb2effe17e..74f6c7120c0 100644 --- a/Core/GameEngine/Include/Common/GameAudio.h +++ b/Core/GameEngine/Include/Common/GameAudio.h @@ -133,7 +133,7 @@ class AudioManager : public SubsystemInterface public: typedef UnsignedInt MuteAudioReasonInt; - enum MuteAudioReason + enum MuteAudioReason CPP_11(: UnsignedInt) { MuteAudioReason_WindowFocus, diff --git a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp index f673e3a0eb9..740d7e48ed3 100644 --- a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp @@ -1114,7 +1114,10 @@ void AudioManager::muteAudio( MuteAudioReason reason ) { m_muteReasonBits |= 1u << reason; - if (m_savedValues) + DEBUG_LOG(("AudioManager::muteAudio(%s): m_muteReason=%u muted=%d", + MuteAudioReasonNames[reason], m_muteReasonBits, (int)(m_muteReasonBits != 0))); + + if (m_muteReasonBits == 0 || m_savedValues) return; // Make all the audio go silent. @@ -1133,6 +1136,9 @@ void AudioManager::unmuteAudio( MuteAudioReason reason ) { m_muteReasonBits &= ~(1u << reason); + DEBUG_LOG(("AudioManager::unmuteAudio(%s): m_muteReason=%u muted=%d", + MuteAudioReasonNames[reason], m_muteReasonBits, (int)(m_muteReasonBits != 0))); + if (m_muteReasonBits != 0 || !m_savedValues) return;