Loudness

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(JavaScript - Loudness.js)
m (Instructions (C# only*))
 
(43 intermediate revisions by 4 users not shown)
Line 4: Line 4:
 
==Description==
 
==Description==
  
Unity's standard volume control uses a "linear taper", and humans hear on a roughly exponential scale"Loudness", unlike the Audio Source's "Volume", will yield perceptually equivalent loudness changes for equivalent value changes.  (Changing the Loudness from 0.2 to 0.3 will yield a similar difference in loudness between 0.7 to 0.8, etc.)
+
Unity's [http://unity3d.com/support/documentation/ScriptReference/AudioSource-volume.html AudioSource.volume] and [http://unity3d.com/support/documentation/ScriptReference/AudioListener-volume.html AudioListener.volume] use what is known as a [http://www.angelfire.com/electronic/funwithtubes/Amp-Volume.html linear taper]Although that is ideal for performance, it means that the 0-1 values that those properties utilize do not match up well with human perception, with loud values taking up a disproportionate amount of the range. This script is designed to make working with loudness more intuitive.
  
== JavaScript - Loudness.js ==
+
Loudness is a complex phenomenon, and this simple script does not, for instance, take [http://en.wikipedia.org/wiki/Equal-loudness_contours equal-loudness contours] into account, but it should yield better results than a linear taper in every real-world case.  I've found the result described [http://www.animations.physics.unsw.edu.au/jw/dB.htm here, that "a 10 dB increase in sound level corresponds approximately to a perceived doubling of loudness"], leads the way to a highly usable loudness control.
<javascript>
+
var loudness : float = 1;
+
private var sqrtOf10 = Mathf.Sqrt(10);
+
  
// I would not leave this in Update() for a release. 
+
==Instructions (C# only*)==
// Put it wherever you need it, to change the volume in-game.
+
  
function Update ()
+
Add this script to your project, wherever you like. It's a static class, so you neither need nor have the ability to attach it to a Game Object.
{
+
audio.volume = (Mathf.Pow(sqrtOf10, Mathf.Log(loudness, 2)));
+
}
+
</javascript>
+
  
== C# - Loudness.cs ==
+
 
<csharp>
+
Loudness.OfListener (which alters AudioListener.volume) is a [http://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx property], so you can assign a 0-1 value to it, or get one back, using the equals sign.
using UnityEngine;
+
<syntaxhighlight lang="csharp">Loudness.OfListener = .5F;  // Half as loud as it can get</syntaxhighlight>
using System.Collections;
+
 
+
 
public class Loudness : MonoBehaviour
+
Extension properties do not exist in C# yet, so for instances of Audio Sources, you have to use separate get and set methods.
 +
<syntaxhighlight lang="csharp">audio.SetLoudness(.5F);  // Affects the AudioSource attached to this Game Object
 +
someAudioSource.GetLoudness(); // gives you a better idea of the portion of maximum loudness than someAudioSource.volume</syntaxhighlight>
 +
 
 +
 
 +
*A UnityScript alternative would have to be more verbose, due to lack of properties and extension methods in that language (at present), but feel free to add a JS solution to this page.  ;-)
 +
 
 +
==Loudness.cs==
 +
<syntaxhighlight lang="csharp">using UnityEngine;
 +
 
 +
public static class Loudness  
 
{
 
{
public float loudness = 1;
+
// A 20 dB increase sounds about 4x louder.
const float oneNinth = (float) (1.0 / 9.0);
+
// A signal needs an amplitude that is 10^(dB/20) greater,
+
// to be increased by 'dB' decibels.
void Update ()  
+
class Exponents
 +
{
 +
public static readonly float Set = Mathf.Log(10, 4);
 +
public static readonly float Get = 1 / Set;
 +
}
 +
 
 +
public static float GetLoudness(this AudioSource audioSource)  
 +
{
 +
return Mathf.Pow(audioSource.volume, Exponents.Get);
 +
}
 +
 
 +
public static float SetLoudness(this AudioSource audioSource, float value)  
 +
{
 +
return audioSource.volume = Mathf.Pow(Mathf.Clamp01(value), Exponents.Set);
 +
}
 +
 
 +
public static float OfListener
 
{
 
{
audio.volume = oneNinth * (Mathf.Pow(10, loudness) - 1);
+
get
 +
{
 +
return Mathf.Pow(AudioListener.volume, Exponents.Get);
 +
}
 +
set
 +
{
 +
AudioListener.volume = Mathf.Pow(Mathf.Clamp01(value), Exponents.Set);
 +
}
 
}
 
}
}
+
}</syntaxhighlight>
</csharp>
+

Latest revision as of 01:23, 29 October 2013

Author: Jessy

[edit] Description

Unity's AudioSource.volume and AudioListener.volume use what is known as a linear taper. Although that is ideal for performance, it means that the 0-1 values that those properties utilize do not match up well with human perception, with loud values taking up a disproportionate amount of the range. This script is designed to make working with loudness more intuitive.

Loudness is a complex phenomenon, and this simple script does not, for instance, take equal-loudness contours into account, but it should yield better results than a linear taper in every real-world case. I've found the result described here, that "a 10 dB increase in sound level corresponds approximately to a perceived doubling of loudness", leads the way to a highly usable loudness control.

[edit] Instructions (C# only*)

Add this script to your project, wherever you like. It's a static class, so you neither need nor have the ability to attach it to a Game Object.


Loudness.OfListener (which alters AudioListener.volume) is a property, so you can assign a 0-1 value to it, or get one back, using the equals sign.

Loudness.OfListener = .5F;  // Half as loud as it can get


Extension properties do not exist in C# yet, so for instances of Audio Sources, you have to use separate get and set methods.

audio.SetLoudness(.5F);  // Affects the AudioSource attached to this Game Object
someAudioSource.GetLoudness(); // gives you a better idea of the portion of maximum loudness than someAudioSource.volume


  • A UnityScript alternative would have to be more verbose, due to lack of properties and extension methods in that language (at present), but feel free to add a JS solution to this page.  ;-)

[edit] Loudness.cs

using UnityEngine;
 
public static class Loudness 
{
	// A 20 dB increase sounds about 4x louder.
	// A signal needs an amplitude that is 10^(dB/20) greater, 
	// to be increased by 'dB' decibels.
	class Exponents 
	{
		public static readonly float Set = Mathf.Log(10, 4);
		public static readonly float Get = 1 / Set;
	}
 
	public static float GetLoudness(this AudioSource audioSource) 
	{
		return Mathf.Pow(audioSource.volume, Exponents.Get);
	}
 
	public static float SetLoudness(this AudioSource audioSource, float value) 
	{
		return audioSource.volume = Mathf.Pow(Mathf.Clamp01(value), Exponents.Set);
	}
 
	public static float OfListener 
	{
		get 
		{
			return Mathf.Pow(AudioListener.volume, Exponents.Get);
		}
		set 
		{
			AudioListener.volume = Mathf.Pow(Mathf.Clamp01(value), Exponents.Set);
		}
	}
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox