// (C) 2008-2009, Lubomir I. Ivanov

// NO WARRANTY IS GRANTED. THIS PLUG-IN IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
// WARRANTY OF ANY KIND. NO LIABILITY IS GRANTED, INCLUDING, BUT NOT LIMITED TO,
// ANY DIRECT OR INDIRECT,  SPECIAL,  INCIDENTAL OR CONSEQUENTIAL DAMAGE ARISING
// OUT OF  THE  USE  OR INABILITY  TO  USE  THIS PLUG-IN,  COMPUTER FAILTURE  OF
// MALFUNCTION INCLUDED.  THE USE OF THE SOURCE CODE,  EITHER  PARTIALLY  OR  IN
// TOTAL, IS ONLY GRANTED,  IF USED IN THE SENSE OF THE AUTHOR'S INTENTION,  AND
// USED WITH ACKNOWLEDGEMENT OF THE AUTHOR. FURTHERMORE IS THIS PLUG-IN A  THIRD
// PARTY CONTRIBUTION,  EVEN IF INCLUDED IN REAPER(TM),  COCKOS INCORPORATED  OR
// ITS AFFILIATES HAVE NOTHING TO DO WITH IT.  LAST BUT NOT LEAST, BY USING THIS
// PLUG-IN YOU RELINQUISH YOUR CLAIM TO SUE IT'S AUTHOR, AS WELL AS THE CLAIM TO
// ENTRUST SOMEBODY ELSE WITH DOING SO.
// 
// Released under GPL:
// <http://www.gnu.org/licenses/>.

//******************************************************************************
// References: "filters3.txt" - modified
// Presence EQ as given in
// James A. Moorer
// The manifold joys of conformal mapping:
// applications to digital filtering in the studio
// JAES, Vol. 31, No. 11, 1983 November
//******************************************************************************

desc:PresenceEQ (Moorer)

slider1:0<0,1,1{Stereo,Mono}>Processing
slider2:7700<3100,18500,0.1>Frequency (Hz)
slider3:0<-15,15,0.01>Cut/Boost (dB)
slider4:0.20<0.07,0.40,0.0001>BW (Min/Max)
slider5:0<-25,25,0.05>Output (dB)

@init

yl=x1l=x2l=y1l=y2l=yr=x1r=x2r=y1r=y2r=SPN=0;

@slider

mono = slider1;
cf = slider2/srate; 
boost = slider3;
bw = slider4; // removed "/srate" here and added BW in proper ranges
outgain = 10^(slider5/20);
ca = tan($pi*(cf-0.25));
A = 10^(boost/20);

(boost < 6.0) && (boost > -6.0) ? (
  F = sqrt(A);
) : ( 
  A > 1 ? (
    F = A/sqrt(2);
  ) : (
    F = A*sqrt(2);
  );
);
T = tan(2*$pi*bw);
as2 = ca*ca;
as4 = as2*as2;
d = 2*as2*T;
sn = (1 + as4)*T;
cs = (1 - as4);
mag = sqrt(sn*sn + cs*cs);
//"d /= mag" prevents adding any boost at all - replaced with d=mag;
d = mag;
delta = atan2(sn,cs);
asnd = asin(d);
theta = 0.5*($pi - asnd - delta);
tmp = 0.5*(asnd-delta);
tmp > 0 && tmp < theta ? (  
  theta = tmp;  
);
xfmbw = theta/(2*$pi);

C = 1/tan(2*$pi*xfmbw);
F2 = F*F;
tmp = A*A - F2;
abs(tmp) <= SPN ? (
  alphad = C;
) : (  
  alphad = sqrt(C*C*(F2-1)/tmp);  
);
alphan = A*alphad;
a2plus1 = 1 + as2;
ma2plus1 = 1 - as2;

a0 = a2plus1 + alphan*ma2plus1;
a1 = 4.0*ca;
a2 = a2plus1 - alphan*ma2plus1;
b0 = a2plus1 + alphad*ma2plus1;
b2 = a2plus1 - alphad*ma2plus1;

recipb0 = 1/b0;
a0 *= recipb0;
a1 *= recipb0;
a2 *= recipb0;
b1 = a1;
b2 *= recipb0;

b1 = -b1;
b2 = -b2;

@sample

//mono
mono == 1 ? (
xl = (spl0+spl1)/2;
 
yl = a0*xl + a1*x1l + a2*x2l + b1*y1l + b2*y2l;
x2l = x1l;
x1l = xl;
y2l = y1l;
y1l = yl;

spl0=spl1=yl*outgain;

//stereo
) : (
xl = spl0;
xr = spl1;
 
yl = a0*xl + a1*x1l + a2*x2l + b1*y1l + b2*y2l;
x2l = x1l;
x1l = xl;
y2l = y1l;
y1l = yl;

yr = a0*xr + a1*x1r + a2*x2r + b1*y1r + b2*y2r;
x2r = x1r;
x1r = xr;
y2r = y1r;
y1r = yr;

spl0=yl*outgain;
spl1=yr*outgain;

);
