/*
Leslie

Rotary speaker simulator.

Speed		Rotor speed: Stop / Slow / Fast
Lo Width		Low rotor pan modulation
Lo Throb		Low rotor amplitude modulation
Hi Width		High rotor pan modulation
Hi Depth		High rotor frequency modulation (doppler)
Hi Throb		High rotor amplitude modulation
X-Over		Crossover frequency between high and low rotors
Output		Level trim
Speed		Fine control for rotor speed
*/

slider1:1<0,2,1>speed mode
slider2:0.5<0,1,0.01>lo width
slider3:0.48<0,1,0.01>lo throb
slider4:0.7<0,1,0.01>hi width
slider5:0.6<0,1,0.01>hi depth
slider6:0.7<0,1,0.01>hi throb
slider7:0.5<0,1,0.01>x-over
slider8:0.5<0,1,0.01>output
slider9:0.6<0,1,0.01>speed
slider10:0<0,3,1{--------,slow,fast,nice}>presets

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

@init
ext_noinit = 1;

hpos = 0;
size = 256;
hbuf = 256;
memset(hbuf, 0, size);

fbuf1 = fbuf2 = 0;
twopi = 6.2831853;

chp = dchp = clp = dclp = shp = dshp = slp = dslp = 0;

lspd = 0;
hspd = 0;
lphi = 0;
hphi = 1.6;

ifs = 1 / srate;

dchp=0;
dclp=0;
dshp=0;

k1 = 32;
k0 = 0.03125; // 1/k1
k = 0;

@slider
fparam0 = slider1; //speed mode: stop,slow,fast
fparam1 = slider2; // lo width
fparam2 = slider3; // lo level
fparam3 = slider4; // hi width
fparam4 = slider5; // hi depth
fparam5 = slider6; // hi level
fparam6 = slider7; // x-over
fparam7 = slider8; // output
fparam8 = slider9; // speed
fparam9 = slider10; // program

fParam9 != old_fParam9 ? (
memset(hbuf, 0, size);
old_fParam9 = fParam9;
);

// add your own presets...(and update slider10 !)
fparam9==1 ? ( //slow
fparam0 = 1; slider1=fParam0;
fparam1 = 0.5; slider2=fParam1;
fparam2 = 0.48; slider3=fParam2;
fparam3 = 0.7; slider4=fParam3;
fparam4 = 0.75; slider5=fParam4;
fparam5 = 0.57; slider6=fParam5;
fparam6 = 0.5; slider7=fParam6;
);
fparam9==2 ? ( //fast
fparam0 = 2; slider1=fParam0;
fparam1 = 0.5; slider2=fParam1;
fparam2 = 0.48; slider3=fParam2;
fparam3 = 0.7; slider4=fParam3;
fparam4 = 0.60; slider5=fParam4;
fparam5 = 0.70; slider6=fParam5;
fparam6 = 0.5; slider7=fParam6;
);
fparam9==3 ? ( //nice
fparam0 = 1; slider1=fParam0;
fparam1 = 0.85; slider2=fParam1;
fparam2 = 0.05; slider3=fParam2;
fparam3 = 0.45; slider4=fParam3;
fparam4 = 0.75; slider5=fParam4;
fparam5 = 0.20; slider6=fParam5;
fparam6 = 0.35; slider7=fParam6;
);

spd = twopi * ifs * 2 * fparam8 * 0.1;

filo = 1 - pow(10, fparam6 * (2.27 - 0.54 * fparam6) - 1.92);

(fparam0<=1) ?
(
(fparam0<0.1) ? //stop
(
lset = 0; hset = 0;
lmom = 0.12; hmom = 0.1;
)
: //low speed
(
//lset = 0.49; hset = 0.66;
lset = 1.49; hset = 1.66;
lmom = 0.27; hmom = 0.18;
);
)
: //high speed
(
//lset = 5.31; hset = 6.4;
lset = 2.31; hset = 3.4;
lmom = 0.14; hmom = 0.09;
);
hmom = pow(10, -ifs / hmom);
lmom = pow(10, -ifs / lmom); 
hset *= spd;
lset *= spd;

gain = 0.4 * pow(10, 2 * fparam7 - 1);
lwid = fparam1 * fparam1;
llev = gain * 0.9 * fparam2 * fparam2;
hwid = fparam3 * fparam3;
hdep = fparam4 * fparam4 * srate / 760;
hlev = gain * 0.9 * fparam5 * fparam5;

@sample
hl=hlev;
hm=hmom;
hw=hwid;
hd=hdep;
ll=llev;
lm=lmom;
lw=lwid;

