/*
Pressure:
mix of attack/ratio

hard/soft Mode:
'soft' mode will polish the envelope curve to minimize artifacts that would be obvious on vocals etc.

Punch:
allpass filter centered around 240 Hz, allowing the transients to pass before the low end and
thus giving a feeling of more "clicky" or "punchy" sound (IF a low end is present that is)
*/

slider1:0<-30,0,0.1>Threshold (dB)
slider2:2<1,20,0.1>Pressure
slider3:0<0,100,1>(comp) Release (%)
slider4:0<0,100,1>(det) Release (%)
slider5:0<-24,24,0.1>Output (dB)
slider6:0<0,1,1{hard,soft}>Mode
slider7:0<0,1,1{off,on}>Punch
slider8:240<120,300,10>--Allpass Freq (Hz)
slider9:0.707<0.5,1,0.001>--Allpass Bandwidth

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

@init
output = 1;
transfer_A = 0;
transfer_B = 1;
gain = 1;
env0 = 0;
env1 = 0;
env2 = 0;

attack = exp(-1/ (0.01/1000*srate));

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

@slider
threshold = 10^(slider1/20);

transfer_A = (1/slider2)-1;
transfer_B = output * pow(threshold,-transfer_A);

attack = exp(-1/((slider2*0.05)/1000*srate));
release = exp(-1/((10+(slider3*4.9))/1000*srate));
envelope_decay0 = exp(-1/((10+(slider4*0.9))/1000*srate));
envelope_decay1 = exp(-1/((10+(slider4*0.6))/1000*srate));
envelope_decay2 = exp(-1/((10+(slider4*0.3))/1000*srate));

vol = 10^(slider5/20);

hard = slider6;

// Allpass Filter
punch = slider7;

f = 2*$pi * min(slider8, 0.49 * srate) / srate;
q =max(min(slider9,1),0.5);

w0 = f;
alpha = sin(w0) / (2*q);

b0 = a2 = 1 - alpha;
b1 = a1 = -2 * cos(w0);
b2 = a0 = 1 + alpha;

a1 /= a0;
a2 /= a0;
b0 /= a0;
b1 /= a0;
b2 /= a0;

@sample
inL = spl0;
inR = spl1;

punch ? (
//Left
x2A = x1A;
x1A = x0A;
x0A = inL;

y2A = y1A;
y1A = y0A;
y0A = b0*x0A + b1*x1A + b2*x2A - a1*y1A - a2*y2A;

//Right
x2B = x1B;
x1B = x0B;
x0B = inR;

y2B = y1B;
y1B = y0B;
y0B = b0*x0B + b1*x1B + b2*x2B - a1*y1B - a2*y2B;

//Output
out0 = (inL+y0A)*0.5;
out1 = (inR+y0B)*0.5;

det = max(abs(out0),abs(out1));
):(
det = max(abs(inL),abs(inR));
);
det += 0.000000000001;

hard ? (
env2 = det >= env2 ? det : det+envelope_decay0*(env2-det);
):(
env0 = det >= env0 ? det : det+envelope_decay0*(env0-det);
env1 = env0 >= env1 ? env0 : env0+envelope_decay1*(env1-env0);
env2 = env1 >= env2 ? env1 : env1+envelope_decay2*(env2-env1);
);

transfer_gain = env2 > threshold ? pow(env2,transfer_A)*transfer_B:output;
gain = transfer_gain < gain ? transfer_gain+attack*(gain-transfer_gain) : transfer_gain+release*(gain-transfer_gain);

spl0 = inL * gain * vol;
spl1 = inR * gain * vol;

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 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);
