OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_dsp/processors/juce_IIRFilter.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
27{
28
29constexpr auto minimumDecibels = -300.0;
30
31template <typename NumericType>
32std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderLowPass (double sampleRate,
33 NumericType frequency)
34{
35 jassert (sampleRate > 0.0);
36 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
37
38 const auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
39
40 return { { n, n, n + 1, n - 1 } };
41}
42
43template <typename NumericType>
44std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderHighPass (double sampleRate,
45 NumericType frequency)
46{
47 jassert (sampleRate > 0.0);
48 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
49
50 const auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
51
52 return { { 1, -1, n + 1, n - 1 } };
53}
54
55template <typename NumericType>
56std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderAllPass (double sampleRate,
57 NumericType frequency)
58{
59 jassert (sampleRate > 0.0);
60 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
61
62 const auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
63
64 return { { n - 1, n + 1, n + 1, n - 1 } };
65}
66
67template <typename NumericType>
68std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowPass (double sampleRate,
69 NumericType frequency)
70{
71 return makeLowPass (sampleRate, frequency, inverseRootTwo);
72}
73
74template <typename NumericType>
75std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowPass (double sampleRate,
76 NumericType frequency,
77 NumericType Q)
78{
79 jassert (sampleRate > 0.0);
80 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
81 jassert (Q > 0.0);
82
83 const auto n = 1 / std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
84 const auto nSquared = n * n;
85 const auto invQ = 1 / Q;
86 const auto c1 = 1 / (1 + invQ * n + nSquared);
87
88 return { { c1, c1 * 2, c1,
89 1, c1 * 2 * (1 - nSquared),
90 c1 * (1 - invQ * n + nSquared) } };
91}
92
93template <typename NumericType>
94std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighPass (double sampleRate,
95 NumericType frequency)
96{
97 return makeHighPass (sampleRate, frequency, inverseRootTwo);
98}
99
100template <typename NumericType>
101std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighPass (double sampleRate,
102 NumericType frequency,
103 NumericType Q)
104{
105 jassert (sampleRate > 0.0);
106 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
107 jassert (Q > 0.0);
108
109 const auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
110 const auto nSquared = n * n;
111 const auto invQ = 1 / Q;
112 const auto c1 = 1 / (1 + invQ * n + nSquared);
113
114 return { { c1, c1 * -2, c1,
115 1, c1 * 2 * (nSquared - 1),
116 c1 * (1 - invQ * n + nSquared) } };
117}
118
119template <typename NumericType>
120std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeBandPass (double sampleRate,
121 NumericType frequency)
122{
123 return makeBandPass (sampleRate, frequency, inverseRootTwo);
124}
125
126template <typename NumericType>
127std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeBandPass (double sampleRate,
128 NumericType frequency,
129 NumericType Q)
130{
131 jassert (sampleRate > 0.0);
132 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
133 jassert (Q > 0.0);
134
135 const auto n = 1 / std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
136 const auto nSquared = n * n;
137 const auto invQ = 1 / Q;
138 const auto c1 = 1 / (1 + invQ * n + nSquared);
139
140 return { { c1 * n * invQ, 0,
141 -c1 * n * invQ, 1,
142 c1 * 2 * (1 - nSquared),
143 c1 * (1 - invQ * n + nSquared) } };
144}
145
146template <typename NumericType>
147std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeNotch (double sampleRate,
148 NumericType frequency)
149{
150 return makeNotch (sampleRate, frequency, inverseRootTwo);
151}
152
153template <typename NumericType>
154std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeNotch (double sampleRate,
155 NumericType frequency,
156 NumericType Q)
157{
158 jassert (sampleRate > 0.0);
159 jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
160 jassert (Q > 0.0);
161
162 const auto n = 1 / std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
163 const auto nSquared = n * n;
164 const auto invQ = 1 / Q;
165 const auto c1 = 1 / (1 + n * invQ + nSquared);
166 const auto b0 = c1 * (1 + nSquared);
167 const auto b1 = 2 * c1 * (1 - nSquared);
168
169 return { { b0, b1, b0, 1, b1, c1 * (1 - n * invQ + nSquared) } };
170}
171
172template <typename NumericType>
173std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeAllPass (double sampleRate,
174 NumericType frequency)
175{
176 return makeAllPass (sampleRate, frequency, inverseRootTwo);
177}
178
179template <typename NumericType>
180std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeAllPass (double sampleRate,
181 NumericType frequency,
182 NumericType Q)
183{
184 jassert (sampleRate > 0);
185 jassert (frequency > 0 && frequency <= sampleRate * 0.5);
186 jassert (Q > 0);
187
188 const auto n = 1 / std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
189 const auto nSquared = n * n;
190 const auto invQ = 1 / Q;
191 const auto c1 = 1 / (1 + invQ * n + nSquared);
192 const auto b0 = c1 * (1 - n * invQ + nSquared);
193 const auto b1 = c1 * 2 * (1 - nSquared);
194
195 return { { b0, b1, 1, 1, b1, b0 } };
196}
197
198template <typename NumericType>
199std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowShelf (double sampleRate,
200 NumericType cutOffFrequency,
201 NumericType Q,
202 NumericType gainFactor)
203{
204 jassert (sampleRate > 0.0);
205 jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
206 jassert (Q > 0.0);
207
208 const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, (NumericType) minimumDecibels));
209 const auto aminus1 = A - 1;
210 const auto aplus1 = A + 1;
211 const auto omega = (2 * MathConstants<NumericType>::pi * jmax (cutOffFrequency, static_cast<NumericType> (2.0))) / static_cast<NumericType> (sampleRate);
212 const auto coso = std::cos (omega);
213 const auto beta = std::sin (omega) * std::sqrt (A) / Q;
214 const auto aminus1TimesCoso = aminus1 * coso;
215
216 return { { A * (aplus1 - aminus1TimesCoso + beta),
217 A * 2 * (aminus1 - aplus1 * coso),
218 A * (aplus1 - aminus1TimesCoso - beta),
219 aplus1 + aminus1TimesCoso + beta,
220 -2 * (aminus1 + aplus1 * coso),
221 aplus1 + aminus1TimesCoso - beta } };
222}
223
224template <typename NumericType>
225std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighShelf (double sampleRate,
226 NumericType cutOffFrequency,
227 NumericType Q,
228 NumericType gainFactor)
229{
230 jassert (sampleRate > 0);
231 jassert (cutOffFrequency > 0 && cutOffFrequency <= static_cast<NumericType> (sampleRate * 0.5));
232 jassert (Q > 0);
233
234 const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, (NumericType) minimumDecibels));
235 const auto aminus1 = A - 1;
236 const auto aplus1 = A + 1;
237 const auto omega = (2 * MathConstants<NumericType>::pi * jmax (cutOffFrequency, static_cast<NumericType> (2.0))) / static_cast<NumericType> (sampleRate);
238 const auto coso = std::cos (omega);
239 const auto beta = std::sin (omega) * std::sqrt (A) / Q;
240 const auto aminus1TimesCoso = aminus1 * coso;
241
242 return { { A * (aplus1 + aminus1TimesCoso + beta),
243 A * -2 * (aminus1 + aplus1 * coso),
244 A * (aplus1 + aminus1TimesCoso - beta),
245 aplus1 - aminus1TimesCoso + beta,
246 2 * (aminus1 - aplus1 * coso),
247 aplus1 - aminus1TimesCoso - beta } };
248}
249
250template <typename NumericType>
251std::array<NumericType, 6> ArrayCoefficients<NumericType>::makePeakFilter (double sampleRate,
252 NumericType frequency,
253 NumericType Q,
254 NumericType gainFactor)
255{
256 jassert (sampleRate > 0);
257 jassert (frequency > 0 && frequency <= static_cast<NumericType> (sampleRate * 0.5));
258 jassert (Q > 0);
259 jassert (gainFactor > 0);
260
261 const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, (NumericType) minimumDecibels));
262 const auto omega = (2 * MathConstants<NumericType>::pi * jmax (frequency, static_cast<NumericType> (2.0))) / static_cast<NumericType> (sampleRate);
263 const auto alpha = std::sin (omega) / (Q * 2);
264 const auto c2 = -2 * std::cos (omega);
265 const auto alphaTimesA = alpha * A;
266 const auto alphaOverA = alpha / A;
267
268 return { { 1 + alphaTimesA, c2, 1 - alphaTimesA, 1 + alphaOverA, c2, 1 - alphaOverA } };
269}
270
271template struct ArrayCoefficients<float>;
272template struct ArrayCoefficients<double>;
273
274//==============================================================================
275template <typename NumericType>
277{
278 assign ({ NumericType(), NumericType(), NumericType(),
279 NumericType(), NumericType(), NumericType() });
280}
281
282template <typename NumericType>
283Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1,
284 NumericType a0, NumericType a1)
285{
286 assign ({ b0, b1,
287 a0, a1 });
288}
289
290template <typename NumericType>
291Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2,
292 NumericType a0, NumericType a1, NumericType a2)
293{
294 assign ({ b0, b1, b2,
295 a0, a1, a2 });
296}
297
298template <typename NumericType>
299Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2, NumericType b3,
300 NumericType a0, NumericType a1, NumericType a2, NumericType a3)
301{
302 assign ({ b0, b1, b2, b3,
303 a0, a1, a2, a3 });
304}
305
306template <typename NumericType>
308 NumericType frequency)
309{
310 return *new Coefficients (ArrayCoeffs::makeFirstOrderLowPass (sampleRate, frequency));
311}
312
313template <typename NumericType>
315 NumericType frequency)
316{
317 return *new Coefficients (ArrayCoeffs::makeFirstOrderHighPass (sampleRate, frequency));
318}
319
320template <typename NumericType>
322 NumericType frequency)
323{
324 return *new Coefficients (ArrayCoeffs::makeFirstOrderAllPass (sampleRate, frequency));
325}
326
327template <typename NumericType>
329 NumericType frequency)
330{
331 return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency));
332}
333
334template <typename NumericType>
336 NumericType frequency,
337 NumericType Q)
338{
339 return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency, Q));
340}
341
342template <typename NumericType>
344 NumericType frequency)
345{
346 return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency));
347}
348
349template <typename NumericType>
351 NumericType frequency,
352 NumericType Q)
353{
354 return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency, Q));
355}
356
357template <typename NumericType>
359 NumericType frequency)
360{
361 return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency));
362}
363
364template <typename NumericType>
366 NumericType frequency,
367 NumericType Q)
368{
369 return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency, Q));
370}
371
372template <typename NumericType>
374 NumericType frequency)
375{
376 return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency));
377}
378
379template <typename NumericType>
381 NumericType frequency,
382 NumericType Q)
383{
384 return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency, Q));
385}
386
387template <typename NumericType>
389 NumericType frequency)
390{
391 return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency));
392}
393
394template <typename NumericType>
396 NumericType frequency,
397 NumericType Q)
398{
399 return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency, Q));
400}
401
402template <typename NumericType>
404 NumericType cutOffFrequency,
405 NumericType Q,
406 NumericType gainFactor)
407{
408 return *new Coefficients (ArrayCoeffs::makeLowShelf (sampleRate, cutOffFrequency, Q, gainFactor));
409}
410
411template <typename NumericType>
413 NumericType cutOffFrequency,
414 NumericType Q,
415 NumericType gainFactor)
416{
417 return *new Coefficients (ArrayCoeffs::makeHighShelf (sampleRate, cutOffFrequency, Q, gainFactor));
418}
419
420template <typename NumericType>
422 NumericType frequency,
423 NumericType Q,
424 NumericType gainFactor)
425{
426 return *new Coefficients (ArrayCoeffs::makePeakFilter (sampleRate, frequency, Q, gainFactor));
427}
428
429template <typename NumericType>
431{
432 return (static_cast<size_t> (coefficients.size()) - 1) / 2;
433}
434
435template <typename NumericType>
436double Coefficients<NumericType>::getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept
437{
438 constexpr Complex<double> j (0, 1);
439 const auto order = getFilterOrder();
440 const auto* coefs = coefficients.begin();
441
442 jassert (frequency >= 0 && frequency <= sampleRate * 0.5);
443
444 Complex<double> numerator = 0.0, denominator = 0.0, factor = 1.0;
445 Complex<double> jw = std::exp (-MathConstants<double>::twoPi * frequency * j / sampleRate);
446
447 for (size_t n = 0; n <= order; ++n)
448 {
449 numerator += static_cast<double> (coefs[n]) * factor;
450 factor *= jw;
451 }
452
453 denominator = 1.0;
454 factor = jw;
455
456 for (size_t n = order + 1; n <= 2 * order; ++n)
457 {
458 denominator += static_cast<double> (coefs[n]) * factor;
459 factor *= jw;
460 }
461
462 return std::abs (numerator / denominator);
463}
464
465template <typename NumericType>
466void Coefficients<NumericType>::getMagnitudeForFrequencyArray (const double* frequencies, double* magnitudes,
467 size_t numSamples, double sampleRate) const noexcept
468{
469 constexpr Complex<double> j (0, 1);
470 const auto order = getFilterOrder();
471 const auto* coefs = coefficients.begin();
472
473 jassert (order >= 0);
474
475 for (size_t i = 0; i < numSamples; ++i)
476 {
477 jassert (frequencies[i] >= 0 && frequencies[i] <= sampleRate * 0.5);
478
479 Complex<double> numerator = 0.0, denominator = 0.0, factor = 1.0;
480 Complex<double> jw = std::exp (-MathConstants<double>::twoPi * frequencies[i] * j / sampleRate);
481
482 for (size_t n = 0; n <= order; ++n)
483 {
484 numerator += static_cast<double> (coefs[n]) * factor;
485 factor *= jw;
486 }
487
488 denominator = 1.0;
489 factor = jw;
490
491 for (size_t n = order + 1; n <= 2 * order; ++n)
492 {
493 denominator += static_cast<double> (coefs[n]) * factor;
494 factor *= jw;
495 }
496
497 magnitudes[i] = std::abs (numerator / denominator);
498 }
499}
500
501template <typename NumericType>
502double Coefficients<NumericType>::getPhaseForFrequency (double frequency, double sampleRate) const noexcept
503{
504 constexpr Complex<double> j (0, 1);
505 const auto order = getFilterOrder();
506 const auto* coefs = coefficients.begin();
507
508 jassert (frequency >= 0 && frequency <= sampleRate * 0.5);
509
510 Complex<double> numerator = 0.0, denominator = 0.0, factor = 1.0;
511 Complex<double> jw = std::exp (-MathConstants<double>::twoPi * frequency * j / sampleRate);
512
513 for (size_t n = 0; n <= order; ++n)
514 {
515 numerator += static_cast<double> (coefs[n]) * factor;
516 factor *= jw;
517 }
518
519 denominator = 1.0;
520 factor = jw;
521
522 for (size_t n = order + 1; n <= 2 * order; ++n)
523 {
524 denominator += static_cast<double> (coefs[n]) * factor;
525 factor *= jw;
526 }
527
528 return std::arg (numerator / denominator);
529}
530
531template <typename NumericType>
532void Coefficients<NumericType>::getPhaseForFrequencyArray (double* frequencies, double* phases,
533 size_t numSamples, double sampleRate) const noexcept
534{
535 jassert (sampleRate > 0);
536
537 constexpr Complex<double> j (0, 1);
538 const auto order = getFilterOrder();
539 const auto* coefs = coefficients.begin();
540 auto invSampleRate = 1 / sampleRate;
541
542 jassert (order >= 0);
543
544 for (size_t i = 0; i < numSamples; ++i)
545 {
546 jassert (frequencies[i] >= 0 && frequencies[i] <= sampleRate * 0.5);
547
548 Complex<double> numerator = 0.0, denominator = 0.0, factor = 1.0;
549 Complex<double> jw = std::exp (-MathConstants<double>::twoPi * frequencies[i] * j * invSampleRate);
550
551 for (size_t n = 0; n <= order; ++n)
552 {
553 numerator += static_cast<double> (coefs[n]) * factor;
554 factor *= jw;
555 }
556
557 denominator = 1.0;
558 factor = jw;
559
560 for (size_t n = order + 1; n <= 2 * order; ++n)
561 {
562 denominator += static_cast<double> (coefs[n]) * factor;
563 factor *= jw;
564 }
565
566 phases[i] = std::arg (numerator / denominator);
567 }
568}
569
570template struct Coefficients<float>;
571template struct Coefficients<double>;
572
573} // namespace juce::dsp::IIR
static Type gainWithLowerBound(Type gain, Type lowerBoundDb)
static constexpr FloatType twoPi
static constexpr FloatType pi
static std::array< NumericType, 6 > makeHighPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 6 > makePeakFilter(double sampleRate, NumericType centreFrequency, NumericType Q, NumericType gainFactor)
static std::array< NumericType, 6 > makeBandPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 4 > makeFirstOrderHighPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 6 > makeLowPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 6 > makeLowShelf(double sampleRate, NumericType cutOffFrequency, NumericType Q, NumericType gainFactor)
static std::array< NumericType, 4 > makeFirstOrderLowPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 4 > makeFirstOrderAllPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 6 > makeAllPass(double sampleRate, NumericType frequency)
static std::array< NumericType, 6 > makeHighShelf(double sampleRate, NumericType cutOffFrequency, NumericType Q, NumericType gainFactor)
static std::array< NumericType, 6 > makeNotch(double sampleRate, NumericType frequency)
static Ptr makeLowShelf(double sampleRate, NumericType cutOffFrequency, NumericType Q, NumericType gainFactor)
static Ptr makeFirstOrderHighPass(double sampleRate, NumericType frequency)
static Ptr makeHighPass(double sampleRate, NumericType frequency)
ReferenceCountedObjectPtr< Coefficients > Ptr
static Ptr makeHighShelf(double sampleRate, NumericType cutOffFrequency, NumericType Q, NumericType gainFactor)
void getMagnitudeForFrequencyArray(const double *frequencies, double *magnitudes, size_t numSamples, double sampleRate) const noexcept
static Ptr makeLowPass(double sampleRate, NumericType frequency)
double getMagnitudeForFrequency(double frequency, double sampleRate) const noexcept
static Ptr makePeakFilter(double sampleRate, NumericType centreFrequency, NumericType Q, NumericType gainFactor)
void getPhaseForFrequencyArray(double *frequencies, double *phases, size_t numSamples, double sampleRate) const noexcept
static Ptr makeAllPass(double sampleRate, NumericType frequency)
static Ptr makeBandPass(double sampleRate, NumericType frequency)
double getPhaseForFrequency(double frequency, double sampleRate) const noexcept
static Ptr makeNotch(double sampleRate, NumericType frequency)
static Ptr makeFirstOrderLowPass(double sampleRate, NumericType frequency)
static Ptr makeFirstOrderAllPass(double sampleRate, NumericType frequency)