FittsLaw/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs

426 lines
13 KiB
C#
Raw Normal View History

2018-10-14 23:33:23 -04:00
using UnityEngine;
using UnityEngine.Audio;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using System;
using System.Reflection;
#endif
public enum PreloadSounds {
Default, // default unity behavior
Preload, // audio clips are forced to preload
ManualPreload, // audio clips are forced to not preload, preloading must be done manually
}
public enum Fade
{
In,
Out
}
[System.Serializable]
public class SoundGroup {
public SoundGroup( string name ) {
this.name = name;
}
public SoundGroup() {
mixerGroup = null;
maxPlayingSounds = 0;
preloadAudio = PreloadSounds.Default;
volumeOverride = 1.0f;
}
public void IncrementPlayCount() {
playingSoundCount = Mathf.Clamp( ++playingSoundCount, 0, maxPlayingSounds );
}
public void DecrementPlayCount() {
playingSoundCount = Mathf.Clamp( --playingSoundCount, 0, maxPlayingSounds );
}
public bool CanPlaySound() {
return ( maxPlayingSounds == 0 ) || ( playingSoundCount < maxPlayingSounds );
}
public string name = string.Empty;
public SoundFX[] soundList = new SoundFX[0];
public AudioMixerGroup mixerGroup = null; // default = AudioManager.defaultMixerGroup
[Range(0,64)]
public int maxPlayingSounds = 0; // default = 0, unlimited
// TODO: this preload behavior is not yet implemented
public PreloadSounds preloadAudio = PreloadSounds.Default; // default = true, audio clip data will be preloaded
public float volumeOverride = 1.0f; // default = 1.0
[HideInInspector]
public int playingSoundCount = 0;
}
/*
-----------------------
AudioManager
-----------------------
*/
public partial class AudioManager : MonoBehaviour {
[Tooltip("Make the audio manager persistent across all scene loads")]
public bool makePersistent = true; // true = don't destroy on load
[Tooltip("Enable the OSP audio plugin features")]
public bool enableSpatializedAudio = true; // true = enable spatialized audio
[Tooltip("Always play spatialized sounds with no reflections (Default)")]
public bool enableSpatializedFastOverride = false; // true = disable spatialized reflections override
[Tooltip("The audio mixer asset used for snapshot blends, etc.")]
public AudioMixer audioMixer = null;
[Tooltip( "The audio mixer group used for the pooled emitters" )]
public AudioMixerGroup defaultMixerGroup = null;
[Tooltip( "The audio mixer group used for the reserved pool emitter" )]
public AudioMixerGroup reservedMixerGroup = null;
[Tooltip( "The audio mixer group used for voice chat" )]
public AudioMixerGroup voiceChatMixerGroup = null;
[Tooltip("Log all PlaySound calls to the Unity console")]
public bool verboseLogging = false; // true = log all PlaySounds
[Tooltip("Maximum sound emitters")]
public int maxSoundEmitters = 32; // total number of sound emitters created
[Tooltip("Default volume for all sounds modulated by individual sound FX volumes")]
public float volumeSoundFX = 1.0f; // user pref: volume of all sound FX
[Tooltip("Sound FX fade time")]
public float soundFxFadeSecs = 1.0f; // sound FX fade time
public float audioMinFallOffDistance = 1.0f; // minimum falloff distance
public float audioMaxFallOffDistance = 25.0f; // maximum falloff distance
public SoundGroup[] soundGroupings = new SoundGroup[0];
private Dictionary<string,SoundFX> soundFXCache = null;
static private AudioManager theAudioManager = null;
static private FastList<string> names = new FastList<string>();
static private string[] defaultSound = new string[1] { "Default Sound" };
static private SoundFX nullSound = new SoundFX();
static private bool hideWarnings = false;
static public bool enableSpatialization { get { return ( theAudioManager !=null ) ? theAudioManager.enableSpatializedAudio : false; } }
static public AudioManager Instance { get { return theAudioManager; } }
static public float NearFallOff { get { return theAudioManager.audioMinFallOffDistance; } }
static public float FarFallOff { get { return theAudioManager.audioMaxFallOffDistance; } }
static public AudioMixerGroup EmitterGroup { get { return theAudioManager.defaultMixerGroup; } }
static public AudioMixerGroup ReservedGroup { get { return theAudioManager.reservedMixerGroup; } }
static public AudioMixerGroup VoipGroup { get { return theAudioManager.voiceChatMixerGroup; } }
/*
-----------------------
Awake()
-----------------------
*/
void Awake() {
Init();
}
/*
-----------------------
OnDestroy()
-----------------------
*/
void OnDestroy() {
// we only want the initialized audio manager instance cleaning up the sound emitters
if ( theAudioManager == this ) {
if ( soundEmitterParent != null ) {
Destroy( soundEmitterParent );
}
}
///TODO - if you change scenes you'll want to call OnPreSceneLoad to detach the sound emitters
///from anything they might be parented to or they will get destroyed with that object
///there should only be one instance of the AudioManager across the life of the game/app
///GameManager.OnPreSceneLoad -= OnPreSceneLoad;
}
/*
-----------------------
Init()
-----------------------
*/
void Init() {
if ( theAudioManager != null ) {
if ( Application.isPlaying && ( theAudioManager != this ) ) {
enabled = false;
}
return;
}
theAudioManager = this;
///TODO - if you change scenes you'll want to call OnPreSceneLoad to detach the sound emitters
///from anything they might be parented to or they will get destroyed with that object
///there should only be one instance of the AudioManager across the life of the game/app
///GameManager.OnPreSceneLoad += OnPreSceneLoad;
// make sure the first one is a null sound
nullSound.name = "Default Sound";
// build the sound FX cache
RebuildSoundFXCache();
// create the sound emitters
if ( Application.isPlaying ) {
InitializeSoundSystem();
if ( makePersistent && ( transform.parent == null ) ) {
// don't destroy the audio manager on scene loads
DontDestroyOnLoad( gameObject );
}
}
#if UNITY_EDITOR
Debug.Log( "[AudioManager] Initialized..." );
#endif
}
/*
-----------------------
Update()
-----------------------
*/
void Update() {
// update the free and playing lists
UpdateFreeEmitters();
}
/*
-----------------------
RebuildSoundFXCache()
-----------------------
*/
void RebuildSoundFXCache() {
// build the SoundFX dictionary for quick name lookups
int count = 0;
for ( int group = 0; group < soundGroupings.Length; group++ ) {
count += soundGroupings[group].soundList.Length;
}
soundFXCache = new Dictionary<string,SoundFX>( count + 1 );
// add the null sound
soundFXCache.Add( nullSound.name, nullSound );
// add the rest
for ( int group = 0; group < soundGroupings.Length; group++ ) {
for ( int i = 0; i < soundGroupings[group].soundList.Length; i++ ) {
if ( soundFXCache.ContainsKey( soundGroupings[group].soundList[i].name ) ) {
Debug.LogError( "ERROR: Duplicate Sound FX name in the audio manager: '" + soundGroupings[group].name + "' > '" + soundGroupings[group].soundList[i].name + "'" );
} else {
soundGroupings[group].soundList[i].Group = soundGroupings[group];
soundFXCache.Add( soundGroupings[group].soundList[i].name, soundGroupings[group].soundList[i] );
}
}
soundGroupings[group].playingSoundCount = 0;
}
}
/*
-----------------------
FindSoundFX()
-----------------------
*/
static public SoundFX FindSoundFX( string name, bool rebuildCache = false ) {
#if UNITY_EDITOR
if ( theAudioManager == null ) {
Debug.LogError( "ERROR: audio manager not yet initialized or created!" + " Time: " + Time.time );
return null;
}
#endif
if ( string.IsNullOrEmpty( name ) ) {
return nullSound;
}
if ( rebuildCache ) {
theAudioManager.RebuildSoundFXCache();
}
if ( !theAudioManager.soundFXCache.ContainsKey( name ) ) {
#if DEBUG_BUILD || UNITY_EDITOR
Debug.LogError( "WARNING: Missing Sound FX in cache: " + name );
#endif
return nullSound;
}
return theAudioManager.soundFXCache[name];
}
/*
-----------------------
FindAudioManager()
-----------------------
*/
static private bool FindAudioManager() {
GameObject audioManagerObject = GameObject.Find( "AudioManager" );
if ( ( audioManagerObject == null ) || ( audioManagerObject.GetComponent<AudioManager>() == null ) ) {
if ( !hideWarnings ) {
Debug.LogError( "[ERROR] AudioManager object missing from hierarchy!" );
hideWarnings = true;
}
return false;
} else {
audioManagerObject.GetComponent<AudioManager>().Init();
}
return true;
}
/*
-----------------------
GetGameObject()
-----------------------
*/
static public GameObject GetGameObject() {
if ( theAudioManager == null ) {
if ( !FindAudioManager() ) {
return null;
}
}
return theAudioManager.gameObject;
}
/*
-----------------------
NameMinusGroup()
strip off the sound group from the inspector dropdown
-----------------------
*/
static public string NameMinusGroup( string name ) {
if ( name.IndexOf( "/" ) > -1 ) {
return name.Substring( name.IndexOf( "/" ) + 1 );
}
return name;
}
/*
-----------------------
GetSoundFXNames()
used by the inspector
-----------------------
*/
static public string[] GetSoundFXNames( string currentValue, out int currentIdx ) {
currentIdx = 0;
names.Clear();
if ( theAudioManager == null ) {
if ( !FindAudioManager() ) {
return defaultSound;
}
}
names.Add( nullSound.name );
for ( int group = 0; group < theAudioManager.soundGroupings.Length; group++ ) {
for ( int i = 0; i < theAudioManager.soundGroupings[group].soundList.Length; i++ ) {
if ( string.Compare( currentValue, theAudioManager.soundGroupings[group].soundList[i].name, true ) == 0 ) {
currentIdx = names.Count;
}
names.Add( theAudioManager.soundGroupings[group].name + "/" + theAudioManager.soundGroupings[group].soundList[i].name );
}
}
//names.Sort( delegate( string s1, string s2 ) { return s1.CompareTo( s2 ); } );
return names.ToArray();
}
#if UNITY_EDITOR
/*
-----------------------
OnPrefabReimported()
-----------------------
*/
static public void OnPrefabReimported() {
if ( theAudioManager != null ) {
Debug.Log( "[AudioManager] Reimporting the sound FX cache." );
theAudioManager.RebuildSoundFXCache();
}
}
/*
-----------------------
PlaySound()
used in the editor
-----------------------
*/
static public void PlaySound( string soundFxName ) {
if ( theAudioManager == null ) {
if ( !FindAudioManager() ) {
return;
}
}
SoundFX soundFX = FindSoundFX( soundFxName, true );
if ( soundFX == null ) {
return;
}
AudioClip clip = soundFX.GetClip();
if ( clip != null ) {
Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
MethodInfo method = audioUtilClass.GetMethod(
"PlayClip",
BindingFlags.Static | BindingFlags.Public,
null,
new System.Type[] { typeof(AudioClip) },
null );
method.Invoke( null, new object[] { clip } );
}
}
/*
-----------------------
IsSoundPlaying()
used in the editor
-----------------------
*/
static public bool IsSoundPlaying( string soundFxName ) {
if ( theAudioManager == null ) {
if ( !FindAudioManager() ) {
return false;
}
}
SoundFX soundFX = FindSoundFX( soundFxName, true );
if ( soundFX == null ) {
return false;
}
AudioClip clip = soundFX.GetClip();
if ( clip != null ) {
Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
MethodInfo method = audioUtilClass.GetMethod(
"IsClipPlaying",
BindingFlags.Static | BindingFlags.Public,
null,
new System.Type[] { typeof(AudioClip) },
null );
return Convert.ToBoolean( method.Invoke( null, new object[] { clip } ) );
}
return false;
}
/*
-----------------------
StopSound()
used in the editor
-----------------------
*/
static public void StopSound(string soundFxName)
{
if (theAudioManager == null)
{
if (!FindAudioManager())
{
return;
}
}
SoundFX soundFX = FindSoundFX(soundFxName, true);
if (soundFX == null)
{
return;
}
AudioClip clip = soundFX.GetClip();
if (clip != null)
{
Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
MethodInfo method = audioUtilClass.GetMethod(
"StopClip",
BindingFlags.Static | BindingFlags.Public,
null,
new System.Type[] { typeof(AudioClip) },
null);
method.Invoke(null, new object[] { clip });
}
}
#endif
}