5 * Copyright (C) 2002-2005 Monty
7 * Postfish 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, or (at your option)
12 * Postfish 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.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* code derived directly from mkfilter by the late A.J. Fisher,
25 University of York <fisher@minster.york.ac.uk> September 1992; this
26 is only the minimum code needed to build an arbitrary Bessel filter */
35 static complex bessel_poles
[] = {
36 { -1.00000000000e+00, 0.00000000000e+00},
37 { -1.10160133059e+00, 6.36009824757e-01},
38 { -1.32267579991e+00, 0.00000000000e+00},
39 { -1.04740916101e+00, 9.99264436281e-01},
40 { -1.37006783055e+00, 4.10249717494e-01},
41 { -9.95208764350e-01, 1.25710573945e+00},
42 { -1.50231627145e+00, 0.00000000000e+00},
43 { -1.38087732586e+00, 7.17909587627e-01},
44 { -9.57676548563e-01, 1.47112432073e+00},
45 { -1.57149040362e+00, 3.20896374221e-01},
46 { -1.38185809760e+00, 9.71471890712e-01},
47 { -9.30656522947e-01, 1.66186326894e+00},
48 { -1.68436817927e+00, 0.00000000000e+00},
49 { -1.61203876622e+00, 5.89244506931e-01},
50 { -1.37890321680e+00, 1.19156677780e+00},
51 { -9.09867780623e-01, 1.83645135304e+00},
52 { -1.75740840040e+00, 2.72867575103e-01},
53 { -1.63693941813e+00, 8.22795625139e-01},
54 { -1.37384121764e+00, 1.38835657588e+00},
55 { -8.92869718847e-01, 1.99832584364e+00},
56 { -1.85660050123e+00, 0.00000000000e+00},
57 { -1.80717053496e+00, 5.12383730575e-01},
58 { -1.65239648458e+00, 1.03138956698e+00},
59 { -1.36758830979e+00, 1.56773371224e+00},
60 { -8.78399276161e-01, 2.14980052431e+00},
61 { -1.92761969145e+00, 2.41623471082e-01},
62 { -1.84219624443e+00, 7.27257597722e-01},
63 { -1.66181024140e+00, 1.22110021857e+00},
64 { -1.36069227838e+00, 1.73350574267e+00},
65 { -8.65756901707e-01, 2.29260483098e+00},
68 #define TWOPI (2.0 * M_PIl)
73 complex poles
[MAXPZ
], zeros
[MAXPZ
];
74 int numpoles
, numzeros
;
77 static complex cdiv(complex z1
, complex z2
){
78 double mag
= (z2
.re
* z2
.re
) + (z2
.im
* z2
.im
);
79 complex ret
={((z1
.re
* z2
.re
) + (z1
.im
* z2
.im
)) / mag
,
80 ((z1
.im
* z2
.re
) - (z1
.re
* z2
.im
)) / mag
};
84 static complex cmul(complex z1
, complex z2
){
85 complex ret
={z1
.re
*z2
.re
- z1
.im
*z2
.im
,
86 z1
.re
*z2
.im
+ z1
.im
*z2
.re
};
89 static complex cadd(complex z1
, complex z2
){
95 static complex csub(complex z1
, complex z2
){
101 static complex cconj(complex z
){
106 static complex eval(complex coeffs
[], int npz
, complex z
){
107 complex sum
= (complex){0.0,0.0};
109 for (i
= npz
; i
>= 0; i
--) sum
= cadd(cmul(sum
, z
), coeffs
[i
]);
113 static complex evaluate(complex topco
[], int nz
, complex botco
[], int np
, complex z
){
114 return cdiv(eval(topco
, nz
, z
),eval(botco
, np
, z
));
117 static complex blt(complex pz
){
119 return cdiv(cadd(two
, pz
), csub(two
, pz
));
122 static void multin(complex w
, int npz
, complex coeffs
[]){
124 complex nw
= (complex){-w
.re
, -w
.im
};
125 for (i
= npz
; i
>= 1; i
--)
126 coeffs
[i
] = cadd(cmul(nw
, coeffs
[i
]), coeffs
[i
-1]);
127 coeffs
[0] = cmul(nw
, coeffs
[0]);
130 static void expand(complex pz
[], int npz
, complex coeffs
[]){
131 /* compute product of poles or zeros as a polynomial of z */
133 coeffs
[0] = (complex){1.0,0.0};
134 for (i
=0; i
< npz
; i
++) coeffs
[i
+1] = (complex){0.0,0.0};
135 for (i
=0; i
< npz
; i
++) multin(pz
[i
], npz
, coeffs
);
136 /* check computed coeffs of z^k are all real */
137 for (i
=0; i
< npz
+1; i
++){
138 if (fabs(coeffs
[i
].im
) > EPS
){
139 fprintf(stderr
, "mkfilter: coeff of z^%d is not real; poles/zeros are not complex conjugates\n", i
);
145 double mkbessel(double raw_alpha
,int order
,double *ycoeff
){
146 int i
,p
= (order
*order
)/4;
147 pzrep splane
, zplane
;
148 complex topcoeffs
[MAXPZ
+1], botcoeffs
[MAXPZ
+1];
152 memset(&splane
,0,sizeof(splane
));
153 memset(&zplane
,0,sizeof(zplane
));
155 if (order
& 1) splane
.poles
[splane
.numpoles
++] = bessel_poles
[p
++];
156 for (i
= 0; i
< order
/2; i
++){
157 splane
.poles
[splane
.numpoles
++] = bessel_poles
[p
];
158 splane
.poles
[splane
.numpoles
++] = cconj(bessel_poles
[p
++]);
161 warped_alpha
= tan(M_PIl
* raw_alpha
) / M_PIl
;
162 for (i
= 0; i
< splane
.numpoles
; i
++){
163 splane
.poles
[i
].re
*= TWOPI
* warped_alpha
;
164 splane
.poles
[i
].im
*= TWOPI
* warped_alpha
;
167 zplane
.numpoles
= splane
.numpoles
;
168 zplane
.numzeros
= splane
.numzeros
;
169 for (i
=0; i
< zplane
.numpoles
; i
++)
170 zplane
.poles
[i
] = blt(splane
.poles
[i
]);
171 for (i
=0; i
< zplane
.numzeros
; i
++)
172 zplane
.zeros
[i
] = blt(splane
.zeros
[i
]);
173 while (zplane
.numzeros
< zplane
.numpoles
)
174 zplane
.zeros
[zplane
.numzeros
++] = (complex){-1.0,0.};
176 expand(zplane
.zeros
, zplane
.numzeros
, topcoeffs
);
177 expand(zplane
.poles
, zplane
.numpoles
, botcoeffs
);
178 dc_gain
= evaluate(topcoeffs
, zplane
.numzeros
, botcoeffs
, zplane
.numpoles
, (complex){1.0,0.0});
181 ycoeff
[order
-i
-1] = -(botcoeffs
[i
].re
/ botcoeffs
[zplane
.numpoles
].re
);
183 return hypot(dc_gain
.re
,dc_gain
.im
);
186 /* applies a 2nd order filter (attack) that is decay-limited by a
187 first-order freefall filter (decay) */
188 void compute_iir_symmetric_limited(float *x
, int n
, iir_state
*is
,
189 iir_filter
*attack
, iir_filter
*limit
){
190 double a_c0
=attack
->c
[0],l_c0
=limit
->c
[0];
191 double a_c1
=attack
->c
[1];
192 double a_g
=1./attack
->g
;
194 double x0
=is
->x
[0],x1
=is
->x
[1];
195 double y0
=is
->y
[0],y1
=is
->y
[1];
199 if(zerome(y0
) && zerome(y1
)) y0
=y1
=0.;
202 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
+ y0
*a_c0
+y1
*a_c1
;
211 is
->x
[0]=x0
;is
->x
[1]=x1
;
212 is
->y
[0]=y0
;is
->y
[1]=y1
;
215 /* applies a 2nd order filter (decay) to decay from peak value only,
216 decay limited by a first-order freefall filter (limit) with the
217 same alpha as decay */
218 void compute_iir_decay_limited(float *x
, int n
, iir_state
*is
,
219 iir_filter
*decay
, iir_filter
*limit
){
220 double d_c0
=decay
->c
[0],l_c0
=limit
->c
[0];
221 double d_c1
=decay
->c
[1];
222 double d_g
=1./decay
->g
;
224 double x0
=is
->x
[0],x1
=is
->x
[1];
225 double y0
=is
->y
[0],y1
=is
->y
[1];
229 if(zerome(y0
) && zerome(y1
)) y0
=y1
=0.;
232 double yd
= (x
[i
]+x0
*2.+x1
)*d_g
+ y0
*d_c0
+y1
*d_c1
;
235 if(yd
<x
[i
])y1
=y0
=yd
=x
[i
];
242 is
->x
[0]=x0
;is
->x
[1]=x1
;
243 is
->y
[0]=y0
;is
->y
[1]=y1
;
246 /* applies a 2nd order filter (attack) that is decay-limited by a
247 first-order filter (decay) */
248 void compute_iir_freefall_limited(float *x
, int n
, iir_state
*is
,
249 iir_filter
*attack
, iir_filter
*limit
){
250 double a_c0
=attack
->c
[0],l_c0
=limit
->c
[0];
251 double a_c1
=attack
->c
[1];
252 double a_g
=1./attack
->g
;
254 double x0
=is
->x
[0],x1
=is
->x
[1];
255 double y0
=is
->y
[0],y1
=is
->y
[1];
259 if(zerome(y0
) && zerome(y1
)) y0
=y1
=0.;
262 double ya
= (x0
*2.+x1
)*a_g
+ y0
*a_c0
+y1
*a_c1
;
278 is
->x
[0]=x0
;is
->x
[1]=x1
;
279 is
->y
[0]=y0
;is
->y
[1]=y1
;
282 void compute_iir_freefallonly1(float *x
, int n
, iir_state
*is
,
284 double d_c0
=decay
->c
[0];
300 /* if we're not in freefall, be sure x[i]_out == x[i]_in */
316 /* a new experiment; bessel followers constructed specifically for
317 compand functions. Hard and soft knee are implemented as part of
320 #define prologue double a_c0=attack->c[0],l_c0=limit->c[0]; \
321 double a_c1=attack->c[1]; \
322 double a_g=1./(knee * attack->g);\
323 double x0=is->x[0],x1=is->x[1]; \
324 double y0=is->y[0],y1=is->y[1]; \
326 if(zerome(y0) && zerome(y1)) y0=y1=0.; \
329 /* Three delicious filters in one: The 'attack' filter is a fast
330 second-order Bessel used two ways; as a direct RMS follower and as
331 a filter pegged to free-fall to the knee value. The 'limit' filter
332 is a first-order free-fall (to 0) Bessel used to limit the 'attack'
333 filter to a linear-dB decay. Output is normalized to place the knee
336 void compute_iir_over_soft(float *x
, int n
, iir_state
*is
,
337 iir_filter
*attack
, iir_filter
*limit
,
338 float knee
, float mult
, float *adj
){
339 double xag
=4./attack
->g
;
342 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
351 adj
[i
++]-= todB_a((float)ya
)*mult
;
355 is
->x
[0]=x0
;is
->x
[1]=x1
;
356 is
->y
[0]=y0
;is
->y
[1]=y1
;
359 void compute_iir_under_soft(float *x
, int n
, iir_state
*is
,
360 iir_filter
*attack
, iir_filter
*limit
,
361 float knee
, float mult
, float *adj
){
362 double xag
=4./attack
->g
;
365 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
374 adj
[i
++]-= todB_a((float)ya
)*mult
;
378 is
->x
[0]=x0
;is
->x
[1]=x1
;
379 is
->y
[0]=y0
;is
->y
[1]=y1
;
382 void compute_iir_over_hard(float *x
, int n
, iir_state
*is
,
383 iir_filter
*attack
, iir_filter
*limit
,
384 float knee
, float mult
, float *adj
){
387 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
395 if(ya
>1.)adj
[i
]-= todB_a((float)ya
)*mult
;
399 is
->x
[0]=x0
;is
->x
[1]=x1
;
400 is
->y
[0]=y0
;is
->y
[1]=y1
;
403 void compute_iir_under_hard(float *x
, int n
, iir_state
*is
,
404 iir_filter
*attack
, iir_filter
*limit
,
405 float knee
, float mult
, float *adj
){
408 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
416 if(ya
<1.)adj
[i
]-= todB_a((float)ya
)*mult
;
420 is
->x
[0]=x0
;is
->x
[1]=x1
;
421 is
->y
[0]=y0
;is
->y
[1]=y1
;
424 /* One more take on the above; we need to be able to gently slew
425 multiplier changes from one block to the next. Although it seems
426 absurd to make eight total compander follower variants, doing this
427 inline avoids a copy later on, and these are enough of a CPU sink
428 that the silliness is actually worth it. */
430 void compute_iir_over_soft_del(float *x
, int n
, iir_state
*is
,
431 iir_filter
*attack
, iir_filter
*limit
,
432 float knee
, float mult
, float mult2
,
434 float multadd
=(mult2
-mult
)/n
;
435 double xag
=4./attack
->g
;
438 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
447 adj
[i
++]-= todB_a((float)ya
)*mult
;
452 is
->x
[0]=x0
;is
->x
[1]=x1
;
453 is
->y
[0]=y0
;is
->y
[1]=y1
;
456 void compute_iir_under_soft_del(float *x
, int n
, iir_state
*is
,
457 iir_filter
*attack
, iir_filter
*limit
,
458 float knee
, float mult
, float mult2
,
460 float multadd
=(mult2
-mult
)/n
;
461 double xag
=4./attack
->g
;
464 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
473 adj
[i
++]-= todB_a((float)ya
)*mult
;
478 is
->x
[0]=x0
;is
->x
[1]=x1
;
479 is
->y
[0]=y0
;is
->y
[1]=y1
;
482 void compute_iir_over_hard_del(float *x
, int n
, iir_state
*is
,
483 iir_filter
*attack
, iir_filter
*limit
,
484 float knee
, float mult
, float mult2
,
486 float multadd
=(mult2
-mult
)/n
;
489 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
497 if(ya
>1.)adj
[i
]-= todB_a((float)ya
)*mult
;
502 is
->x
[0]=x0
;is
->x
[1]=x1
;
503 is
->y
[0]=y0
;is
->y
[1]=y1
;
506 void compute_iir_under_hard_del(float *x
, int n
, iir_state
*is
,
507 iir_filter
*attack
, iir_filter
*limit
,
508 float knee
, float mult
, float mult2
,
510 float multadd
=(mult2
-mult
)/n
;
513 double ya
= (x
[i
]+x0
*2.+x1
)*a_g
;
521 if(ya
<1.)adj
[i
]-= todB_a((float)ya
)*mult
;
526 is
->x
[0]=x0
;is
->x
[1]=x1
;
527 is
->y
[0]=y0
;is
->y
[1]=y1
;
530 void reset_iir(iir_state
*is
,float value
){
532 for(i
=0;i
<MAXORDER
;i
++){
533 is
->x
[i
]=(double)value
;
534 is
->y
[i
]=(double)value
;