ATL.cpp 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055
  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 <ATL.h>
  9. #include <AzCore/Console/ILogger.h>
  10. #include <AzCore/Debug/Profiler.h>
  11. #include <AzCore/StringFunc/StringFunc.h>
  12. #include <SoundCVars.h>
  13. #include <AudioProxy.h>
  14. #include <ATLAudioObject.h>
  15. #include <IAudioSystemImplementation.h>
  16. #if !defined(AUDIO_RELEASE)
  17. // Debug Draw
  18. #include <AzCore/Math/Color.h>
  19. #include <AzFramework/Entity/EntityDebugDisplayBus.h>
  20. #endif // !AUDIO_RELEASE
  21. namespace Audio
  22. {
  23. ///////////////////////////////////////////////////////////////////////////////////////////////////
  24. inline EAudioRequestResult ConvertToRequestResult(const EAudioRequestStatus eAudioRequestStatus)
  25. {
  26. return (eAudioRequestStatus == EAudioRequestStatus::Success) ? EAudioRequestResult::Success : EAudioRequestResult::Failure;
  27. }
  28. ///////////////////////////////////////////////////////////////////////////////////////////////////
  29. CAudioTranslationLayer::CAudioTranslationLayer()
  30. : m_pGlobalAudioObject(nullptr)
  31. , m_nGlobalAudioObjectID(GLOBAL_AUDIO_OBJECT_ID)
  32. , m_nTriggerInstanceIDCounter(1)
  33. , m_nextSourceId(INVALID_AUDIO_SOURCE_ID)
  34. , m_oAudioEventMgr()
  35. , m_oAudioObjectMgr(m_oAudioEventMgr)
  36. , m_oAudioListenerMgr()
  37. , m_oFileCacheMgr(m_cPreloadRequests)
  38. , m_oXmlProcessor(m_cTriggers, m_cRtpcs, m_cSwitches, m_cEnvironments, m_cPreloadRequests, m_oFileCacheMgr)
  39. , m_nFlags(eAIS_NONE)
  40. {
  41. if (GetISystem() && GetISystem()->GetISystemEventDispatcher())
  42. {
  43. GetISystem()->GetISystemEventDispatcher()->RegisterListener(this);
  44. }
  45. #if !defined(AUDIO_RELEASE)
  46. m_oAudioEventMgr.SetDebugNameStore(&m_oDebugNameStore);
  47. m_oAudioObjectMgr.SetDebugNameStore(&m_oDebugNameStore);
  48. m_oXmlProcessor.SetDebugNameStore(&m_oDebugNameStore);
  49. #endif // !AUDIO_RELEASE
  50. }
  51. ///////////////////////////////////////////////////////////////////////////////////////////////////
  52. CAudioTranslationLayer::~CAudioTranslationLayer()
  53. {
  54. // By the time ATL is being destroyed, ReleaseImplComponent should have been called already
  55. // to release the implementation object. See CAudioSystem::Release().
  56. if (GetISystem() && GetISystem()->GetISystemEventDispatcher())
  57. {
  58. GetISystem()->GetISystemEventDispatcher()->RemoveListener(this);
  59. }
  60. }
  61. ///////////////////////////////////////////////////////////////////////////////////////////////////
  62. bool CAudioTranslationLayer::Initialize()
  63. {
  64. m_lastUpdateTime = AZStd::chrono::steady_clock::now();
  65. return true;
  66. }
  67. ///////////////////////////////////////////////////////////////////////////////////////////////////
  68. bool CAudioTranslationLayer::ShutDown()
  69. {
  70. return true;
  71. }
  72. ///////////////////////////////////////////////////////////////////////////////////////////////////
  73. void CAudioTranslationLayer::Update()
  74. {
  75. AZ_PROFILE_FUNCTION(Audio);
  76. auto current = AZStd::chrono::steady_clock::now();
  77. m_elapsedTime = AZStd::chrono::duration_cast<duration_ms>(current - m_lastUpdateTime);
  78. m_lastUpdateTime = current;
  79. float elapsedMs = m_elapsedTime.count();
  80. UpdateSharedData();
  81. m_oAudioObjectMgr.Update(elapsedMs, m_oSharedData.m_oActiveListenerPosition);
  82. m_oFileCacheMgr.Update();
  83. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::Update, elapsedMs);
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////////////////////////
  86. void CAudioTranslationLayer::ProcessRequest(AudioRequestVariant&& requestVariant)
  87. {
  88. bool hasCallback = false;
  89. EAudioRequestStatus status = AZStd::visit(
  90. [this, &hasCallback]([[maybe_unused]] auto&& request) -> EAudioRequestStatus
  91. {
  92. EAudioRequestStatus result = EAudioRequestStatus::None;
  93. request.m_status = EAudioRequestStatus::Pending;
  94. using T = AZStd::decay_t<decltype(request)>;
  95. // ... System ...
  96. if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::Initialize>)
  97. {
  98. result = InitializeImplComponent();
  99. // Immediately release the impl if it failed to init...
  100. if (result != EAudioRequestStatus::Success)
  101. {
  102. ReleaseImplComponent();
  103. }
  104. }
  105. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::Shutdown>)
  106. {
  107. ReleaseImplComponent();
  108. result = EAudioRequestStatus::Success;
  109. }
  110. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::ReserveObject>)
  111. {
  112. result = BoolToARS(
  113. ReserveAudioObjectID(request.m_objectId, request.m_objectName.empty() ? nullptr : request.m_objectName.c_str()));
  114. }
  115. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::CreateSource>)
  116. {
  117. bool created = false;
  118. AudioSystemImplementationRequestBus::BroadcastResult(
  119. created, &AudioSystemImplementationRequestBus::Events::CreateAudioSource, request.m_sourceConfig);
  120. result = BoolToARS(created);
  121. }
  122. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::DestroySource>)
  123. {
  124. AudioSystemImplementationRequestBus::Broadcast(
  125. &AudioSystemImplementationRequestBus::Events::DestroyAudioSource, request.m_sourceId);
  126. result = EAudioRequestStatus::Success;
  127. }
  128. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::LoadControls>)
  129. {
  130. result = ParseControlsData(request.m_controlsPath.c_str(), request.m_scope);
  131. }
  132. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::UnloadControls>)
  133. {
  134. result = ClearControlsData(request.m_scope);
  135. }
  136. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::LoadBank>)
  137. {
  138. result = m_oFileCacheMgr.TryLoadRequest(request.m_preloadRequestId, !request.m_asyncLoad, request.m_autoLoadOnly);
  139. }
  140. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::UnloadBank>)
  141. {
  142. result = m_oFileCacheMgr.TryUnloadRequest(request.m_preloadRequestId);
  143. }
  144. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::UnloadBanksByScope>)
  145. {
  146. result = m_oFileCacheMgr.UnloadDataByScope(request.m_scope);
  147. }
  148. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::ReloadAll>)
  149. {
  150. result = RefreshAudioSystem(request.m_controlsPath.c_str(), request.m_levelName.c_str(), request.m_levelPreloadId);
  151. }
  152. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::LoseFocus>)
  153. {
  154. result = LoseFocus();
  155. }
  156. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::GetFocus>)
  157. {
  158. result = GetFocus();
  159. }
  160. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::MuteAll>)
  161. {
  162. result = MuteAll();
  163. }
  164. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::UnmuteAll>)
  165. {
  166. result = UnmuteAll();
  167. }
  168. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::StopAllAudio>)
  169. {
  170. AudioSystemImplementationRequestBus::BroadcastResult(
  171. result, &AudioSystemImplementationRequestBus::Events::StopAllSounds);
  172. }
  173. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::DrawDebug>)
  174. {
  175. #if !defined(AUDIO_RELEASE)
  176. DrawAudioSystemDebugInfo();
  177. result = EAudioRequestStatus::Success;
  178. #endif // !AUDIO_RELEASE
  179. }
  180. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::ChangeLanguage>)
  181. {
  182. SetImplLanguage();
  183. m_oFileCacheMgr.UpdateLocalizedFileCacheEntries();
  184. result = EAudioRequestStatus::Success;
  185. }
  186. else if constexpr (AZStd::is_same_v<T, Audio::SystemRequest::SetPanningMode>)
  187. {
  188. AudioSystemImplementationRequestBus::Broadcast(
  189. &AudioSystemImplementationRequestBus::Events::SetPanningMode, request.m_panningMode);
  190. result = EAudioRequestStatus::Success;
  191. }
  192. // ... Object ...
  193. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::ExecuteTrigger>)
  194. {
  195. auto audioObject = GetRequestObject(request.m_audioObjectId);
  196. if (!audioObject)
  197. {
  198. result = EAudioRequestStatus::FailureInvalidObjectId;
  199. }
  200. else if (auto it = m_cTriggers.find(request.m_triggerId); it != m_cTriggers.end())
  201. {
  202. result = ActivateTrigger(audioObject, it->second, request.m_owner);
  203. }
  204. else
  205. {
  206. result = EAudioRequestStatus::FailureInvalidControlId;
  207. }
  208. }
  209. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::ExecuteSourceTrigger>)
  210. {
  211. auto audioObject = GetRequestObject(request.m_audioObjectId);
  212. if (!audioObject)
  213. {
  214. result = EAudioRequestStatus::FailureInvalidObjectId;
  215. }
  216. else if (auto it = m_cTriggers.find(request.m_triggerId); it != m_cTriggers.end())
  217. {
  218. SATLSourceData sourceData(request.m_sourceInfo);
  219. result = ActivateTrigger(audioObject, it->second, request.m_owner, &sourceData);
  220. }
  221. else
  222. {
  223. result = EAudioRequestStatus::FailureInvalidControlId;
  224. }
  225. }
  226. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::PrepareTrigger>)
  227. {
  228. auto audioObject = GetRequestObject(request.m_audioObjectId);
  229. if (!audioObject)
  230. {
  231. result = EAudioRequestStatus::FailureInvalidObjectId;
  232. }
  233. else if (auto it = m_cTriggers.find(request.m_triggerId); it != m_cTriggers.end())
  234. {
  235. result = PrepUnprepTriggerAsync(audioObject, it->second, true);
  236. }
  237. else
  238. {
  239. result = EAudioRequestStatus::FailureInvalidControlId;
  240. }
  241. }
  242. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::UnprepareTrigger>)
  243. {
  244. auto audioObject = GetRequestObject(request.m_audioObjectId);
  245. if (!audioObject)
  246. {
  247. result = EAudioRequestStatus::FailureInvalidObjectId;
  248. }
  249. else if (auto it = m_cTriggers.find(request.m_triggerId); it != m_cTriggers.end())
  250. {
  251. result = PrepUnprepTriggerAsync(audioObject, it->second, false);
  252. }
  253. else
  254. {
  255. result = EAudioRequestStatus::FailureInvalidControlId;
  256. }
  257. }
  258. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::StopTrigger>)
  259. {
  260. auto audioObject = GetRequestObject(request.m_audioObjectId);
  261. if (!audioObject)
  262. {
  263. result = EAudioRequestStatus::FailureInvalidObjectId;
  264. }
  265. else if (auto it = m_cTriggers.find(request.m_triggerId); it != m_cTriggers.end())
  266. {
  267. result = StopTrigger(audioObject, it->second);
  268. }
  269. else
  270. {
  271. result = EAudioRequestStatus::FailureInvalidControlId;
  272. }
  273. }
  274. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::StopAllTriggers>)
  275. {
  276. auto audioObject = GetRequestObject(request.m_audioObjectId);
  277. if (!audioObject)
  278. {
  279. result = EAudioRequestStatus::FailureInvalidObjectId;
  280. }
  281. else
  282. {
  283. result = StopAllTriggers(audioObject, request.m_filterByOwner ? request.m_owner : nullptr);
  284. }
  285. }
  286. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::SetPosition>)
  287. {
  288. auto audioObject = GetRequestObject(request.m_audioObjectId);
  289. if (!audioObject)
  290. {
  291. result = EAudioRequestStatus::FailureInvalidObjectId;
  292. }
  293. else if (audioObject->HasPosition())
  294. {
  295. auto const positionalObject = static_cast<CATLAudioObject*>(audioObject);
  296. AudioSystemImplementationRequestBus::BroadcastResult(
  297. result, &AudioSystemImplementationRequestBus::Events::SetPosition, positionalObject->GetImplDataPtr(),
  298. request.m_position);
  299. if (result == EAudioRequestStatus::Success)
  300. {
  301. positionalObject->SetPosition(request.m_position);
  302. }
  303. }
  304. else
  305. {
  306. AZLOG_DEBUG("ATL received a request to set position on the Global Audio Object!");
  307. result = EAudioRequestStatus::FailureInvalidObjectId;
  308. }
  309. }
  310. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::SetParameterValue>)
  311. {
  312. auto audioObject = GetRequestObject(request.m_audioObjectId);
  313. if (!audioObject)
  314. {
  315. result = EAudioRequestStatus::FailureInvalidObjectId;
  316. }
  317. else if (auto it = m_cRtpcs.find(request.m_parameterId); it != m_cRtpcs.end())
  318. {
  319. result = SetRtpc(audioObject, it->second, request.m_value);
  320. }
  321. else
  322. {
  323. result = EAudioRequestStatus::FailureInvalidControlId;
  324. }
  325. }
  326. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::SetSwitchValue>)
  327. {
  328. auto audioObject = GetRequestObject(request.m_audioObjectId);
  329. if (!audioObject)
  330. {
  331. result = EAudioRequestStatus::FailureInvalidObjectId;
  332. }
  333. else if (auto itSwitch = m_cSwitches.find(request.m_switchId); itSwitch != m_cSwitches.end())
  334. {
  335. if (auto itState = itSwitch->second->cStates.find(request.m_stateId);
  336. itState != itSwitch->second->cStates.end())
  337. {
  338. result = SetSwitchState(audioObject, itState->second);
  339. }
  340. else
  341. {
  342. result = EAudioRequestStatus::FailureInvalidControlId;
  343. }
  344. }
  345. else
  346. {
  347. result = EAudioRequestStatus::FailureInvalidControlId;
  348. }
  349. }
  350. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::SetEnvironmentValue>)
  351. {
  352. auto audioObject = GetRequestObject(request.m_audioObjectId);
  353. if (!audioObject)
  354. {
  355. result = EAudioRequestStatus::FailureInvalidObjectId;
  356. }
  357. else if (audioObject->HasPosition())
  358. {
  359. if (auto it = m_cEnvironments.find(request.m_environmentId);
  360. it != m_cEnvironments.end())
  361. {
  362. result = SetEnvironment(audioObject, it->second, request.m_value);
  363. }
  364. else
  365. {
  366. result = EAudioRequestStatus::FailureInvalidControlId;
  367. }
  368. }
  369. else
  370. {
  371. AZLOG_DEBUG("ATL received a request to set environment value on the Global Audio Object!");
  372. result = EAudioRequestStatus::FailureInvalidObjectId;
  373. }
  374. }
  375. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::ResetParameters>)
  376. {
  377. auto audioObject = GetRequestObject(request.m_audioObjectId);
  378. if (!audioObject)
  379. {
  380. result = EAudioRequestStatus::FailureInvalidObjectId;
  381. }
  382. else
  383. {
  384. result = ResetRtpcs(audioObject);
  385. }
  386. }
  387. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::ResetEnvironments>)
  388. {
  389. auto audioObject = GetRequestObject(request.m_audioObjectId);
  390. if (!audioObject)
  391. {
  392. result = EAudioRequestStatus::FailureInvalidObjectId;
  393. }
  394. else
  395. {
  396. result = ResetEnvironments(audioObject);
  397. }
  398. }
  399. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::Release>)
  400. {
  401. if (request.m_audioObjectId != m_nGlobalAudioObjectID)
  402. {
  403. result = BoolToARS(ReleaseAudioObjectID(request.m_audioObjectId));
  404. }
  405. else
  406. {
  407. AZLOG_DEBUG("ATL received a request to release the Global Audio Object!");
  408. result = EAudioRequestStatus::FailureInvalidObjectId;
  409. }
  410. }
  411. else if constexpr (AZStd::is_same_v<T, Audio::ObjectRequest::SetMultiplePositions>)
  412. {
  413. auto audioObject = GetRequestObject(request.m_audioObjectId);
  414. if (!audioObject)
  415. {
  416. result = EAudioRequestStatus::FailureInvalidObjectId;
  417. }
  418. else if (audioObject->HasPosition())
  419. {
  420. auto const positionalObject = static_cast<CATLAudioObject*>(audioObject);
  421. AudioSystemImplementationRequestBus::BroadcastResult(
  422. result, &AudioSystemImplementationRequestBus::Events::SetMultiplePositions, positionalObject->GetImplDataPtr(),
  423. request.m_params);
  424. if (result == EAudioRequestStatus::Success)
  425. {
  426. // This is odd, why is this being done? Because the source of positional information is elsewhere?
  427. positionalObject->SetPosition(SATLWorldPosition());
  428. }
  429. }
  430. else
  431. {
  432. AZLOG_DEBUG("ATL received a request to set multiple positions on the Global Audio Object!");
  433. result = EAudioRequestStatus::FailureInvalidObjectId;
  434. }
  435. }
  436. // ... Callback ...
  437. else if constexpr (AZStd::is_same_v<T, Audio::CallbackRequest::ReportFinishedEvent>)
  438. {
  439. if (CATLEvent* atlEvent = m_oAudioEventMgr.LookupID(request.m_eventId);
  440. atlEvent != nullptr)
  441. {
  442. if (atlEvent->m_nObjectID != m_nGlobalAudioObjectID)
  443. {
  444. m_oAudioObjectMgr.ReportEventFinished(atlEvent);
  445. }
  446. else if (m_pGlobalAudioObject)
  447. {
  448. m_pGlobalAudioObject->EventFinished(atlEvent);
  449. }
  450. m_oAudioEventMgr.ReleaseEvent(atlEvent);
  451. }
  452. result = EAudioRequestStatus::Success;
  453. }
  454. // ... Listener ...
  455. else if constexpr (AZStd::is_same_v<T, Audio::ListenerRequest::SetWorldTransform>)
  456. {
  457. TAudioObjectID listenerId = INVALID_AUDIO_OBJECT_ID;
  458. TAudioObjectID overrideId = m_oAudioListenerMgr.GetOverrideListenerID();
  459. if (request.m_audioObjectId == overrideId
  460. || request.m_audioObjectId == INVALID_AUDIO_OBJECT_ID)
  461. {
  462. listenerId = m_oAudioListenerMgr.GetDefaultListenerID();
  463. }
  464. else
  465. {
  466. listenerId = request.m_audioObjectId;
  467. }
  468. if (CATLListenerObject* listener = m_oAudioListenerMgr.LookupID(listenerId); listener != nullptr)
  469. {
  470. AudioSystemImplementationRequestBus::BroadcastResult(
  471. result, &AudioSystemImplementationRequestBus::Events::SetListenerPosition, listener->m_pImplData,
  472. request.m_transform);
  473. if (result == EAudioRequestStatus::Success)
  474. {
  475. listener->oPosition = request.m_transform;
  476. }
  477. }
  478. else
  479. {
  480. AZLOG_DEBUG("ATL could not find listener with ID %llu", listenerId);
  481. result = EAudioRequestStatus::FailureInvalidObjectId;
  482. }
  483. }
  484. else
  485. {
  486. static_assert(AZStd::is_void_v<T>, "AudioRequestVariant visitor is non-exhaustive across all variant types!");
  487. result = EAudioRequestStatus::FailureInvalidRequest;
  488. }
  489. request.m_status = result;
  490. if (request.m_callback)
  491. {
  492. if (0 != (request.m_flags & eARF_SYNC_CALLBACK))
  493. {
  494. request.m_callback(request);
  495. }
  496. else
  497. {
  498. hasCallback = true;
  499. }
  500. }
  501. return result;
  502. }
  503. , requestVariant);
  504. if (auto audioSystem = AZ::Interface<IAudioSystem>::Get();
  505. audioSystem != nullptr && hasCallback)
  506. {
  507. audioSystem->PushCallback(AZStd::move(requestVariant));
  508. }
  509. if (status != EAudioRequestStatus::Success)
  510. {
  511. AZLOG_DEBUG("Audio Request did not succeed!");
  512. }
  513. }
  514. ///////////////////////////////////////////////////////////////////////////////////////////////////
  515. TAudioControlID CAudioTranslationLayer::GetAudioTriggerID(const char* const audioTriggerName) const
  516. {
  517. auto triggerId = AudioStringToID<TAudioControlID>(audioTriggerName);
  518. auto it = m_cTriggers.find(triggerId);
  519. if (it == m_cTriggers.end())
  520. {
  521. return INVALID_AUDIO_CONTROL_ID;
  522. }
  523. return triggerId;
  524. }
  525. ///////////////////////////////////////////////////////////////////////////////////////////////////
  526. TAudioControlID CAudioTranslationLayer::GetAudioRtpcID(const char* const audioRtpcName) const
  527. {
  528. auto rtpcId = AudioStringToID<TAudioControlID>(audioRtpcName);
  529. auto it = m_cRtpcs.find(rtpcId);
  530. if (it == m_cRtpcs.end())
  531. {
  532. return INVALID_AUDIO_CONTROL_ID;
  533. }
  534. return rtpcId;
  535. }
  536. ///////////////////////////////////////////////////////////////////////////////////////////////////
  537. TAudioControlID CAudioTranslationLayer::GetAudioSwitchID(const char* const audioStateName) const
  538. {
  539. auto switchId = AudioStringToID<TAudioControlID>(audioStateName);
  540. auto it = m_cSwitches.find(switchId);
  541. if (it == m_cSwitches.end())
  542. {
  543. return INVALID_AUDIO_CONTROL_ID;
  544. }
  545. return switchId;
  546. }
  547. ///////////////////////////////////////////////////////////////////////////////////////////////////
  548. TAudioSwitchStateID CAudioTranslationLayer::GetAudioSwitchStateID(const TAudioControlID switchId, const char* const audioSwitchStateName) const
  549. {
  550. auto stateId = AudioStringToID<TAudioSwitchStateID>(audioSwitchStateName);
  551. auto itSwitch = m_cSwitches.find(switchId);
  552. if (itSwitch != m_cSwitches.end())
  553. {
  554. auto itState = itSwitch->second->cStates.find(stateId);
  555. if (itState == itSwitch->second->cStates.end())
  556. {
  557. return INVALID_AUDIO_SWITCH_STATE_ID;
  558. }
  559. }
  560. return stateId;
  561. }
  562. ///////////////////////////////////////////////////////////////////////////////////////////////////
  563. TAudioPreloadRequestID CAudioTranslationLayer::GetAudioPreloadRequestID(const char* const audioPreloadRequestName) const
  564. {
  565. auto preloadRequestId = AudioStringToID<TAudioPreloadRequestID>(audioPreloadRequestName);
  566. auto it = m_cPreloadRequests.find(preloadRequestId);
  567. if (it == m_cPreloadRequests.end())
  568. {
  569. return INVALID_AUDIO_PRELOAD_REQUEST_ID;
  570. }
  571. return preloadRequestId;
  572. }
  573. ///////////////////////////////////////////////////////////////////////////////////////////////////
  574. TAudioEnvironmentID CAudioTranslationLayer::GetAudioEnvironmentID(const char* const audioEnvironmentName) const
  575. {
  576. auto environmentId = AudioStringToID<TAudioEnvironmentID>(audioEnvironmentName);
  577. auto it = m_cEnvironments.find(environmentId);
  578. if (it == m_cEnvironments.end())
  579. {
  580. return INVALID_AUDIO_ENVIRONMENT_ID;
  581. }
  582. return environmentId;
  583. }
  584. ///////////////////////////////////////////////////////////////////////////////////////////////////
  585. bool CAudioTranslationLayer::ReserveAudioObjectID(TAudioObjectID& rAudioObjectID, const char* const sAudioObjectName)
  586. {
  587. const bool bSuccess = m_oAudioObjectMgr.ReserveID(rAudioObjectID, sAudioObjectName);
  588. #if !defined(AUDIO_RELEASE)
  589. if (bSuccess && sAudioObjectName && sAudioObjectName[0] != '\0')
  590. {
  591. m_oDebugNameStore.AddAudioObject(rAudioObjectID, sAudioObjectName);
  592. }
  593. #endif // !AUDIO_RELEASE
  594. return bSuccess;
  595. }
  596. ///////////////////////////////////////////////////////////////////////////////////////////////////
  597. bool CAudioTranslationLayer::ReleaseAudioObjectID(const TAudioObjectID nAudioObjectID)
  598. {
  599. const bool bSuccess = m_oAudioObjectMgr.ReleaseID(nAudioObjectID);
  600. #if !defined(AUDIO_RELEASE)
  601. if (bSuccess)
  602. {
  603. m_oDebugNameStore.RemoveAudioObject(nAudioObjectID);
  604. }
  605. #endif // !AUDIO_RELEASE
  606. return bSuccess;
  607. }
  608. ///////////////////////////////////////////////////////////////////////////////////////////////////
  609. bool CAudioTranslationLayer::ReserveAudioListenerID(TAudioObjectID& rAudioObjectID)
  610. {
  611. return m_oAudioListenerMgr.ReserveID(rAudioObjectID);
  612. }
  613. ///////////////////////////////////////////////////////////////////////////////////////////////////
  614. bool CAudioTranslationLayer::ReleaseAudioListenerID(const TAudioObjectID nAudioObjectID)
  615. {
  616. return m_oAudioListenerMgr.ReleaseID(nAudioObjectID);
  617. }
  618. ///////////////////////////////////////////////////////////////////////////////////////////////////
  619. bool CAudioTranslationLayer::SetAudioListenerOverrideID(const TAudioObjectID nAudioObjectID)
  620. {
  621. return m_oAudioListenerMgr.SetOverrideListenerID(nAudioObjectID);
  622. }
  623. ///////////////////////////////////////////////////////////////////////////////////////////////////
  624. EAudioRequestStatus CAudioTranslationLayer::ParseControlsData(const char* const pConfigFolderPath, const EATLDataScope eDataScope)
  625. {
  626. m_oXmlProcessor.ParseControlsData(pConfigFolderPath, eDataScope);
  627. m_oXmlProcessor.ParsePreloadsData(pConfigFolderPath, eDataScope);
  628. return EAudioRequestStatus::Success;
  629. }
  630. ///////////////////////////////////////////////////////////////////////////////////////////////////
  631. EAudioRequestStatus CAudioTranslationLayer::ClearControlsData(const EATLDataScope eDataScope)
  632. {
  633. m_oXmlProcessor.ClearControlsData(eDataScope);
  634. m_oXmlProcessor.ClearPreloadsData(eDataScope);
  635. return EAudioRequestStatus::Success;
  636. }
  637. ///////////////////////////////////////////////////////////////////////////////////////////////////
  638. const AZStd::string& CAudioTranslationLayer::GetControlsImplSubPath() const
  639. {
  640. return m_implSubPath;
  641. }
  642. ///////////////////////////////////////////////////////////////////////////////////////////////////
  643. TAudioSourceId CAudioTranslationLayer::CreateAudioSource(const SAudioInputConfig& sourceConfig)
  644. {
  645. AZ_Assert(sourceConfig.m_sourceId == INVALID_AUDIO_SOURCE_ID, "ATL - Request to CreateAudioSource already contains a valid source Id.\n");
  646. TAudioSourceId sourceId = ++m_nextSourceId;
  647. Audio::SystemRequest::CreateSource createSourceRequest(sourceConfig);
  648. createSourceRequest.m_sourceConfig.m_sourceId = sourceId;
  649. AZ::Interface<IAudioSystem>::Get()->PushRequestBlocking(AZStd::move(createSourceRequest));
  650. return sourceId;
  651. }
  652. ///////////////////////////////////////////////////////////////////////////////////////////////////
  653. void CAudioTranslationLayer::DestroyAudioSource([[maybe_unused]] TAudioSourceId sourceId)
  654. {
  655. Audio::SystemRequest::DestroySource destroySourceRequest(sourceId);
  656. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(destroySourceRequest));
  657. }
  658. ///////////////////////////////////////////////////////////////////////////////////////////////////
  659. EAudioRequestStatus CAudioTranslationLayer::InitializeImplComponent()
  660. {
  661. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  662. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::Initialize);
  663. if (eResult == EAudioRequestStatus::Success)
  664. {
  665. IATLAudioObjectData* pGlobalObjectData = nullptr;
  666. AudioSystemImplementationRequestBus::BroadcastResult(
  667. pGlobalObjectData, &AudioSystemImplementationRequestBus::Events::NewGlobalAudioObjectData, m_nGlobalAudioObjectID);
  668. m_pGlobalAudioObject = azcreate(
  669. CATLGlobalAudioObject, (m_nGlobalAudioObjectID, pGlobalObjectData), Audio::AudioSystemAllocator);
  670. m_oAudioListenerMgr.Initialize();
  671. m_oAudioObjectMgr.Initialize();
  672. m_oAudioEventMgr.Initialize();
  673. m_oFileCacheMgr.Initialize();
  674. SetImplLanguage();
  675. // Update the implementation subpath for locating ATL controls...
  676. AudioSystemImplementationRequestBus::BroadcastResult(
  677. m_implSubPath, &AudioSystemImplementationRequestBus::Events::GetImplSubPath);
  678. }
  679. #if !defined(AUDIO_RELEASE)
  680. else
  681. {
  682. const char* implementationName = nullptr;
  683. AudioSystemImplementationRequestBus::BroadcastResult(
  684. implementationName, &AudioSystemImplementationRequestBus::Events::GetImplementationNameString);
  685. AZLOG_ERROR("Failed to initialize the AudioSystemImplementation '%s'", implementationName);
  686. }
  687. #endif // !AUDIO_RELEASE
  688. return eResult;
  689. }
  690. ///////////////////////////////////////////////////////////////////////////////////////////////////
  691. void CAudioTranslationLayer::ReleaseImplComponent()
  692. {
  693. // During audio middleware shutdown we do not allow for any new requests originating from the "dying" audio middleware!
  694. m_nFlags |= eAIS_AUDIO_MIDDLEWARE_SHUTTING_DOWN;
  695. m_oXmlProcessor.ClearControlsData(eADS_ALL);
  696. m_oXmlProcessor.ClearPreloadsData(eADS_ALL);
  697. if (m_pGlobalAudioObject)
  698. {
  699. AudioSystemImplementationRequestBus::Broadcast(
  700. &AudioSystemImplementationRequestBus::Events::DeleteAudioObjectData, m_pGlobalAudioObject->GetImplDataPtr());
  701. azdestroy(m_pGlobalAudioObject, Audio::AudioSystemAllocator);
  702. m_pGlobalAudioObject = nullptr;
  703. }
  704. m_oAudioListenerMgr.Release();
  705. m_oAudioObjectMgr.Release();
  706. m_oAudioEventMgr.Release();
  707. m_oFileCacheMgr.Release();
  708. m_implSubPath.clear();
  709. if (AudioSystemImplementationRequestBus::HasHandlers())
  710. {
  711. EAudioRequestStatus result = EAudioRequestStatus::Failure;
  712. AudioSystemImplementationRequestBus::BroadcastResult(result, &AudioSystemImplementationRequestBus::Events::ShutDown);
  713. AZ_Error("ATL", result == EAudioRequestStatus::Success,
  714. "ATL ReleaseImplComponent - Shutting down the audio implementation failed!");
  715. AudioSystemImplementationRequestBus::BroadcastResult(result, &AudioSystemImplementationRequestBus::Events::Release);
  716. AZ_Error("ATL", result == EAudioRequestStatus::Success,
  717. "ATL ReleaseImplComponent - Releasing the audio implementation failed!");
  718. }
  719. m_nFlags &= ~eAIS_AUDIO_MIDDLEWARE_SHUTTING_DOWN;
  720. }
  721. ///////////////////////////////////////////////////////////////////////////////////////////////////
  722. EAudioRequestStatus CAudioTranslationLayer::PrepUnprepTriggerAsync(
  723. CATLAudioObjectBase* const pAudioObject,
  724. const CATLTrigger* const pTrigger,
  725. const bool bPrepare)
  726. {
  727. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  728. const TAudioObjectID nATLObjectID = pAudioObject->GetID();
  729. const TObjectTriggerImplStates& rTriggerImplStates = pAudioObject->GetTriggerImpls();
  730. for (auto const triggerImpl : pTrigger->m_cImplPtrs)
  731. {
  732. TATLEnumFlagsType nTriggerImplFlags = INVALID_AUDIO_ENUM_FLAG_TYPE;
  733. TObjectTriggerImplStates::const_iterator iPlace = rTriggerImplStates.end();
  734. if (FindPlaceConst(rTriggerImplStates, triggerImpl->m_nATLID, iPlace))
  735. {
  736. nTriggerImplFlags = iPlace->second.nFlags;
  737. }
  738. const EATLSubsystem eReceiver = triggerImpl->GetReceiver();
  739. CATLEvent* pEvent = m_oAudioEventMgr.GetEvent(eReceiver);
  740. EAudioRequestStatus ePrepUnprepResult = EAudioRequestStatus::Failure;
  741. switch (eReceiver)
  742. {
  743. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  744. {
  745. if (bPrepare)
  746. {
  747. if (((nTriggerImplFlags & eATS_PREPARED) == 0) && ((nTriggerImplFlags & eATS_LOADING) == 0))
  748. {
  749. AudioSystemImplementationRequestBus::BroadcastResult(ePrepUnprepResult, &AudioSystemImplementationRequestBus::Events::PrepareTriggerAsync,
  750. pAudioObject->GetImplDataPtr(),
  751. triggerImpl->m_pImplData,
  752. pEvent->m_pImplData);
  753. }
  754. }
  755. else
  756. {
  757. if (((nTriggerImplFlags & eATS_PREPARED) != 0) && ((nTriggerImplFlags & eATS_UNLOADING) == 0))
  758. {
  759. AudioSystemImplementationRequestBus::BroadcastResult(ePrepUnprepResult, &AudioSystemImplementationRequestBus::Events::UnprepareTriggerAsync,
  760. pAudioObject->GetImplDataPtr(),
  761. triggerImpl->m_pImplData,
  762. pEvent->m_pImplData);
  763. }
  764. }
  765. if (ePrepUnprepResult == EAudioRequestStatus::Success)
  766. {
  767. pEvent->m_nObjectID = nATLObjectID;
  768. pEvent->m_nTriggerID = triggerImpl->m_nATLID;
  769. pEvent->m_nTriggerImplID = triggerImpl->m_nATLID;
  770. pEvent->m_audioEventState = bPrepare ? eAES_LOADING : eAES_UNLOADING;
  771. }
  772. break;
  773. }
  774. case eAS_ATL_INTERNAL:
  775. {
  776. //TODO: handle this
  777. break;
  778. }
  779. default:
  780. {
  781. break;
  782. }
  783. }
  784. if (ePrepUnprepResult == EAudioRequestStatus::Success)
  785. {
  786. pEvent->SetDataScope(pTrigger->GetDataScope());
  787. pAudioObject->EventStarted(pEvent);
  788. pAudioObject->IncrementRefCount();
  789. eResult = EAudioRequestStatus::Success; // if at least one event fires, it is a success
  790. }
  791. else
  792. {
  793. m_oAudioEventMgr.ReleaseEvent(pEvent);
  794. }
  795. }
  796. #if !defined(AUDIO_RELEASE)
  797. if (eResult != EAudioRequestStatus::Success)
  798. {
  799. // No TriggerImpl produced an active event.
  800. AZLOG_DEBUG(
  801. "PrepUnprepTriggerAsync failed on AudioObject '%s' (ID: %llu)", m_oDebugNameStore.LookupAudioObjectName(nATLObjectID),
  802. nATLObjectID);
  803. }
  804. #endif // !AUDIO_RELEASE
  805. return eResult;
  806. }
  807. ///////////////////////////////////////////////////////////////////////////////////////////////////
  808. EAudioRequestStatus CAudioTranslationLayer::ActivateTrigger(
  809. CATLAudioObjectBase* const pAudioObject,
  810. const CATLTrigger* const pTrigger,
  811. void* const pOwner /* = nullptr */,
  812. const SATLSourceData* pSourceData /* = nullptr */)
  813. {
  814. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  815. if (pAudioObject->HasPosition())
  816. {
  817. // If the AudioObject uses Obstruction/Occlusion then set the values before activating the trigger.
  818. auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
  819. if (pPositionedAudioObject->CanRunRaycasts() && !pPositionedAudioObject->HasActiveEvents())
  820. {
  821. pPositionedAudioObject->RunRaycasts(m_oSharedData.m_oActiveListenerPosition);
  822. }
  823. }
  824. const TAudioControlID nATLTriggerID = pTrigger->GetID();
  825. // Sets eATS_STARTING on this TriggerInstance to avoid
  826. // reporting TriggerFinished while the events are being started.
  827. pAudioObject->TriggerInstanceStarting(m_nTriggerInstanceIDCounter, nATLTriggerID);
  828. for (auto const triggerImpl : pTrigger->m_cImplPtrs)
  829. {
  830. const EATLSubsystem eReceiver = triggerImpl->GetReceiver();
  831. CATLEvent* const pEvent = m_oAudioEventMgr.GetEvent(eReceiver);
  832. pEvent->m_pImplData->m_triggerId = nATLTriggerID;
  833. pEvent->m_pImplData->m_owner = pOwner;
  834. EAudioRequestStatus eActivateResult = EAudioRequestStatus::Failure;
  835. switch (eReceiver)
  836. {
  837. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  838. {
  839. AudioSystemImplementationRequestBus::BroadcastResult(eActivateResult,
  840. &AudioSystemImplementationRequestBus::Events::ActivateTrigger,
  841. pAudioObject->GetImplDataPtr(),
  842. triggerImpl->m_pImplData,
  843. pEvent->m_pImplData,
  844. pSourceData);
  845. break;
  846. }
  847. case eAS_ATL_INTERNAL:
  848. {
  849. eActivateResult = ActivateInternalTrigger(
  850. pAudioObject,
  851. triggerImpl->m_pImplData,
  852. pEvent->m_pImplData);
  853. break;
  854. }
  855. default:
  856. {
  857. break;
  858. }
  859. }
  860. if (eActivateResult == EAudioRequestStatus::Success)
  861. {
  862. pEvent->m_nObjectID = pAudioObject->GetID();
  863. pEvent->m_nTriggerID = nATLTriggerID;
  864. pEvent->m_nTriggerImplID = triggerImpl->m_nATLID;
  865. pEvent->m_nTriggerInstanceID = m_nTriggerInstanceIDCounter;
  866. pEvent->SetDataScope(pTrigger->GetDataScope());
  867. pEvent->m_audioEventState = eAES_PLAYING;
  868. pAudioObject->EventStarted(pEvent);
  869. // If at least one event fires, it is a success: the trigger has been activated.
  870. eResult = EAudioRequestStatus::Success;
  871. }
  872. else
  873. {
  874. m_oAudioEventMgr.ReleaseEvent(pEvent);
  875. }
  876. }
  877. // Either removes the eATS_STARTING flag on this trigger instance or removes it if no event was started.
  878. pAudioObject->TriggerInstanceStarted(m_nTriggerInstanceIDCounter++, pOwner);
  879. #if !defined(AUDIO_RELEASE)
  880. if (eResult != EAudioRequestStatus::Success)
  881. {
  882. // No TriggerImpl generated an active event.
  883. AZLOG_DEBUG(
  884. "ATL Trigger '%s' failed to execute on AudioObject '%s' (ID: %llu)",
  885. m_oDebugNameStore.LookupAudioTriggerName(nATLTriggerID), m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID()),
  886. pAudioObject->GetID());
  887. }
  888. #endif // !AUDIO_RELEASE
  889. return eResult;
  890. }
  891. ///////////////////////////////////////////////////////////////////////////////////////////////////
  892. EAudioRequestStatus CAudioTranslationLayer::StopTrigger(
  893. CATLAudioObjectBase* const pAudioObject,
  894. const CATLTrigger* const pTrigger)
  895. {
  896. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  897. const TAudioControlID nATLTriggerID = pTrigger->GetID();
  898. TObjectEventSet rEvents = pAudioObject->GetActiveEvents();
  899. for (auto eventId : rEvents)
  900. {
  901. const CATLEvent* const pEvent = m_oAudioEventMgr.LookupID(eventId);
  902. if (pEvent && pEvent->IsPlaying() && (pEvent->m_nTriggerID == nATLTriggerID))
  903. {
  904. switch (pEvent->m_eSender)
  905. {
  906. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  907. {
  908. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopEvent,
  909. pAudioObject->GetImplDataPtr(),
  910. pEvent->m_pImplData);
  911. break;
  912. }
  913. case eAS_ATL_INTERNAL:
  914. {
  915. eResult = StopInternalEvent(pAudioObject, pEvent->m_pImplData);
  916. break;
  917. }
  918. default:
  919. {
  920. break;
  921. }
  922. }
  923. }
  924. }
  925. return eResult;
  926. }
  927. ///////////////////////////////////////////////////////////////////////////////////////////////////
  928. EAudioRequestStatus CAudioTranslationLayer::StopAllTriggers(CATLAudioObjectBase* const pAudioObject, void* const pOwner /* = nullptr*/)
  929. {
  930. if (!pOwner)
  931. {
  932. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  933. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopAllEvents, pAudioObject->GetImplDataPtr());
  934. return eResult;
  935. }
  936. else
  937. {
  938. EAudioRequestStatus eResult = EAudioRequestStatus::Success;
  939. auto triggerInstances = pAudioObject->GetTriggerInstancesByOwner(pOwner);
  940. auto activeEvents = pAudioObject->GetActiveEvents();
  941. for (auto eventId : activeEvents)
  942. {
  943. const CATLEvent* const atlEvent = m_oAudioEventMgr.LookupID(eventId);
  944. if (atlEvent && triggerInstances.find(atlEvent->m_nTriggerInstanceID) != triggerInstances.end())
  945. {
  946. EAudioRequestStatus eSingleResult = EAudioRequestStatus::Failure;
  947. switch (atlEvent->m_eSender)
  948. {
  949. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  950. {
  951. AudioSystemImplementationRequestBus::BroadcastResult(eSingleResult, &AudioSystemImplementationRequestBus::Events::StopEvent,
  952. pAudioObject->GetImplDataPtr(),
  953. atlEvent->m_pImplData);
  954. break;
  955. }
  956. case eAS_ATL_INTERNAL:
  957. {
  958. eSingleResult = StopInternalEvent(pAudioObject, atlEvent->m_pImplData);
  959. break;
  960. }
  961. default:
  962. {
  963. break;
  964. }
  965. }
  966. if (eSingleResult != EAudioRequestStatus::Success)
  967. {
  968. eResult = EAudioRequestStatus::Failure;
  969. }
  970. }
  971. }
  972. return eResult;
  973. }
  974. }
  975. ///////////////////////////////////////////////////////////////////////////////////////////////////
  976. EAudioRequestStatus CAudioTranslationLayer::SetSwitchState(
  977. CATLAudioObjectBase* const pAudioObject,
  978. const CATLSwitchState* const pState)
  979. {
  980. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  981. for (auto switchStateImpl : pState->m_cImplPtrs)
  982. {
  983. const EATLSubsystem eReceiver = switchStateImpl->GetReceiver();
  984. EAudioRequestStatus eSetStateResult = EAudioRequestStatus::Failure;
  985. switch (eReceiver)
  986. {
  987. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  988. {
  989. AudioSystemImplementationRequestBus::BroadcastResult(eSetStateResult, &AudioSystemImplementationRequestBus::Events::SetSwitchState,
  990. pAudioObject->GetImplDataPtr(),
  991. switchStateImpl->m_pImplData);
  992. break;
  993. }
  994. case eAS_ATL_INTERNAL:
  995. {
  996. eSetStateResult = SetInternalSwitchState(pAudioObject, switchStateImpl->m_pImplData);
  997. break;
  998. }
  999. default:
  1000. {
  1001. break;
  1002. }
  1003. }
  1004. if (eSetStateResult == EAudioRequestStatus::Success)
  1005. {
  1006. eResult = EAudioRequestStatus::Success; // if at least one of the implementations is set successfully, it is a success
  1007. }
  1008. }
  1009. if (eResult == EAudioRequestStatus::Success)
  1010. {
  1011. pAudioObject->SetSwitchState(pState->GetParentID(), pState->GetID());
  1012. }
  1013. #if !defined(AUDIO_RELEASE)
  1014. else
  1015. {
  1016. const char* const sSwitchName = m_oDebugNameStore.LookupAudioSwitchName(pState->GetParentID());
  1017. const char* const sSwitchStateName = m_oDebugNameStore.LookupAudioSwitchStateName(pState->GetParentID(), pState->GetID());
  1018. const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
  1019. AZLOG_DEBUG(
  1020. "ATL failed to set Switch '%s' to State '%s' on AudioObject '%s' (ID: %llu)", sSwitchName, sSwitchStateName,
  1021. sAudioObjectName, pAudioObject->GetID());
  1022. }
  1023. #endif // !AUDIO_RELEASE
  1024. return eResult;
  1025. }
  1026. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1027. EAudioRequestStatus CAudioTranslationLayer::SetRtpc(
  1028. CATLAudioObjectBase* const pAudioObject,
  1029. const CATLRtpc* const pRtpc,
  1030. const float fValue)
  1031. {
  1032. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  1033. for (auto rtpcImpl : pRtpc->m_cImplPtrs)
  1034. {
  1035. const EATLSubsystem eReceiver = rtpcImpl->GetReceiver();
  1036. EAudioRequestStatus eSetRtpcResult = EAudioRequestStatus::Failure;
  1037. switch (eReceiver)
  1038. {
  1039. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  1040. {
  1041. AudioSystemImplementationRequestBus::BroadcastResult(eSetRtpcResult, &AudioSystemImplementationRequestBus::Events::SetRtpc,
  1042. pAudioObject->GetImplDataPtr(),
  1043. rtpcImpl->m_pImplData,
  1044. fValue);
  1045. break;
  1046. }
  1047. case eAS_ATL_INTERNAL:
  1048. {
  1049. eSetRtpcResult = SetInternalRtpc(pAudioObject, rtpcImpl->m_pImplData, fValue);
  1050. break;
  1051. }
  1052. default:
  1053. {
  1054. break;
  1055. }
  1056. }
  1057. if (eSetRtpcResult == EAudioRequestStatus::Success)
  1058. {
  1059. eResult = EAudioRequestStatus::Success; // if at least one of the implementations is set successfully, it is a success
  1060. }
  1061. }
  1062. if (eResult == EAudioRequestStatus::Success)
  1063. {
  1064. pAudioObject->SetRtpc(pRtpc->GetID(), fValue);
  1065. }
  1066. #if !defined(AUDIO_RELEASE)
  1067. else
  1068. {
  1069. const char* const sRtpcName = m_oDebugNameStore.LookupAudioRtpcName(pRtpc->GetID());
  1070. const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
  1071. AZLOG_DEBUG(
  1072. "ATL failed to set Parameter '%s' to %f on AudioObject '%s' (ID: %llu)", sRtpcName, fValue, sAudioObjectName,
  1073. pAudioObject->GetID());
  1074. }
  1075. #endif // !AUDIO_RELEASE
  1076. return eResult;
  1077. }
  1078. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1079. EAudioRequestStatus CAudioTranslationLayer::ResetRtpcs(CATLAudioObjectBase* const pAudioObject)
  1080. {
  1081. const TObjectRtpcMap rRtpcs = pAudioObject->GetRtpcs();
  1082. EAudioRequestStatus eResult = EAudioRequestStatus::Success;
  1083. for (auto& rtpcPair : rRtpcs)
  1084. {
  1085. auto it = m_cRtpcs.find(rtpcPair.first);
  1086. if (it != m_cRtpcs.end())
  1087. {
  1088. for (auto rtpcImpl : it->second->m_cImplPtrs)
  1089. {
  1090. EAudioRequestStatus eResetRtpcResult = EAudioRequestStatus::Failure;
  1091. switch (rtpcImpl->GetReceiver())
  1092. {
  1093. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  1094. {
  1095. AudioSystemImplementationRequestBus::BroadcastResult(eResetRtpcResult, &AudioSystemImplementationRequestBus::Events::ResetRtpc,
  1096. pAudioObject->GetImplDataPtr(),
  1097. rtpcImpl->m_pImplData);
  1098. break;
  1099. }
  1100. case eAS_ATL_INTERNAL:
  1101. {
  1102. // Implement internal Rtpcs later
  1103. eResetRtpcResult = EAudioRequestStatus::Success;
  1104. break;
  1105. }
  1106. default:
  1107. {
  1108. break;
  1109. }
  1110. }
  1111. // If any reset failed, consider it an overall failure
  1112. if (eResetRtpcResult != EAudioRequestStatus::Success)
  1113. {
  1114. eResult = EAudioRequestStatus::Failure;
  1115. }
  1116. }
  1117. }
  1118. }
  1119. if (eResult == EAudioRequestStatus::Success)
  1120. {
  1121. pAudioObject->ClearRtpcs();
  1122. }
  1123. #if !defined(AUDIO_RELEASE)
  1124. else
  1125. {
  1126. const TAudioObjectID objectId = pAudioObject->GetID();
  1127. AZLOG_DEBUG(
  1128. "ATL failed to reset parameters on AudioObject '%s' (ID: %llu)", m_oDebugNameStore.LookupAudioObjectName(objectId),
  1129. objectId);
  1130. }
  1131. #endif // !AUDIO_RELEASE
  1132. return eResult;
  1133. }
  1134. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1135. EAudioRequestStatus CAudioTranslationLayer::SetEnvironment(
  1136. CATLAudioObjectBase* const pAudioObject,
  1137. const CATLAudioEnvironment* const pEnvironment,
  1138. const float fAmount)
  1139. {
  1140. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  1141. for (auto environmentImpl : pEnvironment->m_cImplPtrs)
  1142. {
  1143. const EATLSubsystem eReceiver = environmentImpl->GetReceiver();
  1144. EAudioRequestStatus eSetEnvResult = EAudioRequestStatus::Failure;
  1145. switch (eReceiver)
  1146. {
  1147. case eAS_AUDIO_SYSTEM_IMPLEMENTATION:
  1148. {
  1149. AudioSystemImplementationRequestBus::BroadcastResult(eSetEnvResult, &AudioSystemImplementationRequestBus::Events::SetEnvironment,
  1150. pAudioObject->GetImplDataPtr(),
  1151. environmentImpl->m_pImplData,
  1152. fAmount);
  1153. break;
  1154. }
  1155. case eAS_ATL_INTERNAL:
  1156. {
  1157. eSetEnvResult = SetInternalEnvironment(pAudioObject, environmentImpl->m_pImplData, fAmount);
  1158. break;
  1159. }
  1160. default:
  1161. {
  1162. break;
  1163. }
  1164. }
  1165. if (eSetEnvResult == EAudioRequestStatus::Success)
  1166. {
  1167. eResult = EAudioRequestStatus::Success; // if at least one of the implementations is set successfully, it is a success
  1168. }
  1169. }
  1170. if (eResult == EAudioRequestStatus::Success)
  1171. {
  1172. pAudioObject->SetEnvironmentAmount(pEnvironment->GetID(), fAmount);
  1173. }
  1174. #if !defined(AUDIO_RELEASE)
  1175. else
  1176. {
  1177. const char* const sEnvironmentName = m_oDebugNameStore.LookupAudioEnvironmentName(pEnvironment->GetID());
  1178. const char* const sAudioObjectName = m_oDebugNameStore.LookupAudioObjectName(pAudioObject->GetID());
  1179. AZLOG_DEBUG(
  1180. "ATL failed to set environment '%s' to %f on AudioObject '%s' (ID: %llu)", sEnvironmentName, fAmount, sAudioObjectName,
  1181. pAudioObject->GetID());
  1182. }
  1183. #endif // !AUDIO_RELEASE
  1184. return eResult;
  1185. }
  1186. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1187. EAudioRequestStatus CAudioTranslationLayer::ResetEnvironments(CATLAudioObjectBase* const pAudioObject)
  1188. {
  1189. const TObjectEnvironmentMap rEnvironments = pAudioObject->GetEnvironments();
  1190. EAudioRequestStatus eResult = EAudioRequestStatus::Success;
  1191. for (auto& environmentAmountPair : rEnvironments)
  1192. {
  1193. auto it = m_cEnvironments.find(environmentAmountPair.first);
  1194. if (it != m_cEnvironments.end())
  1195. {
  1196. const EAudioRequestStatus eSetEnvResult = SetEnvironment(pAudioObject, it->second, 0.0f);
  1197. if (eSetEnvResult != EAudioRequestStatus::Success)
  1198. {
  1199. // If setting at least one Environment fails, we consider this a failure.
  1200. eResult = EAudioRequestStatus::Failure;
  1201. }
  1202. }
  1203. }
  1204. if (eResult == EAudioRequestStatus::Success)
  1205. {
  1206. pAudioObject->ClearEnvironments();
  1207. }
  1208. #if !defined(AUDIO_RELEASE)
  1209. else
  1210. {
  1211. const TAudioObjectID nObjectID = pAudioObject->GetID();
  1212. AZLOG_DEBUG(
  1213. "ATL failed to reset environments on AudioObject '%s' (ID: %llu)", m_oDebugNameStore.LookupAudioObjectName(nObjectID),
  1214. nObjectID);
  1215. }
  1216. #endif // !AUDIO_RELEASE
  1217. return eResult;
  1218. }
  1219. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1220. EAudioRequestStatus CAudioTranslationLayer::ActivateInternalTrigger(
  1221. [[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
  1222. [[maybe_unused]] const IATLTriggerImplData* const pTriggerData,
  1223. [[maybe_unused]] IATLEventData* const pEventData)
  1224. {
  1225. //TODO implement
  1226. return EAudioRequestStatus::Failure;
  1227. }
  1228. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1229. EAudioRequestStatus CAudioTranslationLayer::StopInternalEvent(
  1230. [[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
  1231. [[maybe_unused]] const IATLEventData* const pEventData)
  1232. {
  1233. //TODO implement
  1234. return EAudioRequestStatus::Failure;
  1235. }
  1236. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1237. EAudioRequestStatus CAudioTranslationLayer::StopAllInternalEvents([[maybe_unused]] CATLAudioObjectBase* const pAudioObject)
  1238. {
  1239. //TODO implement
  1240. return EAudioRequestStatus::Failure;
  1241. }
  1242. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1243. EAudioRequestStatus CAudioTranslationLayer::SetInternalRtpc(
  1244. [[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
  1245. [[maybe_unused]] const IATLRtpcImplData* const pRtpcData,
  1246. [[maybe_unused]] const float fValue)
  1247. {
  1248. //TODO implement
  1249. return EAudioRequestStatus::Failure;
  1250. }
  1251. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1252. EAudioRequestStatus CAudioTranslationLayer::SetInternalSwitchState(
  1253. CATLAudioObjectBase* const pAudioObject,
  1254. const IATLSwitchStateImplData* const pSwitchStateData)
  1255. {
  1256. auto const pInternalStateData = static_cast<const SATLSwitchStateImplData_internal*>(pSwitchStateData);
  1257. //TODO: once there is more than one internal switch, a more sensible approach needs to be developed
  1258. if (pInternalStateData->nATLInternalSwitchID == ATLInternalControlIDs::ObstructionOcclusionCalcSwitchID)
  1259. {
  1260. if (pAudioObject->HasPosition())
  1261. {
  1262. auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
  1263. if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[static_cast<size_t>(ObstructionType::Ignore)])
  1264. {
  1265. SATLSoundPropagationData oPropagationData;
  1266. pPositionedAudioObject->SetRaycastCalcType(ObstructionType::Ignore);
  1267. pPositionedAudioObject->GetObstOccData(oPropagationData);
  1268. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::SetObstructionOcclusion,
  1269. pPositionedAudioObject->GetImplDataPtr(),
  1270. oPropagationData.fObstruction,
  1271. oPropagationData.fOcclusion);
  1272. }
  1273. else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[static_cast<size_t>(ObstructionType::SingleRay)])
  1274. {
  1275. pPositionedAudioObject->SetRaycastCalcType(ObstructionType::SingleRay);
  1276. }
  1277. else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OOCStateIDs[static_cast<size_t>(ObstructionType::MultiRay)])
  1278. {
  1279. pPositionedAudioObject->SetRaycastCalcType(ObstructionType::MultiRay);
  1280. }
  1281. else
  1282. {
  1283. AZLOG_DEBUG("SetInternalSwitchState - Unknown value for ObstructionType");
  1284. }
  1285. }
  1286. }
  1287. else if (pInternalStateData->nATLInternalSwitchID == ATLInternalControlIDs::ObjectVelocityTrackingSwitchID)
  1288. {
  1289. if (pAudioObject->HasPosition())
  1290. {
  1291. auto const pPositionedAudioObject = static_cast<CATLAudioObject*>(pAudioObject);
  1292. if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OVTOnStateID)
  1293. {
  1294. pPositionedAudioObject->SetVelocityTracking(true);
  1295. }
  1296. else if (pInternalStateData->nATLInternalStateID == ATLInternalControlIDs::OVTOffStateID)
  1297. {
  1298. pPositionedAudioObject->SetVelocityTracking(false);
  1299. }
  1300. else
  1301. {
  1302. AZLOG_DEBUG("SetInternalSwitchState - Unknown value for ObjectVelocityTracking");
  1303. }
  1304. }
  1305. }
  1306. return EAudioRequestStatus::Success;
  1307. }
  1308. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1309. EAudioRequestStatus CAudioTranslationLayer::SetInternalEnvironment(
  1310. [[maybe_unused]] CATLAudioObjectBase* const pAudioObject,
  1311. [[maybe_unused]] const IATLEnvironmentImplData* const pEnvironmentImplData,
  1312. [[maybe_unused]] const float fAmount)
  1313. {
  1314. // TODO: implement
  1315. return EAudioRequestStatus::Failure;
  1316. }
  1317. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1318. EAudioRequestStatus CAudioTranslationLayer::MuteAll()
  1319. {
  1320. EAudioRequestStatus result = EAudioRequestStatus::Failure;
  1321. const CATLTrigger* trigger = nullptr;
  1322. if (auto it = m_cTriggers.find(ATLInternalControlIDs::MuteAllTriggerID);
  1323. it != m_cTriggers.end())
  1324. {
  1325. trigger = it->second;
  1326. }
  1327. if (trigger)
  1328. {
  1329. result = ActivateTrigger(m_pGlobalAudioObject, trigger);
  1330. }
  1331. else
  1332. {
  1333. AZLOG_DEBUG("ATL Trigger not found for MuteAllTriggerID");
  1334. }
  1335. if (result == EAudioRequestStatus::Success)
  1336. {
  1337. m_nFlags |= eAIS_IS_MUTED;
  1338. }
  1339. AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemMuteAll);
  1340. return result;
  1341. }
  1342. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1343. EAudioRequestStatus CAudioTranslationLayer::UnmuteAll()
  1344. {
  1345. EAudioRequestStatus result = EAudioRequestStatus::Failure;
  1346. const CATLTrigger* trigger = nullptr;
  1347. if (auto it = m_cTriggers.find(ATLInternalControlIDs::UnmuteAllTriggerID);
  1348. it != m_cTriggers.end())
  1349. {
  1350. trigger = it->second;
  1351. }
  1352. if (trigger)
  1353. {
  1354. result = ActivateTrigger(m_pGlobalAudioObject, trigger);
  1355. }
  1356. else
  1357. {
  1358. AZLOG_DEBUG("ATL Trigger not found for UnmuteAllTriggerID");
  1359. }
  1360. if (result == EAudioRequestStatus::Success)
  1361. {
  1362. m_nFlags &= ~eAIS_IS_MUTED;
  1363. }
  1364. AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemUnmuteAll);
  1365. return result;
  1366. }
  1367. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1368. EAudioRequestStatus CAudioTranslationLayer::LoseFocus()
  1369. {
  1370. EAudioRequestStatus result = EAudioRequestStatus::Success; // default is success when nothing needs to happen
  1371. #if !defined(AUDIO_RELEASE)
  1372. if (!Audio::CVars::s_IgnoreWindowFocus && 0 == (m_nFlags & eAIS_IS_MUTED))
  1373. #endif // !AUDIO_RELEASE
  1374. {
  1375. if (auto it = m_cTriggers.find(ATLInternalControlIDs::LoseFocusTriggerID); it != m_cTriggers.end())
  1376. {
  1377. result = ActivateTrigger(m_pGlobalAudioObject, it->second);
  1378. }
  1379. else
  1380. {
  1381. AZLOG_DEBUG("ATL Trigger not found for LoseFocusTriggerID");
  1382. result = EAudioRequestStatus::FailureInvalidControlId;
  1383. }
  1384. AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemLoseFocus);
  1385. }
  1386. return result;
  1387. }
  1388. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1389. EAudioRequestStatus CAudioTranslationLayer::GetFocus()
  1390. {
  1391. EAudioRequestStatus result = EAudioRequestStatus::Success; // default is success when nothing needs to happen
  1392. #if !defined(AUDIO_RELEASE)
  1393. if (!Audio::CVars::s_IgnoreWindowFocus && 0 == (m_nFlags & eAIS_IS_MUTED))
  1394. #endif // !AUDIO_RELEASE
  1395. {
  1396. AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemGetFocus);
  1397. if (auto it = m_cTriggers.find(ATLInternalControlIDs::GetFocusTriggerID); it != m_cTriggers.end())
  1398. {
  1399. result = ActivateTrigger(m_pGlobalAudioObject, it->second);
  1400. }
  1401. else
  1402. {
  1403. AZLOG_DEBUG("ATL Trigger not found for GetFocusTriggerID");
  1404. result = EAudioRequestStatus::FailureInvalidControlId;
  1405. }
  1406. }
  1407. return result;
  1408. }
  1409. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1410. void CAudioTranslationLayer::UpdateSharedData()
  1411. {
  1412. m_oAudioListenerMgr.GetDefaultListenerPosition(m_oSharedData.m_oActiveListenerPosition);
  1413. }
  1414. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1415. void CAudioTranslationLayer::SetImplLanguage()
  1416. {
  1417. if (auto console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
  1418. {
  1419. AZ::CVarFixedString languageAudio;
  1420. if (auto result = console->GetCvarValue("g_languageAudio", languageAudio); result == AZ::GetValueResult::Success)
  1421. {
  1422. AudioSystemImplementationRequestBus::Broadcast(
  1423. &AudioSystemImplementationRequestBus::Events::SetLanguage, languageAudio.data());
  1424. }
  1425. }
  1426. }
  1427. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1428. CATLAudioObjectBase* CAudioTranslationLayer::GetRequestObject(TAudioObjectID objectId)
  1429. {
  1430. if (objectId == INVALID_AUDIO_OBJECT_ID)
  1431. {
  1432. return static_cast<CATLAudioObjectBase*>(m_pGlobalAudioObject);
  1433. }
  1434. else
  1435. {
  1436. return static_cast<CATLAudioObjectBase*>(m_oAudioObjectMgr.LookupID(objectId));
  1437. }
  1438. }
  1439. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1440. void CAudioTranslationLayer::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
  1441. {
  1442. switch (event)
  1443. {
  1444. case ESYSTEM_EVENT_LEVEL_UNLOAD:
  1445. RaycastProcessor::s_raycastsEnabled = false;
  1446. break;
  1447. case ESYSTEM_EVENT_LEVEL_GAMEPLAY_START:
  1448. case ESYSTEM_EVENT_LEVEL_PRECACHE_START:
  1449. RaycastProcessor::s_raycastsEnabled = true;
  1450. break;
  1451. case ESYSTEM_EVENT_EDITOR_GAME_MODE_CHANGED:
  1452. RaycastProcessor::s_raycastsEnabled = (wparam != 0);
  1453. break;
  1454. default:
  1455. break;
  1456. }
  1457. }
  1458. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1459. EAudioRequestStatus CAudioTranslationLayer::RefreshAudioSystem(const char* const controlsPath, const char* const levelName, TAudioPreloadRequestID levelPreloadId)
  1460. {
  1461. AZLOG_INFO("$8Beginning to refresh the AudioSystem...")
  1462. if (!controlsPath || controlsPath[0] == '\0')
  1463. {
  1464. AZLOG_INFO("Controls path is null, cannot continue with refresh");
  1465. return EAudioRequestStatus::Failure;
  1466. }
  1467. EAudioRequestStatus eResult = EAudioRequestStatus::Failure;
  1468. AudioSystemImplementationRequestBus::BroadcastResult(eResult, &AudioSystemImplementationRequestBus::Events::StopAllSounds);
  1469. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1470. "ATL RefreshAudioSystem - Failed to StopAllSounds!");
  1471. eResult = m_oFileCacheMgr.UnloadDataByScope(eADS_LEVEL_SPECIFIC);
  1472. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1473. "ATL RefreshAudioSystem - Failed to unload old level banks!");
  1474. eResult = m_oFileCacheMgr.UnloadDataByScope(eADS_GLOBAL);
  1475. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1476. "ATL RefreshAudioSystem - Failed to unload old global banks!");
  1477. eResult = ClearControlsData(eADS_ALL);
  1478. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1479. "ATL RefreshAudioSystem - Failed to clear old controls data!");
  1480. AudioSystemImplementationNotificationBus::Broadcast(&AudioSystemImplementationNotificationBus::Events::OnAudioSystemRefresh);
  1481. SetImplLanguage();
  1482. eResult = ParseControlsData(controlsPath, eADS_GLOBAL);
  1483. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1484. "ATL RefreshAudioSystem - Failed to load fresh global controls data!");
  1485. eResult = m_oFileCacheMgr.TryLoadRequest(ATLInternalControlIDs::GlobalPreloadRequestID, true, true);
  1486. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1487. "ATL RefreshAudioSystem - Failed to load fresh global banks!");
  1488. if (levelName && levelName[0] != '\0')
  1489. {
  1490. AZStd::string levelControlsPath(controlsPath);
  1491. levelControlsPath.append("levels/");
  1492. levelControlsPath.append(levelName);
  1493. AZ::StringFunc::RelativePath::Normalize(levelControlsPath);
  1494. eResult = ParseControlsData(levelControlsPath.c_str(), eADS_LEVEL_SPECIFIC);
  1495. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1496. "ATL RefreshAudioSystem - Failed to parse fresh level controls data!");
  1497. if (levelPreloadId != INVALID_AUDIO_PRELOAD_REQUEST_ID)
  1498. {
  1499. eResult = m_oFileCacheMgr.TryLoadRequest(levelPreloadId, true, true);
  1500. AZ_Error("AudioTranslationLayer", eResult == EAudioRequestStatus::Success,
  1501. "ATL RefreshAudioSystem - Failed to load fresh level banks!");
  1502. }
  1503. }
  1504. if (m_nFlags & eAIS_IS_MUTED)
  1505. {
  1506. // restore the muted state...
  1507. MuteAll();
  1508. }
  1509. AZLOG_INFO("$3Done refreshing the AudioSystem!");
  1510. return EAudioRequestStatus::Success;
  1511. }
  1512. #if !defined(AUDIO_RELEASE)
  1513. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1514. void CAudioTranslationLayer::DrawAudioSystemDebugInfo()
  1515. {
  1516. AZ_PROFILE_FUNCTION(Audio);
  1517. AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
  1518. AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId);
  1519. AzFramework::DebugDisplayRequests* debugDisplay{ AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus) };
  1520. auto oldState = debugDisplay->GetState();
  1521. if (debugDisplay && CVars::s_debugDrawOptions.GetRawFlags() != 0)
  1522. {
  1523. DrawAudioObjectDebugInfo(*debugDisplay);
  1524. const float textSize = 1.f;
  1525. const size_t nPrimaryPoolSize = AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().Capacity();
  1526. const size_t nPrimaryPoolUsedSize = nPrimaryPoolSize - AZ::AllocatorInstance<Audio::AudioSystemAllocator>::Get().GetUnAllocatedMemory();
  1527. float fPosX = 0.0f;
  1528. float fPosY = 4.0f;
  1529. const AZ::Color colorWhite{ 1.0f, 1.0f, 1.0f, 0.9f };
  1530. const AZ::Color colorRed{ 1.0f, 0.0f, 0.0f, 0.7f };
  1531. const AZ::Color colorGreen{ 0.0f, 1.0f, 0.0f, 0.7f };
  1532. const AZ::Color colorBlue{ 0.4f, 0.4f, 1.0f, 1.0f };
  1533. AZStd::string str;
  1534. const char* implementationName = nullptr;
  1535. AudioSystemImplementationRequestBus::BroadcastResult(implementationName, &AudioSystemImplementationRequestBus::Events::GetImplementationNameString);
  1536. str = AZStd::string::format("Audio Translation Layer with %s", implementationName);
  1537. debugDisplay->SetColor(colorBlue);
  1538. debugDisplay->Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1539. fPosX += 30.0f;
  1540. fPosY += 30.0f;
  1541. str = AZStd::string::format(
  1542. "Audio System Mem: %.2f / %.2f MiB", (nPrimaryPoolUsedSize / 1024) / 1024.f, (nPrimaryPoolSize / 1024) / 1024.f);
  1543. debugDisplay->SetColor(colorWhite);
  1544. debugDisplay->Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1545. float const fLineHeight = 20.0f;
  1546. SAudioImplMemoryInfo oMemoryInfo;
  1547. AudioSystemImplementationRequestBus::Broadcast(&AudioSystemImplementationRequestBus::Events::GetMemoryInfo, oMemoryInfo);
  1548. fPosY += fLineHeight;
  1549. str = AZStd::string::format(
  1550. "Audio Engine Mem: %.2f / %.2f MiB", (oMemoryInfo.nPrimaryPoolUsedSize / 1024) / 1024.f,
  1551. (oMemoryInfo.nPrimaryPoolSize / 1024) / 1024.f);
  1552. debugDisplay->Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1553. const AZ::Vector3 vPos = m_oSharedData.m_oActiveListenerPosition.GetPositionVec();
  1554. const AZ::Vector3 vFwd = m_oSharedData.m_oActiveListenerPosition.GetForwardVec();
  1555. const size_t nNumAudioObjects = m_oAudioObjectMgr.GetNumAudioObjects();
  1556. const size_t nNumActiveAudioObjects = m_oAudioObjectMgr.GetNumActiveAudioObjects();
  1557. const size_t nEvents = m_oAudioEventMgr.GetNumActive();
  1558. const size_t nListeners = m_oAudioListenerMgr.GetNumActive();
  1559. TAudioObjectID activeListenerID = INVALID_AUDIO_OBJECT_ID;
  1560. if (CATLListenerObject* overrideListener = m_oAudioListenerMgr.LookupID(m_oAudioListenerMgr.GetOverrideListenerID()))
  1561. {
  1562. activeListenerID = overrideListener->GetID();
  1563. }
  1564. else if (CATLListenerObject* defaultListener = m_oAudioListenerMgr.LookupID(m_oAudioListenerMgr.GetDefaultListenerID()))
  1565. {
  1566. activeListenerID = defaultListener->GetID();
  1567. }
  1568. fPosY += fLineHeight;
  1569. str = AZStd::string::format(
  1570. "Active Listener (ID: %llu) -> Position: ( %.2f, %.2f, %.2f ) Forward: ( %.2f, %.2f, %.2f )", activeListenerID,
  1571. vPos.GetX(), vPos.GetY(), vPos.GetZ(), vFwd.GetX(), vFwd.GetY(), vFwd.GetZ());
  1572. debugDisplay->SetColor(colorGreen);
  1573. debugDisplay->Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1574. fPosY += fLineHeight;
  1575. str = AZStd::string::format(
  1576. "Audio Objects: %3zu / %3zu | Events: %3zu | Listeners: %zu", nNumActiveAudioObjects, nNumAudioObjects, nEvents,
  1577. nListeners);
  1578. debugDisplay->SetColor(colorWhite);
  1579. debugDisplay->Draw2dTextLabel(fPosX, fPosY, textSize, str.c_str());
  1580. fPosY += fLineHeight;
  1581. DrawATLComponentDebugInfo(*debugDisplay, fPosX, fPosY);
  1582. }
  1583. debugDisplay->SetState(oldState);
  1584. }
  1585. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1586. void CAudioTranslationLayer::DrawATLComponentDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay, float fPosX, float fPosY)
  1587. {
  1588. m_oFileCacheMgr.DrawDebugInfo(debugDisplay, fPosX, fPosY);
  1589. if (CVars::s_debugDrawOptions.AreAllFlagsActive(static_cast<AZ::u32>(DebugDraw::Options::MemoryInfo)))
  1590. {
  1591. DrawImplMemoryPoolDebugInfo(debugDisplay, fPosX, fPosY);
  1592. }
  1593. if (CVars::s_debugDrawOptions.AreAllFlagsActive(static_cast<AZ::u32>(DebugDraw::Options::ActiveObjects)))
  1594. {
  1595. m_oAudioObjectMgr.DrawDebugInfo(debugDisplay, fPosX, fPosY);
  1596. fPosX += 1000.0f;
  1597. }
  1598. if (CVars::s_debugDrawOptions.AreAllFlagsActive(static_cast<AZ::u32>(DebugDraw::Options::ActiveEvents)))
  1599. {
  1600. m_oAudioEventMgr.DrawDebugInfo(debugDisplay, fPosX, fPosY);
  1601. }
  1602. if (CVars::s_debugDrawOptions.AreAllFlagsActive(static_cast<AZ::u32>(DebugDraw::Options::DrawListener)))
  1603. {
  1604. m_oAudioListenerMgr.DrawDebugInfo(debugDisplay);
  1605. }
  1606. }
  1607. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1608. void BytesToString(AZ::u64 bytes, char* buffer, size_t bufLength)
  1609. {
  1610. if (bytes < (1 << 10))
  1611. {
  1612. azsnprintf(buffer, bufLength, " B: %llu", bytes);
  1613. }
  1614. else if (bytes < (1 << 20))
  1615. {
  1616. azsnprintf(buffer, bufLength, "KiB: %.2f", static_cast<double>(bytes) / static_cast<double>(1 << 10));
  1617. }
  1618. else
  1619. {
  1620. azsnprintf(buffer, bufLength, "MiB: %.2f", static_cast<double>(bytes) / static_cast<double>(1 << 20));
  1621. }
  1622. }
  1623. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1624. void CAudioTranslationLayer::DrawImplMemoryPoolDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay, float fPosX, float fPosY)
  1625. {
  1626. const float colorMax = 0.9f;
  1627. const float colorMin = 0.1f;
  1628. const float textSize = 0.8f;
  1629. const float lineHeight = 15.f;
  1630. const AZ::Color whiteColor(colorMax, colorMax, colorMax, 0.9f);
  1631. const AZ::Color greenColor(colorMin, colorMax, colorMin, 0.9f);
  1632. const AZ::Color yellowColor(colorMax, colorMax, colorMin, 0.9f);
  1633. const AZ::Color redColor(colorMax, colorMin, colorMin, 0.9f);
  1634. float posY = fPosY;
  1635. constexpr float xTablePositions[8] = { 0.f, 40.f, 300.f, 500.f, 700.f, 900.f, 1100.f, 1200.f };
  1636. debugDisplay.SetColor(whiteColor);
  1637. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[0], posY, textSize, "ID");
  1638. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[1], posY, textSize, "Name");
  1639. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[2], posY, textSize, "Curr Used");
  1640. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[3], posY, textSize, "Peak Used");
  1641. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[4], posY, textSize, "% of Total Used");
  1642. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[5], posY, textSize, "% of Total Size");
  1643. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[6], posY, textSize, "# Allocs");
  1644. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[7], posY, textSize, "# Frees");
  1645. // Get the memory pool information...
  1646. AZStd::vector<AudioImplMemoryPoolInfo> poolInfos;
  1647. AudioSystemImplementationRequestBus::BroadcastResult(poolInfos, &AudioSystemImplementationRequestBus::Events::GetMemoryPoolInfo);
  1648. if (!poolInfos.empty())
  1649. {
  1650. const AudioImplMemoryPoolInfo& globalInfo = poolInfos.back();
  1651. AZ_Assert(globalInfo.m_poolId == -1, "Global memory info doesn't have the expected ID.\n");
  1652. poolInfos.pop_back();
  1653. AZ::u64 totalPeak = 0;
  1654. AZ::u64 totalAllocs = 0;
  1655. AZ::u64 totalFrees = 0;
  1656. constexpr size_t bufferSize = 32;
  1657. char buffer[bufferSize] = { 0 };
  1658. AZStd::string str;
  1659. for (auto& poolInfo : poolInfos)
  1660. {
  1661. posY += lineHeight;
  1662. totalPeak += poolInfo.m_peakUsed;
  1663. totalAllocs += poolInfo.m_numAllocs;
  1664. totalFrees += poolInfo.m_numFrees;
  1665. float percentUsed = static_cast<float>(poolInfo.m_memoryUsed) / static_cast<float>(globalInfo.m_memoryUsed);
  1666. float percentTotal = static_cast<float>(poolInfo.m_memoryUsed) / static_cast<float>(globalInfo.m_memoryReserved);
  1667. // Calculate a color (green->-yellow->-red) based on percentage.
  1668. AZ::Color percentColor;
  1669. if (percentUsed < 0.5f)
  1670. {
  1671. percentColor = greenColor.Lerp(yellowColor, percentUsed * 2.f);
  1672. }
  1673. else
  1674. {
  1675. percentColor = yellowColor.Lerp(redColor, (percentUsed * 2.f) - 1.f);
  1676. }
  1677. percentUsed *= 100.f;
  1678. percentTotal *= 100.f;
  1679. debugDisplay.SetColor(percentColor);
  1680. // ID
  1681. str = AZStd::string::format("%d", poolInfo.m_poolId);
  1682. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[0], posY, textSize, str.c_str());
  1683. // Name
  1684. str = AZStd::string::format("%s", poolInfo.m_poolName);
  1685. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[1], posY, textSize, str.c_str());
  1686. // Current Used (bytes)
  1687. BytesToString(poolInfo.m_memoryUsed, buffer, bufferSize);
  1688. str = AZStd::string::format("%s", buffer);
  1689. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[2], posY, textSize, str.c_str());
  1690. // Peak Used (bytes)
  1691. BytesToString(poolInfo.m_peakUsed, buffer, bufferSize);
  1692. str = AZStd::string::format("%s", buffer);
  1693. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[3], posY, textSize, str.c_str());
  1694. // % of Used (percentage)
  1695. str = AZStd::string::format("%.2f %%", percentUsed);
  1696. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[4], posY, textSize, str.c_str());
  1697. // % of Total (percentage)
  1698. str = AZStd::string::format("%.2f %%", percentTotal);
  1699. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[5], posY, textSize, str.c_str());
  1700. // # Allocs
  1701. str = AZStd::string::format("%u", poolInfo.m_numAllocs);
  1702. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[6], posY, textSize, str.c_str());
  1703. // # Frees
  1704. str = AZStd::string::format("%u", poolInfo.m_numFrees);
  1705. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[7], posY, textSize, str.c_str());
  1706. }
  1707. debugDisplay.SetColor(whiteColor);
  1708. posY += (2.f * lineHeight);
  1709. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[1], posY, textSize, "Name");
  1710. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[2], posY, textSize, "Total Used");
  1711. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[3], posY, textSize, "Peak Used");
  1712. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[4], posY, textSize, "% Used");
  1713. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[5], posY, textSize, "Total Size");
  1714. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[6], posY, textSize, "# Allocs");
  1715. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[7], posY, textSize, "# Frees");
  1716. posY += lineHeight;
  1717. str = AZStd::string::format("%s", globalInfo.m_poolName);
  1718. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[1], posY, textSize, str.c_str());
  1719. float totalUsagePct = static_cast<float>(globalInfo.m_memoryUsed) / static_cast<float>(globalInfo.m_memoryReserved);
  1720. AZ::Color percentTotalColor;
  1721. if (totalUsagePct < 0.5f)
  1722. {
  1723. percentTotalColor = greenColor.Lerp(yellowColor, totalUsagePct * 2.f);
  1724. }
  1725. else
  1726. {
  1727. percentTotalColor = yellowColor.Lerp(redColor, (totalUsagePct * 2.f) - 1.f);
  1728. }
  1729. totalUsagePct *= 100.f;
  1730. debugDisplay.SetColor(percentTotalColor);
  1731. BytesToString(globalInfo.m_memoryUsed, buffer, bufferSize);
  1732. str = AZStd::string::format("%s", buffer);
  1733. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[2], posY, textSize, str.c_str());
  1734. BytesToString(totalPeak, buffer, bufferSize);
  1735. str = AZStd::string::format("%s", buffer);
  1736. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[3], posY, textSize, str.c_str());
  1737. str = AZStd::string::format("%.2f %%", totalUsagePct);
  1738. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[4], posY, textSize, str.c_str());
  1739. BytesToString(globalInfo.m_memoryReserved, buffer, bufferSize);
  1740. str = AZStd::string::format("%s", buffer);
  1741. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[5], posY, textSize, str.c_str());
  1742. debugDisplay.SetColor(whiteColor);
  1743. str = AZStd::string::format("%llu", totalAllocs);
  1744. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[6], posY, textSize, str.c_str());
  1745. str = AZStd::string::format("%llu", totalFrees);
  1746. debugDisplay.Draw2dTextLabel(fPosX + xTablePositions[7], posY, textSize, str.c_str());
  1747. }
  1748. else
  1749. {
  1750. debugDisplay.SetColor(whiteColor);
  1751. debugDisplay.Draw2dTextLabel(fPosX, posY + lineHeight, textSize, "** No memory pool information is available for display **");
  1752. }
  1753. }
  1754. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1755. void CAudioTranslationLayer::DrawAudioObjectDebugInfo(AzFramework::DebugDisplayRequests& debugDisplay)
  1756. {
  1757. debugDisplay.DepthTestOff();
  1758. SATLWorldPosition oListenerPosition;
  1759. m_oAudioListenerMgr.GetDefaultListenerPosition(oListenerPosition);
  1760. m_oAudioObjectMgr.DrawPerObjectDebugInfo(debugDisplay, oListenerPosition.GetPositionVec());
  1761. debugDisplay.DepthTestOn();
  1762. }
  1763. #endif // !AUDIO_RELEASE
  1764. } // namespace Audio