mirror of
https://github.com/nothke/quality-control.git
synced 2024-11-12 22:03:42 +00:00
Added NAudio
This commit is contained in:
parent
2db5ea7ef2
commit
747458335d
325
Assets/Scripts/NAudio.cs
Normal file
325
Assets/Scripts/NAudio.cs
Normal file
@ -0,0 +1,325 @@
|
||||
///
|
||||
/// NAudio by Nothke
|
||||
/// Simple clip playing and audio source creation in a single line
|
||||
///
|
||||
/// See function summaries and examples for usage
|
||||
///
|
||||
|
||||
/// DEFINES:
|
||||
///
|
||||
/// Pooling creates a few sources on start and saves them in a queue, reusing them on every play,
|
||||
/// so sources are not created and destroyed every time played, freeing GC.
|
||||
/// If you don't want to use pooling, comment this line:
|
||||
#define POOLING
|
||||
|
||||
/// If you are using native audio spatializer, uncomment following line. It will enable spatialization in sources
|
||||
//#define ENABLE_SPATIALIZER_API
|
||||
|
||||
/// If using Oculus audio - ONSP, uncomment following line. It will add the ONSPAudioSource script to sources
|
||||
//#define USE_OCULUS_AUDIO
|
||||
|
||||
//#define SEEK_NOT_PLAYING_SOURCES
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
public static class NAudio
|
||||
{
|
||||
#if POOLING
|
||||
public static Queue<AudioSource> sourcePool;
|
||||
const int POOL_SIZE = 50;
|
||||
#else
|
||||
// Just to make sure destroy won't cut the sound short in case of an increased latency
|
||||
const float DESTROY_AFTER_MARGIN_SECONDS = 0.2f;
|
||||
#endif
|
||||
|
||||
const float DEFAULT_MIN_DISTANCE = 1;
|
||||
const float DEFAULT_SPREAD = 0;
|
||||
|
||||
public static Transform root;
|
||||
|
||||
#if POOLING
|
||||
static AudioSource GetNextSource()
|
||||
{
|
||||
AudioSource source = sourcePool.Dequeue();
|
||||
sourcePool.Enqueue(source);
|
||||
|
||||
#if SEEK_NOT_PLAYING_SOURCES
|
||||
int search = 0;
|
||||
|
||||
while (source.isPlaying)
|
||||
{
|
||||
source = sourcePool.Dequeue();
|
||||
sourcePool.Enqueue(source);
|
||||
|
||||
|
||||
if (search >= POOL_SIZE)
|
||||
{
|
||||
Debug.LogError("All sounds are playing, increase the pool size");
|
||||
break;
|
||||
}
|
||||
|
||||
search++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void InitializePool()
|
||||
{
|
||||
InitializePool(POOL_SIZE);
|
||||
}
|
||||
|
||||
public static void InitializePool(int size)
|
||||
{
|
||||
if (sourcePool != null && sourcePool.Count > 0)
|
||||
{
|
||||
//Debug.LogWarning("Pool already exists");
|
||||
|
||||
foreach (var source in sourcePool)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
Object.Destroy(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourcePool = new Queue<AudioSource>(size);
|
||||
|
||||
GameObject rootGO = new GameObject("NAudio_Pool");
|
||||
root = rootGO.transform;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
sourcePool.Enqueue(CreateSource(root));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Plays a clip at a position with properties
|
||||
/// </summary>
|
||||
/// <param name="clip">Clip to play</param>
|
||||
/// <param name="position">Position at which it will be played</param>
|
||||
/// <param name="volume"></param>
|
||||
/// <param name="pitch"></param>
|
||||
/// <param name="spread">How 'wide' the panning will be in 3d. 0 means it will be heard from only one direction, 180 is all around, 360 is opposite direction.</param>
|
||||
/// <param name="minDistance">The distance at which source volume will be 1 and falloff. Technically this is the sound intensity.</param>
|
||||
/// <param name="mixerGroup">Add source to mixer group</param>
|
||||
/// <param name="parent">A transform to attach source to. Position is still world position before parenting.</param>
|
||||
/// <returns></returns>
|
||||
public static AudioSource Play(
|
||||
this AudioClip clip,
|
||||
Vector3 position,
|
||||
float volume = 1,
|
||||
float pitch = 1,
|
||||
float spread = DEFAULT_SPREAD,
|
||||
float minDistance = DEFAULT_MIN_DISTANCE,
|
||||
AudioMixerGroup mixerGroup = null,
|
||||
Transform parent = null)
|
||||
{
|
||||
if (volume == 0) return null;
|
||||
if (pitch == 0) return null;
|
||||
Debug.Assert(clip != null, "No AudioClip was passed");
|
||||
|
||||
|
||||
#if POOLING
|
||||
if (sourcePool == null)
|
||||
InitializePool();
|
||||
|
||||
AudioSource source = GetNextSource();
|
||||
if (!source) return null;
|
||||
|
||||
GameObject go = source.gameObject;
|
||||
#else
|
||||
GameObject go = new GameObject("AudioTemp");
|
||||
AudioSource source = go.AddComponent<AudioSource>();
|
||||
#endif
|
||||
go.transform.position = position;
|
||||
|
||||
source.spatialBlend = 1; // Makes the source 3D
|
||||
source.minDistance = minDistance;
|
||||
|
||||
source.loop = false;
|
||||
source.clip = clip;
|
||||
|
||||
source.volume = volume;
|
||||
source.pitch = pitch;
|
||||
source.spread = spread;
|
||||
|
||||
source.dopplerLevel = 0;
|
||||
|
||||
source.outputAudioMixerGroup = mixerGroup;
|
||||
|
||||
if (parent)
|
||||
source.transform.parent = parent;
|
||||
|
||||
#if ENABLE_SPATIALIZER_API
|
||||
source.spatialize = true;
|
||||
#endif
|
||||
|
||||
#if USE_OCULUS_AUDIO && !POOLING
|
||||
source.gameObject.AddComponent<ONSPAudioSource>().SetParameters(ref source);
|
||||
#endif
|
||||
|
||||
source.Play();
|
||||
|
||||
#if !POOLING
|
||||
// Division by zero prevented at the top of the function
|
||||
GameObject.Destroy(source.gameObject, clip.length * (1 / pitch) + DESTROY_AFTER_MARGIN_SECONDS);
|
||||
#endif
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random AudioClip from an array at a position
|
||||
/// </summary>
|
||||
/// <param name="clips">An array of AudioClips</param>
|
||||
/// <param name="position">Position at which it will be played</param>
|
||||
/// <param name="volume"></param>
|
||||
/// <param name="pitch"></param>
|
||||
/// <param name="spread">How 'wide' the panning will be in 3d. 0 means it will be heard from only one direction, 180 is all around, 360 is opposite direction.</param>
|
||||
/// <param name="minDistance">The distance at which source volume will be 1 and falloff. Technically this is the sound intensity.</param>
|
||||
/// <param name="mixerGroup">Add source to mixer group</param>
|
||||
/// <param name="parent">A transform to attach source to. Position is still world position before parenting.</param>
|
||||
/// <param name="noRepeatSwap">Swaps the order of array so that the same clip never plays twice in succession. Changes the order of clips in the input array.</param>
|
||||
/// <returns></returns>
|
||||
public static AudioSource Play(
|
||||
this AudioClip[] clips, Vector3 position,
|
||||
float volume = 1, float pitch = 1,
|
||||
float spread = DEFAULT_SPREAD,
|
||||
float minDistance = DEFAULT_MIN_DISTANCE,
|
||||
AudioMixerGroup mixerGroup = null,
|
||||
Transform parent = null,
|
||||
bool noRepeatSwap = false)
|
||||
{
|
||||
Debug.Assert(clips != null, "NAudio: Clips array is null");
|
||||
Debug.Assert(clips.Length != 0, "NAudio: No clips in array");
|
||||
|
||||
int i;
|
||||
if (clips.Length == 0)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
else if (noRepeatSwap)
|
||||
{
|
||||
i = Random.Range(1, clips.Length);
|
||||
var tmp = clips[0];
|
||||
clips[0] = clips[i];
|
||||
clips[i] = tmp;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = Random.Range(0, clips.Length);
|
||||
}
|
||||
|
||||
return Play(clips[i], position, volume, pitch, spread, minDistance, mixerGroup, parent);
|
||||
}
|
||||
|
||||
#region 2D
|
||||
|
||||
static AudioSource _source2D;
|
||||
static AudioSource source2D
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_source2D)
|
||||
_source2D = CreateSource(spatialBlend: 0, loop: false);
|
||||
|
||||
return _source2D;
|
||||
}
|
||||
}
|
||||
|
||||
public static AudioSource Play2D(
|
||||
this AudioClip clip,
|
||||
float volume = 1)
|
||||
{
|
||||
source2D.PlayOneShot(clip, volume);
|
||||
|
||||
return source2D;
|
||||
}
|
||||
|
||||
public static AudioSource Play2D(
|
||||
this AudioClip[] clips, float volume = 1)
|
||||
{
|
||||
source2D.PlayOneShot(clips[Random.Range(0, clips.Length)], volume);
|
||||
|
||||
return source2D;
|
||||
}
|
||||
|
||||
public static AudioSource Play2D(
|
||||
this AudioClip[] clips,
|
||||
float volume = 1, float pitch = 1,
|
||||
float spread = DEFAULT_SPREAD,
|
||||
float minDistance = DEFAULT_MIN_DISTANCE,
|
||||
AudioMixerGroup mixerGroup = null)
|
||||
{
|
||||
return Play(clips[Random.Range(0, clips.Length)], Vector3.zero, volume, pitch, spread, minDistance, mixerGroup);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// AUDIO SOURCE CREATION
|
||||
|
||||
/// <summary>
|
||||
/// Creates an audio source with parameters
|
||||
/// </summary>
|
||||
/// <param name="at">Creates a source object as a child to this transform</param>
|
||||
/// <param name="clip">AudioClip that will be attached to this source and played when Play() is called</param>
|
||||
/// <param name="volume"></param>
|
||||
/// <param name="pitch"></param>
|
||||
/// <param name="loop"></param>
|
||||
/// <param name="playAtStart"></param>
|
||||
/// <param name="minDistance"></param>
|
||||
/// <param name="spread"></param>
|
||||
/// <param name="spatialBlend"></param>
|
||||
/// <param name="mixerGroup"></param>
|
||||
/// <returns></returns>
|
||||
public static AudioSource CreateSource(
|
||||
Transform at = null, AudioClip clip = null,
|
||||
float volume = 1, float pitch = 1,
|
||||
bool loop = true, bool playAtStart = false,
|
||||
float minDistance = DEFAULT_MIN_DISTANCE,
|
||||
float spread = DEFAULT_SPREAD,
|
||||
float spatialBlend = 1,
|
||||
AudioMixerGroup mixerGroup = null)
|
||||
{
|
||||
GameObject go = new GameObject("AudioLoop");
|
||||
go.transform.parent = at;
|
||||
go.transform.localPosition = Vector3.zero;
|
||||
|
||||
AudioSource source = go.AddComponent<AudioSource>();
|
||||
|
||||
source.loop = loop;
|
||||
source.clip = clip;
|
||||
|
||||
source.volume = volume;
|
||||
source.spatialBlend = spatialBlend;
|
||||
source.spread = spread;
|
||||
source.minDistance = minDistance;
|
||||
|
||||
source.playOnAwake = playAtStart;
|
||||
|
||||
source.outputAudioMixerGroup = mixerGroup;
|
||||
|
||||
#if USE_OCULUS_AUDIO
|
||||
source.gameObject.AddComponent<ONSPAudioSource>().SetParameters(ref source);
|
||||
#endif
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
public static void PlayRandomTime(this AudioSource source)
|
||||
{
|
||||
if (source.clip == null) return;
|
||||
|
||||
source.time = Random.Range(0, source.clip.length);
|
||||
source.Play();
|
||||
}
|
||||
}
|
12
Assets/Scripts/NAudio.cs.meta
Normal file
12
Assets/Scripts/NAudio.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22e08800f371729479644cea9437e572
|
||||
timeCreated: 1489646197
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue
Block a user