OpenShot Audio Library | OpenShotAudio: juce_FilterDesign.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
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
26namespace juce::dsp
27{
28
29template <typename FloatType>
30typename FIR::Coefficients<FloatType>::Ptr
31 FilterDesign<FloatType>::designFIRLowpassWindowMethod (FloatType frequency,
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
63template <typename FloatType>
64typename FIR::Coefficients<FloatType>::Ptr
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),
87 WindowingFunction<FloatType>::kaiser, beta);
88}
89
90
91template <typename FloatType>
92typename FIR::Coefficients<FloatType>::Ptr
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
124template <typename FloatType>
125typename FIR::Coefficients<FloatType>::Ptr
126 FilterDesign<FloatType>::designFIRLowpassLeastSquaresMethod (FloatType frequency,
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
233template <typename FloatType>
234typename FIR::Coefficients<FloatType>::Ptr
235 FilterDesign<FloatType>::designFIRLowpassHalfBandEquirippleMethod (FloatType normalisedTransitionWidth,
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
248 auto hn = FilterDesign<FloatType>::getPartialImpulseResponseHn (n, kp);
249 auto hnm = FilterDesign<FloatType>::getPartialImpulseResponseHn (n - 1, kp);
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
292template <typename FloatType>
293 Array<double> FilterDesign<FloatType>::getPartialImpulseResponseHn (int n, double kp)
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
335template <typename FloatType>
336ReferenceCountedArray<IIR::Coefficients<FloatType>>
337 FilterDesign<FloatType>::designIIRLowpassHighOrderButterworthMethod (FloatType frequency, double sampleRate,
338 FloatType normalisedTransitionWidth,
339 FloatType passbandAmplitudedB,
340 FloatType stopbandAmplitudedB)
341{
342 return designIIRLowpassHighOrderGeneralMethod (0, frequency, sampleRate, normalisedTransitionWidth,
343 passbandAmplitudedB, stopbandAmplitudedB);
344}
345
346template <typename FloatType>
347 ReferenceCountedArray<IIR::Coefficients<FloatType>>
348 FilterDesign<FloatType>::designIIRLowpassHighOrderChebyshev1Method (FloatType frequency, double sampleRate,
349 FloatType normalisedTransitionWidth,
350 FloatType passbandAmplitudedB,
351 FloatType stopbandAmplitudedB)
352{
353 return designIIRLowpassHighOrderGeneralMethod (1, frequency, sampleRate, normalisedTransitionWidth,
354 passbandAmplitudedB, stopbandAmplitudedB);
355}
356
357template <typename FloatType>
358 ReferenceCountedArray<IIR::Coefficients<FloatType>>
359 FilterDesign<FloatType>::designIIRLowpassHighOrderChebyshev2Method (FloatType frequency, double sampleRate,
360 FloatType normalisedTransitionWidth,
361 FloatType passbandAmplitudedB,
362 FloatType stopbandAmplitudedB)
363{
364 return designIIRLowpassHighOrderGeneralMethod (2, frequency, sampleRate, normalisedTransitionWidth,
365 passbandAmplitudedB, stopbandAmplitudedB);
366}
367
368template <typename FloatType>
369 ReferenceCountedArray<IIR::Coefficients<FloatType>>
370 FilterDesign<FloatType>::designIIRLowpassHighOrderEllipticMethod (FloatType frequency, double sampleRate,
371 FloatType normalisedTransitionWidth,
372 FloatType passbandAmplitudedB,
373 FloatType stopbandAmplitudedB)
374{
375 return designIIRLowpassHighOrderGeneralMethod (3, frequency, sampleRate, normalisedTransitionWidth,
376 passbandAmplitudedB, stopbandAmplitudedB);
377}
378
379template <typename FloatType>
380 ReferenceCountedArray<IIR::Coefficients<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
428 SpecialFunctions::ellipticIntegralK (k, K, Kp);
429 SpecialFunctions::ellipticIntegralK (k1, K1, K1p);
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
540template <typename FloatType>
541ReferenceCountedArray<IIR::Coefficients<FloatType>>
542 FilterDesign<FloatType>::designIIRLowpassHighOrderButterworthMethod (FloatType frequency,
543 double sampleRate, int order)
544{
545 jassert (sampleRate > 0);
546 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
547 jassert (order > 0);
548
549 ReferenceCountedArray<IIR::Coefficients<FloatType>> arrayFilters;
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
575template <typename FloatType>
576 ReferenceCountedArray<IIR::Coefficients<FloatType>>
577 FilterDesign<FloatType>::designIIRHighpassHighOrderButterworthMethod (FloatType frequency,
578 double sampleRate, int order)
579{
580 jassert (sampleRate > 0);
581 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
582 jassert (order > 0);
583
584 ReferenceCountedArray<IIR::Coefficients<FloatType>> arrayFilters;
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
610template <typename FloatType>
611typename FilterDesign<FloatType>::IIRPolyphaseAllpassStructure
612 FilterDesign<FloatType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (FloatType normalisedTransitionWidth,
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
677 IIRPolyphaseAllpassStructure structure;
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
695template struct FilterDesign<float>;
696template struct FilterDesign<double>;
697
698} // namespace juce::dsp
juce::Array
Definition juce_Array.h:56
juce::Array::setUnchecked
void setUnchecked(int indexToChange, ParameterType newValue)
Definition juce_Array.h:568
juce::Array::addArray
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::Array::resize
void resize(int targetNumItems)
Definition juce_Array.h:670
juce::Decibels::decibelsToGain
static Type decibelsToGain(Type decibels, Type minusInfinityDb=Type(defaultMinusInfinitydB))
Definition juce_Decibels.h:42
juce::ReferenceCountedArray
Definition juce_ReferenceCountedArray.h:51
juce::ReferenceCountedArray::add
ObjectClass * add(ObjectClass *newObject)
Definition juce_ReferenceCountedArray.h:354
juce::ReferenceCountedObjectPtr
Definition juce_ReferenceCountedObject.h:247
juce::dsp::Matrix
Definition juce_Matrix.h:39
juce::dsp::Matrix::hankel
static Matrix hankel(const Matrix &vector, size_t size, size_t offset=0)
Definition juce_Matrix.cpp:59
juce::dsp::Matrix::identity
static Matrix identity(size_t size)
Definition juce_Matrix.cpp:30
juce::dsp::Matrix::toeplitz
static Matrix toeplitz(const Matrix &vector, size_t size)
Definition juce_Matrix.cpp:41
juce::dsp::WindowingFunction
Definition juce_Windowing.h:41
juce::dsp::WindowingFunction::multiplyWithWindowingTable
void multiplyWithWindowingTable(FloatType *samples, size_t size) const noexcept
Definition juce_Windowing.cpp:167
juce::MathConstants
Definition juce_MathsFunctions.h:139
juce::dsp::FIR::Coefficients
Definition juce_FIRFilter.h:214
juce::dsp::FIR::Coefficients::Ptr
ReferenceCountedObjectPtr< Coefficients > Ptr
Definition juce_FIRFilter.h:233
juce::dsp::FilterDesign
Definition juce_FilterDesign.h:40
juce::dsp::FilterDesign::designIIRLowpassHighOrderButterworthMethod
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
Definition juce_FilterDesign.cpp:337
juce::dsp::FilterDesign::designFIRLowpassLeastSquaresMethod
static FIRCoefficientsPtr designFIRLowpassLeastSquaresMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType stopBandWeight)
Definition juce_FilterDesign.cpp:126
juce::dsp::FilterDesign::designFIRLowpassKaiserMethod
static FIRCoefficientsPtr designFIRLowpassKaiserMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType amplitudedB)
Definition juce_FilterDesign.cpp:65
juce::dsp::FilterDesign::designIIRLowpassHalfBandPolyphaseAllpassMethod
static IIRPolyphaseAllpassStructure designIIRLowpassHalfBandPolyphaseAllpassMethod(FloatType normalisedTransitionWidth, FloatType stopbandAmplitudedB)
Definition juce_FilterDesign.cpp:612
juce::dsp::FilterDesign::designIIRLowpassHighOrderChebyshev1Method
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev1Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
Definition juce_FilterDesign.cpp:348
juce::dsp::FilterDesign::designIIRHighpassHighOrderButterworthMethod
static ReferenceCountedArray< IIRCoefficients > designIIRHighpassHighOrderButterworthMethod(FloatType frequency, double sampleRate, int order)
Definition juce_FilterDesign.cpp:577
juce::dsp::FilterDesign::designFIRLowpassTransitionMethod
static FIRCoefficientsPtr designFIRLowpassTransitionMethod(FloatType frequency, double sampleRate, size_t order, FloatType normalisedTransitionWidth, FloatType spline)
Definition juce_FilterDesign.cpp:93
juce::dsp::FilterDesign::designIIRLowpassHighOrderChebyshev2Method
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderChebyshev2Method(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
Definition juce_FilterDesign.cpp:359
juce::dsp::FilterDesign::designIIRLowpassHighOrderEllipticMethod
static ReferenceCountedArray< IIRCoefficients > designIIRLowpassHighOrderEllipticMethod(FloatType frequency, double sampleRate, FloatType normalisedTransitionWidth, FloatType passbandAmplitudedB, FloatType stopbandAmplitudedB)
Definition juce_FilterDesign.cpp:370
juce::dsp::FilterDesign::designFIRLowpassHalfBandEquirippleMethod
static FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
Definition juce_FilterDesign.cpp:235
juce::dsp::FilterDesign::designFIRLowpassWindowMethod
static FIRCoefficientsPtr designFIRLowpassWindowMethod(FloatType frequency, double sampleRate, size_t order, WindowingMethod type, FloatType beta=static_cast< FloatType >(2))
Definition juce_FilterDesign.cpp:31
juce::dsp::FilterDesign::IIRPolyphaseAllpassStructure
Definition juce_FilterDesign.h:257
juce::dsp::IIR::Coefficients
Definition juce_dsp/processors/juce_IIRFilter.h:124
juce::dsp::SpecialFunctions::sne
static Complex< double > sne(Complex< double > u, double k) noexcept
Definition juce_SpecialFunctions.cpp:95
juce::dsp::SpecialFunctions::cde
static Complex< double > cde(Complex< double > u, double k) noexcept
Definition juce_SpecialFunctions.cpp:72
juce::dsp::SpecialFunctions::asne
static Complex< double > asne(Complex< double > w, double k) noexcept
Definition juce_SpecialFunctions.cpp:118
juce::dsp::SpecialFunctions::ellipticIntegralK
static void ellipticIntegralK(double k, double &K, double &Kp) noexcept
Definition juce_SpecialFunctions.cpp:49