2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef CBOX_BIQUAD_FLOAT_H
20 #define CBOX_BIQUAD_FLOAT_H
25 struct cbox_biquadf_state
33 struct cbox_biquadf_coeffs
42 static inline void cbox_biquadf_reset(struct cbox_biquadf_state
*state
)
44 state
->x1
= state
->y1
= state
->x2
= state
->y2
= 0.f
;
47 static inline float cbox_biquadf_is_audible(struct cbox_biquadf_state
*state
, float level
)
49 return fabs(state
->x1
) + fabs(state
->x2
) + fabs(state
->y1
) + fabs(state
->y2
) >= level
;
52 // Based on filter coefficient equations by Robert Bristow-Johnson
53 static inline void cbox_biquadf_set_lp_rbj(struct cbox_biquadf_coeffs
*coeffs
, float fc
, float q
, float sr
)
55 float omega
=(float)(2*M_PI
*fc
/sr
);
58 float alpha
=(float)(sn
/(2*q
));
59 float inv
=(float)(1.0/(1.0+alpha
));
61 coeffs
->a2
= coeffs
->a0
= (float)(inv
*(1 - cs
)*0.5f
);
62 coeffs
->a1
= coeffs
->a0
+ coeffs
->a0
;
63 coeffs
->b1
= (float)(-2*cs
*inv
);
64 coeffs
->b2
= (float)((1 - alpha
)*inv
);
67 static inline void cbox_biquadf_set_lp_rbj_lookup(struct cbox_biquadf_coeffs
*coeffs
, const struct cbox_sincos
*sincos
, float q
)
69 float sn
=sincos
->sine
;
70 float cs
=sincos
->cosine
;
71 float alpha
=(float)(sn
/(2*q
));
72 float inv
=(float)(1.0/(1.0+alpha
));
74 coeffs
->a2
= coeffs
->a0
= (float)(inv
*(1 - cs
)*0.5f
);
75 coeffs
->a1
= coeffs
->a0
+ coeffs
->a0
;
76 coeffs
->b1
= (float)(-2*cs
*inv
);
77 coeffs
->b2
= (float)((1 - alpha
)*inv
);
80 // Based on filter coefficient equations by Robert Bristow-Johnson
81 static inline void cbox_biquadf_set_hp_rbj(struct cbox_biquadf_coeffs
*coeffs
, float fc
, float q
, float sr
)
83 float omega
=(float)(2*M_PI
*fc
/sr
);
86 float alpha
=(float)(sn
/(2*q
));
87 float inv
=(float)(1.0/(1.0+alpha
));
89 coeffs
->a2
= coeffs
->a0
= (float)(inv
*(1 + cs
)*0.5f
);
90 coeffs
->a1
= -2 * coeffs
->a0
;
91 coeffs
->b1
= (float)(-2*cs
*inv
);
92 coeffs
->b2
= (float)((1 - alpha
)*inv
);
95 static inline void cbox_biquadf_set_hp_rbj_lookup(struct cbox_biquadf_coeffs
*coeffs
, const struct cbox_sincos
*sincos
, float q
)
97 float sn
=sincos
->sine
;
98 float cs
=sincos
->cosine
;
99 float alpha
=(float)(sn
/(2*q
));
100 float inv
=(float)(1.0/(1.0+alpha
));
102 coeffs
->a2
= coeffs
->a0
= (float)(inv
*(1 + cs
)*0.5f
);
103 coeffs
->a1
= -2 * coeffs
->a0
;
104 coeffs
->b1
= (float)(-2*cs
*inv
);
105 coeffs
->b2
= (float)((1 - alpha
)*inv
);
108 // Based on filter coefficient equations by Robert Bristow-Johnson
109 static inline void cbox_biquadf_set_bp_rbj(struct cbox_biquadf_coeffs
*coeffs
, float fc
, float q
, float sr
)
111 float omega
=(float)(2*M_PI
*fc
/sr
);
114 float alpha
=(float)(sn
/(2*q
));
115 float inv
=(float)(1.0/(1.0+alpha
));
117 coeffs
->a0
= (float)(inv
*alpha
);
119 coeffs
->a2
= -coeffs
->a0
;
120 coeffs
->b1
= (float)(-2*cs
*inv
);
121 coeffs
->b2
= (float)((1 - alpha
)*inv
);
124 static inline void cbox_biquadf_set_bp_rbj_lookup(struct cbox_biquadf_coeffs
*coeffs
, const struct cbox_sincos
*sincos
, float q
)
126 float sn
=sincos
->sine
;
127 float cs
=sincos
->cosine
;
128 float alpha
=(float)(sn
/(2*q
));
129 float inv
=(float)(1.0/(1.0+alpha
));
131 coeffs
->a0
= (float)(inv
*alpha
);
133 coeffs
->a2
= -coeffs
->a0
;
134 coeffs
->b1
= (float)(-2*cs
*inv
);
135 coeffs
->b2
= (float)((1 - alpha
)*inv
);
139 // Based on filter coefficient equations by Robert Bristow-Johnson
140 static inline void cbox_biquadf_set_peakeq_rbj(struct cbox_biquadf_coeffs
*coeffs
, float freq
, float q
, float peak
, float sr
)
142 float A
= sqrt(peak
);
143 float w0
= freq
* 2 * M_PI
* (1.0 / sr
);
144 float alpha
= sin(w0
) / (2 * q
);
145 float ib0
= 1.0 / (1 + alpha
/A
);
146 coeffs
->a1
= coeffs
->b1
= -2*cos(w0
) * ib0
;
147 coeffs
->a0
= ib0
* (1 + alpha
*A
);
148 coeffs
->a2
= ib0
* (1 - alpha
*A
);
149 coeffs
->b2
= ib0
* (1 - alpha
/A
);
152 static inline void cbox_biquadf_set_peakeq_rbj_scaled(struct cbox_biquadf_coeffs
*coeffs
, float freq
, float q
, float A
, float sr
)
154 float w0
= freq
* 2 * M_PI
* (1.0 / sr
);
155 float alpha
= sin(w0
) / (2 * q
);
156 float ib0
= 1.0 / (1 + alpha
/A
);
157 coeffs
->a1
= coeffs
->b1
= -2*cos(w0
) * ib0
;
158 coeffs
->a0
= ib0
* (1 + alpha
*A
);
159 coeffs
->a2
= ib0
* (1 - alpha
*A
);
160 coeffs
->b2
= ib0
* (1 - alpha
/A
);
163 // This is my math, and it's rather suspect
164 static inline void cbox_biquadf_set_1plp(struct cbox_biquadf_coeffs
*coeffs
, float freq
, float sr
)
166 float w
= hz2w(freq
, sr
);
167 float x
= tan (w
* 0.5f
);
168 float q
= 1 / (1 + x
);
179 static inline void cbox_biquadf_set_1php(struct cbox_biquadf_coeffs
*coeffs
, float freq
, float sr
)
181 float w
= hz2w(freq
, sr
);
182 float x
= tan (w
* 0.5f
);
183 float q
= 1 / (1 + x
);
194 static inline void cbox_biquadf_set_1p(struct cbox_biquadf_coeffs
*coeffs
, float a0
, float a1
, float b1
, int two_copies
)
198 // (a0 + a1z) * (a0 + a1z) = a0^2 + 2*a0*a1*z + a1^2*z^2
199 // (1 - b1z) * (1 - b1z) = 1 - 2b1*z + b1^2*z^2
201 coeffs
->a1
= 2*a0
*a1
;
216 static inline void cbox_biquadf_set_1plp_lookup(struct cbox_biquadf_coeffs
*coeffs
, struct cbox_sincos
*sincos
, int two_copies
)
218 float x
= sincos
->prewarp
;
219 float q
= 1 / (1 + x
);
223 cbox_biquadf_set_1p(coeffs
, a01
, a01
, b1
, two_copies
);
226 static inline void cbox_biquadf_set_1php_lookup(struct cbox_biquadf_coeffs
*coeffs
, struct cbox_sincos
*sincos
, int two_copies
)
228 float x
= sincos
->prewarp
;
229 float q
= 1 / (1 + x
);
233 cbox_biquadf_set_1p(coeffs
, q
, -q
, b1
, two_copies
);
238 #include <arm_neon.h>
240 static inline void cbox_biquadf_process(struct cbox_biquadf_state
*state
, struct cbox_biquadf_coeffs
*coeffs
, float *buffer
)
243 float32x2_t c0
= {coeffs
->a0
, 0};
244 float32x2_t c1
= {coeffs
->a1
, -coeffs
->b1
};
245 float32x2_t c2
= {coeffs
->a2
, -coeffs
->b2
};
246 float32x2_t s1
= {state
->x1
, state
->y1
};
247 float32x2_t s2
= {state
->x2
, state
->y2
};
249 for (i
= 0; i
< CBOX_BLOCK_SIZE
; i
++)
251 float32x2_t in12
= {buffer
[i
], 0.f
};
253 float32x2_t out12
= vmla_f32(vmla_f32(vmul_f32(c1
, s1
), c2
, s2
), in12
, c0
); // [a1 * x1 + a2 * x2 + a0 * in, -b1 * y1 - b2 * y2 + 0]
254 float32x2x2_t trn
= vtrn_f32(out12
, in12
); // [[a1 * x1 + a2 * x2 + a0 * in, in12], [-b1 * y1 - b2 * y2, 0]]
255 float32x2_t out120
= vadd_f32(trn
.val
[0], trn
.val
[1]);
258 s1
= vrev64_f32(out120
);
259 buffer
[i
] = out120
[0];
269 static inline void cbox_biquadf_process(struct cbox_biquadf_state
*state
, struct cbox_biquadf_coeffs
*coeffs
, float *buffer
)
272 float a0
= coeffs
->a0
;
273 float a1
= coeffs
->a1
;
274 float a2
= coeffs
->a2
;
275 float b1
= coeffs
->b1
;
276 float b2
= coeffs
->b2
;
277 double y1
= state
->y1
;
278 double y2
= state
->y2
;
280 for (i
= 0; i
< CBOX_BLOCK_SIZE
; i
++)
282 float in
= buffer
[i
];
283 double out
= a0
* in
+ a1
* state
->x1
+ a2
* state
->x2
- b1
* y1
- b2
* y2
;
286 state
->x2
= state
->x1
;
291 state
->y2
= sanef(y2
);
292 state
->y1
= sanef(y1
);
297 static inline double cbox_biquadf_process_sample(struct cbox_biquadf_state
*state
, struct cbox_biquadf_coeffs
*coeffs
, double in
)
299 double out
= sanef(coeffs
->a0
* sanef(in
) + coeffs
->a1
* state
->x1
+ coeffs
->a2
* state
->x2
- coeffs
->b1
* state
->y1
- coeffs
->b2
* state
->y2
);
301 state
->x2
= state
->x1
;
303 state
->y2
= state
->y1
;
309 static inline void cbox_biquadf_process_to(struct cbox_biquadf_state
*state
, struct cbox_biquadf_coeffs
*coeffs
, float *buffer_in
, float *buffer_out
)
312 float a0
= coeffs
->a0
;
313 float a1
= coeffs
->a1
;
314 float a2
= coeffs
->a2
;
315 float b1
= coeffs
->b1
;
316 float b2
= coeffs
->b2
;
317 double y1
= state
->y1
;
318 double y2
= state
->y2
;
320 for (i
= 0; i
< CBOX_BLOCK_SIZE
; i
++)
322 float in
= buffer_in
[i
];
323 double out
= a0
* in
+ a1
* state
->x1
+ a2
* state
->x2
- b1
* y1
- b2
* y2
;
326 state
->x2
= state
->x1
;
331 state
->y2
= sanef(y2
);
332 state
->y1
= sanef(y1
);
335 static inline void cbox_biquadf_process_adding(struct cbox_biquadf_state
*state
, struct cbox_biquadf_coeffs
*coeffs
, float *buffer_in
, float *buffer_out
)
338 float a0
= coeffs
->a0
;
339 float a1
= coeffs
->a1
;
340 float a2
= coeffs
->a2
;
341 float b1
= coeffs
->b1
;
342 float b2
= coeffs
->b2
;
343 double y1
= state
->y1
;
344 double y2
= state
->y2
;
346 for (i
= 0; i
< CBOX_BLOCK_SIZE
; i
++)
348 float in
= buffer_in
[i
];
349 double out
= a0
* in
+ a1
* state
->x1
+ a2
* state
->x2
- b1
* y1
- b2
* y2
;
351 buffer_out
[i
] += out
;
352 state
->x2
= state
->x1
;
357 state
->y2
= sanef(y2
);
358 state
->y1
= sanef(y1
);