Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Filter.h
00001 #ifndef GAMMA_FILTER_H_INC
00002 #define GAMMA_FILTER_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 #include "Gamma/ipl.h"
00008 #include "Gamma/scl.h"
00009 
00010 #include "Gamma/Containers.h"
00011 //#include "Gamma/Strategy.h"
00012 #include "Gamma/Sync.h"
00013 #include "Gamma/Types.h"
00014 
00015 namespace gam{
00016 
00017 
00019 enum FilterType{
00020     LOW_PASS,           
00021     HIGH_PASS,          
00022     BAND_PASS,          
00023     BAND_PASS_UNIT,     
00024     BAND_REJECT,        
00025     ALL_PASS            
00026 //  COMB_FBK_EVEN,
00027 //  COMB_FBK_ODD,
00028 //  COMB_FFD_EVEN,
00029 //  COMB_FFD_ODD
00030 };
00031 
00032 
00033 
00035 template <class T>
00036 inline T poleRadius(T bw, double ups){ return ::exp(-M_PI * bw * ups); }
00037 //return (T)1 - (M_2PI * bw * ups); // linear apx for fn < ~0.02
00038 
00040 template <class T>
00041 inline T freqToRad(T freq, double ups){ return scl::clip(freq * ups, 0.499) * M_PI; }
00042 
00043 
00044 
00046 
00059 template<class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00060 class AllPass1 : public Ts {
00061 public:
00064     AllPass1(Tp frq=1000);
00065 
00066     void freq (Tp v);       
00067     void freqF(Tp v);       
00068     void zero(){ d1=Tv(0); }
00069     
00070     Tv operator()(Tv input);
00071     
00072     Tv high(Tv input);      
00073     Tv low (Tv input);      
00074     
00075     Tp freq();              
00076     
00077     virtual void onResync(double r);
00078     
00079 protected:
00080     Tv d1;      // once delayed value
00081     Tp c;       // feed coefficient
00082     Tp mFreq;
00083 };
00084 
00085 
00087 
00100 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00101 class Biquad : public Ts{
00102 public:
00103 
00107     Biquad(Tp frq = Tp(1000), Tp res = Tp(1), FilterType type = LOW_PASS);
00108 
00110     void coef(Tp a0, Tp a1, Tp a2, Tp b0, Tp b1, Tp b2);
00111 
00112     void freq(Tp v);                    
00113     void res(Tp v);                     
00114     void set(Tp frq, Tp res);           
00115     void set(Tp frq, Tp res, FilterType type);  
00116     void type(FilterType type);         
00117     void zero();                        
00118 
00119     Tv operator()(Tv i0);               
00120     Tv nextBP(Tv i0);                   
00121     
00122     Tp freq() const { return mFreq; }   
00123     Tp res() const { return mRes; }     
00124     FilterType type() const { return mType; }   
00125     
00126     virtual void onResync(double r);
00127 
00128 protected:
00129     Tp mA0, mA1, mA2, mB0, mB1, mB2;    // ffd and fbk coefficients
00130     Tv d1, d2;      // inner sample delays
00131     Tp mFreq, mRes; // center frequency, resonance
00132     FilterType mType;
00133     Tp mReal, mImag;    // real, imag components of center frequency
00134     Tp mAlpha;
00135     Tp mFrqToRad;
00136 };
00137 
00138 
00139 
00141 
00145 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00146 class BlockDC : public Ts{
00147 public:
00148 
00150     BlockDC(Tp width=35): d1(0), mWidth(width){ Ts::initSynced(); }
00151 
00153     Tv operator()(Tv i0){       
00154         i0 += d1*mB1; Tv o0 = i0-d1; d1 = i0; return o0;
00155     }
00156 
00158     void width(Tp v){
00159         mWidth = v; mB1 = poleRadius(v, Ts::ups());
00160     }
00161 
00162     void zero(){ d1=0; }
00163 
00164     virtual void onResync(double r){ width(mWidth); }
00165 
00166 protected:
00167     Tv d1; Tp mWidth, mB1;
00168 };
00169 
00170 
00171 
00173 
00177 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00178 class BlockNyq : public BlockDC<Tv,Tp,Ts>{
00179 public:
00180 
00182     BlockNyq(Tp width=35): Base(width){}
00183 
00185     Tv operator()(Tv i0){       
00186         i0 += d1*mB1; Tv o0 = i0-d1; d1 =-i0; return o0;
00187     }
00188 
00189 protected:
00190     typedef BlockDC<Tv,Tp,Ts> Base;
00191     using Base::d1; using Base::mB1;
00192 };
00193 
00194 
00195 
00197 
00201 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00202 class Filter2 : public Ts{
00203 public:
00204 
00206     void freq(Tp v){ freqRef(v); }
00207 
00209     void width(Tp v){
00210         mWidth = v;
00211         mRad = poleRadius(mWidth, Ts::ups());
00212         cd2 = -mRad * mRad;
00213         computeCoef1();
00214     }
00215 
00217     void zero(){ d2=d1=Tv(0); }
00218     
00219     virtual void onResync(double r){ freq(mFreq); width(mWidth); }
00220 
00221 protected:
00222 
00223     Filter2(Tp frq, Tp wid)
00224     :   mFreq(frq), mWidth(wid)
00225     {   zero(); }
00226 
00227     void freqRef(Tp& v){
00228         mFreq = v;      
00229         v = scl::clip<Tp>(v * Ts::ups(), 0.5);
00230         //mCos = scl::cosP3<Tp>(v);
00231         mCos = scl::cosT8<Tp>(v * M_2PI);
00232         computeCoef1();
00233     }
00234     
00235     void computeCoef1(){ cd1 = Tp(2) * mRad * mCos; }
00236     void delay(Tv v){ d2 = d1; d1 = v; }
00237     
00238     Tp mFreq, mWidth;
00239     Tp mB0, cd1, cd2;   // coefficients
00240     Tp mCos, mRad;
00241     Tv d2, d1;          // 2- and 1-sample delays
00242 };
00243 
00244 
00245 #define INHERIT_FILTER2 \
00246 typedef Filter2<Tv,Tp,Ts> Base;\
00247 using Base::mFreq;\
00248 using Base::mWidth;\
00249 using Base::d2;\
00250 using Base::d1;\
00251 using Base::mB0;\
00252 using Base::cd1;\
00253 using Base::cd2;\
00254 using Base::mRad;\
00255 using Base::mCos
00256 
00257 
00259 
00265 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00266 class AllPass2 : public Filter2<Tv,Tp,Ts>{
00267 public:
00268 
00271     AllPass2(Tp frq=1000, Tp wid=100): Base(frq, wid){ Ts::initSynced(); }
00272 
00274     Tv operator()(Tv i0){
00275         i0 += d1*cd1 + d2*cd2;
00276         Tv o0 = i0*-cd2 - d1*cd1 + d2;
00277         delay(i0); return o0;
00278     }
00279 
00280 protected:
00281     INHERIT_FILTER2;
00282 };
00283 
00284 
00285 
00287 
00291 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00292 class Notch : public Filter2<Tv,Tp,Ts>{
00293 public:
00294     
00297     Notch(Tp frq=1000, Tp wid=100): Base(frq, wid){ Ts::initSynced(); }
00298 
00300     void freq(Tp v){ Base::freq(v); computeGain(); }
00301 
00303     void width(Tp v){ Base::width(v); computeGain(); }
00304 
00306     Tv operator()(Tv i0){
00307         i0 *= mB0;
00308         Tv o0 = i0 - d1*cd1 - d2*cd2; delay(i0); return o0;
00309     }
00310 
00311     virtual void onResync(double r){ freq(mFreq); width(mWidth); }
00312 
00313 protected:
00314     INHERIT_FILTER2;
00315 
00316     // compute constant gain factor
00317     void computeGain(){ mB0 = Tp(1) / (Tp(1) + scl::abs(cd1) - cd2); }
00318 };
00319 
00320 
00321 
00323 
00327 template <class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00328 class Reson : public Filter2<Tv,Tp,Ts>{
00329 public:
00330 
00333     Reson(Tp frq=440, Tp wid=100): Base(frq, wid){ Ts::initSynced(); }
00334 
00336     void freq(Tp v){
00337         Base::freqRef(v);
00338         mSin = scl::cosP3<Tp>(scl::foldOnce<Tp>(v - Tp(0.25), Tp(0.5)));
00339         computeGain();
00340     }
00341 
00343     void width(Tp v){ Base::width(v); computeGain(); }
00344 
00345     void set(Tp frq, Tp wid){ Base::width(wid); freq(frq); }
00346 
00348     Tv operator()(Tv i0){
00349         i0 *= mB0;
00350         i0 += d1*cd1 + d2*cd2; delay(i0); return i0; 
00351     }
00352 
00353     void onResync(double r){ freq(mFreq); width(mWidth); }
00354 
00355 protected:
00356     INHERIT_FILTER2;
00357     Tp mSin;
00358 
00359     // compute constant gain factor
00360     void computeGain(){ mB0 = (Tp(1) - mRad*mRad) * mSin; }
00361 };
00362 
00363 
00364 
00366 
00369 template <class Tv=gam::real, class Tp=gam::real>
00370 class Hilbert {
00371 public:
00372     #define SR 44100.
00373     Hilbert()
00374     :   cf0(   5.4135/SR), cf1(  41.118 /SR), cf2(  167.3595/SR),   /* for SR=44100 */
00375         cf3( 671.3715/SR), cf4(2694.363 /SR), cf5(11976.867 /SR),
00376         sf0(  18.786 /SR), sf1(  83.5065/SR), sf2(  335.1345/SR), 
00377         sf3(1344.4065/SR), sf4(5471.871 /SR), sf5(41551.671 /SR)
00378     {}
00379     #undef SR
00380 
00382     Complex<Tv> operator()(const Tv& i){
00383         return Complex<Tv>(
00384             cf0(cf1(cf2(cf3(cf4(cf5(i)))))),
00385             -sf0(sf1(sf2(sf3(sf4(sf5(i))))))
00386         );
00387     }
00388 
00389 protected:
00390     AllPass1<Tv, Tp, Synced1> cf0,cf1,cf2,cf3,cf4,cf5, sf0,sf1,sf2,sf3,sf4,sf5;
00391 };
00392 
00393 
00394 
00396 
00399 template <class Tv=double, class Tp=double>
00400 class Integrator{
00401 public:
00402 
00405     Integrator(const Tp& leakCoef=Tp(1), const Tv& v=Tv(0)){
00406         mo[0]=v;
00407         leak(leakCoef);
00408     }
00409 
00411     Tv operator()(const Tv& i0) const { return mo[0]=mo[0]*mb[0] + i0; }
00412     
00413     Integrator& leak(const Tp& v){ mb[0]=v; return *this; }
00414     Integrator& zero(){ mo[0]=Tv(0); return *this; }
00415 
00416 protected:
00417     mutable Tv mo[1];
00418     Tp mb[1];
00419 };
00420 
00421 
00422 
00424 
00430 template <class Tv=gam::real>
00431 class MovingAvg : public DelayN<Tv>{
00432 public:
00433 
00435     explicit MovingAvg(uint32_t size)
00436     :   Base(size), mSum(0), mRSize(0)
00437     {   onResize(); }
00438 
00439     MovingAvg& operator=(const Tv& v){ DelayN<Tv>::operator=(v); return *this; }
00440     
00441     Tv operator()(const Tv& i0){
00442         mSum += i0 - Base::operator()(i0);
00443         return mSum * mRSize;
00444     }
00445     
00446     void zero(){ assign(Tv(0)); }
00447 
00448     virtual void onResize(){
00449         mRSize = 1./Base::size();
00450         //printf("mRSize = %g\n", mRSize);
00451     }
00452 
00453 protected:
00454     typedef DelayN<Tv> Base;
00455     
00456     Tv mSum;        // the moving sum
00457     double mRSize;  // reciprocal of the size
00458 };
00459 
00460 
00461 
00463 
00467 template<class Tv=gam::real, class Tp=gam::real, class Ts=Synced>
00468 class OnePole : public Ts{ 
00469 public:
00470     OnePole();
00471 
00474     OnePole(Tp freq, const Tv& stored=0);
00475 
00476     const Tp& freq() const { return mFreq; }    
00477 
00478     void operator  = (const Tv& val);   
00479     void operator *= (const Tv& val);   
00480     void freq(Tp val);                  
00481     void smooth(Tp val);                
00482     void zero(){ o1=0; }                
00483     void reset(const Tv& v){ o1=v; mStored=v; }
00484 
00485     const Tv& operator()();             
00486     const Tv& operator()(const Tv& input);      
00487     const Tv& last() const;             
00488     const Tv& stored() const;           
00489     Tv& stored();                       
00490     bool zeroing(Tv eps=0.0001) const;  
00491     
00492     virtual void onResync(double r);
00493 
00494 protected:
00495     Tp mFreq, mA0, mB1;
00496     Tv mStored, o1;
00497 };
00498 
00499 
00500 
00501 
00502 // Implementation_______________________________________________________________
00503 
00504 #define TEM template <class Tv>
00505 #define T_VPS template <class Tv, class Tp, class Ts>
00506 
00507 //---- AllPass1
00508 
00509 T_VPS AllPass1<Tv,Tp,Ts>::AllPass1(Tp frq)
00510 :   d1(Tv(0)), mFreq(frq)
00511 {   Ts::initSynced(); }
00512 
00513 T_VPS inline void AllPass1<Tv,Tp,Ts>::freq(Tp v){
00514     mFreq = v;
00515     c = tan( freqToRad(v, Ts::ups()) - M_PI_4); // valid ang in [-pi/4, pi/4]
00516 }
00517 
00518 T_VPS inline void AllPass1<Tv,Tp,Ts>::freqF(Tp v){
00519     mFreq = v;
00520     c = freqToRad(v, Ts::ups());
00521     c = Tp(1.27323954474) * c - Tp(1);      // 4/pi * c - 1, linear apx
00522     c = c * (Tp(0.76) + Tp(0.24) * c * c);
00523 }
00524 
00525 T_VPS inline Tv AllPass1<Tv,Tp,Ts>::operator()(Tv i0){ 
00526     i0 -= d1 * c;           // o0 = c * (i0 - c * d1) + d1
00527     Tv o0 = i0 * c + d1;    //    = c * i0 + (1 - c*c) * d1
00528     d1 = i0;
00529     return o0;
00530 }
00531 
00532 T_VPS inline Tv AllPass1<Tv,Tp,Ts>::high(Tv i0){ return (i0 - operator()(i0)) * Tv(0.5); }
00533 T_VPS inline Tv AllPass1<Tv,Tp,Ts>::low (Tv i0){ return (i0 + operator()(i0)) * Tv(0.5); }
00534 
00535 T_VPS inline Tp AllPass1<Tv,Tp,Ts>::freq(){ return mFreq; }
00536 T_VPS void AllPass1<Tv,Tp,Ts>::onResync(double r){ freq(mFreq); }
00537 
00538 
00539 
00540 
00541 //---- Biquad
00542 T_VPS Biquad<Tv,Tp,Ts>::Biquad(Tp frq, Tp res, FilterType type)
00543 :   d1(0), d2(0)
00544 {
00545     Ts::initSynced();
00546     set(frq, res, type);
00547 }
00548 
00549 T_VPS void Biquad<Tv,Tp,Ts>::onResync(double r){
00550     mFrqToRad = M_2PI * Ts::ups();
00551     freq(mFreq);
00552 }
00553 
00554 T_VPS void Biquad<Tv,Tp,Ts>::set(Tp freqA, Tp resA, FilterType typeA){
00555     mRes = resA;
00556     mType = typeA;
00557     freq(freqA);
00558 }
00559 
00560 T_VPS void Biquad<Tv,Tp,Ts>::zero(){ d1=d2=(Tv)0; }
00561 
00562 T_VPS void Biquad<Tv,Tp,Ts>::coef(Tp a0, Tp a1, Tp a2, Tp b0, Tp b1, Tp b2){
00563     mA0=a0; mA1=a1; mA2=a2; mB0=b0; mB1=b1; mB2=b2;
00564 }
00565 
00566 T_VPS inline void Biquad<Tv,Tp,Ts>::freq(Tp v){
00567 //  float w = freqA * mFrqToRad;    // radial frequency [0, pi)
00568 //  mReal = cos(w);
00569 //  mImag = sin(w);
00570 
00571     mFreq = v;
00572     float phs = scl::clip(mFreq * mFrqToRad, 3.11f);
00573     mReal = scl::cosT8(phs);
00574     mImag = scl::sinT7(phs);
00575     res(mRes);
00576 }
00577 
00578 T_VPS inline void Biquad<Tv,Tp,Ts>::res(Tp v){
00579     mRes = v;
00580     mAlpha = mImag / mRes;
00581     mB0 = Tp(1) / (Tp(1) + mAlpha); // reciprocal of mB0
00582     mB1 = Tp(-2) * mReal * mB0;
00583     mB2 = (Tp(1) - mAlpha) * mB0;
00584     
00585     type(mType);
00586 }
00587 
00588 T_VPS inline void Biquad<Tv,Tp,Ts>::set(Tp frq, Tp res){ set(frq, res, mType); }
00589 
00590 /*
00591 void setAllpass(float fr, float R){
00592   R= 1.f/R;
00593   double cs = -2*cos((2*PI*fr)/sr); 
00594   mA1 = cs*R;
00595   mA2 = R*R;
00596   mB1 = cs/R;
00597   mB2 = 1/m_a2;
00598   mA0 = 1;
00599 }
00600 */
00601 
00602 T_VPS inline void Biquad<Tv,Tp,Ts>::type(FilterType typeA){
00603     mType = typeA;
00604     
00605     switch(mType){
00606     case LOW_PASS:
00607         mA1 = (Tp(1) - mReal) * mB0;
00608         mA0 = mA1 * Tp(0.5);
00609         mA2 = mA0;
00610         break;
00611     case HIGH_PASS:
00612         mA1 = -(Tp(1) + mReal) * mB0;
00613         mA0 = -mA1 * Tp(0.5);
00614         mA2 = mA0;
00615         break;
00616     case BAND_PASS:
00617         mA0 = mImag * Tp(0.5) * mB0;
00618         mA1 = Tp(0);
00619         mA2 = -mA0;
00620         break;
00621     case BAND_PASS_UNIT:
00622         mA0 = mAlpha * mB0;
00623         mA1 = Tp(0);
00624         mA2 = -mA0;
00625         break;
00626     case BAND_REJECT:
00627         mA0 = mB0;  // 1.f * a0
00628         mA1 = mB1;
00629         mA2 = mB0;  // 1.f * a0
00630         break;
00631     case ALL_PASS:
00632         mA0 = mB2;
00633         mA1 = mB1;
00634         mA2 = mB0;
00635         break;
00636     default:;
00637     };
00638 }
00639 
00640 T_VPS inline Tv Biquad<Tv,Tp,Ts>::operator()(Tv i0){
00641     // Direct form II
00642     i0 = i0 - d1*mB1 - d2*mB2;
00643     Tv o0 = i0*mA0 + d1*mA1 + d2*mA2;
00644     d2 = d1; d1 = i0;
00645     return o0;
00646 }
00647 
00648 T_VPS inline Tv Biquad<Tv,Tp,Ts>::nextBP(Tv i0){
00649     i0 = i0 - d1*mB1 - d2*mB2;  
00650     Tv o0 = (i0 - d2)*mA0;
00651     d2 = d1; d1 = i0;
00652     return o0;
00653 }
00654 
00655 
00656 //---- OnePole
00657 T_VPS OnePole<Tv,Tp,Ts>::OnePole()
00658 :   mFreq(10), mStored(Tv(0)), o1(Tv(0))
00659 {   Ts::initSynced(); }
00660 
00661 T_VPS OnePole<Tv,Tp,Ts>::OnePole(Tp frq, const Tv& stored)
00662 :   mFreq(frq), mStored(stored), o1(stored)
00663 {   Ts::initSynced(); }
00664 
00665 T_VPS void OnePole<Tv,Tp,Ts>::onResync(double r){ freq(mFreq); }
00666 
00667 T_VPS inline void OnePole<Tv,Tp,Ts>::operator  = (const Tv& v){ mStored  = v; }
00668 T_VPS inline void OnePole<Tv,Tp,Ts>::operator *= (const Tv& v){ mStored *= v; }
00669 
00670 // f = ln(mB1) / -M_2PI * SR  ( @ 44.1 f = ln(c01) * -7018.733)
00671 // @ 44.1 : 0.9     <=> 739.5
00672 // @ 44.1 : 0.99    <=>  70.54
00673 // @ 44.1 : 0.999   <=>   7.022
00674 // @ 44.1 : 0.9999  <=>   0.702
00675 // @ 44.1 : 0.99999 <=>   0.0702
00676 T_VPS inline void OnePole<Tv,Tp,Ts>::freq(Tp v){
00677     mFreq = v;  
00678     v = scl::max(v, Tp(0)); // ensure positive freq
00679     
00680     // freq is half the bandwidth of a pole at 0
00681     smooth( poleRadius(Tp(2) * v, Ts::ups()) );
00682     //printf("%f, %f, %f\n", Ts::spu(), mB1, v);
00683 }
00684 
00685 T_VPS inline void OnePole<Tv,Tp,Ts>::smooth(Tp v){ mB1=v; mA0=Tp(1) - scl::abs(v); }
00686 
00687 T_VPS inline const Tv& OnePole<Tv,Tp,Ts>::operator()(){ return (*this)(mStored); }
00688 T_VPS inline const Tv& OnePole<Tv,Tp,Ts>::operator()(const Tv& i0){ o1 = o1*mB1 + i0*mA0; return o1; }
00689 
00690 T_VPS inline const Tv& OnePole<Tv,Tp,Ts>::last() const { return o1; }
00691 T_VPS inline const Tv& OnePole<Tv,Tp,Ts>::stored() const { return mStored; }
00692 T_VPS inline Tv& OnePole<Tv,Tp,Ts>::stored(){ return mStored; }
00693 T_VPS inline bool OnePole<Tv,Tp,Ts>::zeroing(Tv eps) const { return scl::abs(o1) < eps && mStored == Tv(0); }
00694 
00695 #undef TEM
00696 #undef T_VPS
00697 
00698 } // gam::
00699 #endif