2023-05-08 15:56:10 +03:00

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);
}