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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 791 - (show annotations) (download) (as text)
Sun Oct 16 14:50:20 2005 UTC (18 years, 6 months ago) by persson
File MIME type: text/x-c++hdr
File size: 24526 byte(s)
* Filter tuning: calculation of cutoff frequency and bandwidth
  improved. Removed use of "BasicBPFilter". Changed bandpass filter
  from constant peak to constant skirt. Use gig parameter Resonance if
  no resonance controller is set. Removed keyboard tracking influence
  on resonance.

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __LS_BIQUADFILTER_H__
25 #define __LS_BIQUADFILTER_H__
26
27 #include <math.h>
28
29 #include "../../common/global.h"
30
31 /// ln(2) / 2
32 #define LN_2_2 0.34657359f
33
34 #ifndef LIMIT
35 # define LIMIT(v,l,u) (v < l ? l : (v > u ? u : v))
36 #endif
37
38 namespace LinuxSampler {
39
40 typedef float bq_t;
41
42 /**
43 * Internal parameters of the biquad filter, which are actually the
44 * final parameters of the filter's transfer function. This strucure is
45 * only needed when these parameters should stored outside the
46 * BiquadFilter class, e.g. to save calculation time by sharing them
47 * between multiple filters.
48 */
49 struct biquad_param_t {
50 bq_t b0;
51 bq_t b1;
52 bq_t b2;
53 bq_t a1;
54 bq_t a2;
55 };
56
57 /**
58 * Bi-quadratic filter
59 * (adapted from lisp code by Eli Brandt, http://www.cs.cmu.edu/~eli/)
60 */
61 class BiquadFilter {
62 protected:
63 // following five variables are only used if no external biquad_param_t reference is used
64 bq_t b0;
65 bq_t b1;
66 bq_t b2;
67 bq_t a1;
68 bq_t a2;
69 // following four variables are used to buffer the feedback
70 bq_t x1;
71 bq_t x2;
72 bq_t y1;
73 bq_t y2;
74
75 #if __GNUC__ >= 4
76 float fbc;
77 #else
78 const static float fbc = 0.98;
79 #endif
80
81 /**
82 * Prevent \a f from going into denormal mode which would slow down
83 * subsequent floating point calculations, we achieve that by setting
84 * \a f to zero when it falls under the denormal threshold value.
85 */
86 inline void KillDenormal(bq_t& f) {
87 // TODO: this is a generic solution for 32bit floats, should be replaced by CPU specific asm code
88 f += 1e-18f;
89 f -= 1e-18f;
90 }
91 public:
92 BiquadFilter() {
93 Reset();
94 #if __GNUC__ >= 4
95 fbc = 0.98f;
96 #endif
97 }
98
99 void Reset() {
100 x1 = 0.0f;
101 x2 = 0.0f;
102 y1 = 0.0f;
103 y2 = 0.0f;
104 }
105
106 inline bq_t Apply(const bq_t x) {
107 bq_t y;
108
109 y = this->b0 * x + this->b1 * this->x1 + this->b2 * this->x2 +
110 this->a1 * this->y1 + this->a2 * this->y2;
111 KillDenormal(y);
112 this->x2 = this->x1;
113 this->x1 = x;
114 this->y2 = this->y1;
115 this->y1 = y;
116
117 return y;
118 }
119
120 inline bq_t Apply(biquad_param_t* param, const bq_t x) {
121 bq_t y;
122
123 y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
124 param->a1 * this->y1 + param->a2 * this->y2;
125 KillDenormal(y);
126 this->x2 = this->x1;
127 this->x1 = x;
128 this->y2 = this->y1;
129 this->y1 = y;
130
131 return y;
132 }
133
134 #if CONFIG_ASM && ARCH_X86
135 // expects to find input in xmm0 (xmm0 stays unmodified) and finally leaves output in xmm6
136 inline void Apply4StepsSSE(biquad_param_t* param) {
137 __asm__ __volatile__ (
138 "movss (%2),%%xmm4 # b0\n\t"
139 "shufps $0x00,%%xmm4,%%xmm4 # copy b0 to other cells\n\t"
140 "mulps %%xmm0,%%xmm4 # xmm4 = x*b0\n\t"
141 "movups (%0),%%xmm2 # load b1,b2,a1,a2\n\t"
142 "movups (%1),%%xmm5 # load x1,x2,y1,y2\n\t"
143 /* sample 0 */
144 "movaps %%xmm5,%%xmm3\n\t"
145 "mulps %%xmm2,%%xmm5 # xmm5 = [b1,b2,a1,a2] * [x1,x2,y1,y2]\n\t"
146 "shufps $0x0a,%%xmm3,%%xmm3 # x2 = x1, y2 = y1\n\t"
147 "movss %%xmm4,%%xmm6\n\t"
148 "addss %%xmm5,%%xmm6\n\t"
149 "shufps $0x39,%%xmm5,%%xmm5\n\t"
150 "addss %%xmm5,%%xmm6\n\t"
151 "shufps $0x39,%%xmm5,%%xmm5\n\t"
152 "addss %%xmm5,%%xmm6\n\t"
153 "shufps $0x39,%%xmm5,%%xmm5\n\t"
154 "addss %%xmm5,%%xmm6 # xmm6 = b0*x + b1*x1 + b2*x2 + a1*y1 + a2*y2\n\t"
155 /* sample 1 */
156 "shufps $0x39,%%xmm4,%%xmm4 # rotate xmm4 down 1 cell\n\t"
157 "movss %%xmm6,%%xmm3 # y1 = y\n\t"
158 "shufps $0x4e,%%xmm3,%%xmm3 # rotate 2 cells\n\t"
159 "movss %%xmm0,%%xmm3 # x1 = x\n\t"
160 "shufps $0x93,%%xmm6,%%xmm6 # rotate output up 1 cell\n\t"
161 "movaps %%xmm3,%%xmm5\n\t"
162 "shufps $0x39,%%xmm0,%%xmm0 # rotate input down 1 cell\n\t"
163 "mulps %%xmm2,%%xmm5 # xmm5 = [b1,b2,a1,a2] * [x1,x2,y1,y2]\n\t"
164 "movss %%xmm5,%%xmm6\n\t"
165 "addss %%xmm4,%%xmm6\n\t"
166 "shufps $0x39,%%xmm5,%%xmm5\n\t"
167 "addss %%xmm5,%%xmm6\n\t"
168 "shufps $0x39,%%xmm5,%%xmm5\n\t"
169 "addss %%xmm5,%%xmm6\n\t"
170 "shufps $0x39,%%xmm5,%%xmm5\n\t"
171 "addss %%xmm5,%%xmm6 # xmm6 = b0*x + b1*x1 + b2*x2 + a1*y1 + a2*y2\n\t"
172 /* sample 2 */
173 "shufps $0x0a,%%xmm3,%%xmm3 # x2 = x1, y2 = y1\n\t"
174 "shufps $0x39,%%xmm4,%%xmm4 # rotate xmm4 down 1 cell\n\t"
175 "movss %%xmm6,%%xmm3 # y1 = y\n\t"
176 "shufps $0x4e,%%xmm3,%%xmm3 # rotate 2 cells\n\t"
177 "movss %%xmm0,%%xmm3 # x1 = x\n\t"
178 "shufps $0x93,%%xmm6,%%xmm6 # rotate output up 1 cell\n\t"
179 "movaps %%xmm3,%%xmm5\n\t"
180 "shufps $0x39,%%xmm0,%%xmm0 # rotate input down 1 cell\n\t"
181 "mulps %%xmm2,%%xmm5 # xmm5 = [b1,b2,a1,a2] * [x1,x2,y1,y2]\n\t"
182 "movss %%xmm5,%%xmm6\n\t"
183 "addss %%xmm4,%%xmm6\n\t"
184 "shufps $0x39,%%xmm5,%%xmm5\n\t"
185 "addss %%xmm5,%%xmm6\n\t"
186 "shufps $0x39,%%xmm5,%%xmm5\n\t"
187 "addss %%xmm5,%%xmm6\n\t"
188 "shufps $0x39,%%xmm5,%%xmm5\n\t"
189 "addss %%xmm5,%%xmm6 # xmm6 = b0*x + b1*x1 + b2*x2 + a1*y1 + a2*y2\n\t"
190 /* sample 3 */
191 "shufps $0x0a,%%xmm3,%%xmm3 # x2 = x1, y2 = y1\n\t"
192 "shufps $0x39,%%xmm4,%%xmm4 # rotate xmm4 down 1 cell\n\t"
193 "movss %%xmm6,%%xmm3 # y1 = y\n\t"
194 "shufps $0x4e,%%xmm3,%%xmm3 # rotate 2 cells\n\t"
195 "movss %%xmm0,%%xmm3 # x1 = x\n\t"
196 "shufps $0x93,%%xmm6,%%xmm6 # rotate output up 1 cell\n\t"
197 "mulps %%xmm3,%%xmm2 # xmm5 = [b1,b2,a1,a2] * [x1,x2,y1,y2]\n\t"
198 "shufps $0x39,%%xmm0,%%xmm0 # rotate input down 1 cell\n\t"
199 "movss %%xmm2,%%xmm6\n\t"
200 "shufps $0x39,%%xmm2,%%xmm2\n\t"
201 "addss %%xmm2,%%xmm6\n\t"
202 "shufps $0x39,%%xmm2,%%xmm2\n\t"
203 "addss %%xmm2,%%xmm6\n\t"
204 "shufps $0x39,%%xmm2,%%xmm2\n\t"
205 "addss %%xmm2,%%xmm6\n\t"
206 "addss %%xmm4,%%xmm6 # xmm6 = b0*x + b1*x1 + b2*x2 + a1*y1 + a2*y2\n\t"
207 /* done */
208 "shufps $0x0a,%%xmm3,%%xmm3 # x2 = x1, y2 = y1\n\t"
209 "movss %%xmm6,%%xmm3 # y1 = y\n\t"
210 "shufps $0x4e,%%xmm3,%%xmm3 # rotate 2 cells\n\t"
211 "movss %%xmm0,%%xmm3 # x1 = x\n\t"
212 "shufps $0x1b,%%xmm6,%%xmm6 # swap output to correct order\n\t"
213 "shufps $0x39,%%xmm0,%%xmm0 # rotate input down 1 cell, to restore original input\n\t"
214 "movups %%xmm3,(%1) # store x1,x2,y1,y2\n\t"
215 : /* no output */
216 : "r" (&param->b1), /* %0 - [b1,b2,a1,a2] */
217 "r" (&x1), /* %1 - [x1,x2,y1,y2] */
218 "r" (&param->b0) /* %2 */
219 );
220 }
221 #endif // CONFIG_ASM && ARCH_X86
222
223 inline bq_t ApplyFB(bq_t x, const bq_t fb) {
224 bq_t y;
225
226 x += this->y1 * fb * 0.98;
227 y = this->b0 * x + this->b1 * this->x1 + this->b2 * this->x2 +
228 this->a1 * this->y1 + this->a2 * this->y2;
229 KillDenormal(y);
230 this->x2 = this->x1;
231 this->x1 = x;
232 this->y2 = this->y1;
233 this->y1 = y;
234
235 return y;
236 }
237
238 inline bq_t ApplyFB(biquad_param_t* param, bq_t x, const bq_t fb) {
239 bq_t y;
240
241 x += this->y1 * fb * 0.98;
242 y = param->b0 * x + param->b1 * this->x1 + param->b2 * this->x2 +
243 param->a1 * this->y1 + param->a2 * this->y2;
244 KillDenormal(y);
245 this->x2 = this->x1;
246 this->x1 = x;
247 this->y2 = this->y1;
248 this->y1 = y;
249
250 return y;
251 }
252
253 #if CONFIG_ASM && ARCH_X86
254 // expects to find input in xmm0 (xmm0 stays unmodified) and finally leaves output in xmm7
255 inline void ApplyFB4StepsSSE(biquad_param_t* param, const bq_t &fb) {
256 float xs, ys;
257 float t0, t1, t2, t3, t4, t5, t6, t7, t8; // temporary stack space
258 __asm__ __volatile__ (
259 /* prepare input */
260 "movss %15,%%xmm5\n\t"
261 "movss %%xmm0,(%14)\n\t"
262 /* sample 0 */
263 "movss %0, %%xmm3\n\t"
264 "movss %1, %%xmm4\n\t"
265 "mulss %%xmm4, %%xmm5\n\t"
266 "movss %%xmm3, %2\n\t"
267 "movss %%xmm5, %16\n\t"
268 "mulss %%xmm3, %%xmm5\n\t"
269 "movss %19, %%xmm2\n\t"
270 "movss %3, %%xmm6\n\t"
271 "movss %21, %%xmm3\n\t"
272 "addss %%xmm5, %%xmm6\n\t"
273 "movss %%xmm2, %%xmm5\n\t"
274 "movss %20, %%xmm4\n\t"
275 "movss %%xmm6, %4\n\t"
276 "mulss %%xmm6, %%xmm5\n\t"
277 "movss %5, %%xmm6\n\t"
278 "movss %%xmm2, %6\n\t"
279 "movss %%xmm4, %7\n\t"
280 "movss %%xmm3, %%xmm2\n\t"
281 "mulss %%xmm6, %%xmm4\n\t"
282 "mulss %8, %%xmm2\n\t"
283 "movss %%xmm3, %9\n\t"
284 "addss %%xmm4, %%xmm5\n\t"
285 "movss %18, %%xmm3\n\t"
286 "movss %17, %%xmm4\n\t"
287 "addss %%xmm2, %%xmm5\n\t"
288 "movss %%xmm4, %10\n\t"
289 "movss %%xmm3, %%xmm2\n\t"
290 "mulss %11, %%xmm4\n\t"
291 "mulss %12, %%xmm2\n\t"
292 "movss %%xmm3, %13\n\t"
293 "addss %%xmm4, %%xmm5\n\t"
294 "movss %11, %%xmm3\n\t"
295 "movss %4, %%xmm4\n\t"
296 "addss %%xmm2, %%xmm5\n\t"
297 :: "m" (y1), /* %0 */
298 "m" (fbc), /* %1 */
299 "m" (t0), /* %2 */
300 "m" (xs), /* %3 */
301 "m" (t7), /* %4 */
302 "m" (x1), /* %5 */
303 "m" (t1), /* %6 */
304 "m" (t2), /* %7 */
305 "m" (x2), /* %8 */
306 "m" (t3), /* %9 */
307 "m" (t4), /* %10 */
308 "m" (t0), /* %11 */
309 "m" (y2), /* %12 */
310 "m" (t5), /* %13 */
311 "r" (&xs), /* %14 */
312 "m" (fb), /* %15 */
313 "m" (ys), /* %16 */
314 "m" (param->a1), /* %17 */
315 "m" (param->a2), /* %18 */
316 "m" (param->b0), /* %19 */
317 "m" (param->b1), /* %20 */
318 "m" (param->b2) /* %21 */
319 );
320 __asm__ __volatile__ (
321 "shufps $0x39,%%xmm0,%%xmm0 # rotate down one cell\n\t"
322 "movss %%xmm5,%%xmm7\n\t"
323 ::
324 );
325 /* sample 1 */
326 __asm__ __volatile__ (
327 "movss %0, %%xmm4\n\t"
328 "movss %%xmm0, %%xmm3\n\t"
329 "mulss %%xmm5, %%xmm4\n\t"
330 "mulss %3, %%xmm6\n\t"
331 "movss %5, %%xmm2\n\t"
332 "addss %%xmm4, %%xmm3\n\t"
333 "mulss %7, %%xmm2\n\t"
334 "movss %6, %%xmm4\n\t"
335 "movss %%xmm3, %8\n\t"
336 "mulss %%xmm3, %%xmm4\n\t"
337 "addss %%xmm2, %%xmm4\n\t"
338 "movss %9, %%xmm3\n\t"
339 "mulss %%xmm5, %%xmm3\n\t"
340 "movss %10, %%xmm2\n\t"
341 "addss %%xmm6, %%xmm4\n\t"
342 "mulss %11, %%xmm2\n\t"
343 "addss %%xmm3, %%xmm4\n\t"
344 "addss %%xmm2, %%xmm4\n\t"
345 :: "m" (ys), /* %0 */
346 "m" (fbc), /* %1 */
347 "m" (xs), /* %2 */
348 "m" (t3), /* %3 */
349 "m" (y2), /* %4 */
350 "m" (t2), /* %5 */
351 "m" (t1), /* %6 */
352 "m" (t7), /* %7 */
353 "m" (t8), /* %8 */
354 "m" (t4), /* %9 */
355 "m" (t5), /* %10 */
356 "m" (t0), /* %11 */
357 "m" (x2), /* %12 */
358 "m" (x1), /* %13 */
359 "m" (y1) /* %14 */
360 );
361 __asm__ __volatile__ (
362 "shufps $0x93,%%xmm7,%%xmm7 # rotate up one cell\n\t"
363 "shufps $0x39,%%xmm0,%%xmm0 # rotate down one cell\n\t"
364 "movss %%xmm4,%%xmm7\n\t"
365 ::
366 );
367 /* sample 2 */
368 __asm__ __volatile__ (
369 "movss %2, %%xmm6\n\t"
370 "movss %3, %%xmm3\n\t"
371 "mulss %%xmm4, %%xmm6\n\t"
372 "movss %4, %%xmm2\n\t"
373 "mulss %9, %%xmm2\n\t"
374 "addss %%xmm0, %%xmm6\n\t"
375 "mulss %7, %%xmm5\n\t"
376 "mulss %%xmm6, %%xmm3\n\t"
377 "addss %%xmm2, %%xmm3\n\t"
378 "movss %5, %%xmm2\n\t"
379 "mulss %8, %%xmm2\n\t"
380 "addss %%xmm2, %%xmm3\n\t"
381 "movss %6, %%xmm2\n\t"
382 "mulss %%xmm4, %%xmm2\n\t"
383 "addss %%xmm5, %%xmm2\n\t"
384 "addss %%xmm2, %%xmm3\n\t"
385 :: "m" (xs), /* %0 */
386 "m" (fb), /* %1 */
387 "m" (ys), /* %2 */
388 "m" (t1), /* %3 */
389 "m" (t2), /* %4 */
390 "m" (t3), /* %5 */
391 "m" (t4), /* %6 */
392 "m" (t5), /* %7 */
393 "m" (t7), /* %8 */
394 "m" (t8), /* %9 */
395 "m" (x1), /* %10 */
396 "m" (x2), /* %11 */
397 "m" (y1), /* %12 */
398 "m" (y2) /* %13 */
399 );
400 __asm__ __volatile__ (
401 "shufps $0x39,%%xmm0,%%xmm0 # rotate down one cell\n\t"
402 "shufps $0x93,%%xmm7,%%xmm7 # rotate up one cell\n\t"
403 "movss %%xmm3,%%xmm7\n\t"
404 ::
405 );
406 /* sample 3 */
407 __asm__ __volatile__ (
408 "movss %1, %%xmm2\n\t"
409 "mulss %7, %%xmm4\n\t"
410 "mulss %%xmm3, %%xmm2\n\t"
411 "movss %3, %%xmm5\n\t"
412 "movss %%xmm6, %11\n\t"
413 "addss %%xmm0, %%xmm2\n\t"
414 "movss %%xmm3, %13\n\t"
415 "mulss %%xmm2, %%xmm5\n\t"
416 "mulss %4, %%xmm6\n\t"
417 "movss %%xmm2, %10\n\t"
418 "addss %%xmm6, %%xmm5\n\t"
419 "movss %5, %%xmm2\n\t"
420 "mulss %9, %%xmm2\n\t"
421 "mulss %6, %%xmm3\n\t"
422 "addss %%xmm2, %%xmm5\n\t"
423 "addss %%xmm3, %%xmm4\n\t"
424 "addss %%xmm4, %%xmm5\n\t"
425 "movss %%xmm5, %12\n\t"
426 :: "m" (xs), /* %0 */
427 "m" (ys), /* %1 */
428 "m" (fbc), /* %2 */
429 "m" (t1), /* %3 */
430 "m" (t2), /* %4 */
431 "m" (t3), /* %5 */
432 "m" (t4), /* %6 */
433 "m" (t5), /* %7 */
434 "m" (t6), /* %8 */
435 "m" (t8), /* %9 */
436 "m" (x1), /* %10 */
437 "m" (x2), /* %11 */
438 "m" (y1), /* %12 */
439 "m" (y2) /* %13 */
440 );
441 __asm__ __volatile__ (
442 "shufps $0x93,%%xmm7,%%xmm7 # rotate up one cell\n\t"
443 "shufps $0x39,%%xmm0,%%xmm0 # rotate down one cell to restore original input\n\t"
444 "movss %%xmm5,%%xmm7\n\t"
445 "shufps $0x1b,%%xmm7,%%xmm7 # swap output to correct order\n\t"
446 ::
447 );
448 }
449 #endif // CONFIG_ASM && ARCH_X86
450 };
451
452 /** @brief Lowpass Filter
453 *
454 * Lowpass filter based on biquad filter implementation.
455 */
456 class LowpassFilter : public BiquadFilter {
457 public:
458 inline LowpassFilter() : BiquadFilter() {}
459
460 inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
461 bq_t omega = 2.0 * M_PI * fc / fs;
462 bq_t sn = sin(omega);
463 bq_t cs = cos(omega);
464 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
465
466 const float a0r = 1.0 / (1.0 + alpha);
467 this->b0 = a0r * (1.0 - cs) * 0.5;
468 this->b1 = a0r * (1.0 - cs);
469 this->b2 = a0r * (1.0 - cs) * 0.5;
470 this->a1 = a0r * (2.0 * cs);
471 this->a2 = a0r * (alpha - 1.0);
472 }
473
474 inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
475 bq_t omega = 2.0 * M_PI * fc / fs;
476 bq_t sn = sin(omega);
477 bq_t cs = cos(omega);
478 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
479
480 const float a0r = 1.0 / (1.0 + alpha);
481 param->b0 = a0r * (1.0 - cs) * 0.5;
482 param->b1 = a0r * (1.0 - cs);
483 param->b2 = a0r * (1.0 - cs) * 0.5;
484 param->a1 = a0r * (2.0 * cs);
485 param->a2 = a0r * (alpha - 1.0);
486 }
487 };
488
489 /** @brief Bandpass Filter
490 *
491 * Bandpass filter based on biquad filter implementation.
492 */
493 class BandpassFilter : public BiquadFilter {
494 public:
495 inline BandpassFilter() : BiquadFilter() {}
496
497 inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
498 bq_t omega = 2.0 * M_PI * fc / fs;
499 bq_t sn = sin(omega);
500 bq_t cs = cos(omega);
501 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
502
503 const float a0r = 1.0 / (1.0 + alpha);
504 this->b0 = a0r * sn * 0.71;
505 this->b1 = 0.0;
506 this->b2 = a0r * -sn * 0.71;
507 this->a1 = a0r * (2.0 * cs);
508 this->a2 = a0r * (alpha - 1.0);
509 }
510
511 inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
512 bq_t omega = 2.0 * M_PI * fc / fs;
513 bq_t sn = sin(omega);
514 bq_t cs = cos(omega);
515 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
516
517 const float a0r = 1.0 / (1.0 + alpha);
518 param->b0 = a0r * sn * 0.71;
519 param->b1 = 0.0;
520 param->b2 = a0r * -sn * 0.71;
521 param->a1 = a0r * (2.0 * cs);
522 param->a2 = a0r * (alpha - 1.0);
523 }
524 };
525
526 /** @brief Highpass Filter
527 *
528 * Highpass filter based on biquad filter implementation.
529 */
530 class HighpassFilter : public BiquadFilter {
531 public:
532 inline HighpassFilter() : BiquadFilter() {}
533
534 inline void SetParameters(bq_t fc, bq_t bw, bq_t fs) {
535 bq_t omega = 2.0 * M_PI * fc / fs;
536 bq_t sn = sin(omega);
537 bq_t cs = cos(omega);
538 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
539
540 const float a0r = 1.0 / (1.0 + alpha);
541 this->b0 = a0r * (1.0 + cs) * 0.5;
542 this->b1 = a0r * -(1.0 + cs);
543 this->b2 = a0r * (1.0 + cs) * 0.5;
544 this->a1 = a0r * (2.0 * cs);
545 this->a2 = a0r * (alpha - 1.0);
546 }
547
548 inline void SetParameters(biquad_param_t* param, bq_t fc, bq_t bw, bq_t fs) {
549 bq_t omega = 2.0 * M_PI * fc / fs;
550 bq_t sn = sin(omega);
551 bq_t cs = cos(omega);
552 bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
553
554 const float a0r = 1.0 / (1.0 + alpha);
555 param->b0 = a0r * (1.0 + cs) * 0.5;
556 param->b1 = a0r * -(1.0 + cs);
557 param->b2 = a0r * (1.0 + cs) * 0.5;
558 param->a1 = a0r * (2.0 * cs);
559 param->a2 = a0r * (alpha - 1.0);
560 }
561 };
562
563 } // namespace LinuxSampler
564
565 #endif // __LS_BIQUADFILTER_H__

  ViewVC Help
Powered by ViewVC