1 module nes.filter; 2 3 import std.math; 4 5 interface Filter { 6 float step(float x); 7 } 8 9 // First order filters are defined by the following parameters. 10 // y[n] = B0*x[n] + B1*x[n-1] - A1*y[n-1] 11 class FirstOrderFilter : Filter { 12 this(float b0, float b1, float a1, float prevX, float prevY) { 13 this.b0 = b0; 14 this.b1 = b1; 15 this.a1 = a1; 16 this.prevX = prevX; 17 this.prevY = prevY; 18 } 19 20 float step(float x) { 21 auto y = this.b0 * x + this.b1 * this.prevX - this.a1 * this.prevY; 22 this.prevY = y; 23 this.prevX = x; 24 return y; 25 } 26 27 private: 28 float b0, b1, a1, prevX, prevY; 29 } 30 31 class FilterChain : Filter { 32 this(Filter[] filters ...) { 33 this.filterChain = filters.dup; 34 } 35 36 float step(float x) { 37 if (this.filterChain != null) { 38 foreach (f; this.filterChain) { 39 x = f.step(x); 40 } 41 } 42 return x; 43 } 44 45 private: 46 Filter[] filterChain; 47 } 48 49 // sampleRate: samples per second 50 // cutoffFreq: oscillations per second 51 Filter LowPassFilter(float sampleRate, float cutoffFreq) { 52 auto c = sampleRate / std.math.PI / cutoffFreq; 53 auto a0i = 1 / (1 + c); 54 return new FirstOrderFilter(a0i, a0i, (1 - c) * a0i, 0, 0); 55 } 56 57 Filter HighPassFilter(float sampleRate, float cutoffFreq) { 58 auto c = sampleRate / std.math.PI / cutoffFreq; 59 auto a0i = 1 / (1 + c); 60 return new FirstOrderFilter(c * a0i, -c * a0i, (1 - c) * a0i, 0, 0); 61 }