1 module pixelperfectengine.audio.base.filter;
2
3 import inteli.emmintrin;
4 import pixelperfectengine.audio.base.func;
5 import std.math;
6
7 /**
8 * Defines a biquad infinite response filter bank for various uses.
9 */
10 public struct IIRBank {
11 ///All initial values + some precalculated ones.
12 __m128 x1, x2, y1, y2, b0a0, b1a0, b2a0, a1a0, a2a0;
13
14 ///Calculates the output of the filter, then stores the input and output values.
15 pragma (inline, true)
16 __m128 output(__m128 x0) @nogc @safe pure nothrow {
17 const __m128 y0 = (b0a0 * x0) + (b1a0 * x1) + (b2a0 * x2) - (a1a0 * y1) - (a2a0 * y2);
18 x2 = x1;
19 x1 = x0;
20 y2 = y1;
21 y1 = y0;
22 return y0;
23 }
24 /**
25 * Sets the filter to the given values.
26 * Params:
27 * vals = Biquad values.
28 * n = Filter selector (0 <= n <= 3).
29 */
30 void setFilter(BiquadFilterValues vals, int n) @nogc @safe pure nothrow {
31 b0a0[n] = vals.b0 / vals.a0;
32 b1a0[n] = vals.b1 / vals.a0;
33 b2a0[n] = vals.b2 / vals.a0;
34 a1a0[n] = vals.a1 / vals.a0;
35 a2a0[n] = vals.a2 / vals.a0;
36 }
37 /// Resets all filter statuses.
38 void reset() @nogc @safe pure nothrow {
39 x1 = __m128(0);
40 x2 = __m128(0);
41 y1 = __m128(0);
42 y2 = __m128(0);
43 b0a0 = __m128(0);
44 b1a0 = __m128(0);
45 b2a0 = __m128(0);
46 a1a0 = __m128(0);
47 a2a0 = __m128(0);
48 }
49 /// Resets filter values, if NaN or infinity has been hit.
50 void fixFilter() @nogc @safe pure nothrow {
51 for (int i = 0 ; i < 4 ; i++) {
52 if (isNaN(x1[i]) || isNaN(x2[i]) || isNaN(y1[i]) || isNaN(y2[i]) || isInfinity(x1[i]) || isInfinity(x2[i]) ||
53 isInfinity(y1[i]) || isInfinity(y2[i])) {
54 x1[i] = 0.0;
55 x2[i] = 0.0;
56 y1[i] = 0.0;
57 y2[i] = 0.0;
58 }
59 }
60 }
61 }