From dae4b61b5b654f47da642a0df6da5961936aa6ab Mon Sep 17 00:00:00 2001 From: Iliyas Jorio Date: Sat, 21 Jan 2023 13:22:39 +0100 Subject: [PATCH] Remove sources from the mixer before deleting them --- src/SoundMixer/ChannelImpl.cpp | 7 ++++++- src/SoundMixer/cmixer.cpp | 15 ++++++++++++++- src/SoundMixer/cmixer.h | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/SoundMixer/ChannelImpl.cpp b/src/SoundMixer/ChannelImpl.cpp index caf4d35..933d97e 100644 --- a/src/SoundMixer/ChannelImpl.cpp +++ b/src/SoundMixer/ChannelImpl.cpp @@ -31,7 +31,7 @@ ChannelImpl::ChannelImpl(SndChannelPtr _macChannel, bool transferMacChannelOwner ChannelImpl::~ChannelImpl() { - Unlink(); + Unlink(); // Unlink chan from list of managed chans macChannel->channelImpl = nullptr; @@ -39,6 +39,11 @@ ChannelImpl::~ChannelImpl() { delete macChannel; } + + // Make sure we've stopped mixing the source before we allow its destructor + // to be called. Otherwise, the WavSource's buffer may be freed as it is still + // being processed! + source.RemoveFromMixer(); } void ChannelImpl::Recycle() diff --git a/src/SoundMixer/cmixer.cpp b/src/SoundMixer/cmixer.cpp index 86f2575..cc711cf 100644 --- a/src/SoundMixer/cmixer.cpp +++ b/src/SoundMixer/cmixer.cpp @@ -255,16 +255,29 @@ void Source::Init(int theSampleRate, int theLength) Stop(); } -Source::~Source() +void Source::RemoveFromMixer() { gMixer.Lock(); if (active) { gMixer.sources.remove(this); + active = false; } gMixer.Unlock(); } +Source::~Source() +{ + if (active) + { + // You MUST call RemoveFromMixer before destroying a source. If you get here, your program is incorrect. + fprintf(stderr, "Source wasn't removed from mixer prior to destruction!\n"); +#if _DEBUG + std::terminate(); +#endif + } +} + void Source::Rewind() { RewindImplementation(); diff --git a/src/SoundMixer/cmixer.h b/src/SoundMixer/cmixer.h index 6e88467..cad21d6 100644 --- a/src/SoundMixer/cmixer.h +++ b/src/SoundMixer/cmixer.h @@ -77,6 +77,8 @@ namespace cmixer public: virtual ~Source(); + void RemoveFromMixer(); + void Clear(); void Rewind();