No doubt we've all at some point coded volume control as...
Code: Select all
output = input * volume
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 )
Code: Select all
output = input * 0.001 * exp( volume * 6.908 )
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
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
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