/*
Resonant Filter

VCF with LFO and EG.

Frequency	Cut-off frequency
Resonance	Resonance
Output		Level trim
Env->VCF	Positive or negative (squelchy!) Envelope modulation of cut-off frequency
Attack		Attack time
Release		Release time (use fast attack and release for "dirty" modulation)
LFO->VCF	LFO modulation of cut-off frequency (turn to left for sample & hold LFO, right for sine)
LFO Rate		LFO modulation speed
Trigger		Envelope trigger level (normally set to minimum to acts as a free-running envelope follower)
Min Frequency	Limit minimum cut-off frequency (sometimes frequencies can get very low...)
Max Frequency	Limit maximum cut-off frequency for a mellower sound (when it's getting too squelchy...)
*/

desc: Mono.

slider1:0.5<0,1,0.01>frequency
slider2:0<0,1,0.01>resonance
slider3:0.5<0,1,0.01>output
slider4:0.5<0,1,0.01>env -> vcf
slider5:0<0,1,0.01>attack
slider6:0.5<0,1,0.01>release
slider7:0.5<0,1,0.01>lfo -> vcf
slider8:0.5<0,1,0.01>lfo rate
slider9:0<0,1,0.01>trigger
slider10:0.02<0,1,0.01>min frequency
slider11:0.88<0,1,0.01>max frequency

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

@init
itm1=itm2=otm1=otm2=0;

buf0=0;
buf1=0;
buf2=0;

@slider
fParam0 = slider1; //freq (fff)
fParam1 = slider2; //res (fq)
fParam2 = slider3; //output (fg)
fParam3 = slider4; //env->vcf (fenv)
fParam4 = slider5; //att
fParam5 = slider6; //rel
fParam6 = slider7; //lfo->vcf (lfo)
fParam7 = slider8; //lfo rate
fParam8 = slider9; //trigger
fParam9 = slider10; //min freq (fmin)
fParam10 = slider11; //max freq (fmax)

fff = 1.5 * fParam0 * fParam0 - 0.15;
fq = 0.99 * pow(fParam1,0.3);
fg = 0.5 * pow(10, 2 * fParam2 - 1);

fmin = 0.99 + 0.3 * fParam1;
(fmin>(1.3 * fParam9)) ? fmin=1.3*fParam9;
fmax = 0.99 + 0.3 * fParam1;
(fmax>(1.3 * fParam10)) ? fmax=1.3*fParam10;

fenv = 2*(0.5 - fParam3)*(0.5 - fParam3);
fenv = (fParam3>0.5) ? fenv : -fenv;
att = pow(10, -0.01 - 3.2 * fParam4);
rel = 1 - pow(10, -3.2 - 2 * fParam5);

lfomode=0;
flfo = 2 * (fParam6 - 0.5)*(fParam6 - 0.5);
dphi = (6.2832 * pow(10, 3 * fParam7 - 1.5) / srate); // 2*$pi * ???
(fParam6<0.5) ? ( lfomode=1; flfo *= 0.001; dphi *= 0.15915; ); // S&H

(fParam8<0.1) ? tthr = 0 : tthr = 3 * fParam8 * fParam8;

@sample
tt=ttrig;
bl=bufl;
ph=phi;

b0=buf0;
b1=buf1;
b2=buf2;

(tthr==0) ? (

a = spl0+spl1;

i = (a>0) ? a : -a; // envelope
env = (i>env) ? env + att * (i - env) : env * rel;

(lfomode==0) ? (bl = flfo * sin(ph); ): // lfo
(ph>1) ? ( bl = flfo*(rand(2000)-1000); ph=0; );
ph += dphi;

f = fff + fenv * env + bl; // freq
(f<fmin) ? (i=fmin; ):( i=(f>fmax) ? fmax : f; );
o = 1 - i;

b0 = o * b0 + i * (fg*a + fq*(1 + (1/o)) * (b0-b1) );
b1 = o * b1 + i * b0; // filter
b2 = o * b2 + i * b1;

spl0 = b2;
spl1 = b2;

otm1=0.999*otm1 + spl0 - itm1; itm1=spl0; spl0=otm1;
otm2=0.999*otm2 + spl1 - itm2; itm2=spl1; spl1=otm2;

):(

a = spl0+spl1;

i = (a>0) ? a : -a; // envelope
env = (i>env) ? i : env * rel;
(env>tthr) ? ( (tt==0) ? (tatt=1; (lfomode==1) ? ph=2; ); tt=1; ) : tt=0;
(tatt==1) ? ( env2 += att*(1-env2); (env2>0.999) ? tatt=0; ) : env2*=rel;

(lfomode==0) ? (bl = flfo * sin(ph); ): // lfo
(ph>1) ? ( bl = flfo*(rand(2000)-1000); ph=0; );
ph += dphi;

f = fff + fenv * env + bl; // freq
(f<fmin) ? (i=fmin; ):( i=(f>fmax) ? fmax : f; );
o = 1 - i;

b0 = o * b0 + i * (fg*a + fq*(1 + (1/o)) * (b0-b1) );
b1 = o * b1 + i * b0; // filter
b2 = o * b2 + i * b1;

spl0 = b2;
spl1 = b2;

otm1=0.999*otm1 + spl0 - itm1; itm1=spl0; spl0=otm1;
otm2=0.999*otm2 + spl1 - itm2; itm2=spl1; spl1=otm2;

);

