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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 80 - (hide annotations) (download) (as text)
Sun May 23 19:16:33 2004 UTC (19 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 9330 byte(s)
* biquad filter parameters are now calculated outside the interpolate
  loop for better performance
* couple of loop unroll optimizations
* filter is now enabled by default
* cubic interpolation is now enabled by default
* reduced debug level to 1 to lower verbosity
* raised default limit for voices to 128
* raised default limit for streams to 150
* added some compiler optimization flags (-ffast-math -march -mcpu)

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 53 * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23     #ifndef __LS_BIQUADFILTER_H__
24     #define __LS_BIQUADFILTER_H__
25    
26     /// ln(2) / 2
27     #define LN_2_2 0.34657359f
28    
29     #ifndef LIMIT
30     # define LIMIT(v,l,u) (v < l ? l : (v > u ? u : v))
31     #endif
32    
33     namespace LinuxSampler {
34    
35     typedef float bq_t;
36    
37     /**
38 schoenebeck 80 * Internal parameters of the biquad filter, which are actually the
39     * final parameters of the filter's transfer function. This strucure is
40     * only needed when these parameters should stored outside the
41     * BiquadFilter class, e.g. to save calculation time by sharing them
42     * between multiple filters.
43     */
44     struct biquad_param_t {
45     bq_t a1;
46     bq_t a2;
47     bq_t b0;
48     bq_t b1;
49     bq_t b2;
50     };
51    
52     /**
53     * Bi-quadratic filter
54     * (adapted from lisp code by Eli Brandt, http://www.cs.cmu.edu/~eli/)
55     */
56 schoenebeck 53 class BiquadFilter {
57     protected:
58 schoenebeck 80 // following five variables are only used if no external biquad_param_t reference is used
59 schoenebeck 53 bq_t a1;
60     bq_t a2;
61     bq_t b0;
62     bq_t b1;
63     bq_t b2;
64 schoenebeck 80 // following four variables are used to buffer the feedback
65 schoenebeck 53 bq_t x1;
66     bq_t x2;
67     bq_t y1;
68     bq_t y2;
69    
70     /**
71 schoenebeck 80 * Prevent \a f from going into denormal mode which would slow down
72     * subsequent floating point calculations, we achieve that by setting
73     * \a f to zero when it falls under the denormal threshold value.
74     */
75     inline void KillDenormal(bq_t& f) {
76 schoenebeck 53 // TODO: this is a generic solution for 32bit floats, should be replaced by CPU specific asm code
77     f += 1e-18f;
78     f -= 1e-18f;
79     }
80     public:
81     inline BiquadFilter() {
82     x1 = 0.0f;
83     x2 = 0.0f;
84     y1 = 0.0f;
85     y2 = 0.0f;
86     }
87    
88     inline bq_t Apply(const bq_t x) {
89     bq_t y;
90    
91     y = this->b0 * x + this->b1 * this->x1 + this->b2 * this->x2 +
92     this->a1 * this->y1 + this->a2 * this->y2;
93     KillDenormal(y);
94     this->x2 = this->x1;
95     this->x1 = x;
96     this->y2 = this->y1;
97     this->y1 = y;
98    
99     return y;
100     }
101    
102 schoenebeck 80 inline bq_t Apply(biquad_param_t* param, const bq_t x) {
103     bq_t y;
104    
105     y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
106     param->a1 * this->y1 + param->a2 * this->y2;
107     KillDenormal(y);
108     this->x2 = this->x1;
109     this->x1 = x;
110     this->y2 = this->y1;
111     this->y1 = y;
112    
113     return y;
114     }
115    
116 schoenebeck 53 inline bq_t ApplyFB(bq_t x, const bq_t fb) {
117     bq_t y;
118    
119     x += this->y1 * fb * 0.98;
120     y = this->b0 * x + this->b1 * this->x1 + this->b2 * this->x2 +
121     this->a1 * this->y1 + this->a2 * this->y2;
122     KillDenormal(y);
123     this->x2 = this->x1;
124     this->x1 = x;
125     this->y2 = this->y1;
126     this->y1 = y;
127    
128     return y;
129     }
130 schoenebeck 80
131     inline bq_t ApplyFB(biquad_param_t* param, bq_t x, const bq_t fb) {
132     bq_t y;
133    
134     x += this->y1 * fb * 0.98;
135     y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
136     param->a1 * this->y1 + param->a2 * this->y2;
137     KillDenormal(y);
138     this->x2 = this->x1;
139     this->x1 = x;
140     this->y2 = this->y1;
141     this->y1 = y;
142    
143     return y;
144     }
145 schoenebeck 53 };
146    
147     class LowpassFilter : public BiquadFilter {
148     public:
149     inline LowpassFilter() : BiquadFilter() {}
150    
151     inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
152     bq_t omega = 2.0 * M_PI * fc / fs;
153     bq_t sn = sin(omega);
154     bq_t cs = cos(omega);
155     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
156    
157     const float a0r = 1.0 / (1.0 + alpha);
158     this->b0 = a0r * (1.0 - cs) * 0.5;
159     this->b1 = a0r * (1.0 - cs);
160     this->b2 = a0r * (1.0 - cs) * 0.5;
161     this->a1 = a0r * (2.0 * cs);
162     this->a2 = a0r * (alpha - 1.0);
163     }
164 schoenebeck 80
165     inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
166     bq_t omega = 2.0 * M_PI * fc / fs;
167     bq_t sn = sin(omega);
168     bq_t cs = cos(omega);
169     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
170    
171     const float a0r = 1.0 / (1.0 + alpha);
172     param->b0 = a0r * (1.0 - cs) * 0.5;
173     param->b1 = a0r * (1.0 - cs);
174     param->b2 = a0r * (1.0 - cs) * 0.5;
175     param->a1 = a0r * (2.0 * cs);
176     param->a2 = a0r * (alpha - 1.0);
177     }
178 schoenebeck 53 };
179    
180     class BandpassFilter : public BiquadFilter {
181     public:
182     inline BandpassFilter() : BiquadFilter() {}
183    
184     inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
185     bq_t omega = 2.0 * M_PI * fc / fs;
186     bq_t sn = sin(omega);
187     bq_t cs = cos(omega);
188     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
189    
190     const float a0r = 1.0 / (1.0 + alpha);
191     this->b0 = a0r * alpha;
192     this->b1 = 0.0;
193     this->b2 = a0r * -alpha;
194     this->a1 = a0r * (2.0 * cs);
195     this->a2 = a0r * (alpha - 1.0);
196     }
197 schoenebeck 80
198     inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
199     bq_t omega = 2.0 * M_PI * fc / fs;
200     bq_t sn = sin(omega);
201     bq_t cs = cos(omega);
202     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
203    
204     const float a0r = 1.0 / (1.0 + alpha);
205     param->b0 = a0r * alpha;
206     param->b1 = 0.0;
207     param->b2 = a0r * -alpha;
208     param->a1 = a0r * (2.0 * cs);
209     param->a2 = a0r * (alpha - 1.0);
210     }
211 schoenebeck 53 };
212    
213     class HighpassFilter : public BiquadFilter {
214     public:
215     inline HighpassFilter() : BiquadFilter() {}
216    
217     inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
218     bq_t omega = 2.0 * M_PI * fc / fs;
219     bq_t sn = sin(omega);
220     bq_t cs = cos(omega);
221     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
222    
223     const float a0r = 1.0 / (1.0 + alpha);
224     this->b0 = a0r * (1.0 + cs) * 0.5;
225     this->b1 = a0r * -(1.0 + cs);
226     this->b2 = a0r * (1.0 + cs) * 0.5;
227     this->a1 = a0r * (2.0 * cs);
228     this->a2 = a0r * (alpha - 1.0);
229     }
230 schoenebeck 80
231     inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
232     bq_t omega = 2.0 * M_PI * fc / fs;
233     bq_t sn = sin(omega);
234     bq_t cs = cos(omega);
235     bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
236    
237     const float a0r = 1.0 / (1.0 + alpha);
238     param->b0 = a0r * (1.0 + cs) * 0.5;
239     param->b1 = a0r * -(1.0 + cs);
240     param->b2 = a0r * (1.0 + cs) * 0.5;
241     param->a1 = a0r * (2.0 * cs);
242     param->a2 = a0r * (alpha - 1.0);
243     }
244 schoenebeck 53 };
245    
246     } // namespace LinuxSampler
247    
248     #endif // __LS_BIQUADFILTER_H__

  ViewVC Help
Powered by ViewVC