[Ardour-Dev] gain-mapping - was Re: OSC next

Robin Gareus robin at gareus.org
Sat May 14 05:40:44 PDT 2016

On 05/13/2016 08:53 PM, Len Ovens wrote:
> On Fri, 13 May 2016, Melanie Bernkopf wrote:
>> yes I can only give a full ack to this it is just mimic of the
>> position and not about gain or DB.

At first thought, I think this is not a good idea.

It would limit the control surface to the same fader-deflection which
Ardour chose and does not expose any actual relevant numerics.

But the lack of a well defined "no gain" 0dB point is the most obvious flaw.

Internally Ardour uses a floating point gain-factor (coefficient) for
both: state and processing. Resetting a fader sets it exactly to 1.f and
the control has a detent (in the GUI) because it is impossible to
otherwise reach this point (With integer ratios 41 bits of precision are
required for the power law to result in exactly 1.f).

> Yes and no. With either gain or dB I can remotely say I want x amount of
> gain. It is easy to put a button in that zeros a fader with either dB
> (send 0) or gain (send 1.0). It is impossible to do that with 1023 INT.
> 800 comes closest at 0.006990539841353893 dB. (Using two surfaces one
> with int1024 and the other with dB, setting position to 799, 800 or 801
> and seeing what Ardour sends to the other surface)

+1 for testing the whole system. That's very good practice and pretty
much the simplest way to find out how rounding (and float
parsing/precision) behaves.

Here's the math for completeness:

With fader position 0 <= p <= 1.0, Ardour calculates the gain as follows:

  $g = 2^{\frac{1}{6}(-192 + 198 \sqrt[8]{p})}$ [1]

The inverse of which is

  $p = (\frac{1}{198} (6 \log_2(g) + 192))^8$ [2]

At unity gain, [2] evaluates to (192/198)^8 = (32/33)^8

You'll need to add a factor much much larger factor than 1024 to
represent unity gain with an exact integer.

As you can read in the source [3], the gain/fader-position relation is
derived from measuring a console fader. The intended range is 0..2
(-inf, +6. dB) which is reflected in the base of the logarithm, but the
actual range is configurable(!).

The initial polynomial fit (old gain math) had a problem that inverse
function had a large error and  f(f^{-1}(x)) was off by a few dB for
smaller values of x. The power-function is a close approximation of it

$ gnuplot
set key horizontal top left
set ylabel "dB"
set xlabel "% fader"
set samples 250
plot[0:100][-200:6] 20 * log10 (2**((198 * (x / 100)**(.125) - 192) /
6)) t "Ardour fader"

Also note that granularity of the fader position p is not fixed in
Ardour. Fader length scales with the GUI, and the fine-grained mode is
constrained by a gtk adjustment. Default GUI granularity is  250 *
ui_scale (rounded to px),  hence "set samples 250" in the plot, With
"Keyboard::GainExtraFineScaleModifier" Ardour increases granularity by
a factor of 200 to a total of 50K steps with default GUI scaling.

> So with dB, I can on
> the surface enter as text an exact gain in dB. Also, the text value on
> the surface shows the value in dB which is much more useful to the user
> than some number from 0 to 1023.


However, are there any OSC controllers out there that can provide a
power-law fader?

As far as I know the answer is no. Furthermore neither log-scale (dB)
nor linear (coefficient) are appropriate for a fader.

One way would be to add a *new* interface specifically for OSC with the
following properties:

 - power-scale - similar to Ardour's Fader
 - 0dB can be represented by an integer fraction with small denominator.
 - the range is independent of Ardour's max_gain configuration
 - relatively simple relation to dB.

One candidate that fulfills these criteria is

 $g = (1.26 p)^3 ; 0 \leq p \leq 126; p \in \mathbb{Z}_{\geq 0}$

with x = 100 / 126 this results in a gain = 0dB
and x = 126/126; gain ~= +6dB

This could also be mapped to MIDI 0..127 with a small overshoot (1.26 *
127 / 126)^3 = 6.23 dB  and OSC could use 0 .. 1260  with unity at 1000.

This interface would be available in *addition* to a dB interface (two
in total).


The equations in text (non LaTeX) are:

[1] g = 2 ^ ((198 * p ^ (1/8) - 192) / 6)

[2] p = ((6 * log(g) / log(2) + 192) / 198) ^ 8

[3] https://github.com/Ardour/ardour/blob/master/libs/ardour/ardour/utils.h

More information about the Ardour-Dev mailing list