slider1:0<-60,0,0.1>Threshold (dB)
slider2:0<0,60,0.1>Knee (dB)
slider3:2<1,20,0.1>Ratio
slider4:3<1,20,0.1>Attack (ms)
slider5:100<20,1000,1>Release (ms)
slider6:0<-24,24,0.1>Output (dB)
slider7:0<0,1,1{Off,On}>Delta

in_pin:L in
in_pin:R in
out_pin:L out
out_pin:R out

@init
threshold = slider1;
knee_width = slider2;

ratio = slider3;
slope = ((1 - ratio) / ratio);

attack = slider4/1000;
release = slider5/1000;
alphaA = attack>0 ? exp(-1 / (attack * srate)) : 0;
alphaR = release>0 ? exp(-1 / (release * srate)) : 0;

Tlo = (threshold - knee_width / 2);
Thi = (threshold + knee_width / 2);
knee_factor = (slope / (knee_width * 2));

yR = 0;
yA = 0;

function computeGain(x)
(
(x < Tlo) ? x = 0 :
(x > Thi) ? x = slope * (x - threshold) :
(delta = x - Tlo;
x = delta * delta * knee_factor;);
);

function smoothAverage(x, alphaA, alphaR)
(
eps = 0.0000000001;
yR = min(x, alphaR * yR + (1 - alphaR) * x + eps - eps);
yA = alphaA * yA + (1 - alphaA) * yR + eps - eps;
x = yA;
);

dbc = 20/log(10);
function db2ratio(d) ( 10^(d/20); );
function ratio2db(r) ( log(abs(r))*dbc; );

gr_meter = 1;
gr_meter_decay = exp(1/(1*srate));

@slider
threshold = slider1;
knee_width = slider2;

ratio = slider3;
slope = ((1 - ratio) / ratio);

attack = slider4/1000;
release = slider5/1000;
alphaA = attack>0 ? exp(-1 / (attack * srate)) : 0;
alphaR = release>0 ? exp(-1 / (release * srate)) : 0;

Tlo = (threshold - knee_width / 2);
Thi = (threshold + knee_width / 2);
knee_factor = (slope / (knee_width * 2));

output = 10^(slider6/20);

listen = slider7;

@sample
inL = spl0;
inR = spl1;

xL = max(abs(inL),abs(inR));

xG = ratio2db(xL);
yG = computeGain(xG);
cG = smoothAverage(yG, alphaA, alphaR);
cL = db2ratio(cG);

listen == 0 ? (
spl0 = inL * cL * output;
spl1 = inR * cL * output;
);
listen == 1 ? (
spl0 = ((inL * cL) - inL)  * output;
spl1 = ((inR * cL) - inR)  * output;
);

gr = db2ratio(cL);
grv = ratio2db(gr);
grv < gr_meter ? gr_meter=grv : ( gr_meter*=gr_meter_decay; gr_meter>1?gr_meter=1; );
grmin = min( min(cG,cG) , grmin);

@gfx 0 36
gfx_r=1; gfx_g=gfx_b=0; gfx_a=0.8;

meter_bot=21;
meter_h=min(gfx_h,gfx_h-4);
xscale=gfx_w*20/meter_bot;

gfx_y=0;
gfx_x=gfx_w + log10(gr_meter)*xscale;
gfx_rectto(gfx_w,meter_h);

gfx_r=gfx_g=gfx_b=1; gfx_a=0.6;

s2=sqrt(2)/2;
g = s2;
while(
gfx_x=gfx_w + log10(g)*xscale;
gfx_x >= 0 ? (
gfx_y=0;
gfx_lineto(gfx_x,meter_h,0);
gfx_y=meter_h-gfx_texth;
gfx_x+=2;
gfx_drawnumber(log10(g)*20,0);
gfx_drawchar($'d');
gfx_drawchar($'B');
);
g*=s2;
gfx_x >=0;
);

(mouse_cap) ? (grmin=0;);
gfx_x=2;
gfx_y=meter_h/2 - gfx_texth/2;
gfx_drawnumber(grmin,1);
