OpenShot Audio Library | OpenShotAudio  0.6.0
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 
26 namespace juce::dsp::IIR
27 {
28 
29 constexpr auto minimumDecibels = -300.0;
30 
31 template <typename NumericType>
32 std::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 
43 template <typename NumericType>
44 std::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 
55 template <typename NumericType>
56 std::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 
67 template <typename NumericType>
68 std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowPass (double sampleRate,
69  NumericType frequency)
70 {
71  return makeLowPass (sampleRate, frequency, inverseRootTwo);
72 }
73 
74 template <typename NumericType>
75 std::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 
93 template <typename NumericType>
94 std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighPass (double sampleRate,
95  NumericType frequency)
96 {
97  return makeHighPass (sampleRate, frequency, inverseRootTwo);
98 }
99 
100 template <typename NumericType>
101 std::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 
119 template <typename NumericType>
120 std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeBandPass (double sampleRate,
121  NumericType frequency)
122 {
123  return makeBandPass (sampleRate, frequency, inverseRootTwo);
124 }
125 
126 template <typename NumericType>
127 std::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 
146 template <typename NumericType>
147 std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeNotch (double sampleRate,
148  NumericType frequency)
149 {
150  return makeNotch (sampleRate, frequency, inverseRootTwo);
151 }
152 
153 template <typename NumericType>
154 std::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 
172 template <typename NumericType>
173 std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeAllPass (double sampleRate,
174  NumericType frequency)
175 {
176  return makeAllPass (sampleRate, frequency, inverseRootTwo);
177 }
178 
179 template <typename NumericType>
180 std::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 
198 template <typename NumericType>
199 std::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 
224 template <typename NumericType>
225 std::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 
250 template <typename NumericType>
251 std::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 
271 template struct ArrayCoefficients<float>;
272 template struct ArrayCoefficients<double>;
273 
274 //==============================================================================
275 template <typename NumericType>
277 {
278  assign ({ NumericType(), NumericType(), NumericType(),
279  NumericType(), NumericType(), NumericType() });
280 }
281 
282 template <typename NumericType>
283 Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1,
284  NumericType a0, NumericType a1)
285 {
286  assign ({ b0, b1,
287  a0, a1 });
288 }
289 
290 template <typename NumericType>
291 Coefficients<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 
298 template <typename NumericType>
299 Coefficients<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 
306 template <typename NumericType>
308  NumericType frequency)
309 {
310  return *new Coefficients (ArrayCoeffs::makeFirstOrderLowPass (sampleRate, frequency));
311 }
312 
313 template <typename NumericType>
315  NumericType frequency)
316 {
317  return *new Coefficients (ArrayCoeffs::makeFirstOrderHighPass (sampleRate, frequency));
318 }
319 
320 template <typename NumericType>
322  NumericType frequency)
323 {
324  return *new Coefficients (ArrayCoeffs::makeFirstOrderAllPass (sampleRate, frequency));
325 }
326 
327 template <typename NumericType>
329  NumericType frequency)
330 {
331  return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency));
332 }
333 
334 template <typename NumericType>
336  NumericType frequency,
337  NumericType Q)
338 {
339  return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency, Q));
340 }
341 
342 template <typename NumericType>
344  NumericType frequency)
345 {
346  return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency));
347 }
348 
349 template <typename NumericType>
351  NumericType frequency,
352  NumericType Q)
353 {
354  return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency, Q));
355 }
356 
357 template <typename NumericType>
359  NumericType frequency)
360 {
361  return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency));
362 }
363 
364 template <typename NumericType>
366  NumericType frequency,
367  NumericType Q)
368 {
369  return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency, Q));
370 }
371 
372 template <typename NumericType>
374  NumericType frequency)
375 {
376  return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency));
377 }
378 
379 template <typename NumericType>
381  NumericType frequency,
382  NumericType Q)
383 {
384  return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency, Q));
385 }
386 
387 template <typename NumericType>
389  NumericType frequency)
390 {
391  return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency));
392 }
393 
394 template <typename NumericType>
396  NumericType frequency,
397  NumericType Q)
398 {
399  return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency, Q));
400 }
401 
402 template <typename NumericType>
404  NumericType cutOffFrequency,
405  NumericType Q,
406  NumericType gainFactor)
407 {
408  return *new Coefficients (ArrayCoeffs::makeLowShelf (sampleRate, cutOffFrequency, Q, gainFactor));
409 }
410 
411 template <typename NumericType>
413  NumericType cutOffFrequency,
414  NumericType Q,
415  NumericType gainFactor)
416 {
417  return *new Coefficients (ArrayCoeffs::makeHighShelf (sampleRate, cutOffFrequency, Q, gainFactor));
418 }
419 
420 template <typename NumericType>
422  NumericType frequency,
423  NumericType Q,
424  NumericType gainFactor)
425 {
426  return *new Coefficients (ArrayCoeffs::makePeakFilter (sampleRate, frequency, Q, gainFactor));
427 }
428 
429 template <typename NumericType>
431 {
432  return (static_cast<size_t> (coefficients.size()) - 1) / 2;
433 }
434 
435 template <typename NumericType>
436 double 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 
465 template <typename NumericType>
466 void 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 
501 template <typename NumericType>
502 double 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 
531 template <typename NumericType>
532 void 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 
570 template struct Coefficients<float>;
571 template struct Coefficients<double>;
572 
573 } // namespace juce::dsp::IIR
static Type gainWithLowerBound(Type gain, Type lowerBoundDb)
Definition: juce_Decibels.h:68
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)
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)