slider1:100<-100,100,1>bias (%)
slider2:24<0,48,0.1>drive (dB)
slider3:0<-36,12,0.1>output (dB)
slider10:2<1,8,1>--oversampling
slider12:7<0,10,0.1>filter ---------- color
slider13:8<0,10,0.1>depth
slider14:5<0.5,10,0.1>width
//----------------------------------------------------------
slider20:1<0,1,1{off,on}>cab --------- mode
slider21:/Cabs:4x12 Classic.wav:IR
slider22:-18<-60,6,1>--preamp (dB)
slider23:1<0,1,1{no,yes}>--upsample impulse if required
slider24:0<0,1,1{mono,stereo}>channel mode
slider25:0,--Filter size
slider26:0,--FFT size
slider27:0,PDC delay

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

@init
ext_nodenorm=1;

mode=slider20;
stereo_mode=slider24;

last_aa=0;

function singlepole_set(ms)
instance(coeff)
(
coeff = exp(-1/(ms/1000*srate));
);

function singlepole(in,target)
instance(coeff)
(
in*coeff + target*(1-coeff);
);

function tanh(x) 
( 
x = exp(2*x);
(x - 1) / (x + 1);
);

//----------------------------------------------------------
fftsize=-1;
need_refft=1;
convsrc=128*1024;
lslider21=-1;
impbuf=256*1024;

pdc_delay=slider27;
pdc_bot_ch=0;
pdc_top_ch=2;

@slider
bias = -slider1*0.5;

input = 10^(slider2/20);
output = 10^((slider3-9.6)/20);

aasize=(slider10+0.5)|0;
aasize<1?aasize=1:aasize>256?aasize=256;

aasize != last_aa ? (

aasize>1 ? (
Q=0.707;
pos=0.9/aasize * $pi;

cpos=cos(pos);
spos=sin(pos);

alpha=spos/(2*Q);

sc = 1/( 1 + alpha);
b1 = (1-cpos) * sc;
b2 = b0 = b1*0.5;
a1 = -2 * cpos * sc;
a2 = (1-alpha)*sc;
);
last_aa=aasize;

hist4=hist5=hist6=hist7=0;
hist8=hist9=hist10=hist11=0;
hist12=hist13=hist14=hist15=0;
hist16=hist17=hist18=hist19=0;
);

AP1Freq = 5 * (2 ^(slider12)) + 50;
depth = slider13/20;
idepth = 1 - abs(depth);
width = slider14;

LP1period = 300/(5248*width);
HP1freq = 800 / width;
HP1period = 1000/HP1freq;

AP1_dsc = AP1Freq*2/srate;
AP1_coef = (1-AP1_dsc)/(1+AP1_dsc);

LP1.singlepole_set(LP1period);
HP1.singlepole_set(HP1period);

//----------------------------------------------------------

tmp=slider21|0;
tmp != lslider21 ?
(
lslider21=tmp;

filehandle=file_open(slider21);
impbuf_l=impbuf_nch=impbuf_srate=0;
filehandle > 0 ? 
(
file_riff(filehandle,impbuf_nch,impbuf_srate);
impbuf_nch ?
(
impbuf_l=(file_avail(filehandle)/impbuf_nch)|0; 
need_refft=1; 
file_mem(filehandle,impbuf,impbuf_l*impbuf_nch);
);
file_close(filehandle);
);
);

!mode != !slider20 ? ( need_refft=1; mode=slider20; );
!stereo_mode != !slider24 ? ( need_refft=1; stereo_mode=slider24; );
useresample != slider23 ? (useresample=slider23; need_refft=1; );
preamp=slider22 <= -60.0 ? 0.0 : 10 ^ (slider22 / 20);

slider25=filtersize;
slider26=fftsize;
pdc_delay=slider27;
pdc_bot_ch=0;
pdc_top_ch=2;

//----------------------------------------------------------
@block
mode == 1 ? (

need_refft ? (  // prepare convolution source, here...
useresample && srate > impbuf_srate && impbuf_srate > 1 ? 
(
filtersize = ((srate*impbuf_l)/impbuf_srate)|0;
isc=impbuf_srate/srate;
)
: 
(
filtersize=impbuf_l;
isc=1;
);

fftsize=32;

while(
filtersize > fftsize*0.5 ? 
(
fftsize += fftsize;
) : 0;
);
slider25=filtersize;
slider26=fftsize;
sliderchange(slider25);
sliderchange(slider26); 
chunksize=fftsize-filtersize-1; // size of chunk size of audio to use
chunksize2=chunksize*2;

slider27=chunksize;
sliderchange(slider27);

bpos=0; 
curblock=0;
lastblock=64*1024;
invfsize=1/fftsize;
i=0;
i2=0;
loop(min(fftsize,filtersize),
ipos=i|0;
ipart=(i-ipos);
convsrc[i2]=impbuf[ipos*impbuf_nch]*(1-ipart) + impbuf[(ipos+1)*impbuf_nch]*ipart;
convsrc[i2+1]=stereo_mode ? 0.0 : (impbuf[(ipos+1)*impbuf_nch-1]*(1-ipart) +
impbuf[(ipos+1)*impbuf_nch-1]*(ipart));
i += isc;
i2+=2;
);
loop(fftsize-filtersize,
convsrc[i2]=convsrc[i2+1]=0;
i2+=2;
);
fft(convsrc,fftsize);
i=0;
loop(fftsize*2, convsrc[i] *= invfsize; i+=1; );
need_refft=0;
);

):(
slider27=0;
sliderchange(slider27);
);

