00001 #ifndef GAMMA_FILTER_H_INC
00002 #define GAMMA_FILTER_H_INC
00003
00004
00005
00006
00007 #include "Gamma/ipl.h"
00008 #include "Gamma/scl.h"
00009
00010 #include "Gamma/Containers.h"
00011
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
00027
00028
00029
00030 };
00031
00032
00033
00035 template <class T>
00036 inline T poleRadius(T bw, double ups){ return ::exp(-M_PI * bw * ups); }
00037
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;
00081 Tp c;
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;
00130 Tv d1, d2;
00131 Tp mFreq, mRes;
00132 FilterType mType;
00133 Tp mReal, mImag;
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
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;
00240 Tp mCos, mRad;
00241 Tv d2, d1;
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
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
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),
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
00451 }
00452
00453 protected:
00454 typedef DelayN<Tv> Base;
00455
00456 Tv mSum;
00457 double mRSize;
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
00503
00504 #define TEM template <class Tv>
00505 #define T_VPS template <class Tv, class Tp, class Ts>
00506
00507
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);
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);
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;
00527 Tv o0 = i0 * 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
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
00568
00569
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);
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
00592
00593
00594
00595
00596
00597
00598
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;
00628 mA1 = mB1;
00629 mA2 = mB0;
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
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
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
00671
00672
00673
00674
00675
00676 T_VPS inline void OnePole<Tv,Tp,Ts>::freq(Tp v){
00677 mFreq = v;
00678 v = scl::max(v, Tp(0));
00679
00680
00681 smooth( poleRadius(Tp(2) * v, Ts::ups()) );
00682
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 }
00699 #endif