/// <devdoc> /// Evaluates the transfer function of a Bessel filter. The gain is normalized to 1 for DC. /// It returns a complex number that corresponds to the gain and phase of the filter output. /// </devdoc> private static Complex TransferFunction(double[] besselPolynomialCoefficients, Complex frequency) { var f = new Polynomials.RationalFraction { Top = new double[] { besselPolynomialCoefficients[besselPolynomialCoefficients.Length - 1] }, // to normalize gain at DC Bottom = besselPolynomialCoefficients }; return(Polynomials.Evaluate(f, frequency)); }
/// <devdoc> /// Returns the IIR filter coefficients for a transfer function. /// Normalizes the coefficients so that a[0] is 1. /// </devdoc> private static IirFilterCoefficients ComputeIirFilterCoefficients(Polynomials.RationalFraction tf, double gain) { // Note that compared to the original C code by Tony Fisher the order of the A/B coefficients // is reverse and the A coefficients are negated. double scale = tf.Bottom[0]; var coefficients = new IirFilterCoefficients(); coefficients.A = tf.Bottom.Select(x => x / scale / gain).ToArray(); coefficients.A[0] = 1; coefficients.B = tf.Top.Select(x => x / scale / gain).ToArray(); return coefficients; }
private static double ComputeGain(Polynomials.RationalFraction tf, FilterKind type, double fcf1, double fcf2) { switch (type) { case FilterKind.LowPass: return ComputeGainAt(tf, Complex.One); // At DC case FilterKind.HighPass: // At Nyquist return ComputeGainAt(tf, new Complex(-1, 0)); case FilterKind.BandPass: // At center frequency return ComputeGainAt(tf, Mathx.Expj(2 * Math.PI * ((fcf1 + fcf2) / 2))); case FilterKind.BandStop: // At sqrt( [gain at DC] * [gain at samplingRate/2] return Math.Sqrt(ComputeGainAt(tf, Complex.One) * ComputeGainAt(tf, new Complex(-1, 0))); default: throw new System.ComponentModel.InvalidEnumArgumentException("type", (int)type, typeof(FilterKind)); } }
private static double ComputeGainAt(Polynomials.RationalFraction tf, Complex w) { return Complex.Abs(Polynomials.Evaluate(tf, w)); }