Volume law

Post Reply
ColinP
Posts: 1000
Joined: Mon Aug 03, 2020 7:46 pm

Volume law

Post by ColinP »

Having looked at Pan Law I thought I'd share my recent thoughts on Volume Law.

No doubt we've all at some point coded volume control as...

Code: Select all

output = input * volume
...where volume is a double between 0 and 1.

This obviously works but doesn't take into account how we perceive loudness.

Rather than linear gain we could use an equation in the form...

Code: Select all

output = input * a * exp( volume * b )
For a 60 dB dynamic range this becomes...

Code: Select all

output = input * 0.001 * exp( volume * 6.908 )
Here's a comparison between the linear and exponential curves...

volumeLaw1.png
volumeLaw1.png (37.92 KiB) Viewed 1717 times

As you can see there's a huge difference. In practice this means that the top half of the linear volume control has very little impact on the perceived volume.

But exponential curves are asymptotic, so a volume of zero still lets through a tiny unwanted amount of signal.

One way around this is to smoothly switch over to a linear response below 10% volume using code like this...

Code: Select all

if( volume > 0.1 )
	output = input * 0.001 * Math.exp( volume * 6.908 )
else
	output = input * volume * 0.019953
The transition is shown in close-up below...

volumeLaw2.png
volumeLaw2.png (30.15 KiB) Viewed 1717 times

I scaled the graphic too small but hopefully you can see how the green line neatly takes us down to minus infinity dB at zero volume.

However, there's a reasonable approximation that's far cheaper and automatically goes to zero and that's to use the sxith power of the volume...

Code: Select all

output = input * volume ^ 6
Here are the two basic curves for comparison...

volumeLaw3.png
volumeLaw3.png (33.9 KiB) Viewed 1717 times

The sixth power isn't perfect but it's pretty good and can be coded using just four multiplications as follows...

Code: Select all

double t = volume * volume * volume;
output = input * t * t
If you are doing volume control just at UI speed then the method involving a comparison, potential branch, two multiplications and Math.exp() or pow( e, x ) isn't going to be a worry, but if you need to code exponential VCA's the x^6 approximation might be a winner.
ColinP
Posts: 1000
Joined: Mon Aug 03, 2020 7:46 pm

Re: Volume law

Post by ColinP »

I've been doing some real-world testing on this and I now think that the x^6 approximation is a poor choice. In most listening situations it produces a curve that is way too quiet at low volume settings.

My conclusion is that...

Code: Select all

if( volume > 0.1 )
	output = input * 0.001 * Math.exp( volume * 6.908 )
else
	output = input * volume * 0.019953
...is the best code for situations where you want good control over quiet signals when monitoring at fairly high levels in a low-noise environment.

For more everday situations lowering the nominal dynamic range from 60 dB to 50 dB might be a sensible option, so the following code might be the best all-rounder...

Code: Select all

if( volume > 0.1 )
	output = input * 0.00312623 * Math.exp( volume * 5.757 )
else
	output = input * volume * 0.05623755;
Reasonable fast approximations are x^4 or x^3.

If you just want a fast and dirty volume control that's much better than linear then the I'd recommend the following...

Code: Select all

	output = input * volume * volume * volume;
As before this is for volume in the range [0, 1].
Post Reply

Return to “Module Designer”