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.
This commit is contained in:
Randy Heit 2015-04-22 20:28:09 -05:00
parent 7ee1853403
commit a7ff9478a7
2 changed files with 11 additions and 9 deletions

View file

@ -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);

View file

@ -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);
}
}
}