void AnalogLowPass::design (int numPoles, WorkspaceBase* w) { if (m_numPoles != numPoles) { m_numPoles = numPoles; reset (); RootFinderBase& solver (w->roots); for (int i = 0; i < numPoles + 1; ++i) solver.coef()[i] = reversebessel (i, numPoles); solver.solve (numPoles); const int pairs = numPoles / 2; for (int i = 0; i < pairs; ++i) { complex_t c = solver.root()[i]; addPoleZeroConjugatePairs (c, infinity()); } if (numPoles & 1) add (solver.root()[pairs].real(), infinity()); } }
void AnalogLowShelf::design (int numPoles, double gainDb) { if (m_numPoles != numPoles || m_gainDb != gainDb) { m_numPoles = numPoles; m_gainDb = gainDb; reset (); const double n2 = numPoles * 2; const double g = pow (pow (10., gainDb/20), 1. / n2); const double gp = -1. / g; const double gz = -g; const int pairs = numPoles / 2; for (int i = 1; i <= pairs; ++i) { const double theta = doublePi * (0.5 - (2 * i - 1) / n2); addPoleZeroConjugatePairs (std::polar (std::abs(gp), theta), std::polar (std::abs(gz), theta)); } if (numPoles & 1) add (gp, gz); } }
void AnalogLowPass::design (int numPoles, double stopBandDb) { if (m_numPoles != numPoles || m_stopBandDb != stopBandDb) { m_numPoles = numPoles; m_stopBandDb = stopBandDb; reset (); const double eps = std::sqrt (1. / (std::exp (stopBandDb * 0.1 * doubleLn10) - 1)); const double v0 = asinh (1 / eps) / numPoles; const double sinh_v0 = -sinh (v0); const double cosh_v0 = cosh (v0); const double fn = doublePi / (2 * numPoles); int k = 1; for (int i = numPoles / 2; --i >= 0; k+=2) { const double a = sinh_v0 * cos ((k - numPoles) * fn); const double b = cosh_v0 * sin ((k - numPoles) * fn); const double d2 = a * a + b * b; const double im = 1 / cos (k * fn); addPoleZeroConjugatePairs (complex_t (a / d2, b / d2), complex_t (0, im)); } if (numPoles & 1) { add (1 / sinh_v0, infinity()); } } }
void AnalogLowShelf::design (int numPoles, double gainDb, double stopBandDb) { if (m_numPoles != numPoles || m_stopBandDb != stopBandDb || m_gainDb != gainDb) { m_numPoles = numPoles; m_stopBandDb = stopBandDb; m_gainDb = gainDb; reset (); gainDb = -gainDb; if (stopBandDb >= fabs(gainDb)) stopBandDb = fabs (gainDb); if (gainDb<0) stopBandDb = -stopBandDb; const double G = std::pow (10., gainDb / 20.0 ); const double Gb = std::pow (10., (gainDb - stopBandDb) / 20.0); const double G0 = 1; const double g0 = pow (G0 , 1. / numPoles); double eps; if (Gb != G0 ) eps = sqrt((G*G-Gb*Gb)/(Gb*Gb-G0*G0)); else eps = G-1; // This is surely wrong const double b = pow (G/eps+Gb*sqrt(1+1/(eps*eps)), 1./numPoles); const double u = log (b / g0); const double v = log (pow (1. / eps+sqrt(1+1/(eps*eps)),1./numPoles)); const double sinh_u = sinh (u); const double sinh_v = sinh (v); const double cosh_u = cosh (u); const double cosh_v = cosh (v); const double n2 = 2 * numPoles; const int pairs = numPoles / 2; for (int i = 1; i <= pairs; ++i) { const double a = doublePi * (2 * i - 1) / n2; const double sn = sin (a); const double cs = cos (a); addPoleZeroConjugatePairs (complex_t (-sn * sinh_u, cs * cosh_u), complex_t (-sn * sinh_v, cs * cosh_v)); } if (numPoles & 1) add (-sinh_u, -sinh_v); } }
void AnalogLowPass::design (int numPoles, WorkspaceBase* w) { if (m_numPoles != numPoles) { m_numPoles = numPoles; reset (); PolynomialFinderBase& poly (w->poly); RootFinderBase& poles (w->roots); poly.solve (numPoles); int degree = numPoles * 2; poles.coef()[0] = 1 + poly.coef()[0]; poles.coef()[1] = 0; for (int i = 1; i <= degree; ++i) { poles.coef()[2*i] = poly.coef()[i] * ((i & 1) ? -1 : 1); poles.coef()[2*i+1] = 0; } poles.solve (degree); int j = 0; for (int i = 0; i < degree; ++i) if (poles.root()[i].real() <= 0) poles.root()[j++] = poles.root()[i]; // sort descending imag() and cut degree in half poles.sort (degree/2); const int pairs = numPoles / 2; for (int i = 0; i < pairs; ++i) { complex_t c = poles.root()[i]; addPoleZeroConjugatePairs (c, infinity()); } if (numPoles & 1) add (poles.root()[pairs].real(), infinity()); } }
void AnalogLowPass::design (int numPoles) { if (m_numPoles != numPoles) { m_numPoles = numPoles; reset (); const double n2 = 2 * numPoles; const int pairs = numPoles / 2; for (int i = 0; i < pairs; ++i) { complex_t c = std::polar (1., doublePi_2 + (2 * i + 1) * doublePi / n2); addPoleZeroConjugatePairs (c, infinity()); } if (numPoles & 1) add (-1, infinity()); } }
void AnalogLowPass::design(int numPoles, double rippleDb) { if (m_numPoles != numPoles || m_rippleDb != rippleDb) { m_numPoles = numPoles; m_rippleDb = rippleDb; reset(); const double eps = std::sqrt(1. / std::exp(-rippleDb * 0.1 * doubleLn10) - 1); const double v0 = asinh(1 / eps) / numPoles; const double sinh_v0 = -sinh(v0); const double cosh_v0 = cosh(v0); const double n2 = 2 * numPoles; const int pairs = numPoles / 2; for (int i = 0; i < pairs; ++i) { const int k = 2 * i + 1 - numPoles; double a = sinh_v0 * cos(k * doublePi / n2); double b = cosh_v0 * sin(k * doublePi / n2); //addPoleZero (complex_t (a, b), infinity()); //addPoleZero (complex_t (a, -b), infinity()); addPoleZeroConjugatePairs(complex_t (a, b), infinity()); } if (numPoles & 1) { add(complex_t (sinh_v0, 0), infinity()); setNormal(0, 1); } else { setNormal(0, pow(10, -rippleDb/20.)); } } }
void AnalogLowShelf::design (int numPoles, double gainDb, WorkspaceBase* w) { if (m_numPoles != numPoles || m_gainDb != gainDb) { m_numPoles = numPoles; m_gainDb = gainDb; reset (); const double G = pow (10., gainDb / 20) - 1; RootFinderBase& poles (w->roots); for (int i = 0; i < numPoles + 1; ++i) poles.coef()[i] = reversebessel (i, numPoles); poles.solve (numPoles); RootFinder<50> zeros; for (int i = 0; i < numPoles + 1; ++i) zeros.coef()[i] = reversebessel (i, numPoles); double a0 = reversebessel (0, numPoles); zeros.coef()[0] += G * a0; zeros.solve (numPoles); const int pairs = numPoles / 2; for (int i = 0; i < pairs; ++i) { complex_t p = poles.root()[i]; complex_t z = zeros.root()[i]; addPoleZeroConjugatePairs (p, z); } if (numPoles & 1) add (poles.root()[pairs].real(), zeros.root()[pairs].real()); } }