// Limiter threshold - the limiter has zero attack time but uses the same release time as the compressor

slider1:1<0,1,0.01>threshold
slider2:0.5<0,1,0.01>ratio
slider3:0.5<0,1,0.01>output
slider4:0.5<0,1,0.01>attack
slider5:0.5<0,1,0.01>release
slider6:1<0,1,0.01>limiter
slider7:0<0,1,0.01>gate threshold
slider8:0.5<0,1,0.01>gate attack
slider9:0.5<0,1,0.01>gate release
slider10:1<0,1,0.01>mix

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

@init
mode = 0;
gain = 1;
env = env2 = genv = 0;

log2dB = 8.6858896380650365530225783783321;
db2log = 0.11512925464970228420089957273422;
gr_meter = 1;
gr_meter_decay = exp(1/(1*srate));

@slider
fParam1 = slider1; // threshold
fParam2 = slider2; // ratio
fParam3 = slider3; // output
fParam4 = slider4; // attack
fParam5 = slider5; // release
fParam6 = slider6; // limiter
fParam7 = slider7; // gate thresh
fParam8 = slider8; // gate att
fParam9 = slider9; // gate rel
fParam10 = slider10; // mix

mode = 0;
thr = pow(10, 2 * fParam1 - 2);
rat = fParam2 * 0.9375;
trim = pow(10, 4 * fParam3 - 2);
att = pow(10, -0.002 - 2 * fParam4);
rel = pow(10, -3 - 2 * fParam5);
re = (1-rel);

(fParam6>0.99) ? ( lthr=0; ): //limiter
( lthr=pow(10,(20*fParam6 - 20)/20); mode = 1; );

(fParam7<0.02) ? ( xthr=0; ): //gate
( xthr=pow(10,3 * fParam7 - 3); mode = 1; );

xrat = 1 - pow(10, -2 - 3.3 * fParam9);
gatt = pow(10, -0.002 - 3 * fParam8);

(rat<0 && thr<0.1) ? rat *= thr*15;

dry = 1 - fParam10; trim *= fParam10; //fx mix

@sample
e=env;
e2=env2;
ge=genv;

mode ? (

(lthr==0) ? lthr=1000;

a = spl0;
b = spl1;

i = (a<0) ? -a : a;
j = (b<0) ? -b : b;
i = (j>i) ? j : i;

e = (i>e) ? e + att * (i - e) : e * re;
e2 = (i>e) ? i : e2 * re;
g = (e>thr) ? trim / (1 + rat * ((e/thr) - 1)) : trim;

gain = (g + dry) / trim;

(g<0) ? g = 0;
(g*e2>lthr) ? g = lthr/e2; //limit

ge = (e>xthr) ? ge + gatt - gatt * ge : ge * xrat; //gate

c = a * (g * ge + dry);
d = b * (g * ge + dry);

spl0=c;
spl1=d;

):(

a = spl0;
b = spl1;

i = (a<0) ? -a : a;
j = (b<0) ? -b : b;
i = (j>i) ? j : i;

e = (i>e) ? e + att * (i - e) : e * re;
g = (e>thr) ? trim / (1 + rat * ((e/thr) - 1)) : trim;

gain = (g + dry) / trim;

c = a * (g + dry);
d = b * (g + dry);

spl0=c;
spl1=d;

);

(e<0.0000000001) ? ( env=0; ):( env=e; );
(e2<0.0000000001) ? ( env2=0; ):( env2=e2; );
(ge<0.0000000001) ? ( genv=0; ):( genv=ge; );

gr = log(gain)*log2dB;
grv = exp(gr*db2log);
grv < gr_meter ? gr_meter=grv : ( gr_meter*=gr_meter_decay; gr_meter>1?gr_meter=1; );
grmin = min( min(gr,gr) , grmin);

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

meter_bot=21;
meter_h=min(gfx_h,20);
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);

//------------------------------------------------------------------------

gfx_r=0.8; gfx_g=0.5; gfx_b=0.2; gfx_a=1;
gfx_setfont(1,Arial, 16);

gfx_x =20; gfx_y =30;  gfx_printf("%.1f",(40*fParam1 - 40) );
gfx_x =80; gfx_y =30;  gfx_printf("dB");
gfx_x =120; gfx_y =30;  gfx_printf("Threshold");

gfx_x =20; gfx_y =50;  gfx_printf("%.2f",(1/(1-rat)) );
gfx_x =80; gfx_y =50;  gfx_printf(": 1");
gfx_x =120; gfx_y =50;  gfx_printf("Ratio");

gfx_x =20; gfx_y =70;  gfx_printf("%.1f",(80*fParam3 - 40) );
gfx_x =80; gfx_y =70;  gfx_printf("dB");
gfx_x =120; gfx_y =70;  gfx_printf("Output");

gfx_x =20; gfx_y =90;  gfx_printf("%.1f",(-301030.1 / (srate * log10(1 - att))) );
gfx_x =80; gfx_y =90;  gfx_printf("s");
gfx_x =120; gfx_y =90;  gfx_printf("Attack");

gfx_x =20; gfx_y =110;  gfx_printf("%.1f",(-301.0301 / (srate * log10(1 - rel))) );
gfx_x =80; gfx_y =110;  gfx_printf("ms");
gfx_x =120; gfx_y =110;  gfx_printf("Release");

gfx_r=0.8; gfx_g=0.8; gfx_b=0.2;

(fParam6>0.99) ? (
gfx_x =120; gfx_y =130;  gfx_printf("Limiter Off");
):(
gfx_x =20; gfx_y =130;  gfx_printf("%.1f",(20*fParam6 - 20) );
gfx_x =80; gfx_y =130;  gfx_printf("dB");
gfx_x =120; gfx_y =130;  gfx_printf("Limiter");
);

gfx_r=0.2; gfx_g=0.8; gfx_b=0.8;

(fParam7<0.02) ? (
gfx_x =120; gfx_y =150;  gfx_printf("Gate Off");
):(
gfx_x =20; gfx_y =150;  gfx_printf("%.1f",(60*fParam7 - 60) );
gfx_x =80; gfx_y =150;  gfx_printf("dB");
gfx_x =120; gfx_y =150;  gfx_printf("Gate Threshold");
);

gfx_x =20; gfx_y =170;  gfx_printf("%.1f",(-301030.1 / (srate * log10(1 - gatt))) );
gfx_x =80; gfx_y =170;  gfx_printf("s");
gfx_x =120; gfx_y =170;  gfx_printf("Gate Attack");

gfx_x =20; gfx_y =190;  gfx_printf("%.1f",(-1806 / (srate * log10(xrat))) );
gfx_x =80; gfx_y =190;  gfx_printf("ms");
gfx_x =120; gfx_y =190;  gfx_printf("Gate Release");

gfx_r=0; gfx_g=0.9; gfx_b=0;

gfx_x =20; gfx_y =210;  gfx_printf("%.0f",(100*fParam10) );
gfx_x =80; gfx_y =210;  gfx_drawchar($'%');
gfx_x =120; gfx_y =210;  gfx_printf("Mix");
