ATLComponents.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <ATLComponents.h>
  9. #include <AzCore/Console/ILogger.h>
  10. #include <AzCore/Debug/Profiler.h>
  11. #include <AzCore/IO/FileIO.h>
  12. #include <AzCore/std/functional.h>
  13. #include <AzCore/std/string/string_view.h>
  14. #include <AzCore/StringFunc/StringFunc.h>
  15. #include <AzFramework/FileFunc/FileFunc.h>
  16. #include <AzFramework/Physics/PhysicsScene.h>
  17. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  18. #include <AudioFileUtils.h>
  19. #include <ATLCommon.h>
  20. #include <SoundCVars.h>
  21. #include <IAudioSystemImplementation.h>
  22. #include <MathConversion.h>
  23. #if !defined(AUDIO_RELEASE)
  24. // Debug Draw
  25. #include <AzCore/std/string/conversions.h>
  26. #include <AzFramework/Entity/EntityDebugDisplayBus.h>
  27. #endif // !AUDIO_RELEASE
  28. namespace Audio
  29. {
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////
  31. // AudioObjectIDFactory
  32. ///////////////////////////////////////////////////////////////////////////////////////////////////
  33. const TAudioObjectID AudioObjectIDFactory::s_invalidAudioObjectID = INVALID_AUDIO_OBJECT_ID;
  34. const TAudioObjectID AudioObjectIDFactory::s_globalAudioObjectID = GLOBAL_AUDIO_OBJECT_ID;
  35. const TAudioObjectID AudioObjectIDFactory::s_minValidAudioObjectID = (GLOBAL_AUDIO_OBJECT_ID + 1);
  36. const TAudioObjectID AudioObjectIDFactory::s_maxValidAudioObjectID = static_cast<TAudioObjectID>(-256);
  37. // Beyond the max ID value, allow for a range of 255 ID values which will be reserved for the audio middleware.
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////
  39. // static
  40. TAudioObjectID AudioObjectIDFactory::GetNextID()
  41. {
  42. static TAudioObjectID s_nextId = s_minValidAudioObjectID;
  43. return (s_nextId <= s_maxValidAudioObjectID ? s_nextId++ : s_invalidAudioObjectID);
  44. }
  45. ///////////////////////////////////////////////////////////////////////////////////////////////////
  46. // CAudioEventManager
  47. ///////////////////////////////////////////////////////////////////////////////////////////////////
  48. ///////////////////////////////////////////////////////////////////////////////////////////////////
  49. CAudioEventManager::CAudioEventManager()
  50. : m_oAudioEventPool(Audio::CVars::s_AudioEventPoolSize, 1)
  51. #if !defined(AUDIO_RELEASE)
  52. , m_pDebugNameStore(nullptr)
  53. #endif // !AUDIO_RELEASE
  54. {
  55. }
  56. ///////////////////////////////////////////////////////////////////////////////////////////////////
  57. CAudioEventManager::~CAudioEventManager()
  58. {
  59. }
  60. ///////////////////////////////////////////////////////////////////////////////////////////////////
  61. void CAudioEventManager::Initialize()
  62. {
  63. const size_t numActiveAudioEvents = m_cActiveAudioEvents.size();
  64. for (size_t i = 0; i < m_oAudioEventPool.m_nReserveSize - numActiveAudioEvents; ++i)
  65. {
  66. const TAudioEventID nEventID = m_oAudioEventPool.GetNextID();
  67. IATLEventData* pNewEventData = nullptr;
  68. AudioSystemImplementationRequestBus::BroadcastResult(pNewEventData, &AudioSystemImplementationRequestBus::Events::NewAudioEventData, nEventID);
  69. auto pNewEvent = azcreate(CATLEvent, (nEventID, eAS_AUDIO_SYSTEM_IMPLEMENTATION, pNewEventData), Audio::AudioSystemAllocator);
  70. m_oAudioEventPool.m_cReserved.push_back(pNewEvent);
  71. }
  72. TActiveEventMap::const_iterator Iter(m_cActiveAudioEvents.begin());
  73. TActiveEventMap::const_iterator const IterEnd(m_cActiveAudioEvents.end());
  74. for (; Iter != IterEnd; ++Iter)
  75. {
  76. CATLEvent* const pEvent = Iter->second;
  77. IATLEventData* pNewEventData = nullptr;
  78. AudioSystemImplementationRequestBus::BroadcastResult(pNewEventData, &AudioSystemImplementationRequestBus::Events::NewAudioEventData, pEvent->GetID());
  79. pEvent->m_pImplData = pNewEventData;
  80. }
  81. }
  82. ///////////////////////////////////////////////////////////////////////////////////////////////////
  83. void CAudioEventManager::Release()
  84. {
  85. for (auto audioEvent : m_oAudioEventPool.m_cReserved)
  86. {
  87. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioEventData, audioEvent->m_pImplData);
  88. azdestroy(audioEvent, Audio::AudioSystemAllocator);
  89. }
  90. m_oAudioEventPool.m_cReserved.clear();
  91. TActiveEventMap::const_iterator IterActiveAudioEvents(m_cActiveAudioEvents.begin());
  92. TActiveEventMap::const_iterator const IterActiveAudioEventsEnd(m_cActiveAudioEvents.end());
  93. for (; IterActiveAudioEvents != IterActiveAudioEventsEnd; ++IterActiveAudioEvents)
  94. {
  95. CATLEvent* const pEvent = IterActiveAudioEvents->second;
  96. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::ResetAudioEventData, pEvent->m_pImplData);
  97. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioEventData, pEvent->m_pImplData);
  98. pEvent->m_pImplData = nullptr;
  99. }
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////////////////////////
  102. CATLEvent* CAudioEventManager::GetEvent(const EATLSubsystem eSender)
  103. {
  104. CATLEvent* pATLEvent = nullptr;
  105. switch (eSender)
  106. {
  107. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  108. {
  109. pATLEvent = GetImplInstance();
  110. break;
  111. }
  112. case eAS_ATL_INTERNAL:
  113. {
  114. pATLEvent = GetInternalInstance();
  115. break;
  116. }
  117. default:
  118. {
  119. AZ_Assert(false, "Unknown sender specified in GetEvent (%d)", eSender);
  120. break;
  121. }
  122. }
  123. if (pATLEvent)
  124. {
  125. m_cActiveAudioEvents[pATLEvent->GetID()] = pATLEvent;
  126. }
  127. return pATLEvent;
  128. }
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////
  130. CATLEvent* CAudioEventManager::LookupID(const TAudioEventID nID) const
  131. {
  132. auto iPlace = m_cActiveAudioEvents.begin();
  133. const bool bLookupResult = FindPlaceConst(m_cActiveAudioEvents, nID, iPlace);
  134. return bLookupResult ? iPlace->second : nullptr;
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////////////////////////
  137. void CAudioEventManager::ReleaseEvent(CATLEvent* const pEvent)
  138. {
  139. if (pEvent)
  140. {
  141. m_cActiveAudioEvents.erase(pEvent->GetID());
  142. switch (pEvent->m_eSender)
  143. {
  144. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  145. {
  146. ReleaseImplInstance(pEvent);
  147. break;
  148. }
  149. case eAS_ATL_INTERNAL:
  150. {
  151. ReleaseInternalInstance(pEvent);
  152. break;
  153. }
  154. default:
  155. {
  156. AZ_Assert(false, "Unknown sender specified in ReleaseEvent (%d)", pEvent->m_eSender);
  157. break;
  158. }
  159. }
  160. }
  161. }
  162. ///////////////////////////////////////////////////////////////////////////////////////////////////
  163. CATLEvent* CAudioEventManager::GetImplInstance()
  164. {
  165. CATLEvent* pEvent = nullptr;
  166. if (!m_oAudioEventPool.m_cReserved.empty())
  167. {
  168. //have reserved instances
  169. pEvent = m_oAudioEventPool.m_cReserved.back();
  170. m_oAudioEventPool.m_cReserved.pop_back();
  171. }
  172. else
  173. {
  174. //need to get a new instance
  175. const TAudioEventID nNewID = m_oAudioEventPool.GetNextID();
  176. IATLEventData* pNewEventData = nullptr;
  177. AudioSystemImplementationRequestBus::BroadcastResult(pNewEventData, &AudioSystemImplementationRequestBus::Events::NewAudioEventData, nNewID);
  178. pEvent = azcreate(CATLEvent, (nNewID, eAS_AUDIO_SYSTEM_IMPLEMENTATION, pNewEventData), Audio::AudioSystemAllocator);
  179. if (!pEvent)
  180. {
  181. AZLOG_ERROR("%s", "Failed to get a new instance of an ATLEvent from the implementation.");
  182. }
  183. }
  184. return pEvent;
  185. }
  186. ///////////////////////////////////////////////////////////////////////////////////////////////////
  187. void CAudioEventManager::ReleaseImplInstance(CATLEvent* const pOldEvent)
  188. {
  189. if (pOldEvent)
  190. {
  191. pOldEvent->Clear();
  192. if (m_oAudioEventPool.m_cReserved.size() < m_oAudioEventPool.m_nReserveSize)
  193. {
  194. // can return the instance to the reserved pool
  195. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::ResetAudioEventData, pOldEvent->m_pImplData);
  196. m_oAudioEventPool.m_cReserved.push_back(pOldEvent);
  197. }
  198. else
  199. {
  200. // the reserve pool is full, can return the instance to the implementation to dispose
  201. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioEventData, pOldEvent->m_pImplData);
  202. azdestroy(pOldEvent, Audio::AudioSystemAllocator);
  203. }
  204. }
  205. }
  206. ///////////////////////////////////////////////////////////////////////////////////////////////////
  207. CATLEvent* CAudioEventManager::GetInternalInstance()
  208. {
  209. AZ_Assert(false, "GetInternalInstance was called yet it has no implementation!"); // implement when it is needed
  210. return nullptr;
  211. }
  212. ///////////////////////////////////////////////////////////////////////////////////////////////////
  213. void CAudioEventManager::ReleaseInternalInstance([[maybe_unused]] CATLEvent* const pOldEvent)
  214. {
  215. AZ_Assert(false, "ReleaseInternalInstance was called yet it has no implementation!"); // implement when it is needed
  216. }
  217. ///////////////////////////////////////////////////////////////////////////////////////////////////
  218. size_t CAudioEventManager::GetNumActive() const
  219. {
  220. return m_cActiveAudioEvents.size();
  221. }
  222. ///////////////////////////////////////////////////////////////////////////////////////////////////
  223. // CAudioObjectManager
  224. ///////////////////////////////////////////////////////////////////////////////////////////////////
  225. ///////////////////////////////////////////////////////////////////////////////////////////////////
  226. CAudioObjectManager::CAudioObjectManager([[maybe_unused]] CAudioEventManager& refAudioEventManager)
  227. : m_cObjectPool(Audio::CVars::s_AudioObjectPoolSize, AudioObjectIDFactory::s_minValidAudioObjectID)
  228. , m_fTimeSinceLastVelocityUpdateMS(0.0f)
  229. #if !defined(AUDIO_RELEASE)
  230. , m_pDebugNameStore(nullptr)
  231. #endif // !AUDIO_RELEASE
  232. {
  233. }
  234. ///////////////////////////////////////////////////////////////////////////////////////////////////
  235. CAudioObjectManager::~CAudioObjectManager()
  236. {
  237. }
  238. float CAudioObjectManager::s_fVelocityUpdateIntervalMS = 100.0f;
  239. ///////////////////////////////////////////////////////////////////////////////////////////////////
  240. void CAudioObjectManager::Update(const float fUpdateIntervalMS, const SATLWorldPosition& rListenerPosition)
  241. {
  242. AZ_PROFILE_FUNCTION(Audio);
  243. m_fTimeSinceLastVelocityUpdateMS += fUpdateIntervalMS;
  244. const bool bUpdateVelocity = m_fTimeSinceLastVelocityUpdateMS > s_fVelocityUpdateIntervalMS;
  245. m_raycastManager.ProcessRaycastResults(fUpdateIntervalMS);
  246. for (auto& audioObjectPair : m_cAudioObjects)
  247. {
  248. CATLAudioObject* const pObject = audioObjectPair.second;
  249. if (pObject->HasActiveEvents())
  250. {
  251. AZ_PROFILE_SCOPE(Audio, "Inner Per-Object CAudioObjectManager::Update");
  252. pObject->Update(fUpdateIntervalMS, rListenerPosition);
  253. if (pObject->CanRunRaycasts())
  254. {
  255. SATLSoundPropagationData propData;
  256. pObject->GetObstOccData(propData);
  257. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::SetObstructionOcclusion,
  258. pObject->GetImplDataPtr(),
  259. propData.fObstruction,
  260. propData.fOcclusion);
  261. }
  262. if (bUpdateVelocity && pObject->GetVelocityTracking())
  263. {
  264. pObject->UpdateVelocity(m_fTimeSinceLastVelocityUpdateMS);
  265. }
  266. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::UpdateAudioObject, pObject->GetImplDataPtr());
  267. }
  268. }
  269. if (bUpdateVelocity)
  270. {
  271. m_fTimeSinceLastVelocityUpdateMS = 0.0f;
  272. }
  273. }
  274. ///////////////////////////////////////////////////////////////////////////////////////////////////
  275. bool CAudioObjectManager::ReserveID(TAudioObjectID& rAudioObjectID, const char* const sAudioObjectName)
  276. {
  277. CATLAudioObject* const pNewObject = GetInstance();
  278. bool bSuccess = false;
  279. rAudioObjectID = INVALID_AUDIO_OBJECT_ID;
  280. if (pNewObject)
  281. {
  282. EAudioRequestStatus eImplResult = EAudioRequestStatus::Failure;
  283. AudioSystemImplementationRequestBus::BroadcastResult(
  284. eImplResult, &AudioSystemImplementationRequestBus::Events::RegisterAudioObject, pNewObject->GetImplDataPtr(),
  285. sAudioObjectName);
  286. if (eImplResult == EAudioRequestStatus::Success)
  287. {
  288. pNewObject->IncrementRefCount();
  289. rAudioObjectID = pNewObject->GetID();
  290. m_cAudioObjects.emplace(rAudioObjectID, pNewObject);
  291. bSuccess = true;
  292. }
  293. else
  294. {
  295. ReleaseInstance(pNewObject);
  296. bSuccess = false;
  297. }
  298. }
  299. return bSuccess;
  300. }
  301. ///////////////////////////////////////////////////////////////////////////////////////////////////
  302. bool CAudioObjectManager::ReleaseID(const TAudioObjectID nAudioObjectID)
  303. {
  304. bool bSuccess = false;
  305. CATLAudioObject* const pOldObject = LookupID(nAudioObjectID);
  306. if (pOldObject)
  307. {
  308. // If the refcount is one, that means it's the "self" reference and there are no
  309. // active events, so we can release/recycle the object back to the pool.
  310. // Otherwise we can decrement the "self" reference and let outstanding events
  311. // naturally finish and auto-release the object.
  312. if (pOldObject->GetRefCount() == 1)
  313. {
  314. bSuccess = ReleaseInstance(pOldObject);
  315. }
  316. else
  317. {
  318. pOldObject->DecrementRefCount();
  319. }
  320. }
  321. return bSuccess;
  322. }
  323. ///////////////////////////////////////////////////////////////////////////////////////////////////
  324. CATLAudioObject* CAudioObjectManager::LookupID(const TAudioObjectID nID) const
  325. {
  326. CATLAudioObject* pResult = nullptr;
  327. auto it = m_cAudioObjects.find(nID);
  328. if (it != m_cAudioObjects.end())
  329. {
  330. pResult = it->second;
  331. }
  332. return pResult;
  333. }
  334. ///////////////////////////////////////////////////////////////////////////////////////////////////
  335. void CAudioObjectManager::ReportEventFinished(const CATLEvent* atlEvent)
  336. {
  337. if (atlEvent)
  338. {
  339. if (CATLAudioObject* audioObject = LookupID(atlEvent->m_nObjectID);
  340. audioObject != nullptr)
  341. {
  342. audioObject->EventFinished(atlEvent);
  343. // EventFinished will decr ref count (assuming the event was valid).
  344. // This handles a case where ReleaseID was called for the object, but there were
  345. // active events. The object's "self" reference has already been decremented.
  346. // So if the event finishing naturally causes refcount to zero, we can recycle the object.
  347. if (audioObject->GetRefCount() == 0)
  348. {
  349. ReleaseInstance(audioObject);
  350. }
  351. }
  352. #if !defined(AUDIO_RELEASE)
  353. else
  354. {
  355. AZLOG_DEBUG(
  356. "Removing Event %llu from object '%s' - Object no longer exists!", atlEvent->GetID(),
  357. m_pDebugNameStore->LookupAudioObjectName(atlEvent->m_nObjectID));
  358. }
  359. #endif // !AUDIO_RELEASE
  360. }
  361. }
  362. ///////////////////////////////////////////////////////////////////////////////////////////////////
  363. CATLAudioObject* CAudioObjectManager::GetInstance()
  364. {
  365. CATLAudioObject* pObject = nullptr;
  366. if (!m_cObjectPool.m_cReserved.empty())
  367. {
  368. //have reserved instances
  369. pObject = m_cObjectPool.m_cReserved.back();
  370. m_cObjectPool.m_cReserved.pop_back();
  371. }
  372. else
  373. {
  374. //need to get a new instance
  375. const TAudioObjectID nNewID = AudioObjectIDFactory::GetNextID();
  376. IATLAudioObjectData* pObjectData = nullptr;
  377. AudioSystemImplementationRequestBus::BroadcastResult(pObjectData, &AudioSystemImplementationRequestBus::Events::NewAudioObjectData, nNewID);
  378. size_t unallocatedMemorySize = AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().GetUnAllocatedMemory();
  379. const size_t minimalMemorySize = 100 * 1024;
  380. if (unallocatedMemorySize < minimalMemorySize)
  381. {
  382. AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().GarbageCollect();
  383. unallocatedMemorySize = AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().GetUnAllocatedMemory();
  384. }
  385. if (unallocatedMemorySize >= minimalMemorySize)
  386. {
  387. pObject = azcreate(CATLAudioObject, (nNewID, pObjectData), Audio::AudioSystemAllocator);
  388. }
  389. if (!pObject)
  390. {
  391. AZLOG_ERROR("%s", "Failed to get a new instance of an AudioObject from the implementation. "
  392. "If this limit was reached from legitimate content creation and not a scripting error, "
  393. "try increasing the Capacity of Audio::AudioSystemAllocator.");
  394. //failed to get a new instance from the implementation
  395. }
  396. }
  397. return pObject;
  398. }
  399. ///////////////////////////////////////////////////////////////////////////////////////////////////
  400. bool CAudioObjectManager::ReleaseInstance(CATLAudioObject* const pOldObject)
  401. {
  402. bool bSuccess = false;
  403. if (pOldObject)
  404. {
  405. const TAudioObjectID nObjectID = pOldObject->GetID();
  406. m_cAudioObjects.erase(nObjectID);
  407. #if !defined(AUDIO_RELEASE)
  408. m_pDebugNameStore->RemoveAudioObject(nObjectID);
  409. pOldObject->CheckBeforeRemoval(m_pDebugNameStore);
  410. #endif // !AUDIO_RELEASE
  411. pOldObject->Clear();
  412. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  413. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::UnregisterAudioObject, pOldObject->GetImplDataPtr());
  414. bSuccess = (eResult == EAudioRequestStatus::Success);
  415. if (m_cObjectPool.m_cReserved.size() < m_cObjectPool.m_nReserveSize)
  416. {
  417. // can return the instance to the reserved pool
  418. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::ResetAudioObject, pOldObject->GetImplDataPtr());
  419. m_cObjectPool.m_cReserved.push_back(pOldObject);
  420. }
  421. else
  422. {
  423. // the reserve pool is full, can return the instance to the implementation to dispose
  424. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioObjectData, pOldObject->GetImplDataPtr());
  425. azdestroy(pOldObject, Audio::AudioSystemAllocator);
  426. }
  427. }
  428. return bSuccess;
  429. }
  430. ///////////////////////////////////////////////////////////////////////////////////////////////////
  431. void CAudioObjectManager::Initialize()
  432. {
  433. const size_t numRegisteredObjects = m_cAudioObjects.size();
  434. for (size_t i = 0; i < m_cObjectPool.m_nReserveSize - numRegisteredObjects; ++i)
  435. {
  436. const auto nObjectID = AudioObjectIDFactory::GetNextID();
  437. IATLAudioObjectData* pObjectData = nullptr;
  438. AudioSystemImplementationRequestBus::BroadcastResult(pObjectData, &AudioSystemImplementationRequestBus::Events::NewAudioObjectData, nObjectID);
  439. auto pObject = azcreate(CATLAudioObject, (nObjectID, pObjectData), Audio::AudioSystemAllocator);
  440. m_cObjectPool.m_cReserved.push_back(pObject);
  441. }
  442. for (const auto& audioObjectPair : m_cAudioObjects)
  443. {
  444. CATLAudioObject* const pAudioObject = audioObjectPair.second;
  445. IATLAudioObjectData* pObjectData = nullptr;
  446. AudioSystemImplementationRequestBus::BroadcastResult(pObjectData, &AudioSystemImplementationRequestBus::Events::NewAudioObjectData, pAudioObject->GetID());
  447. pAudioObject->SetImplDataPtr(pObjectData);
  448. char const* szAudioObjectName = nullptr;
  449. #if !defined(AUDIO_RELEASE)
  450. szAudioObjectName = m_pDebugNameStore->LookupAudioObjectName(pAudioObject->GetID());
  451. #endif // !AUDIO_RELEASE
  452. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  453. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::RegisterAudioObject, pAudioObject->GetImplDataPtr(), szAudioObjectName);
  454. AZ_Assert(eResult == EAudioRequestStatus::Success, "RegisterAudioObject failed to register object named '%s'", szAudioObjectName);
  455. }
  456. }
  457. ///////////////////////////////////////////////////////////////////////////////////////////////////
  458. void CAudioObjectManager::Release()
  459. {
  460. for (auto audioObject : m_cObjectPool.m_cReserved)
  461. {
  462. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioObjectData, audioObject->GetImplDataPtr());
  463. azdestroy(audioObject, Audio::AudioSystemAllocator);
  464. }
  465. m_cObjectPool.m_cReserved.clear();
  466. for (const auto& audioObjectPair : m_cAudioObjects)
  467. {
  468. CATLAudioObject* const pAudioObject = audioObjectPair.second;
  469. if (auto implObject = pAudioObject->GetImplDataPtr())
  470. {
  471. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  472. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::UnregisterAudioObject, implObject);
  473. AZ_Error("CAudioObjectManager", eResult == EAudioRequestStatus::Success, "Failed to Unregister Audio Object!");
  474. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::ResetAudioObject, implObject);
  475. AZ_Error("CAudioObjectManager", eResult == EAudioRequestStatus::Success, "Failed to Reset Audio Object!");
  476. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioObjectData, implObject);
  477. pAudioObject->SetImplDataPtr(nullptr);
  478. }
  479. }
  480. }
  481. ///////////////////////////////////////////////////////////////////////////////////////////////////
  482. void AudioRaycastManager::PushAudioRaycastRequest(const AudioRaycastRequest& request)
  483. {
  484. // [Audio Thread]
  485. AZStd::scoped_lock lock(m_raycastRequestsMutex);
  486. m_raycastRequests.push_back(request);
  487. }
  488. AudioRaycastManager::AudioRaycastManager()
  489. : m_sceneFinishSimHandler([this](
  490. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  491. [[maybe_unused]] float fixedDeltatime)
  492. {
  493. this->OnPhysicsSubtickFinished();
  494. }, aznumeric_cast<int32_t>(AzPhysics::SceneEvents::PhysicsStartFinishSimulationPriority::Audio))
  495. {
  496. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  497. {
  498. AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  499. sceneInterface->RegisterSceneSimulationFinishHandler(sceneHandle, m_sceneFinishSimHandler);
  500. }
  501. AudioRaycastRequestBus::Handler::BusConnect();
  502. }
  503. AudioRaycastManager::~AudioRaycastManager()
  504. {
  505. AudioRaycastRequestBus::Handler::BusDisconnect();
  506. m_sceneFinishSimHandler.Disconnect();
  507. }
  508. ///////////////////////////////////////////////////////////////////////////////////////////////////
  509. void AudioRaycastManager::OnPhysicsSubtickFinished()
  510. {
  511. // [Main Thread]
  512. AzPhysics::SceneHandle sceneHandle = AzPhysics::InvalidSceneHandle;
  513. auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
  514. if (sceneInterface != nullptr)
  515. {
  516. sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  517. }
  518. AZ_Warning("AudioRaycastManager", sceneHandle != AzPhysics::InvalidSceneHandle, "Unable to retrive default physics scene.");
  519. AudioRaycastRequestQueueType processingQueue;
  520. // Lock and swap the main request container with a local one for processing...
  521. {
  522. AZStd::scoped_lock lock(m_raycastRequestsMutex);
  523. processingQueue.swap(m_raycastRequests);
  524. }
  525. AudioRaycastResultQueueType resultsQueue;
  526. resultsQueue.reserve(processingQueue.size());
  527. // Process raycasts and enter results in resultsQueue...
  528. for (const AudioRaycastRequest& request : processingQueue)
  529. {
  530. AZ_Assert(request.m_request.m_maxResults <= s_maxHitResultsPerRaycast,
  531. "Encountered audio raycast request that has maxResults set too high (%" PRIu64 ")!\n", request.m_request.m_maxResults);
  532. AzPhysics::SceneQueryHits hitResults;
  533. if (sceneInterface != nullptr)
  534. {
  535. hitResults = sceneInterface->QueryScene(sceneHandle, &request.m_request);
  536. }
  537. AZ_Error("Audio Raycast", hitResults.m_hits.size() <= s_maxHitResultsPerRaycast,
  538. "RayCastMultiple returned too many hits (%zu)!\n", hitResults.m_hits.size());
  539. resultsQueue.emplace_back(AZStd::move(hitResults.m_hits), request.m_audioObjectId, request.m_rayIndex);
  540. }
  541. // Lock and swap the local results into the target container (or move-append if necessary)...
  542. {
  543. AZStd::scoped_lock lock(m_raycastResultsMutex);
  544. if (m_raycastResults.empty())
  545. {
  546. m_raycastResults.swap(resultsQueue);
  547. }
  548. else
  549. {
  550. AZStd::move(resultsQueue.begin(), resultsQueue.end(), AZStd::back_inserter(m_raycastResults));
  551. }
  552. }
  553. }
  554. ///////////////////////////////////////////////////////////////////////////////////////////////////
  555. void AudioRaycastManager::ProcessRaycastResults([[maybe_unused]] float updateIntervalMs)
  556. {
  557. // [Audio Thread]
  558. AZStd::scoped_lock lock(m_raycastResultsMutex);
  559. for (const AudioRaycastResult& result : m_raycastResults)
  560. {
  561. AudioRaycastNotificationBus::Event(result.m_audioObjectId, &AudioRaycastNotificationBus::Events::OnAudioRaycastResults, result);
  562. }
  563. m_raycastResults.clear();
  564. }
  565. ///////////////////////////////////////////////////////////////////////////////////////////////////
  566. // CAudioListenerManager
  567. ///////////////////////////////////////////////////////////////////////////////////////////////////
  568. ///////////////////////////////////////////////////////////////////////////////////////////////////
  569. CAudioListenerManager::CAudioListenerManager()
  570. : m_pDefaultListenerObject(nullptr)
  571. , m_nDefaultListenerID(AudioObjectIDFactory::GetNextID())
  572. , m_listenerOverrideID(INVALID_AUDIO_OBJECT_ID)
  573. {
  574. m_cListenerPool.reserve(m_numReservedListeners);
  575. }
  576. ///////////////////////////////////////////////////////////////////////////////////////////////////
  577. CAudioListenerManager::~CAudioListenerManager()
  578. {
  579. }
  580. ///////////////////////////////////////////////////////////////////////////////////////////////////
  581. void CAudioListenerManager::Initialize()
  582. {
  583. IATLListenerData* pNewListenerData = nullptr;
  584. // Default listener...
  585. AudioSystemImplementationRequestBus::BroadcastResult(pNewListenerData, &AudioSystemImplementationRequestBus::Events::NewDefaultAudioListenerObjectData, m_nDefaultListenerID);
  586. m_pDefaultListenerObject = azcreate(CATLListenerObject, (m_nDefaultListenerID, pNewListenerData), Audio::AudioSystemAllocator);
  587. if (m_pDefaultListenerObject)
  588. {
  589. m_cActiveListeners[m_nDefaultListenerID] = m_pDefaultListenerObject;
  590. }
  591. // Additional listeners...
  592. for (size_t listener = 0; listener < m_numReservedListeners; ++listener)
  593. {
  594. const TAudioObjectID listenerId = AudioObjectIDFactory::GetNextID();
  595. AudioSystemImplementationRequestBus::BroadcastResult(pNewListenerData, &AudioSystemImplementationRequestBus::Events::NewAudioListenerObjectData, listenerId);
  596. auto listenerObject = azcreate(CATLListenerObject, (listenerId, pNewListenerData), Audio::AudioSystemAllocator);
  597. m_cListenerPool.push_back(listenerObject);
  598. }
  599. }
  600. ///////////////////////////////////////////////////////////////////////////////////////////////////
  601. void CAudioListenerManager::Release()
  602. {
  603. if (m_pDefaultListenerObject) // guard against double deletions
  604. {
  605. m_cActiveListeners.erase(m_nDefaultListenerID);
  606. AudioSystemImplementationRequestBus::Broadcast(
  607. &AudioSystemImplementationRequestBus::Events::DeleteAudioListenerObjectData, m_pDefaultListenerObject->m_pImplData);
  608. azdestroy(m_pDefaultListenerObject, Audio::AudioSystemAllocator);
  609. m_pDefaultListenerObject = nullptr;
  610. }
  611. // Release any remaining active audio listeners
  612. for (auto listenerPair : m_cActiveListeners)
  613. {
  614. AudioSystemImplementationRequestBus::Broadcast(
  615. &AudioSystemImplementationRequestBus::Events::DeleteAudioListenerObjectData, listenerPair.second->m_pImplData);
  616. azdestroy(listenerPair.second, Audio::AudioSystemAllocator);
  617. }
  618. m_cActiveListeners.clear();
  619. // Delete all remaining listeners from the audio listener pool
  620. for (auto listener : m_cListenerPool)
  621. {
  622. AudioSystemImplementationRequestBus::Broadcast(
  623. &AudioSystemImplementationRequestBus::Events::DeleteAudioListenerObjectData, listener->m_pImplData);
  624. azdestroy(listener, Audio::AudioSystemAllocator);
  625. }
  626. m_cListenerPool.clear();
  627. }
  628. ///////////////////////////////////////////////////////////////////////////////////////////////////
  629. bool CAudioListenerManager::ReserveID(TAudioObjectID& rAudioObjectID)
  630. {
  631. bool bSuccess = false;
  632. if (!m_cListenerPool.empty())
  633. {
  634. CATLListenerObject* pListener = m_cListenerPool.back();
  635. m_cListenerPool.pop_back();
  636. const TAudioObjectID nID = pListener->GetID();
  637. m_cActiveListeners.emplace(nID, pListener);
  638. rAudioObjectID = nID;
  639. bSuccess = true;
  640. }
  641. else
  642. {
  643. AZLOG_WARN("%s", "CAudioListenerManager::ReserveID - Reserved pool of pre-allocated Audio Listeners has been exhausted!");
  644. }
  645. return bSuccess;
  646. }
  647. ///////////////////////////////////////////////////////////////////////////////////////////////////
  648. bool CAudioListenerManager::ReleaseID(const TAudioObjectID nAudioObjectID)
  649. {
  650. bool bSuccess = false;
  651. CATLListenerObject* pListener = LookupID(nAudioObjectID);
  652. if (pListener)
  653. {
  654. m_cActiveListeners.erase(nAudioObjectID);
  655. m_cListenerPool.push_back(pListener);
  656. bSuccess = true;
  657. }
  658. return bSuccess;
  659. }
  660. ///////////////////////////////////////////////////////////////////////////////////////////////////
  661. CATLListenerObject* CAudioListenerManager::LookupID(const TAudioObjectID nID) const
  662. {
  663. CATLListenerObject* pListenerObject = nullptr;
  664. TActiveListenerMap::const_iterator iPlace = m_cActiveListeners.begin();
  665. if (FindPlaceConst(m_cActiveListeners, nID, iPlace))
  666. {
  667. pListenerObject = iPlace->second;
  668. }
  669. return pListenerObject;
  670. }
  671. ///////////////////////////////////////////////////////////////////////////////////////////////////
  672. size_t CAudioListenerManager::GetNumActive() const
  673. {
  674. return m_cActiveListeners.size();
  675. }
  676. ///////////////////////////////////////////////////////////////////////////////////////////////////
  677. void CAudioListenerManager::GetDefaultListenerPosition(SATLWorldPosition& oPosition)
  678. {
  679. if (m_pDefaultListenerObject)
  680. {
  681. oPosition = m_pDefaultListenerObject->oPosition;
  682. }
  683. }
  684. ///////////////////////////////////////////////////////////////////////////////////////////////////
  685. bool CAudioListenerManager::SetOverrideListenerID(const TAudioObjectID nAudioObjectID)
  686. {
  687. // If passed ID is INVALID_AUDIO_OBJECT_ID, override is being turned off.
  688. TActiveListenerMap::const_iterator itBegin = m_cActiveListeners.begin();
  689. if (nAudioObjectID == INVALID_AUDIO_OBJECT_ID
  690. || FindPlaceConst(m_cActiveListeners, nAudioObjectID, itBegin))
  691. {
  692. m_listenerOverrideID = nAudioObjectID;
  693. return true;
  694. }
  695. return false;
  696. }
  697. ///////////////////////////////////////////////////////////////////////////////////////////////////
  698. // CATLXMLProcessor
  699. ///////////////////////////////////////////////////////////////////////////////////////////////////
  700. ///////////////////////////////////////////////////////////////////////////////////////////////////
  701. CATLXmlProcessor::CATLXmlProcessor(
  702. TATLTriggerLookup& rTriggers,
  703. TATLRtpcLookup& rRtpcs,
  704. TATLSwitchLookup& rSwitches,
  705. TATLEnvironmentLookup& rEnvironments,
  706. TATLPreloadRequestLookup& rPreloadRequests,
  707. CFileCacheManager& rFileCacheMgr)
  708. : m_rTriggers(rTriggers)
  709. , m_rRtpcs(rRtpcs)
  710. , m_rSwitches(rSwitches)
  711. , m_rEnvironments(rEnvironments)
  712. , m_rPreloadRequests(rPreloadRequests)
  713. , m_nTriggerImplIDCounter(AUDIO_TRIGGER_IMPL_ID_NUM_RESERVED)
  714. , m_rFileCacheMgr(rFileCacheMgr)
  715. , m_rootPath("@products@")
  716. #if !defined(AUDIO_RELEASE)
  717. , m_pDebugNameStore(nullptr)
  718. #endif // !AUDIO_RELEASE
  719. {
  720. }
  721. ///////////////////////////////////////////////////////////////////////////////////////////////////
  722. void CATLXmlProcessor::ParseControlsData(const char* const folderPath, const EATLDataScope dataScope)
  723. {
  724. AZStd::string searchPath;
  725. AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath);
  726. auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml");
  727. for (const auto& file : foundFiles)
  728. {
  729. AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str());
  730. AZLOG_INFO("Loading Audio Controls Library: '%s'", file.c_str());
  731. Audio::ScopedXmlLoader xmlFileLoader(file.Native());
  732. if (xmlFileLoader.HasError())
  733. {
  734. continue;
  735. }
  736. const AZ::rapidxml::xml_node<char>* xmlRootNode = xmlFileLoader.GetRootNode();
  737. if (xmlRootNode)
  738. {
  739. auto childNode = xmlRootNode->first_node(nullptr, 0, false);
  740. while (childNode)
  741. {
  742. if (azstricmp(childNode->name(), ATLXmlTags::TriggersNodeTag) == 0)
  743. {
  744. ParseAudioTriggers(childNode, dataScope);
  745. }
  746. else if (azstricmp(childNode->name(), ATLXmlTags::RtpcsNodeTag) == 0)
  747. {
  748. ParseAudioRtpcs(childNode, dataScope);
  749. }
  750. else if (azstricmp(childNode->name(), ATLXmlTags::SwitchesNodeTag) == 0)
  751. {
  752. ParseAudioSwitches(childNode, dataScope);
  753. }
  754. else if (azstricmp(childNode->name(), ATLXmlTags::EnvironmentsNodeTag) == 0)
  755. {
  756. ParseAudioEnvironments(childNode, dataScope);
  757. }
  758. childNode = childNode->next_sibling(nullptr, 0, false);
  759. }
  760. }
  761. }
  762. }
  763. ///////////////////////////////////////////////////////////////////////////////////////////////////
  764. void CATLXmlProcessor::ParsePreloadsData(const char* const folderPath, const EATLDataScope dataScope)
  765. {
  766. AZStd::string searchPath;
  767. AZ::StringFunc::Path::Join(m_rootPath.c_str(), folderPath, searchPath);
  768. auto foundFiles = Audio::FindFilesInPath(searchPath, "*.xml");
  769. for (const auto& file : foundFiles)
  770. {
  771. AZ_Assert(AZ::IO::FileIOBase::GetInstance()->Exists(file.c_str()), "FindFiles found file '%s' but FileIO says it doesn't exist!", file.c_str());
  772. AZLOG_INFO("Loading Audio Preloads Library: '%s'", file.c_str());
  773. Audio::ScopedXmlLoader xmlFileLoader(file.Native());
  774. if (xmlFileLoader.HasError())
  775. {
  776. continue;
  777. }
  778. const AZ::rapidxml::xml_node<char>* xmlRootNode = xmlFileLoader.GetRootNode();
  779. if (xmlRootNode)
  780. {
  781. auto childNode = xmlRootNode->first_node(ATLXmlTags::PreloadsNodeTag, 0, false);
  782. while (childNode)
  783. {
  784. if (dataScope == eADS_LEVEL_SPECIFIC)
  785. {
  786. AZStd::string_view relativePath(folderPath);
  787. AZStd::string levelName;
  788. AZ::StringFunc::Path::GetFileName(relativePath.data(), levelName);
  789. ParseAudioPreloads(childNode, dataScope, levelName.data());
  790. }
  791. else
  792. {
  793. ParseAudioPreloads(childNode, dataScope, nullptr);
  794. }
  795. childNode = childNode->next_sibling(ATLXmlTags::PreloadsNodeTag, 0, false);
  796. }
  797. }
  798. }
  799. }
  800. ///////////////////////////////////////////////////////////////////////////////////////////////////
  801. void CATLXmlProcessor::ClearControlsData(const EATLDataScope eDataScope)
  802. {
  803. // Remove Triggers...
  804. for (auto itRemove = m_rTriggers.begin(); itRemove != m_rTriggers.end(); )
  805. {
  806. auto const pTrigger = itRemove->second;
  807. if (eDataScope == eADS_ALL || (pTrigger->GetDataScope() == eDataScope))
  808. {
  809. #if !defined(AUDIO_RELEASE)
  810. m_pDebugNameStore->RemoveAudioTrigger(pTrigger->GetID());
  811. #endif // !AUDIO_RELEASE
  812. DeleteAudioTrigger(pTrigger);
  813. itRemove = m_rTriggers.erase(itRemove);
  814. }
  815. else
  816. {
  817. ++itRemove;
  818. }
  819. }
  820. // Remove Rtpcs...
  821. for (auto itRemove = m_rRtpcs.begin(); itRemove != m_rRtpcs.end(); )
  822. {
  823. auto const pRtpc = itRemove->second;
  824. if (eDataScope == eADS_ALL || (pRtpc->GetDataScope() == eDataScope))
  825. {
  826. #if !defined(AUDIO_RELEASE)
  827. m_pDebugNameStore->RemoveAudioRtpc(pRtpc->GetID());
  828. #endif // !AUDIO_RELEASE
  829. DeleteAudioRtpc(pRtpc);
  830. itRemove = m_rRtpcs.erase(itRemove);
  831. }
  832. else
  833. {
  834. ++itRemove;
  835. }
  836. }
  837. // Remove Switches...
  838. for (auto itRemove = m_rSwitches.begin(); itRemove != m_rSwitches.end(); )
  839. {
  840. auto const pSwitch = itRemove->second;
  841. if (eDataScope == eADS_ALL || (pSwitch->GetDataScope() == eDataScope))
  842. {
  843. #if !defined(AUDIO_RELEASE)
  844. m_pDebugNameStore->RemoveAudioSwitch(pSwitch->GetID());
  845. #endif // !AUDIO_RELEASE
  846. DeleteAudioSwitch(pSwitch);
  847. itRemove = m_rSwitches.erase(itRemove);
  848. }
  849. else
  850. {
  851. ++itRemove;
  852. }
  853. }
  854. // Remove Environments...
  855. for (auto itRemove = m_rEnvironments.begin(); itRemove != m_rEnvironments.end(); )
  856. {
  857. auto const pEnvironment = itRemove->second;
  858. if (eDataScope == eADS_ALL || (pEnvironment->GetDataScope() == eDataScope))
  859. {
  860. #if !defined(AUDIO_RELEASE)
  861. m_pDebugNameStore->RemoveAudioEnvironment(pEnvironment->GetID());
  862. #endif // !AUDIO_RELEASE
  863. DeleteAudioEnvironment(pEnvironment);
  864. itRemove = m_rEnvironments.erase(itRemove);
  865. }
  866. else
  867. {
  868. ++itRemove;
  869. }
  870. }
  871. }
  872. ///////////////////////////////////////////////////////////////////////////////////////////////////
  873. void CATLXmlProcessor::ParseAudioPreloads(const AZ::rapidxml::xml_node<char>* preloadsXmlRoot, const EATLDataScope dataScope, const char* const folderName)
  874. {
  875. auto preloadNode = preloadsXmlRoot->first_node(ATLXmlTags::ATLPreloadRequestTag, 0, false);
  876. while (preloadNode)
  877. {
  878. TAudioPreloadRequestID preloadRequestId = ATLInternalControlIDs::GlobalPreloadRequestID;
  879. const char* preloadRequestName = ATLInternalControlNames::GlobalPreloadRequestName;
  880. bool autoLoad = false;
  881. auto loadTypeAttr = preloadNode->first_attribute(ATLXmlTags::ATLTypeAttribute, 0, false);
  882. auto nameAttr = preloadNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  883. if (loadTypeAttr && azstricmp(loadTypeAttr->value(), ATLXmlTags::ATLDataLoadType) == 0)
  884. {
  885. autoLoad = true;
  886. if (dataScope == eADS_LEVEL_SPECIFIC)
  887. {
  888. preloadRequestName = folderName;
  889. preloadRequestId = AudioStringToID<TAudioPreloadRequestID>(preloadRequestName);
  890. }
  891. }
  892. else if (nameAttr)
  893. {
  894. preloadRequestName = nameAttr->value();
  895. preloadRequestId = AudioStringToID<TAudioPreloadRequestID>(preloadRequestName);
  896. }
  897. if (preloadRequestId != INVALID_AUDIO_PRELOAD_REQUEST_ID)
  898. {
  899. // Legacy support - Try legacy first here because it contains more nodes than the newer format...
  900. auto fileEntryIds = LegacyParseFileEntries(preloadNode, dataScope, autoLoad);
  901. if (fileEntryIds.empty())
  902. {
  903. fileEntryIds = ParseFileEntries(preloadNode, dataScope, autoLoad);
  904. }
  905. auto it = m_rPreloadRequests.find(preloadRequestId);
  906. if (it == m_rPreloadRequests.end())
  907. {
  908. auto preloadRequest = azcreate(CATLPreloadRequest, (preloadRequestId, dataScope, autoLoad, fileEntryIds), Audio::AudioSystemAllocator);
  909. m_rPreloadRequests[preloadRequestId] = preloadRequest;
  910. #if !defined(AUDIO_RELEASE)
  911. m_pDebugNameStore->AddAudioPreloadRequest(preloadRequestId, preloadRequestName);
  912. #endif // !AUDIO_RELEASE
  913. }
  914. else if (!fileEntryIds.empty())
  915. {
  916. it->second->m_cFileEntryIDs.insert(it->second->m_cFileEntryIDs.end(), fileEntryIds.begin(), fileEntryIds.end());
  917. }
  918. }
  919. preloadNode = preloadNode->next_sibling(ATLXmlTags::ATLPreloadRequestTag, 0, false);
  920. }
  921. }
  922. ///////////////////////////////////////////////////////////////////////////////////////////////////
  923. CATLPreloadRequest::TFileEntryIDs CATLXmlProcessor::LegacyParseFileEntries(const AZ::rapidxml::xml_node<char>* preloadNode, const EATLDataScope dataScope, bool autoLoad)
  924. {
  925. CATLPreloadRequest::TFileEntryIDs fileEntryIds;
  926. auto platformsNode = preloadNode->first_node(ATLXmlTags::ATLPlatformsTag, 0, false);
  927. auto configGroupNode = preloadNode->first_node(ATLXmlTags::ATLConfigGroupTag, 0, false);
  928. if (platformsNode && configGroupNode)
  929. {
  930. const char* configGroupName = nullptr;
  931. auto platformNode = platformsNode->first_node(ATLXmlTags::PlatformNodeTag, 0, false);
  932. while (platformNode)
  933. {
  934. auto platformAttr = platformNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  935. if (platformAttr)
  936. {
  937. if (azstricmp(platformAttr->value(), ATLXmlTags::PlatformName) == 0 || azstricmp(platformAttr->value(), ATLXmlTags::PlatformCodeName) == 0)
  938. {
  939. auto configGroupAttr = platformNode->first_attribute(ATLXmlTags::ATLConfigGroupAttribute, 0, false);
  940. if (configGroupAttr)
  941. {
  942. configGroupName = configGroupAttr->value();
  943. break;
  944. }
  945. }
  946. }
  947. platformNode = platformNode->next_sibling(ATLXmlTags::PlatformNodeTag, 0, false);
  948. }
  949. if (configGroupName)
  950. {
  951. while (configGroupNode)
  952. {
  953. auto configGroupAttr = configGroupNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  954. if (configGroupAttr && azstricmp(configGroupAttr->value(), configGroupName) == 0)
  955. {
  956. // Found a config group associated with this platform...
  957. auto fileNode = configGroupNode->first_node(nullptr, 0, false);
  958. while (fileNode)
  959. {
  960. TAudioFileEntryID fileEntryId = m_rFileCacheMgr.TryAddFileCacheEntry(fileNode, dataScope, autoLoad);
  961. if (fileEntryId != INVALID_AUDIO_FILE_ENTRY_ID)
  962. {
  963. fileEntryIds.push_back(fileEntryId);
  964. }
  965. fileNode = fileNode->next_sibling(nullptr, 0, false);
  966. }
  967. // No need to continue looking through the config groups once a match is found...
  968. break;
  969. }
  970. configGroupNode = configGroupNode->next_sibling(ATLXmlTags::ATLConfigGroupTag, 0, false);
  971. }
  972. }
  973. }
  974. return fileEntryIds;
  975. }
  976. ///////////////////////////////////////////////////////////////////////////////////////////////////
  977. CATLPreloadRequest::TFileEntryIDs CATLXmlProcessor::ParseFileEntries(const AZ::rapidxml::xml_node<char>* preloadNode, const EATLDataScope dataScope, bool autoLoad)
  978. {
  979. CATLPreloadRequest::TFileEntryIDs fileEntryIds;
  980. auto fileNode = preloadNode->first_node(nullptr, 0, false);
  981. while (fileNode)
  982. {
  983. TAudioFileEntryID fileEntryId = m_rFileCacheMgr.TryAddFileCacheEntry(fileNode, dataScope, autoLoad);
  984. if (fileEntryId != INVALID_AUDIO_FILE_ENTRY_ID)
  985. {
  986. fileEntryIds.push_back(fileEntryId);
  987. }
  988. fileNode = fileNode->next_sibling(nullptr, 0, false);
  989. }
  990. return fileEntryIds;
  991. }
  992. ///////////////////////////////////////////////////////////////////////////////////////////////////
  993. void CATLXmlProcessor::ClearPreloadsData(const EATLDataScope eDataScope)
  994. {
  995. for (auto itRemove = m_rPreloadRequests.begin(); itRemove != m_rPreloadRequests.end(); )
  996. {
  997. auto const pRequest = itRemove->second;
  998. if (eDataScope == eADS_ALL || (pRequest->GetDataScope() == eDataScope))
  999. {
  1000. #if !defined(AUDIO_RELEASE)
  1001. m_pDebugNameStore->RemoveAudioPreloadRequest(pRequest->GetID());
  1002. #endif // !AUDIO_RELEASE
  1003. DeleteAudioPreloadRequest(pRequest);
  1004. itRemove = m_rPreloadRequests.erase(itRemove);
  1005. }
  1006. else
  1007. {
  1008. ++itRemove;
  1009. }
  1010. }
  1011. }
  1012. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1013. void CATLXmlProcessor::ParseAudioEnvironments(const AZ::rapidxml::xml_node<char>* environmentsXmlRoot, const EATLDataScope dataScope)
  1014. {
  1015. auto environmentNode = environmentsXmlRoot->first_node(ATLXmlTags::ATLEnvironmentTag, 0, false);
  1016. while (environmentNode)
  1017. {
  1018. auto environmentAttr = environmentNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1019. const char* atlEnvironmentName = nullptr;
  1020. if (environmentAttr)
  1021. {
  1022. atlEnvironmentName = environmentAttr->value();
  1023. }
  1024. const auto atlEnvironmentId = AudioStringToID<TAudioEnvironmentID>(atlEnvironmentName);
  1025. if ((atlEnvironmentId != INVALID_AUDIO_ENVIRONMENT_ID) && (m_rEnvironments.find(atlEnvironmentId) == m_rEnvironments.end()))
  1026. {
  1027. CATLAudioEnvironment::TImplPtrVec envImpls;
  1028. auto environmentImplNode = environmentNode->first_node(nullptr, 0, false);
  1029. while (environmentImplNode)
  1030. {
  1031. IATLEnvironmentImplData* environmentImplData = nullptr;
  1032. EATLSubsystem receiver = eAS_NONE;
  1033. if (azstricmp(environmentImplNode->name(), ATLXmlTags::ATLEnvironmentRequestTag) == 0)
  1034. {
  1035. environmentImplData = NewAudioEnvironmentImplDataInternal(environmentImplNode);
  1036. receiver = eAS_ATL_INTERNAL;
  1037. }
  1038. else
  1039. {
  1040. AudioSystemImplementationRequestBus::BroadcastResult(environmentImplData, &AudioSystemImplementationRequestBus::Events::NewAudioEnvironmentImplData, environmentImplNode);
  1041. receiver = eAS_AUDIO_SYSTEM_IMPLEMENTATION;
  1042. }
  1043. if (environmentImplData)
  1044. {
  1045. auto environmentImpl = azcreate(CATLEnvironmentImpl, (receiver, environmentImplData), Audio::AudioSystemAllocator);
  1046. envImpls.push_back(environmentImpl);
  1047. }
  1048. environmentImplNode = environmentImplNode->next_sibling(nullptr, 0, false);
  1049. }
  1050. if (!envImpls.empty())
  1051. {
  1052. auto newEnvironment = azcreate(CATLAudioEnvironment, (atlEnvironmentId, dataScope, envImpls), Audio::AudioSystemAllocator);
  1053. m_rEnvironments[atlEnvironmentId] = newEnvironment;
  1054. #if !defined(AUDIO_RELEASE)
  1055. m_pDebugNameStore->AddAudioEnvironment(atlEnvironmentId, atlEnvironmentName);
  1056. #endif // !AUDIO_RELEASE
  1057. }
  1058. }
  1059. environmentNode = environmentNode->next_sibling(ATLXmlTags::ATLEnvironmentTag, 0, false);
  1060. }
  1061. }
  1062. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1063. void CATLXmlProcessor::ParseAudioTriggers(const AZ::rapidxml::xml_node<char>* triggersXmlRoot, const EATLDataScope dataScope)
  1064. {
  1065. auto triggerNode = triggersXmlRoot->first_node(ATLXmlTags::ATLTriggerTag, 0, false);
  1066. while (triggerNode)
  1067. {
  1068. auto triggerAttr = triggerNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1069. const char* atlTriggerName = nullptr;
  1070. if (triggerAttr)
  1071. {
  1072. atlTriggerName = triggerAttr->value();
  1073. }
  1074. const auto atlTriggerId = AudioStringToID<TAudioControlID>(atlTriggerName);
  1075. if ((atlTriggerId != INVALID_AUDIO_CONTROL_ID) && (m_rTriggers.find(atlTriggerId) == m_rTriggers.end()))
  1076. {
  1077. CATLTrigger::TImplPtrVec triggerImpls;
  1078. auto triggerImplNode = triggerNode->first_node(nullptr, 0, false);
  1079. while (triggerImplNode)
  1080. {
  1081. IATLTriggerImplData* triggerImplData = nullptr;
  1082. EATLSubsystem receiver = eAS_NONE;
  1083. if (azstricmp(triggerImplNode->name(), ATLXmlTags::ATLTriggerRequestTag) == 0)
  1084. {
  1085. triggerImplData = NewAudioTriggerImplDataInternal(triggerImplNode);
  1086. receiver = eAS_ATL_INTERNAL;
  1087. }
  1088. else
  1089. {
  1090. AudioSystemImplementationRequestBus::BroadcastResult(triggerImplData, &AudioSystemImplementationRequestBus::Events::NewAudioTriggerImplData, triggerImplNode);
  1091. receiver = eAS_AUDIO_SYSTEM_IMPLEMENTATION;
  1092. }
  1093. if (triggerImplData)
  1094. {
  1095. auto triggerImpl = azcreate(CATLTriggerImpl, (++m_nTriggerImplIDCounter, atlTriggerId, receiver, triggerImplData), Audio::AudioSystemAllocator);
  1096. triggerImpls.push_back(triggerImpl);
  1097. }
  1098. triggerImplNode = triggerImplNode->next_sibling(nullptr, 0, false);
  1099. }
  1100. if (!triggerImpls.empty())
  1101. {
  1102. auto newTrigger = azcreate(CATLTrigger, (atlTriggerId, dataScope, triggerImpls), Audio::AudioSystemAllocator);
  1103. m_rTriggers[atlTriggerId] = newTrigger;
  1104. #if !defined(AUDIO_RELEASE)
  1105. m_pDebugNameStore->AddAudioTrigger(atlTriggerId, atlTriggerName);
  1106. #endif // !AUDIO_RELEASE
  1107. }
  1108. }
  1109. triggerNode = triggerNode->next_sibling(ATLXmlTags::ATLTriggerTag, 0, false);
  1110. }
  1111. }
  1112. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1113. void CATLXmlProcessor::ParseAudioSwitches(const AZ::rapidxml::xml_node<char>* switchesXmlRoot, const EATLDataScope dataScope)
  1114. {
  1115. auto switchNode = switchesXmlRoot->first_node(ATLXmlTags::ATLSwitchTag, 0, false);
  1116. while (switchNode)
  1117. {
  1118. auto switchAttr = switchNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1119. const char* atlSwitchName = nullptr;
  1120. if (switchAttr)
  1121. {
  1122. atlSwitchName = switchAttr->value();
  1123. }
  1124. const auto atlSwitchId = AudioStringToID<TAudioControlID>(atlSwitchName);
  1125. if ((atlSwitchId != INVALID_AUDIO_CONTROL_ID) && (m_rSwitches.find(atlSwitchId) == m_rSwitches.end()))
  1126. {
  1127. auto newSwitch = azcreate(CATLSwitch, (atlSwitchId, dataScope), Audio::AudioSystemAllocator);
  1128. #if !defined(AUDIO_RELEASE)
  1129. m_pDebugNameStore->AddAudioSwitch(atlSwitchId, atlSwitchName);
  1130. #endif // !AUDIO_RELEASE
  1131. auto stateNode = switchNode->first_node(ATLXmlTags::ATLSwitchStateTag, 0, false);
  1132. while (stateNode)
  1133. {
  1134. auto stateAttr = stateNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1135. const char* atlStateName = nullptr;
  1136. if (stateAttr)
  1137. {
  1138. atlStateName = stateAttr->value();
  1139. }
  1140. const auto atlStateId = AudioStringToID<TAudioSwitchStateID>(atlStateName);
  1141. if (atlStateId != INVALID_AUDIO_SWITCH_STATE_ID)
  1142. {
  1143. CATLSwitchState::TImplPtrVec switchStateImplVec;
  1144. auto stateImplNode = stateNode->first_node(nullptr, 0, false);
  1145. while (stateImplNode)
  1146. {
  1147. IATLSwitchStateImplData* newSwitchStateImplData = nullptr;
  1148. EATLSubsystem receiver = eAS_NONE;
  1149. const char* stateImplTag = stateImplNode->name();
  1150. if (azstricmp(stateImplTag, ATLXmlTags::ATLSwitchRequestTag) == 0)
  1151. {
  1152. newSwitchStateImplData = NewAudioSwitchStateImplDataInternal(stateImplNode);
  1153. receiver = eAS_ATL_INTERNAL;
  1154. }
  1155. else
  1156. {
  1157. AudioSystemImplementationRequestBus::BroadcastResult(newSwitchStateImplData, &AudioSystemImplementationRequestBus::Events::NewAudioSwitchStateImplData, stateImplNode);
  1158. receiver = eAS_AUDIO_SYSTEM_IMPLEMENTATION;
  1159. }
  1160. if (newSwitchStateImplData)
  1161. {
  1162. auto switchStateImpl = azcreate(CATLSwitchStateImpl, (receiver, newSwitchStateImplData), Audio::AudioSystemAllocator);
  1163. switchStateImplVec.push_back(switchStateImpl);
  1164. }
  1165. stateImplNode = stateImplNode->next_sibling(nullptr, 0, false);
  1166. }
  1167. auto newState = azcreate(CATLSwitchState, (atlSwitchId, atlStateId, switchStateImplVec), Audio::AudioSystemAllocator);
  1168. newSwitch->cStates[atlStateId] = newState;
  1169. #if !defined(AUDIO_RELEASE)
  1170. m_pDebugNameStore->AddAudioSwitchState(atlSwitchId, atlStateId, atlStateName);
  1171. #endif // !AUDIO_RELEASE
  1172. }
  1173. stateNode = stateNode->next_sibling(ATLXmlTags::ATLSwitchStateTag, 0, false);
  1174. }
  1175. m_rSwitches[atlSwitchId] = newSwitch;
  1176. }
  1177. switchNode = switchNode->next_sibling(ATLXmlTags::ATLSwitchTag, 0, false);
  1178. }
  1179. }
  1180. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1181. void CATLXmlProcessor::ParseAudioRtpcs(const AZ::rapidxml::xml_node<char>* rtpcsXmlRoot, const EATLDataScope dataScope)
  1182. {
  1183. auto rtpcNode = rtpcsXmlRoot->first_node(ATLXmlTags::ATLRtpcTag, 0, false);
  1184. while (rtpcNode)
  1185. {
  1186. auto rtpcAttr = rtpcNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1187. const char* atlRtpcName = rtpcAttr->value();
  1188. const auto atlRtpcId = AudioStringToID<TAudioControlID>(atlRtpcName);
  1189. if ((atlRtpcId != INVALID_AUDIO_CONTROL_ID) && (m_rRtpcs.find(atlRtpcId) == m_rRtpcs.end()))
  1190. {
  1191. CATLRtpc::TImplPtrVec rtpcImpls;
  1192. auto rtpcImplNode = rtpcNode->first_node(nullptr, 0, false);
  1193. while (rtpcImplNode)
  1194. {
  1195. IATLRtpcImplData* rtpcImplData = nullptr;
  1196. EATLSubsystem receiver = eAS_NONE;
  1197. if (azstricmp(rtpcImplNode->name(), ATLXmlTags::ATLRtpcRequestTag) == 0)
  1198. {
  1199. rtpcImplData = NewAudioRtpcImplDataInternal(rtpcImplNode);
  1200. receiver = eAS_ATL_INTERNAL;
  1201. }
  1202. else
  1203. {
  1204. AudioSystemImplementationRequestBus::BroadcastResult(rtpcImplData, &AudioSystemImplementationRequestBus::Events::NewAudioRtpcImplData, rtpcImplNode);
  1205. receiver = eAS_AUDIO_SYSTEM_IMPLEMENTATION;
  1206. }
  1207. if (rtpcImplData)
  1208. {
  1209. auto rtpcImpl = azcreate(CATLRtpcImpl, (receiver, rtpcImplData), Audio::AudioSystemAllocator);
  1210. rtpcImpls.push_back(rtpcImpl);
  1211. }
  1212. rtpcImplNode = rtpcImplNode->next_sibling(nullptr, 0, false);
  1213. }
  1214. if (!rtpcImpls.empty())
  1215. {
  1216. auto newRtpc = azcreate(CATLRtpc, (atlRtpcId, dataScope, rtpcImpls), Audio::AudioSystemAllocator);
  1217. m_rRtpcs[atlRtpcId] = newRtpc;
  1218. #if !defined(AUDIO_RELEASE)
  1219. m_pDebugNameStore->AddAudioRtpc(atlRtpcId, atlRtpcName);
  1220. #endif // !AUDIO_RELEASE
  1221. }
  1222. }
  1223. rtpcNode = rtpcNode->next_sibling(ATLXmlTags::ATLRtpcTag, 0, false);
  1224. }
  1225. }
  1226. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1227. IATLTriggerImplData* CATLXmlProcessor::NewAudioTriggerImplDataInternal([[maybe_unused]] const AZ::rapidxml::xml_node<char>* triggerXmlRoot)
  1228. {
  1229. return nullptr;
  1230. }
  1231. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1232. IATLRtpcImplData* CATLXmlProcessor::NewAudioRtpcImplDataInternal([[maybe_unused]] const AZ::rapidxml::xml_node<char>* rtpcXmlRoot)
  1233. {
  1234. return nullptr;
  1235. }
  1236. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1237. IATLSwitchStateImplData* CATLXmlProcessor::NewAudioSwitchStateImplDataInternal(const AZ::rapidxml::xml_node<char>* switchXmlRoot)
  1238. {
  1239. SATLSwitchStateImplData_internal* switchStateImpl = nullptr;
  1240. auto switchNameAttr = switchXmlRoot->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1241. if (switchNameAttr)
  1242. {
  1243. const char* internalSwitchName = switchNameAttr->value();
  1244. auto valueNode = switchXmlRoot->first_node(ATLXmlTags::ATLValueTag, 0, false);
  1245. if (valueNode)
  1246. {
  1247. auto stateNameAttr = valueNode->first_attribute(ATLXmlTags::ATLNameAttribute, 0, false);
  1248. if (stateNameAttr)
  1249. {
  1250. const char* internalStateName = stateNameAttr->value();
  1251. const auto internalSwitchId = AudioStringToID<TAudioControlID>(internalSwitchName);
  1252. const auto internalStateId = AudioStringToID<TAudioSwitchStateID>(internalStateName);
  1253. if (internalSwitchId != INVALID_AUDIO_CONTROL_ID && internalStateId != INVALID_AUDIO_SWITCH_STATE_ID)
  1254. {
  1255. switchStateImpl = azcreate(SATLSwitchStateImplData_internal, (internalSwitchId, internalStateId), Audio::AudioSystemAllocator);
  1256. }
  1257. }
  1258. }
  1259. }
  1260. return switchStateImpl;
  1261. }
  1262. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1263. IATLEnvironmentImplData* CATLXmlProcessor::NewAudioEnvironmentImplDataInternal([[maybe_unused]] const AZ::rapidxml::xml_node<char>* environmentXmlRoot)
  1264. {
  1265. return nullptr;
  1266. }
  1267. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1268. void CATLXmlProcessor::DeleteAudioTrigger(CATLTrigger* const pOldTrigger)
  1269. {
  1270. if (pOldTrigger)
  1271. {
  1272. for (auto const triggerImpl : pOldTrigger->m_cImplPtrs)
  1273. {
  1274. if (triggerImpl->GetReceiver() == eAS_ATL_INTERNAL)
  1275. {
  1276. azdestroy(triggerImpl->m_pImplData, Audio::AudioSystemAllocator);
  1277. }
  1278. else
  1279. {
  1280. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioTriggerImplData, triggerImpl->m_pImplData);
  1281. }
  1282. azdestroy(triggerImpl, Audio::AudioSystemAllocator);
  1283. }
  1284. azdestroy(pOldTrigger, Audio::AudioSystemAllocator);
  1285. }
  1286. }
  1287. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1288. void CATLXmlProcessor::DeleteAudioRtpc(CATLRtpc* const pOldRtpc)
  1289. {
  1290. if (pOldRtpc)
  1291. {
  1292. for (auto const rtpcImpl : pOldRtpc->m_cImplPtrs)
  1293. {
  1294. if (rtpcImpl->GetReceiver() == eAS_ATL_INTERNAL)
  1295. {
  1296. azdestroy(rtpcImpl->m_pImplData, Audio::AudioSystemAllocator);
  1297. }
  1298. else
  1299. {
  1300. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioRtpcImplData, rtpcImpl->m_pImplData);
  1301. }
  1302. azdestroy(rtpcImpl, Audio::AudioSystemAllocator);
  1303. }
  1304. azdestroy(pOldRtpc, Audio::AudioSystemAllocator);
  1305. }
  1306. }
  1307. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1308. void CATLXmlProcessor::DeleteAudioSwitch(CATLSwitch* const pOldSwitch)
  1309. {
  1310. if (pOldSwitch)
  1311. {
  1312. for (auto& statePair : pOldSwitch->cStates)
  1313. {
  1314. auto switchState = statePair.second;
  1315. if (switchState)
  1316. {
  1317. for (auto const stateImpl : switchState->m_cImplPtrs)
  1318. {
  1319. if (stateImpl->GetReceiver() == eAS_ATL_INTERNAL)
  1320. {
  1321. azdestroy(stateImpl->m_pImplData, Audio::AudioSystemAllocator);
  1322. }
  1323. else
  1324. {
  1325. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioSwitchStateImplData, stateImpl->m_pImplData);
  1326. }
  1327. azdestroy(stateImpl, Audio::AudioSystemAllocator);
  1328. }
  1329. azdestroy(switchState, Audio::AudioSystemAllocator);
  1330. }
  1331. }
  1332. azdestroy(pOldSwitch, Audio::AudioSystemAllocator);
  1333. }
  1334. }
  1335. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1336. void CATLXmlProcessor::DeleteAudioPreloadRequest(CATLPreloadRequest* const pOldPreloadRequest)
  1337. {
  1338. if (pOldPreloadRequest)
  1339. {
  1340. const EATLDataScope eScope = pOldPreloadRequest->GetDataScope();
  1341. for (auto preloadFileId : pOldPreloadRequest->m_cFileEntryIDs)
  1342. {
  1343. m_rFileCacheMgr.TryRemoveFileCacheEntry(preloadFileId, eScope);
  1344. }
  1345. azdestroy(pOldPreloadRequest, Audio::AudioSystemAllocator);
  1346. }
  1347. }
  1348. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1349. void CATLXmlProcessor::DeleteAudioEnvironment(CATLAudioEnvironment* const pOldEnvironment)
  1350. {
  1351. if (pOldEnvironment)
  1352. {
  1353. for (auto const environmentImpl : pOldEnvironment->m_cImplPtrs)
  1354. {
  1355. if (environmentImpl->GetReceiver() == eAS_ATL_INTERNAL)
  1356. {
  1357. azdestroy(environmentImpl->m_pImplData, Audio::AudioSystemAllocator);
  1358. }
  1359. else
  1360. {
  1361. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::DeleteAudioEnvironmentImplData, environmentImpl->m_pImplData);
  1362. }
  1363. azdestroy(environmentImpl, Audio::AudioSystemAllocator);
  1364. }
  1365. azdestroy(pOldEnvironment, Audio::AudioSystemAllocator);
  1366. }
  1367. }
  1368. #if !defined(AUDIO_RELEASE)
  1369. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1370. void CAudioEventManager::DrawDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay, float fPosX, float fPosY) const
  1371. {
  1372. static const AZ::Color headerColor{ 1.0f, 1.0f, 1.0f, 0.9f };
  1373. static const AZ::Color itemPlayingColor{ 0.3f, 0.6f, 0.3f, 0.9f };
  1374. static const AZ::Color itemLoadingColor{ 0.9f, 0.2f, 0.2f, 0.9f };
  1375. static const AZ::Color itemOtherColor{ 0.8f, 0.8f, 0.8f, 0.9f };
  1376. const float textSize = 0.8f;
  1377. auto headerStr = AZStd::fixed_string<32>::format("Audio Events [%zu]", m_cActiveAudioEvents.size());
  1378. debugDisplay.SetColor(headerColor);
  1379. debugDisplay.Draw2dTextLabel(fPosX, fPosY, textSize, headerStr.c_str());
  1380. fPosX += 20.0f;
  1381. fPosY += 17.0f;
  1382. auto triggerFilter = static_cast<AZ::CVarFixedString>(Audio::CVars::s_AudioTriggersDebugFilter);
  1383. AZStd::to_lower(triggerFilter.begin(), triggerFilter.end());
  1384. for (auto& audioEventPair : m_cActiveAudioEvents)
  1385. {
  1386. auto const atlEvent = audioEventPair.second;
  1387. AZStd::string triggerName(m_pDebugNameStore->LookupAudioTriggerName(atlEvent->m_nTriggerID));
  1388. AZStd::to_lower(triggerName.begin(), triggerName.end());
  1389. if (AudioDebugDrawFilter(triggerName, triggerFilter))
  1390. {
  1391. if (atlEvent->IsPlaying())
  1392. {
  1393. debugDisplay.SetColor(itemPlayingColor);
  1394. }
  1395. else if (atlEvent->m_audioEventState == eAES_LOADING)
  1396. {
  1397. debugDisplay.SetColor(itemLoadingColor);
  1398. }
  1399. else
  1400. {
  1401. debugDisplay.SetColor(itemOtherColor);
  1402. }
  1403. AZStd::string str = AZStd::string::format(
  1404. "%s (%llu): %s (%llu)", m_pDebugNameStore->LookupAudioObjectName(atlEvent->m_nObjectID), atlEvent->m_nObjectID,
  1405. triggerName.c_str(), atlEvent->GetID());
  1406. debugDisplay.Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1407. fPosY += 16.0f;
  1408. }
  1409. }
  1410. }
  1411. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1412. void CAudioEventManager::SetDebugNameStore(const CATLDebugNameStore* const pDebugNameStore)
  1413. {
  1414. m_pDebugNameStore = pDebugNameStore;
  1415. }
  1416. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1417. size_t CAudioObjectManager::GetNumAudioObjects() const
  1418. {
  1419. return m_cAudioObjects.size();
  1420. }
  1421. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1422. size_t CAudioObjectManager::GetNumActiveAudioObjects() const
  1423. {
  1424. size_t nNumActiveAudioObjects = 0;
  1425. for (auto& audioObjectPair : m_cAudioObjects)
  1426. {
  1427. auto const audioObject = audioObjectPair.second;
  1428. if (audioObject->HasActiveEvents())
  1429. {
  1430. ++nNumActiveAudioObjects;
  1431. }
  1432. }
  1433. return nNumActiveAudioObjects;
  1434. }
  1435. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1436. void CAudioObjectManager::DrawPerObjectDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& rListenerPos) const
  1437. {
  1438. auto audioObjectFilter = static_cast<AZ::CVarFixedString>(Audio::CVars::s_AudioObjectsDebugFilter);
  1439. AZStd::to_lower(audioObjectFilter.begin(), audioObjectFilter.end());
  1440. for (auto& audioObjectPair : m_cAudioObjects)
  1441. {
  1442. auto const audioObject = audioObjectPair.second;
  1443. AZStd::string audioObjectName(m_pDebugNameStore->LookupAudioObjectName(audioObject->GetID()));
  1444. AZStd::to_lower(audioObjectName.begin(), audioObjectName.end());
  1445. bool bDraw = AudioDebugDrawFilter(audioObjectName, audioObjectFilter);
  1446. bDraw = bDraw && (!Audio::CVars::s_ShowActiveAudioObjectsOnly || audioObject->HasActiveEvents());
  1447. if (bDraw)
  1448. {
  1449. audioObject->DrawDebugInfo(debugDisplay, rListenerPos, m_pDebugNameStore);
  1450. }
  1451. }
  1452. }
  1453. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1454. void CAudioObjectManager::DrawDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay, float fPosX, float fPosY) const
  1455. {
  1456. static const AZ::Color headerColor{ 1.0f, 1.0f, 1.0f, 0.9f };
  1457. static const AZ::Color itemActiveColor{ 0.3f, 0.6f, 0.3f, 0.9f };
  1458. static const AZ::Color itemInactiveColor{ 0.8f, 0.8f, 0.8f, 0.9f };
  1459. static const AZ::Color overloadColor{ 1.0f, 0.3f, 0.3f, 0.9f };
  1460. AZStd::string str;
  1461. size_t activeObjects = 0;
  1462. size_t aliveObjects = m_cAudioObjects.size();
  1463. size_t remainingObjects = (m_cObjectPool.m_nReserveSize > aliveObjects ? m_cObjectPool.m_nReserveSize - aliveObjects : 0);
  1464. const float fHeaderPosY = fPosY;
  1465. const float textSize = 0.8f;
  1466. fPosX += 20.0f;
  1467. fPosY += 17.0f;
  1468. auto audioObjectFilter = static_cast<AZ::CVarFixedString>(Audio::CVars::s_AudioObjectsDebugFilter);
  1469. AZStd::to_lower(audioObjectFilter.begin(), audioObjectFilter.end());
  1470. for (auto& audioObjectPair : m_cAudioObjects)
  1471. {
  1472. auto const audioObject = audioObjectPair.second;
  1473. AZStd::string audioObjectName(m_pDebugNameStore->LookupAudioObjectName(audioObject->GetID()));
  1474. AZStd::to_lower(audioObjectName.begin(), audioObjectName.end());
  1475. bool bDraw = AudioDebugDrawFilter(audioObjectName, audioObjectFilter);
  1476. bool hasActiveEvents = audioObject->HasActiveEvents();
  1477. bDraw = bDraw && (!Audio::CVars::s_ShowActiveAudioObjectsOnly || hasActiveEvents);
  1478. if (bDraw)
  1479. {
  1480. const AZ::Vector3 position(audioObject->GetPosition().GetPositionVec());
  1481. SATLSoundPropagationData propData;
  1482. audioObject->GetObstOccData(propData);
  1483. str = AZStd::string::format(
  1484. "[%.2f %.2f %.2f] (ID: %llu Obst: %.2f Occl: %.2f): %s",
  1485. position.GetX(), position.GetY(), position.GetZ(), audioObject->GetID(),
  1486. propData.fObstruction, propData.fOcclusion, audioObjectName.c_str());
  1487. debugDisplay.SetColor(hasActiveEvents ? itemActiveColor : itemInactiveColor);
  1488. debugDisplay.Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1489. fPosY += 16.0f;
  1490. }
  1491. if (hasActiveEvents)
  1492. {
  1493. ++activeObjects;
  1494. }
  1495. }
  1496. static const char* headerFormat = "Audio Objects [Active : %3zu | Alive: %3zu | Pool: %3zu | Remaining: %3zu]";
  1497. const bool overloaded = (m_cAudioObjects.size() > m_cObjectPool.m_nReserveSize);
  1498. str = AZStd::string::format(headerFormat, activeObjects, aliveObjects,
  1499. m_cObjectPool.m_nReserveSize, remainingObjects);
  1500. debugDisplay.SetColor(overloaded ? overloadColor : headerColor);
  1501. debugDisplay.Draw2dTextLabel(fPosX, fHeaderPosY, textSize, str.c_str());
  1502. }
  1503. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1504. void CAudioObjectManager::SetDebugNameStore(CATLDebugNameStore* const pDebugNameStore)
  1505. {
  1506. m_pDebugNameStore = pDebugNameStore;
  1507. }
  1508. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1509. void CATLXmlProcessor::SetDebugNameStore(CATLDebugNameStore* const pDebugNameStore)
  1510. {
  1511. m_pDebugNameStore = pDebugNameStore;
  1512. }
  1513. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1514. void CATLXmlProcessor::SetRootPath(const char* path)
  1515. {
  1516. if (path && path[0] != '\0')
  1517. {
  1518. m_rootPath = path;
  1519. }
  1520. }
  1521. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1522. void CAudioListenerManager::DrawDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay) const
  1523. {
  1524. static const AZ::Color audioListenerColor(0.2f, 0.6f, 0.9f, 0.9f);
  1525. static const AZ::Color xAxisColor(1.f, 0.f, 0.f, 0.9f);
  1526. static const AZ::Color yAxisColor(0.f, 1.f, 0.f, 0.9f);
  1527. static const AZ::Color zAxisColor(0.f, 0.f, 1.f, 0.9f);
  1528. if (m_pDefaultListenerObject)
  1529. {
  1530. AZ::Vector3 vListenerPos = m_pDefaultListenerObject->oPosition.GetPositionVec();
  1531. // Draw Axes...
  1532. debugDisplay.SetColor(xAxisColor);
  1533. debugDisplay.DrawLine(vListenerPos, vListenerPos + m_pDefaultListenerObject->oPosition.GetRightVec());
  1534. debugDisplay.SetColor(yAxisColor);
  1535. debugDisplay.DrawLine(vListenerPos, vListenerPos + m_pDefaultListenerObject->oPosition.GetForwardVec());
  1536. debugDisplay.SetColor(zAxisColor);
  1537. debugDisplay.DrawLine(vListenerPos, vListenerPos + m_pDefaultListenerObject->oPosition.GetUpVec());
  1538. // Draw Sphere...
  1539. const float radius = 0.05f; // 0.15 meters
  1540. debugDisplay.SetColor(audioListenerColor);
  1541. debugDisplay.DrawWireSphere(vListenerPos, radius);
  1542. }
  1543. }
  1544. #endif // !AUDIO_RELEASE
  1545. } // namespace Audio