Loudness

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Why this works)
m (Instructions (C# only*))
 
(38 intermediate revisions by 4 users not shown)
Line 4: Line 4:
 
==Description==
 
==Description==
  
Unity's standard volume control uses a "linear taper", which does not correspond with human hearing.  "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 rangeThis 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.
 +
 
 +
 
 +
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.
 +
<syntaxhighlight lang="csharp">Loudness.OfListener = .5F;  // Half as loud as it can get</syntaxhighlight>
 +
 
 +
 
 +
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
 
{
 
{
audio.volume = Mathf.Pow(sqrtOf10, Mathf.Log(loudness, 2));
+
// A 20 dB increase sounds about 4x louder.
}
+
// A signal needs an amplitude that is 10^(dB/20) greater,
</javascript>
+
// 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);
 +
}
  
==Why this works==
+
public static float OfListener
Coming shortly!
+
{
<math>abc</math>
+
get
 +
{
 +
return Mathf.Pow(AudioListener.volume, Exponents.Get);
 +
}
 +
set
 +
{
 +
AudioListener.volume = Mathf.Pow(Mathf.Clamp01(value), Exponents.Set);
 +
}
 +
}
 +
}</syntaxhighlight>

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