@sample
stereo_mode==0 ? (
sspos=0;
src0=(spl0+spl1)*0.5;

loop(aasize,
// run input filter
aasize > 1 ? (
sspl0 = src0*b0 + hist4*b1 + hist5*b2 - hist6*a1 - hist7*a2;
hist5=hist4; hist4=src0; hist7=hist6; hist6=sspl0;
) : (
sspl0=src0;
);

in=(sspl0)*input;
mu = atan(1/(0.001+sign(in)));
E = (75/$pi)*log(1+abs(in)*exp(100*(1+mu+(100-bias)/sqrt(75^2))));
P = (E/1000)*(1+sign(E));
out = tanh(in*P);
sspl0=out*output;

// run output filters
aasize > 1 ? (

(sspos+=1)==1 ? (
spl0 = sspl0*b0 + hist12*b1 + hist13*b2 - hist14*a1 - hist15*a2;
spl1 = spl0;
hist13=hist12; hist12=sspl0; hist15=hist14; hist14=(spl0+spl1)*0.5;
) : (
tmp0 = sspl0*b0 + hist12*b1 + hist13*b2 - hist14*a1 - hist15*a2;
hist13=hist12; hist12=sspl0; hist15=hist14; hist14=tmp0;
);
) : (
spl0=sspl0;
spl1=spl0;
);
);
);

stereo_mode==1 ? (
sspos=0;
src0=spl0;
src1=spl1;

loop(aasize,

// run input filter
aasize > 1 ? (
sspl0 = src0*b0 + hist4*b1 + hist5*b2 - hist6*a1 - hist7*a2;
hist5=hist4; hist4=src0; hist7=hist6; hist6=sspl0;

sspl1 = src1*b0 + hist8*b1 + hist9*b2 - hist10*a1 - hist11*a2;
hist9=hist8; hist8=src1; hist11=hist10; hist10=sspl1;
) : (
sspl0=src0; 
sspl1=src1;
);

in0=(sspl0)*input;
mu0 = atan(1/(0.001+sign(in0)));
E0 = (75/$pi)*log(1+abs(in0)*exp(100*(1+mu0+(100-bias)/sqrt(75^2))));
P0 = (E0/1000)*(1+sign(E0));
out0 = tanh(in0*P0);
sspl0=out0*output;

in1=(sspl1)*input;
mu1 = atan(1/(0.001+sign(in1)));
E1 = (75/$pi)*log(1+abs(in1)*exp(100*(1+mu1+(100-bias)/sqrt(75^2))));
P1 = (E1/1000)*(1+sign(E1));
out1 = tanh(in1*P1);
sspl1=out1*output;

// run output filters
aasize > 1 ? (

(sspos+=1)==1 ? (
spl0 = sspl0*b0 + hist12*b1 + hist13*b2 - hist14*a1 - hist15*a2;
spl1 = sspl1*b0 + hist16*b1 + hist17*b2 - hist18*a1 - hist19*a2;

hist13=hist12; hist12=sspl0; hist15=hist14; hist14=spl0;
hist17=hist16; hist16=sspl1; hist19=hist18; hist18=spl1;
) : (
tmp0 = sspl0*b0 + hist12*b1 + hist13*b2 - hist14*a1 - hist15*a2;
tmp1 = sspl1*b0 + hist16*b1 + hist17*b2 - hist18*a1 - hist19*a2;

hist13=hist12; hist12=sspl0; hist15=hist14; hist14=tmp0;
hist17=hist16; hist16=sspl1; hist19=hist18; hist18=tmp1;
);
) : (
spl0=sspl0;
spl1=sspl1;
);
);
);

x1 = spl0;
ly1 = AP1_coef * (ly1 + x1) - lx1; lx1 = x1;
ly2 = AP1_coef * (ly2 + ly1) - lx2; lx2 = ly1;

rx = spl1;
ry1 = AP1_coef * (ry1 + rx) - rx1; rx1 = rx;
ry2 = AP1_coef * (ry2 + ry1) - rx2; rx2 = ry1;

colored_l = idepth*spl0 + depth*ly2;
colored_r = idepth*spl1 + depth*ry2;

LP1_l = LP1.singlepole(LP1_l,colored_l);
LP1_r = LP1.singlepole(LP1_r,colored_r);

HP1_l = LP1_l - HP1_l_L = HP1.singlepole(HP1_l_L,LP1_l);
HP1_r = LP1_r - HP1_r_L = HP1.singlepole(HP1_r_L,LP1_r);

out0 = HP1_l;
out1 = HP1_r;

//----------------------------------------------------------
mode == 1 ? (

filtersize > 0 ?
(
bpos >= chunksize ? 
(
t=lastblock;
lastblock=curblock;
curblock=t;

memset(curblock+chunksize*2,0,(fftsize-chunksize)*2);

fft(curblock,fftsize);
convolve_c(curblock,convsrc,fftsize);

ifft(curblock,fftsize);

bpos=0;
);

// save sample
bp2=bpos*2;
lastblock[bp2]=out0*preamp;
lastblock[bp2+1]=stereo_mode ? (out1*preamp) : 0;

spl0=curblock[bp2];
spl1=curblock[bp2+1];

bpos < fftsize-chunksize ? 
(
spl0+=lastblock[chunksize2+bp2];
spl1+=lastblock[chunksize2+bp2+1];
);

bpos += 1;
);

):(
spl0=out0;
spl1=stereo_mode ? out1 : out0;
);
