// sounds nice with a roland tr-505/tr-707 drum kit

slider1:0<0,6,1{Sine,Triangle,Square,Saw,Noise,Ring,Filter}>mode
slider2:1<0,1,0.01>dynamics
slider3:1<0,1,0.01>mix
slider4:0.5<0,1,0.01>glide
slider5:0.5<0,1,0.01>transpose
slider6:0.5<0,1,0.01>maximum
slider7:0.5<0,1,0.01>trigger
slider8: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;

twopi = 6.2831853;
bold = 0;
dn = 0;
buf1 = buf2 = buf3 = buf4 = 0;

dphi = 100/srate; //initial pitch
min = srate/30; //lower limit
res1 = cos(0.01); //p
res2 = sin(0.01); //q

att = pow(10,-60/srate);
//rel = pow(10,-10/srate);
rel = pow(10,-60/srate); // ???

function filterFreq(hz) (
r = 0.999;
j = r * r - 1;
k = (2 - 2 * r * r * cos(0.647 * hz / srate ));
hz = ((sqrt(k*k - 4*j*j) - k) / (2*j));
);

fo = filterFreq(50);
fi = (1 - fo)*(1 - fo);

itm1=itm2=otm1=otm2=0;

@slider
fParam1 = slider1; //Mode
fParam2 = slider2; //Dynamics
fParam3 = slider3; //Mix
fParam4 = slider4; //Tracking
fParam5 = slider5; //Transpose
fParam6 = slider6; //Maximum Hz
fParam7 = slider7; //Trigger dB
fParam8 = slider8; //Output dB

mode = fParam1|0;

ddphi = fParam4 * fParam4;
thr = pow(10, 3*fParam7 - 3.8);
max = (srate / pow(10, 1.6 + 2.2 * fParam6))|0;
trans = pow(1.0594631,(72*fParam5 - 36|0));
wet = pow(10, 2*fParam8 - 1);

(mode<6) ? (
dyn = wet * 0.6 * fParam3 * fParam2;
dry = wet * sqrt(1 - fParam3);
wet = wet * 0.3 * fParam3 * (1 - fParam2);
):(
dry = wet * (1 - fParam3);
wet *= (0.02*fParam3 - 0.004);
dyn = 0;
);

@sample
b1=buf1;
b2=buf2;
b3=buf3;
b4=buf4;

n=num;

p=phi;
dp=dphi;
s=sig;
bo=bold;

e=env;
sw=saw;
dsw=dsaw;
r1=res1;
r2=res2;

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

a = spl0;
b = spl1;

x = a + b;

tmp = (x>0) ? x : -x; //dynamics envelope
//e = (tmp>e) ? 0.5*(tmp + e) : e * rel; // ???
//e = (tmp>e) ? 4*tmp + att*(e-4*tmp) : e * rel; // ???
e = (tmp>e) ? 4*tmp + att*(e-4*tmp) : 4*tmp + rel*(e-4*tmp); // ???

b1 = fo*b1 + fi*x; 
b2 = fo*b2 + b1; //low-pass filter

(b2>thr) ? //if >thresh
(
(s<1) ? //and was <thresh
(
(n<min) ? //not long ago
(
tmp2 = b2 / (b2 - bo); //update period
tmp = trans*twopi/(n + dn - tmp2);
dp = dp + ddphi * (tmp - dp);
dn = tmp2;
dsw = 0.3183098 * dp;

(mode==6) ?
(
r1 = cos(4*dp); //resonator
r2 = sin(4*dp);
);
);
n = 0; //restart period measurement
);
s = 1;
):(
(n>max) ? s = 0; //now <thresh
);
n += 1;
bo = b2;

//p = mod(p+dp,twopi);
test0 = p+dp;
test1 = (test0 / twopi) |0;
test2 = test1 * twopi;
p = test0 - test2;

mode==0 ? ( //sine
x=sin(p);
);
mode==1 ? ( //triangle
x = (2*p/$pi-1);
(x>1) ? x = 2-x;
);
mode==2 ? ( //square
x=(sin(p)>0) ? 0.5 : -0.5;
);
mode==3 ? ( //saw
//sw = mod(sw+dsw,2);
test10 = sw+dsw;
test11 = (test10 / 2) |0;
test12 = test11 * 2;
sw = test10 - test12;
x = sw - 1;
);
mode==4 ? ( //noise
x = (rand(2)-1)*0.25;
);
mode==5 ? ( //ring
x *= sin(p);
);
mode==6 ? ( //filt
x += (b3 * r1) - (b4 * r2); 
b4 = 0.996 * ((b3 * r2) + (b4 * r1));
b3 = 0.996 * x;
);

x *= (wet + dyn * e);

spl0 = dry*a + x;
spl1 = dry*b + x;

(abs(b1)<0.000000001) ? ( buf1=0; buf2=0; buf3=0; buf4=0; ):( buf1=b1; buf2=b2; buf3=b3; buf4=b4; );

phi=p;
dphi=dp;
sig=s;
bold=bo;

num=(n>100000) ? 100000 : n;

env=e;
saw=sw;
dsaw=dsw;
res1=r1;
res2=r2;

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

gfx_x =20; gfx_y =10;  gfx_printf("%.0f",(100 * fParam2) );
gfx_x =80; gfx_y =10;  gfx_drawchar($'%');
gfx_x =130; gfx_y =10;  gfx_printf("Dynamics");

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

gfx_x =20; gfx_y =50;  gfx_printf("%.0f",(100 * fParam4) );
gfx_x =80; gfx_y =50;  gfx_drawchar($'%');
gfx_x =130; gfx_y =50;  gfx_printf("Glide");

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",(72*fParam5 - 36) );
gfx_x =80; gfx_y =70;  gfx_printf("semi");
gfx_x =130; gfx_y =70;  gfx_printf("Transpose");

gfx_x =20; gfx_y =90;  gfx_printf("%.0f",(srate/max) );
gfx_x =80; gfx_y =90;  gfx_printf("Hz");
gfx_x =130; gfx_y =90;  gfx_printf("Maximum");

gfx_x =20; gfx_y =110;  gfx_printf("%.1f",(60*fParam7 - 60) );
gfx_x =80; gfx_y =110;  gfx_printf("dB");
gfx_x =130; gfx_y =110;  gfx_printf("Trigger");

gfx_x =20; gfx_y =130;  gfx_printf("%.1f",(40*fParam8 - 20) );
gfx_x =80; gfx_y =130;  gfx_printf("dB");
gfx_x =130; gfx_y =130;  gfx_printf("Output");
