multiple xr toolkit package
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ONSPAudioSource.cs 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /************************************************************************************
  2. Filename : ONSPAudioSource.cs
  3. Content : Interface into the Oculus Native Spatializer Plugin
  4. Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
  5. Licensed under the Oculus SDK Version 3.5 (the "License");
  6. you may not use the Oculus SDK except in compliance with the License,
  7. which is provided at the time of installation or download, or which
  8. otherwise accompanies this software in either electronic or hard copy form.
  9. You may obtain a copy of the License at
  10. https://developer.oculus.com/licenses/sdk-3.5/
  11. Unless required by applicable law or agreed to in writing, the Oculus SDK
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. ************************************************************************************/
  17. // Uncomment below to test access of read-only spatializer parameters
  18. //#define TEST_READONLY_PARAMETERS
  19. using UnityEngine;
  20. using System;
  21. using System.Collections;
  22. using System.Runtime.InteropServices;
  23. public class ONSPAudioSource : MonoBehaviour
  24. {
  25. #if TEST_READONLY_PARAMETERS
  26. // Spatializer read-only system parameters (global)
  27. static int readOnly_GlobalRelectionOn = 8;
  28. static int readOnly_NumberOfUsedSpatializedVoices = 9;
  29. #endif
  30. // Import functions
  31. public const string strONSPS = "AudioPluginOculusSpatializer";
  32. [DllImport(strONSPS)]
  33. private static extern void ONSP_GetGlobalRoomReflectionValues(ref bool reflOn, ref bool reverbOn,
  34. ref float width, ref float height, ref float length);
  35. // Public
  36. [SerializeField]
  37. private bool enableSpatialization = true;
  38. public bool EnableSpatialization
  39. {
  40. get
  41. {
  42. return enableSpatialization;
  43. }
  44. set
  45. {
  46. enableSpatialization = value;
  47. }
  48. }
  49. [SerializeField]
  50. private float gain = 0.0f;
  51. public float Gain
  52. {
  53. get
  54. {
  55. return gain;
  56. }
  57. set
  58. {
  59. gain = Mathf.Clamp(value, 0.0f, 24.0f);
  60. }
  61. }
  62. [SerializeField]
  63. private bool useInvSqr = false;
  64. public bool UseInvSqr
  65. {
  66. get
  67. {
  68. return useInvSqr;
  69. }
  70. set
  71. {
  72. useInvSqr = value;
  73. }
  74. }
  75. [SerializeField]
  76. private float near = 0.25f;
  77. public float Near
  78. {
  79. get
  80. {
  81. return near;
  82. }
  83. set
  84. {
  85. near = Mathf.Clamp(value, 0.0f, 1000000.0f);
  86. }
  87. }
  88. [SerializeField]
  89. private float far = 250.0f;
  90. public float Far
  91. {
  92. get
  93. {
  94. return far;
  95. }
  96. set
  97. {
  98. far = Mathf.Clamp(value, 0.0f, 1000000.0f);
  99. }
  100. }
  101. [SerializeField]
  102. private float volumetricRadius = 0.0f;
  103. public float VolumetricRadius
  104. {
  105. get
  106. {
  107. return volumetricRadius;
  108. }
  109. set
  110. {
  111. volumetricRadius = Mathf.Clamp(value, 0.0f, 1000.0f);
  112. }
  113. }
  114. [SerializeField]
  115. private float reverbSend = 0.0f;
  116. public float ReverbSend
  117. {
  118. get
  119. {
  120. return reverbSend;
  121. }
  122. set
  123. {
  124. reverbSend = Mathf.Clamp(value, -60.0f, 20.0f);
  125. }
  126. }
  127. [SerializeField]
  128. private bool enableRfl = false;
  129. public bool EnableRfl
  130. {
  131. get
  132. {
  133. return enableRfl;
  134. }
  135. set
  136. {
  137. enableRfl = value;
  138. }
  139. }
  140. /// VRCHAT: We need to reset the params after avatar loading and viseme setup
  141. public void Reset()
  142. {
  143. var source = GetComponent<AudioSource>();
  144. if(source == null)
  145. {
  146. enabled = false;
  147. return;
  148. }
  149. SetParameters(ref source);
  150. }
  151. /// <summary>
  152. /// Awake this instance.
  153. /// </summary>
  154. void Awake()
  155. {
  156. Reset();
  157. }
  158. /// <summary>
  159. /// Start this instance.
  160. /// </summary>
  161. void Start()
  162. {
  163. #if VRC_CLIENT
  164. var source = GetComponent<AudioSource>();
  165. if(source != null && source.outputAudioMixerGroup != VRCAudioManager.GetAvatarGroup())
  166. VRCAudioManager.ApplyGameAudioMixerSettings(source);
  167. #endif
  168. }
  169. /// <summary>
  170. /// Update this instance.
  171. /// </summary>
  172. void LateUpdate()
  173. {
  174. // We might iterate through multiple sources / game object
  175. var source = GetComponent<AudioSource>();
  176. if(source == null)
  177. {
  178. enabled = false;
  179. return;
  180. }
  181. // READ-ONLY PARAMETER TEST
  182. #if TEST_READONLY_PARAMETERS
  183. float rfl_enabled = 0.0f;
  184. source.GetSpatializerFloat(readOnly_GlobalRelectionOn, out rfl_enabled);
  185. float num_voices = 0.0f;
  186. source.GetSpatializerFloat(readOnly_NumberOfUsedSpatializedVoices, out num_voices);
  187. String readOnly = System.String.Format
  188. ("Read only values: refl enabled: {0:F0} num voices: {1:F0}", rfl_enabled, num_voices);
  189. Debug.Log(readOnly);
  190. #endif
  191. // Check to see if we should disable spatializion
  192. if ((Application.isPlaying == false) ||
  193. (AudioListener.pause == true) ||
  194. (source.isPlaying == false) ||
  195. (source.isActiveAndEnabled == false)
  196. )
  197. {
  198. source.spatialize = false;
  199. return;
  200. }
  201. else
  202. {
  203. SetParameters(ref source);
  204. }
  205. }
  206. enum Parameters : int
  207. {
  208. P_GAIN = 0,
  209. P_USEINVSQR,
  210. P_NEAR,
  211. P_FAR,
  212. P_RADIUS,
  213. P_DISABLE_RFL,
  214. P_VSPEAKERMODE,
  215. P_AMBISTAT,
  216. P_READONLY_GLOBAL_RFL_ENABLED, // READ-ONLY
  217. P_READONLY_NUM_VOICES, // READ-ONLY
  218. P_SENDLEVEL,
  219. P_NUM
  220. };
  221. /// <summary>
  222. /// Sets the parameters.
  223. /// </summary>
  224. /// <param name="source">Source.</param>
  225. public void SetParameters(ref AudioSource source)
  226. {
  227. // VRCHAT: indentation is weird intentionally, for easier diff
  228. // jnuccio: added try here to catch unknown exception reported in analytics
  229. try
  230. {
  231. if (source == null)
  232. return;
  233. // See if we should enable spatialization
  234. source.spatialize = enableSpatialization;
  235. source.SetSpatializerFloat((int)Parameters.P_GAIN, gain);
  236. // All inputs are floats; convert bool to 0.0 and 1.0
  237. if(useInvSqr == true)
  238. source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 1.0f);
  239. else
  240. source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 0.0f);
  241. source.SetSpatializerFloat((int)Parameters.P_NEAR, near);
  242. source.SetSpatializerFloat((int)Parameters.P_FAR, far);
  243. source.SetSpatializerFloat((int)Parameters.P_RADIUS, volumetricRadius);
  244. if(enableRfl == true)
  245. source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 0.0f);
  246. else
  247. source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 1.0f);
  248. source.SetSpatializerFloat((int)Parameters.P_SENDLEVEL, reverbSend);
  249. // VRCHAT: indentation is weird intentionally, for easier diff
  250. }
  251. catch (Exception)
  252. {
  253. // not sure why this throws sometimes
  254. }
  255. }
  256. private static ONSPAudioSource RoomReflectionGizmoAS = null;
  257. /// <summary>
  258. ///
  259. /// </summary>
  260. void OnDrawGizmos()
  261. {
  262. // Are we the first one created? make sure to set our static ONSPAudioSource
  263. // for drawing out room parameters once
  264. if(RoomReflectionGizmoAS == null)
  265. {
  266. RoomReflectionGizmoAS = this;
  267. }
  268. Color c;
  269. const float colorSolidAlpha = 0.1f;
  270. // Draw the near/far spheres
  271. // Near (orange)
  272. c.r = 1.0f;
  273. c.g = 0.5f;
  274. c.b = 0.0f;
  275. c.a = 1.0f;
  276. Gizmos.color = c;
  277. Gizmos.DrawWireSphere(transform.position, Near);
  278. c.a = colorSolidAlpha;
  279. Gizmos.color = c;
  280. Gizmos.DrawSphere(transform.position, Near);
  281. // Far (red)
  282. c.r = 1.0f;
  283. c.g = 0.0f;
  284. c.b = 0.0f;
  285. c.a = 1.0f;
  286. Gizmos.color = Color.red;
  287. Gizmos.DrawWireSphere(transform.position, Far);
  288. c.a = colorSolidAlpha;
  289. Gizmos.color = c;
  290. Gizmos.DrawSphere(transform.position, Far);
  291. // VolumetricRadius (purple)
  292. c.r = 1.0f;
  293. c.g = 0.0f;
  294. c.b = 1.0f;
  295. c.a = 1.0f;
  296. Gizmos.color = c;
  297. Gizmos.DrawWireSphere(transform.position, VolumetricRadius);
  298. c.a = colorSolidAlpha;
  299. Gizmos.color = c;
  300. Gizmos.DrawSphere(transform.position, VolumetricRadius);
  301. // Draw room parameters ONCE only, provided reflection engine is on
  302. if (RoomReflectionGizmoAS == this)
  303. {
  304. // Get global room parameters (write new C api to get reflection values)
  305. bool reflOn = false;
  306. bool reverbOn = false;
  307. float width = 1.0f;
  308. float height = 1.0f;
  309. float length = 1.0f;
  310. ONSP_GetGlobalRoomReflectionValues(ref reflOn, ref reverbOn, ref width, ref height, ref length);
  311. // TO DO: Get the room reflection values and render those out as well (like we do in the VST)
  312. if((Camera.main != null) && (reflOn == true))
  313. {
  314. // Set color of cube (cyan is early reflections only, white is with reverb on)
  315. if(reverbOn == true)
  316. c = Color.white;
  317. else
  318. c = Color.cyan;
  319. Gizmos.color = c;
  320. Gizmos.DrawWireCube(Camera.main.transform.position, new Vector3(width, height, length));
  321. c.a = colorSolidAlpha;
  322. Gizmos.color = c;
  323. Gizmos.DrawCube(Camera.main.transform.position, new Vector3(width, height, length));
  324. }
  325. }
  326. }
  327. /// <summary>
  328. ///
  329. /// </summary>
  330. void OnDestroy()
  331. {
  332. // We will null out single pointer instance
  333. // of the room reflection gizmo since we are being destroyed.
  334. // Any ONSPAS that is alive or born will re-set this pointer
  335. // so that we only draw it once
  336. if(RoomReflectionGizmoAS == this)
  337. {
  338. RoomReflectionGizmoAS = null;
  339. }
  340. }
  341. }