(abs(b0)<0.0000000001) ? ( buf0=0; buf1=0; buf2=0; ):( buf0=b0; buf1=b1; buf2=b2; );

ttrig=tt;
bufl=bl;

// modulo: phi=mod(ph,6.2831853) ==>
// (ph%6.2831853)
// for phi...
test1 = (ph / 6.2831853) |0;
test2 = test1 * 6.2831853;
phi = ph - test2;

// or for phi...
//test10 = ph/6.2831853;
//test11 = test10|0;
//test12 = test10-test11;
//phi = test12*6.2831853;

@gfx 0 240
gfx_r=0.2; gfx_g=0.8; gfx_b=0.8; gfx_a=1;
gfx_setfont(1,"Arial", 16);

gfx_x =20; gfx_y =10;  gfx_printf("%.0f",(100 * fParam0) );
gfx_x =70; gfx_y =10;  gfx_drawchar($'%');
gfx_x =120; gfx_y =10;  gfx_printf("Frequency");

gfx_x =20; gfx_y =30;  gfx_printf("%.0f",(100 * fParam1) );
gfx_x =70; gfx_y =30;  gfx_drawchar($'%');
gfx_x =120; gfx_y =30;  gfx_printf("Resonance");

gfx_r=0; gfx_g=0.9; gfx_b=0;

gfx_x =20; gfx_y =50;  gfx_printf("%.1f",(40 *fParam2 - 20) );
gfx_x =70; gfx_y =50;  gfx_printf("dB");
gfx_x =120; gfx_y =50;  gfx_printf("Output");

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

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",(200 * fParam3 - 100) );
gfx_x =70; gfx_y =70;  gfx_drawchar($'%');
gfx_x =120; gfx_y =70;  gfx_printf("Env -> VCF");

gfx_x =20; gfx_y =90;  gfx_printf("%.2f",(-301.0301 / (srate * log10(1 - att))) );
gfx_x =70; gfx_y =90;  gfx_printf("ms");
gfx_x =120; gfx_y =90;  gfx_printf("Attack");

gfx_x =20; gfx_y =110;  gfx_printf("%.0f",(-301.0301 / (srate * log10(rel))) );
gfx_x =70; gfx_y =110;  gfx_printf("ms");
gfx_x =120; gfx_y =110;  gfx_printf("Release");

gfx_x =20; gfx_y =130;  gfx_printf("%.0f",(200 * fParam6 - 100) );
gfx_x =70; gfx_y =130;  gfx_drawchar($'%');
gfx_x =120; gfx_y =130;  gfx_printf("LFO -> VCF");

gfx_x =20; gfx_y =150;  gfx_printf("%.2f",pow(10,4*fParam7-2) );
gfx_x =70; gfx_y =150;  gfx_printf("Hz");
gfx_x =120; gfx_y =150;  gfx_printf("LFO Rate");

(fParam6<0.5) ? (
gfx_r=0.8; gfx_g=0.8; gfx_b=0.2;
gfx_x =210; gfx_y =130;  gfx_printf("-S&H-");
):(
gfx_r=0.8; gfx_g=0.5; gfx_b=0.2;
gfx_x =210; gfx_y =130;  gfx_printf("-Sine-");
);

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

(tthr==0) ? (
gfx_x =20; gfx_y =170;  gfx_printf("Free Run");
):( 
gfx_x =20; gfx_y =170;  gfx_printf("%.1f",20*log10(0.5*tthr) );
gfx_x =70; gfx_y =170;  gfx_printf("dB");
);
gfx_x =120; gfx_y =170;  gfx_printf("Trigger");

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

gfx_x =20; gfx_y =190;  gfx_printf("%.0f",(100 * fParam9) );
gfx_x =70; gfx_y =190;  gfx_drawchar($'%');
gfx_x =120; gfx_y =190;  gfx_printf("Min Frequency");

gfx_x =20; gfx_y =210;  gfx_printf("%.0f",(100 * fParam10) );
gfx_x =70; gfx_y =210;  gfx_drawchar($'%');
gfx_x =120; gfx_y =210;  gfx_printf("Max Frequency");
