Add other filters.

topic/diffentiators
Vincent Samy 2018-12-14 18:55:16 +09:00
rodzic 001f25f1cc
commit 3dbaf8036f
2 zmienionych plików z 69 dodań i 25 usunięć

Wyświetl plik

@ -9,6 +9,9 @@ namespace fratio {
// https://www.dsprelated.com/showarticle/1119.php // https://www.dsprelated.com/showarticle/1119.php
template <typename T> template <typename T>
class Butterworth : public GenericFilter<T> { class Butterworth : public GenericFilter<T> {
public:
T PI = static_cast<T>(M_PI);
public: public:
enum class Type { enum class Type {
LowPass, LowPass,
@ -27,14 +30,15 @@ private:
void initialize(size_t order, T fc, T fs); void initialize(size_t order, T fc, T fs);
void computeDigitalRep(); void computeDigitalRep();
void updateCoeffSize(); void updateCoeffSize();
void transformFilter(); std::complex<T> generateAnalogPole(T fpw, size_t k);
std::vector<std::complex<T>> generateAnalogZeros();
void scaleAmplitude();
private: private:
Type m_type; Type m_type;
size_t m_order; size_t m_order;
T m_fc; T m_fc;
T m_fs; T m_fs;
std::vector<std::complex<T>> m_poles;
}; };
} // namespace fratio } // namespace fratio

Wyświetl plik

@ -38,7 +38,6 @@ void Butterworth<T>::initialize(size_t order, T fc, T fs)
m_order = order; m_order = order;
m_fc = fc; m_fc = fc;
m_fs = fs; m_fs = fs;
m_poles.resize(order);
updateCoeffSize(); updateCoeffSize();
computeDigitalRep(); computeDigitalRep();
} }
@ -46,38 +45,26 @@ void Butterworth<T>::initialize(size_t order, T fc, T fs)
template <typename T> template <typename T>
void Butterworth<T>::computeDigitalRep() void Butterworth<T>::computeDigitalRep()
{ {
T pi = static_cast<T>(M_PI);
// Continuous pre-warped frequency // Continuous pre-warped frequency
T fpw = (m_fs / pi) * std::tan(pi * m_fc / m_fs); T fpw = (m_fs / PI) * std::tan(PI * m_fc / m_fs);
T scaleFactor = 2 * pi * fpw;
auto thetaK = [pi, order = m_order](size_t k) -> T {
return (2 * k - 1) * pi / (2 * order);
};
// Compute poles // Compute poles
std::complex<T> scalePole; std::complex<T> analogPole;
std::vector<std::complex<T>> poles(m_order);
for (size_t k = 1; k <= m_order; ++k) { for (size_t k = 1; k <= m_order; ++k) {
scalePole = scaleFactor * std::complex<T>(-std::sin(thetaK(k)), std::cos(thetaK(k))); analogPole = generateAnalogPole(fpw, k);
BilinearTransform<std::complex<T>>::SToZ(m_fs, scalePole, m_poles[k - 1]); BilinearTransform<std::complex<T>>::SToZ(m_fs, analogPole, poles[k - 1]);
} }
std::vector<std::complex<T>> numPoles(m_order, std::complex<T>(-1)); std::vector<std::complex<T>> zeros = generateAnalogZeros();
std::vector<std::complex<T>> a = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(m_poles); std::vector<std::complex<T>> a = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(poles);
std::vector<std::complex<T>> b = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(numPoles); std::vector<std::complex<T>> b = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(zeros);
T norm = 0;
T sumB = 0;
for (size_t i = 0; i < m_order + 1; ++i) { for (size_t i = 0; i < m_order + 1; ++i) {
m_aCoeff[i] = a[i].real(); m_aCoeff[i] = a[i].real();
m_bCoeff[i] = b[i].real(); m_bCoeff[i] = b[i].real();
norm += m_aCoeff[i];
sumB += m_bCoeff[i];
} }
norm /= sumB; scaleAmplitude();
for (auto& b : m_bCoeff)
b *= norm;
checkCoeff(m_aCoeff, m_bCoeff); checkCoeff(m_aCoeff, m_bCoeff);
} }
@ -90,16 +77,69 @@ void Butterworth<T>::updateCoeffSize()
} }
template <typename T> template <typename T>
void Butterworth<T>::transformFilter() std::complex<T> Butterworth<T>::generateAnalogPole(T fpw, size_t k)
{
T scaleFactor = 2 * PI * fpw;
auto thetaK = [pi = PI, order = m_order](size_t k) -> T {
return (2 * k - 1) * pi / (2 * order);
};
std::complex<T> analogPole(-std::sin(thetaK(k)), std::cos(thetaK(k)));
switch (m_type) {
case Type::HighPass:
return scaleFactor / analogPole;
case Type::LowPass:
default:
return scaleFactor * analogPole;
}
}
template <typename T>
std::vector<std::complex<T>> Butterworth<T>::generateAnalogZeros()
{ {
switch (m_type) { switch (m_type) {
case Type::HighPass: case Type::HighPass:
return std::vector<std::complex<T>>(m_order, std::complex<T>(1));
case Type::LowPass:
default:
return std::vector<std::complex<T>>(m_order, std::complex<T>(-1));
}
}
template <typename T>
void Butterworth<T>::scaleAmplitude()
{
T scale = 0;
T sumB = 0;
switch (m_type) {
case Type::HighPass:
for (size_t i = 0; i < m_order + 1; ++i) {
if (i % 2 == 0) {
scale += m_aCoeff[i];
sumB += m_bCoeff[i];
} else {
scale -= m_aCoeff[i];
sumB -= m_bCoeff[i];
}
}
break; break;
case Type::LowPass: case Type::LowPass:
default: default:
for (size_t i = 0; i < m_order + 1; ++i) {
scale += m_aCoeff[i];
sumB += m_bCoeff[i];
}
break; break;
} }
scale /= sumB;
for (auto& b : m_bCoeff)
b *= scale;
} }
} // namespace fratio } // namespace fratio