// (C) 2008 Michael Gruhn.
// Idea by beat.by.bit
// For low/high shelf mode anything lower than a 2 oct width will give resonance

// Shapes: < 1 concave
//         = 1 linear
//         > 1 convex

desc:MIDI EQ Ducker
desc:MIDI EQ Ducker [LOSER]
//tags: dynamics equalizer compressor processing MIDI
//author: LOSER

slider1:0<0,129,1{All,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>MIDI Note #
slider2:10<0,75,1>Attack (ms)
slider3:1<0,4,.01>Atack Shape
slider4:100<0,500,1>Release (ms)
slider5:1<0,4,.1>Release Shape
slider6:0<0,15000,100>Frequency Coarse (Hz)
slider7:60<0,100,1>Frequency Fine (Hz)
slider8:1<0,2,.1>Width (Oct)
slider9:0<-32,32,1>Volume (dB)
slider10:0<0,4,1{Freq Peak,Freq Low Shelf,Freq High Shelf,Gate,Pump}> Mode
slider11:0<0,1,1{No,Yes}>Gate/Pump React To MIDI Velocity

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
pos = vol_s = 0;

@slider

att_s = max(slider3,0.01);
rel_s = max(slider5,0.01);

att = 1 / max(srate*slider2/1000,1);
rel = 1 / max(srate*slider4/1000,1);

freq = slider6+slider7;
Q = max(slider8,0.1);

to_db = slider9;

mode = slider10;

@block
memset(0,-1,samplesblock);

while (
midirecv(offs,msg1,msg23) ? 
(
  m=msg1&240;
  vel = (msg23/256)|0;
  note=msg23&127;
  (m == 9*16 || m == 8*16) && (note == (slider1-1) || slider1 == 0) ? 
  (
     m == 9*16 ? volume[offs] = vel/127;
     m == 8*16 ? volume[offs] = 0;   
  );
);
);

pos = 0;


@sample
volume[pos] == -1 ? vol_in = vol_in : (vol_in = sign(volume[pos]); volume[pos] > 0 ? vol_m = volume[pos]);

att_s == 1 ? att_l = att;
att_s < 1 ? att_l = (att_s+vol_s*(1-att_s))*att;
att_s > 1 ? att_l = (att_s-vol_s*(att_s-1))*att;

rel_s == 1 ? rel_l = rel;
rel_s < 1 ? rel_l = (rel_s+vol_s*(1-rel_s))*rel;
rel_s > 1 ? rel_l = (rel_s-vol_s*(rel_s-1))*rel;

vol_s = vol_s < vol_in ? min(vol_s + att_l , vol_in) : max(vol_s - rel_l , vol_in);


mode == 0 || mode == 1 || mode == 2 ? (

vol = vol_s * vol_m;

A = sqrt( 10^(to_db*(vol)/20) );
w0 = 2*$pi*freq/srate;
tmp = log(2)/2 * Q * w0/sin(w0);
alpha = sin(w0) * (exp(tmp)-exp(-tmp))/2;

mode == 0 ? (
  b0 =   1 + alpha*A ;
  b1 =  -2*cos(w0)   ;
  b2 =   1 - alpha*A ;
  a0 =   1 + alpha/A ;
  a1 =  -2*cos(w0)   ;
  a2 =   1 - alpha/A ;
):(

mode == 1 ? (
  b0 =    A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
  b1 =  2*A*( (A-1) - (A+1)*cos(w0)                   );
  b2 =    A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
  a0 =        (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha  ;
  a1 =   -2*( (A-1) + (A+1)*cos(w0)                   );
  a2 =        (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha  ;
):(
    b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
    b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
    b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
    a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha  ;
    a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
    a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha  ;
);
);
// normalize a0
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;

tmp = spl0;
spl0 = b0 * spl0 + b1 * xl1 + b2 * xl2 - a1 * yl1 - a2 * yl2;
xl2 = xl1; xl1 = tmp; yl2 = yl1; yl1 = spl0;
    
tmp = spl1;
spl1 = b0 * spl1 + b1 * xr1 + b2 * xr2 - a1 * yr1 - a2 * yr2;
xr2 = xr1; xr1 = tmp; yr2 = yr1; yr1 = spl1;
):(

slider11 ? vol = vol_s * vol_m : vol = vol_s;

mode == 3 ? (
spl0 *= vol;
spl1 *= vol;

):(

spl0 *= (1-vol);
spl1 *= (1-vol);

);


);
pos += 1;
