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 }