From e88b1039a3c592ee23a24dad07b31a05f922ee9f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 29 Jan 2020 10:49:25 -0800 Subject: [PATCH] Stop sources immediately when the sound is forced to stop The reason for the previous delay was to allow OpenAL Soft to fade the sound to silence and avoid a sudden amplitude change, which can cause a "click" or "pop" noise. However, with OpenAL Soft 1.20, this is a built-in feature of the mixer so the extra complexity is unnecessary. --- src/sound/backend/oalsound.cpp | 93 +++++----------------------------- src/sound/backend/oalsound.h | 6 --- 2 files changed, 13 insertions(+), 86 deletions(-) diff --git a/src/sound/backend/oalsound.cpp b/src/sound/backend/oalsound.cpp index 515dce882..63b193067 100644 --- a/src/sound/backend/oalsound.cpp +++ b/src/sound/backend/oalsound.cpp @@ -185,7 +185,7 @@ class OpenALSoundStream : public SoundStream if(Renderer->FreeSfx.Size() == 0) { FSoundChan *lowest = Renderer->FindLowestChannel(); - if(lowest) Renderer->ForceStopChannel(lowest); + if(lowest) Renderer->StopChannel(lowest); if(Renderer->FreeSfx.Size() == 0) return false; @@ -667,14 +667,6 @@ OpenALSoundRenderer::OpenALSoundRenderer() return; } - ALCint refresh=0; - alcGetIntegerv(Device, ALC_REFRESH, 1, &refresh); - if(refresh > 0) - { - // Round up instead of down - UpdateTimeMS = (1000+refresh-1) / refresh; - } - ALCint numMono=0, numStereo=0; alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &numMono); alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &numStereo); @@ -1212,7 +1204,7 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) if((ALuint)bufID == buffer) { FSoundChan *next = schan->NextChan; - ForceStopChannel(schan); + StopChannel(schan); schan = next; continue; } @@ -1220,20 +1212,6 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) schan = schan->NextChan; } - // Make sure to kill any currently fading sounds too - for(auto iter = FadingSources.begin();iter != FadingSources.end();) - { - ALint bufID = 0; - alGetSourcei(iter->first, AL_BUFFER, &bufID); - if(static_cast(bufID) == buffer) - { - FreeSource(iter->first); - iter = FadingSources.erase(iter); - } - else - ++iter; - } - alDeleteBuffers(1, &buffer); getALError(); } @@ -1257,7 +1235,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int if(FreeSfx.Size() == 0) { FSoundChan *lowest = FindLowestChannel(); - if(lowest) ForceStopChannel(lowest); + if(lowest) StopChannel(lowest); if(FreeSfx.Size() == 0) return NULL; @@ -1363,7 +1341,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener { if(lowest->Priority < priority || (lowest->Priority == priority && lowest->DistanceSqr > dist_sqr)) - ForceStopChannel(lowest); + StopChannel(lowest); } if(FreeSfx.Size() == 0) return NULL; @@ -1566,8 +1544,15 @@ void OpenALSoundRenderer::ChannelPitch(FISoundChannel *chan, float pitch) alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)); } -void OpenALSoundRenderer::FreeSource(ALuint source) +void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) { + if(chan == NULL || chan->SysChannel == NULL) + return; + + ALuint source = GET_PTRID(chan->SysChannel); + // Release first, so it can be properly marked as evicted if it's being killed + soundEngine->ChannelEnded(chan); + alSourceRewind(source); alSourcei(source, AL_BUFFER, 0); getALError(); @@ -1583,41 +1568,6 @@ void OpenALSoundRenderer::FreeSource(ALuint source) FreeSfx.Push(source); } -void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) -{ - if(chan == NULL || chan->SysChannel == NULL) - return; - - ALuint source = GET_PTRID(chan->SysChannel); - // Release first, so it can be properly marked as evicted if it's being killed - soundEngine->ChannelEnded(chan); - - ALint state = AL_INITIAL; - alGetSourcei(source, AL_SOURCE_STATE, &state); - if(state != AL_PLAYING) - FreeSource(source); - else - { - // The sound is being killed while playing, so set its gain to 0 and track it - // as it fades. - alSourcef(source, AL_GAIN, 0.f); - getALError(); - - FadingSources.insert(std::make_pair( - source, std::chrono::steady_clock::now().time_since_epoch().count() - )); - } -} - -void OpenALSoundRenderer::ForceStopChannel(FISoundChannel *chan) -{ - ALuint source = GET_PTRID(chan->SysChannel); - if(!source) return; - - soundEngine->ChannelEnded(chan); - FreeSource(source); -} - unsigned int OpenALSoundRenderer::GetPosition(FISoundChannel *chan) { @@ -1884,23 +1834,6 @@ void OpenALSoundRenderer::UpdateSounds() { alProcessUpdatesSOFT(); - if(!FadingSources.empty()) - { - auto cur_time = std::chrono::steady_clock::now().time_since_epoch(); - for(auto iter = FadingSources.begin();iter != FadingSources.end();) - { - auto time_diff = std::chrono::duration_cast(cur_time - - std::chrono::steady_clock::time_point::duration(iter->second)); - if(time_diff.count() >= UpdateTimeMS) - { - FreeSource(iter->first); - iter = FadingSources.erase(iter); - } - else - ++iter; - } - } - if(ALC.EXT_disconnect) { ALCint connected = ALC_TRUE; @@ -2049,7 +1982,7 @@ void OpenALSoundRenderer::PurgeStoppedSources() { if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) { - ForceStopChannel(schan); + StopChannel(schan); break; } schan = schan->NextChan; diff --git a/src/sound/backend/oalsound.h b/src/sound/backend/oalsound.h index 2179ca0de..efa007689 100644 --- a/src/sound/backend/oalsound.h +++ b/src/sound/backend/oalsound.h @@ -245,10 +245,8 @@ private: void RemoveStream(OpenALSoundStream *stream); void LoadReverb(const ReverbContainer *env); - void FreeSource(ALuint source); void PurgeStoppedSources(); static FSoundChan *FindLowestChannel(); - void ForceStopChannel(FISoundChannel *chan); std::thread StreamThread; std::mutex StreamLock; @@ -269,10 +267,6 @@ private: TArray ReverbSfx; TArray SfxGroup; - int UpdateTimeMS; - using SourceTimeMap = std::unordered_map; - SourceTimeMap FadingSources; - const ReverbContainer *PrevEnvironment; typedef TMap EffectMap;