From a7ff9478a7d45a0734c91f2980223ebba2524ce7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 22 Apr 2015 20:28:09 -0500 Subject: [PATCH] Fixed: S_PrecacheLevel() could create orphan channels - S_PrecacheLevel() must also mark currently playing sounds as used. If we don't, the sound could be unloaded and the underlying channel stopped without triggering a channel callback. That would leave the code in s_sound.cpp thinking the sound is still playing even though it isn't. - Added an invalid channel check to FMODSoundRenderer::StopChannel() so that orphan channels passed to it will be returned at least when S_StopAllChannels() is called. --- src/s_sound.cpp | 13 ++++++------- src/sound/fmodsound.cpp | 7 +++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 5b3d5457b..7b543c4e4 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -383,7 +383,7 @@ void S_Start () { // kill all playing sounds at start of level (trust me - a good idea) S_StopAllChannels(); - + // Check for local sound definitions. Only reload if they differ // from the previous ones. FString LocalSndInfo; @@ -487,6 +487,11 @@ void S_PrecacheLevel () { level.info->PrecacheSounds[i].MarkUsed(); } + // Don't unload sounds that are playing right now. + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + chan->SoundID.MarkUsed(); + } for (i = 1; i < S_sfx.Size(); ++i) { @@ -2083,12 +2088,6 @@ void S_ChannelEnded(FISoundChannel *ichan) evicted = (pos < len); } } - /* - else - { - evicted = false; - } - */ if (!evicted) { S_ReturnChannel(schan); diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 1739556b4..269720c48 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -2050,7 +2050,7 @@ FISoundChannel *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, FISou //========================================================================== // -// FMODSoundRenderer :: StopSound +// FMODSoundRenderer :: StopChannel // //========================================================================== @@ -2058,7 +2058,10 @@ void FMODSoundRenderer::StopChannel(FISoundChannel *chan) { if (chan != NULL && chan->SysChannel != NULL) { - ((FMOD::Channel *)chan->SysChannel)->stop(); + if (((FMOD::Channel *)chan->SysChannel)->stop() == FMOD_ERR_INVALID_HANDLE) + { // The channel handle was invalid; pretend it ended. + S_ChannelEnded(chan); + } } }