diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e9d1263bc9..146c77a682 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ May 30, 2008 +- Fixed: Deactivating the game no longer allows reverb effects to continue + playing while the sound is paused. - Fixed: S_StartNamedSound() looked for SECF_SILENT in MoreFlags instead of Flags. - Fixed: DSBarInfo::updateState() sprung leaks and didn't allocate enough diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index fbea4f864c..78d4aee4fe 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -621,6 +621,7 @@ bool FMODSoundRenderer::Init() PrevEnvironment = DefaultEnvironments[0]; DSPClockLo = 0; DSPClockHi = 0; + ChannelGroupTargetUnit = NULL; Printf("I_InitSound: Initializing FMOD\n"); @@ -928,6 +929,29 @@ bool FMODSoundRenderer::Init() } LastWaterLP = snd_waterlp; + // Find the FMOD Channel Group Target Unit. To completely eliminate sound + // while the program is deactivated, we can deactivate this DSP unit, and + // all audio processing will cease. This is not directly exposed by the + // API but can be easily located by getting the master channel group and + // tracing its single output, since it is known to hook up directly to the + // Channel Group Target Unit. (See FMOD Profiler for proof.) + FMOD::ChannelGroup *master_group; + result = Sys->getMasterChannelGroup(&master_group); + if (result == FMOD_OK) + { + FMOD::DSP *master_head; + + result = master_group->getDSPHead(&master_head); + if (result == FMOD_OK) + { + result = master_head->getOutput(0, &ChannelGroupTargetUnit, NULL); + if (result != FMOD_OK) + { + ChannelGroupTargetUnit = NULL; + } + } + } + result = SPC_CreateCodec(Sys); if (result != FMOD_OK) { @@ -1584,6 +1608,24 @@ void FMODSoundRenderer::SetSfxPaused(bool paused) } } +//========================================================================== +// +// FMODSoundRenderer :: SetInactive +// +// This is similar to SetSfxPaused but will *pause* everything, including +// the global reverb effect. This is meant to be used only when the +// game is deactivated, not for general sound pausing. +// +//========================================================================== + +void FMODSoundRenderer::SetInactive(bool inactive) +{ + if (ChannelGroupTargetUnit != NULL) + { + ChannelGroupTargetUnit->setActive(!inactive); + } +} + //========================================================================== // // FMODSoundRenderer :: UpdateSoundParams3D diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 370f893ed2..0231efd3d1 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -34,6 +34,8 @@ public: // Pauses or resumes all sound effect channels. void SetSfxPaused (bool paused); + void SetInactive (bool inactive); + // Updates the position of a sound channel. void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]); @@ -87,6 +89,7 @@ private: FMOD::ChannelGroup *MusicGroup; FMOD::DSP *WaterLP, *WaterReverb; FMOD::DSPConnection *SfxConnection; + FMOD::DSP *ChannelGroupTargetUnit; float LastWaterLP; // Just for snd_status display diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 910c90a482..2aa312ff84 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -98,6 +98,9 @@ public: // Pauses or resumes all sound effect channels. virtual void SetSfxPaused (bool paused) = 0; + // Pauses or resumes *every* channel, including environmental reverb. + virtual void SetInactive(bool inactive) = 0; + // Updates the volume, separation, and pitch of a sound channel. virtual void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]) = 0; diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 5903e36cfa..cd03fb1b14 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -1529,7 +1529,10 @@ static void SetSoundPaused (int state) { if (paused <= 0) { - S_ResumeSound (); + if (GSnd != NULL) + { + GSnd->SetInactive(false); + } if (!netgame #ifdef _DEBUG && !demoplayback @@ -1544,7 +1547,10 @@ static void SetSoundPaused (int state) { if (paused == 0) { - S_PauseSound (false); + if (GSnd != NULL) + { + GSnd->SetInactive(true); + } if (!netgame #ifdef _DEBUG && !demoplayback