diff --git a/Source/Engine/Audio/AudioBackend.h b/Source/Engine/Audio/AudioBackend.h index 61d2c223a..ccfea09c3 100644 --- a/Source/Engine/Audio/AudioBackend.h +++ b/Source/Engine/Audio/AudioBackend.h @@ -58,8 +58,8 @@ private: virtual void Source_DequeueProcessedBuffers(AudioSource* source) = 0; // Buffer - virtual void Buffer_Create(uint32& bufferId) = 0; - virtual void Buffer_Delete(uint32& bufferId) = 0; + virtual uint32 Buffer_Create() = 0; + virtual void Buffer_Delete(uint32 bufferId) = 0; virtual void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) = 0; // Base @@ -224,15 +224,14 @@ public: { public: - FORCE_INLINE static void Create(uint32& bufferId) + FORCE_INLINE static uint32 Create() { - Instance->Buffer_Create(bufferId); + return Instance->Buffer_Create(); } - FORCE_INLINE static void Delete(uint32& bufferId) + FORCE_INLINE static void Delete(uint32 bufferId) { - if (Instance) - Instance->Buffer_Delete(bufferId); + Instance->Buffer_Delete(bufferId); } FORCE_INLINE static void Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) diff --git a/Source/Engine/Audio/AudioClip.cpp b/Source/Engine/Audio/AudioClip.cpp index d91eb358c..8750bed03 100644 --- a/Source/Engine/Audio/AudioClip.cpp +++ b/Source/Engine/Audio/AudioClip.cpp @@ -19,7 +19,7 @@ REGISTER_BINARY_ASSET_WITH_UPGRADER(AudioClip, "FlaxEngine.AudioClip", AudioClip bool AudioClip::StreamingTask::Run() { AssetReference ref = _asset.Get(); - if (ref == nullptr) + if (ref == nullptr || AudioBackend::Instance == nullptr) return true; ScopeLock lock(ref->Locker); const auto& queue = ref->StreamingQueue; @@ -34,13 +34,13 @@ bool AudioClip::StreamingTask::Run() uint32& bufferId = clip->Buffers[idx]; if (bufferId == AUDIO_BUFFER_ID_INVALID) { - AudioBackend::Buffer::Create(bufferId); + bufferId = AudioBackend::Buffer::Create(); } else { // Release unused data AudioBackend::Buffer::Delete(bufferId); - bufferId = 0; + bufferId = AUDIO_BUFFER_ID_INVALID; } } @@ -370,9 +370,7 @@ Asset::LoadResult AudioClip::load() return LoadResult::CannotLoadData; // Create single buffer - uint32 bufferId; - AudioBackend::Buffer::Create(bufferId); - Buffers[0] = bufferId; + Buffers[0] = AudioBackend::Buffer::Create(); // Write data to audio buffer if (WriteBuffer(0)) @@ -398,14 +396,12 @@ void AudioClip::unload(bool isReloading) StopStreaming(); StreamingQueue.Clear(); - if (hasAnyBuffer) + if (hasAnyBuffer && AudioBackend::Instance) { for (AUDIO_BUFFER_ID_TYPE bufferId : Buffers) { if (bufferId != AUDIO_BUFFER_ID_INVALID) - { AudioBackend::Buffer::Delete(bufferId); - } } } Buffers.Clear(); diff --git a/Source/Engine/Audio/None/AudioBackendNone.cpp b/Source/Engine/Audio/None/AudioBackendNone.cpp index 42a31b775..a56315bbe 100644 --- a/Source/Engine/Audio/None/AudioBackendNone.cpp +++ b/Source/Engine/Audio/None/AudioBackendNone.cpp @@ -114,12 +114,12 @@ void AudioBackendNone::Source_DequeueProcessedBuffers(AudioSource* source) { } -void AudioBackendNone::Buffer_Create(uint32& bufferId) +uint32 AudioBackendNone::Buffer_Create() { - bufferId = 1; + return 1; } -void AudioBackendNone::Buffer_Delete(uint32& bufferId) +void AudioBackendNone::Buffer_Delete(uint32 bufferId) { } diff --git a/Source/Engine/Audio/None/AudioBackendNone.h b/Source/Engine/Audio/None/AudioBackendNone.h index 1e90b42ac..e3f5134a6 100644 --- a/Source/Engine/Audio/None/AudioBackendNone.h +++ b/Source/Engine/Audio/None/AudioBackendNone.h @@ -40,8 +40,8 @@ public: void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override; void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override; void Source_DequeueProcessedBuffers(AudioSource* source) override; - void Buffer_Create(uint32& bufferId) override; - void Buffer_Delete(uint32& bufferId) override; + uint32 Buffer_Create() override; + void Buffer_Delete(uint32 bufferId) override; void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override; const Char* Base_Name() override; FeatureFlags Base_Features() override; diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp index cc5036e25..84642ac1f 100644 --- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp +++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp @@ -589,13 +589,15 @@ void AudioBackendOAL::Source_DequeueProcessedBuffers(AudioSource* source) } } -void AudioBackendOAL::Buffer_Create(uint32& bufferId) +uint32 AudioBackendOAL::Buffer_Create() { + uint32 bufferId; alGenBuffers(1, &bufferId); ALC_CHECK_ERROR(alGenBuffers); + return bufferId; } -void AudioBackendOAL::Buffer_Delete(uint32& bufferId) +void AudioBackendOAL::Buffer_Delete(uint32 bufferId) { alDeleteBuffers(1, &bufferId); ALC_CHECK_ERROR(alDeleteBuffers); diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.h b/Source/Engine/Audio/OpenAL/AudioBackendOAL.h index 5590de518..daf981e8c 100644 --- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.h +++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.h @@ -40,8 +40,8 @@ public: void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override; void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override; void Source_DequeueProcessedBuffers(AudioSource* source) override; - void Buffer_Create(uint32& bufferId) override; - void Buffer_Delete(uint32& bufferId) override; + uint32 Buffer_Create() override; + void Buffer_Delete(uint32 bufferId) override; void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override; const Char* Base_Name() override; FeatureFlags Base_Features() override; diff --git a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp index bbef7d421..698a6025a 100644 --- a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp +++ b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp @@ -9,6 +9,7 @@ #include "Engine/Audio/Audio.h" #include "Engine/Audio/AudioSource.h" #include "Engine/Audio/AudioListener.h" +#include "Engine/Threading/Threading.h" #if PLATFORM_WINDOWS // Tweak Win ver @@ -206,6 +207,7 @@ namespace XAudio2 UINT32 Channels; bool ForceDirty = true; Listener Listeners[AUDIO_MAX_LISTENERS]; + CriticalSection Locker; Array Sources(32); // TODO: use ChunkedArray for better performance Array Buffers(64); // TODO: use ChunkedArray for better performance or use buffers pool? EngineCallback Callback; @@ -306,7 +308,6 @@ void AudioBackendXAudio2::Listener_OnAdd(AudioListener* listener) void AudioBackendXAudio2::Listener_OnRemove(AudioListener* listener) { - // Free listener XAudio2::Listener* aListener = XAudio2::GetListener(listener); if (aListener) { @@ -346,6 +347,7 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source) if (source->Clip == nullptr || !source->Clip->IsLoaded()) return; auto clip = source->Clip.Get(); + ScopeLock lock(XAudio2::Locker); // Get first free source XAudio2::Source* aSource = nullptr; @@ -419,6 +421,7 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source) void AudioBackendXAudio2::Source_OnRemove(AudioSource* source) { + ScopeLock lock(XAudio2::Locker); source->Cleanup(); } @@ -485,8 +488,10 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source) // Looping is defined during buffer submission so reset source buffer (this is called only for non-streamable sources that ue single buffer) + XAudio2::Locker.Lock(); const uint32 bufferId = source->Clip->Buffers[0]; XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1]; + XAudio2::Locker.Unlock(); const bool isPlaying = source->IsActuallyPlayingSth(); if (isPlaying) @@ -536,6 +541,7 @@ void AudioBackendXAudio2::Source_SpatialSetupChanged(AudioSource* source) void AudioBackendXAudio2::Source_ClipLoaded(AudioSource* source) { + ScopeLock lock(XAudio2::Locker); auto aSource = XAudio2::GetSource(source); if (!aSource) { @@ -546,6 +552,7 @@ void AudioBackendXAudio2::Source_ClipLoaded(AudioSource* source) void AudioBackendXAudio2::Source_Cleanup(AudioSource* source) { + ScopeLock lock(XAudio2::Locker); auto aSource = XAudio2::GetSource(source); if (!aSource) return; @@ -632,8 +639,10 @@ void AudioBackendXAudio2::Source_SetNonStreamingBuffer(AudioSource* source) if (!aSource) return; + XAudio2::Locker.Lock(); const uint32 bufferId = source->Clip->Buffers[0]; XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1]; + XAudio2::Locker.Unlock(); XAUDIO2_BUFFER buffer = { 0 }; buffer.pContext = aBuffer; @@ -695,8 +704,11 @@ void AudioBackendXAudio2::Source_DequeueProcessedBuffers(AudioSource* source) } } -void AudioBackendXAudio2::Buffer_Create(uint32& bufferId) +uint32 AudioBackendXAudio2::Buffer_Create() { + uint32 bufferId; + ScopeLock lock(XAudio2::Locker); + // Get first free buffer slot XAudio2::Buffer* aBuffer = nullptr; for (int32 i = 0; i < XAudio2::Buffers.Count(); i++) @@ -718,10 +730,12 @@ void AudioBackendXAudio2::Buffer_Create(uint32& bufferId) } aBuffer->Data.Resize(0); + return bufferId; } -void AudioBackendXAudio2::Buffer_Delete(uint32& bufferId) +void AudioBackendXAudio2::Buffer_Delete(uint32 bufferId) { + ScopeLock lock(XAudio2::Locker); XAudio2::Buffer*& aBuffer = XAudio2::Buffers[bufferId - 1]; aBuffer->Data.Resize(0); Delete(aBuffer); @@ -730,7 +744,9 @@ void AudioBackendXAudio2::Buffer_Delete(uint32& bufferId) void AudioBackendXAudio2::Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) { + XAudio2::Locker.Lock(); XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1]; + XAudio2::Locker.Unlock(); const uint32 bytesPerSample = info.BitDepth / 8; const int32 samplesLength = info.NumSamples * bytesPerSample; diff --git a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h index 1257cb2df..52df27eff 100644 --- a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h +++ b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h @@ -40,8 +40,8 @@ public: void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override; void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override; void Source_DequeueProcessedBuffers(AudioSource* source) override; - void Buffer_Create(uint32& bufferId) override; - void Buffer_Delete(uint32& bufferId) override; + uint32 Buffer_Create() override; + void Buffer_Delete(uint32 bufferId) override; void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override; const Char* Base_Name() override; FeatureFlags Base_Features() override;