desc:HyperSat
author: Belovw
V0.17 19.03.2022
V0.21 04.05.2022 Pererabotan algoritm chetnyh garmonik
V0.22 05.05.2022 DC Offset dlya chetnyh garmonik
V0.23 05.05.2022 Bag Compute Kni
V0.24 05.05.2022 Even Harm Behavior
V0.25 05.05.2022 Global ON<>OFF

slider1:10<-20,24>HyperSat (dB)
slider2:0<0,1> Even Harm
slider3:0<0,17>Kni L 
slider4:0<0,17>Kni R
slider6:0<0,1,{ON,OFF}>Global

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
ext_noinit=1;
//out0=out1=0;

//fmax=3000;
fmax=srate/15;

Q=1;//0.46; // 0.5 // 0.8

knid0=0.00001;
knid1=0.00001;
countmax=srate/10;

aa=exp(-log(9)*1000/srate/300);
ar=exp(-log(9)*1000/srate/3000);

@slider
_global.hypersat=slider6;

HS=10^(slider1/20);
HS2=HS*2;
f=fmax;//-100*HS;


////////////////////////
/// Bi Quad Low Pass ///
////////////////////////

w=2*$pi*f/srate;
a=sin(w)/(2*Q);

b1=1-cos(w);
b0=b2=b1/2;

a0=1+a;
a1=-2*cos(w);
a2=1-a;

////////////////////////////
// Privedennye koeficenty //
////////////////////////////

b0p=b0/a0; 
b1p=b1/a0;
b2p=b2/a0;
a1p=a1/a0;
a2p=a2/a0;

/////////////////////////
/// Bi Quad High Pass ///
/// DC Offset         ///
/////////////////////////

w=2*$pi*20/srate; // High Pass 20 Hz
a=sin(w)/(2*0.7); // Q=0.7

b1=-1-cos(w);
b0=b2=-b1/2;

a0=1+a;
a1=-2*cos(w);
a2=1-a;

////////////////////////////
// Privedennye koeficenty //
////////////////////////////

b0d=b0/a0; 
b1d=b1/a0;
b2d=b2/a0;
a1d=a1/a0;
a2d=a2/a0;

S=min(max(0,slider2),1)/20;

@block
slider6=_global.hypersat;

@sample
_global.hypersat == 0 ? (

in0=spl0; in1=spl1;

//////////////////
/// Filter out ///
//////////////////


out0 = b0p*in0 + b1p*in01 + b2p*in02 - a1p*out01 - a2p*out02;
out1 = b0p*in1 + b1p*in11 + b2p*in12 - a1p*out11 - a2p*out12;

out02=out01 ; out01=out0;
out12=out11 ; out11=out1;

in02=in01 ; in01=in0 ;
in12=in11 ; in11=in1 ;

/////////////////
/// Saturator ///
/////////////////

outs0=out0+S;
outs1=out1+S;

e2f0=$e^(HS2*outs0);
e2f1=$e^(HS2*outs1);

hs0=(e2f0-1)/(e2f0+1)/HS;
hs1=(e2f1-1)/(e2f1+1)/HS;

/////////
// OUT //
/////////

spl0=in0-out0+hs0;
spl1=in1-out1+hs1;

///////////////
// DC Offset //
///////////////

S > 0 ? (
outd0 = b0d*spl0 + b1d*ind01 + b2d*ind02 - a1d*outd01 - a2d*outd02;
outd1 = b0d*spl1 + b1d*ind11 + b2d*ind12 - a1d*outd11 - a2d*outd12;

outd02=outd01 ; outd01=outd0;
outd12=outd11 ; outd11=outd1;

ind02=ind01 ; ind01=spl0 ;
ind12=ind11 ; ind11=spl1 ;

spl0=outd0;
spl1=outd1;
);

/////////
// Kni //
/////////

count > 0 ? (


kni0=1-(hs0+0.00000001)/(outs0+0.00000001);
kni1=1-(hs1+0.00000001)/(outs1+0.00000001);


kni0>knid0? knid0=knid0/aa: 
            knid0=knid0*ar;
            
kni1>knid1? knid1=knid1/aa: 
            knid1=knid1*ar;
count-=1;);

);
@gfx

slider3=ceil(1000*knid0)/10;
slider4=ceil(1000*knid1)/10;
count=countmax;
