#include "polynome_functions.h" #include #include namespace fratio { template Butterworth::Butterworth(Type type) : m_type(type) { } template Butterworth::Butterworth(size_t order, T fc, T fs, Type type) : m_type(type) { initialize(order, fc, fs); } template void Butterworth::setFilterParameters(size_t order, T fc, T fs) { initialize(order, fc, fs); } template void Butterworth::initialize(size_t order, T fc, T fs) { if (m_fc > m_fs / 2.) { m_status = FilterStatus::BAD_CUTOFF_FREQUENCY; return; } m_order = order; m_fc = fc; m_fs = fs; m_poles.resize(order); updateCoeffSize(); computeDigitalRep(); } template void Butterworth::computeDigitalRep() { T pi = static_cast(M_PI); // Continuous pre-warped frequency T fpw = (m_fs / pi) * std::tan(pi * m_fc / m_fs); T scaleFactor = T(2) * pi * fpw; auto thetaK = [pi, order = m_order](size_t k) -> T { return (T(2) * k - T(1)) * pi / (T(2) * order); }; // Compute poles std::complex scalePole; for (size_t k = 1; k <= m_order; ++k) { scalePole = scaleFactor * std::complex(-std::sin(thetaK(k)), std::cos(thetaK(k))); scalePole /= T(2) * m_fs; m_poles(k - 1) = (T(1) + scalePole) / (T(1) - scalePole); } Eigen::VectorX> numPoles = Eigen::VectorX::Constant(m_order, std::complex(-1)); Eigen::VectorX> a = VietaAlgo>::polyCoeffFromRoot(m_poles); Eigen::VectorX> b = VietaAlgo>::polyCoeffFromRoot(numPoles); T norm = 0; T sumB = 0; for (size_t i = 0; i < m_order + 1; ++i) { m_aCoeff(i) = a(i).real(); m_bCoeff(i) = b(i).real(); norm += m_aCoeff(i); sumB += m_bCoeff(i); } norm /= sumB; m_bCoeff *= norm; checkCoeffs(m_aCoeff, m_bCoeff); } template void Butterworth::updateCoeffSize() { m_aCoeff.resize(m_order + 1); m_bCoeff.resize(m_order + 1); resetFilter(); } } // namespace fratio