AkGameplayStatics.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. /*=============================================================================
  16. AkAudioClasses.cpp:
  17. =============================================================================*/
  18. #include "AkGameplayStatics.h"
  19. #include "AkAmbientSound.h"
  20. #include "AkAudioDevice.h"
  21. #include "AkAudioEvent.h"
  22. #include "AkAudioType.h"
  23. #include "AkComponent.h"
  24. #include "AkEffectShareSet.h"
  25. #include "AkRtpc.h"
  26. #include "AkStateValue.h"
  27. #include "AkSwitchValue.h"
  28. #include "AkTrigger.h"
  29. #include "Engine/GameEngine.h"
  30. #include "EngineUtils.h"
  31. #include "AkAcousticPortal.h"
  32. #include "AkRoomComponent.h"
  33. #include "AkAuxBus.h"
  34. #include "Wwise/API/WwiseSoundEngineAPI.h"
  35. #include "Wwise/API/WwiseSpatialAudioAPI.h"
  36. #include "Wwise/WwiseExternalSourceManager.h"
  37. #include "AkComponentHelpers.h"
  38. #include "inttypes.h"
  39. #include "WwiseInitBankLoader/WwiseInitBankLoader.h"
  40. bool UAkGameplayStatics::m_bSoundEngineRecording = false;
  41. /*-----------------------------------------------------------------------------
  42. UAkGameplayStatics.
  43. -----------------------------------------------------------------------------*/
  44. UAkGameplayStatics::UAkGameplayStatics(const class FObjectInitializer& ObjectInitializer)
  45. : Super(ObjectInitializer)
  46. {
  47. // Property initialization
  48. }
  49. class UAkComponent * UAkGameplayStatics::GetAkComponent( class USceneComponent* AttachToComponent, bool& ComponentCreated, FName AttachPointName, FVector Location, EAttachLocation::Type LocationType )
  50. {
  51. if ( AttachToComponent == NULL )
  52. {
  53. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::GetAkComponent: NULL AttachToComponent specified!"));
  54. return NULL;
  55. }
  56. FAkAudioDevice * AkAudioDevice = FAkAudioDevice::Get();
  57. if( AkAudioDevice )
  58. {
  59. return AkAudioDevice->GetAkComponent( AttachToComponent, AttachPointName, &Location, LocationType, ComponentCreated );
  60. }
  61. return NULL;
  62. }
  63. bool UAkGameplayStatics::IsEditor()
  64. {
  65. #if WITH_EDITOR
  66. return true;
  67. #else
  68. return false;
  69. #endif
  70. }
  71. bool UAkGameplayStatics::IsGame(UObject* WorldContextObject)
  72. {
  73. EWorldType::Type WorldType = EWorldType::None;
  74. if (WorldContextObject)
  75. {
  76. UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
  77. if(World)
  78. WorldType = World->WorldType;
  79. }
  80. return WorldType == EWorldType::Game || WorldType == EWorldType::GamePreview || WorldType == EWorldType::PIE;
  81. }
  82. int32 UAkGameplayStatics::PostEvent(UAkAudioEvent* AkEvent, AActor* Actor, int32 CallbackMask,
  83. const FOnAkPostEventCallback& PostEventCallback, bool bStopWhenAttachedToDestroyed)
  84. {
  85. if (LIKELY(!IsValid(AkEvent)))
  86. {
  87. UE_LOG(LogAkAudio, Warning, TEXT("Failed to post invalid AkAudioEvent."))
  88. return AK_INVALID_PLAYING_ID;
  89. }
  90. return AkEvent->PostOnActor(Actor, PostEventCallback, CallbackMask, bStopWhenAttachedToDestroyed);
  91. }
  92. int32 UAkGameplayStatics::PostAndWaitForEndOfEvent(UAkAudioEvent* AkEvent, AActor* Actor, bool bStopWhenAttachedToDestroyed,
  93. FLatentActionInfo LatentInfo)
  94. {
  95. if (UNLIKELY(!IsValid(AkEvent)))
  96. {
  97. UE_LOG(LogAkAudio, Error, TEXT("Failed to post and wait invalid AkAudioEvent on actor '%s'."), IsValid(Actor) ? *Actor->GetName() : TEXT("(invalid)"));
  98. return AK_INVALID_PLAYING_ID;
  99. }
  100. return AkEvent->PostOnActorAndWait(Actor, bStopWhenAttachedToDestroyed, LatentInfo);
  101. }
  102. int32 UAkGameplayStatics::PostEventAtLocation(class UAkAudioEvent* AkEvent, FVector Location, FRotator Orientation, UObject* WorldContextObject)
  103. {
  104. if (LIKELY(IsValid(AkEvent)))
  105. {
  106. return AkEvent->PostAtLocation(Location, Orientation, {}, 0, WorldContextObject);
  107. }
  108. AkDeviceAndWorld DeviceAndWorld(WorldContextObject);
  109. if (UNLIKELY(!DeviceAndWorld.IsValid()))
  110. return AK_INVALID_PLAYING_ID;
  111. return AkEvent->PostAtLocation(Location, Orientation, {}, 0, WorldContextObject);
  112. }
  113. UAkComponent* UAkGameplayStatics::SpawnAkComponentAtLocation(UObject* WorldContextObject, class UAkAudioEvent* AkEvent, FVector Location, FRotator Orientation, bool AutoPost, const FString& EventName, bool AutoDestroy /* = true*/)
  114. {
  115. AkDeviceAndWorld DeviceAndWorld(WorldContextObject);
  116. if (UNLIKELY(!DeviceAndWorld.IsValid()))
  117. {
  118. return nullptr;
  119. }
  120. return DeviceAndWorld.AkAudioDevice->SpawnAkComponentAtLocation(AkEvent, Location, Orientation, AutoPost, EventName, AutoDestroy, DeviceAndWorld.CurrentWorld);
  121. }
  122. void UAkGameplayStatics::SetRTPCValue(const UAkRtpc* RTPCValue, float Value, int32 InterpolationTimeMs, AActor* Actor, FName RTPC)
  123. {
  124. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  125. if (AudioDevice)
  126. {
  127. if (RTPCValue)
  128. {
  129. AudioDevice->SetRTPCValue(RTPCValue, Value, InterpolationTimeMs, Actor);
  130. }
  131. else if (RTPC.IsValid())
  132. {
  133. AudioDevice->SetRTPCValue(*RTPC.ToString(), Value, InterpolationTimeMs, Actor);
  134. }
  135. }
  136. }
  137. void UAkGameplayStatics::GetRTPCValue(const UAkRtpc* RTPCValue, int32 PlayingID, ERTPCValueType InputValueType, float& Value, ERTPCValueType& OutputValueType, AActor* Actor, FName RTPC)
  138. {
  139. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  140. if (AudioDevice)
  141. {
  142. AK::SoundEngine::Query::RTPCValue_type RTPCType = (AK::SoundEngine::Query::RTPCValue_type)InputValueType;
  143. AkGameObjectID IdToGet = AK_INVALID_GAME_OBJECT;
  144. if (Actor != nullptr)
  145. {
  146. UAkComponent * ComponentToGet = AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  147. IdToGet = ComponentToGet->GetAkGameObjectID();
  148. }
  149. if (RTPCValue)
  150. {
  151. AudioDevice->GetRTPCValue(RTPCValue, IdToGet, PlayingID, Value, RTPCType);
  152. }
  153. else if (RTPC.IsValid())
  154. {
  155. AudioDevice->GetRTPCValue(*RTPC.ToString(), IdToGet, PlayingID, Value, RTPCType);
  156. }
  157. OutputValueType = (ERTPCValueType)RTPCType;
  158. }
  159. }
  160. void UAkGameplayStatics::ResetRTPCValue(UAkRtpc const* RTPCValue, int32 InterpolationTimeMs, AActor* Actor, FName RTPC)
  161. {
  162. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  163. if (AudioDevice)
  164. {
  165. AkGameObjectID IdToGet = AK_INVALID_GAME_OBJECT;
  166. if (Actor != nullptr)
  167. {
  168. UAkComponent* ComponentToGet = AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  169. IdToGet = ComponentToGet->GetAkGameObjectID();
  170. }
  171. if (RTPCValue == NULL && RTPC.IsNone())
  172. {
  173. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::ResetRTPCValue: No parameter specified!"));
  174. return;
  175. }
  176. AKRESULT Result = AK_Success;
  177. if (RTPCValue)
  178. {
  179. Result = AudioDevice->ResetRTPCValue(RTPCValue, IdToGet, InterpolationTimeMs);
  180. }
  181. else if (RTPC.IsValid())
  182. {
  183. Result = AudioDevice->ResetRTPCValue(*RTPC.ToString(), IdToGet, InterpolationTimeMs);
  184. }
  185. else
  186. {
  187. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::ResetRTPCValue: Could not reset RTPC value, valid RTPC value not provided"));
  188. }
  189. if (Result == AK_IDNotFound)
  190. {
  191. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::ResetRTPCValue: Could not reset RTPC value, RTPC %s not found"), *RTPC.ToString());
  192. }
  193. else if (Result != AK_Success)
  194. {
  195. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::ResetRTPCValue: Could not reset RTPC value!"));
  196. }
  197. }
  198. }
  199. void UAkGameplayStatics::SetState(const UAkStateValue* StateValue, FName stateGroup, FName state)
  200. {
  201. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  202. if( AudioDevice && stateGroup.IsValid() && state.IsValid() )
  203. {
  204. if (StateValue)
  205. {
  206. AudioDevice->SetState(StateValue);
  207. }
  208. else if (stateGroup.IsValid() && state.IsValid())
  209. {
  210. AudioDevice->SetState(*stateGroup.ToString(), *state.ToString());
  211. }
  212. }
  213. }
  214. void UAkGameplayStatics::PostTrigger(const UAkTrigger* TriggerValue, AActor* Actor, FName Trigger)
  215. {
  216. if ( Actor == NULL )
  217. {
  218. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::PostTrigger: NULL Actor specified!"));
  219. return;
  220. }
  221. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  222. if( AudioDevice)
  223. {
  224. if (TriggerValue)
  225. {
  226. AudioDevice->PostTrigger(TriggerValue, Actor);
  227. }
  228. else if (Trigger.IsValid())
  229. {
  230. AudioDevice->PostTrigger(*Trigger.ToString(), Actor);
  231. }
  232. }
  233. }
  234. void UAkGameplayStatics::SetSwitch(const UAkSwitchValue* SwitchValue, AActor* Actor, FName SwitchGroup, FName SwitchState)
  235. {
  236. if (Actor == NULL)
  237. {
  238. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetSwitch: NULL Actor specified!"));
  239. return;
  240. }
  241. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  242. if (AudioDevice)
  243. {
  244. if (SwitchValue)
  245. {
  246. AudioDevice->SetSwitch(SwitchValue, Actor);
  247. }
  248. else if (SwitchGroup.IsValid() && SwitchState.IsValid())
  249. {
  250. AudioDevice->SetSwitch(*SwitchGroup.ToString(), *SwitchState.ToString(), Actor);
  251. }
  252. }
  253. }
  254. void UAkGameplayStatics::SetMultiplePositions(UAkComponent* GameObjectAkComponent, TArray<FTransform> Positions,
  255. AkMultiPositionType MultiPositionType /*= AkMultiPositionType::MultiPositionType_MultiDirections*/)
  256. {
  257. if (GameObjectAkComponent == NULL)
  258. {
  259. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetMultiplePositions: NULL Component specified!"));
  260. return;
  261. }
  262. FAkAudioDevice * pAudioDevice = FAkAudioDevice::Get();
  263. if (pAudioDevice)
  264. {
  265. pAudioDevice->SetMultiplePositions(GameObjectAkComponent, Positions, MultiPositionType);
  266. }
  267. }
  268. void UAkGameplayStatics::SetMultipleChannelEmitterPositions(UAkComponent* GameObjectAkComponent,
  269. TArray<AkChannelConfiguration> ChannelMasks,
  270. TArray<FTransform> Positions,
  271. AkMultiPositionType MultiPositionType
  272. )
  273. {
  274. if (GameObjectAkComponent == NULL)
  275. {
  276. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetMultipleChannelEmitterPositions: NULL Component specified!"));
  277. return;
  278. }
  279. FAkAudioDevice * pAudioDevice = FAkAudioDevice::Get();
  280. if (pAudioDevice)
  281. {
  282. pAudioDevice->SetMultiplePositions(GameObjectAkComponent, ChannelMasks, Positions, MultiPositionType);
  283. }
  284. }
  285. void UAkGameplayStatics::SetMultipleChannelMaskEmitterPositions(UAkComponent* GameObjectAkComponent,
  286. TArray<FAkChannelMask> ChannelMasks,
  287. TArray<FTransform> Positions,
  288. AkMultiPositionType MultiPositionType
  289. )
  290. {
  291. if (GameObjectAkComponent == NULL)
  292. {
  293. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetMultipleChannelMaskEmitterPositions: NULL Component specified!"));
  294. return;
  295. }
  296. FAkAudioDevice * pAudioDevice = FAkAudioDevice::Get();
  297. if (pAudioDevice)
  298. {
  299. pAudioDevice->SetMultiplePositions(GameObjectAkComponent, ChannelMasks, Positions, MultiPositionType);
  300. }
  301. }
  302. void UAkGameplayStatics::UseReverbVolumes(bool inUseReverbVolumes, class AActor* Actor )
  303. {
  304. if ( Actor == NULL )
  305. {
  306. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::UseReverbVolumes: NULL Actor specified!"));
  307. return;
  308. }
  309. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  310. if( AudioDevice )
  311. {
  312. UAkComponent * ComponentToSet = AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  313. if( ComponentToSet != NULL )
  314. {
  315. ComponentToSet->bUseReverbVolumes = inUseReverbVolumes;
  316. }
  317. }
  318. }
  319. void UAkGameplayStatics::SetReflectionsOrder(int Order, bool RefreshPaths)
  320. {
  321. if (Order > 4 || Order < 0)
  322. {
  323. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetReflectionsOrder: Invalid reflection order value (%d). Clamping between 0 and 4."), Order);
  324. Order = FMath::Clamp(Order, 0, 4);
  325. }
  326. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  327. if (AudioDevice)
  328. {
  329. AudioDevice->SetReflectionsOrder(Order, RefreshPaths);
  330. }
  331. }
  332. void UAkGameplayStatics::SetDiffractionOrder(int InDiffractionOrder, bool bInUpdatePaths)
  333. {
  334. if (InDiffractionOrder < 0)
  335. {
  336. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetDiffractionOrder: Invalid diffraction order value (%d). Clamping to 0."), InDiffractionOrder);
  337. InDiffractionOrder = 0;
  338. }
  339. auto* SpatialAudio = IWwiseSpatialAudioAPI::Get();
  340. if (UNLIKELY(!SpatialAudio)) return;
  341. SpatialAudio->SetDiffractionOrder(InDiffractionOrder, bInUpdatePaths);
  342. }
  343. void UAkGameplayStatics::SetMaxEmitterRoomAuxSends(int InMaxEmitterRoomAuxSends)
  344. {
  345. if (InMaxEmitterRoomAuxSends < 0)
  346. {
  347. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetMaxEmitterRoomAuxSends: Invalid MaxEmitterRoomAuxSends value (%d). Clamping to 0."), InMaxEmitterRoomAuxSends);
  348. InMaxEmitterRoomAuxSends = 0;
  349. }
  350. auto* SpatialAudio = IWwiseSpatialAudioAPI::Get();
  351. if (UNLIKELY(!SpatialAudio)) return;
  352. SpatialAudio->SetMaxEmitterRoomAuxSends(InMaxEmitterRoomAuxSends);
  353. }
  354. void UAkGameplayStatics::SetNumberOfPrimaryRays(int InNbPrimaryRays)
  355. {
  356. if (InNbPrimaryRays < 0)
  357. {
  358. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetNumberOfPrimaryRays: Invalid number of Primary Rays (%d). Clamping to 0."), InNbPrimaryRays);
  359. InNbPrimaryRays = 0;
  360. }
  361. auto* SpatialAudio = IWwiseSpatialAudioAPI::Get();
  362. if (UNLIKELY(!SpatialAudio)) return;
  363. SpatialAudio->SetNumberOfPrimaryRays(InNbPrimaryRays);
  364. }
  365. void UAkGameplayStatics::SetLoadBalancingSpread(int InNbFrames)
  366. {
  367. if (InNbFrames < 1)
  368. {
  369. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetLoadBalancingSpread: Invalid number of frames (%d). Clamping to 1."), InNbFrames);
  370. InNbFrames = 1;
  371. }
  372. auto* SpatialAudio = IWwiseSpatialAudioAPI::Get();
  373. if (UNLIKELY(!SpatialAudio)) return;
  374. SpatialAudio->SetLoadBalancingSpread(InNbFrames);
  375. }
  376. void UAkGameplayStatics::SetPortalObstructionAndOcclusion(UAkPortalComponent* PortalComponent, float ObstructionValue, float OcclusionValue)
  377. {
  378. if (ObstructionValue > 1.f || ObstructionValue < 0.f)
  379. {
  380. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetPortalObstructionAndOcclusion: Setting Portal %s to an invalid obstruction value (%.6g). Clamping between 0.0 and 1.0."), *PortalComponent->GetPortalName(), ObstructionValue);
  381. ObstructionValue = FMath::Clamp(ObstructionValue, 0.f, 1.f);
  382. }
  383. if (OcclusionValue > 1.f || OcclusionValue < 0.f)
  384. {
  385. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetPortalObstructionAndOcclusion: Setting Portal %s to an invalid occlusion value (%.6g). Clamping between 0.0 and 1.0."), *PortalComponent->GetPortalName(), OcclusionValue);
  386. OcclusionValue = FMath::Clamp(OcclusionValue, 0.f, 1.f);
  387. }
  388. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  389. if (AudioDevice)
  390. {
  391. AudioDevice->SetPortalObstructionAndOcclusion(PortalComponent, ObstructionValue, OcclusionValue);
  392. }
  393. }
  394. void UAkGameplayStatics::SetGameObjectToPortalObstruction(UAkComponent* GameObjectAkComponent, UAkPortalComponent* PortalComponent, float ObstructionValue)
  395. {
  396. if (ObstructionValue > 1.f || ObstructionValue < 0.f)
  397. {
  398. FString gameObjectName;
  399. GameObjectAkComponent->GetAkGameObjectName(gameObjectName);
  400. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetGameObjectToPortalObstruction: Setting an invalid obstruction value (%.6g) between Game Object %s and Portal %s. Clamping between 0.0 and 1.0."), ObstructionValue, *gameObjectName, *PortalComponent->GetPortalName());
  401. ObstructionValue = FMath::Clamp(ObstructionValue, 0.f, 1.f);
  402. }
  403. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  404. if (AudioDevice)
  405. {
  406. AudioDevice->SetGameObjectToPortalObstruction(GameObjectAkComponent, PortalComponent, ObstructionValue);
  407. }
  408. }
  409. void UAkGameplayStatics::SetPortalToPortalObstruction(UAkPortalComponent* PortalComponent0, UAkPortalComponent* PortalComponent1, float ObstructionValue)
  410. {
  411. if (ObstructionValue > 1.f || ObstructionValue < 0.f)
  412. {
  413. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetGameObjectToPortalObstruction: Setting an invalid obstruction value (%.6g) between Portals %s and %s. Clamping between 0.0 and 1.0."), ObstructionValue, *PortalComponent0->GetPortalName(), *PortalComponent1->GetPortalName());
  414. ObstructionValue = FMath::Clamp(ObstructionValue, 0.f, 1.f);
  415. }
  416. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  417. if (AudioDevice)
  418. {
  419. AudioDevice->SetPortalToPortalObstruction(PortalComponent0, PortalComponent1, ObstructionValue);
  420. }
  421. }
  422. void UAkGameplayStatics::SetOutputBusVolume(float BusVolume, class AActor* Actor)
  423. {
  424. if (Actor == NULL)
  425. {
  426. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetOutputBusVolume: NULL Actor specified!"));
  427. return;
  428. }
  429. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  430. if (AudioDevice)
  431. {
  432. UAkComponent * ComponentToSet = AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  433. if (ComponentToSet != NULL)
  434. {
  435. ComponentToSet->SetOutputBusVolume(BusVolume);
  436. }
  437. }
  438. }
  439. void UAkGameplayStatics::SetBusConfig(const FString& BusName, AkChannelConfiguration ChannelConfiguration)
  440. {
  441. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  442. if (UNLIKELY(!AudioDevice))
  443. {
  444. return;
  445. }
  446. AkChannelConfig config;
  447. FAkAudioDevice::GetChannelConfig(ChannelConfiguration, config);
  448. AudioDevice->SetBusConfig(BusName, config);
  449. }
  450. void UAkGameplayStatics::SetPanningRule(PanningRule PanRule)
  451. {
  452. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  453. if (UNLIKELY(!AudioDevice))
  454. {
  455. return;
  456. }
  457. AkPanningRule AkPanRule = (PanRule == PanningRule::PanningRule_Headphones) ? AkPanningRule_Headphones : AkPanningRule_Speakers;
  458. AudioDevice->SetPanningRule(AkPanRule);
  459. }
  460. void UAkGameplayStatics::ReplaceMainOutput(const FAkOutputSettings& MainOutputSettings)
  461. {
  462. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  463. if (UNLIKELY(!AudioDevice))
  464. {
  465. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::ReplaceMainOutput: Could not fetch audio device, main output will not be replaced."));
  466. return;
  467. }
  468. AkUInt32 ShortID = AudioDevice->GetShortIDFromString(MainOutputSettings.AudioDeviceShareSetName);
  469. AkOutputSettings OutSettings;
  470. OutSettings.audioDeviceShareset = ShortID;
  471. OutSettings.idDevice = MainOutputSettings.IdDevice;
  472. OutSettings.ePanningRule = (MainOutputSettings.PanRule == PanningRule::PanningRule_Headphones) ? AkPanningRule_Headphones : AkPanningRule_Speakers;
  473. FAkAudioDevice::GetChannelConfig(MainOutputSettings.ChannelConfig, OutSettings.channelConfig);
  474. AudioDevice->ReplaceMainOutput(OutSettings);
  475. }
  476. void UAkGameplayStatics::GetSpeakerAngles(TArray<float>& SpeakerAngles, float& HeightAngle, const FString& DeviceShareSet)
  477. {
  478. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  479. if (UNLIKELY(!AudioDevice))
  480. {
  481. return;
  482. }
  483. AkOutputDeviceID DeviceID = DeviceShareSet.IsEmpty() ? 0 : AudioDevice->GetOutputID(DeviceShareSet);
  484. AudioDevice->GetSpeakerAngles(SpeakerAngles, HeightAngle, DeviceID);
  485. }
  486. void UAkGameplayStatics::SetSpeakerAngles(const TArray<float>& SpeakerAngles, float HeightAngles, const FString& DeviceShareSet)
  487. {
  488. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  489. if (UNLIKELY(!AudioDevice))
  490. {
  491. return;
  492. }
  493. AkOutputDeviceID DeviceID = DeviceShareSet.IsEmpty() ? 0 : AudioDevice->GetOutputID(DeviceShareSet);
  494. AudioDevice->SetSpeakerAngles(SpeakerAngles, HeightAngles, DeviceID);
  495. }
  496. void UAkGameplayStatics::SetOcclusionRefreshInterval(float RefreshInterval, class AActor* Actor)
  497. {
  498. if (Actor == NULL)
  499. {
  500. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetOcclusionRefreshInterval: NULL Actor specified!"));
  501. return;
  502. }
  503. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  504. if (UNLIKELY(!AudioDevice))
  505. {
  506. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetOcclusionRefreshInterval: Could not retrieve audio device."));
  507. return;
  508. }
  509. if (RefreshInterval < 0)
  510. {
  511. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetOcclusionRefreshInterval: Setting actor %s to an invalid RefreshInterval value (%.6g). Clamping to 0.0."), *Actor->GetName(), RefreshInterval);
  512. RefreshInterval = 0;
  513. }
  514. UAkComponent* ComponentToSet = AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  515. if (ComponentToSet != NULL)
  516. {
  517. ComponentToSet->OcclusionRefreshInterval = RefreshInterval;
  518. }
  519. UAkPortalComponent* PortalComponent = AkComponentHelpers::GetChildComponentOfType<UAkPortalComponent>(*Actor->GetRootComponent());
  520. if(PortalComponent != NULL)
  521. {
  522. PortalComponent->ObstructionRefreshInterval = RefreshInterval;
  523. }
  524. }
  525. void UAkGameplayStatics::StopActor(class AActor* Actor)
  526. {
  527. if ( Actor == NULL )
  528. {
  529. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::StopActor: NULL Actor specified!"));
  530. return;
  531. }
  532. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  533. if (UNLIKELY(!AudioDevice))
  534. {
  535. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::StopActor: Could not retrieve audio device."));
  536. return;
  537. }
  538. AudioDevice->StopGameObject(AudioDevice->GetAkComponent(Actor->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset));
  539. }
  540. void UAkGameplayStatics::StopAll()
  541. {
  542. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  543. if (UNLIKELY(!AudioDevice))
  544. {
  545. return;
  546. }
  547. AudioDevice->StopAllSounds();
  548. }
  549. void UAkGameplayStatics::CancelEventCallback(const FOnAkPostEventCallback& PostEventCallback)
  550. {
  551. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  552. if (UNLIKELY(!AudioDevice))
  553. {
  554. return;
  555. }
  556. AudioDevice->CancelEventCallbackDelegate(PostEventCallback);
  557. }
  558. void UAkGameplayStatics::StartAllAmbientSounds(UObject* WorldContextObject)
  559. {
  560. AkDeviceAndWorld DeviceAndWorld(WorldContextObject);
  561. if (UNLIKELY(!DeviceAndWorld.IsValid()))
  562. {
  563. return;
  564. }
  565. for (FActorIterator It(DeviceAndWorld.CurrentWorld); It; ++It)
  566. {
  567. AAkAmbientSound* pAmbientSound = Cast<AAkAmbientSound>(*It);
  568. if (pAmbientSound != NULL)
  569. {
  570. UAkComponent* pComponent = pAmbientSound->AkComponent;
  571. if (pComponent && GWorld->Scene == pComponent->GetScene())
  572. {
  573. pAmbientSound->StartPlaying();
  574. }
  575. }
  576. }
  577. }
  578. void UAkGameplayStatics::StopAllAmbientSounds(UObject* WorldContextObject)
  579. {
  580. AkDeviceAndWorld DeviceAndWorld(WorldContextObject);
  581. if (UNLIKELY(!DeviceAndWorld.IsValid()))
  582. {
  583. return;
  584. }
  585. for (FActorIterator It(DeviceAndWorld.CurrentWorld); It; ++It)
  586. {
  587. AAkAmbientSound* pAmbientSound = Cast<AAkAmbientSound>(*It);
  588. if (pAmbientSound != NULL)
  589. {
  590. UAkComponent* pComponent = pAmbientSound->AkComponent;
  591. if (pComponent && GWorld->Scene == pComponent->GetScene())
  592. {
  593. pAmbientSound->StopPlaying();
  594. }
  595. }
  596. }
  597. }
  598. void UAkGameplayStatics::ClearSoundBanksAndMedia()
  599. {
  600. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  601. if (UNLIKELY(!AudioDevice))
  602. {
  603. return;
  604. }
  605. AudioDevice->ClearSoundBanksAndMedia();
  606. }
  607. void UAkGameplayStatics::LoadInitBank()
  608. {
  609. auto* InitBankLoader = FWwiseInitBankLoader::Get();
  610. if(UNLIKELY(!InitBankLoader))
  611. {
  612. UE_LOG(LogAkAudio, Error, TEXT("LoadInitBank: WwiseInitBankLoader is not initialized."));
  613. return;
  614. }
  615. InitBankLoader->LoadInitBank();
  616. }
  617. void UAkGameplayStatics::UnloadInitBank()
  618. {
  619. auto* InitBankLoader = FWwiseInitBankLoader::Get();
  620. if(UNLIKELY(!InitBankLoader))
  621. {
  622. UE_LOG(LogAkAudio, Error, TEXT("UnloadInitBank: WwiseInitBankLoader is not initialized."));
  623. return;
  624. }
  625. InitBankLoader->UnloadInitBank();
  626. }
  627. void UAkGameplayStatics::StartOutputCapture(const FString& Filename)
  628. {
  629. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  630. if (UNLIKELY(!AudioDevice))
  631. {
  632. return;
  633. }
  634. FString name = Filename;
  635. if (!name.EndsWith(".wav"))
  636. {
  637. name += ".wav";
  638. }
  639. AudioDevice->StartOutputCapture(name);
  640. }
  641. void UAkGameplayStatics::AddOutputCaptureMarker(const FString& MarkerText)
  642. {
  643. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  644. if( AudioDevice )
  645. {
  646. AudioDevice->AddOutputCaptureMarker(MarkerText);
  647. }
  648. }
  649. void UAkGameplayStatics::StopOutputCapture()
  650. {
  651. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  652. if( AudioDevice )
  653. {
  654. AudioDevice->StopOutputCapture();
  655. }
  656. }
  657. void UAkGameplayStatics::StartProfilerCapture(const FString& Filename)
  658. {
  659. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  660. if( AudioDevice )
  661. {
  662. FString name = Filename;
  663. if( !name.EndsWith(".prof") )
  664. {
  665. name += ".prof";
  666. }
  667. AudioDevice->StartProfilerCapture(name);
  668. }
  669. }
  670. void UAkGameplayStatics::StopProfilerCapture()
  671. {
  672. FAkAudioDevice * AudioDevice = FAkAudioDevice::Get();
  673. if( AudioDevice )
  674. {
  675. AudioDevice->StopProfilerCapture();
  676. }
  677. }
  678. FString UAkGameplayStatics::GetCurrentAudioCulture()
  679. {
  680. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  681. if (AudioDevice)
  682. {
  683. return AudioDevice->GetCurrentAudioCulture();
  684. }
  685. return FString();
  686. }
  687. TArray<FString> UAkGameplayStatics::GetAvailableAudioCultures()
  688. {
  689. FAkAudioDevice* AudioDevice = FAkAudioDevice::Get();
  690. if (AudioDevice)
  691. {
  692. return AudioDevice->GetAvailableAudioCultures();
  693. }
  694. return TArray<FString>();
  695. }
  696. void UAkGameplayStatics::SetCurrentAudioCulture(const FString& AudioCulture, FLatentActionInfo LatentInfo, UObject* WorldContextObject)
  697. {
  698. AkDeviceAndWorld DeviceAndWorld(WorldContextObject);
  699. FLatentActionManager& LatentActionManager = DeviceAndWorld.CurrentWorld->GetLatentActionManager();
  700. FSetCurrentAudioCultureAction* NewAction = LatentActionManager.FindExistingAction<FSetCurrentAudioCultureAction>(LatentInfo.CallbackTarget, LatentInfo.UUID);
  701. if (!NewAction)
  702. {
  703. NewAction = new FSetCurrentAudioCultureAction(LatentInfo);
  704. LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, NewAction);
  705. }
  706. if (FAkAudioDevice* AudioDevice = FAkAudioDevice::Get())
  707. {
  708. AudioDevice->SetCurrentAudioCultureAsync(AudioCulture, NewAction);
  709. }
  710. else
  711. {
  712. NewAction->ActionDone = true;
  713. }
  714. }
  715. void UAkGameplayStatics::SetCurrentAudioCultureAsync(const FString& AudioCulture, const FOnSetCurrentAudioCultureCallback& Completed)
  716. {
  717. if (FAkAudioDevice* AudioDevice = FAkAudioDevice::Get())
  718. {
  719. AudioDevice->SetCurrentAudioCultureAsync(AudioCulture, FOnSetCurrentAudioCultureCompleted::CreateLambda([Completed](bool Succeeded) {
  720. Completed.ExecuteIfBound(Succeeded);
  721. }));
  722. }
  723. }
  724. UObject* UAkGameplayStatics::GetAkAudioTypeUserData(const UAkAudioType* Instance, const UClass* Type)
  725. {
  726. if (UNLIKELY(!Instance))
  727. {
  728. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::GetAkAudioTypeUserData: nullptr Instance specified!"));
  729. return nullptr;
  730. }
  731. if (UNLIKELY(!Type))
  732. {
  733. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::GetAkAudioTypeUserData: nullptr Type specified!"));
  734. return nullptr;
  735. }
  736. for (auto* const Entry : Instance->UserData)
  737. {
  738. if (LIKELY(Entry && IsValid(Entry)) && Entry->GetClass()->IsChildOf(Type))
  739. {
  740. return Entry;
  741. }
  742. }
  743. return nullptr;
  744. }
  745. void UAkGameplayStatics::SetDistanceProbe(AActor* Listener, AActor* DistanceProbe)
  746. {
  747. if (Listener == nullptr)
  748. {
  749. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetDistanceProbe: NULL Listener specified!"));
  750. return;
  751. }
  752. if (FAkAudioDevice* AudioDevice = FAkAudioDevice::Get())
  753. {
  754. UAkComponent * ListenerAkComponent = AudioDevice->GetAkComponent(Listener->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset);
  755. UAkComponent* DistanceProbeAkComponent =
  756. DistanceProbe != nullptr ?
  757. AudioDevice->GetAkComponent(DistanceProbe->GetRootComponent(), FName(), NULL, EAttachLocation::KeepRelativeOffset) :
  758. nullptr;
  759. AudioDevice->SetDistanceProbe(ListenerAkComponent, DistanceProbeAkComponent);
  760. }
  761. }
  762. bool UAkGameplayStatics::SetOutputDeviceEffect(const FAkOutputDeviceID InDeviceID, const int32 InEffectIndex, const UAkEffectShareSet* InEffectShareSet)
  763. {
  764. if(UNLIKELY(!InEffectShareSet))
  765. {
  766. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetOutputDeviceEffect: NULL Effect ShareSet specified!"));
  767. return false;
  768. }
  769. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  770. if (UNLIKELY(!SoundEngine)) return false;
  771. UE_LOG(LogAkAudio, Verbose, TEXT("UAkGameplayStatics::SetOutputDeviceEffect: DeviceID: %" PRIu64 ", InEffectIndex: %d, EffectShareSet Asset Name: %s, EffectShareSet ShortID: %" PRIu32 "."),
  772. InDeviceID.UInt64Value, InEffectIndex, *InEffectShareSet->GetName(), InEffectShareSet->GetShortID());
  773. AKRESULT Result = SoundEngine->SetOutputDeviceEffect(InDeviceID.UInt64Value, InEffectIndex, InEffectShareSet->GetShortID());
  774. return Result == AK_Success;
  775. }
  776. bool UAkGameplayStatics::SetBusEffectByName(const FString InBusName, const int32 InEffectIndex, const UAkEffectShareSet* InEffectShareSet)
  777. {
  778. if(UNLIKELY(!InEffectShareSet))
  779. {
  780. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetBusEffectByName: NULL Effect ShareSet specified!"));
  781. return false;
  782. }
  783. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  784. if (UNLIKELY(!SoundEngine)) return false;
  785. UE_LOG(LogAkAudio, Verbose, TEXT("UAkGameplayStatics::SetBusEffectByName: BusName: %s, InEffectIndex: %d, EffectShareSet Asset Name: %s, EffectShareSet ShortID: %" PRIu32 "."),
  786. *InBusName, InEffectIndex, *InEffectShareSet->GetName(), InEffectShareSet->GetShortID());
  787. AKRESULT Result = SoundEngine->SetBusEffect(TCHAR_TO_AK(*InBusName), InEffectIndex, InEffectShareSet->GetShortID());
  788. return Result == AK_Success;
  789. }
  790. bool UAkGameplayStatics::SetBusEffectByID(const FAkUniqueID InBusID, const int32 InEffectIndex, const UAkEffectShareSet* InEffectShareSet)
  791. {
  792. if(UNLIKELY(!InEffectShareSet))
  793. {
  794. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetBusEffectByID: NULL Effect ShareSet specified!"));
  795. return false;
  796. }
  797. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  798. if (UNLIKELY(!SoundEngine)) return false;
  799. UE_LOG(LogAkAudio, Verbose, TEXT("UAkGameplayStatics::SetBusEffectByID: BusID: %" PRIu32 ", InEffectIndex: %d, EffectShareSet Asset Name: %s, EffectShareSet ShortID: %" PRIu32 "."),
  800. InBusID.UInt32Value, InEffectIndex, *InEffectShareSet->GetName(), InEffectShareSet->GetShortID());
  801. AKRESULT Result = SoundEngine->SetBusEffect(InBusID.UInt32Value, InEffectIndex, InEffectShareSet->GetShortID());
  802. return Result == AK_Success;
  803. }
  804. bool UAkGameplayStatics::SetAuxBusEffect(const UAkAuxBus* InAuxBus, const int32 InEffectIndex, const UAkEffectShareSet* InEffectShareSet)
  805. {
  806. if(UNLIKELY(!InEffectShareSet))
  807. {
  808. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetAuxBusEffect: NULL Effect ShareSet specified!"));
  809. return false;
  810. }
  811. if(UNLIKELY(!InAuxBus))
  812. {
  813. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetAuxBusEffect: NULL Aux Bus specified!"));
  814. return false;
  815. }
  816. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  817. if (UNLIKELY(!SoundEngine)) return false;
  818. UE_LOG(LogAkAudio, Verbose, TEXT("UAkGameplayStatics::SetAuxBusEffect: AuxBus Asset Name: %s, AuxBus Short ID: %" PRIu32 ", InEffectIndex: %d, EffectShareSet Asset Name: %s, EffectShareSet ShortID: %" PRIu32 "."),
  819. *InAuxBus->GetName(), InAuxBus->GetShortID(), InEffectIndex, *InEffectShareSet->GetName(), InEffectShareSet->GetShortID());
  820. AKRESULT Result = SoundEngine->SetBusEffect(InAuxBus->GetShortID(), InEffectIndex, InEffectShareSet->GetShortID());
  821. return Result == AK_Success;
  822. }
  823. bool UAkGameplayStatics::SetActorMixerEffect(const FAkUniqueID InAudioNodeID,const int32 InEffectIndex, const UAkEffectShareSet* InEffectShareSet)
  824. {
  825. if(UNLIKELY(!InEffectShareSet))
  826. {
  827. UE_LOG(LogAkAudio, Warning, TEXT("UAkGameplayStatics::SetActorMixerEffect: NULL Effect ShareSet specified!"));
  828. return false;
  829. }
  830. auto* SoundEngine = IWwiseSoundEngineAPI::Get();
  831. if (UNLIKELY(!SoundEngine)) return false;
  832. UE_LOG(LogAkAudio, Verbose, TEXT("UAkGameplayStatics::SetActorMixerEffect: AudioNodeID: %" PRIu32 ", InEffectIndex: %d, EffectShareSet Asset Name: %s, EffectShareSet ShortID: %" PRIu32 "."),
  833. InAudioNodeID.UInt32Value, InEffectIndex, *InEffectShareSet->GetName(), InEffectShareSet->GetShortID());
  834. AKRESULT Result = SoundEngine->SetActorMixerEffect(InAudioNodeID.UInt32Value, InEffectIndex, InEffectShareSet->GetShortID());
  835. return Result == AK_Success;
  836. }