32 template <
typename FloatType>
35 double sampleRate,
size_t order,
39 jassert (sampleRate > 0);
40 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
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)))
85 : roundToInt (std::ceil (5.79 / (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);
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;
158 / (MathConstants<double>::pi * x); };
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);
196 / (MathConstants<double>::pi * x); };
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>
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;
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));
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]));
517 auto b0 =
static_cast<FloatType
> (H0 * std::real (g[0]));
519 auto a1 =
static_cast<FloatType
> (-std::real (p[0]));
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])));
538 return cascadedCoefficients;
541 template <
typename 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])));
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, providing a minimum phase low-pass filter without any ripple in the stop band only.
A set of coefficients for use in an FIRFilter object.
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, providing a minimum phase low-pass filter with ripples in both the pass band and in the stop band.
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, providing a minimum phase low-pass filter without any ripple in the pass band only.
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 Type decibelsToGain(Type decibels, Type minusInfinityDb=Type(defaultMinusInfinitydB))
Converts a dBFS value to its equivalent gain level.
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.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
ReferenceCountedObjectPtr< Coefficients > Ptr
The Coefficients structure is ref-counted, so this is a handy type that can be used as a pointer to o...
static Matrix identity(size_t size)
Creates the identity matrix.
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...
void resize(int targetNumItems)
This will enlarge or shrink the array to the given number of elements, by adding or removing items fr...
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.
NumericType * getRawCoefficients() noexcept
Returns a raw data pointer to the coefficients.
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 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...
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
A set of coefficients for use in an Filter object.
void multiplyWithWindowingTable(FloatType *samples, size_t size) noexcept
Multiplies the content of a buffer with the given window.
A class which provides multiple windowing functions useful for filter design and spectrum analyzers...
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...
int size() const noexcept
Returns the current number of elements in the array.
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 FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
This method generates a FIR::Coefficients for a low-pass filter, with a cutoff frequency at half band...
A smart-pointer class which points to a reference-counted 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 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, providing a minimum phase low-pass filter without any ripple in the pass band and in the stop band.
The structure returned by the function designIIRLowpassHalfBandPolyphaseAllpassMethod.
Commonly used mathematical constants.
static Matrix toeplitz(const Matrix &vector, size_t size)
Creates a Toeplitz Matrix from a vector with a given squared size.
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...
General matrix and vectors class, meant for classic math manipulation such as additions, multiplications, and linear systems of equations solving.
This class provides a set of functions which generates FIR::Coefficients and IIR::Coefficients, of high-order low-pass filters.
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...
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
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, providing a minimum phase high-pass filter without any ripple in the pass band and in the stop band.