[linux-audio-dev] Writing a winner takes it all gain filter.

Orlarey Yann orlarey at grame.fr
Fri Jun 16 20:34:45 UTC 2006


Hi Alex,

Alex Polite a écrit :
> My first project will be a winner-takes-it-all-gain filter that takes
> n number of inputs and lowers the gain on all but the loudest signal.
If I have correctly understood the problem, here is how it could be
implemented in Faust :

    envelop        = abs : max ~ -(0.00001);
    loudest(x,y)   = x*(envelop(x)>envelop(y)) + y*(envelop(x) <=
envelop(y));
    process        = loudest;

The first line compute a very simple envelop from an input signal :
    y(t) = max( abs(x(t)), y(t-1) - 0.000001 )
The second line computes the loudest of two signals by comparing their
envelops.
The last line defines the 'process' we want to compute (the equivalent
of main in C).

Here is the core of the code generated by the Faust compiler :

        for (int i=0; i<count; i++) {
            float fTemp0 = input1[i];
            float fRec0Temp = max((fRec0 - 1.000000e-05f), fabsf(fTemp0));
            float fTemp1 = input0[i];
            float fRec1Temp = max((fRec1 - 1.000000e-05f), fabsf(fTemp1));
            output0[i] = ((fTemp1 * (fRec1Temp > fRec0Temp)) + (fTemp0 *
(fRec1Temp <= fRec0Temp)));
            fRec1 = fRec1Temp;
            fRec0 = fRec0Temp;
        }

If you need more than two input signals you can cascade several loudest
modules. For example :
    process = loudest : loudest;
will take the loudest of 3 signals

And :
    process = loudest : loudest : loudest;
will take the loudest of 4 signals.

Instead of cascading 'loudest' manually so to speak, you could also write :
    process = seq(i,7,loudest);
This will take the loudest of 8 signals  by cascading 'loudest' 7 times.
Obviously this is not the most efficient way as it computes 2*7 envelops
instead of the 8 needed.

Here is a more efficient solution that computes the right number of
envelops:

    envelop            = abs : max ~ -(0.00001);
    loudest(ex,x,y)    = max(ex, envelop(y)),  x*(ex>envelop(y)) + y*(ex
<= envelop(y));
    chain(n)           = first : seq(i,n-1,loudest) : ! ;
    first(x)           = envelop(x), x;
    process            = chain (8);

As you can see, loudest now takes 3 arguments and produces 2 signals.
The first argument is the envelop of x and the first result is the
combined envelop of x and y.

Hoping this will help...

Yann





More information about the Linux-audio-dev mailing list