/* Chebyshev1IIRDesigner.java created 2010-09-12
*
*/
package org.signalml.math.iirdesigner;
import org.apache.commons.math.complex.Complex;
import org.signalml.math.iirdesigner.math.SpecialMath;
/**
* This class represents a designer which is capable of designing a Chebyshev I filter.
*
* @author Piotr Szachewicz
*/
class Chebyshev1IIRDesigner extends ChebyshevIIRDesigner {
/**
* Returns zeros, poles, and gain of an normalized prototype analog
* lowpass Chebyshev I filter which meets the specification.
*
* @param filterOrder the order of the prototype
* @param gpass the maximum loss in the passband [dB]
* @param gstop the minimum attenuation in the stopband [dB]
* @return zeros, poles and gain of the filter prototype which meets the given specification
*/
@Override
protected FilterZerosPolesGain calculatePrototype(int filterOrder, double gpass, double gstop) {
return calculatePrototype(filterOrder, gpass);
}
/**
* Returns zeros, poles, and gain of an normalized prototype analog
* lowpass Chebyshev I filter which meets the specification.
*
* @param filterOrder the order of the prototype
* @param gpass the maximum loss in the passband [dB]
* @return zeros, poles and gain of the filter prototype which meets the given specification
*/
protected FilterZerosPolesGain calculatePrototype(int filterOrder, double gpass) {
double epsilon = Math.sqrt(Math.pow(10, 0.1 * gpass) - 1.0);
double mu = 1.0 / filterOrder * Math.log((1.0 + Math.sqrt(1.0 + epsilon * epsilon)) / epsilon);
Complex[] poles = new Complex[filterOrder];
//calculate the poles
double theta;
for (int i = 1; i <= filterOrder; i++) {
theta = Math.PI / 2.0 * (2 * i - 1.0) / filterOrder;
poles[i-1] = new Complex(-Math.sinh(mu) * Math.sin(theta), Math.cosh(mu) * Math.cos(theta));
}
//calculate gain
Complex product = new Complex(1.0, 0.0);
for (int i = 0; i < poles.length; i++)
product = product.multiply(poles[i].negate());
double gain = product.getReal();
if (SpecialMath.isEven(filterOrder))
gain = gain / Math.sqrt(1 + epsilon * epsilon);
//return zeros, poles & gain
FilterZerosPolesGain zpk = new FilterZerosPolesGain(new Complex[0], poles, gain);
return zpk;
}
/**
* Calculates the natural (critical) frequencies for a given specification (the 3dB frequency)
*
* @param type type of the filter (lowpass/highpass/bandpass/bandstop)
* @param filterOrder the order of the filter to be designed (can be calculated using {@link AbstractIIRDesigner#calculateFilterOrder(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double, boolean) })
* @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 critical frequencies
*/
@Override
protected double[] calculateNaturalFrequency(FilterType type, int filterOrder, double[] wp, double[] ws, double gpass, double gstop, boolean analog) {
if (type.isBandstop()) {
double[] passb;
double[] stopb;
if (!analog) {
passb = prewarpFrequencies(wp);
stopb = prewarpFrequencies(ws);
}
else {
passb = wp.clone();
stopb = ws.clone();
}
double[] result = optimizeBandstopFilterPassbandFrequencies(passb, stopb, gpass, gstop);
passb[0] = result[0];
passb[1] = result[1];
if (!analog)
passb = unwarpFrequencies(passb);
return passb;
}
return wp;
}
}