/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /************************************************************************************ * Filename : ONSPAudioSource.cs * Content : Interface into the Oculus Native Spatializer Plugin ***********************************************************************************/ // Uncomment below to test access of read-only spatializer parameters //#define TEST_READONLY_PARAMETERS #if !(UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || (UNITY_ANDROID && !UNITY_EDITOR)) #define ONSP_UNSUPPORTED_PLATFORM #endif using UnityEngine; using System; using System.Collections; using System.Runtime.InteropServices; public class ONSPAudioSource : MonoBehaviour { #if TEST_READONLY_PARAMETERS // Spatializer read-only system parameters (global) static int readOnly_GlobalRelectionOn = 7; static int readOnly_NumberOfUsedSpatializedVoices = 8; #endif [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] static void OnBeforeSceneLoadRuntimeMethod() { #if !ONSP_UNSUPPORTED_PLATFORM OSP_SetGlobalVoiceLimit(ONSPSettings.Instance.voiceLimit); #endif } // Import functions public const string strONSPS = "AudioPluginOculusSpatializer"; [DllImport(strONSPS)] private static extern void ONSP_GetGlobalRoomReflectionValues(ref bool reflOn, ref bool reverbOn, ref float width, ref float height, ref float length); // Public [SerializeField] private bool enableSpatialization = true; public bool EnableSpatialization { get { return enableSpatialization; } set { enableSpatialization = value; } } [SerializeField] private float gain = 0.0f; public float Gain { get { return gain; } set { gain = Mathf.Clamp(value, 0.0f, 24.0f); } } [SerializeField] private bool useInvSqr = false; public bool UseInvSqr { get { return useInvSqr; } set { useInvSqr = value; } } [SerializeField] private float near = 0.25f; public float Near { get { return near; } set { near = Mathf.Clamp(value, 0.0f, 1000000.0f); } } [SerializeField] private float far = 250.0f; public float Far { get { return far; } set { far = Mathf.Clamp(value, 0.0f, 1000000.0f); } } [SerializeField] private float volumetricRadius = 0.0f; public float VolumetricRadius { get { return volumetricRadius; } set { volumetricRadius = Mathf.Clamp(value, 0.0f, 1000.0f); } } [SerializeField] private float reverbSend = 0.0f; public float ReverbSend { get { return reverbSend; } set { reverbSend = Mathf.Clamp(value, -60.0f, 20.0f); } } [SerializeField] private bool enableRfl = false; public bool EnableRfl { get { return enableRfl; } set { enableRfl = value; } } /// /// Awake this instance. /// void Awake() { // We might iterate through multiple sources / game object var source = GetComponent(); SetParameters(ref source); } /// /// Start this instance. /// void Start() { } /// /// Update this instance. /// void Update() { // We might iterate through multiple sources / game object var source = GetComponent(); // READ-ONLY PARAMETER TEST #if TEST_READONLY_PARAMETERS float rfl_enabled = 0.0f; source.GetSpatializerFloat(readOnly_GlobalRelectionOn, out rfl_enabled); float num_voices = 0.0f; source.GetSpatializerFloat(readOnly_NumberOfUsedSpatializedVoices, out num_voices); String readOnly = System.String.Format ("Read only values: refl enabled: {0:F0} num voices: {1:F0}", rfl_enabled, num_voices); Debug.Log(readOnly); #endif // Check to see if we should disable spatializion if ((Application.isPlaying == false) || (AudioListener.pause == true) || (source.isPlaying == false) || (source.isActiveAndEnabled == false) ) { source.spatialize = false; return; } else { SetParameters(ref source); } } enum Parameters : int { P_GAIN = 0, P_USEINVSQR, P_NEAR, P_FAR, P_RADIUS, P_DISABLE_RFL, P_AMBISTAT, P_READONLY_GLOBAL_RFL_ENABLED, // READ-ONLY P_READONLY_NUM_VOICES, // READ-ONLY P_SENDLEVEL, P_NUM }; /// /// Sets the parameters. /// /// Source. public void SetParameters(ref AudioSource source) { // See if we should enable spatialization source.spatialize = enableSpatialization; source.SetSpatializerFloat((int)Parameters.P_GAIN, gain); // All inputs are floats; convert bool to 0.0 and 1.0 if(useInvSqr == true) source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 1.0f); else source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 0.0f); source.SetSpatializerFloat((int)Parameters.P_NEAR, near); source.SetSpatializerFloat((int)Parameters.P_FAR, far); source.SetSpatializerFloat((int)Parameters.P_RADIUS, volumetricRadius); if(enableRfl == true) source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 0.0f); else source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 1.0f); source.SetSpatializerFloat((int)Parameters.P_SENDLEVEL, reverbSend); } private static ONSPAudioSource RoomReflectionGizmoAS = null; /// /// /// void OnDrawGizmos() { // Are we the first one created? make sure to set our static ONSPAudioSource // for drawing out room parameters once if(RoomReflectionGizmoAS == null) { RoomReflectionGizmoAS = this; } Color c; const float colorSolidAlpha = 0.1f; // Draw the near/far spheres // Near (orange) c.r = 1.0f; c.g = 0.5f; c.b = 0.0f; c.a = 1.0f; Gizmos.color = c; Gizmos.DrawWireSphere(transform.position, Near); c.a = colorSolidAlpha; Gizmos.color = c; Gizmos.DrawSphere(transform.position, Near); // Far (red) c.r = 1.0f; c.g = 0.0f; c.b = 0.0f; c.a = 1.0f; Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, Far); c.a = colorSolidAlpha; Gizmos.color = c; Gizmos.DrawSphere(transform.position, Far); // VolumetricRadius (purple) c.r = 1.0f; c.g = 0.0f; c.b = 1.0f; c.a = 1.0f; Gizmos.color = c; Gizmos.DrawWireSphere(transform.position, VolumetricRadius); c.a = colorSolidAlpha; Gizmos.color = c; Gizmos.DrawSphere(transform.position, VolumetricRadius); // Draw room parameters ONCE only, provided reflection engine is on if (RoomReflectionGizmoAS == this) { // Get global room parameters (write new C api to get reflection values) bool reflOn = false; bool reverbOn = false; float width = 1.0f; float height = 1.0f; float length = 1.0f; ONSP_GetGlobalRoomReflectionValues(ref reflOn, ref reverbOn, ref width, ref height, ref length); // TO DO: Get the room reflection values and render those out as well (like we do in the VST) if((Camera.main != null) && (reflOn == true)) { // Set color of cube (cyan is early reflections only, white is with reverb on) if(reverbOn == true) c = Color.white; else c = Color.cyan; Gizmos.color = c; Gizmos.DrawWireCube(Camera.main.transform.position, new Vector3(width, height, length)); c.a = colorSolidAlpha; Gizmos.color = c; Gizmos.DrawCube(Camera.main.transform.position, new Vector3(width, height, length)); } } } /// /// /// void OnDestroy() { // We will null out single pointer instance // of the room reflection gizmo since we are being destroyed. // Any ONSPAS that is alive or born will re-set this pointer // so that we only draw it once if(RoomReflectionGizmoAS == this) { RoomReflectionGizmoAS = null; } } [System.Runtime.InteropServices.DllImport("AudioPluginOculusSpatializer")] private static extern int OSP_SetGlobalVoiceLimit(int VoiceLimit); }