OpenShot Audio Library | OpenShotAudio  0.6.0
juce_FilterDesign.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11  Agreement and JUCE Privacy Policy.
12 
13  End User License Agreement: www.juce.com/juce-7-licence
14  Privacy Policy: www.juce.com/juce-privacy-policy
15 
16  Or: You may also use this code under the terms of the GPL v3 (see
17  www.gnu.org/licenses).
18 
19  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21  DISCLAIMED.
22 
23  ==============================================================================
24 */
25 
26 namespace juce::dsp
27 {
28 
29 template <typename FloatType>
32  double sampleRate, size_t order,
33  WindowingMethod type,
34  FloatType beta)
35 {
36  jassert (sampleRate > 0);
37  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
38 
39  auto* result = new typename FIR::Coefficients<FloatType> (order + 1u);
40 
41  auto* c = result->getRawCoefficients();
42  auto normalisedFrequency = frequency / sampleRate;
43 
44  for (size_t i = 0; i <= order; ++i)
45  {
46  if (i == order / 2)
47  {
48  c[i] = static_cast<FloatType> (normalisedFrequency * 2);
49  }
50  else
51  {
52  auto indice = MathConstants<double>::pi * (static_cast<double> (i) - 0.5 * static_cast<double> (order));
53  c[i] = static_cast<FloatType> (std::sin (2.0 * indice * normalisedFrequency) / indice);
54  }
55  }
56 
57  WindowingFunction<FloatType> theWindow (order + 1, type, false, beta);
58  theWindow.multiplyWithWindowingTable (c, order + 1);
59 
60  return *result;
61 }
62 
63 template <typename FloatType>
65  FilterDesign<FloatType>::designFIRLowpassKaiserMethod (FloatType frequency, double sampleRate,
66  FloatType normalisedTransitionWidth,
67  FloatType amplitudedB)
68 {
69  jassert (sampleRate > 0);
70  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
71  jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
72  jassert (amplitudedB >= -100 && amplitudedB <= 0);
73 
74  FloatType beta = 0;
75 
76  if (amplitudedB < -50)
77  beta = static_cast<FloatType> (0.1102 * (-amplitudedB - 8.7));
78  else if (amplitudedB <= -21)
79  beta = static_cast<FloatType> (0.5842 * std::pow (-amplitudedB - 21, 0.4) + 0.07886 * (-amplitudedB - 21));
80 
81  int order = amplitudedB < -21 ? roundToInt (std::ceil ((-amplitudedB - 7.95) / (2.285 * normalisedTransitionWidth * MathConstants<double>::twoPi)))
82  : roundToInt (std::ceil (5.79 / (normalisedTransitionWidth * MathConstants<double>::twoPi)));
83 
84  jassert (order >= 0);
85 
86  return designFIRLowpassWindowMethod (frequency, sampleRate, static_cast<size_t> (order),
88 }
89 
90 
91 template <typename FloatType>
93  FilterDesign<FloatType>::designFIRLowpassTransitionMethod (FloatType frequency, double sampleRate, size_t order,
94  FloatType normalisedTransitionWidth, FloatType spline)
95 {
96  jassert (sampleRate > 0);
97  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
98  jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
99  jassert (spline >= 1.0 && spline <= 4.0);
100 
101  auto normalisedFrequency = frequency / static_cast<FloatType> (sampleRate);
102 
103  auto* result = new typename FIR::Coefficients<FloatType> (order + 1u);
104  auto* c = result->getRawCoefficients();
105 
106  for (size_t i = 0; i <= order; ++i)
107  {
108  if (i == order / 2 && order % 2 == 0)
109  {
110  c[i] = static_cast<FloatType> (2 * normalisedFrequency);
111  }
112  else
113  {
114  auto indice = MathConstants<double>::pi * ((double) i - 0.5 * (double) order);
115  auto indice2 = MathConstants<double>::pi * normalisedTransitionWidth * ((double) i - 0.5 * (double) order) / spline;
116  c[i] = static_cast<FloatType> (std::sin (2 * indice * normalisedFrequency)
117  / indice * std::pow (std::sin (indice2) / indice2, spline));
118  }
119  }
120 
121  return *result;
122 }
123 
124 template <typename FloatType>
127  double sampleRate, size_t order,
128  FloatType normalisedTransitionWidth,
129  FloatType stopBandWeight)
130 {
131  jassert (sampleRate > 0);
132  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
133  jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
134  jassert (stopBandWeight >= 1.0 && stopBandWeight <= 100.0);
135 
136  auto normalisedFrequency = static_cast<double> (frequency) / sampleRate;
137 
138  auto wp = MathConstants<double>::twoPi * (static_cast<double> (normalisedFrequency - normalisedTransitionWidth / 2.0));
139  auto ws = MathConstants<double>::twoPi * (static_cast<double> (normalisedFrequency + normalisedTransitionWidth / 2.0));
140 
141  auto N = order + 1;
142 
143  auto* result = new typename FIR::Coefficients<FloatType> (static_cast<size_t> (N));
144  auto* c = result->getRawCoefficients();
145 
146  auto sinc = [] (double x)
147  {
148  return approximatelyEqual (x, 0.0) ? 1 : std::sin (x * MathConstants<double>::pi) / (MathConstants<double>::pi * x);
149  };
150 
151  if (N % 2 == 1)
152  {
153  // Type I
154  auto M = (N - 1) / 2;
155 
156  Matrix<double> b (M + 1, 1),
157  q (2 * M + 1, 1);
158 
159  auto factorp = wp / MathConstants<double>::pi;
160  auto factors = ws / MathConstants<double>::pi;
161 
162  for (size_t i = 0; i <= M; ++i)
163  b (i, 0) = factorp * sinc (factorp * (double) i);
164 
165  q (0, 0) = factorp + stopBandWeight * (1.0 - factors);
166 
167  for (size_t i = 1; i <= 2 * M; ++i)
168  q (i, 0) = factorp * sinc (factorp * (double) i) - stopBandWeight * factors * sinc (factors * (double) i);
169 
170  auto Q1 = Matrix<double>::toeplitz (q, M + 1);
171  auto Q2 = Matrix<double>::hankel (q, M + 1, 0);
172 
173  Q1 += Q2; Q1 *= 0.5;
174 
175  Q1.solve (b);
176 
177  c[M] = static_cast<FloatType> (b (0, 0));
178 
179  for (size_t i = 1; i <= M; ++i)
180  {
181  c[M - i] = static_cast<FloatType> (b (i, 0) * 0.5);
182  c[M + i] = static_cast<FloatType> (b (i, 0) * 0.5);
183  }
184  }
185  else
186  {
187  // Type II
188  auto M = N / 2;
189 
190  Matrix<double> b (M, 1);
191  Matrix<double> qp (2 * M, 1);
192  Matrix<double> qs (2 * M, 1);
193 
194  auto factorp = wp / MathConstants<double>::pi;
195  auto factors = ws / MathConstants<double>::pi;
196 
197  for (size_t i = 0; i < M; ++i)
198  b (i, 0) = factorp * sinc (factorp * ((double) i + 0.5));
199 
200  for (size_t i = 0; i < 2 * M; ++i)
201  {
202  qp (i, 0) = 0.25 * factorp * sinc (factorp * (double) i);
203  qs (i, 0) = -0.25 * stopBandWeight * factors * sinc (factors * (double) i);
204  }
205 
206  auto Q1p = Matrix<double>::toeplitz (qp, M);
207  auto Q2p = Matrix<double>::hankel (qp, M, 1);
208  auto Q1s = Matrix<double>::toeplitz (qs, M);
209  auto Q2s = Matrix<double>::hankel (qs, M, 1);
210 
211  auto Id = Matrix<double>::identity (M);
212  Id *= (0.25 * stopBandWeight);
213 
214  Q1p += Q2p;
215  Q1s += Q2s;
216  Q1s += Id;
217 
218  auto& Q = Q1s;
219  Q += Q1p;
220 
221  Q.solve (b);
222 
223  for (size_t i = 0; i < M; ++i)
224  {
225  c[M - i - 1] = static_cast<FloatType> (b (i, 0) * 0.25);
226  c[M + i] = static_cast<FloatType> (b (i, 0) * 0.25);
227  }
228  }
229 
230  return *result;
231 }
232 
233 template <typename FloatType>
236  FloatType amplitudedB)
237 {
238  jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
239  jassert (amplitudedB >= -300 && amplitudedB <= -10);
240 
241  auto wpT = (0.5 - normalisedTransitionWidth) * MathConstants<double>::pi;
242 
243  auto n = roundToInt (std::ceil ((amplitudedB - 18.18840664 * wpT + 33.64775300) / (18.54155181 * wpT - 29.13196871)));
244  auto kp = (n * wpT - 1.57111377 * n + 0.00665857) / (-1.01927560 * n + 0.37221484);
245  auto A = (0.01525753 * n + 0.03682344 + 9.24760314 / (double) n) * kp + 1.01701407 + 0.73512298 / (double) n;
246  auto B = (0.00233667 * n - 1.35418408 + 5.75145813 / (double) n) * kp + 1.02999650 - 0.72759508 / (double) n;
247 
250 
251  auto diff = (hn.size() - hnm.size()) / 2;
252 
253  for (int i = 0; i < diff; ++i)
254  {
255  hnm.add (0.0);
256  hnm.insert (0, 0.0);
257  }
258 
259  auto hh = hn;
260 
261  for (int i = 0; i < hn.size(); ++i)
262  hh.setUnchecked (i, A * hh[i] + B * hnm[i]);
263 
264  auto* result = new typename FIR::Coefficients<FloatType> (static_cast<size_t> (hh.size()));
265  auto* c = result->getRawCoefficients();
266 
267  for (int i = 0; i < hh.size(); ++i)
268  c[i] = (float) hh[i];
269 
270  auto NN = [&]
271  {
272  if (n % 2 == 0)
273  return 2.0 * result->getMagnitudeForFrequency (0.5, 1.0);
274 
275  auto w01 = std::sqrt (kp * kp + (1 - kp * kp) * std::pow (std::cos (MathConstants<double>::pi / (2.0 * n + 1.0)), 2.0));
276 
277  if (std::abs (w01) > 1.0)
278  return 2.0 * result->getMagnitudeForFrequency (0.5, 1.0);
279 
280  auto om01 = std::acos (-w01);
281  return -2.0 * result->getMagnitudeForFrequency (om01 / MathConstants<double>::twoPi, 1.0);
282  }();
283 
284  for (int i = 0; i < hh.size(); ++i)
285  c[i] = static_cast<FloatType> ((A * hn[i] + B * hnm[i]) / NN);
286 
287  c[2 * n + 1] = static_cast<FloatType> (0.5);
288 
289  return *result;
290 }
291 
292 template <typename FloatType>
294 {
295  Array<double> alpha;
296  alpha.resize (2 * n + 1);
297 
298  alpha.setUnchecked (2 * n, 1.0 / std::pow (1.0 - kp * kp, n));
299 
300  if (n > 0)
301  alpha.setUnchecked (2 * n - 2, -(2 * n * kp * kp + 1) * alpha[2 * n]);
302 
303  if (n > 1)
304  alpha.setUnchecked (2 * n - 4, -(4 * n + 1 + (n - 1) * (2 * n - 1) * kp * kp) / (2.0 * n) * alpha[2 * n - 2]
305  - (2 * n + 1) * ((n + 1) * kp * kp + 1) / (2.0 * n) * alpha[2 * n]);
306 
307  for (int k = n; k >= 3; --k)
308  {
309  auto c1 = (3 * (n*(n + 2) - k * (k - 2)) + 2 * k - 3 + 2 * (k - 2)*(2 * k - 3) * kp * kp) * alpha[2 * k - 4];
310  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];
311  auto c3 = (n * (n + 2) - (k - 1) * (k + 1)) * alpha[2 * k];
312  auto c4 = (n * (n + 2) - (k - 3) * (k - 1));
313 
314  alpha.setUnchecked (2 * k - 6, -(c1 + c2 + c3) / c4);
315  }
316 
317  Array<double> ai;
318  ai.resize (2 * n + 1 + 1);
319 
320  for (int k = 0; k <= n; ++k)
321  ai.setUnchecked (2 * k + 1, alpha[2 * k] / (2.0 * k + 1.0));
322 
323  Array<double> hn;
324  hn.resize (2 * n + 1 + 2 * n + 1 + 1);
325 
326  for (int k = 0; k <= n; ++k)
327  {
328  hn.setUnchecked (2 * n + 1 + (2 * k + 1), 0.5 * ai[2 * k + 1]);
329  hn.setUnchecked (2 * n + 1 - (2 * k + 1), 0.5 * ai[2 * k + 1]);
330  }
331 
332  return hn;
333 }
334 
335 template <typename FloatType>
336 ReferenceCountedArray<IIR::Coefficients<FloatType>>
338  FloatType normalisedTransitionWidth,
339  FloatType passbandAmplitudedB,
340  FloatType stopbandAmplitudedB)
341 {
342  return designIIRLowpassHighOrderGeneralMethod (0, frequency, sampleRate, normalisedTransitionWidth,
343  passbandAmplitudedB, stopbandAmplitudedB);
344 }
345 
346 template <typename FloatType>
349  FloatType normalisedTransitionWidth,
350  FloatType passbandAmplitudedB,
351  FloatType stopbandAmplitudedB)
352 {
353  return designIIRLowpassHighOrderGeneralMethod (1, frequency, sampleRate, normalisedTransitionWidth,
354  passbandAmplitudedB, stopbandAmplitudedB);
355 }
356 
357 template <typename FloatType>
360  FloatType normalisedTransitionWidth,
361  FloatType passbandAmplitudedB,
362  FloatType stopbandAmplitudedB)
363 {
364  return designIIRLowpassHighOrderGeneralMethod (2, frequency, sampleRate, normalisedTransitionWidth,
365  passbandAmplitudedB, stopbandAmplitudedB);
366 }
367 
368 template <typename FloatType>
371  FloatType normalisedTransitionWidth,
372  FloatType passbandAmplitudedB,
373  FloatType stopbandAmplitudedB)
374 {
375  return designIIRLowpassHighOrderGeneralMethod (3, frequency, sampleRate, normalisedTransitionWidth,
376  passbandAmplitudedB, stopbandAmplitudedB);
377 }
378 
379 template <typename FloatType>
381  FilterDesign<FloatType>::designIIRLowpassHighOrderGeneralMethod (int type, FloatType frequency, double sampleRate,
382  FloatType normalisedTransitionWidth,
383  FloatType passbandAmplitudedB,
384  FloatType stopbandAmplitudedB)
385 {
386  jassert (0 < sampleRate);
387  jassert (0 < frequency && frequency <= sampleRate * 0.5);
388  jassert (0 < normalisedTransitionWidth && normalisedTransitionWidth <= 0.5);
389  jassert (-20 < passbandAmplitudedB && passbandAmplitudedB < 0);
390  jassert (-300 < stopbandAmplitudedB && stopbandAmplitudedB < -20);
391 
392  auto normalisedFrequency = frequency / sampleRate;
393 
394  auto fp = normalisedFrequency - normalisedTransitionWidth / 2;
395  jassert (0.0 < fp && fp < 0.5);
396 
397  auto fs = normalisedFrequency + normalisedTransitionWidth / 2;
398  jassert (0.0 < fs && fs < 0.5);
399 
400  double Ap = passbandAmplitudedB;
401  double As = stopbandAmplitudedB;
402  auto Gp = Decibels::decibelsToGain (Ap, -300.0);
403  auto Gs = Decibels::decibelsToGain (As, -300.0);
404  auto epsp = std::sqrt (1.0 / (Gp * Gp) - 1.0);
405  auto epss = std::sqrt (1.0 / (Gs * Gs) - 1.0);
406 
407  auto omegap = std::tan (MathConstants<double>::pi * fp);
408  auto omegas = std::tan (MathConstants<double>::pi * fs);
409  constexpr auto halfPi = MathConstants<double>::halfPi;
410 
411  auto k = omegap / omegas;
412  auto k1 = epsp / epss;
413 
414  int N;
415 
416  if (type == 0)
417  {
418  N = roundToInt (std::ceil (std::log (1.0 / k1) / std::log (1.0 / k)));
419  }
420  else if (type == 1 || type == 2)
421  {
422  N = roundToInt (std::ceil (std::acosh (1.0 / k1) / std::acosh (1.0 / k)));
423  }
424  else
425  {
426  double K, Kp, K1, K1p;
427 
430 
431  N = roundToInt (std::ceil ((K1p * K) / (K1 * Kp)));
432  }
433 
434  const int r = N % 2;
435  const int L = (N - r) / 2;
436  const double H0 = (type == 1 || type == 3) ? std::pow (Gp, 1.0 - r) : 1.0;
437 
438  Array<Complex<double>> pa, za;
439  Complex<double> j (0, 1);
440 
441  if (type == 0)
442  {
443  if (r == 1)
444  pa.add (-omegap * std::pow (epsp, -1.0 / (double) N));
445 
446  for (int i = 1; i <= L; ++i)
447  {
448  auto ui = (2 * i - 1.0) / (double) N;
449  pa.add (omegap * std::pow (epsp, -1.0 / (double) N) * j * exp (ui * halfPi * j));
450  }
451  }
452  else if (type == 1)
453  {
454  auto v0 = std::asinh (1.0 / epsp) / (N * halfPi);
455 
456  if (r == 1)
457  pa.add (-omegap * std::sinh (v0 * halfPi));
458 
459  for (int i = 1; i <= L; ++i)
460  {
461  auto ui = (2 * i - 1.0) / (double) N;
462  pa.add (omegap * j * std::cos ((ui - j * v0) * halfPi));
463  }
464  }
465  else if (type == 2)
466  {
467  auto v0 = std::asinh (epss) / (N * halfPi);
468 
469  if (r == 1)
470  pa.add (-1.0 / (k / omegap * std::sinh (v0 * halfPi)));
471 
472  for (int i = 1; i <= L; ++i)
473  {
474  auto ui = (2 * i - 1.0) / (double) N;
475 
476  pa.add (1.0 / (k / omegap * j * std::cos ((ui - j * v0) * halfPi)));
477  za.add (1.0 / (k / omegap * j * std::cos (ui * halfPi)));
478  }
479  }
480  else
481  {
482  auto v0 = -j * (SpecialFunctions::asne (j / epsp, k1) / (double) N);
483 
484  if (r == 1)
485  pa.add (omegap * j * SpecialFunctions::sne (j * v0, k));
486 
487  for (int i = 1; i <= L; ++i)
488  {
489  auto ui = (2 * i - 1.0) / (double) N;
490  auto zetai = SpecialFunctions::cde (ui, k);
491 
492  pa.add (omegap * j * SpecialFunctions::cde (ui - j * v0, k));
493  za.add (omegap * j / (k * zetai));
494  }
495  }
496 
497  Array<Complex<double>> p, z, g;
498 
499  if (r == 1)
500  {
501  p.add ((1.0 + pa[0]) / (1.0 - pa[0]));
502  g.add (0.5 * (1.0 - p[0]));
503  }
504 
505  for (int i = 0; i < L; ++i)
506  {
507  p.add ((1.0 + pa[i + r]) / (1.0 - pa[i + r]));
508  z.add (za.size() == 0 ? -1.0 : (1.0 + za[i]) / (1.0 - za[i]));
509  g.add ((1.0 - p[i + r]) / (1.0 - z[i]));
510  }
511 
512  ReferenceCountedArray<IIR::Coefficients<FloatType>> cascadedCoefficients;
513 
514  if (r == 1)
515  {
516  auto b0 = static_cast<FloatType> (H0 * std::real (g[0]));
517  auto b1 = b0;
518  auto a1 = static_cast<FloatType> (-std::real (p[0]));
519 
520  cascadedCoefficients.add (new IIR::Coefficients<FloatType> (b0, b1, 1.0f, a1));
521  }
522 
523  for (int i = 0; i < L; ++i)
524  {
525  auto gain = std::pow (std::abs (g[i + r]), 2.0);
526 
527  auto b0 = static_cast<FloatType> (gain);
528  auto b1 = static_cast<FloatType> (std::real (-z[i] - std::conj (z[i])) * gain);
529  auto b2 = static_cast<FloatType> (std::real ( z[i] * std::conj (z[i])) * gain);
530 
531  auto a1 = static_cast<FloatType> (std::real (-p[i+r] - std::conj (p[i + r])));
532  auto a2 = static_cast<FloatType> (std::real ( p[i+r] * std::conj (p[i + r])));
533 
534  cascadedCoefficients.add (new IIR::Coefficients<FloatType> (b0, b1, b2, 1, a1, a2));
535  }
536 
537  return cascadedCoefficients;
538 }
539 
540 template <typename FloatType>
541 ReferenceCountedArray<IIR::Coefficients<FloatType>>
543  double sampleRate, int order)
544 {
545  jassert (sampleRate > 0);
546  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
547  jassert (order > 0);
548 
550 
551  if (order % 2 == 1)
552  {
553  arrayFilters.add (*IIR::Coefficients<FloatType>::makeFirstOrderLowPass (sampleRate, frequency));
554 
555  for (int i = 0; i < order / 2; ++i)
556  {
557  auto Q = 1.0 / (2.0 * std::cos ((i + 1.0) * MathConstants<double>::pi / order));
558  arrayFilters.add (*IIR::Coefficients<FloatType>::makeLowPass (sampleRate, frequency,
559  static_cast<FloatType> (Q)));
560  }
561  }
562  else
563  {
564  for (int i = 0; i < order / 2; ++i)
565  {
566  auto Q = 1.0 / (2.0 * std::cos ((2.0 * i + 1.0) * MathConstants<double>::pi / (order * 2.0)));
567  arrayFilters.add (*IIR::Coefficients<FloatType>::makeLowPass (sampleRate, frequency,
568  static_cast<FloatType> (Q)));
569  }
570  }
571 
572  return arrayFilters;
573 }
574 
575 template <typename FloatType>
578  double sampleRate, int order)
579 {
580  jassert (sampleRate > 0);
581  jassert (frequency > 0 && frequency <= sampleRate * 0.5);
582  jassert (order > 0);
583 
585 
586  if (order % 2 == 1)
587  {
588  arrayFilters.add (*IIR::Coefficients<FloatType>::makeFirstOrderHighPass (sampleRate, frequency));
589 
590  for (int i = 0; i < order / 2; ++i)
591  {
592  auto Q = 1.0 / (2.0 * std::cos ((i + 1.0) * MathConstants<double>::pi / order));
593  arrayFilters.add (*IIR::Coefficients<FloatType>::makeHighPass (sampleRate, frequency,
594  static_cast<FloatType> (Q)));
595  }
596  }
597  else
598  {
599  for (int i = 0; i < order / 2; ++i)
600  {
601  auto Q = 1.0 / (2.0 * std::cos ((2.0 * i + 1.0) * MathConstants<double>::pi / (order * 2.0)));
602  arrayFilters.add (*IIR::Coefficients<FloatType>::makeHighPass (sampleRate, frequency,
603  static_cast<FloatType> (Q)));
604  }
605  }
606 
607  return arrayFilters;
608 }
609 
610 template <typename FloatType>
613  FloatType stopbandAmplitudedB)
614 {
615  jassert (normalisedTransitionWidth > 0 && normalisedTransitionWidth <= 0.5);
616  jassert (stopbandAmplitudedB > -300 && stopbandAmplitudedB < -10);
617 
618  const double wt = MathConstants<double>::twoPi * normalisedTransitionWidth;
619  const double ds = Decibels::decibelsToGain (stopbandAmplitudedB, static_cast<FloatType> (-300.0));
620 
621  auto k = std::pow (std::tan ((MathConstants<double>::pi - wt) / 4), 2.0);
622  auto kp = std::sqrt (1.0 - k * k);
623  auto e = (1 - std::sqrt (kp)) / (1 + std::sqrt (kp)) * 0.5;
624  auto q = e + 2 * std::pow (e, 5.0) + 15 * std::pow (e, 9.0) + 150 * std::pow (e, 13.0);
625 
626  auto k1 = ds * ds / (1 - ds * ds);
627  int n = roundToInt (std::ceil (std::log (k1 * k1 / 16) / std::log (q)));
628 
629  if (n % 2 == 0)
630  ++n;
631 
632  if (n == 1)
633  n = 3;
634 
635  auto q1 = std::pow (q, (double) n);
636  k1 = 4 * std::sqrt (q1);
637 
638  const int N = (n - 1) / 2;
639  Array<double> ai;
640 
641  for (int i = 1; i <= N; ++i)
642  {
643  double num = 0.0;
644  double delta = 1.0;
645  int m = 0;
646 
647  while (std::abs (delta) > 1e-100)
648  {
649  delta = std::pow (-1, m) * std::pow (q, m * (m + 1))
650  * std::sin ((2 * m + 1) * MathConstants<double>::pi * i / (double) n);
651  num += delta;
652  m++;
653  }
654 
655  num *= 2 * std::pow (q, 0.25);
656 
657  double den = 0.0;
658  delta = 1.0;
659  m = 1;
660 
661  while (std::abs (delta) > 1e-100)
662  {
663  delta = std::pow (-1, m) * std::pow (q, m * m)
664  * std::cos (m * MathConstants<double>::twoPi * i / (double) n);
665  den += delta;
666  ++m;
667  }
668 
669  den = 1 + 2 * den;
670 
671  auto wi = num / den;
672  auto api = std::sqrt ((1 - wi * wi * k) * (1 - wi * wi / k)) / (1 + wi * wi);
673 
674  ai.add ((1 - api) / (1 + api));
675  }
676 
678 
679  for (int i = 0; i < N; i += 2)
680  structure.directPath.add (new IIR::Coefficients<FloatType> (static_cast<FloatType> (ai[i]),
681  0, 1, 1, 0, static_cast<FloatType> (ai[i])));
682 
683  structure.delayedPath.add (new IIR::Coefficients<FloatType> (0, 1, 1, 0));
684 
685  for (int i = 1; i < N; i += 2)
686  structure.delayedPath.add (new IIR::Coefficients<FloatType> (static_cast<FloatType> (ai[i]),
687  0, 1, 1, 0, static_cast<FloatType> (ai[i])));
688 
689  structure.alpha.addArray (ai);
690 
691  return structure;
692 }
693 
694 
695 template struct FilterDesign<float>;
696 template struct FilterDesign<double>;
697 
698 } // namespace juce::dsp
void setUnchecked(int indexToChange, ParameterType newValue)
Definition: juce_Array.h:568
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition: juce_Array.h:583
void add(const ElementType &newElement)
Definition: juce_Array.h:418
void resize(int targetNumItems)
Definition: juce_Array.h:670
static Type decibelsToGain(Type decibels, Type minusInfinityDb=Type(defaultMinusInfinitydB))
Definition: juce_Decibels.h:42
ObjectClass * add(ObjectClass *newObject)
static Matrix hankel(const Matrix &vector, size_t size, size_t offset=0)
Definition: juce_Matrix.cpp:59
static Matrix identity(size_t size)
Definition: juce_Matrix.cpp:30
static Matrix toeplitz(const Matrix &vector, size_t size)
Definition: juce_Matrix.cpp:41
void multiplyWithWindowingTable(FloatType *samples, size_t size) const noexcept
ReferenceCountedObjectPtr< Coefficients > Ptr
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
static FIRCoefficientsPtr designFIRLowpassLeastSquaresMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType stopBandWeight)
static FIRCoefficientsPtr designFIRLowpassKaiserMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType amplitudedB)
static IIRPolyphaseAllpassStructure designIIRLowpassHalfBandPolyphaseAllpassMethod(FloatType normalisedTransitionWidth, FloatType stopbandAmplitudedB)
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev1Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
static ReferenceCountedArray< IIRCoefficients > designIIRHighpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, int order)
static FIRCoefficientsPtr designFIRLowpassTransitionMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType spline)
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev2Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderEllipticMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
static FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
static FIRCoefficientsPtr designFIRLowpassWindowMethod(FloatType frequency, double sampleRate, size_t order, WindowingMethod type, FloatType beta=static_cast< FloatType >(2))
static Complex< double > sne(Complex< double > u, double k) noexcept
static Complex< double > cde(Complex< double > u, double k) noexcept
static Complex< double > asne(Complex< double > w, double k) noexcept
static void ellipticIntegralK(double k, double &K, double &Kp) noexcept