374 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			374 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| /*
 | |
|  * 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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Awake this instance.
 | |
|     /// </summary>
 | |
|     void Awake()
 | |
|     {
 | |
|         // We might iterate through multiple sources / game object
 | |
|         var source = GetComponent<AudioSource>();
 | |
|         SetParameters(ref source);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Start this instance.
 | |
|     /// </summary>
 | |
|     void Start()
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Update this instance.
 | |
|     /// </summary>
 | |
|     void Update()
 | |
|     {
 | |
|         // We might iterate through multiple sources / game object
 | |
|         var source = GetComponent<AudioSource>();
 | |
| 
 | |
|         // 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
 | |
|     };
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Sets the parameters.
 | |
|     /// </summary>
 | |
|     /// <param name="source">Source.</param>
 | |
|     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;
 | |
| 
 | |
|     /// <summary>
 | |
|     ///
 | |
|     /// </summary>
 | |
|     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));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     ///
 | |
|     /// </summary>
 | |
|     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);
 | |
| }
 |