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 }