From d719ef8d0329c5132f6e46536dd77838ee7d9559 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 20 Apr 2023 10:56:57 +0200 Subject: [PATCH] Fix crash when reimporting audio clip while it's being played --- .../Viewport/Previews/AudioClipPreview.cs | 16 +++++++++---- Source/Engine/Audio/AudioClip.cpp | 23 +++++++++++++++---- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Source/Editor/Viewport/Previews/AudioClipPreview.cs b/Source/Editor/Viewport/Previews/AudioClipPreview.cs index ef3d7fe75..446cef657 100644 --- a/Source/Editor/Viewport/Previews/AudioClipPreview.cs +++ b/Source/Editor/Viewport/Previews/AudioClipPreview.cs @@ -126,12 +126,18 @@ namespace FlaxEditor.Viewport.Previews { lock (_locker) { - // Release any cached data - _pcmData = null; + if (_asset != null) + { + // Release any cached data + _pcmData = null; - // Invalidate any in-flight data download to reject cached data due to refresh - if (_pcmSequence != 0) - _pcmSequence++; + // Invalidate any in-flight data download to reject cached data due to refresh + if (_pcmSequence != 0) + _pcmSequence++; + + // Use async task to gather PCM data (engine loads it from the asset) + Task.Run(DownloadData); + } } } diff --git a/Source/Engine/Audio/AudioClip.cpp b/Source/Engine/Audio/AudioClip.cpp index 34cf60441..68f2e3471 100644 --- a/Source/Engine/Audio/AudioClip.cpp +++ b/Source/Engine/Audio/AudioClip.cpp @@ -200,6 +200,8 @@ bool AudioClip::ExtractData(Array& resultData, AudioDataInfo& resultDataIn ASSERT(!IsVirtual()); if (WaitForLoaded()) return true; + ScopeLock lock(Locker); + auto storageLock = Storage->LockSafe(); // Allocate memory ASSERT(_totalChunksSize > 0); @@ -245,6 +247,7 @@ bool AudioClip::ExtractDataRaw(Array& resultData, AudioDataInfo& resultDat { if (WaitForLoaded()) return true; + ScopeLock lock(Locker); switch (Format()) { case AudioFormat::Raw: @@ -461,20 +464,32 @@ Asset::LoadResult AudioClip::load() void AudioClip::unload(bool isReloading) { + bool hasAnyBuffer = false; + for (const AUDIO_BUFFER_ID_TYPE bufferId : Buffers) + hasAnyBuffer |= bufferId != AUDIO_BUFFER_ID_INVALID; + + // Stop any audio sources that are using this clip right now + // TODO: find better way to collect audio sources using audio clip and impl it for AudioStreamingHandler too + for (int32 sourceIndex = 0; sourceIndex < Audio::Sources.Count(); sourceIndex++) + { + const auto src = Audio::Sources[sourceIndex]; + if (src->Clip == this) + src->Stop(); + } + StopStreaming(); StreamingQueue.Clear(); - if (Buffers.HasItems()) + if (hasAnyBuffer) { - for (int32 i = 0; i < Buffers.Count(); i++) + for (AUDIO_BUFFER_ID_TYPE bufferId : Buffers) { - auto bufferId = Buffers[i]; if (bufferId != AUDIO_BUFFER_ID_INVALID) { AudioBackend::Buffer::Delete(bufferId); } } - Buffers.Clear(); } + Buffers.Clear(); _totalChunks = 0; Platform::MemoryClear(&AudioHeader, sizeof(AudioHeader)); }