diff --git a/Source/Managers/AudioMan.cpp b/Source/Managers/AudioMan.cpp index a196a49157..36ae07bad7 100644 --- a/Source/Managers/AudioMan.cpp +++ b/Source/Managers/AudioMan.cpp @@ -130,6 +130,9 @@ bool AudioMan::Initialize() { void AudioMan::Destroy() { if (m_AudioEnabled) { StopAll(); + // FMOD loads sounds on a thread of its own, which crashes if the audio system gets released while it's still at it. That's the case when quitting shortly after launching. + // Releasing a sound waits for it to be done loading, and FMOD wants them all released before the audio system anyway. + ContentFile::FreeAllLoadedSounds(); m_AudioSystem->release(); Clear(); } diff --git a/Source/System/ContentFile.cpp b/Source/System/ContentFile.cpp index 3d7b9b4b8f..f57c07b34e 100644 --- a/Source/System/ContentFile.cpp +++ b/Source/System/ContentFile.cpp @@ -60,6 +60,15 @@ void ContentFile::FreeAllLoaded() { } } +void ContentFile::FreeAllLoadedSounds() { + for (const auto& [soundPath, sound]: s_LoadedSamples) { + if (sound) { + sound->release(); + } + } + s_LoadedSamples.clear(); +} + int ContentFile::ReadProperty(const std::string_view& propName, Reader& reader) { StartPropertyList(return Serializable::ReadProperty(propName, reader)); diff --git a/Source/System/ContentFile.h b/Source/System/ContentFile.h index 454511d13b..0b451cb604 100644 --- a/Source/System/ContentFile.h +++ b/Source/System/ContentFile.h @@ -61,6 +61,9 @@ namespace RTE { /// Frees all loaded data used by all ContentFile instances. This should ONLY be done when quitting the app, or after everything else is completely destroyed. static void FreeAllLoaded(); + + /// Releases all the sounds loaded by all ContentFile instances, waiting for the ones FMOD is still loading asynchronously. This has to be done before the audio system gets released. + static void FreeAllLoadedSounds(); #pragma endregion #pragma region Getters and Setters