// prepared for adding more distortion types...

slider1:0<0,6,1{DI,speaker sim,radio,mesa boogie 1,mesa boogie 8,marshall 4x12 celestion,scooped-out metal 4x12}>select
slider2:0<0,1,0.01>drive
slider3:0.5<0,1,0.01>bias
slider4:0.5<0,1,0.01>output
slider5:0<0,1,1{mono,stereo}>mode
slider6:0.4<0,1,0.01>hpf freq
slider7:0.5<0,1,0.01>hpf res
slider8:0<0,1,1{soft saturation,clipping distortion}>drive mode

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

@init
ext_noinit = 1;

size = 1024;
buffer = size;
memset(buffer, 0, size+2);
buffer2 = size;
memset(buffer2, 0, size+2);

bufpos = 0;

ff1=0; ff2=0; ff3=0; ff4=0; ff5=0;
ff6=0; ff7=0; ff8=0; ff9=0; ff10=0;
hh0 = hh1 = 0;
hhf = hhq = 0; // ???

r = 0.999;
j = r * r - 1;

//itma=a;
//itma2=a2;
//otma=otma2=0;

itm1=itm2=otm1=otm2=0;

@slider
fParam1 = slider1; //select
fParam2 = slider2; //drive
fParam3 = slider3; //bias
fParam4 = slider4; //output
fParam5 = slider5; //stereo
fParam6 = slider6/20; //hpf freq
fParam7 = slider7; //hpf res
fParam8 = slider8; //drive mode

(fParam5>0.5) ? ( ster=1; ):( ster=0; );

(
fParam1 == 0 ? ( //DI
drive = 1;
trim = 0.5;
lpf = 18000;
mix1 = 0;
mix2 = 0;
del1 = 0;
del2 = 0;
hpf = 25;
outm = 1;
outst = 0.5;
) :
fParam1 == 1 ? ( //speaker sim
trim = 0.53;
lpf = 2700;
mix1 = 0;
mix2 = 0;
del1 = 0;
del2 = 0;
hpf = 382;
outm = 1.3;
outst = 0.65;
) :
fParam1 == 2 ? ( //radio
trim = 1.1;
lpf = 1685;
mix1 = -1.7;
mix2 = 0.82; 
del1 = (srate / 6546)|0;
del2 = (srate / 4315)|0;
hpf = 25;
outm = 0.78;
outst = 0.39;
) :
fParam1 == 3 ? ( //mesa boogie 1
trim = 0.98;
lpf = 1385;
mix1 = -0.53;
mix2 = 0.21;
del1 = (srate / 7345)|0;
del2 = (srate / 1193)|0;
hpf = 25;
outm = 0.94;
outst = 0.47;
) :
fParam1 == 4 ? ( //mesa boogie 8
trim = 0.96;
lpf = 1685;
mix1 = -0.85;
mix2 = 0.41; 
del1 = (srate / 6546)|0;
del2 = (srate / 3315)|0;
hpf = 25;
outm = 1.02;
outst = 0.51;
) :
fParam1 == 5 ? ( //marshall 4x12 celestion
trim = 0.59;
lpf = 2795; 
mix1 = -0.29;
mix2 = 0.38;
del1 = (srate / 982)|0;
del2 = (srate / 2402)|0;
hpf = 459;
outm = 1.5;
outst = 0.75;
) :
fParam1 == 6 ? ( //scooped-out metal 4x12
trim = 0.30;
lpf = 1744;
mix1 = -0.96;
mix2 = 1.6; 
del1 = (srate / 356)|0;
del2 = (srate / 1263)|0;
hpf = 382;
outm = 1.56;
outst = 0.78;
);
);

mode = (fParam8<0.5) ? 1 : 0;

(mode) ? ( //soft clipping
fParam2 = 0.5*(fParam2-1);
drive = pow(10, 2 + 6 * fParam2);
trim *= min(0.55 + 150 * pow(fParam2,4),10);
):( //hard clipping
fParam2 = 0.5*(fParam2+1);
drive = 1;
clip = 11.7 - 16*fParam2;
(fParam2>0.7) ? (
drive = pow(10, 7*fParam2 - 4.9);
clip = 0.5;
);
);

//bias = 1.2 * fParam3 - 0.6;
bias = 0.1 * fParam3 - 0.05;

(fParam8>0.5) ? (
bias /= (1 + 3 * (fParam2+1));
):(
bias /= (1 + 3 * (1-fParam2));
);
trim *= pow(10, 2*fParam4 - 1);
(ster) ? trim*=2;

hhf = fParam6;
hhq = 1.1 - fParam7;
(fParam6>0.025) ? drive = drive * (1 + 0.1 * drive);

k0 = (2 - 2 * r * r * cos(0.647 * lpf /srate )); //lowpass filter
filterlp = ((sqrt(k0*k0 - 4*j*j) - k0) / (2*j));

k1 = (2 - 2 * r * r * cos(0.647 * hpf /srate )); //highpass filter
filterhp = ((sqrt(k1*k1 - 4*j*j) - k1) / (2*j));

@sample
o=filterlp;
i=1-filterlp;
o2=filterhp;

f1=ff1;
f2=ff2;
f3=ff3;
f4=ff4;
f5=ff5;
f6=ff6;
f7=ff7;
f8=ff8;
f9=ff9;
f10=ff10;

hf0=hhf;
hf1=hhf;
hq0=hhq;
hq1=hhq;
h00=hh0;
h01=hh0;
h10=hh1;
h11=hh1;

