//! fcd = cut-off (1=sampling rate) //! ord = Filter order //! ripple = passband ripple in dB void chebyshev_iir(iir_coeff& filt, float_type fcd, bool lpf, float_type ripple = 3.0) { const float_type ten = 10.0; long order = filt.order; float_type epi = pow(ten, (ripple / ten)) - 1.0; epi = pow(epi, (float_type)(1. / (1.0 * order))); float_type wca = tan(0.5 * PI * fcd); //! wca - pre-warped angular frequency long n2 = (order + 1) / 2; chebyshev_s(filt.poles, filt.zeros, lpf, wca, epi, order, n2); filt.bilinear(); filt.convert_to_ab(); }
//! fcd = cut-off (1=sampling rate) //! ord = Filter order //! ripple = passband ripple in dB void chebyshev2_iir(iir_coeff& filt, float_type fcd, float_type stopband = 40.0) { const float_type ten = 10.0; auto order = filt.getOrder(); float_type delta = pow(ten, -stopband/20.0); float_type epi = delta/sqrt(1 - delta*delta); float_type wca = (filt.get_type()==filter_type::high) ? tan(M_PI * (0.5-fcd)) : tan(M_PI*fcd); chebyshev2_s(filt, wca, epi, order); filt.bilinear(); if (filt.get_type()==filter_type::bandpass || filt.get_type()==filter_type::bandstop) { filt.make_band(filt.get_center()); } else { filt.convert_to_ab(); } if (filt.get_type()==filter_type::bandpass) filt.set_bandpass_gain(); }
// Get frequency response for IIR void iir_freq(iir_coeff& MF, int pts, double* w, double inc) { double w_inc = inc*M_PI/(float)pts; for (int i=0;i<pts;i++) { double t = MF.freqz_mag(w_inc*i); if (t==0) t = 0.00001; w[i] = 20.0*log(t)/log(10.0); } }
//! Calculate poles (chebyshev) void chebyshev2_s(iir_coeff& filt, float_type wp, float_type epi, size_t order) { auto l = 1; size_t n2 = (order + 1) / 2; float_type x = 1 / epi; float_type lambda = pow(x*(1.0 + sqrt(1.0 + epi*epi)),1.0/order); float_type sm = 0.5*((1.0/lambda) - lambda); float_type cm = 0.5*((1.0/lambda) + lambda); for (size_t j = 0; j < n2; j++) { float_type arg = M_PI * (2*l-1) / ((float_type)(2*order)); std::complex<float_type> p = std::complex<float_type>(sm * sin(arg), cm * cos(arg)); if (filt.get_type()==filter_type::low) { // Get regular chebyshev pole first // then transform for inverse chebyshev filt.set_pole((-wp*p/norm(p)), n2-1-j); // inverse chebyshev zero filt.set_zero(std::complex<float_type>(0,wp/cos(arg)),n2-1-j); } else { filt.set_pole(-p/wp, n2-1-j); filt.set_zero(std::complex<float_type>(0,cos(arg)/wp),n2-1-j); } l++; } }