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.
This commit is contained in:
Chris Robinson 2020-01-29 10:49:25 -08:00 committed by Christoph Oelckers
parent c095872b0a
commit e88b1039a3
2 changed files with 13 additions and 86 deletions

View file

@ -185,7 +185,7 @@ class OpenALSoundStream : public SoundStream
if(Renderer->FreeSfx.Size() == 0) if(Renderer->FreeSfx.Size() == 0)
{ {
FSoundChan *lowest = Renderer->FindLowestChannel(); FSoundChan *lowest = Renderer->FindLowestChannel();
if(lowest) Renderer->ForceStopChannel(lowest); if(lowest) Renderer->StopChannel(lowest);
if(Renderer->FreeSfx.Size() == 0) if(Renderer->FreeSfx.Size() == 0)
return false; return false;
@ -667,14 +667,6 @@ OpenALSoundRenderer::OpenALSoundRenderer()
return; 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; ALCint numMono=0, numStereo=0;
alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &numMono); alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &numMono);
alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &numStereo); alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &numStereo);
@ -1212,7 +1204,7 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
if((ALuint)bufID == buffer) if((ALuint)bufID == buffer)
{ {
FSoundChan *next = schan->NextChan; FSoundChan *next = schan->NextChan;
ForceStopChannel(schan); StopChannel(schan);
schan = next; schan = next;
continue; continue;
} }
@ -1220,20 +1212,6 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
schan = schan->NextChan; 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<ALuint>(bufID) == buffer)
{
FreeSource(iter->first);
iter = FadingSources.erase(iter);
}
else
++iter;
}
alDeleteBuffers(1, &buffer); alDeleteBuffers(1, &buffer);
getALError(); getALError();
} }
@ -1257,7 +1235,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
if(FreeSfx.Size() == 0) if(FreeSfx.Size() == 0)
{ {
FSoundChan *lowest = FindLowestChannel(); FSoundChan *lowest = FindLowestChannel();
if(lowest) ForceStopChannel(lowest); if(lowest) StopChannel(lowest);
if(FreeSfx.Size() == 0) if(FreeSfx.Size() == 0)
return NULL; return NULL;
@ -1363,7 +1341,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
{ {
if(lowest->Priority < priority || (lowest->Priority == priority && if(lowest->Priority < priority || (lowest->Priority == priority &&
lowest->DistanceSqr > dist_sqr)) lowest->DistanceSqr > dist_sqr))
ForceStopChannel(lowest); StopChannel(lowest);
} }
if(FreeSfx.Size() == 0) if(FreeSfx.Size() == 0)
return NULL; return NULL;
@ -1566,8 +1544,15 @@ void OpenALSoundRenderer::ChannelPitch(FISoundChannel *chan, float pitch)
alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)); 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); alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0); alSourcei(source, AL_BUFFER, 0);
getALError(); getALError();
@ -1583,41 +1568,6 @@ void OpenALSoundRenderer::FreeSource(ALuint source)
FreeSfx.Push(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) unsigned int OpenALSoundRenderer::GetPosition(FISoundChannel *chan)
{ {
@ -1884,23 +1834,6 @@ void OpenALSoundRenderer::UpdateSounds()
{ {
alProcessUpdatesSOFT(); 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<std::chrono::milliseconds>(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) if(ALC.EXT_disconnect)
{ {
ALCint connected = ALC_TRUE; ALCint connected = ALC_TRUE;
@ -2049,7 +1982,7 @@ void OpenALSoundRenderer::PurgeStoppedSources()
{ {
if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel))
{ {
ForceStopChannel(schan); StopChannel(schan);
break; break;
} }
schan = schan->NextChan; schan = schan->NextChan;

View file

@ -245,10 +245,8 @@ private:
void RemoveStream(OpenALSoundStream *stream); void RemoveStream(OpenALSoundStream *stream);
void LoadReverb(const ReverbContainer *env); void LoadReverb(const ReverbContainer *env);
void FreeSource(ALuint source);
void PurgeStoppedSources(); void PurgeStoppedSources();
static FSoundChan *FindLowestChannel(); static FSoundChan *FindLowestChannel();
void ForceStopChannel(FISoundChannel *chan);
std::thread StreamThread; std::thread StreamThread;
std::mutex StreamLock; std::mutex StreamLock;
@ -269,10 +267,6 @@ private:
TArray<ALuint> ReverbSfx; TArray<ALuint> ReverbSfx;
TArray<ALuint> SfxGroup; TArray<ALuint> SfxGroup;
int UpdateTimeMS;
using SourceTimeMap = std::unordered_map<ALuint,int64_t>;
SourceTimeMap FadingSources;
const ReverbContainer *PrevEnvironment; const ReverbContainer *PrevEnvironment;
typedef TMap<uint16_t,ALuint> EffectMap; typedef TMap<uint16_t,ALuint> EffectMap;