bp = bufpos;

trm = trim * i * i * i * i;

in0 = spl0;
in1 = spl1;

(ster == 1) ? ( //stereo

a = drive * (2 * in0 + bias) * 0.707;
a2 = drive * (2 * in1 + bias) * 0.707;

//otma=0.999*otma + a - itma; itma=a; a=otma;
//otma2=0.999*otma2 + a2 - itma2; itma2=a2; a2=otma2;

(mode) ? ( //softclip
b = (a>0) ? a : -a;
b2 = (a2>0) ? a2 : -a2;
b = a / (1 + b);
b2 = a2 / (1+ b2);
):( //distort
b = (a>clip) ? clip : a;
b2 = (a2>clip) ? clip : a2;
b = (a<-clip) ? -clip : b;
b2 = (a2<-clip) ? -clip : b2;
);

h00 += hf0 * (h10 + b); //resonant highpass
h10 -= hf0 * (h00 + hq0 * h10);
b += h10;

h01 += hf1 * (h11 + b2); //resonant highpass
h11 -= hf1 * (h01 + hq1 * h11);
b2 += h11;

buf[buffer + bp] = b;
buf2[buffer2 + bp] = b2; 
b += (mix1* buf[buffer+((bp+del1)%1000)]) + (mix2* buf[buffer+((bp+del2)%1000)]);
b2 += (mix1* buf2[buffer2+((bp+del1)%1000)]) + (mix2* buf2[buffer2+((bp+del2)%1000)]);

f1 = o * f1 + trm * b; f6 = o * f6 + trm * b2; //-24dB/oct filter
f2 = o * f2 +  f1; f7 = o * f7 +  f6;
f3 = o * f3 +  f2; f8 = o * f8 +  f7;
f4 = o * f4 +  f3; f9 = o * f9 +  f8;

f5 = o2 * (f5 - f4) + f4; f10 = o2 * (f10 - f9) + f9; //highpass
b = f4 - f5; b2 = f9 - f10;

//(bp==0) ? bufpos = 999 : bufpos= bp - 1; //buffer position
bp = (bp==0) ? 999 : bp - 1; //buffer position

out0 = b * outst;	
out1 = b2 * outst;

):( //mono

a = drive * (in0 + in1 + bias) * 0.707;

//otma=0.999*otma + a - itma; itma=a; a=otma;

(mode) ? ( //soft clip
b = (a>0) ? a : -a;
b = a / (1 + b);
):( //distort
b = (a>clip) ? clip : a;
b = (a<-clip) ? -clip : b;
);

h00 += hf0 * (h10 + b); //resonant highpass
h10 -= hf0 * (h00 + hq0 * h10);
b += h10;

buf[buffer + bp] = b; 
b += (mix1* buf[buffer+((bp+del1)%1000)]) + (mix2* buf[buffer+((bp+del2)%1000)]);
    
f1 = o * f1 + trm * b; //-24dB/oct filter
f2 = o * f2 +  f1;
f3 = o * f3 +  f2;
f4 = o * f4 +  f3;

f5 = o2 * (f5 - f4) + f4; //highpass
b = f4 - f5;

bp = (bp==0) ? 999 : bp - 1; //buffer position

out0 = b * outm;	
out1 = b * outm;

);

bufpos = bp;

spl0 = out0;
spl1 = out1;

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

(abs(f1)<0.0000000001) ? ( ff1=0; ff2=0; ff3=0; ff4=0; ff5=0; ):( ff1=f1; ff2=f2; ff3=f3; ff4=f4; ff5=f5; );
(abs(f6)<0.0000000001) ? ( ff6=0; ff7=0; ff8=0; ff9=0; ff10=0; ):( ff6=f6; ff7=f7; ff8=f8; ff9=f9; ff10=f10; );
(abs(h00)<0.0000000001) ? ( hh0 = hh1 = 0; ):( hh0=h00; hh1=h10; );

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

gfx_x =20; gfx_y =10;  (mode == 1) ? ( gfx_printf("%.0f",(200 * fParam2 + 100) ); ):( gfx_printf("%.0f",(200 * fParam2 -100) ); );
gfx_x =60; gfx_y =10;  gfx_drawchar($'%');
gfx_x =90; gfx_y =10;  (fParam2>0.7) ? ( gfx_printf("Drive ***"); ):( gfx_printf("Drive"); );

gfx_x =20; gfx_y =30;  gfx_printf("%.0f",(200 * fParam3 - 100) );
gfx_x =60; gfx_y =30;  gfx_drawchar($'%');
gfx_x =90; gfx_y =30;  gfx_printf("Bias");

gfx_x =20; gfx_y =50;  gfx_printf("%.1f",(40 * fParam4 - 20) );
gfx_x =60; gfx_y =50;  gfx_printf("dB");
gfx_x =90; gfx_y =50;  gfx_printf("Output");

gfx_x =20; gfx_y =70;  gfx_printf("%.0f",(100 * fParam6 * 20) );
gfx_x =60; gfx_y =70;  gfx_drawchar($'%');
gfx_x =90; gfx_y =70;  (fParam6>0.025) ? ( gfx_printf("HP Filter ~ Drive ***"); ):( gfx_printf("HP Filter"); );

gfx_x =20; gfx_y =90;  gfx_printf("%.0f",(100 * fParam7) );
gfx_x =60; gfx_y =90;  gfx_drawchar($'%');
gfx_x =90; gfx_y =90;  gfx_printf("HP Res");
