32 template <
typename FloatType>
35 double sampleRate,
size_t order,
39 jassert (sampleRate > 0);
40 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
44 auto* c = result->getRawCoefficients();
45 auto normalisedFrequency = frequency / sampleRate;
47 for (
size_t i = 0; i <= order; ++i)
51 c[i] =
static_cast<FloatType
> (normalisedFrequency * 2);
56 c[i] =
static_cast<FloatType
> (std::sin (2.0 * indice * normalisedFrequency) / indice);
66 template <
typename FloatType>
69 FloatType normalisedTransitionWidth,
70 FloatType amplitudedB)
72 jassert (sampleRate > 0);
73 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
74 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
75 jassert (amplitudedB >= -100 && amplitudedB <= 0);
79 if (amplitudedB < -50)
80 beta =
static_cast<FloatType
> (0.1102 * (-amplitudedB - 8.7));
81 else if (amplitudedB <= -21)
82 beta =
static_cast<FloatType
> (0.5842 * std::pow (-amplitudedB - 21, 0.4) + 0.07886 * (-amplitudedB - 21));
84 int order = amplitudedB < -21 ? roundToInt (std::ceil ((-amplitudedB - 7.95) / (2.285 * normalisedTransitionWidth *
MathConstants<double>::twoPi)))
89 return designFIRLowpassWindowMethod (frequency, sampleRate,
static_cast<size_t> (order),
94 template <
typename FloatType>
97 FloatType normalisedTransitionWidth, FloatType spline)
99 jassert (sampleRate > 0);
100 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
101 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
102 jassert (spline >= 1.0 && spline <= 4.0);
104 auto normalisedFrequency = frequency /
static_cast<FloatType
> (sampleRate);
107 auto* c = result->getRawCoefficients();
109 for (
size_t i = 0; i <= order; ++i)
111 if (i == order / 2 && order % 2 == 0)
113 c[i] =
static_cast<FloatType
> (2 * normalisedFrequency);
119 c[i] =
static_cast<FloatType
> (std::sin (2 * indice * normalisedFrequency)
120 / indice * std::pow (std::sin (indice2) / indice2, spline));
127 template <
typename FloatType>
130 double sampleRate,
size_t order,
131 FloatType normalisedTransitionWidth,
132 FloatType stopBandWeight)
134 jassert (sampleRate > 0);
135 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
136 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
137 jassert (stopBandWeight >= 1.0 && stopBandWeight <= 100.0);
139 auto normalisedFrequency =
static_cast<double> (frequency) / sampleRate;
147 auto* c = result->getRawCoefficients();
152 auto M = (N - 1) / 2;
163 for (
size_t i = 0; i <= M; ++i)
164 b (i, 0) = factorp * sinc (factorp * i);
166 q (0, 0) = factorp + stopBandWeight * (1.0 - factors);
168 for (
size_t i = 1; i <= 2 * M; ++i)
169 q (i, 0) = factorp * sinc (factorp * i) - stopBandWeight * factors * sinc (factors * i);
178 c[M] =
static_cast<FloatType
> (b (0, 0));
180 for (
size_t i = 1; i <= M; ++i)
182 c[M - i] =
static_cast<FloatType
> (b (i, 0) * 0.5);
183 c[M + i] =
static_cast<FloatType
> (b (i, 0) * 0.5);
201 for (
size_t i = 0; i < M; ++i)
202 b (i, 0) = factorp * sinc (factorp * (i + 0.5));
204 for (
size_t i = 0; i < 2 * M; ++i)
206 qp (i, 0) = 0.25 * factorp * sinc (factorp * i);
207 qs (i, 0) = -0.25 * stopBandWeight * factors * sinc (factors * i);
216 Id *= (0.25 * stopBandWeight);
227 for (
size_t i = 0; i < M; ++i)
229 c[M - i - 1] =
static_cast<FloatType
> (b (i, 0) * 0.25);
230 c[M + i] =
static_cast<FloatType
> (b (i, 0) * 0.25);
237 template <
typename FloatType>
240 FloatType amplitudedB)
242 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
243 jassert (amplitudedB >= -300 && amplitudedB <= -10);
247 auto n = roundToInt (std::ceil ((amplitudedB - 18.18840664 * wpT + 33.64775300) / (18.54155181 * wpT - 29.13196871)));
248 auto kp = (n * wpT - 1.57111377 * n + 0.00665857) / (-1.01927560 * n + 0.37221484);
249 auto A = (0.01525753 * n + 0.03682344 + 9.24760314 / (double) n) * kp + 1.01701407 + 0.73512298 / (double) n;
250 auto B = (0.00233667 * n - 1.35418408 + 5.75145813 / (double) n) * kp + 1.02999650 - 0.72759508 / (double) n;
255 auto diff = (hn.size() - hnm.size()) / 2;
257 for (
int i = 0; i < diff; ++i)
265 for (
int i = 0; i < hn.size(); ++i)
266 hh.setUnchecked (i, A * hh[i] + B * hnm[i]);
269 auto* c = result->getRawCoefficients();
271 for (
int i = 0; i < hh.size(); ++i)
272 c[i] = (
float) hh[i];
278 NN = 2.0 * result->getMagnitudeForFrequency (0.5, 1.0);
283 auto om01 = std::acos (-w01);
288 for (
int i = 0; i < hh.size(); ++i)
289 c[i] =
static_cast<FloatType
> ((A * hn[i] + B * hnm[i]) / NN);
291 c[2 * n + 1] =
static_cast<FloatType
> (0.5);
296 template <
typename FloatType>
302 alpha.
setUnchecked (2 * n, 1.0 / std::pow (1.0 - kp * kp, n));
305 alpha.
setUnchecked (2 * n - 2, -(2 * n * kp * kp + 1) * alpha[2 * n]);
308 alpha.
setUnchecked (2 * n - 4, -(4 * n + 1 + (n - 1) * (2 * n - 1) * kp * kp) / (2.0 * n) * alpha[2 * n - 2]
309 - (2 * n + 1) * ((n + 1) * kp * kp + 1) / (2.0 * n) * alpha[2 * n]);
311 for (
int k = n; k >= 3; --k)
313 auto c1 = (3 * (n*(n + 2) - k * (k - 2)) + 2 * k - 3 + 2 * (k - 2)*(2 * k - 3) * kp * kp) * alpha[2 * k - 4];
314 auto c2 = (3 * (n*(n + 2) - (k - 1) * (k + 1)) + 2 * (2 * k - 1) + 2 * k*(2 * k - 1) * kp * kp) * alpha[2 * k - 2];
315 auto c3 = (n * (n + 2) - (k - 1) * (k + 1)) * alpha[2 * k];
316 auto c4 = (n * (n + 2) - (k - 3) * (k - 1));
322 ai.
resize (2 * n + 1 + 1);
324 for (
int k = 0; k <= n; ++k)
325 ai.
setUnchecked (2 * k + 1, alpha[2 * k] / (2.0 * k + 1.0));
328 hn.
resize (2 * n + 1 + 2 * n + 1 + 1);
330 for (
int k = 0; k <= n; ++k)
332 hn.
setUnchecked (2 * n + 1 + (2 * k + 1), 0.5 * ai[2 * k + 1]);
333 hn.
setUnchecked (2 * n + 1 - (2 * k + 1), 0.5 * ai[2 * k + 1]);
339 template <
typename FloatType>
340 ReferenceCountedArray<IIR::Coefficients<FloatType>>
342 FloatType normalisedTransitionWidth,
343 FloatType passbandAmplitudedB,
344 FloatType stopbandAmplitudedB)
346 return designIIRLowpassHighOrderGeneralMethod (0, frequency, sampleRate, normalisedTransitionWidth,
347 passbandAmplitudedB, stopbandAmplitudedB);
350 template <
typename FloatType>
353 FloatType normalisedTransitionWidth,
354 FloatType passbandAmplitudedB,
355 FloatType stopbandAmplitudedB)
357 return designIIRLowpassHighOrderGeneralMethod (1, frequency, sampleRate, normalisedTransitionWidth,
358 passbandAmplitudedB, stopbandAmplitudedB);
361 template <
typename FloatType>
364 FloatType normalisedTransitionWidth,
365 FloatType passbandAmplitudedB,
366 FloatType stopbandAmplitudedB)
368 return designIIRLowpassHighOrderGeneralMethod (2, frequency, sampleRate, normalisedTransitionWidth,
369 passbandAmplitudedB, stopbandAmplitudedB);
372 template <
typename FloatType>
375 FloatType normalisedTransitionWidth,
376 FloatType passbandAmplitudedB,
377 FloatType stopbandAmplitudedB)
379 return designIIRLowpassHighOrderGeneralMethod (3, frequency, sampleRate, normalisedTransitionWidth,
380 passbandAmplitudedB, stopbandAmplitudedB);
383 template <
typename FloatType>
386 FloatType normalisedTransitionWidth,
387 FloatType passbandAmplitudedB,
388 FloatType stopbandAmplitudedB)
390 jassert (sampleRate > 0);
391 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
392 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
393 jassert (passbandAmplitudedB > -20 && passbandAmplitudedB < 0);
394 jassert (stopbandAmplitudedB > -300 && stopbandAmplitudedB < -20);
396 auto normalisedFrequency = frequency / sampleRate;
398 auto fp = normalisedFrequency - normalisedTransitionWidth / 2;
399 auto fs = normalisedFrequency + normalisedTransitionWidth / 2;
401 double Ap = passbandAmplitudedB;
402 double As = stopbandAmplitudedB;
405 auto epsp = std::sqrt (1.0 / (Gp * Gp) - 1.0);
406 auto epss = std::sqrt (1.0 / (Gs * Gs) - 1.0);
412 auto k = omegap / omegas;
413 auto k1 = epsp / epss;
419 N = roundToInt (std::ceil (std::log (1.0 / k1) / std::log (1.0 / k)));
421 else if (type == 1 || type == 2)
423 N = roundToInt (std::ceil (std::acosh (1.0 / k1) / std::acosh (1.0 / k)));
427 double K, Kp, K1, K1p;
432 N = roundToInt (std::ceil ((K1p * K) / (K1 * Kp)));
436 const int L = (N - r) / 2;
437 const double H0 = (type == 1 || type == 3) ? std::pow (Gp, 1.0 - r) : 1.0;
439 Array<Complex<double>> pa, za;
440 Complex<double> j (0, 1);
445 pa.add (-omegap * std::pow (epsp, -1.0 / (
double) N));
447 for (
int i = 1; i <= L; ++i)
449 auto ui = (2 * i - 1.0) / (
double) N;
450 pa.add (omegap * std::pow (epsp, -1.0 / (
double) N) * j * exp (ui * halfPi * j));
455 auto v0 = std::asinh (1.0 / epsp) / (N * halfPi);
458 pa.add (-omegap * std::sinh (v0 * halfPi));
460 for (
int i = 1; i <= L; ++i)
462 auto ui = (2 * i - 1.0) / (
double) N;
463 pa.add (omegap * j * std::cos ((ui - j * v0) * halfPi));
468 auto v0 = std::asinh (epss) / (N * halfPi);
471 pa.add(-1.0 / (k / omegap * std::sinh (v0 * halfPi)));
473 for (
int i = 1; i <= L; ++i)
475 auto ui = (2 * i - 1.0) / (
double) N;
477 pa.add (1.0 / (k / omegap * j * std::cos ((ui - j * v0) * halfPi)));
478 za.add (1.0 / (k / omegap * j * std::cos (ui * halfPi)));
488 for (
int i = 1; i <= L; ++i)
490 auto ui = (2 * i - 1.0) / (
double) N;
494 za.add (omegap * j / (k * zetai));
498 Array<Complex<double>> p, z, g;
502 p.add ((1.0 + pa[0]) / (1.0 - pa[0]));
503 g.add (0.5 * (1.0 - p[0]));
506 for (
int i = 0; i < L; ++i)
508 p.add ((1.0 + pa[i + r]) / (1.0 - pa[i + r]));
509 z.add (za.size() == 0 ? -1.0 : (1.0 + za[i]) / (1.0 - za[i]));
510 g.add ((1.0 - p[i + r]) / (1.0 - z[i]));
513 ReferenceCountedArray<IIR::Coefficients<FloatType>> cascadedCoefficients;
517 auto b0 =
static_cast<FloatType
> (H0 * std::real (g[0]));
519 auto a1 =
static_cast<FloatType
> (-std::real (p[0]));
521 cascadedCoefficients.add (
new IIR::Coefficients<FloatType> (b0, b1, 1.0f, a1));
524 for (
int i = 0; i < L; ++i)
526 auto gain = std::pow (std::abs (g[i + r]), 2.0);
528 auto b0 =
static_cast<FloatType
> (gain);
529 auto b1 =
static_cast<FloatType
> (std::real (-z[i] - std::conj (z[i])) * gain);
530 auto b2 =
static_cast<FloatType
> (std::real ( z[i] * std::conj (z[i])) * gain);
532 auto a1 =
static_cast<FloatType
> (std::real (-p[i+r] - std::conj (p[i + r])));
533 auto a2 =
static_cast<FloatType
> (std::real ( p[i+r] * std::conj (p[i + r])));
535 cascadedCoefficients.add (
new IIR::Coefficients<FloatType> (b0, b1, b2, 1, a1, a2));
538 return cascadedCoefficients;
541 template <
typename FloatType>
542 ReferenceCountedArray<IIR::Coefficients<FloatType>>
544 double sampleRate,
int order)
546 jassert (sampleRate > 0);
547 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
556 for (
auto i = 0; i < order / 2; ++i)
560 static_cast<FloatType
> (Q)));
565 for (
auto i = 0; i < order / 2; ++i)
569 static_cast<FloatType
> (Q)));
576 template <
typename FloatType>
579 double sampleRate,
int order)
581 jassert (sampleRate > 0);
582 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
591 for (
auto i = 0; i < order / 2; ++i)
595 static_cast<FloatType
> (Q)));
600 for (
auto i = 0; i < order / 2; ++i)
604 static_cast<FloatType
> (Q)));
611 template <
typename FloatType>
614 FloatType stopbandAmplitudedB)
616 jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
617 jassert (stopbandAmplitudedB > -300 && stopbandAmplitudedB < -10);
623 auto kp = std::sqrt (1.0 - k * k);
624 auto e = (1 - std::sqrt (kp)) / (1 + std::sqrt (kp)) * 0.5;
625 auto q = e + 2 * std::pow (e, 5.0) + 15 * std::pow (e, 9.0) + 150 * std::pow (e, 13.0);
627 auto k1 = ds * ds / (1 - ds * ds);
628 int n = roundToInt (std::ceil (std::log (k1 * k1 / 16) / std::log (q)));
636 auto q1 = std::pow (q, (
double) n);
637 k1 = 4 * std::sqrt (q1);
639 const int N = (n - 1) / 2;
642 for (
int i = 1; i <= N; ++i)
648 while (std::abs (delta) > 1e-100)
650 delta = std::pow (-1, m) * std::pow (q, m * (m + 1))
656 num *= 2 * std::pow (q, 0.25);
662 while (std::abs (delta) > 1e-100)
664 delta = std::pow (-1, m) * std::pow (q, m * m)
673 auto api = std::sqrt ((1 - wi * wi * k) * (1 - wi * wi / k)) / (1 + wi * wi);
675 ai.
add ((1 - api) / (1 + api));
680 for (
int i = 0; i < N; i += 2)
682 0, 1, 1, 0,
static_cast<FloatType
> (ai[i])));
686 for (
int i = 1; i < N; i += 2)
688 0, 1, 1, 0,
static_cast<FloatType
> (ai[i])));
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
void resize(int targetNumItems)
This will enlarge or shrink the array to the given number of elements, by adding or removing items fr...
static Type decibelsToGain(Type decibels, Type minusInfinityDb=Type(defaultMinusInfinitydB))
Converts a dBFS value to its equivalent gain level.
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
A smart-pointer class which points to a reference-counted object.
General matrix and vectors class, meant for classic math manipulation such as additions,...
static Matrix hankel(const Matrix &vector, size_t size, size_t offset=0)
Creates a squared size x size Hankel Matrix from a vector with an optional offset.
static Matrix identity(size_t size)
Creates the identity matrix.
static Matrix toeplitz(const Matrix &vector, size_t size)
Creates a Toeplitz Matrix from a vector with a given squared size.
A class which provides multiple windowing functions useful for filter design and spectrum analyzers.
void multiplyWithWindowingTable(FloatType *samples, size_t size) noexcept
Multiplies the content of a buffer with the given window.
Commonly used mathematical constants.
A set of coefficients for use in an FIRFilter object.
ReferenceCountedObjectPtr< Coefficients > Ptr
The Coefficients structure is ref-counted, so this is a handy type that can be used as a pointer to o...
This class provides a set of functions which generates FIR::Coefficients and IIR::Coefficients,...
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
This method returns an array of IIR::Coefficients, made to be used in cascaded IIRFilters,...
static FIRCoefficientsPtr designFIRLowpassLeastSquaresMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType stopBandWeight)
This method generates a FIR::Coefficients for a low-pass filter, by minimizing the average error betw...
static FIRCoefficientsPtr designFIRLowpassKaiserMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType amplitudedB)
This a variant of the function designFIRLowpassWindowMethod, which allows the user to specify a trans...
static IIRPolyphaseAllpassStructure designIIRLowpassHalfBandPolyphaseAllpassMethod(FloatType normalisedTransitionWidth, FloatType stopbandAmplitudedB)
This method generates arrays of IIR::Coefficients for a low-pass filter, with a cutoff frequency at h...
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev1Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
This method returns an array of IIR::Coefficients, made to be used in cascaded IIRFilters,...
static ReferenceCountedArray< IIRCoefficients > designIIRHighpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, int order)
This method returns an array of IIR::Coefficients, made to be used in cascaded IIRFilters,...
static FIRCoefficientsPtr designFIRLowpassTransitionMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType spline)
This method is also a variant of the function designFIRLowpassWindowMethod, using a rectangular windo...
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev2Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
This method returns an array of IIR::Coefficients, made to be used in cascaded IIRFilters,...
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderEllipticMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
This method returns an array of IIR::Coefficients, made to be used in cascaded IIR::Filters,...
static FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
This method generates a FIR::Coefficients for a low-pass filter, with a cutoff frequency at half band...
static FIRCoefficientsPtr designFIRLowpassWindowMethod(FloatType frequency, double sampleRate, size_t order, WindowingMethod type, FloatType beta=static_cast< FloatType >(2))
This method generates a FIR::Coefficients for a low-pass filter, using the windowing design method,...
The structure returned by the function designIIRLowpassHalfBandPolyphaseAllpassMethod.
A set of coefficients for use in an Filter object.
static Complex< double > sne(Complex< double > u, double k) noexcept
Computes the Jacobian elliptic function sn for the elliptic modulus k and the quarter-period units u.
static Complex< double > cde(Complex< double > u, double k) noexcept
Computes the Jacobian elliptic function cd for the elliptic modulus k and the quarter-period units u.
static Complex< double > asne(Complex< double > w, double k) noexcept
Computes the inverse of the Jacobian elliptic function sn for the elliptic modulus k and the quarter-...
static void ellipticIntegralK(double k, double &K, double &Kp) noexcept
Computes the complete elliptic integral of the first kind K for a given double value k,...