// mod with synced delay times + hiss and different filters...

slider1:250<10,1000,1>delay (ms)
slider2:0<0,1,1{free,sync}>sync mode
slider3:6<0,13,1{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
slider4:0.7<0,1,0.01>feedback
slider5:0.1<0,1,0.01>lfo depth
slider6:0.5<0,1,0.01>lfo speed

slider7:30<0,100,1>hp filter
slider8:0.5<0,1,0.01>hp res
slider9:80<0,100,1>lp filter
slider10:0.5<0,1,0.01>lp res
slider11:0<0,1,0.01>hiss

slider12:0.33<0,1,0.01>wet mix
slider13:0.5<0,1,0.01>output

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

@init
ext_noinit = 1;
size = 65536*2; //set max delay time at max sample rate
buffer = 4096;
memset(buffer, 0, size);

ipos = 0;
fil0 = 0;
env = 0;
phi = 0;
dlbuf = 0;

ddl = 0;
k = 0;

twopi = 2*$pi;
twopi2 = twopi*100;

fs = srate;
(fs < 8000) ? fs = 44100; //??? bug somewhere!

// filter
mX10 = mX20 = mY10 = mY20 = 0;
mX11 = mX21 = mY11 = mY21 = 0;

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

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

slider2 == 0 ?
(
fParam0 = slider1; //delay
):(
fParam0 = sync;
slider1 = fParam0;
);

fParam3 = slider5; //lfo depth

del = min((fParam0 * fs * 0.001)|0,size);
mod = 0.049 * fParam3 * del; //mod = 0.49 * fParam3 * del;

@slider
(old_s7 != slider7 && slider7 > slider9) ? slider9 = slider7;
(old_s9 != slider9 && slider9 < slider7) ? slider7 = slider9;
old_s7 = slider7;
old_s9 = slider9;

fParam1 = slider4; //feedback
fParam4 = slider6; //lfo speed

fParam5 = slider7; //hp filter
fParam6 = slider8; //hp res
fParam7 = slider9; //lp filter
fParam8 = slider10; //lp res
fParam9 = slider11; //hiss

fParam10 = slider12; //wet mix
fParam11 = slider13; //output

fbk = abs(2.2 * fParam1 - 1.1);
(fParam1>0.5) ? (rel=0.9997; ):( rel=0.8; ); //limit or clip

wet = 1 - fParam10;
wet = fParam11 * (1 - wet * wet); //-3dB at 50% mix
dry = fParam11 * 2 * (1 - fParam10 * fParam10);

dphi = (twopi2 * pow(10, 3 * fParam4 - 2) / fs); //100-sample steps

// filter hp
sx0 = 16+fParam5*1.20103;
cx0 = floor(exp(sx0*log(1.059))*8.17742);
cutoff0 = 2 * cx0 / fs;
resx0 = (0.5 * fParam6) - 0.25;
res0 = pow(10, -resx0);
kx0 = 0.5 * res0 * sin($pi * cutoff0);
c10 = 0.5 * (1 - kx0) / (1 + kx0);
c20 = (0.5 + c10) * cos($pi * cutoff0);
c30 = (0.5 + c10 + c20) * 0.25;

mA00 = 2 * c30;
mA10 = -4 * c30;
mA20 = 2 * c30;
mB10 = -2 * c20;
mB20 = 2 * c10;

// filter lp
sx1 = 16+fParam7*1.20103;
cx1 = floor(exp(sx1*log(1.059))*8.17742);
cutoff1 = 2 * cx1 / fs;
resx1 = (0.5 * fParam8) - 0.25;
res1 = pow(10, -resx1);
kx1 = 0.5 * res1 * sin($pi * cutoff1);
c11 = 0.5 * (1 - kx1) / (1 + kx1);
c21 = (0.5 + c11) * cos($pi * cutoff1);
c31 = (0.5 + c11 - c21) * 0.25;

mA01 = 2 * c31;
mA11 = 4 * c31;
mA21 = 2 * c31;
mB11 = -2 * c21;
mB21 = 2 * c11;

// noise
hiss = fParam9 * 0.05;

@sample
dl=dlbuf;
db=dlbuf;
f0=fil0;
i=ipos;

a = spl0;
b = spl1;
c = (spl0+spl1)*0.5;
noise = (lp+=(((rand(2)-1)-lp) * 0.02)) * hiss; //white noise lp-filtered ~140Hz

(k==0) ? //update delay length at slower rate (could be improved!)
(
db += 0.01 * (del - db - mod - mod * sin(phi)); //smoothed delay+lfo
ddl = 0.01 * (db - dl); //linear step
phi += dphi;
(phi>twopi) ? phi -= twopi;
k = 100;
);
k -= 1;
dl += ddl; //lin interp between points

i -= 1;
(i<0) ? i = size; //delay positions

l = dl|0;
tmp = dl - l; //remainder

l += i;
(l>size) ? l -= (size+1);

ol = buf[buffer + l]; //delay output

l += 1;
(l>size) ? l = 0;
ol += tmp * (buf[buffer + l] - ol); //lin interp

ol += noise;

tmp = c + fbk * ol; //mix input (Mono!) & feedback

// filter hp
in0 = tmp;
out0 = mA00*in0 + mA10*mX10 + mA20*mX20 - mB10*mY10 - mB20*mY20;
mX20 = mX10;
mX10 = in0;
mY20 = mY10;
mY10 = out0;
tmp = out0;

// filter lp
in1 = tmp;
out1 = mA01*in1 + mA11*mX11 + mA21*mX21 - mB11*mY11 - mB21*mY21;
mX21 = mX11;
mX11 = in1;
mY21 = mY11;
mY11 = out1;
tmp = out1;

g=(tmp<0) ? -tmp : tmp; //simple limiter
env *= rel;
(g>env) ? env = g;
(env>1) ? tmp /= env;

buf[buffer + i] = tmp; //delay input

ol *= wet; //wet

spl0 = dry * a + ol; //dry
spl1 = dry * b + ol;

ipos = i;
dlbuf = dl;
(abs(f0)<0.0000000001) ? ( fil0=0; env=0; ):( fil0=f0; env=env; ); //trap denormals

@gfx 0 220
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 =10;  gfx_printf("%.0f",220 * fParam1 - 110);
gfx_x =80; gfx_y =10;  gfx_drawchar($'%');
gfx_x =120; gfx_y =10;  gfx_printf("Feedback");
gfx_x =200; gfx_y =10;  gfx_printf("Sat <> Lim");

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

gfx_x =20; gfx_y =30;  gfx_printf("%.0f",100 * fParam3);
gfx_x =80; gfx_y =30;  gfx_drawchar($'%');
gfx_x =120; gfx_y =30;  gfx_printf("LFO Depth");

gfx_x =20; gfx_y =50;  gfx_printf("%.2f",pow(10, 2 - 3 * fParam4));
gfx_x =80; gfx_y =50;  gfx_printf("sec");
gfx_x =120; gfx_y =50;  gfx_printf("LFO Speed");

gfx_r=0.2; gfx_g=0.8; gfx_b=0.8; gfx_a=1;

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",cx0);
gfx_x =80; gfx_y =70;  gfx_printf("Hz");
gfx_x =120; gfx_y =70;  gfx_printf("HP Filter");

gfx_x =20; gfx_y =90;  gfx_printf("%.1f",(20*resx0));
gfx_x =80; gfx_y =90;  gfx_printf("dB");
gfx_x =120; gfx_y =90;  gfx_printf("HP Res");

gfx_x =20; gfx_y =110;  gfx_printf("%.0f",cx1);
gfx_x =80; gfx_y =110;  gfx_printf("Hz");
gfx_x =120; gfx_y =110;  gfx_printf("LP Filter");

gfx_x =20; gfx_y =130;  gfx_printf("%.1f",(20*resx1));
gfx_x =80; gfx_y =130;  gfx_printf("dB");
gfx_x =120; gfx_y =130;  gfx_printf("LP Res");

gfx_r=0; gfx_g=1; gfx_b=1; gfx_a=1;

gfx_x =20; gfx_y =150;  gfx_printf("%.1f",20 * log10(hiss/11));
gfx_x =80; gfx_y =150;  gfx_printf("dB");
gfx_x =120; gfx_y =150;  gfx_printf("Hiss");

gfx_r=0; gfx_g=0.9; gfx_b=0; gfx_a=1;

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

gfx_x =20; gfx_y =190;  gfx_printf("%.1f",20 * log10(2 * fParam11));
gfx_x =80; gfx_y =190;  gfx_printf("dB");
gfx_x =120; gfx_y =190;  gfx_printf("Output");
