Audio

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removing all content from page)
m (Reverted edits by Joseph05408 (Talk); changed back to last version by Jessy)
Line 1: Line 1:
 +
[[Category: Sound]]
 +
Author: ''Jessy''
  
 +
==Description==
 +
 +
This is a script that replaces most properties of Audio Sources.  I feel that its controls behave more intuitively then those of the Audio Source component itself, and it extends functionality as well.  I intend for it to be easy to switch from scripting and tweaking Audio Sources directly, to utilizing this script.
 +
 +
I have also created a [[Listener|simple derivative of this script]], to control the volume of the Audio Listener.
 +
 +
== General Instructions==
 +
 +
Attach this script to the Game Objects that contain Audio Sources.  Change the exposed variables in the Editor for immediate results, or use the methods described in the JavaScript or C# sections.
 +
 +
If your Game Object has only one Audio Source, then it will automatically be assigned to this script's '''Audio Source''' variable, when the script attached.  (If there is no Audio Source present on the Game Object when you attach this script, one will automatically be created, attached, and assigned.)  The '''Audio Listener''' variable should always be automatically assigned properly, as Unity requires there to be exactly one Audio Listener per scene.  If the '''Audio Source''' and '''Audio Listener''' parameters are not automatically populated to your liking, or you make later changes to your scene setup that requires reassignment, drag the Game Objects containing the appropriate components onto the '''Audio Source''' and/or '''Audio Listener''' variable slots in the Inspector.  You can make assignments programmatically via the '''''audioSource''''' and '''''audioListener''''' variables. 
 +
 +
The '''Volume''', '''Min Volume''', '''Max Volume''', and '''Rolloff Factor''' parameters perform the tasks that the similarly-named parameters of Audio Sources were intended to perform.
 +
 +
'''Rolloff Threshold''' defines a distance from the Audio Listener within which sound will not get quieter over distance.  (Unity normally fixes this distance to 1 world unit.)  This can be especially useful for dealing with "extreme" scale characters.  (Use large values for giant monsters, small values for insects.  See the bottom of this page for more tips.)
 +
 +
If '''Ignore Distance''' is unchecked, it allows stereo clips to fade in volume over distance (but they do not get positioned in 3D "sound space").  For mono clips, checking this is a more efficient method for achieving the same result as setting '''Rolloff Factor''' to zero.
 +
 +
 +
==Javascript Instructions==
 +
Use the following variable declaration in an external script, and drag the Game Object containing the Audio (script) component onto the '''Audio Script''' variable slot in the Inspector:
 +
 +
<javascript>var audioScript : Audio;</javascript>
 +
 +
 +
In that script, use the following methods to assign the '''volume''', '''minVolume''', '''maxVolume''', and '''rolloffFactor''' parameters a value of ''value'', instead of assigning a value to any of those parameter directly. 
 +
 +
''audioScript.Volume(value);''
 +
 +
''audioScript.MinVolume(value);''
 +
 +
''audioScript.MaxVolume(value);''
 +
 +
''audioScript.RolloffFactor(value);''
 +
 +
 +
Advanced users can access the resulting values of what the '''volume''', '''minVolume''', '''maxVolume''', and '''rolloffFactor''' parameters are used for, via these methods:
 +
 +
''audioScript.Volume()''
 +
 +
''audioScript.MinVolume()''
 +
 +
''audioScript.MaxVolume()''
 +
 +
''audioScript.RolloffFactor()''
 +
 +
 +
(You may find the way properties are handled via C# to be more intuitive.)
 +
 +
'''''audioScript.audioSource''''', '''''audioScript.audioListener''''', '''''audioScript.RolloffThreshold''''', and '''''audioScript.ignoreDistance''''' should be read and written to directly.
 +
 +
 +
== JavaScript - Audio.js ==
 +
<javascript>// helps to automatically link the first attached instance of this script
 +
// to an Audio Source, if no Audio Sources were present
 +
@script RequireComponent(AudioSource)
 +
 +
// also helps to automatically link the Audio Listener
 +
@script ExecuteInEditMode()
 +
 +
var audioSource : AudioSource;
 +
var audioListener : Transform;
 +
var volume : float = 1;
 +
var minVolume : float = 0;
 +
var maxVolume : float = 1;
 +
var rolloffFactor : float = 1;
 +
var rolloffThreshold : float = 1;
 +
var ignoreDistance = false;
 +
 +
private var loudness : float;
 +
private var minLoudness;
 +
private var maxLoudness;
 +
private var loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2);
 +
 +
function Volume ()
 +
{return loudness;}
 +
 +
function Volume (value)
 +
{
 +
// volume values outside 0-1 mean nothing in Unity
 +
volume = Mathf.Clamp01(value);
 +
 +
loudness = Mathf.Pow(volume, loudnessExponent);
 +
if (audioSource && ignoreDistance)
 +
audioSource.volume = Mathf.Clamp(loudness, minLoudness, maxLoudness);
 +
}
 +
 +
function MinVolume ()
 +
{return minLoudness;}
 +
 +
function MinVolume (value)
 +
{
 +
// volume values less than 0 mean nothing in Unity
 +
// ensure minVolume is not greater than maxVolume;
 +
minVolume = Mathf.Clamp(value, 0, maxVolume);
 +
 +
minLoudness = Mathf.Pow(minVolume, loudnessExponent);
 +
}
 +
 +
function MaxVolume ()
 +
{return maxLoudness;}
 +
 +
function MaxVolume (value)
 +
{
 +
// ensure maxVolume is not less than minVolume;
 +
// volume values greater than 1 mean nothing in Unity
 +
maxVolume = Mathf.Clamp(value, minVolume, 1);
 +
 +
maxLoudness = Mathf.Pow(maxVolume, loudnessExponent);
 +
}
 +
 +
private var rolloffExponent;
 +
 +
function RolloffFactor ()
 +
{return rolloffExponent;}
 +
 +
function RolloffFactor (value)
 +
{
 +
// Negative values don't make sense for this
 +
rolloffFactor = Mathf.Max(value, 0);
 +
 +
rolloffExponent = Mathf.Log(.5, (1 / rolloffFactor + 1));
 +
}
 +
 +
// no need for a "getter"; use rolloffThreshold directly
 +
function RolloffThreshold (value)
 +
{
 +
// Negative values don't make sense for this
 +
rolloffThreshold = Mathf.Max(value, 0);
 +
}
 +
 +
var thisTransform : Transform;
 +
 +
function Start()
 +
{
 +
// If there is only one Audio Source attached to this game object,
 +
// and there are no other instances of this script attached,
 +
// automatically link this script to the Audio Source.
 +
if (GetComponents(AudioSource).Length < 2 &&
 +
GetComponents(typeof this).Length < 2)
 +
audioSource = audio;
 +
 +
if (!audioListener)
 +
{
 +
var listenerComponent : Component = FindObjectOfType(AudioListener);
 +
if (listenerComponent)
 +
audioListener = listenerComponent.gameObject.transform;
 +
}
 +
 +
// These properties are not useful;
 +
// initializing them this way keeps this script as tidy as possible.
 +
if (audioSource)
 +
{
 +
audioSource.minVolume = 0;
 +
audioSource.maxVolume = 1;
 +
audioSource.rolloffFactor = 0;
 +
}
 +
 +
thisTransform = transform;
 +
 +
Volume(volume);
 +
MinVolume(minVolume);
 +
MaxVolume(maxVolume);
 +
RolloffFactor(rolloffFactor);
 +
 +
// Change values in the Editor (during Play Mode); get results.
 +
if (Application.isEditor & Application.isPlaying)
 +
StartCoroutine("RefreshProperties");
 +
}
 +
 +
// Using OnDrawGizmos() would be a performance hit
 +
// in the Editor, given several properties to update.
 +
function RefreshProperties ()
 +
{
 +
while (true)
 +
{
 +
Volume(volume);
 +
yield;
 +
MinVolume(minVolume);
 +
yield;
 +
MaxVolume(maxVolume);
 +
yield;
 +
RolloffFactor(rolloffFactor);
 +
yield;
 +
}
 +
}
 +
 +
function Update ()
 +
{
 +
if (Application.isPlaying && audioSource && audioListener && (ignoreDistance == false))
 +
{
 +
var distanceToListener = Vector3.Distance(thisTransform.position, audioListener.position);
 +
var rolloffBase = distanceToListener / rolloffThreshold;
 +
var positionalVolume = Mathf.Pow(rolloffBase, rolloffExponent) * loudness;
 +
audioSource.volume = Mathf.Clamp(positionalVolume, minLoudness, maxLoudness);
 +
}
 +
}</javascript>
 +
 +
 +
==C# Instructions==
 +
Use the following variable declaration in an external script, and drag the Game Object containing the Audio (script) component onto the '''Audio Script''' variable slot in the Inspector::
 +
 +
<csharp>public Audio audioScript;</csharp>
 +
 +
 +
In that script, instead of assigning the values of the '''volume''', '''minVolume''', '''maxVolume''', and '''rolloffFactor''' parameters directly, use the following properties.  (Note the uppercase first letter.)
 +
 +
''audioScript.Volume''
 +
 +
''audioScript.MinVolume''
 +
 +
''audioScript.MaxVolume''
 +
 +
''audioScript.RolloffFactor''
 +
 +
 +
Advanced users can also access the resulting values of what the '''volume''', '''minVolume''', '''maxVolume''', and '''rolloffFactor''' parameters are used for, via those properties.
 +
 +
'''''audioScript.audioSource''''', '''''audioScript.audioListener''''', '''''audioScript.RolloffThreshold''''', and '''''audioScript.ignoreDistance''''' should be read and written to directly.
 +
 +
 +
== C# - Audio.cs==
 +
<csharp>using UnityEngine;
 +
using System.Collections;
 +
 +
// helps to automatically link the first attached instance of this script
 +
// to an Audio Source, if no Audio Sources were present
 +
[RequireComponent (typeof(AudioSource))]
 +
 +
// also helps to automatically link the Audio Listener
 +
[ExecuteInEditMode()]
 +
 +
public class Audio : MonoBehaviour
 +
{
 +
public AudioSource audioSource;
 +
public Transform audioListener;
 +
public float volume = 1;
 +
public float minVolume = 0;
 +
public float maxVolume = 1;
 +
public float rolloffFactor = 1;
 +
public float rolloffThreshold = 1;
 +
public bool ignoreDistance = false;
 +
 +
float loudness;
 +
float minLoudness;
 +
float maxLoudness;
 +
float loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2);
 +
 +
public float Volume
 +
{
 +
get
 +
{return loudness;}
 +
set
 +
{
 +
// volume values outside 0-1 mean nothing in Unity
 +
volume = Mathf.Clamp01(value);
 +
 +
loudness = Mathf.Pow(volume, loudnessExponent);
 +
if (audioSource && ignoreDistance)
 +
audioSource.volume = Mathf.Clamp(loudness, minLoudness, maxLoudness);
 +
}
 +
}
 +
 +
public float MinVolume
 +
{
 +
get
 +
{return minLoudness;}
 +
set
 +
{
 +
// volume values less than 0 mean nothing in Unity
 +
// ensure minVolume is not greater than maxVolume;
 +
minVolume = Mathf.Clamp(value, 0, maxVolume);
 +
 +
minLoudness = Mathf.Pow(minVolume, loudnessExponent);
 +
}
 +
}
 +
 +
public float MaxVolume
 +
{
 +
get
 +
{return maxLoudness;}
 +
set
 +
{
 +
// ensure maxVolume is not less than minVolume;
 +
// volume values greater than 1 mean nothing in Unity
 +
maxVolume = Mathf.Clamp(value, minVolume, 1);
 +
 +
maxLoudness = Mathf.Pow(maxVolume, loudnessExponent);
 +
}
 +
}
 +
 +
float rolloffExponent;
 +
 +
public float RolloffFactor
 +
{
 +
get
 +
{return rolloffExponent;}
 +
set
 +
{
 +
// Negative values don't make sense for this
 +
rolloffFactor = Mathf.Max(value, 0);
 +
 +
rolloffExponent = Mathf.Log(.5f, (1 / rolloffFactor + 1));
 +
}
 +
}
 +
 +
public float RolloffThreshold
 +
{
 +
// no need for a getter; use rolloffThreshold directly
 +
 +
set
 +
{
 +
// Negative values don't make sense for this
 +
rolloffThreshold = Mathf.Max(value, 0);
 +
}
 +
}
 +
 +
Transform thisTransform;
 +
 +
void Start()
 +
{
 +
// If there is only one Audio Source attached to this game object,
 +
// and there are no other instances of this script attached,
 +
// automatically link this script to the Audio Source.
 +
if (GetComponents(typeof(AudioSource)).Length < 2 &&
 +
GetComponents(this.GetType()).Length < 2)
 +
audioSource = audio;
 +
 +
if (!audioListener)
 +
{
 +
Component listenerComponent = FindObjectOfType(typeof(AudioListener)) as Component;
 +
if (listenerComponent)
 +
audioListener = listenerComponent.gameObject.transform;
 +
}
 +
 +
// These properties are not useful;
 +
// initializing them this way keeps this script as tidy as possible.
 +
if (audioSource)
 +
{
 +
audioSource.minVolume = 0;
 +
audioSource.maxVolume = 1;
 +
audioSource.rolloffFactor = 0;
 +
}
 +
 +
thisTransform = transform;
 +
 +
Volume = volume;
 +
MinVolume = minVolume;
 +
MaxVolume = maxVolume;
 +
RolloffFactor = rolloffFactor;
 +
 +
// Change values in the Editor (during Play Mode); get results.
 +
if (Application.isEditor & Application.isPlaying)
 +
StartCoroutine("RefreshProperties");
 +
}
 +
 +
// Using OnDrawGizmos() would be a performance hit
 +
// in the Editor, given several properties to update.
 +
IEnumerator RefreshProperties ()
 +
{
 +
while (true)
 +
{
 +
Volume = volume;
 +
yield return 0;
 +
MinVolume = minVolume;
 +
yield return 0;
 +
MaxVolume = maxVolume;
 +
yield return 0;
 +
RolloffFactor = rolloffFactor;
 +
        yield return 0;
 +
}
 +
    }
 +
 +
void Update ()
 +
{
 +
if (Application.isPlaying && audioSource && audioListener && (ignoreDistance == false))
 +
{
 +
float distanceToListener = Vector3.Distance(thisTransform.position, audioListener.position);
 +
float rolloffBase = distanceToListener / rolloffThreshold;
 +
float positionalVolume = Mathf.Pow(rolloffBase, rolloffExponent) * loudness;
 +
audioSource.volume = Mathf.Clamp(positionalVolume, minLoudness, maxLoudness);
 +
}
 +
}
 +
}</csharp >
 +
 +
 +
==Why I find it necessary to use this==
 +
Tweaking the controls for Audio Sources in Unity is not as predictable as it could be.  Here are the rogue properties of Audio Sources, with their descriptions as provided by [http://unity3d.com/support/documentation/Components/class-AudioSource.html the Unity Reference Manual], and descriptions as they have actually behaved in my tests.
 +
 +
(To be clear, volume is a multiplier for audio samples, which directly correlate with how far your speaker drivers (tweeters, woofers, etc.) are displaced from their resting position during playback.  volume = 0 means that your speakers won't be displaced at all.  Simplifying a bit, volume = 1 means that the audio will play back as loud as it was recorded, and fractional values will play the audio back as if it were recorded at a lower level.  As samples get played back over time, waveforms are recreated, so saying that volume is a multiplier for amplitude is accurate enough that I will be using the term "amplitude" to mean 'distance from zero', later on this page.)
 +
 +
 +
'''''Play On Awake:'''''  ''If enabled, the sound will start playing the moment the scene launches. If disabled, you need to start it using the Play() command from scripting.''
 +
 +
It actually means "Play On Enable".  Yes, the sound will start playing the moment the scene launches, but it will also start playing if the Audio Source is disabled, and then enabled again, any time after the scene launches.  I'm documenting this here, for the sake of completeness, but I am not providing a fix for this, because I don't think this is a problem, other than being incorrectly named and documented.
 +
 +
 +
'''''Volume:'''''  ''How loud the sound is at a distance of 1 world unit (1 meter) from the Audio Listener.''
 +
 +
This is only true in the Audio Listener's YZ plane.  A sound traveling along the Audio Listener's X is 3 dB louder than it should be, according to this description, and it only plays through one speaker, at least in my two-speaker environment.  Obviously, this is due to the 3D positional audio algorithm, but the description of the property is not precise, and the algorithm is highly unrealistic along the Audio Listener's X axis.  (Fortunately, it gets better if more axes are involved.) 
 +
 +
To avoid distortion when within 1 world unit of the Audio Listener, along the X axis, it seems that all mono clips imported into Unity are reduced in level by 3 dB.  The Unity 2.5 Audio Importer's "Audio Channels" box also assures that no clips that are converted from stereo to mono have any peaks above -3 dB.  Unfortunately, although this is apparently not the case for everyone, on my system, Unity actually clips all samples above -3 dB to exactly -3 dB, which causes distortion for clips with loud peaks.  (An appropriate solution would be to multiply all samples by ''10^(-3/20)'', if the 3 dB boost along the Audio Listener's X axis can not be avoided.)
 +
 +
Also, while AudioSource.volume can accept values between 0 and infinity, values above 1 do the same thing as 1.  That is to say, an Audio Clip will never play back louder than it was recorded.  Boosting the level of audio clips can only be done outside of Unity, at least for now.
 +
 +
A further problem with the volume control is that it uses a "linear taper", which does not correspond with human hearing.  For example, if volume is 0.5, instead of sounding half as loud as 1, it sounds about 2/3 as loud.  If volume is 0.1, instead of sounding 1/10 as loud as 1, it sounds about 1/4 as loud.
 +
 +
 +
 +
'''''Min Volume:'''  The minimum value of the sound. No matter how far away you get, the sound will not get softer than this value.''
 +
 +
'''''Max Volume:'''  How loud the sound gets at the loudest. No matter how close you get, the sound will never get louder than this value.''
 +
 +
These variables actually have nothing to do with distance.  Instead, they are just clamps for  AudioSource.volume.  The following odd behavior ensues,  if Min Volume is greater than Max Volume:
 +
 +
 +
''Unity iPhone:''
 +
 +
If  Volume is less than Min Volume, then Volume behaves as if it were set to Min Volume.
 +
If  Volume is greater than or equal to Min Volume, then Volume behaves as if it were set to Max Volume.
 +
 +
 +
''Unity 2.5:''
 +
 +
If  Volume is less than Min Volume, and Volume is less than 1, then Volume behaves as if it were set to Min Volume.
 +
If  Volume is greater than or equal to Min Volume, or greater than or equal to 1, then Volume behaves as if it were set to Max Volume.
 +
 +
 +
Like Volume, although Min Volume and  Max Volume can accept values between 0 and infinity, values above 1 do the same thing as 1.
 +
 +
 +
 +
'''''Rolloff Factor: ''' How fast the sound fades. The higher the value, the closer the Listener has to be before hearing the sound.''
 +
 +
"How fast the sound fades" is a good description, but the "before hearing the sound" part is inaccurate.  A better way to put what Unity is going for is:
 +
"The sound will be as loud as if were 'Rolloff Factor' times as far away as it actually is, from the Audio Listener".  However, that is not really what happens.  The algorithm gets a little wacky, in an effort to balance this idea with the intention of a sound being as loud as AudioSource.volume at a distance of 1 world unit.
 +
 +
Sound has a friendly property:  its measured amplitude decreases directly with distance from its source.  (Take a measurement of amplitude, move n times farther away from the sound source than you already are, and a new measurement will yield 1/n  times the original amplitude.  This isn't true indoors, due to reflection and absorption of sound waves, but this ideal case is pretty accurate in open fields.  Getting realistic indoor sound is not really within the capabilities of Unity's current audio engine.)  So, using the realistic (outdoor) model, we could use the equation ''amplitude = volume/(rolloffFactor * distance)'', and accurately have the sound play back as if it were 'Rolloff Factor' times as far away as it is.  The problem with this model, is that instead of the sound's amplitude being ''volume * loudness of clip''  at a distance of 1 world unit, it is  ''volume * loudness of clip'' at a distance of ''1/rolloffFactor'' world units.  This codependence of properties is not particularly desirable, but unavoidable if adhering to this model.
 +
 +
In an effort to combine these two competing ideals, Unity uses the distance model of [http://forum.unity3d.com/viewtopic.php?t=19455&postdays=0&postorder=asc&start=15 amplitude = volume / (1.0 + rolloffFactor * (distance – 1.0))].  For mono audio clips, if rolloffFactor = 1, then the equation is physically accurate, and if rolloffFactor = 0, then there is some degree of positioning, despite the overall sound level not varying if distance from the Listener is altered.  (See the description of what happens along the Listener's X axis, under 'Volume', above.)  However, no other rolloffFactor values make sense, outside of a heavily mathematical context.
 +
 +
For example, if rolloffFactor = 2,  at a distance of two world units, you would expect the sound to be as loud as it would be at 4 world units, if rolloffFactor were 1.  However, instead of the amplitude being multiplied by 1/4, as desired, the multiplicative factor would be 1/3.  Tweaking rolloffFactor will probably be less intuitive, to anyone, than tweaking a good volume, minVolume, or maxVolume control, so I don't think it's as important to "fix" this property, as it is to fix the others, but I do believe that it can be improved.
 +
 +
==Details of my audio control improvement methods==
 +
 +
'''''Volume:'''''  Although Unity's volume control is a precise multiplier of audio amplitude (from 0 to 1, anyway), the amplitude of a waveform does not correlate directly with human perception of loudness.  Loudness perception is complex, but [http://www.phys.unsw.edu.au/jw/dB.html "experimentally it was found that a 10 dB increase in sound level corresponds approximately to a perceived doubling of loudness."].  Therefore, it makes sense for a volume control to yield an amplitude that is...
 +
 +
 +
exactly what is input, for a value of 1,
 +
 +
10 decibels below the input, for a value of .5,
 +
 +
20 decibels below the input, for a value of .25,
 +
 +
etc. 
 +
 +
 +
Amplitudinal difference, as a multiplicative factor, based on a difference in decibels, can be found with the expression ''10^(dB / 20)''.  Inputting the value of 10 dB results in ''10^(10/20)'', which '''''Mathf.Sqrt(10)''''' in the code represents.
 +
 +
 +
Raising this value to a base 2 logarithm gives exactly the behavior we want for a volume control.  This expression would be ''(10^(1/2))^log[2]volume''.  However, the algorithm will execute faster in the form that I gave in the code, which is ''volume^log[2](10^(1/2))'' (the '''''RefreshLoudness''''' function), due to only having to calculate a logarithm once, at runtime.  Thanks to David Huntrods (dawvee on the Unity forums), for [http://forum.unity3d.com/viewtopic.php?p=144609#144609 proof that ''x^log(y) = y^log(x)'']:
 +
 +
''y = x^log[x]y''.
 +
 +
Therefore, ''x^log(y) = x^log(x^log[x]y)''.
 +
 +
Due to the property ''log[b](x^n) = n * log[b]x''...
 +
 +
''x^log(y) = x^(log[x]y * log(x))''. 
 +
 +
That can be rewritten as ''x^log(y) = (x^log[x]y)^log(x)''.
 +
 +
Again, because ''y = x^log[x]y'', ''x^log(y) = y^log(x)''.
 +
 +
 +
 +
 +
 +
'''''Min Volume''''' and '''''Max Volume:'''''  These properties incorporate the same "human-corrected" calculation that '''Volume''' does.  In addition, they function as described in the manual.  As with Audio Sources, I do use them as clamps for '''Volume''', but only if '''Ignore Distance''' is checked.
 +
 +
 +
* Although Unity restricts Audio Sources' '''Volume''', '''Min Volume''', and '''Max Volume''' properties, and my replacements for them, to a functional range of 0-1, my "skewing" would continue to function properly, above values of 1, if the restriction is ever dropped.  (I use Mathf.Clamp01 in my code, right now, to make clear what is actually happening.  I have always found it confusing for Unity to allow values greater than 1, as they don't reflect reality.)
 +
 +
 +
 +
 +
'''''RolloffFactor''''' and '''''Rolloff Threshold:'''''  Although I actually like what Unity is going for, in terms of its model for RolloffFactor, I definitely want to be able to set the volume of a sound at a certain distance, independent of the RolloffFactor setting, so a different model has to be used.  Mine can be described like this:
 +
 +
''Ideally, a sound becomes quieter by a fixed amount (about 6 decibels), as its distance from a listener is doubled. Using my method, the sound will still become 6 dB quieter at a further distance, but that distance will be 'Rolloff Factor' times closer to any point outside of '''Rolloff Threshold''' than it would be in ideal reality.''
 +
 +
Keep in mind that '''Rolloff Threshold''' can not be zero, as sound measurements must be taken at a certain distance from a source.  This distance can be infinitesimally small, but can not be zero.  Given that AudioSource.volume is a linear amplitude multiplier, my equation is as follows:
 +
 +
''audio.volume = loudness * (distance/ Rolloff Threshold) ^ log[1+ (1 / Rolloff Factor) ](1/2)'',
 +
where ''loudness'' is the result of the volume equation detailed above.
 +
 +
 +
Let's break this down.  Assuming '''''Volume''' = 1'', '''''Rolloff Threshold''' = 1'' (which imitates the behavior of the Audio Source's rolloff model), and '''''Rolloff Factor''' = 1'', then we can simplify the equation to
 +
 +
''audio.volume = (1/2) ^ log[2]distance''.
 +
 +
This can be read as...
 +
 +
''As distance from the Audio Listener is doubled, outside of the range of 1 world unit from the Listener, the amplitude of the audio signal will decrease by half.''
 +
 +
(Halving the amplitude results in a decrease of 20 log(1/2), which is about - 6 dB.)  At a distance of 1, the amplitude is 1.  At 2, the amplitude is 1/2.  If we instead wanted the amplitude to be 1/2, twice as close to 1 as 2 is (1 + (2-1) / 2, a.k.a. 1.5), then we would substitute 1.5 into the logarithm:
 +
 +
''audio.volume = (1/2) ^ log[1.5]distance''
 +
 +
The general case for this is ''audio.volume = (1/2) ^ log[1+ (1 / '''Rolloff Factor''') ]distance''.  However, when ''distance = 1'', then audio.volume will be 1, no matter the Rolloff Factor.  To change it so that ''audio.volume = 1'' at a distance of '''Rolloff Threshold''', then we first divide distance by '''Rolloff Threshold''', before computing the rest of the equation.  This yields...
 +
 +
''audio.volume = (1/2) ^ log[1+ (1 / Rolloff Factor)](distance / Rolloff Threshold)'',
 +
 +
which, when the '''Volume''' property is accounted for, can be modified to the final form seen above, using the property of logs + exponents that was detailed under '''Volume'''.
 +
 +
 +
 +
To elaborate on what I mentioned in the [[Audio#Instructions|Instructions]], '''Rolloff Threshold''' is probably best used to match the overall scale of your game.  '''Rolloff Factor''' can be used to emulate the sonic effects of different environments, in an extremely simplified fashion.  Highly reflective rooms, like empty basements with concrete walls, would be more realistic with lower '''Rolloff Factor''' values.  Higher values would be appropriate in environments with more sound absorption.  An attic filled with fiberglass insulation is an excellent example of such a space.  When '''Rolloff Factor''' is set to 1, "realistic outdoor behavior" will be modeled.  (This is also true of the Audio Source's ''Rolloff Factor''.)
 +
 +
 +
* Be aware that mono clips will exhibit the "+ 3 dB along the X axis" behavior, despite the use of this script.  Unity does not provide access to individual audio channels, so this cannot be overridden, unfortunately.
 +
 +
 +
 +
'''''Ignore Distance:'''''  When unchecked, this does allow the volume of stereo clips to be automatically faded over distance.  However, because the script does not have access to Unity's internal audio smoothing algorithms, which mono clips utilize, you run the risk of introducing "crackling" artifacts into your audio, if you change the position too rapidly.  This is due to samples jumping to arbitrary values, drastically changing the slope of the waveform momentarily.

Revision as of 19:26, 19 October 2009

Author: Jessy

Contents

Description

This is a script that replaces most properties of Audio Sources. I feel that its controls behave more intuitively then those of the Audio Source component itself, and it extends functionality as well. I intend for it to be easy to switch from scripting and tweaking Audio Sources directly, to utilizing this script.

I have also created a simple derivative of this script, to control the volume of the Audio Listener.

General Instructions

Attach this script to the Game Objects that contain Audio Sources. Change the exposed variables in the Editor for immediate results, or use the methods described in the JavaScript or C# sections.

If your Game Object has only one Audio Source, then it will automatically be assigned to this script's Audio Source variable, when the script attached. (If there is no Audio Source present on the Game Object when you attach this script, one will automatically be created, attached, and assigned.) The Audio Listener variable should always be automatically assigned properly, as Unity requires there to be exactly one Audio Listener per scene. If the Audio Source and Audio Listener parameters are not automatically populated to your liking, or you make later changes to your scene setup that requires reassignment, drag the Game Objects containing the appropriate components onto the Audio Source and/or Audio Listener variable slots in the Inspector. You can make assignments programmatically via the audioSource and audioListener variables.

The Volume, Min Volume, Max Volume, and Rolloff Factor parameters perform the tasks that the similarly-named parameters of Audio Sources were intended to perform.

Rolloff Threshold defines a distance from the Audio Listener within which sound will not get quieter over distance. (Unity normally fixes this distance to 1 world unit.) This can be especially useful for dealing with "extreme" scale characters. (Use large values for giant monsters, small values for insects. See the bottom of this page for more tips.)

If Ignore Distance is unchecked, it allows stereo clips to fade in volume over distance (but they do not get positioned in 3D "sound space"). For mono clips, checking this is a more efficient method for achieving the same result as setting Rolloff Factor to zero.


Javascript Instructions

Use the following variable declaration in an external script, and drag the Game Object containing the Audio (script) component onto the Audio Script variable slot in the Inspector:

<javascript>var audioScript : Audio;</javascript>


In that script, use the following methods to assign the volume, minVolume, maxVolume, and rolloffFactor parameters a value of value, instead of assigning a value to any of those parameter directly.

audioScript.Volume(value);

audioScript.MinVolume(value);

audioScript.MaxVolume(value);

audioScript.RolloffFactor(value);


Advanced users can access the resulting values of what the volume, minVolume, maxVolume, and rolloffFactor parameters are used for, via these methods:

audioScript.Volume()

audioScript.MinVolume()

audioScript.MaxVolume()

audioScript.RolloffFactor()


(You may find the way properties are handled via C# to be more intuitive.)

audioScript.audioSource, audioScript.audioListener, audioScript.RolloffThreshold, and audioScript.ignoreDistance should be read and written to directly.


JavaScript - Audio.js

<javascript>// helps to automatically link the first attached instance of this script // to an Audio Source, if no Audio Sources were present @script RequireComponent(AudioSource)

// also helps to automatically link the Audio Listener @script ExecuteInEditMode()

var audioSource : AudioSource; var audioListener : Transform; var volume : float = 1; var minVolume : float = 0; var maxVolume : float = 1; var rolloffFactor : float = 1; var rolloffThreshold : float = 1; var ignoreDistance = false;

private var loudness : float; private var minLoudness; private var maxLoudness; private var loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2);

function Volume () {return loudness;}

function Volume (value) { // volume values outside 0-1 mean nothing in Unity volume = Mathf.Clamp01(value);

loudness = Mathf.Pow(volume, loudnessExponent); if (audioSource && ignoreDistance) audioSource.volume = Mathf.Clamp(loudness, minLoudness, maxLoudness); }

function MinVolume () {return minLoudness;}

function MinVolume (value) { // volume values less than 0 mean nothing in Unity // ensure minVolume is not greater than maxVolume; minVolume = Mathf.Clamp(value, 0, maxVolume);

minLoudness = Mathf.Pow(minVolume, loudnessExponent); }

function MaxVolume () {return maxLoudness;}

function MaxVolume (value) { // ensure maxVolume is not less than minVolume; // volume values greater than 1 mean nothing in Unity maxVolume = Mathf.Clamp(value, minVolume, 1);

maxLoudness = Mathf.Pow(maxVolume, loudnessExponent); }

private var rolloffExponent;

function RolloffFactor () {return rolloffExponent;}

function RolloffFactor (value) { // Negative values don't make sense for this rolloffFactor = Mathf.Max(value, 0);

rolloffExponent = Mathf.Log(.5, (1 / rolloffFactor + 1)); }

// no need for a "getter"; use rolloffThreshold directly function RolloffThreshold (value) { // Negative values don't make sense for this rolloffThreshold = Mathf.Max(value, 0); }

var thisTransform : Transform;

function Start() { // If there is only one Audio Source attached to this game object, // and there are no other instances of this script attached, // automatically link this script to the Audio Source. if (GetComponents(AudioSource).Length < 2 && GetComponents(typeof this).Length < 2) audioSource = audio;

if (!audioListener) { var listenerComponent : Component = FindObjectOfType(AudioListener); if (listenerComponent) audioListener = listenerComponent.gameObject.transform; }

// These properties are not useful; // initializing them this way keeps this script as tidy as possible. if (audioSource) { audioSource.minVolume = 0; audioSource.maxVolume = 1; audioSource.rolloffFactor = 0; }

thisTransform = transform;

Volume(volume); MinVolume(minVolume); MaxVolume(maxVolume); RolloffFactor(rolloffFactor);

// Change values in the Editor (during Play Mode); get results. if (Application.isEditor & Application.isPlaying) StartCoroutine("RefreshProperties"); }

// Using OnDrawGizmos() would be a performance hit // in the Editor, given several properties to update. function RefreshProperties () { while (true) { Volume(volume); yield; MinVolume(minVolume); yield; MaxVolume(maxVolume); yield; RolloffFactor(rolloffFactor); yield; } }

function Update () { if (Application.isPlaying && audioSource && audioListener && (ignoreDistance == false)) { var distanceToListener = Vector3.Distance(thisTransform.position, audioListener.position); var rolloffBase = distanceToListener / rolloffThreshold; var positionalVolume = Mathf.Pow(rolloffBase, rolloffExponent) * loudness; audioSource.volume = Mathf.Clamp(positionalVolume, minLoudness, maxLoudness); } }</javascript>


C# Instructions

Use the following variable declaration in an external script, and drag the Game Object containing the Audio (script) component onto the Audio Script variable slot in the Inspector::

<csharp>public Audio audioScript;</csharp>


In that script, instead of assigning the values of the volume, minVolume, maxVolume, and rolloffFactor parameters directly, use the following properties. (Note the uppercase first letter.)

audioScript.Volume

audioScript.MinVolume

audioScript.MaxVolume

audioScript.RolloffFactor


Advanced users can also access the resulting values of what the volume, minVolume, maxVolume, and rolloffFactor parameters are used for, via those properties.

audioScript.audioSource, audioScript.audioListener, audioScript.RolloffThreshold, and audioScript.ignoreDistance should be read and written to directly.


C# - Audio.cs

<csharp>using UnityEngine; using System.Collections;

// helps to automatically link the first attached instance of this script // to an Audio Source, if no Audio Sources were present [RequireComponent (typeof(AudioSource))]

// also helps to automatically link the Audio Listener [ExecuteInEditMode()]

public class Audio : MonoBehaviour { public AudioSource audioSource; public Transform audioListener; public float volume = 1; public float minVolume = 0; public float maxVolume = 1; public float rolloffFactor = 1; public float rolloffThreshold = 1; public bool ignoreDistance = false;

float loudness; float minLoudness; float maxLoudness; float loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2);

public float Volume { get {return loudness;} set { // volume values outside 0-1 mean nothing in Unity volume = Mathf.Clamp01(value);

loudness = Mathf.Pow(volume, loudnessExponent); if (audioSource && ignoreDistance) audioSource.volume = Mathf.Clamp(loudness, minLoudness, maxLoudness); } }

public float MinVolume { get {return minLoudness;} set { // volume values less than 0 mean nothing in Unity // ensure minVolume is not greater than maxVolume; minVolume = Mathf.Clamp(value, 0, maxVolume);

minLoudness = Mathf.Pow(minVolume, loudnessExponent); } }

public float MaxVolume { get {return maxLoudness;} set { // ensure maxVolume is not less than minVolume; // volume values greater than 1 mean nothing in Unity maxVolume = Mathf.Clamp(value, minVolume, 1);

maxLoudness = Mathf.Pow(maxVolume, loudnessExponent); } }

float rolloffExponent;

public float RolloffFactor { get {return rolloffExponent;} set { // Negative values don't make sense for this rolloffFactor = Mathf.Max(value, 0);

rolloffExponent = Mathf.Log(.5f, (1 / rolloffFactor + 1)); } }

public float RolloffThreshold { // no need for a getter; use rolloffThreshold directly

set { // Negative values don't make sense for this rolloffThreshold = Mathf.Max(value, 0); } }

Transform thisTransform;

void Start() { // If there is only one Audio Source attached to this game object, // and there are no other instances of this script attached, // automatically link this script to the Audio Source. if (GetComponents(typeof(AudioSource)).Length < 2 && GetComponents(this.GetType()).Length < 2) audioSource = audio;

if (!audioListener) { Component listenerComponent = FindObjectOfType(typeof(AudioListener)) as Component; if (listenerComponent) audioListener = listenerComponent.gameObject.transform; }

// These properties are not useful; // initializing them this way keeps this script as tidy as possible. if (audioSource) { audioSource.minVolume = 0; audioSource.maxVolume = 1; audioSource.rolloffFactor = 0; }

thisTransform = transform;

Volume = volume; MinVolume = minVolume; MaxVolume = maxVolume; RolloffFactor = rolloffFactor;

// Change values in the Editor (during Play Mode); get results. if (Application.isEditor & Application.isPlaying) StartCoroutine("RefreshProperties"); }

// Using OnDrawGizmos() would be a performance hit // in the Editor, given several properties to update. IEnumerator RefreshProperties () { while (true) { Volume = volume; yield return 0; MinVolume = minVolume; yield return 0; MaxVolume = maxVolume; yield return 0; RolloffFactor = rolloffFactor; yield return 0; }

   }

void Update () { if (Application.isPlaying && audioSource && audioListener && (ignoreDistance == false)) { float distanceToListener = Vector3.Distance(thisTransform.position, audioListener.position); float rolloffBase = distanceToListener / rolloffThreshold; float positionalVolume = Mathf.Pow(rolloffBase, rolloffExponent) * loudness; audioSource.volume = Mathf.Clamp(positionalVolume, minLoudness, maxLoudness); } } }</csharp >


Why I find it necessary to use this

Tweaking the controls for Audio Sources in Unity is not as predictable as it could be. Here are the rogue properties of Audio Sources, with their descriptions as provided by the Unity Reference Manual, and descriptions as they have actually behaved in my tests.

(To be clear, volume is a multiplier for audio samples, which directly correlate with how far your speaker drivers (tweeters, woofers, etc.) are displaced from their resting position during playback. volume = 0 means that your speakers won't be displaced at all. Simplifying a bit, volume = 1 means that the audio will play back as loud as it was recorded, and fractional values will play the audio back as if it were recorded at a lower level. As samples get played back over time, waveforms are recreated, so saying that volume is a multiplier for amplitude is accurate enough that I will be using the term "amplitude" to mean 'distance from zero', later on this page.)


Play On Awake: If enabled, the sound will start playing the moment the scene launches. If disabled, you need to start it using the Play() command from scripting.

It actually means "Play On Enable". Yes, the sound will start playing the moment the scene launches, but it will also start playing if the Audio Source is disabled, and then enabled again, any time after the scene launches. I'm documenting this here, for the sake of completeness, but I am not providing a fix for this, because I don't think this is a problem, other than being incorrectly named and documented.


Volume: How loud the sound is at a distance of 1 world unit (1 meter) from the Audio Listener.

This is only true in the Audio Listener's YZ plane. A sound traveling along the Audio Listener's X is 3 dB louder than it should be, according to this description, and it only plays through one speaker, at least in my two-speaker environment. Obviously, this is due to the 3D positional audio algorithm, but the description of the property is not precise, and the algorithm is highly unrealistic along the Audio Listener's X axis. (Fortunately, it gets better if more axes are involved.)

To avoid distortion when within 1 world unit of the Audio Listener, along the X axis, it seems that all mono clips imported into Unity are reduced in level by 3 dB. The Unity 2.5 Audio Importer's "Audio Channels" box also assures that no clips that are converted from stereo to mono have any peaks above -3 dB. Unfortunately, although this is apparently not the case for everyone, on my system, Unity actually clips all samples above -3 dB to exactly -3 dB, which causes distortion for clips with loud peaks. (An appropriate solution would be to multiply all samples by 10^(-3/20), if the 3 dB boost along the Audio Listener's X axis can not be avoided.)

Also, while AudioSource.volume can accept values between 0 and infinity, values above 1 do the same thing as 1. That is to say, an Audio Clip will never play back louder than it was recorded. Boosting the level of audio clips can only be done outside of Unity, at least for now.

A further problem with the volume control is that it uses a "linear taper", which does not correspond with human hearing. For example, if volume is 0.5, instead of sounding half as loud as 1, it sounds about 2/3 as loud. If volume is 0.1, instead of sounding 1/10 as loud as 1, it sounds about 1/4 as loud.


Min Volume: The minimum value of the sound. No matter how far away you get, the sound will not get softer than this value.

Max Volume: How loud the sound gets at the loudest. No matter how close you get, the sound will never get louder than this value.

These variables actually have nothing to do with distance. Instead, they are just clamps for AudioSource.volume. The following odd behavior ensues, if Min Volume is greater than Max Volume:


Unity iPhone:

If Volume is less than Min Volume, then Volume behaves as if it were set to Min Volume. If Volume is greater than or equal to Min Volume, then Volume behaves as if it were set to Max Volume.


Unity 2.5:

If Volume is less than Min Volume, and Volume is less than 1, then Volume behaves as if it were set to Min Volume. If Volume is greater than or equal to Min Volume, or greater than or equal to 1, then Volume behaves as if it were set to Max Volume.


Like Volume, although Min Volume and Max Volume can accept values between 0 and infinity, values above 1 do the same thing as 1.


Rolloff Factor: How fast the sound fades. The higher the value, the closer the Listener has to be before hearing the sound.

"How fast the sound fades" is a good description, but the "before hearing the sound" part is inaccurate. A better way to put what Unity is going for is: "The sound will be as loud as if were 'Rolloff Factor' times as far away as it actually is, from the Audio Listener". However, that is not really what happens. The algorithm gets a little wacky, in an effort to balance this idea with the intention of a sound being as loud as AudioSource.volume at a distance of 1 world unit.

Sound has a friendly property: its measured amplitude decreases directly with distance from its source. (Take a measurement of amplitude, move n times farther away from the sound source than you already are, and a new measurement will yield 1/n times the original amplitude. This isn't true indoors, due to reflection and absorption of sound waves, but this ideal case is pretty accurate in open fields. Getting realistic indoor sound is not really within the capabilities of Unity's current audio engine.) So, using the realistic (outdoor) model, we could use the equation amplitude = volume/(rolloffFactor * distance), and accurately have the sound play back as if it were 'Rolloff Factor' times as far away as it is. The problem with this model, is that instead of the sound's amplitude being volume * loudness of clip at a distance of 1 world unit, it is volume * loudness of clip at a distance of 1/rolloffFactor world units. This codependence of properties is not particularly desirable, but unavoidable if adhering to this model.

In an effort to combine these two competing ideals, Unity uses the distance model of amplitude = volume / (1.0 + rolloffFactor * (distance – 1.0)). For mono audio clips, if rolloffFactor = 1, then the equation is physically accurate, and if rolloffFactor = 0, then there is some degree of positioning, despite the overall sound level not varying if distance from the Listener is altered. (See the description of what happens along the Listener's X axis, under 'Volume', above.) However, no other rolloffFactor values make sense, outside of a heavily mathematical context.

For example, if rolloffFactor = 2, at a distance of two world units, you would expect the sound to be as loud as it would be at 4 world units, if rolloffFactor were 1. However, instead of the amplitude being multiplied by 1/4, as desired, the multiplicative factor would be 1/3. Tweaking rolloffFactor will probably be less intuitive, to anyone, than tweaking a good volume, minVolume, or maxVolume control, so I don't think it's as important to "fix" this property, as it is to fix the others, but I do believe that it can be improved.

Details of my audio control improvement methods

Volume: Although Unity's volume control is a precise multiplier of audio amplitude (from 0 to 1, anyway), the amplitude of a waveform does not correlate directly with human perception of loudness. Loudness perception is complex, but "experimentally it was found that a 10 dB increase in sound level corresponds approximately to a perceived doubling of loudness.". Therefore, it makes sense for a volume control to yield an amplitude that is...


exactly what is input, for a value of 1,

10 decibels below the input, for a value of .5,

20 decibels below the input, for a value of .25,

etc.


Amplitudinal difference, as a multiplicative factor, based on a difference in decibels, can be found with the expression 10^(dB / 20). Inputting the value of 10 dB results in 10^(10/20), which Mathf.Sqrt(10) in the code represents.


Raising this value to a base 2 logarithm gives exactly the behavior we want for a volume control. This expression would be (10^(1/2))^log[2]volume. However, the algorithm will execute faster in the form that I gave in the code, which is volume^log[2](10^(1/2)) (the RefreshLoudness function), due to only having to calculate a logarithm once, at runtime. Thanks to David Huntrods (dawvee on the Unity forums), for proof that x^log(y) = y^log(x):

y = x^log[x]y.

Therefore, x^log(y) = x^log(x^log[x]y).

Due to the property log[b](x^n) = n * log[b]x...

x^log(y) = x^(log[x]y * log(x)).

That can be rewritten as x^log(y) = (x^log[x]y)^log(x).

Again, because y = x^log[x]y, x^log(y) = y^log(x).



Min Volume and Max Volume: These properties incorporate the same "human-corrected" calculation that Volume does. In addition, they function as described in the manual. As with Audio Sources, I do use them as clamps for Volume, but only if Ignore Distance is checked.


  • Although Unity restricts Audio Sources' Volume, Min Volume, and Max Volume properties, and my replacements for them, to a functional range of 0-1, my "skewing" would continue to function properly, above values of 1, if the restriction is ever dropped. (I use Mathf.Clamp01 in my code, right now, to make clear what is actually happening. I have always found it confusing for Unity to allow values greater than 1, as they don't reflect reality.)



RolloffFactor and Rolloff Threshold: Although I actually like what Unity is going for, in terms of its model for RolloffFactor, I definitely want to be able to set the volume of a sound at a certain distance, independent of the RolloffFactor setting, so a different model has to be used. Mine can be described like this:

Ideally, a sound becomes quieter by a fixed amount (about 6 decibels), as its distance from a listener is doubled. Using my method, the sound will still become 6 dB quieter at a further distance, but that distance will be 'Rolloff Factor' times closer to any point outside of Rolloff Threshold than it would be in ideal reality.

Keep in mind that Rolloff Threshold can not be zero, as sound measurements must be taken at a certain distance from a source. This distance can be infinitesimally small, but can not be zero. Given that AudioSource.volume is a linear amplitude multiplier, my equation is as follows:

audio.volume = loudness * (distance/ Rolloff Threshold) ^ log[1+ (1 / Rolloff Factor) ](1/2), where loudness is the result of the volume equation detailed above.


Let's break this down. Assuming Volume = 1, Rolloff Threshold = 1 (which imitates the behavior of the Audio Source's rolloff model), and Rolloff Factor = 1, then we can simplify the equation to

audio.volume = (1/2) ^ log[2]distance.

This can be read as...

As distance from the Audio Listener is doubled, outside of the range of 1 world unit from the Listener, the amplitude of the audio signal will decrease by half.

(Halving the amplitude results in a decrease of 20 log(1/2), which is about - 6 dB.) At a distance of 1, the amplitude is 1. At 2, the amplitude is 1/2. If we instead wanted the amplitude to be 1/2, twice as close to 1 as 2 is (1 + (2-1) / 2, a.k.a. 1.5), then we would substitute 1.5 into the logarithm:

audio.volume = (1/2) ^ log[1.5]distance

The general case for this is audio.volume = (1/2) ^ log[1+ (1 / Rolloff Factor) ]distance. However, when distance = 1, then audio.volume will be 1, no matter the Rolloff Factor. To change it so that audio.volume = 1 at a distance of Rolloff Threshold, then we first divide distance by Rolloff Threshold, before computing the rest of the equation. This yields...

audio.volume = (1/2) ^ log[1+ (1 / Rolloff Factor)](distance / Rolloff Threshold),

which, when the Volume property is accounted for, can be modified to the final form seen above, using the property of logs + exponents that was detailed under Volume.


To elaborate on what I mentioned in the Instructions, Rolloff Threshold is probably best used to match the overall scale of your game. Rolloff Factor can be used to emulate the sonic effects of different environments, in an extremely simplified fashion. Highly reflective rooms, like empty basements with concrete walls, would be more realistic with lower Rolloff Factor values. Higher values would be appropriate in environments with more sound absorption. An attic filled with fiberglass insulation is an excellent example of such a space. When Rolloff Factor is set to 1, "realistic outdoor behavior" will be modeled. (This is also true of the Audio Source's Rolloff Factor.)


  • Be aware that mono clips will exhibit the "+ 3 dB along the X axis" behavior, despite the use of this script. Unity does not provide access to individual audio channels, so this cannot be overridden, unfortunately.


Ignore Distance: When unchecked, this does allow the volume of stereo clips to be automatically faded over distance. However, because the script does not have access to Unity's internal audio smoothing algorithms, which mono clips utilize, you run the risk of introducing "crackling" artifacts into your audio, if you change the position too rapidly. This is due to samples jumping to arbitrary values, drastically changing the slope of the waveform momentarily.

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox