SoundCVars.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  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 <SoundCVars.h>
  9. #include <IAudioSystem.h>
  10. #include <AudioSystem_Traits_Platform.h>
  11. #include <AzCore/Console/ConsoleTypeHelpers.h>
  12. #include <AzCore/Console/ILogger.h>
  13. #include <AzCore/StringFunc/StringFunc.h>
  14. #include <MicrophoneBus.h>
  15. namespace Audio::CVars
  16. {
  17. // Keep the name of this the same as it was in legacy CSystem.
  18. AZ_CVAR(AZ::u32, sys_audio_disable, 0,
  19. nullptr,
  20. AZ::ConsoleFunctorFlags::Null,
  21. "Globally enable/disable the audio system, 0 (default) = Audio is Enabled, 1 = Audio is Disabled\n"
  22. "It is advised to put this setting under \"/O3DE/Autoexec/ConsoleCommands/\" in Settings Registry.");
  23. // CVar: s_EnableRaycasts
  24. // Usage: s_EnableRaycasts=true (false)
  25. AZ_CVAR(bool, s_EnableRaycasts, true,
  26. nullptr,
  27. AZ::ConsoleFunctorFlags::Null,
  28. "Set to true/false to globally enable/disable raycasting for audio occlusion & obstruction.");
  29. // CVar: s_RaycastMinDistance
  30. // Usage: s_RaycastMinDistance=0.5
  31. // Note: This callback defines an "absolute" minimum constant that the value of the CVar should not go below.
  32. // We clamp the value to this minimum if it goes below this.
  33. AZ_CVAR(float, s_RaycastMinDistance, 0.5f,
  34. [](const float& minDist) -> void
  35. {
  36. if (minDist >= s_RaycastMaxDistance)
  37. {
  38. AZ_Warning("SoundCVars", false,
  39. "CVar 's_RaycastMinDistance' (%f) needs to be less than 's_RaycastMaxDistance' (%f).\n"
  40. "Audio raycasts won't run until the distance range is fixed.\n",
  41. static_cast<float>(s_RaycastMinDistance), static_cast<float>(s_RaycastMaxDistance));
  42. }
  43. static constexpr float s_absoluteMinRaycastDistance = 0.1f;
  44. s_RaycastMinDistance = AZ::GetMax(minDist, s_absoluteMinRaycastDistance);
  45. AZ_Warning("SoundCVars", s_RaycastMinDistance == minDist,
  46. "CVar 's_RaycastMinDistance' will be clamped to an absolute minimum value of %f.\n", s_absoluteMinRaycastDistance);
  47. },
  48. AZ::ConsoleFunctorFlags::Null,
  49. "Raycasts for obstruction/occlusion are not sent for sounds whose distance to the listener is less than this value.");
  50. // CVar: s_RaycastMaxDistance
  51. // Usage: s_RaycastMaxDistance=100.0
  52. // Note: This callback defines an "absolute" maximum constant that the value of the CVar should not go above.
  53. // We clamp the value to this maximum if it goes above this.
  54. AZ_CVAR(float, s_RaycastMaxDistance, 100.f,
  55. [](const float& maxDist) -> void
  56. {
  57. if (maxDist <= s_RaycastMinDistance)
  58. {
  59. AZ_Warning("SoundCVars", false,
  60. "CVar 's_RaycastMaxDistance' (%f) needs to be greater than 's_RaycastMinDistance' (%f).\n"
  61. "Audio raycasts won't run until the distance range is fixed.\n",
  62. static_cast<float>(s_RaycastMaxDistance), static_cast<float>(s_RaycastMinDistance));
  63. }
  64. static constexpr float s_absoluteMaxRaycastDistance = 1000.f;
  65. s_RaycastMaxDistance = AZ::GetMin(maxDist, s_absoluteMaxRaycastDistance);
  66. AZ_Warning("SoundCVars", s_RaycastMaxDistance == maxDist,
  67. "CVar 's_RaycastMaxDistance' will be clamped to an absolute maximum value of %f.\n", s_absoluteMaxRaycastDistance);
  68. },
  69. AZ::ConsoleFunctorFlags::Null,
  70. "Raycasts for obstruction/occlusion are not sent for sounds whose distance to the listener is greater than this value.");
  71. // CVar: s_RaycastCacheTimeMs
  72. // Usage: s_RaycastCacheTimeMs=250.0
  73. // Note: This callback defines an "absolute" minimum constant that the value of the CVar should not go below.
  74. // We clamp the value to this minimum if it goes below this.
  75. AZ_CVAR(float, s_RaycastCacheTimeMs, 250.f,
  76. [](const float& cacheTimeMs) -> void
  77. {
  78. static constexpr float s_absoluteMinRaycastCacheTimeMs = 1 / 60.f;
  79. s_RaycastCacheTimeMs = AZ::GetMax(cacheTimeMs, s_absoluteMinRaycastCacheTimeMs);
  80. AZ_Warning("SoundCVars", cacheTimeMs == s_RaycastCacheTimeMs,
  81. "CVar 's_RaycastCacheTimeMs' will be clamped to an absolute minimum of %f.\n", s_absoluteMinRaycastCacheTimeMs);
  82. },
  83. AZ::ConsoleFunctorFlags::Null,
  84. "Physics raycast results are given this amount of time before they are considered dirty and need to be recast.");
  85. // CVar: s_RaycastSmoothFactor
  86. // Usage: s_RaycastSmoothFactor=5.0
  87. AZ_CVAR(float, s_RaycastSmoothFactor, 7.f,
  88. [](const float& smoothFactor) -> void
  89. {
  90. static constexpr float s_absoluteMinRaycastSmoothFactor = 0.f;
  91. static constexpr float s_absoluteMaxRaycastSmoothFactor = 10.f;
  92. s_RaycastSmoothFactor = AZ::GetClamp(smoothFactor, s_absoluteMinRaycastSmoothFactor, s_absoluteMaxRaycastSmoothFactor);
  93. AZ_Warning("SoundCVars", s_RaycastSmoothFactor == smoothFactor,
  94. "CVar 's_RaycastSmoothFactor' was be clamped to an absolute range of [%f, %f].\n",
  95. s_absoluteMinRaycastSmoothFactor, s_absoluteMaxRaycastSmoothFactor);
  96. },
  97. AZ::ConsoleFunctorFlags::Null,
  98. "How slowly the smoothing of obstruction/occlusion values should smooth to target: delta / (smoothFactor^2 + 1). "
  99. "Low values will smooth faster, high values will smooth slower.");
  100. AZ_CVAR(AZ::u64, s_ATLMemorySize, AZ_TRAIT_AUDIOSYSTEM_ATL_POOL_SIZE,
  101. nullptr, AZ::ConsoleFunctorFlags::Null,
  102. "The size in KiB of memory to be used by the ATL/Audio System.\n"
  103. "Usage: s_ATLMemorySize=" AZ_TRAIT_AUDIOSYSTEM_ATL_POOL_SIZE_DEFAULT_TEXT "\n");
  104. AZ_CVAR(AZ::u64, s_FileCacheManagerMemorySize, AZ_TRAIT_AUDIOSYSTEM_FILE_CACHE_MANAGER_SIZE,
  105. nullptr, AZ::ConsoleFunctorFlags::Null,
  106. "The size in KiB the File Cache Manager will use for banks.\n"
  107. "Usage: s_FileCacheManagerMemorySize=" AZ_TRAIT_AUDIOSYSTEM_FILE_CACHE_MANAGER_SIZE_DEFAULT_TEXT "\n");
  108. AZ_CVAR(AZ::u64, s_AudioEventPoolSize, AZ_TRAIT_AUDIOSYSTEM_AUDIO_EVENT_POOL_SIZE,
  109. nullptr, AZ::ConsoleFunctorFlags::Null,
  110. "The number of audio events to preallocate in a pool.\n"
  111. "Usage: s_AudioEventPoolSize=" AZ_TRAIT_AUDIOSYSTEM_AUDIO_EVENT_POOL_SIZE_DEFAULT_TEXT "\n");
  112. AZ_CVAR(AZ::u64, s_AudioObjectPoolSize, AZ_TRAIT_AUDIOSYSTEM_AUDIO_OBJECT_POOL_SIZE,
  113. nullptr, AZ::ConsoleFunctorFlags::Null,
  114. "The number of audio objects to preallocate in a pool.\n"
  115. "Usage: s_AudioObjectPoolSize=" AZ_TRAIT_AUDIOSYSTEM_AUDIO_OBJECT_POOL_SIZE_DEFAULT_TEXT "\n");
  116. AZ_CVAR(float, s_PositionUpdateThreshold, 0.1f,
  117. nullptr, AZ::ConsoleFunctorFlags::Null,
  118. "An audio object needs to move by this distance in order to issue a position update to the audio system.\n"
  119. "Usage: s_PositionUpdateThreshold=5.0\n");
  120. AZ_CVAR(float, s_VelocityTrackingThreshold, 0.1f,
  121. nullptr, AZ::ConsoleFunctorFlags::Null,
  122. "An audio object needs to have its velocity changed by this amount in order to issue an 'object_speed' Rtpc update to the audio system.\n"
  123. "Usage: s_VelocityTrackingThreshold=0.5\n");
  124. AZ_CVAR(AZ::u32, s_AudioProxiesInitType, 0,
  125. [](const AZ::u32& initType) -> void
  126. {
  127. static constexpr AZ::u32 s_numAudioProxyInitTypes = 3;
  128. if (initType < s_numAudioProxyInitTypes)
  129. {
  130. s_AudioProxiesInitType = initType;
  131. }
  132. },
  133. AZ::ConsoleFunctorFlags::Null,
  134. "Overrides the initialization mode of audio proxies globally.\n"
  135. "0: AudioProxy-specific initiaization (Default).\n"
  136. "1: All AudioProxy's initialize synchronously.\n"
  137. "2: All AudioProxy's initialize asynchronously.\n"
  138. "Usage: s_AudioProxiesInitType=2\n");
  139. auto OnChangeAudioLanguage = []([[maybe_unused]] const AZ::CVarFixedString& language) -> void
  140. {
  141. if (auto audioSystem = AZ::Interface<IAudioSystem>::Get();
  142. audioSystem != nullptr)
  143. {
  144. Audio::SystemRequest::ChangeLanguage changeLanguage;
  145. audioSystem->PushRequest(AZStd::move(changeLanguage));
  146. }
  147. };
  148. AZ_CVAR(AZ::CVarFixedString, g_languageAudio, "", OnChangeAudioLanguage, AZ::ConsoleFunctorFlags::Null, "");
  149. #if !defined(AUDIO_RELEASE)
  150. AZ_CVAR(bool, s_IgnoreWindowFocus, false,
  151. nullptr, AZ::ConsoleFunctorFlags::Null,
  152. "Determines whether application focus should issue events to the audio system or not.\n"
  153. "false: Window focus event should be issued (Default).\n"
  154. "true: Ignore window focus events.\n"
  155. "Usage: s_IgnoreWindowFocus=true\n");
  156. AZ_CVAR(bool, s_ShowActiveAudioObjectsOnly, false,
  157. nullptr, AZ::ConsoleFunctorFlags::Null,
  158. "Determines whether active or all audio objects should be drawn when debug drawing is enabled.\n"
  159. "false: Draws all audio objects (Default).\n"
  160. "true: Draws only active audio objects.\n"
  161. "Usage: s_ShowActiveAudioObjectsOnly=true\n");
  162. AZ_CVAR(AZ::CVarFixedString, s_AudioTriggersDebugFilter, "",
  163. nullptr, AZ::ConsoleFunctorFlags::Null,
  164. "Filters debug drawing to only audio triggers that match this filter as sub-string.\n"
  165. "Usage: s_AudioTriggersDebugFilter=impact_hit\n");
  166. AZ_CVAR(AZ::CVarFixedString, s_AudioObjectsDebugFilter, "",
  167. nullptr, AZ::ConsoleFunctorFlags::Null,
  168. "Filters debug drawing to only audio objects whose name matches this filter as a sub-string.\n"
  169. "Usage: s_AudioObjectsDebugFilter=weapon_axe\n");
  170. auto OnChangeDebugDrawOptions = [](const AZ::CVarFixedString& options) -> void
  171. {
  172. s_debugDrawOptions.ClearAllFlags();
  173. if (options == "0")
  174. {
  175. return;
  176. }
  177. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::DrawObjects), options.contains("a"));
  178. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ObjectLabels), options.contains("b"));
  179. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ObjectTriggers), options.contains("c"));
  180. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ObjectStates), options.contains("d"));
  181. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ObjectRtpcs), options.contains("e"));
  182. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ObjectEnvironments), options.contains("f"));
  183. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::DrawRays), options.contains("g"));
  184. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::RayLabels), options.contains("h"));
  185. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::DrawListener), options.contains("i"));
  186. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ActiveEvents), options.contains("v"));
  187. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::ActiveObjects), options.contains("w"));
  188. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::FileCacheInfo), options.contains("x"));
  189. s_debugDrawOptions.SetFlags(static_cast<AZ::u32>(DebugDraw::Options::MemoryInfo), options.contains("y"));
  190. };
  191. AZ_CVAR(AZ::CVarFixedString, s_DrawAudioDebug, "",
  192. OnChangeDebugDrawOptions,
  193. AZ::ConsoleFunctorFlags::IsCheat,
  194. "Draws AudioTranslationLayer related debug data to the screen.\n"
  195. "Usage: s_DrawAudioDebug=abcde (flags can be combined)\n"
  196. "0: Turn off.\n"
  197. "a: Draw spheres around active audio objects.\n"
  198. "b: Show text labels for active audio objects.\n"
  199. "c: Show trigger names for active audio objects.\n"
  200. "d: Show current states for active audio objects.\n"
  201. "e: Show RTPC values for active audio objects.\n"
  202. "f: Show Environment amounts for active audio objects.\n"
  203. "g: Draw occlusion rays.\n"
  204. "h: Show occlusion ray labels.\n"
  205. "i: Draw sphere around active audio listener.\n"
  206. "v: List active Events.\n"
  207. "w: List active Audio Objects.\n"
  208. "x: Show FileCache Manager debug info.\n"
  209. "y: Show memory usage info for the audio engine.\n");
  210. auto OnChangeFileCacheManagerFilterOptions = [](const AZ::CVarFixedString& options) -> void
  211. {
  212. s_fcmDrawOptions.ClearAllFlags();
  213. if (options == "0")
  214. {
  215. return;
  216. }
  217. s_fcmDrawOptions.SetFlags(static_cast<AZ::u32>(FileCacheManagerDebugDraw::Options::Global), options.contains("a"));
  218. s_fcmDrawOptions.SetFlags(static_cast<AZ::u32>(FileCacheManagerDebugDraw::Options::LevelSpecific), options.contains("b"));
  219. s_fcmDrawOptions.SetFlags(static_cast<AZ::u32>(FileCacheManagerDebugDraw::Options::UseCounted), options.contains("c"));
  220. s_fcmDrawOptions.SetFlags(static_cast<AZ::u32>(FileCacheManagerDebugDraw::Options::Loaded), options.contains("d"));
  221. };
  222. AZ_CVAR(AZ::CVarFixedString, s_FileCacheManagerDebugFilter, "",
  223. OnChangeFileCacheManagerFilterOptions,
  224. AZ::ConsoleFunctorFlags::IsCheat,
  225. "Allows for filtered display of the file cache entries such as Globals, Level Specifics, Use Counted and so on.\n"
  226. "Usage: s_FileCacheManagerDebugFilter [0ab...] (flags can be combined)\n"
  227. "Default: 0 (all)\n"
  228. "a: Globals\n"
  229. "b: Level Specifics\n"
  230. "c: Use Counted\n"
  231. "d: Currently Loaded\n");
  232. static void s_ExecuteTrigger(const AZ::ConsoleCommandContainer& args);
  233. static void s_StopTrigger(const AZ::ConsoleCommandContainer& args);
  234. static void s_SetRtpc(const AZ::ConsoleCommandContainer& args);
  235. static void s_SetSwitchState(const AZ::ConsoleCommandContainer& args);
  236. static void s_LoadPreload(const AZ::ConsoleCommandContainer& args);
  237. static void s_UnloadPreload(const AZ::ConsoleCommandContainer& args);
  238. static void s_PlayFile(const AZ::ConsoleCommandContainer& args);
  239. static void s_Microphone(const AZ::ConsoleCommandContainer& args);
  240. static void s_PlayExternalSource(const AZ::ConsoleCommandContainer& args);
  241. static void s_SetPanningMode(const AZ::ConsoleCommandContainer& args);
  242. AZ_CONSOLEFREEFUNC(s_ExecuteTrigger, AZ::ConsoleFunctorFlags::IsCheat,
  243. "Execute an Audio Trigger.\n"
  244. "The first argument is the name of the AudioTrigger to be executed, the second argument is an optional AudioObject ID.\n"
  245. "If the second argument is provided, the AudioTrigger is executed on the AudioObject with the given ID,\n"
  246. "otherwise, the AudioTrigger is executed on the GlobalAudioObject\n"
  247. "Usage: s_ExecuteTrigger Play_chicken_idle 605 or s_ExecuteTrigger MuteDialog\n");
  248. AZ_CONSOLEFREEFUNC(s_StopTrigger, AZ::ConsoleFunctorFlags::IsCheat,
  249. "Stops an Audio Trigger.\n"
  250. "The first argument is the name of the AudioTrigger to be stopped, the second argument is an optional AudioObject ID.\n"
  251. "If the second argument is provided, the AudioTrigger is stopped on the AudioObject with the given ID,\n"
  252. "otherwise, the AudioTrigger is stopped on the GlobalAudioObject\n"
  253. "Usage: s_StopTrigger Play_chicken_idle 605 or s_StopTrigger MuteDialog\n");
  254. AZ_CONSOLEFREEFUNC(s_SetRtpc, AZ::ConsoleFunctorFlags::IsCheat,
  255. "Set an Audio RTPC value.\n"
  256. "The first argument is the name of the AudioRtpc to be set, the second argument is the float value to be set,"
  257. "the third argument is an optional AudioObject ID.\n"
  258. "If the third argument is provided, the AudioRtpc is set on the AudioObject with the given ID,\n"
  259. "otherwise, the AudioRtpc is set on the GlobalAudioObject\n"
  260. "Usage: s_SetRtpc character_speed 0.0 601 or s_SetRtpc volume_music 1.0\n");
  261. AZ_CONSOLEFREEFUNC(s_SetSwitchState, AZ::ConsoleFunctorFlags::IsCheat,
  262. "Set an Audio Switch to a provided State.\n"
  263. "The first argument is the name of the AudioSwitch to, the second argument is the name of the SwitchState to be set,"
  264. "the third argument is an optional AudioObject ID.\n"
  265. "If the third argument is provided, the AudioSwitch is set on the AudioObject with the given ID,\n"
  266. "otherwise, the AudioSwitch is set on the GlobalAudioObject\n"
  267. "Usage: s_SetSwitchState SurfaceType concrete 601 or s_SetSwitchState weather rain\n");
  268. AZ_CONSOLEFREEFUNC(s_LoadPreload, AZ::ConsoleFunctorFlags::IsCheat,
  269. "Load an Audio Preload to the FileCacheManager.\n"
  270. "The first argument is the name of the ATL preload.\n"
  271. "Usage: s_LoadPreload GlobalBank\n");
  272. AZ_CONSOLEFREEFUNC(s_UnloadPreload, AZ::ConsoleFunctorFlags::IsCheat,
  273. "Unload an Audio Preload from the FileCacheManager.\n"
  274. "The first argument is the name of the ATL Prelaod.\n"
  275. "Usage: s_UnloadPreload GlobalBank\n");
  276. AZ_CONSOLEFREEFUNC(s_PlayFile, AZ::ConsoleFunctorFlags::IsCheat,
  277. "Play an audio file directly.\n"
  278. "First argument is the name of the file to play. Only .wav and .pcm (raw) files are supported right now.\n"
  279. "Second argument is the name of the audio trigger to use."
  280. "Usage: s_PlayFile \"sounds\\wwise\\external_sources\\sfx\\my_file.wav\" Play_audio_input_2D\n");
  281. AZ_CONSOLEFREEFUNC(s_Microphone, AZ::ConsoleFunctorFlags::IsCheat,
  282. "Turn on/off microphone input.\n"
  283. "First argument is 0 or 1 to turn off or on the Microphone, respectively.\n"
  284. "Second argument is the name of the ATL trigger to use (when turning microphone on) for Audio Input.\n"
  285. "Usage: s_Microphone 1 Play_audio_input_2D\n"
  286. "Usage: s_Microphone 0\n");
  287. AZ_CONSOLEFREEFUNC(s_PlayExternalSource, AZ::ConsoleFunctorFlags::IsCheat,
  288. "Execute an 'External Source' audio trigger.\n"
  289. "The first argument is the name of the audio trigger to execute.\n"
  290. "The second argument is the collection Id.\n"
  291. "The third argument is the language Id.\n"
  292. "The fourth argument is the file Id.\n"
  293. "Usage: s_PlayExternalSource Play_external_VO 0 0 1\n");
  294. AZ_CONSOLEFREEFUNC(s_SetPanningMode, AZ::ConsoleFunctorFlags::IsCheat,
  295. "Set the Panning mode to either 'speakers' or 'headphones'.\n"
  296. "Speakers will have a 60 degree angle from the listener to the L/R speakers.\n"
  297. "Headphones will have a 180 degree angle from the listener to the L/R speakers.\n"
  298. "Usage: s_SetPanningMode speakers (default)\n"
  299. "Usage: s_SetPanningMode headphones\n");
  300. ///////////////////////////////////////////////////////////////////////////////////////////////////
  301. static void s_ExecuteTrigger(const AZ::ConsoleCommandContainer& args)
  302. {
  303. if (args.size() == 1 || args.size() == 2)
  304. {
  305. AZStd::string triggerName(args[0]);
  306. TAudioControlID triggerId = AZ::Interface<IAudioSystem>::Get()->GetAudioTriggerID(triggerName.c_str());
  307. if (triggerId != INVALID_AUDIO_CONTROL_ID)
  308. {
  309. TAudioObjectID objectId = INVALID_AUDIO_OBJECT_ID;
  310. if (args.size() == 2)
  311. {
  312. if (!AZ::ConsoleTypeHelpers::StringToValue<TAudioObjectID>(objectId, args[1]))
  313. {
  314. AZLOG_DEBUG("Invalid Object ID: %.*s", AZ_STRING_ARG(args[1]));
  315. return;
  316. }
  317. }
  318. Audio::ObjectRequest::ExecuteTrigger execTrigger;
  319. execTrigger.m_audioObjectId = objectId;
  320. execTrigger.m_triggerId = triggerId;
  321. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(execTrigger));
  322. }
  323. else
  324. {
  325. AZLOG_DEBUG("Unknown trigger name: %.*s", AZ_STRING_ARG(args[0]));
  326. }
  327. }
  328. else
  329. {
  330. AZLOG_INFO("Usage: s_ExecuteTrigger <TriggerName> [<Object ID>]");
  331. }
  332. }
  333. ///////////////////////////////////////////////////////////////////////////////////////////////////
  334. static void s_StopTrigger(const AZ::ConsoleCommandContainer& args)
  335. {
  336. if (args.size() == 1 || args.size() == 2)
  337. {
  338. AZStd::string triggerName(args[0]);
  339. TAudioControlID triggerId = AZ::Interface<IAudioSystem>::Get()->GetAudioTriggerID(triggerName.c_str());
  340. if (triggerId != INVALID_AUDIO_CONTROL_ID)
  341. {
  342. TAudioObjectID objectId = INVALID_AUDIO_OBJECT_ID;
  343. if (args.size() == 2)
  344. {
  345. if (!AZ::ConsoleTypeHelpers::StringToValue<TAudioObjectID>(objectId, args[1]))
  346. {
  347. AZLOG_DEBUG("Invalid Object ID: %.*s", AZ_STRING_ARG(args[1]));
  348. return;
  349. }
  350. }
  351. Audio::ObjectRequest::StopTrigger stopTrigger;
  352. stopTrigger.m_audioObjectId = objectId;
  353. stopTrigger.m_triggerId = triggerId;
  354. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(stopTrigger));
  355. }
  356. else
  357. {
  358. AZLOG_DEBUG("Unknown trigger name: %.*s", AZ_STRING_ARG(args[0]));
  359. }
  360. }
  361. else
  362. {
  363. AZLOG_INFO("Usage: s_StopTrigger <TriggerName> [<Object ID>]");
  364. }
  365. }
  366. ///////////////////////////////////////////////////////////////////////////////////////////////////
  367. static void s_SetRtpc(const AZ::ConsoleCommandContainer& args)
  368. {
  369. if (args.size() == 2 || args.size() == 3)
  370. {
  371. AZStd::string rtpcName(args[0]);
  372. TAudioControlID rtpcId = AZ::Interface<IAudioSystem>::Get()->GetAudioRtpcID(rtpcName.c_str());
  373. if (rtpcId != INVALID_AUDIO_CONTROL_ID)
  374. {
  375. float value = 0.f;
  376. if (!AZ::ConsoleTypeHelpers::StringToValue<float>(value, args[1]))
  377. {
  378. AZLOG_DEBUG("Invalid float number: %.*s", AZ_STRING_ARG(args[1]));
  379. return;
  380. }
  381. TAudioObjectID objectId = INVALID_AUDIO_OBJECT_ID;
  382. if (args.size() == 3)
  383. {
  384. if (!AZ::ConsoleTypeHelpers::StringToValue<TAudioObjectID>(objectId, args[2]))
  385. {
  386. AZLOG_DEBUG("Invalid Object ID: %.*s", AZ_STRING_ARG(args[2]));
  387. return;
  388. }
  389. }
  390. Audio::ObjectRequest::SetParameterValue setParameter;
  391. setParameter.m_audioObjectId = objectId;
  392. setParameter.m_parameterId = rtpcId;
  393. setParameter.m_value = value;
  394. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(setParameter));
  395. }
  396. else
  397. {
  398. AZLOG_DEBUG("Unknown parameter name: %.*s", AZ_STRING_ARG(args[0]));
  399. }
  400. }
  401. else
  402. {
  403. AZLOG_INFO("Usage: s_SetRtpc <ParameterName> [<Object ID>]");
  404. }
  405. }
  406. ///////////////////////////////////////////////////////////////////////////////////////////////////
  407. static void s_SetSwitchState(const AZ::ConsoleCommandContainer& args)
  408. {
  409. if (args.size() == 2 || args.size() == 3)
  410. {
  411. AZStd::string switchName(args[0]);
  412. TAudioControlID switchId = AZ::Interface<IAudioSystem>::Get()->GetAudioSwitchID(switchName.c_str());
  413. if (switchId != INVALID_AUDIO_CONTROL_ID)
  414. {
  415. AZStd::string stateName(args[1]);
  416. TAudioSwitchStateID stateId = AZ::Interface<IAudioSystem>::Get()->GetAudioSwitchStateID(switchId, stateName.c_str());
  417. if (stateId != INVALID_AUDIO_SWITCH_STATE_ID)
  418. {
  419. TAudioObjectID objectId = INVALID_AUDIO_OBJECT_ID;
  420. if (args.size() == 3)
  421. {
  422. if (!AZ::ConsoleTypeHelpers::StringToValue<TAudioObjectID>(objectId, args[2]))
  423. {
  424. AZLOG_DEBUG("Invalid Object ID: %.*s", AZ_STRING_ARG(args[2]));
  425. return;
  426. }
  427. }
  428. Audio::ObjectRequest::SetSwitchValue setSwitch;
  429. setSwitch.m_audioObjectId = objectId;
  430. setSwitch.m_switchId = switchId;
  431. setSwitch.m_stateId = stateId;
  432. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(setSwitch));
  433. }
  434. else
  435. {
  436. AZLOG_DEBUG("Invalid Switch State name: %.*s", AZ_STRING_ARG(args[1]));
  437. }
  438. }
  439. else
  440. {
  441. AZLOG_DEBUG("Unknown Switch name: %.*s", AZ_STRING_ARG(args[0]));
  442. }
  443. }
  444. else
  445. {
  446. AZLOG_INFO("Usage: s_SetSwitchState <SwitchName> <StateName> [<Object ID>]");
  447. }
  448. }
  449. ///////////////////////////////////////////////////////////////////////////////////////////////////
  450. static void s_LoadPreload(const AZ::ConsoleCommandContainer& args)
  451. {
  452. if (args.size() == 1)
  453. {
  454. AZStd::string preloadName(args[0]);
  455. TAudioPreloadRequestID preloadId = AZ::Interface<IAudioSystem>::Get()->GetAudioPreloadRequestID(preloadName.c_str());
  456. if (preloadId != INVALID_AUDIO_PRELOAD_REQUEST_ID)
  457. {
  458. Audio::SystemRequest::LoadBank loadBank;
  459. loadBank.m_preloadRequestId = preloadId;
  460. loadBank.m_asyncLoad = true;
  461. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(loadBank));
  462. }
  463. else
  464. {
  465. AZLOG_DEBUG("Preload named %.*s not found", AZ_STRING_ARG(args[0]));
  466. }
  467. }
  468. else
  469. {
  470. AZLOG_INFO("Usage: s_LoadPreload <PreloadName>");
  471. }
  472. }
  473. ///////////////////////////////////////////////////////////////////////////////////////////////////
  474. static void s_UnloadPreload(const AZ::ConsoleCommandContainer& args)
  475. {
  476. if (args.size() == 1)
  477. {
  478. AZStd::string preloadName(args[0]);
  479. TAudioPreloadRequestID preloadId = AZ::Interface<IAudioSystem>::Get()->GetAudioPreloadRequestID(preloadName.c_str());
  480. if (preloadId != INVALID_AUDIO_PRELOAD_REQUEST_ID)
  481. {
  482. Audio::SystemRequest::UnloadBank unloadBank;
  483. unloadBank.m_preloadRequestId = preloadId;
  484. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(unloadBank));
  485. }
  486. else
  487. {
  488. AZLOG_DEBUG("Preload name %.*s not found", AZ_STRING_ARG(args[0]));
  489. }
  490. }
  491. else
  492. {
  493. AZLOG_INFO("Usage: s_UnloadPreload <PreloadName>");
  494. }
  495. }
  496. ///////////////////////////////////////////////////////////////////////////////////////////////////
  497. static void s_PlayFile(const AZ::ConsoleCommandContainer& args)
  498. {
  499. if (args.size() >= 2)
  500. {
  501. AZStd::string filename(args[0]);
  502. AZStd::string fileext;
  503. AZStd::to_lower(fileext.begin(), fileext.end());
  504. AZ::StringFunc::Path::GetExtension(filename.c_str(), fileext, false);
  505. AudioInputSourceType audioInputType = AudioInputSourceType::Unsupported;
  506. // Use file extension to guess the file type
  507. if (fileext.compare("wav") == 0)
  508. {
  509. audioInputType = AudioInputSourceType::WavFile;
  510. }
  511. else if (fileext.compare("pcm") == 0)
  512. {
  513. audioInputType = AudioInputSourceType::PcmFile;
  514. }
  515. if (audioInputType != AudioInputSourceType::Unsupported)
  516. {
  517. // Setup the configuration...
  518. SAudioInputConfig audioInputConfig(audioInputType, filename.c_str());
  519. if (audioInputType == AudioInputSourceType::PcmFile)
  520. {
  521. if (args.size() == 4)
  522. {
  523. audioInputConfig.m_bitsPerSample = 16;
  524. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u32>(audioInputConfig.m_numChannels, args[2]))
  525. {
  526. AZLOG_DEBUG("Invalid number of channels: %.*s", AZ_STRING_ARG(args[2]));
  527. return;
  528. }
  529. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u32>(audioInputConfig.m_sampleRate, args[3]))
  530. {
  531. AZLOG_DEBUG("Invalid sample rate: %.*s", AZ_STRING_ARG(args[3]));
  532. return;
  533. }
  534. audioInputConfig.m_sampleType = AudioInputSampleType::Int;
  535. }
  536. else
  537. {
  538. AZLOG_DEBUG("When using PCM file, additional parameters needed: [<NumChannels>] [<SampleRate>]");
  539. return;
  540. }
  541. }
  542. TAudioSourceId sourceId = AZ::Interface<IAudioSystem>::Get()->CreateAudioSource(audioInputConfig);
  543. if (sourceId != INVALID_AUDIO_SOURCE_ID)
  544. {
  545. TAudioControlID triggerId = AZ::Interface<IAudioSystem>::Get()->GetAudioTriggerID(args[1].data());
  546. if (triggerId != INVALID_AUDIO_CONTROL_ID)
  547. {
  548. Audio::ObjectRequest::ExecuteSourceTrigger execSourceTrigger;
  549. execSourceTrigger.m_triggerId = triggerId;
  550. execSourceTrigger.m_sourceInfo.m_sourceId = sourceId;
  551. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(execSourceTrigger));
  552. }
  553. else
  554. {
  555. AZ::Interface<IAudioSystem>::Get()->DestroyAudioSource(sourceId);
  556. AZLOG_DEBUG("Failed to find the trigger named %.*s", AZ_STRING_ARG(args[1]));
  557. }
  558. }
  559. else
  560. {
  561. AZLOG_DEBUG("Unable to create a new audio source");
  562. }
  563. }
  564. else
  565. {
  566. AZLOG_DEBUG("Audio files with extension '.%s' are unsupported", fileext.c_str());
  567. }
  568. }
  569. else
  570. {
  571. AZLOG_INFO("Usage: s_PlayFile <FilePath> <TriggerName>");
  572. }
  573. }
  574. ///////////////////////////////////////////////////////////////////////////////////////////////////
  575. static void s_Microphone(const AZ::ConsoleCommandContainer& args)
  576. {
  577. static bool micState = false; // mic is off initially
  578. static TAudioSourceId micSourceId = INVALID_AUDIO_SOURCE_ID;
  579. static TAudioControlID triggerId = INVALID_AUDIO_CONTROL_ID;
  580. if (args.size() == 2)
  581. {
  582. AZ::u32 state;
  583. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u32>(state, args[0]))
  584. {
  585. AZLOG_DEBUG("Invalid number passed: %.*s, should be 0 or 1", AZ_STRING_ARG(args[0]));
  586. return;
  587. }
  588. AZStd::string triggerName(args[1]);
  589. if (state == 1 && !micState && micSourceId == INVALID_AUDIO_SOURCE_ID && triggerId == INVALID_AUDIO_CONTROL_ID)
  590. {
  591. AZLOG_INFO("Turning on Microphone with %s", triggerName.c_str());
  592. bool success = true;
  593. triggerId = AZ::Interface<IAudioSystem>::Get()->GetAudioTriggerID(triggerName.c_str());
  594. if (triggerId != INVALID_AUDIO_CONTROL_ID)
  595. {
  596. // Start the mic session
  597. bool startedMic = false;
  598. MicrophoneRequestBus::BroadcastResult(startedMic, &MicrophoneRequestBus::Events::StartSession);
  599. if (startedMic)
  600. {
  601. SAudioInputConfig micConfig;
  602. MicrophoneRequestBus::BroadcastResult(micConfig, &MicrophoneRequestBus::Events::GetFormatConfig);
  603. // If you want to test resampling, set the values here before you create an Audio Source.
  604. // In this case, we would be specifying 16kHz, 16-bit integers.
  605. // micConfig.m_sampleRate = 16000;
  606. // micConfig.m_bitsPerSample = 16;
  607. // micConfig.m_sampleType = AudioInputSampleType::Int;
  608. micSourceId = AZ::Interface<IAudioSystem>::Get()->CreateAudioSource(micConfig);
  609. if (micSourceId != INVALID_AUDIO_SOURCE_ID)
  610. {
  611. Audio::ObjectRequest::ExecuteSourceTrigger execSourceTrigger;
  612. execSourceTrigger.m_triggerId = triggerId;
  613. execSourceTrigger.m_sourceInfo.m_sourceId = micSourceId;
  614. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(execSourceTrigger));
  615. }
  616. else
  617. {
  618. success = false;
  619. AZLOG_DEBUG("Failed to create a new audio source for the microphone");
  620. }
  621. }
  622. else
  623. {
  624. success = false;
  625. AZLOG_DEBUG("Failed to start the microphone session");
  626. }
  627. }
  628. else
  629. {
  630. success = false;
  631. AZLOG_DEBUG("Failed to find the trigger named '%s'", triggerName.c_str());
  632. }
  633. if (success)
  634. {
  635. micState = true;
  636. }
  637. else
  638. {
  639. AZ::Interface<IAudioSystem>::Get()->DestroyAudioSource(micSourceId);
  640. MicrophoneRequestBus::Broadcast(&MicrophoneRequestBus::Events::EndSession);
  641. micSourceId = INVALID_AUDIO_SOURCE_ID;
  642. triggerId = INVALID_AUDIO_CONTROL_ID;
  643. }
  644. }
  645. else
  646. {
  647. AZLOG_DEBUG("Error encountered while turning on/off microphone");
  648. }
  649. }
  650. else if (args.size() == 1)
  651. {
  652. AZ::u32 state;
  653. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u32>(state, args[0]))
  654. {
  655. AZLOG_DEBUG("Invalid number passed '%.*s', should be 0 or 1", AZ_STRING_ARG(args[0]));
  656. return;
  657. }
  658. if (state == 0 && micState && micSourceId != INVALID_AUDIO_SOURCE_ID && triggerId != INVALID_AUDIO_CONTROL_ID)
  659. {
  660. AZLOG_INFO("Turning off Microphone");
  661. // Stop the trigger (may not be necessary)
  662. Audio::ObjectRequest::StopTrigger stopTrigger;
  663. stopTrigger.m_triggerId = triggerId;
  664. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(stopTrigger));
  665. // Destroy the audio source, end the mic session, and reset state...
  666. AZ::Interface<IAudioSystem>::Get()->DestroyAudioSource(micSourceId);
  667. MicrophoneRequestBus::Broadcast(&MicrophoneRequestBus::Events::EndSession);
  668. micSourceId = INVALID_AUDIO_SOURCE_ID;
  669. triggerId = INVALID_AUDIO_CONTROL_ID;
  670. micState = false;
  671. }
  672. else
  673. {
  674. AZLOG_DEBUG("Error encountered while turning on/off microphone");
  675. }
  676. }
  677. else
  678. {
  679. AZLOG_INFO("Usage: s_Microphone 1 <TriggerName>\nUsage: s_Microphone 0");
  680. }
  681. }
  682. ///////////////////////////////////////////////////////////////////////////////////////////////////
  683. static void s_PlayExternalSource(const AZ::ConsoleCommandContainer& args)
  684. {
  685. // This cookie value is a hash on the name of the External Source.
  686. // By default when you add an External Source to a sound, it gives the name 'External_Source' and has this hash.
  687. // Apparently it can be changed in the Wwise project, so it's unfortunately content-dependent. But there's no easy
  688. // way to extract that info in this context.
  689. static constexpr AZ::u64 externalSourceCookieValue = 618371124ull;
  690. TAudioControlID triggerId = INVALID_AUDIO_CONTROL_ID;
  691. if (args.size() == 4)
  692. {
  693. AZStd::string triggerName(args[0]);
  694. triggerId = AZ::Interface<IAudioSystem>::Get()->GetAudioTriggerID(triggerName.c_str());
  695. if (triggerId == INVALID_AUDIO_CONTROL_ID)
  696. {
  697. AZLOG_DEBUG("Failed to find the trigger named '%s'", triggerName.c_str());
  698. return;
  699. }
  700. AZ::u64 collection;
  701. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u64>(collection, args[1]))
  702. {
  703. AZLOG_DEBUG("Invalid collection number: %.*s", AZ_STRING_ARG(args[1]));
  704. return;
  705. }
  706. AZ::u64 language;
  707. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u64>(language, args[2]))
  708. {
  709. AZLOG_DEBUG("Invalid language number: %.*s", AZ_STRING_ARG(args[2]));
  710. return;
  711. }
  712. AZ::u64 file;
  713. if (!AZ::ConsoleTypeHelpers::StringToValue<AZ::u64>(file, args[3]))
  714. {
  715. AZLOG_DEBUG("Invalid file number: %.*s", AZ_STRING_ARG(args[3]));
  716. return;
  717. }
  718. Audio::ObjectRequest::ExecuteSourceTrigger execSourceTrigger;
  719. execSourceTrigger.m_triggerId = triggerId;
  720. execSourceTrigger.m_sourceInfo = SAudioSourceInfo(externalSourceCookieValue, file, language, collection, eACT_PCM);
  721. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(execSourceTrigger));
  722. }
  723. else
  724. {
  725. AZLOG_INFO("Usage: s_PlayExternalSource <TriggerName> <Collection#> <Language#> <File#>");
  726. }
  727. }
  728. ///////////////////////////////////////////////////////////////////////////////////////////////////
  729. static void s_SetPanningMode(const AZ::ConsoleCommandContainer& args)
  730. {
  731. if (args.size() == 1)
  732. {
  733. Audio::SystemRequest::SetPanningMode setPanningMode;
  734. AZStd::string mode(args[0]);
  735. AZStd::to_lower(mode.begin(), mode.end());
  736. if (mode == "speakers")
  737. {
  738. setPanningMode.m_panningMode = PanningMode::Speakers;
  739. AZLOG_DEBUG("Setting Panning Mode to 'Speakers'");
  740. }
  741. else if (mode == "headphones")
  742. {
  743. setPanningMode.m_panningMode = PanningMode::Headphones;
  744. AZLOG_DEBUG("Setting Panning Mode to 'Headphones'");
  745. }
  746. else
  747. {
  748. AZLOG_DEBUG("Panning mode '%.*s' is invalid. Please specify either 'speakers' or 'headphones'", AZ_STRING_ARG(args[0]));
  749. return;
  750. }
  751. AZ::Interface<IAudioSystem>::Get()->PushRequest(AZStd::move(setPanningMode));
  752. }
  753. else
  754. {
  755. AZLOG_INFO("Usage: s_SetPanningMode <Speakers|Headphones>");
  756. }
  757. }
  758. #endif // !AUDIO_RELEASE
  759. } // namespace Audio::CVars