diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index f3cc77a52..e5c4fd3c9 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -178,6 +178,25 @@ void AudioSystem::Shutdown() { worker_thread_->Wait(0, 0, 0, nullptr); worker_thread_.reset(); } + + // Unregister all active clients to shut down their audio drivers before + // the semaphores are destroyed with this AudioSystem. + { + auto global_lock = global_critical_region_.Acquire(); + for (size_t i = 0; i < kMaximumClientCount; ++i) { + if (clients_[i].in_use) { + DestroyDriver(clients_[i].driver); + if (clients_[i].wrapped_callback_arg) { + memory()->SystemHeapFree(clients_[i].wrapped_callback_arg); + } + clients_[i].driver = nullptr; + clients_[i].callback = 0; + clients_[i].callback_arg = 0; + clients_[i].wrapped_callback_arg = 0; + clients_[i].in_use = false; + } + } + } } X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg, diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc index 7b254808b..f9c199224 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc +++ b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc @@ -308,8 +308,13 @@ void XAudio2AudioDriver::Shutdown() { template void XAudio2AudioDriver::ShutdownObjects(Objects& objects) { + // Stop the engine first to ensure no callbacks are in-flight before + // destroying voices and the callback object. + if (objects.audio) { + objects.audio->StopEngine(); + } + if (objects.pcm_voice) { - objects.pcm_voice->Stop(); objects.pcm_voice->DestroyVoice(); objects.pcm_voice = nullptr; } @@ -320,7 +325,6 @@ void XAudio2AudioDriver::ShutdownObjects(Objects& objects) { } if (objects.audio) { - objects.audio->StopEngine(); objects.audio->Release(); objects.audio = nullptr; }