ATLAudioObject.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. #pragma once
  9. #include <AzCore/Math/Vector3.h>
  10. #include <AzCore/std/containers/set.h>
  11. #include <ATLEntities.h>
  12. #include <ATLEntityData.h>
  13. #include <climits>
  14. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  15. namespace AzFramework
  16. {
  17. class DebugDisplayRequests;
  18. }
  19. class ATLAudioObjectTest;
  20. namespace Audio
  21. {
  22. ///////////////////////////////////////////////////////////////////////////////////////////////////
  23. struct SATLTriggerImplState
  24. {
  25. TATLEnumFlagsType nFlags{ eATS_NONE };
  26. };
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////
  28. struct SATLTriggerInstanceState
  29. {
  30. TATLEnumFlagsType nFlags{ eATS_NONE };
  31. TAudioControlID nTriggerID{ INVALID_AUDIO_CONTROL_ID };
  32. size_t numPlayingEvents{ 0 };
  33. void* pOwner{ nullptr };
  34. };
  35. ///////////////////////////////////////////////////////////////////////////////////////////////////
  36. // CATLAudioObjectBase-related typedefs
  37. using TObjectEventSet = ATLSetLookupType<TAudioEventID>;
  38. using TObjectTriggerInstanceSet = ATLSetLookupType<TAudioTriggerInstanceID>;
  39. using TObjectTriggerImplStates = ATLMapLookupType<TAudioTriggerImplID, SATLTriggerImplState>;
  40. using TObjectTriggerStates = ATLMapLookupType<TAudioTriggerInstanceID, SATLTriggerInstanceState>;
  41. using TObjectStateMap = ATLMapLookupType<TAudioControlID, TAudioSwitchStateID>;
  42. using TObjectRtpcMap = ATLMapLookupType<TAudioControlID, float>;
  43. using TObjectEnvironmentMap = ATLMapLookupType<TAudioEnvironmentID, float>;
  44. ///////////////////////////////////////////////////////////////////////////////////////////////////
  45. // this class wraps the common functionality shared by the AudioObject and the GlobalAudioObject
  46. class CATLAudioObjectBase
  47. : public CATLEntity<TAudioObjectID>
  48. {
  49. public:
  50. void TriggerInstanceStarting(TAudioTriggerInstanceID triggerInstanceId, TAudioControlID audioControlId);
  51. void TriggerInstanceStarted(TAudioTriggerInstanceID triggerInstanceId, void* owner);
  52. void TriggerInstanceFinished(TObjectTriggerStates::const_iterator iter);
  53. void EventStarted(const CATLEvent* const atlEvent);
  54. void EventFinished(const CATLEvent* const atlEvent);
  55. void SetSwitchState(const TAudioControlID nSwitchID, const TAudioSwitchStateID nStateID);
  56. void SetRtpc(const TAudioControlID nRtpcID, const float fValue);
  57. void SetEnvironmentAmount(const TAudioEnvironmentID nEnvironmentID, const float fAmount);
  58. const TObjectTriggerImplStates& GetTriggerImpls() const;
  59. const TObjectRtpcMap& GetRtpcs() const;
  60. const TObjectEnvironmentMap& GetEnvironments() const;
  61. void ClearRtpcs();
  62. void ClearEnvironments();
  63. const TObjectEventSet& GetActiveEvents() const
  64. {
  65. return m_cActiveEvents;
  66. }
  67. bool HasActiveEvents() const;
  68. TObjectTriggerInstanceSet GetTriggerInstancesByOwner(void* const pOwner) const;
  69. void IncrementRefCount()
  70. {
  71. ++m_nRefCounter;
  72. }
  73. void DecrementRefCount()
  74. {
  75. AZ_Assert(m_nRefCounter > 0, "CATLAudioObjectBase - Too many refcount decrements!");
  76. --m_nRefCounter;
  77. }
  78. size_t GetRefCount() const
  79. {
  80. return m_nRefCounter;
  81. }
  82. void SetImplDataPtr(IATLAudioObjectData* const pImplData)
  83. {
  84. m_pImplData = pImplData;
  85. }
  86. IATLAudioObjectData* GetImplDataPtr() const
  87. {
  88. return m_pImplData;
  89. }
  90. virtual bool HasPosition() const = 0;
  91. protected:
  92. CATLAudioObjectBase(const TAudioObjectID nObjectID, const EATLDataScope eDataScope, IATLAudioObjectData* const pImplData = nullptr)
  93. : CATLEntity<TAudioObjectID>(nObjectID, eDataScope)
  94. , m_nRefCounter(0)
  95. , m_pImplData(pImplData)
  96. {}
  97. virtual void Clear();
  98. virtual void Update(const float fUpdateIntervalMS, const SATLWorldPosition& rListenerPosition);
  99. TObjectEventSet m_cActiveEvents;
  100. TObjectTriggerStates m_cTriggers;
  101. TObjectTriggerImplStates m_cTriggerImpls;
  102. TObjectRtpcMap m_cRtpcs;
  103. TObjectEnvironmentMap m_cEnvironments;
  104. TObjectStateMap m_cSwitchStates;
  105. size_t m_nRefCounter;
  106. IATLAudioObjectData* m_pImplData;
  107. #if !defined(AUDIO_RELEASE)
  108. public:
  109. void CheckBeforeRemoval(const CATLDebugNameStore* const pDebugNameStore);
  110. protected:
  111. ///////////////////////////////////////////////////////////////////////////////////////////////
  112. class CStateDebugDrawData
  113. {
  114. public:
  115. CStateDebugDrawData(const TAudioSwitchStateID nState = INVALID_AUDIO_SWITCH_STATE_ID);
  116. ~CStateDebugDrawData();
  117. void Update(const TAudioSwitchStateID nNewState);
  118. TAudioSwitchStateID nCurrentState;
  119. float fCurrentAlpha;
  120. private:
  121. static const float fMaxAlpha;
  122. static const float fMinAlpha;
  123. static const int nMaxToMinUpdates;
  124. };
  125. using TStateDrawInfoMap = ATLMapLookupType<TAudioControlID, CStateDebugDrawData>;
  126. AZStd::string GetTriggerNames(const char* const sSeparator, const CATLDebugNameStore* const pDebugNameStore);
  127. AZStd::string GetEventIDs(const char* const sSeparator);
  128. mutable TStateDrawInfoMap m_cStateDrawInfoMap;
  129. #endif // !AUDIO_RELEASE
  130. };
  131. ///////////////////////////////////////////////////////////////////////////////////////////////////
  132. class CATLGlobalAudioObject
  133. : public CATLAudioObjectBase
  134. {
  135. public:
  136. CATLGlobalAudioObject(const TAudioObjectID nID, IATLAudioObjectData* const pImplData)
  137. : CATLAudioObjectBase(nID, eADS_GLOBAL, pImplData)
  138. {}
  139. bool HasPosition() const override
  140. {
  141. return false;
  142. }
  143. };
  144. // Physics-related obstruction/occlusion raycasting...
  145. static constexpr AZ::u16 s_maxHitResultsPerRaycast = 5;
  146. static constexpr AZ::u16 s_maxRaysPerObject = 5;
  147. ///////////////////////////////////////////////////////////////////////////////////////////////////
  148. struct AudioRaycastRequest
  149. {
  150. AzPhysics::RayCastRequest m_request{};
  151. TAudioObjectID m_audioObjectId = INVALID_AUDIO_OBJECT_ID;
  152. size_t m_rayIndex = 0;
  153. AudioRaycastRequest(const AzPhysics::RayCastRequest& request, TAudioObjectID audioObjectId, size_t rayId)
  154. : m_request(request)
  155. , m_audioObjectId(audioObjectId)
  156. , m_rayIndex(rayId)
  157. {}
  158. };
  159. ///////////////////////////////////////////////////////////////////////////////////////////////////
  160. struct AudioRaycastResult
  161. {
  162. AZStd::vector<AzPhysics::SceneQueryHit> m_result{};
  163. TAudioObjectID m_audioObjectId = INVALID_AUDIO_OBJECT_ID;
  164. size_t m_rayIndex = 0;
  165. AudioRaycastResult(AZStd::vector<AzPhysics::SceneQueryHit>&& result, TAudioObjectID audioObjectId, size_t rayId)
  166. : m_result(AZStd::move(result))
  167. , m_audioObjectId(audioObjectId)
  168. , m_rayIndex(rayId)
  169. {}
  170. };
  171. ///////////////////////////////////////////////////////////////////////////////////////////////////
  172. class AudioRaycastRequests
  173. : public AZ::EBusTraits
  174. {
  175. public:
  176. virtual ~AudioRaycastRequests() = default;
  177. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  178. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
  179. // No mutex! All audio raycast requests are initiated and received on the Audio Thread.
  180. virtual void PushAudioRaycastRequest(const AudioRaycastRequest&) = 0;
  181. };
  182. using AudioRaycastRequestBus = AZ::EBus<AudioRaycastRequests>;
  183. ///////////////////////////////////////////////////////////////////////////////////////////////////
  184. class AudioRaycastNotifications
  185. : public AZ::EBusTraits
  186. {
  187. public:
  188. virtual ~AudioRaycastNotifications() = default;
  189. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  190. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  191. // No mutex! All audio raycast notifications are initiated and received on the Audio Thread.
  192. using BusIdType = TAudioObjectID;
  193. virtual void OnAudioRaycastResults(const AudioRaycastResult&) = 0;
  194. };
  195. using AudioRaycastNotificationBus = AZ::EBus<AudioRaycastNotifications>;
  196. ///////////////////////////////////////////////////////////////////////////////////////////////////
  197. struct RaycastInfo
  198. {
  199. AZStd::fixed_vector<AzPhysics::SceneQueryHit, s_maxHitResultsPerRaycast> m_hits;
  200. AzPhysics::RayCastRequest m_raycastRequest;
  201. float m_contribution = 0.f;
  202. float m_cacheTimerMs = 0.f;
  203. AZ::u16 m_numHits = 0;
  204. bool m_pending = false; //!< Whether the ray has been requested and is still pending.
  205. bool m_cached = false;
  206. void UpdateContribution();
  207. void Reset()
  208. {
  209. m_hits.clear();
  210. m_contribution = 0.f;
  211. m_cacheTimerMs = 0.f;
  212. m_numHits = 0;
  213. m_pending = false;
  214. m_cached = false;
  215. }
  216. float GetDistanceScaledContribution() const;
  217. float GetNearestHitDistance() const;
  218. };
  219. ///////////////////////////////////////////////////////////////////////////////////////////////////
  220. class RaycastProcessor
  221. {
  222. friend class CATLAudioObject;
  223. public:
  224. RaycastProcessor(const TAudioObjectID objectId, const SATLWorldPosition& objectPosition);
  225. void Update(float deltaMs);
  226. void Reset();
  227. void SetType(ObstructionType calcType);
  228. bool CanRun() const;
  229. void Run(const SATLWorldPosition& listenerPosition);
  230. void CastRay(const AZ::Vector3& origin, const AZ::Vector3& dest, const AZ::u16 rayIndex);
  231. float GetObstruction() const
  232. {
  233. return AZ::GetClamp(m_obstructionValue.GetCurrent(), 0.f, 1.f);
  234. }
  235. float GetOcclusion() const
  236. {
  237. return AZ::GetClamp(m_occlusionValue.GetCurrent(), 0.f, 1.f);
  238. }
  239. void SetupTestRay(AZ::u16 rayIndex);
  240. #if !defined(AUDIO_RELEASE)
  241. void DrawObstructionRays(AzFramework::DebugDisplayRequests& debugDisplay) const;
  242. #endif // !AUDIO_RELEASE
  243. static constexpr float s_epsilon = 1e-3f;
  244. static bool s_raycastsEnabled;
  245. private:
  246. AZStd::fixed_vector<RaycastInfo, s_maxRaysPerObject> m_rayInfos;
  247. const SATLWorldPosition& m_position;
  248. CSmoothFloat m_obstructionValue;
  249. CSmoothFloat m_occlusionValue;
  250. TAudioObjectID m_audioObjectId;
  251. ObstructionType m_obstOccType;
  252. };
  253. ///////////////////////////////////////////////////////////////////////////////////////////////////
  254. class CATLAudioObject
  255. : public CATLAudioObjectBase
  256. , public AudioRaycastNotificationBus::Handler
  257. {
  258. friend class ::ATLAudioObjectTest;
  259. public:
  260. explicit CATLAudioObject(const TAudioObjectID nID, IATLAudioObjectData* const pImplData = nullptr)
  261. : CATLAudioObjectBase(nID, eADS_NONE, pImplData)
  262. , m_nFlags(eAOF_NONE)
  263. , m_fPreviousVelocity(0.0f)
  264. , m_raycastProcessor(nID, m_oPosition)
  265. {
  266. }
  267. ~CATLAudioObject() override
  268. {
  269. AudioRaycastNotificationBus::Handler::BusDisconnect();
  270. }
  271. CATLAudioObject(const CATLAudioObject&) = delete; // not defined; calls will fail at compile time
  272. CATLAudioObject& operator=(const CATLAudioObject&) = delete; // not defined; calls will fail at compile time
  273. // CATLAudioObjectBase
  274. bool HasPosition() const override
  275. {
  276. return true;
  277. }
  278. void Clear() override;
  279. void Update(const float fUpdateIntervalMS, const SATLWorldPosition& rListenerPosition) override;
  280. // ~CATLAudioObjectBase
  281. void SetPosition(const SATLWorldPosition& oNewPosition);
  282. void SetRaycastCalcType(const ObstructionType type);
  283. void RunRaycasts(const SATLWorldPosition& listenerPos);
  284. bool CanRunRaycasts() const;
  285. void GetObstOccData(SATLSoundPropagationData& data) const;
  286. // AudioRaycastNotificationBus::Handler
  287. void OnAudioRaycastResults(const AudioRaycastResult& result) override;
  288. void SetVelocityTracking(const bool bTrackingOn);
  289. bool GetVelocityTracking() const
  290. {
  291. return (m_nFlags & eAOF_TRACK_VELOCITY) != 0;
  292. }
  293. void UpdateVelocity(const float fUpdateIntervalMS);
  294. private:
  295. TATLEnumFlagsType m_nFlags;
  296. float m_fPreviousVelocity;
  297. SATLWorldPosition m_oPosition;
  298. SATLWorldPosition m_oPreviousPosition;
  299. RaycastProcessor m_raycastProcessor;
  300. #if !defined(AUDIO_RELEASE)
  301. public:
  302. void DrawDebugInfo(
  303. AzFramework::DebugDisplayRequests& debugDisplay,
  304. const AZ::Vector3& listenerPos,
  305. const CATLDebugNameStore* const debugNameStore) const;
  306. const SATLWorldPosition& GetPosition() const
  307. {
  308. return m_oPosition;
  309. }
  310. #endif // !AUDIO_RELEASE
  311. };
  312. } // namespace Audio