/*
Delay

Simple stereo delay.

Left Delay		Left channel delay time
Right Delay	Right channel delay - variable delay as a percentage of left channel delay
Right Ratio	Ratio as a percentage of left channel delay - variable to left, fixed ratios to right
Feedback		Feedback (sum of left and right outputs)
Tone		Feedback filtering - low-pass to left, high-pass to right
Wet Mix		Wet / dry mix
Output		Level trim
*/

slider1:0.4<0,1,0.0005>delay left
slider2:0.5<0,1,0.005>delay right variable
slider3:0<0,9,1>>>> delay right ratio
slider4:0.7<0,1,0.01>feedback
slider5:0.4<0,1,0.01>tone
slider6:0.33<0,1,0.01>wet mix
slider7: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; //set max delay time at max sample rate
buffer = size;
memset(buffer, 0, size);

ipos = 0;
fil0 = 0;
fil1 = 0;

twopi = 2*$pi;

@slider
fParam0 = slider1; //delay left
fParam1 = slider2; //delay right
fParam2 = slider4; //feedback
fParam3 = slider5; //tone
fParam4 = slider6; //wet mix
fParam5 = slider7; //output

oldel = ldel;
ldel = (size * fParam0 * fParam0)|0;
(ldel<4) ? ldel=4;
oldel != ldel ? freembuf(ldel*2);

slider3 == 0 ? tmp = 2 * fParam1; //variable ratio

slider3 == 1 ? tmp = 2; //fixed ratios
slider3 == 2 ? tmp = 3/2;
slider3 == 3 ? tmp = 4/3;
slider3 == 4 ? tmp = 6/5;
slider3 == 5 ? tmp = 1;
slider3 == 6 ? tmp = 5/6;
slider3 == 7 ? tmp = 3/4;
slider3 == 8 ? tmp = 2/3;
slider3 == 9 ? tmp = 1/2;

ordel = rdel;
rdel = (size * fParam0 * fParam0 * tmp)|0;
(rdel>size) ? rdel=size;
(rdel<4) ? rdel=4;
ordel != rdel ? freembuf(rdel*2);

fil = fParam3;
(fParam3>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) / srate);

fbk = 0.99 * fParam2;
wet = 1 - fParam4;
wet = fParam5 * (1 - wet * wet); //-3dB at 50% mix
dry = fParam5 * 2 * (1 - fParam4 * fParam4);

@sample
f0=fil0;
f1=fil1;
i=ipos;

l = (i + ldel) % (size + 1);
r = (i + rdel) % (size + 1);

a = spl0;
b = spl1;

ol = buf[buffer + l]; //delay outputs
or = buf[buffer + r];

tmpA = wet * a + fbk * ol; //mix input & feedback
tmpB = wet * b + fbk * or; //mix input & feedback
f0 = fil * (f0 - tmpA) + tmpA; //low-pass filter
f1 = fil * (f1 - tmpB) + tmpB; //low-pass filter
buf[buffer + i] = lmix * f0 + hmix * tmpA; //delay input
buf[buffer + i] = lmix * f1 + hmix * tmpB; //delay input

i-=1; (i<0) ? i=size;
l-=1; (l<0) ? l=size;
r-=1; (r<0) ? r=size;

spl0 = dry * a + ol; //mix wet & dry
spl1 = dry * b + or;

ipos = i;

(abs(f0)<0.0000000001) ? ( fil0=0; ):( fil0=f0; ); //trap denormals
(abs(f1)<0.0000000001) ? ( fil1=0; ):( fil1=f1; ); //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",ldel * 1000 / srate);
gfx_x =80; gfx_y =10;  gfx_printf("ms");
gfx_x =160; gfx_y =10;  gfx_printf("Delay Left");

gfx_x =20; gfx_y =30;  gfx_printf("%.0f",100 * rdel / ldel);
gfx_x =80; gfx_y =30;  gfx_drawchar($'%');
gfx_x =160; gfx_y =30;  gfx_printf("Delay Right");

slider3 > 0 ? (
gfx_x =250; gfx_y =30;  gfx_printf("-fixed-");
):(
gfx_x =250; gfx_y =30;  gfx_printf("-variable-");
);

gfx_x =20; gfx_y =50;  gfx_printf("%.0f",100 * fParam2);
gfx_x =80; gfx_y =50;  gfx_drawchar($'%');
gfx_x =160; gfx_y =50;  gfx_printf("Feedback");

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",200 * fParam3 - 100);
gfx_x =80; gfx_y =70;  gfx_printf("Lo <> Hi");
gfx_x =160; gfx_y =70;  gfx_printf("Tone");

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

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