diff --git a/source/core/actorlist.cpp b/source/core/actorlist.cpp index ef81ea9a4..1234c3591 100644 --- a/source/core/actorlist.cpp +++ b/source/core/actorlist.cpp @@ -35,6 +35,7 @@ #include "build.h" #include "coreactor.h" #include "gamefuncs.h" +#include "raze_sound.h" // Doubly linked ring list of Actors @@ -367,6 +368,21 @@ DCoreActor* InsertActor(PClass* type, sectortype* sector, int stat, bool tail) void DCoreActor::OnDestroy() { + FVector3 pos = GetSoundPos(&spr.pos); + soundEngine->RelinkSound(SOURCE_Actor, this, nullptr, &pos); + + // also scan all other sounds if they have this actor as source. If so, null the source and stop looped sounds. + soundEngine->EnumerateChannels([=](FSoundChan* chan) + { + if (chan->Source == this) + { + if (chan->ChanFlags & CHANF_LOOP) soundEngine->StopChannel(chan); + else chan->Source = nullptr; + } + return 0; + }); + + if(link_stat == INT_MAX) return; int stat = link_stat; diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 22bc3c876..173ef140e 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -216,50 +216,61 @@ void S_SerializeSounds(FSerializer& arc) { FSoundChan* chan; -GSnd->Sync(true); + GSnd->Sync(true); -if (arc.isWriting()) -{ - // Count channels and accumulate them so we can store them in - // reverse order. That way, they will be in the same order when - // reloaded later as they are now. - TArray chans = soundEngine->AllActiveChannels(); - - if (chans.Size() > 0 && arc.BeginArray("sounds")) + if (arc.isWriting()) { - for (unsigned int i = chans.Size(); i-- != 0; ) - { - // Replace start time with sample position. - uint64_t start = chans[i]->StartTime; - chans[i]->StartTime = GSnd ? GSnd->GetPosition(chans[i]) : 0; - arc(nullptr, *chans[i]); - chans[i]->StartTime = start; - } - arc.EndArray(); - } -} -else -{ - unsigned int count; + // Count channels and accumulate them so we can store them in + // reverse order. That way, they will be in the same order when + // reloaded later as they are now. + TArray chans = soundEngine->AllActiveChannels(); - soundEngine->StopAllChannels(); - if (arc.BeginArray("sounds")) - { - count = arc.ArraySize(); - for (unsigned int i = 0; i < count; ++i) + if (chans.Size() > 0 && arc.BeginArray("sounds")) { - chan = (FSoundChan*)soundEngine->GetChannel(nullptr); - arc(nullptr, *chan); - // Sounds always start out evicted when restored from a save. - chan->ChanFlags |= CHANF_EVICTED | CHANF_ABSTIME; + for (unsigned int i = chans.Size(); i-- != 0; ) + { + // Replace start time with sample position. + uint64_t start = chans[i]->StartTime; + chans[i]->StartTime = GSnd ? GSnd->GetPosition(chans[i]) : 0; + arc(nullptr, *chans[i]); + chans[i]->StartTime = start; + } + arc.EndArray(); } - arc.EndArray(); } - // Add a small delay so that eviction only runs once the game is up and runnnig. - soundEngine->SetRestartTime(I_GetTime() + 2); -} -GSnd->Sync(false); -GSnd->UpdateSounds(); + else + { + unsigned int count; + + soundEngine->StopAllChannels(); + if (arc.BeginArray("sounds")) + { + count = arc.ArraySize(); + for (unsigned int i = 0; i < count; ++i) + { + chan = (FSoundChan*)soundEngine->GetChannel(nullptr); + arc(nullptr, *chan); + // Sounds always start out evicted when restored from a save. + chan->ChanFlags |= CHANF_EVICTED | CHANF_ABSTIME; + } + arc.EndArray(); + } + // Add a small delay so that eviction only runs once the game is up and runnnig. + soundEngine->SetRestartTime(I_GetTime() + 2); + } + // Check if there's actor sounds without an actor. This can happen if a savegame is badly timed with a freshly destroyed actor. + soundEngine->EnumerateChannels([](FSoundChan* chan) + { + auto eng = static_cast(soundEngine); + if (eng->SourceIsActor(chan) && chan->Source == nullptr) + { + eng->StopChannel(chan); + } + return 0; + }); + + GSnd->Sync(false); + GSnd->UpdateSounds(); } //========================================================================== diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index 82077f9a3..750c7cc38 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -50,10 +50,6 @@ DBloodActor* InsertSprite(sectortype* pSector, int nStat) int DeleteSprite(DBloodActor* actor) { - auto sp = &actor->s(); - FVector3 pos = GetSoundPos(&actor->s().pos); - soundEngine->RelinkSound(SOURCE_Actor, actor, nullptr, &pos); - #ifdef NOONE_EXTENSIONS for (auto& ctrl : gPlayerCtrl) if (ctrl.qavScene.initiator == actor) ctrl.qavScene.initiator = nullptr; #endif diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 786ad4949..437f67537 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -76,8 +76,7 @@ void deletesprite(DDukeActor *const actor) { if (actor->s->picnum == MUSICANDSFX && actor->temp_data[0] == 1) S_StopSound(actor->s->lotag, actor); - else - S_RelinkActorSound(actor, nullptr); + actor->Destroy(); } diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index 2f63b5266..76ad01173 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -553,12 +553,6 @@ int S_PlayActorSound(int soundNum, DDukeActor* actor, int channel, EChanFlags fl S_PlaySound3D(soundNum, actor, &actor->s->pos, channel, flags)); } -void S_RelinkActorSound(DDukeActor* from, DDukeActor* to) -{ - FVector3 pos = GetSoundPos(&from->s->pos); - soundEngine->RelinkSound(SOURCE_Actor, from, to, &pos); -} - void S_StopSound(int sndNum, DDukeActor* actor, int channel) { sndNum = GetReplacementSound(sndNum); diff --git a/source/games/duke/src/sounds.h b/source/games/duke/src/sounds.h index c0c894cf1..51fa1cecf 100644 --- a/source/games/duke/src/sounds.h +++ b/source/games/duke/src/sounds.h @@ -42,7 +42,6 @@ void S_WorldTourMappingsForOldSounds(); int S_PlaySound(int num, int channel = CHAN_AUTO, EChanFlags flags = 0, float vol =0.8f); int S_PlaySound3D(int num, DDukeActor* spriteNum, const vec3_t* pos, int channel = CHAN_AUTO, EChanFlags flags = 0); int S_PlayActorSound(int soundNum, DDukeActor* spriteNum, int channel = CHAN_AUTO, EChanFlags flags = 0); -void S_RelinkActorSound(DDukeActor* from, DDukeActor* to); void S_MenuSound(void); void S_StopSound(int sndNum, DDukeActor* spr = nullptr, int flags = -1); diff --git a/source/games/exhumed/src/exhumed.cpp b/source/games/exhumed/src/exhumed.cpp index 2c57b15b7..71ec704a4 100644 --- a/source/games/exhumed/src/exhumed.cpp +++ b/source/games/exhumed/src/exhumed.cpp @@ -532,9 +532,6 @@ void DeleteActor(DExhumedActor* actor) return; } - FVector3 pos = GetSoundPos(&actor->s().pos); - soundEngine->RelinkSound(SOURCE_Actor, &actor->s(), nullptr, &pos); - if (actor == bestTarget) { bestTarget = nullptr; } diff --git a/source/games/sw/src/sprite.cpp b/source/games/sw/src/sprite.cpp index b1b803736..d17d91ad7 100644 --- a/source/games/sw/src/sprite.cpp +++ b/source/games/sw/src/sprite.cpp @@ -765,9 +765,6 @@ void KillActor(DSWActor* actor) actor->clearUser(); } - FVector3 pos = GetSoundPos(&actor->s().pos); - soundEngine->RelinkSound(SOURCE_Actor, &actor->s(), nullptr, &pos); - // shred your garbage sp->clear(); actor->Destroy();