/* ChebyshevIIRDesigner.java created 2010-09-14 * */ package org.signalml.math.iirdesigner; import org.signalml.math.iirdesigner.math.SpecialMath; /** * This abstract class represents a designer which is capable of designing a Chebyshev filter. * * @author Piotr Szachewicz */ abstract class ChebyshevIIRDesigner extends AbstractIIRDesigner { /** * Calculates the minimum filter order of the filter which would meets the given specifications. * * @param type type of the filter (lowpass/highpass/bandpass/bandstop) * @param wp passband edge frequencies [PI*rad/sample for digital filters or rad/sec. for analog filters ] * @param ws stopband edge frequencies [PI*rad/sample for digital filters or rad/sec. for analog filters ] * @param gpass the maximum loss in the passband [dB] * @param gstop the minimum attenuation in the stopband [dB] * @param analog true to design an analog filter, false to design a digital filter * @return the order of filter */ @Override protected int calculateFilterOrder(FilterType type, double[] wp, double[] ws, double gpass, double gstop, boolean analog) throws BadFilterParametersException { double[] passb; double[] stopb; if (!analog) { passb = prewarpFrequencies(wp); stopb = prewarpFrequencies(ws); } else { passb = wp.clone(); stopb = ws.clone(); } double frequencyRatio = calculateFrequencyRatio(type, passb, stopb, gpass, gstop); double GSTOP = Math.pow(10.0, 0.1*Math.abs(gstop)); double GPASS = Math.pow(10.0, 0.1*Math.abs(gpass)); int filterOrder = (int)(Math.ceil(SpecialMath.acosh(Math.sqrt((GSTOP - 1.0) / (GPASS - 1.0))) / SpecialMath.acosh(frequencyRatio))); if (filterOrder == 0) throw new BadFilterParametersException("Filter order is zero - check the input parameters!"); return filterOrder; } /** * Calculates the bandstop objective function value which is used to find * optimal values for passband edge frequencies (if the filter is an analog bandstop filter) * to minimize the filter order. * * @param passbandEdge the new passband edge frequency [rad/sec.] * @param variablePassbandEdgeIndex specifies which passband edge to vary (0 or 1) * @param passb passband edge frequencies [rad/sec.] * @param stopb stopband edge frequencies [rad/sec.] * @param gpass the maximum loss in the passband [dB] * @param gstop the minimum attenuation in the stopband [dB] * @return the filter order (possibly non-integer) */ @Override protected double calculateBandstopObjectiveFunctionValue(double passbandEdge, int variablePassbandEdgeIndex, double[] passb, double[] stopb, double gpass, double gstop) { double[] passbCopy = passb.clone(); passbCopy[variablePassbandEdgeIndex] = passbandEdge; double[] possibilities = new double[2]; possibilities[0] = stopb[0] * (passbCopy[0] - passbCopy[1]) / (Math.pow(stopb[0], 2) - passbCopy[0] * passbCopy[1]); possibilities[1] = stopb[1] * (passbCopy[0] - passbCopy[1]) / (Math.pow(stopb[1], 2) - passbCopy[0] * passbCopy[1]); double nat = Math.min(Math.abs(possibilities[0]), Math.abs(possibilities[1])); double GSTOP = Math.pow(10, 0.1 * Math.abs(gstop)); double GPASS = Math.pow(10, 0.1 * Math.abs(gpass)); double filterOrder = SpecialMath.acosh(Math.sqrt((GSTOP - 1.0) / (GPASS - 1.0))) / SpecialMath.acosh(nat); return filterOrder; } }