public class BiquadCoefficient { public double a0; public double a1; public double a2; public double b0; public double b1; public double b2; public BiquadCoefficient( double a0, double a1, double a2, double b0, double b1, double b2) { this.a0 = a0; this.a1 = a1; this.a2 = a2; this.b0 = b0; this.b1 = b1; this.b2 = b2; } } /// /// 2次ずつに分解し、直列接続したタイプの IIR フィルタ。 /// public class SerialIirFilter : IFilter { #region 内部クラス /// /// 2次 IIR(ゲインなし)。 /// class Iir2 : System.ICloneable { double a1, a2, b1, b2; double t1, t2; public Iir2( double a1, double a2, double b1, double b2) { this.a1 = a1; this.a2 = a2; this.b1 = b1; this.b2 = b2; } public double GetValue(double x) { x += this.a1 * this.t1; double y = this.b1 * this.t1; x += this.a2 * this.t2; y += this.b2 * this.t2; y += x; this.t2 = this.t1; this.t1 = x; return y; } public void Clear() { this.t1 = this.t2 = 0; } #region ICloneable メンバ public object Clone() { Iir2 f = new Iir2(this.a1, this.a2, this.b1, this.b2); f.t1 = this.t1; f.t2 = this.t2; return f; } #endregion } #endregion #region フィールド double c; Iir2[] filters; #endregion #region コンストラクタ public SerialIirFilter(params BiquadCoefficient[] coefs) { this.filters = new Iir2[coefs.Length]; this.c = 1; for (int i = 0; i < coefs.Length; ++i) { BiquadCoefficient coef = coefs[i]; this.c *= coef.b0 / coef.a0; this.filters[i] = new Iir2( -coef.a1 / coef.a0, -coef.a2 / coef.a0, coef.b1 / coef.b0, coef.b2 / coef.b0); } } SerialIirFilter(Iir2[] filters) { } #endregion #region IFilter メンバ /// /// 各時刻 n で、 /// t[n] = c * x[n] + Σ a[i - 1] * t[n - i] /// y[n] = t[n] + Σ b[i - 1] * t[n - i] /// /// 入力 /// フィルタ出力 public double GetValue(double x) { double y = x; for (int i = 0; i < this.filters.Length; ++i) { y = this.filters[i].GetValue(y); } return y; } public void Clear() { for (int i = 0; i < this.filters.Length; ++i) { this.filters[i].Clear(); } } #endregion #region ICloneable メンバ public object Clone() { return new SerialIirFilter( (Iir2[])this.filters.Clone()); } #endregion }