/// <summary> /// Creates an IIR filter from zeros and poles. The zeros and poles must be made up of real and complex conjugate pairs. /// </summary> public IirFilter(ZeroPoleGain zeroPoleGain) { Debug.Assert(zeroPoleGain.Zeros.Length == zeroPoleGain.Poles.Length); this.zeroPoleGain = zeroPoleGain; transferFunction = FilterModifiers.ConvertSosToTransferFunction(sosGain); sosGain = FilterModifiers.ConvertZeroPoleToSosFilter(zeroPoleGain); this.sections = new FilterChain(sosGain.Sections); this.order = sosGain.Sections.Sum(x => x.Order); //Check whether this is linear phase double[] b = transferFunction.B; isLinearPhase = true; for (int i = 0; i < b.Length; i++) { if (b[i] != b[b.Length - 1 - i] && b[i] != -b[b.Length - 1 - i]) { isLinearPhase = false; break; } } return; }
public static ZeroPoleGain ConvertSosToZeroPole(SosGain sosGain) { double gain = sosGain.Gain; Complex[] zeros = sosGain.Sections.SelectMany(x => x.ZeroPoleGain.Zeros).ToArray(); Complex[] poles = sosGain.Sections.SelectMany(x => x.ZeroPoleGain.Poles).ToArray(); return new ZeroPoleGain(gain, zeros, poles); }
// Calculate transfer function polynomials of the sections together (similiar to sos2tf in matlab) public static TransferFunction ConvertSosToTransferFunction(SosGain sosGain) { double[] coefA = sosGain.Sections.Select(x => x.TransferFunction.A).Aggregate(new[] { 1.0 }, (x, y) => Helpers.Convolution(x, y)); double[] coefB = sosGain.Sections.Select(x => x.TransferFunction.B).Aggregate(new[] { 1.0 }, (x, y) => Helpers.Convolution(x, y)); // Incorporate gain into transfer function coefB = Array.ConvertAll(coefB, x => sosGain.Gain * x); // Remove trailing zeros if (coefA.Length > 3 && coefA.Last() == 0) Array.Resize(ref coefA, coefA.Length - 1); if (coefB.Length > 3 && coefB.Last() == 0) Array.Resize(ref coefB, coefB.Length - 1); return new TransferFunction(coefB, coefA); }