Initial Commit
This commit is contained in:
@@ -0,0 +1,429 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace OVR
|
||||
{
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
} // namespace OVR
|
||||
Reference in New Issue
Block a user