/*
Thru-Zero Flanger

Tape flanger and ADT.

This plug simulates tape-flanging, where two copies of a signal cancel out completely
as the tapes pass each other. It can also be used for other "modulated delay" effects
such as phasing and simple chorusing.

Rate		Modulation rate (sine wave) - set to minimum for static comb filtering
Depth		Maximum modulation depth
Mix		Wet / dry mix - set to 50% for complete cancelling
Feedback		Add positive or negative feedback for harsher or "ringing" sound
Min Delay		Modulation depth - set to less than 100% to limit build up of low fequencies with feedback
*/

slider1:0.5<0,1,0.01>rate
slider2:0.3<0,1,0.01>depth
slider3:0.45<0,1,0.01>mix
slider4:0.3<0,1,0.01>feedback
slider5:0.7<0,1,0.01>min delay
slider6: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;

bufpos = 0;

BUFMAX = 2048;
buffer = BUFMAX;
buffer2 = BUFMAX;
memset(buffer, 0, BUFMAX);
memset(buffer2, 0, BUFMAX);

phi = fb = fb1 = fb2 = 0;

@slider
fParam0 = slider1; //rate
fParam1 = slider2; //depth
fParam2 = slider3; //mix
fParam3 = slider4; //feedback
fParam4 = slider5; //min delay
fParam5 = slider6; //output

rat = (pow(10, 3 * fParam0 - 2) * 2 / srate);
dep = 2000 * fParam1 * fParam1;
dem = dep - dep * fParam4;
dep -= dem;

wet = 2 * fParam5 * fParam2;
dry = 2 * fParam5 * 1 - wet;
(fParam0<0.01) ? ( rat=0; phi=0; );
fb = 1.9 * fParam3 - 0.95;

@sample
f1=fb1;
f2=fb2;
ph=phi;
dm=dem;
bp=bufpos;

a = spl0;
b = spl1;

ph += rat; 
(ph>1) ? ph -= 2;

bp -= 1;
bp &= 0x7FF;
buf[buffer + bp] = a + fb * f1;
buf2[buffer2 + bp] = b + fb * f2;

tmpf = dm + dep * (1 - ph * ph); //delay mod shape
tmp = (tmpf)|0;
tmpf -= tmp;
tmp = (tmp + bp) & 0x7FF;
tmpi = (tmp + 1) & 0x7FF; 

f1 = buf[buffer + tmp];  //try adding a constant to reduce denormalling
f2 = buf2[buffer2 + tmp];
f1 = tmpf * (buf[buffer + tmpi] - f1) + f1; //linear interpolation
f2 = tmpf * (buf2[buffer2 + tmpi] - f2) + f2;

a = a * dry - f1 * wet;
b = b * dry - f2 * wet;

spl0 = a;
spl1 = b;

(abs(f1)>0.0000000001) ? ( fb1 = f1; fb2 = f2; ) : fb1 = fb2 = 0; //catch denormals
phi = ph;
bufpos = bp;

@gfx 0 140
gfx_r=0; gfx_g=0.9; gfx_b=0; gfx_a=1;
gfx_setfont(1,"Arial", 16);

slider1 == 0 ? (
gfx_x =20; gfx_y =10;  gfx_printf("Static");
gfx_x =80; gfx_y =10;  gfx_printf("sec");
gfx_x =160; gfx_y =10;  gfx_printf("Rate");
):(
gfx_x =20; gfx_y =10;  gfx_printf("%.2f",pow(10 ,2 - 3 * fParam0));
gfx_x =80; gfx_y =10;  gfx_printf("sec");
gfx_x =160; gfx_y =10;  gfx_printf("Rate");
);

gfx_x =20; gfx_y =30;  gfx_printf("%.2f",1000 * dep / srate);
gfx_x =80; gfx_y =30;  gfx_printf("ms");
gfx_x =160; gfx_y =30;  gfx_printf("Depth");

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("Mix");

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",200 * fParam3 - 100);
gfx_x =80; gfx_y =70;  gfx_drawchar($'%');
gfx_x =160; gfx_y =70;  gfx_printf("Feedback");

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("Min Delay");

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");
