123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AudioSystem.h>
- #include <AudioProxy.h>
- #include <SoundCVars.h>
- #include <AudioSystem_Traits_Platform.h>
- #include <AzCore/PlatformDef.h>
- #include <AzCore/Debug/Profiler.h>
- #include <AzCore/std/bind/bind.h>
- #include <AzCore/StringFunc/StringFunc.h>
- namespace Audio
- {
- extern CAudioLogger g_audioLogger;
- static constexpr const char AudioControlsBasePath[]{ "libs/gameaudio/" };
- // Save off the threadId of the "Main Thread" that was used to connect EBuses.
- AZStd::thread_id g_mainThreadId;
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // CAudioThread
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- CAudioThread::~CAudioThread()
- {
- Deactivate();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioThread::Run()
- {
- AZ_Assert(m_audioSystem, "Audio Thread has no Audio System to run!\n");
- m_running = true;
- while (m_running)
- {
- m_audioSystem->InternalUpdate();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioThread::Activate(CAudioSystem* const audioSystem)
- {
- m_audioSystem = audioSystem;
- AZStd::thread_desc threadDesc;
- threadDesc.m_name = "Audio Thread";
- threadDesc.m_cpuId = AZ_TRAIT_AUDIOSYSTEM_AUDIO_THREAD_AFFINITY;
- auto threadFunc = AZStd::bind(&CAudioThread::Run, this);
- m_thread = AZStd::thread(threadDesc, threadFunc);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioThread::Deactivate()
- {
- if (m_running)
- {
- m_running = false;
- m_thread.join();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // CAudioSystem
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- CAudioSystem::CAudioSystem()
- : m_bSystemInitialized(false)
- {
- g_mainThreadId = AZStd::this_thread::get_id();
- m_apAudioProxies.reserve(Audio::CVars::s_AudioObjectPoolSize);
- m_apAudioProxiesToBeFreed.reserve(16);
- m_controlsPath.assign(Audio::AudioControlsBasePath);
- AudioSystemRequestBus::Handler::BusConnect();
- AudioSystemThreadSafeRequestBus::Handler::BusConnect();
- AudioSystemInternalRequestBus::Handler::BusConnect();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- CAudioSystem::~CAudioSystem()
- {
- AudioSystemRequestBus::Handler::BusDisconnect();
- AudioSystemThreadSafeRequestBus::Handler::BusDisconnect();
- AudioSystemInternalRequestBus::Handler::BusDisconnect();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::PushRequest(const SAudioRequest& audioRequestData)
- {
- CAudioRequestInternal request(audioRequestData);
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::PushRequest - called from non-Main thread!");
- AZ_Assert(0 == (request.nFlags & eARF_THREAD_SAFE_PUSH), "AudioSystem::PushRequest - called with flag THREAD_SAFE_PUSH!");
- AZ_Assert(0 == (request.nFlags & eARF_EXECUTE_BLOCKING), "AudioSystem::PushRequest - called with flag EXECUTE_BLOCKING!");
- AudioSystemInternalRequestBus::QueueBroadcast(&AudioSystemInternalRequestBus::Events::ProcessRequestByPriority, request);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::PushRequestBlocking(const SAudioRequest& audioRequestData)
- {
- // Main Thread!
- AZ_PROFILE_FUNCTION(Audio);
- CAudioRequestInternal request(audioRequestData);
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::PushRequestBlocking - called from non-Main thread!");
- AZ_Assert(0 != (request.nFlags & eARF_EXECUTE_BLOCKING), "AudioSystem::PushRequestBlocking - called without EXECUTE_BLOCKING flag!");
- AZ_Assert(0 == (request.nFlags & eARF_THREAD_SAFE_PUSH), "AudioSystem::PushRequestBlocking - called with THREAD_SAFE_PUSH flag!");
- ProcessRequestBlocking(request);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::PushRequestThreadSafe(const SAudioRequest& audioRequestData)
- {
- CAudioRequestInternal request(audioRequestData);
- AZ_Assert(0 != (request.nFlags & eARF_THREAD_SAFE_PUSH), "AudioSystem::PushRequestThreadSafe - called without THREAD_SAFE_PUSH flag!");
- AZ_Assert(0 == (request.nFlags & eARF_EXECUTE_BLOCKING), "AudioSystem::PushRequestThreadSafe - called with flag EXECUTE_BLOCKING!");
- AudioSystemThreadSafeRequestBus::QueueFunction(AZStd::bind(&CAudioSystem::ProcessRequestThreadSafe, this, request));
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::AddRequestListener(
- AudioRequestCallbackType func,
- void* const callbackOwner,
- const EAudioRequestType requestType,
- const TATLEnumFlagsType specificRequestMask)
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::AddRequestListener - called from a non-Main thread!");
- if (func)
- {
- SAudioEventListener listener;
- listener.m_callbackOwner = callbackOwner;
- listener.m_fnOnEvent = func;
- listener.m_requestType = requestType;
- listener.m_specificRequestMask = specificRequestMask;
- m_oATL.AddRequestListener(listener);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::RemoveRequestListener(AudioRequestCallbackType func, void* const callbackOwner)
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::RemoveRequestListener - called from a non-Main thread!");
- SAudioEventListener listener;
- listener.m_callbackOwner = callbackOwner;
- listener.m_fnOnEvent = func;
- m_oATL.RemoveRequestListener(listener);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ExternalUpdate()
- {
- // Main Thread!
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ExternalUpdate - called from non-Main thread!");
- // Notify callbacks on the pending callbacks queue...
- // These are requests that were completed then queued for callback processing to happen here.
- ExecuteRequestCompletionCallbacks(m_pendingCallbacksQueue, m_pendingCallbacksMutex);
- // Notify callbacks from the "thread safe" queue...
- ExecuteRequestCompletionCallbacks(m_threadSafeCallbacksQueue, m_threadSafeCallbacksMutex, true);
- // Other notifications to be sent out...
- AudioTriggerNotificationBus::ExecuteQueuedEvents();
- // Free any Audio Proxies that are queued up for deletion...
- for (auto audioProxy : m_apAudioProxiesToBeFreed)
- {
- azdestroy(audioProxy, Audio::AudioSystemAllocator);
- }
- m_apAudioProxiesToBeFreed.clear();
- #if !defined(AUDIO_RELEASE)
- DrawAudioDebugData();
- #endif // !AUDIO_RELEASE
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::InternalUpdate()
- {
- // Audio Thread!
- AZ_PROFILE_FUNCTION(Audio);
- auto startUpdateTime = AZStd::chrono::system_clock::now(); // stamp the start time
- bool handledBlockingRequests = false;
- {
- AZStd::lock_guard<AZStd::mutex> lock(m_blockingRequestsMutex);
- handledBlockingRequests = ProcessRequests(m_blockingRequestsQueue);
- }
- if (!handledBlockingRequests)
- {
- // Call the ProcessRequestByPriority events queued up...
- AudioSystemInternalRequestBus::ExecuteQueuedEvents();
- }
- // Call the ProcessRequestThreadSafe events queued up...
- AudioSystemThreadSafeRequestBus::ExecuteQueuedEvents();
- m_oATL.Update();
- #if !defined(AUDIO_RELEASE)
- #if defined(PROVIDE_GETNAME_SUPPORT)
- {
- AZ_PROFILE_SCOPE(Audio, "Sync Debug Name Changes");
- AZStd::lock_guard<AZStd::mutex> lock(m_debugNameStoreMutex);
- m_debugNameStore.SyncChanges(m_oATL.GetDebugStore());
- }
- #endif // PROVIDE_GETNAME_SUPPORT
- #endif // !AUDIO_RELEASE
- if (!handledBlockingRequests)
- {
- auto endUpdateTime = AZStd::chrono::system_clock::now(); // stamp the end time
- auto elapsedUpdateTime = AZStd::chrono::duration_cast<duration_ms>(endUpdateTime - startUpdateTime);
- if (elapsedUpdateTime < m_targetUpdatePeriod)
- {
- AZ_PROFILE_SCOPE(Audio, "Wait Remaining Time in Update Period");
- m_processingEvent.try_acquire_for(m_targetUpdatePeriod - elapsedUpdateTime);
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- bool CAudioSystem::Initialize()
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::Initialize - called from a non-Main thread!");
- if (!m_bSystemInitialized)
- {
- m_audioSystemThread.Deactivate();
- m_oATL.Initialize();
- m_audioSystemThread.Activate(this);
- for (AZ::u64 i = 0; i < Audio::CVars::s_AudioObjectPoolSize; ++i)
- {
- auto audioProxy = azcreate(CAudioProxy, (), Audio::AudioSystemAllocator, "AudioProxy");
- m_apAudioProxies.push_back(audioProxy);
- }
- m_bSystemInitialized = true;
- }
- return m_bSystemInitialized;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::Release()
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::Release - called from a non-Main thread!");
- for (auto audioProxy : m_apAudioProxies)
- {
- azdestroy(audioProxy, Audio::AudioSystemAllocator);
- }
- for (auto audioProxy : m_apAudioProxiesToBeFreed)
- {
- azdestroy(audioProxy, Audio::AudioSystemAllocator);
- }
- m_apAudioProxies.clear();
- m_apAudioProxiesToBeFreed.clear();
- // Release the audio implementation...
- SAudioRequest request;
- SAudioManagerRequestData<eAMRT_RELEASE_AUDIO_IMPL> requestData;
- request.nFlags = (eARF_PRIORITY_HIGH | eARF_EXECUTE_BLOCKING);
- request.pData = &requestData;
- PushRequestBlocking(request);
- m_audioSystemThread.Deactivate();
- m_oATL.ShutDown();
- m_bSystemInitialized = false;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioControlID CAudioSystem::GetAudioTriggerID(const char* const sAudioTriggerName) const
- {
- return m_oATL.GetAudioTriggerID(sAudioTriggerName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioControlID CAudioSystem::GetAudioRtpcID(const char* const sAudioRtpcName) const
- {
- return m_oATL.GetAudioRtpcID(sAudioRtpcName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioControlID CAudioSystem::GetAudioSwitchID(const char* const sAudioStateName) const
- {
- return m_oATL.GetAudioSwitchID(sAudioStateName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioSwitchStateID CAudioSystem::GetAudioSwitchStateID(const TAudioControlID nSwitchID, const char* const sAudioSwitchStateName) const
- {
- return m_oATL.GetAudioSwitchStateID(nSwitchID, sAudioSwitchStateName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioPreloadRequestID CAudioSystem::GetAudioPreloadRequestID(const char* const sAudioPreloadRequestName) const
- {
- return m_oATL.GetAudioPreloadRequestID(sAudioPreloadRequestName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioEnvironmentID CAudioSystem::GetAudioEnvironmentID(const char* const sAudioEnvironmentName) const
- {
- return m_oATL.GetAudioEnvironmentID(sAudioEnvironmentName);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- bool CAudioSystem::ReserveAudioListenerID(TAudioObjectID& rAudioObjectID)
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ReserveAudioListenerID - called from a non-Main thread!");
- return m_oATL.ReserveAudioListenerID(rAudioObjectID);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- bool CAudioSystem::ReleaseAudioListenerID(TAudioObjectID const nAudioObjectID)
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::ReleaseAudioListenerID - called from a non-Main thread!");
- return m_oATL.ReleaseAudioListenerID(nAudioObjectID);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- bool CAudioSystem::SetAudioListenerOverrideID(const TAudioObjectID nAudioObjectID)
- {
- return m_oATL.SetAudioListenerOverrideID(nAudioObjectID);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::GetInfo([[maybe_unused]] SAudioSystemInfo& rAudioSystemInfo)
- {
- //TODO:
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- const char* CAudioSystem::GetControlsPath() const
- {
- return m_controlsPath.c_str();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::UpdateControlsPath()
- {
- AZStd::string controlsPath{ Audio::AudioControlsBasePath };
- const AZStd::string& subPath = m_oATL.GetControlsImplSubPath();
- if (!subPath.empty())
- {
- controlsPath.append(subPath);
- }
- if (AZ::StringFunc::RelativePath::Normalize(controlsPath))
- {
- m_controlsPath = controlsPath;
- }
- else
- {
- g_audioLogger.Log(
- eALT_ERROR, "AudioSystem::UpdateControlsPath - failed to normalize the controls path '%s'!", controlsPath.c_str());
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::RefreshAudioSystem([[maybe_unused]] const char* const levelName)
- {
- #if !defined(AUDIO_RELEASE)
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::RefreshAudioSystem - called from a non-Main thread!");
- // Get the controls path and a level-specific preload Id first.
- // This will be passed with the request so that it doesn't have to lookup this data
- // and punch the AudioSystemRequestBus from the Audio Thread.
- const char* audioControlsPath = GetControlsPath();
- Audio::TAudioPreloadRequestID levelPreloadId = INVALID_AUDIO_PRELOAD_REQUEST_ID;
- if (levelName && levelName[0] != '\0')
- {
- levelPreloadId = GetAudioPreloadRequestID(levelName);
- }
- Audio::SAudioManagerRequestData<Audio::eAMRT_REFRESH_AUDIO_SYSTEM> requestData(audioControlsPath, levelName, levelPreloadId);
- Audio::SAudioRequest request;
- request.nFlags = (Audio::eARF_PRIORITY_HIGH | Audio::eARF_EXECUTE_BLOCKING);
- request.pData = &requestData;
- PushRequestBlocking(request);
- #endif // !AUDIO_RELEASE
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- IAudioProxy* CAudioSystem::GetFreeAudioProxy()
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetFreeAudioProxy - called from a non-Main thread!");
- CAudioProxy* audioProxy = nullptr;
- if (!m_apAudioProxies.empty())
- {
- audioProxy = m_apAudioProxies.back();
- m_apAudioProxies.pop_back();
- }
- else
- {
- audioProxy = azcreate(CAudioProxy, (), Audio::AudioSystemAllocator, "AudioProxyEx");
- #if !defined(AUDIO_RELEASE)
- if (!audioProxy)
- {
- g_audioLogger.Log(eALT_ASSERT, "AudioSystem::GetFreeAudioProxy - failed to create new AudioProxy instance!");
- }
- #endif // !AUDIO_RELEASE
- }
- return static_cast<IAudioProxy*>(audioProxy);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::FreeAudioProxy(IAudioProxy* const audioProxyI)
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::FreeAudioProxy - called from a non-Main thread!");
- auto const audioProxy = static_cast<CAudioProxy*>(audioProxyI);
- if (AZStd::find(m_apAudioProxiesToBeFreed.begin(), m_apAudioProxiesToBeFreed.end(), audioProxy) != m_apAudioProxiesToBeFreed.end() || AZStd::find(m_apAudioProxies.begin(), m_apAudioProxies.end(), audioProxy) != m_apAudioProxies.end())
- {
- AZ_Warning("AudioSystem", false, "Attempting to free an already freed audio proxy");
- return;
- }
- if (m_apAudioProxies.size() < Audio::CVars::s_AudioObjectPoolSize)
- {
- m_apAudioProxies.push_back(audioProxy);
- }
- else
- {
- m_apAudioProxiesToBeFreed.push_back(audioProxy);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- TAudioSourceId CAudioSystem::CreateAudioSource(const SAudioInputConfig& sourceConfig)
- {
- return m_oATL.CreateAudioSource(sourceConfig);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::DestroyAudioSource(TAudioSourceId sourceId)
- {
- m_oATL.DestroyAudioSource(sourceId);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- const char* CAudioSystem::GetAudioControlName([[maybe_unused]] const EAudioControlType controlType, [[maybe_unused]] const TATLIDType atlID) const
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetAudioControlName - called from non-Main thread!");
- const char* sResult = nullptr;
- #if !defined(AUDIO_RELEASE)
- #if defined(PROVIDE_GETNAME_SUPPORT)
- AZStd::lock_guard<AZStd::mutex> lock(m_debugNameStoreMutex);
- switch (controlType)
- {
- case eACT_AUDIO_OBJECT:
- {
- sResult = m_debugNameStore.LookupAudioObjectName(atlID);
- break;
- }
- case eACT_TRIGGER:
- {
- sResult = m_debugNameStore.LookupAudioTriggerName(atlID);
- break;
- }
- case eACT_RTPC:
- {
- sResult = m_debugNameStore.LookupAudioRtpcName(atlID);
- break;
- }
- case eACT_SWITCH:
- {
- sResult = m_debugNameStore.LookupAudioSwitchName(atlID);
- break;
- }
- case eACT_PRELOAD:
- {
- sResult = m_debugNameStore.LookupAudioPreloadRequestName(atlID);
- break;
- }
- case eACT_ENVIRONMENT:
- {
- sResult = m_debugNameStore.LookupAudioEnvironmentName(atlID);
- break;
- }
- case eACT_SWITCH_STATE: // not handled here, use GetAudioSwitchStateName!
- case eACT_NONE:
- default: // fall-through!
- {
- g_audioLogger.Log(eALT_WARNING, "AudioSystem::GetAudioControlName - called with invalid EAudioControlType!");
- break;
- }
- }
- #endif // PROVIDE_GETNAME_SUPPORT
- #endif // !AUDIO_RELEASE
- return sResult;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- const char* CAudioSystem::GetAudioSwitchStateName([[maybe_unused]] const TAudioControlID switchID, [[maybe_unused]] const TAudioSwitchStateID stateID) const
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::GetAudioSwitchStateName - called from non-Main thread!");
- const char* sResult = nullptr;
- #if !defined(AUDIO_RELEASE)
- #if defined(PROVIDE_GETNAME_SUPPORT)
- AZStd::lock_guard<AZStd::mutex> lock(m_debugNameStoreMutex);
- sResult = m_debugNameStore.LookupAudioSwitchStateName(switchID, stateID);
- #endif // PROVIDE_GETNAME_SUPPORT
- #endif // !AUDIO_RELEASE
- return sResult;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ExtractCompletedRequests(TAudioRequests& requestQueue, TAudioRequests& extractedCallbacks)
- {
- auto iter(requestQueue.begin());
- auto iterEnd(requestQueue.end());
- while (iter != iterEnd)
- {
- const CAudioRequestInternal& refRequest = (*iter);
- if (refRequest.IsComplete())
- {
- // the request has completed, eligible for notification callback.
- // move the request to the extraction queue.
- extractedCallbacks.push_back(refRequest);
- iter = requestQueue.erase(iter);
- iterEnd = requestQueue.end();
- continue;
- }
- ++iter;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ExecuteRequestCompletionCallbacks(TAudioRequests& requestQueue, AZStd::mutex& requestQueueMutex, bool tryLock)
- {
- TAudioRequests extractedCallbacks;
- if (tryLock)
- {
- if (requestQueueMutex.try_lock())
- {
- ExtractCompletedRequests(requestQueue, extractedCallbacks);
- requestQueueMutex.unlock();
- }
- }
- else
- {
- AZStd::lock_guard<AZStd::mutex> lock(requestQueueMutex);
- ExtractCompletedRequests(requestQueue, extractedCallbacks);
- }
- // Notify listeners
- for (const auto& callback : extractedCallbacks)
- {
- m_oATL.NotifyListener(callback);
- }
- extractedCallbacks.clear();
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ProcessRequestBlocking(CAudioRequestInternal& request)
- {
- AZ_PROFILE_FUNCTION(Audio);
- if (m_oATL.CanProcessRequests())
- {
- {
- AZStd::lock_guard<AZStd::mutex> lock(m_blockingRequestsMutex);
- m_blockingRequestsQueue.push_back(request);
- }
- m_processingEvent.release();
- m_mainEvent.acquire();
- ExecuteRequestCompletionCallbacks(m_blockingRequestsQueue, m_blockingRequestsMutex);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ProcessRequestThreadSafe(CAudioRequestInternal request)
- {
- // Audio Thread!
- AZ_PROFILE_SCOPE(Audio, "Process Thread-Safe Request");
- if (m_oATL.CanProcessRequests())
- {
- if (request.eStatus == eARS_NONE)
- {
- request.eStatus = eARS_PENDING;
- m_oATL.ProcessRequest(request);
- }
- AZ_Assert(request.eStatus != eARS_PENDING, "AudioSystem::ProcessRequestThreadSafe - ATL finished processing request, but request is still in pending state!");
- if (request.eStatus != eARS_PENDING)
- {
- // push the request onto a callbacks queue for main thread to process later...
- AZStd::lock_guard<AZStd::mutex> lock(m_threadSafeCallbacksMutex);
- m_threadSafeCallbacksQueue.push_back(request);
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- void CAudioSystem::ProcessRequestByPriority(CAudioRequestInternal request)
- {
- // Todo: This should handle request priority, use request priority as bus Address and process in priority order.
- AZ_PROFILE_SCOPE(Audio, "Process Normal Request");
- AZ_Assert(g_mainThreadId != AZStd::this_thread::get_id(), "AudioSystem::ProcessRequestByPriority - called from Main thread!");
- if (m_oATL.CanProcessRequests())
- {
- if (request.eStatus == eARS_NONE)
- {
- request.eStatus = eARS_PENDING;
- m_oATL.ProcessRequest(request);
- }
- AZ_Assert(request.eStatus != eARS_PENDING, "AudioSystem::ProcessRequestByPriority - ATL finished processing request, but request is still in pending state!");
- if (request.eStatus != eARS_PENDING)
- {
- // push the request onto a callbacks queue for main thread to process later...
- AZStd::lock_guard<AZStd::mutex> lock(m_pendingCallbacksMutex);
- m_pendingCallbacksQueue.push_back(request);
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- bool CAudioSystem::ProcessRequests(TAudioRequests& requestQueue)
- {
- bool success = false;
- for (auto& request : requestQueue)
- {
- if (!(request.nInternalInfoFlags & eARIF_WAITING_FOR_REMOVAL))
- {
- AZ_PROFILE_SCOPE(Audio, "Process Blocking Request");
- if (request.eStatus == eARS_NONE)
- {
- request.eStatus = eARS_PENDING;
- m_oATL.ProcessRequest(request);
- success = true;
- }
- if (request.eStatus != eARS_PENDING)
- {
- if (request.nFlags & eARF_EXECUTE_BLOCKING)
- {
- request.nInternalInfoFlags |= eARIF_WAITING_FOR_REMOVAL;
- m_mainEvent.release();
- }
- }
- else
- {
- g_audioLogger.Log(eALT_ERROR, "AudioSystem::ProcessRequests - request still in Pending state after being processed by ATL!");
- }
- }
- }
- return success;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #if !defined(AUDIO_RELEASE)
- void CAudioSystem::DrawAudioDebugData()
- {
- AZ_Assert(g_mainThreadId == AZStd::this_thread::get_id(), "AudioSystem::DrawAudioDebugData - called from non-Main thread!");
- if (CVars::s_debugDrawOptions.GetRawFlags() != 0)
- {
- SAudioRequest oRequest;
- oRequest.nFlags = (eARF_PRIORITY_HIGH | eARF_EXECUTE_BLOCKING);
- SAudioManagerRequestData<eAMRT_DRAW_DEBUG_INFO> oRequestData;
- oRequest.pData = &oRequestData;
- PushRequestBlocking(oRequest);
- }
- }
- #endif // !AUDIO_RELEASE
- } // namespace Audio
|