ht=hset*(1-hm);
lt=lset*(1-lm);

chp = cos(hphi); chp *= chp * chp;
clp = cos(lphi);
shp = sin(hphi);
slp = sin(lphi);

a = (spl0+spl1)*0.5; //*0.5 ???

(k>0) ? (
k-=1;
):(
lspd = (lm * lspd) + lt; // tend to required speed
hspd = (hm * hspd) + ht;
lphi += k1 * lspd;
hphi += k1 * hspd;

dchp = cos(hphi + k1*hspd);
dchp = k0 * (dchp * dchp * dchp - chp); // sin^3 level mod
dclp = k0 * (cos(lphi + k1*lspd) - clp);
dshp = k0 * (sin(hphi + k1*hspd) - shp);
dslp = k0 * (sin(lphi + k1*lspd) - slp);

k=k1;
);

fbuf1 = filo * (fbuf1 - a) + a; // crossover
fbuf2 = filo * (fbuf2 - fbuf1) + fbuf1;
h = (gain - hl * chp) * (a - fbuf2); // volume
l = (gain - ll * clp) * fbuf2;

(hpos>0) ? hpos-=1 : hpos=200; 
hint = hpos + hd * (1 + chp);
hdd = hint|0; 
hint = hint - hdd;
hdd2 = hdd + 1;
(hdd>199) ? ( (hdd>200) ? hdd -= 201; hdd2 -= 201; );

buf[hbuf+hpos] = h;
a = buf[hbuf+hdd];
h += a + hint * ( buf[hbuf+hdd2] - a);

c = l + h;
d = l + h;
h *= hw * shp;
l *= lw * slp;
d += l - h;
c += h - l;

spl0 = c;
spl1 = d;

chp += dchp;
clp += dclp;
shp += dshp;
slp += dslp;

lphi = ((lphi+(k1-k)*lspd)); lphi>=twopi ? lphi-=twopi;
hphi = ((hphi+(k1-k)*hspd)); hphi>=twopi ? hphi-=twopi;
(abs(fbuf1)<=0.0000000001) ? fbuf1=0; 
(abs(fbuf2)<=0.0000000001) ? fbuf2=0;

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

(fparam0<=1) ?
(
(fparam0<0.1) ? //stop
(
gfx_x =20; gfx_y =10;  gfx_printf("Stop")
)
: //low speed
(
gfx_x =20; gfx_y =10;  gfx_printf("Slow")
);
)
: //high speed
(
gfx_x =20; gfx_y =10;  gfx_printf("Fast")
);
gfx_x =110; gfx_y =10;  gfx_printf("Speed Mode");

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

gfx_x =20; gfx_y =30;  gfx_printf("%.0f",(100 * fparam1) );
gfx_x =70; gfx_y =30;  gfx_drawchar($'%');
gfx_x =110; gfx_y =30;  gfx_printf("Lo Width");

gfx_x =20; gfx_y =50;  gfx_printf("%.0f",(100 * fparam2) );
gfx_x =70; gfx_y =50;  gfx_drawchar($'%');
gfx_x =110; gfx_y =50;  gfx_printf("Lo Throb");

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

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",(100 * fparam3) );
gfx_x =70; gfx_y =70;  gfx_drawchar($'%');
gfx_x =110; gfx_y =70;  gfx_printf("Hi Width");

gfx_x =20; gfx_y =90;  gfx_printf("%.0f",(100 * fparam4) );
gfx_x =70; gfx_y =90;  gfx_drawchar($'%');
gfx_x =110; gfx_y =90;  gfx_printf("Hi Depth");

gfx_x =20; gfx_y =110;  gfx_printf("%.0f",(100 * fparam5) );
gfx_x =70; gfx_y =110;  gfx_drawchar($'%');
gfx_x =110; gfx_y =110;  gfx_printf("Hi Throb");

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

gfx_x =20; gfx_y =130;  gfx_printf("%.0f",(10*(pow(10,1.179 + fparam6))|0) );
gfx_x =70; gfx_y =130;  gfx_printf("Hz");
gfx_x =110; gfx_y =130;  gfx_printf("X-Over");

gfx_x =20; gfx_y =150;  gfx_printf("%.1f",(40 * fparam7 - 20) );
gfx_x =70; gfx_y =150;  gfx_printf("dB");
gfx_x =110; gfx_y =150;  gfx_printf("Output");

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

gfx_x =20; gfx_y =170;  gfx_printf("%.0f",(200 * fparam8) );
gfx_x =70; gfx_y =170;  gfx_drawchar($'%');
gfx_x =110; gfx_y =170;  gfx_printf("Speed");
