// mod with synced delay times...

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.4<0,1,0.01>tone
slider6:0.1<0,1,0.01>lfo depth
slider7:0.5<0,1,0.01>lfo speed
slider8:0.33<0,1,0.01>wet mix
slider9: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!

@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 = slider6; //lfo depth

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

@slider
fParam1 = slider4; //feedback
fParam2 = slider5; //tone
fParam4 = slider7; //lfo speed
fParam5 = slider8; //wet mix
fParam6 = slider9; //output

fil = fParam2;
(fParam2>0.5) ? //simultaneously change crossover frequency & high/low mix
(
fil = 0.5 * fil - 0.25;
lmix = -2 * fil;
hmix = 1;
):(
hmix = 2 * fil;
lmix = 1 - hmix;
);
fil = exp(-twopi * pow(10, 2.2 + 4.5 * fil) / fs);

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

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

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

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

a = spl0;
b = spl1;
c = (spl0+spl1)*0.5;

(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

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

f0 = fil * (f0 - tmp) + tmp; //low-pass filter
tmp = lmix * f0 + hmix * tmp;

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 140
gfx_r=0; gfx_g=0.9; gfx_b=0; 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_x =20; gfx_y =30;  gfx_printf("%.0f",200 * fParam2 - 100);
gfx_x =80; gfx_y =30;  gfx_drawchar($'%');
gfx_x =120; gfx_y =30;  gfx_printf("Tone");
gfx_x =200; gfx_y =30;  gfx_printf("Lo <> Hi");

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

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

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

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