/[svn]/linuxsampler/trunk/src/engines/common/BiquadFilter.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/BiquadFilter.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 56 by schoenebeck, Tue Apr 27 09:21:58 2004 UTC revision 268 by capela, Thu Oct 7 22:20:20 2004 UTC
# Line 23  Line 23 
23  #ifndef __LS_BIQUADFILTER_H__  #ifndef __LS_BIQUADFILTER_H__
24  #define __LS_BIQUADFILTER_H__  #define __LS_BIQUADFILTER_H__
25    
26    #include <math.h>
27    
28  /// ln(2) / 2  /// ln(2) / 2
29  #define LN_2_2                  0.34657359f  #define LN_2_2                  0.34657359f
30    
# Line 35  namespace LinuxSampler { Line 37  namespace LinuxSampler {
37      typedef float bq_t;      typedef float bq_t;
38    
39      /**      /**
40      * Bi-quadratic filter       * Internal parameters of the biquad filter, which are actually the
41      * (adapted from lisp code by Eli Brandt, http://www.cs.cmu.edu/~eli/)       * final parameters of the filter's transfer function. This strucure is
42      */       * only needed when these parameters should stored outside the
43         * BiquadFilter class, e.g. to save calculation time by sharing them
44         * between multiple filters.
45         */
46        struct biquad_param_t {
47            bq_t a1;
48            bq_t a2;
49            bq_t b0;
50            bq_t b1;
51            bq_t b2;
52        };
53    
54        /**
55         * Bi-quadratic filter
56         * (adapted from lisp code by Eli Brandt, http://www.cs.cmu.edu/~eli/)
57         */
58      class BiquadFilter {      class BiquadFilter {
59          protected:          protected:
60                // following five variables are only used if no external biquad_param_t reference is used
61              bq_t a1;              bq_t a1;
62              bq_t a2;              bq_t a2;
63              bq_t b0;              bq_t b0;
64              bq_t b1;              bq_t b1;
65              bq_t b2;              bq_t b2;
66                // following four variables are used to buffer the feedback
67              bq_t x1;              bq_t x1;
68              bq_t x2;              bq_t x2;
69              bq_t y1;              bq_t y1;
70              bq_t y2;              bq_t y2;
71    
72              /**              /**
73              * Prevent \a f from going into denormal mode which would slow down               * Prevent \a f from going into denormal mode which would slow down
74              * subsequent floating point calculations, we achieve that by setting               * subsequent floating point calculations, we achieve that by setting
75              * \a f to zero when it falls under the denormal threshold value.               * \a f to zero when it falls under the denormal threshold value.
76              */               */
77              inline void KillDenormal(float& f) {              inline void KillDenormal(bq_t& f) {
78                  // TODO: this is a generic solution for 32bit floats, should be replaced by CPU specific asm code                  // TODO: this is a generic solution for 32bit floats, should be replaced by CPU specific asm code
79                  f += 1e-18f;                  f += 1e-18f;
80                  f -= 1e-18f;                  f -= 1e-18f;
# Line 82  namespace LinuxSampler { Line 101  namespace LinuxSampler {
101                  return y;                  return y;
102              }              }
103    
104                inline bq_t Apply(biquad_param_t* param, const bq_t x) {
105                    bq_t y;
106    
107                    y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
108                        param->a1 * this->y1 + param->a2 * this->y2;
109                    KillDenormal(y);
110                    this->x2 = this->x1;
111                    this->x1 = x;
112                    this->y2 = this->y1;
113                    this->y1 = y;
114    
115                    return y;
116                }
117    
118              inline bq_t ApplyFB(bq_t x, const bq_t fb) {              inline bq_t ApplyFB(bq_t x, const bq_t fb) {
119                  bq_t y;                  bq_t y;
120    
# Line 96  namespace LinuxSampler { Line 129  namespace LinuxSampler {
129    
130                  return y;                  return y;
131              }              }
132    
133                inline bq_t ApplyFB(biquad_param_t* param, bq_t x, const bq_t fb) {
134                    bq_t y;
135    
136                    x += this->y1 * fb * 0.98;
137                    y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
138                        param->a1 * this->y1 + param->a2 * this->y2;
139                    KillDenormal(y);
140                    this->x2 = this->x1;
141                    this->x1 = x;
142                    this->y2 = this->y1;
143                    this->y1 = y;
144    
145                    return y;
146                }
147      };      };
148    
149      class LowpassFilter : public BiquadFilter {      class LowpassFilter : public BiquadFilter {
# Line 115  namespace LinuxSampler { Line 163  namespace LinuxSampler {
163                  this->a1 = a0r * (2.0 * cs);                  this->a1 = a0r * (2.0 * cs);
164                  this->a2 = a0r * (alpha - 1.0);                  this->a2 = a0r * (alpha - 1.0);
165              }              }
166    
167                inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
168                    bq_t omega = 2.0 * M_PI * fc / fs;
169                    bq_t sn    = sin(omega);
170                    bq_t cs    = cos(omega);
171                    bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
172    
173                    const float a0r = 1.0 / (1.0 + alpha);
174                    param->b0 = a0r * (1.0 - cs) * 0.5;
175                    param->b1 = a0r * (1.0 - cs);
176                    param->b2 = a0r * (1.0 - cs) * 0.5;
177                    param->a1 = a0r * (2.0 * cs);
178                    param->a2 = a0r * (alpha - 1.0);
179                }
180      };      };
181    
182      class BandpassFilter : public BiquadFilter {      class BandpassFilter : public BiquadFilter {
# Line 134  namespace LinuxSampler { Line 196  namespace LinuxSampler {
196                  this->a1 = a0r * (2.0 * cs);                  this->a1 = a0r * (2.0 * cs);
197                  this->a2 = a0r * (alpha - 1.0);                  this->a2 = a0r * (alpha - 1.0);
198              }              }
199    
200                inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
201                    bq_t omega = 2.0 * M_PI * fc / fs;
202                    bq_t sn    = sin(omega);
203                    bq_t cs    = cos(omega);
204                    bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
205    
206                    const float a0r = 1.0 / (1.0 + alpha);
207                    param->b0 = a0r * alpha;
208                    param->b1 = 0.0;
209                    param->b2 = a0r * -alpha;
210                    param->a1 = a0r * (2.0 * cs);
211                    param->a2 = a0r * (alpha - 1.0);
212                }
213      };      };
214    
215      class HighpassFilter : public BiquadFilter {      class HighpassFilter : public BiquadFilter {
# Line 153  namespace LinuxSampler { Line 229  namespace LinuxSampler {
229                  this->a1 = a0r * (2.0 * cs);                  this->a1 = a0r * (2.0 * cs);
230                  this->a2 = a0r * (alpha - 1.0);                  this->a2 = a0r * (alpha - 1.0);
231              }              }
232    
233                inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
234                    bq_t omega = 2.0 * M_PI * fc / fs;
235                    bq_t sn    = sin(omega);
236                    bq_t cs    = cos(omega);
237                    bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
238    
239                    const float a0r = 1.0 / (1.0 + alpha);
240                    param->b0 = a0r * (1.0 + cs) * 0.5;
241                    param->b1 = a0r * -(1.0 + cs);
242                    param->b2 = a0r * (1.0 + cs) * 0.5;
243                    param->a1 = a0r * (2.0 * cs);
244                    param->a2 = a0r * (alpha - 1.0);
245                }
246      };      };
247    
248  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.56  
changed lines
  Added in v.268

  ViewVC Help
Powered by ViewVC