ATLComponents.cpp 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  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