// delay with some weird feedback etc. routing...

slider1:250<10,1000,1>Delay (ms)
slider2:-6<-30,-1,0.1>Feedback (dB)
slider3:0<-30,12,0.1>Mix in (dB)
slider4:-6<-30,12,0.1>Wet (dB)
slider5:0<-30,12,0.1>Dry (dB)
slider6:0<0,1,1{free,sync}>Sync mode
slider7:10<0,17,1{1 d,1,1 t,1/2 d,1/2,1/2 t,1/4 d,1/4,1/4 t,1/8 d,1/8,1/8 t,1/16 d,1/16,1/16 t,1/32 d,1/32,1/32 t}>Sync
slider9:0<0,1,1{1+2,3+4}>Output
slider10:0<0,1.2,0.01>Xtra Feedback
slider11:0<0,7018,1>High-pass (Hz)
slider12:0<0,1,0.001>Resonance
slider13:7018<0,7018,1>Low-pass (Hz)
slider14:0<0,1,0.001>Resonance
slider15:0<0,1,1{A Routing,B Routing}>Filter mode

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

@init
delaypos = 0;

n1A = 0;
n2A = 0;
n3A = 0;
n4A = 0;
n1B = 0;
n2B = 0;
n3B =0;
n4B = 0;

fb_lp = 0;
fb_hp = 0;

output = 1;
gain = 1;
gaini = 1;
gainii = 1;
env = 0;
envi = 0;
envii = 0;
threshold = 10^(-0.3/20);
transfer_A = -1;
transfer_B = 1 * pow(threshold,-transfer_A);
attack = exp(-1/(0.004/1000*srate));
release = exp(-1/(300/1000*srate));
envelope_decay = exp(-1/(100/1000*srate));

@slider
wetmix = slider2 <= -30.0 ? 0.0 : 10^(slider2/20);
drymix = slider3 <= -30.0 ? 0.0 : 10^(slider3/20);
wetmix2 = slider4 <= -30.0 ? 0.0 : 10^(slider4/20);
drymix2 = slider5 <= -30.0 ? 0.0 : 10^(slider5/20);

xtra = slider10;
filtermode = slider15;

(old_s11 != slider11 && slider11 > slider13) ? slider13 = slider11;
(old_s13 != slider13 && slider13 < slider11) ? slider11 = slider13;
old_s11 = slider11;
old_s13 = slider13;

cut_hp = 2 * $pi * slider11/srate;
res_hp = slider12*0.9;
cut_lp = 2 * $pi * slider13/srate;
res_lp = slider14*0.895;

@block
slider7==0?(
grid=3/2;
);
slider7==1?(
grid=1;
);
slider7==2?(
grid=2/3;
);
slider7==3?(
grid=3/4;
);
slider7==4?(
grid=1/2;
);
slider7==5?(
grid=1/3;
);
slider7==6?(
grid=3/8;
);
slider7==7?(
grid=1/4;
);
slider7==8?(
grid=1/6;
);
slider7==9?(
grid=3/16;
);
slider7==10?(
grid=1/8;
);
slider7==11?(
grid=1/12;
);
slider7==12?(
grid=3/32;
);
slider7==13?(
grid=1/16;
);
slider7==14?(
grid=1/24;
);
slider7==15?(
grid=3/64;
);
slider7==16?(
grid=1/32;
);
slider7==17?(
grid=1/48;
);

sync = ((grid*240)/tempo)*1000;

slider6 == 0 ? (
temp = slider1;
):(
temp = sync;
slider1 = temp;
);

odelay = delaylen;
delaylen = (temp * srate / 1000)|0;
odelay != delaylen ? freembuf(delaylen*2);

@sample
dpint = delaypos*2;

filtermode == 0 ? (
os1=dpint[0]+ospl0;
os2=dpint[1]+ospl1;
);
filtermode == 1 ? (
spl0=spl0+ospl0;
spl1=spl1+ospl1;
os1=dpint[0];
os2=dpint[1];
);

dpint[0]=min(max(spl0*drymix + os1*wetmix,-4),4);
dpint[1]=min(max(spl1*drymix + os2*wetmix,-4),4);

(delaypos+=1) >= delaylen ? delaypos=0;

slider9 ? (
spl0=spl0*drymix2;
spl1=spl1*drymix2;
spl2=os1*wetmix2;
spl3=os2*wetmix2;
):(
spl0=spl0*drymix2 + os1*wetmix2;
spl1=spl1*drymix2 + os2*wetmix2;
);

inA = os1*wetmix2*xtra;
inB = os2*wetmix2*xtra;

fb_lp=res_lp+res_lp/(1-cut_lp);
fb_hp=res_hp+res_hp/(1-cut_hp);

n1A=n1A+cut_lp*(inA-n1A+fb_lp*(n1A-n2A));
n2A=n2A+cut_lp*(n1A-n2A);
n3A=n3A+cut_hp*(n2A-n3A+fb_hp*(n3A-n4A));
n4A=n4A+cut_hp*(n3A-n4A);

n1B=n1B+cut_lp*(inB-n1B+fb_lp*(n1B-n2B));
n2B=n2B+cut_lp*(n1B-n2B);
n3B=n3B+cut_hp*(n2B-n3B+fb_hp*(n3B-n4B));
n4B=n4B+cut_hp*(n3B-n4B);

out0=n2A-n4A;
out1=n2B-n4B;

det= max(abs(out0),abs(out1));
deti = max(abs(spl0),abs(spl1));
detii = max(abs(spl2),abs(spl3));
det += 0.000000000001;
deti += 0.000000000001;
detii += 0.000000000001;
env = det >= env ? det : det+envelope_decay*(env-det);
envi = deti >= envi ? deti : deti+envelope_decay*(envi-deti);
envii = detii >= envii ? detii : detii+envelope_decay*(envii-detii);
transfer_gain = env > threshold ? pow(env,transfer_A)*transfer_B:output;
transfer_gaini = envi > threshold ? pow(envi,transfer_A)*transfer_B:output;
transfer_gainii = envii > threshold ? pow(envii,transfer_A)*transfer_B:output;
gain = transfer_gain < gain ? transfer_gain+attack *(gain-transfer_gain) : transfer_gain+release*(gain-transfer_gain);
gaini = transfer_gaini < gaini ? transfer_gaini+attack *(gaini-transfer_gaini) : transfer_gaini+release*(gaini-transfer_gaini);
gainii = transfer_gainii < gainii ? transfer_gainii+attack *(gainii-transfer_gainii) : transfer_gainii+release*(gainii-transfer_gainii);

ospl0 = out0 * gain;
ospl1 = out1 * gain;

spl0 *= gaini;
spl1 *= gaini;

spl2 *= gainii;
spl3 *= gainii;
