When you try to map between a linear multiplier (0.0 to 1.0) and a "curve" value, which is exponential, you may be tempted to use exp(x), because it goes between linear and exponential. However, that's not good enough.

You probably want exp(a*x+b)+c. The reason is that exp() won't quite go down to 0 no matter what the input, and it's probably more convenient to work in the range exp([1,log(2)]) and subtract one. Set

a = (log(2)-1);

b = 1;

c = -1;

x = your-input-value-in-the-range-[0,1]

actualValueA = exp(a*x+b)+c;

This results in an exponential response in the range [0,1] from the range [0,1].

Another way to get a "curve" response is to raise the input to some power, say 2. That would mean:

actualValueB = x*x;

It serves the same purpose of giving more resolution towards the bottom end, without all the complication :-)

You also probably want the inverse values, so that getParameter() can get back a useful value (unless you just cache the input values):

invActualValueA = (log(actualValueA-c)-b)/a;

invActualValueB = sqrtf( actualValueB );

Another useful response function is the "dB" one with a special case for 0. You map some range of dB; say, (-96,0] to the range (0,1], and treat 0 special as "minus infinity". The functions then look like:

dBFromValue = value ? value*96-96 : -INFINITY;

gainFromDb = db == -INFINITY ? 0 : pow( 10., db/20. );

valueFromDb = db == -INFINITY ? 0 : (db+96)/96;

dbFromGain = gain ? log10( gain ) * 20 : -INFINITY;