mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
IIRFilter: Fix potential divide by zero
This commit is contained in:
parent
2aff537ced
commit
f2e03eade0
3 changed files with 101 additions and 83 deletions
|
|
@ -60,6 +60,20 @@ public:
|
|||
: minusInfinityDb;
|
||||
}
|
||||
|
||||
/** Restricts a gain value based on a lower bound specified in dBFS.
|
||||
|
||||
This is useful if you want to make sure a gain value never reaches zero.
|
||||
*/
|
||||
template <typename Type>
|
||||
static Type gainWithLowerBound (Type gain, Type lowerBoundDb)
|
||||
{
|
||||
// You probably want to use a negative decibel value or the gain will
|
||||
// be restricted to boosting only!
|
||||
jassert (lowerBoundDb < (Type) 0.0);
|
||||
|
||||
return jmax ((Type) gain, Decibels::decibelsToGain (lowerBoundDb, lowerBoundDb - (Type) 1.0));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Converts a decibel reading to a string.
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
constexpr auto minimumDecibels = -300.0f;
|
||||
|
||||
IIRCoefficients::IIRCoefficients() noexcept
|
||||
{
|
||||
zeromem (coefficients, sizeof (coefficients));
|
||||
|
|
@ -44,7 +46,7 @@ IIRCoefficients& IIRCoefficients::operator= (const IIRCoefficients& other) noexc
|
|||
IIRCoefficients::IIRCoefficients (double c1, double c2, double c3,
|
||||
double c4, double c5, double c6) noexcept
|
||||
{
|
||||
auto a = 1.0 / c4;
|
||||
const auto a = 1.0 / c4;
|
||||
|
||||
coefficients[0] = (float) (c1 * a);
|
||||
coefficients[1] = (float) (c2 * a);
|
||||
|
|
@ -67,9 +69,9 @@ IIRCoefficients IIRCoefficients::makeLowPass (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
auto nSquared = n * n;
|
||||
auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
const auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
const auto nSquared = n * n;
|
||||
const auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
|
||||
return IIRCoefficients (c1,
|
||||
c1 * 2.0,
|
||||
|
|
@ -93,9 +95,9 @@ IIRCoefficients IIRCoefficients::makeHighPass (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto n = std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
auto nSquared = n * n;
|
||||
auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
const auto n = std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
const auto nSquared = n * n;
|
||||
const auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
|
||||
return IIRCoefficients (c1,
|
||||
c1 * -2.0,
|
||||
|
|
@ -119,9 +121,9 @@ IIRCoefficients IIRCoefficients::makeBandPass (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
auto nSquared = n * n;
|
||||
auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
const auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
const auto nSquared = n * n;
|
||||
const auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
|
||||
return IIRCoefficients (c1 * n / Q,
|
||||
0.0,
|
||||
|
|
@ -145,9 +147,9 @@ IIRCoefficients IIRCoefficients::makeNotchFilter (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
auto nSquared = n * n;
|
||||
auto c1 = 1.0 / (1.0 + n / Q + nSquared);
|
||||
const auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
const auto nSquared = n * n;
|
||||
const auto c1 = 1.0 / (1.0 + n / Q + nSquared);
|
||||
|
||||
return IIRCoefficients (c1 * (1.0 + nSquared),
|
||||
2.0 * c1 * (1.0 - nSquared),
|
||||
|
|
@ -171,9 +173,9 @@ IIRCoefficients IIRCoefficients::makeAllPass (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
auto nSquared = n * n;
|
||||
auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
const auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
|
||||
const auto nSquared = n * n;
|
||||
const auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
|
||||
|
||||
return IIRCoefficients (c1 * (1.0 - n / Q + nSquared),
|
||||
c1 * 2.0 * (1.0 - nSquared),
|
||||
|
|
@ -192,13 +194,13 @@ IIRCoefficients IIRCoefficients::makeLowShelf (double sampleRate,
|
|||
jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto A = jmax (0.0f, std::sqrt (gainFactor));
|
||||
auto aminus1 = A - 1.0;
|
||||
auto aplus1 = A + 1.0;
|
||||
auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
|
||||
auto coso = std::cos (omega);
|
||||
auto beta = std::sin (omega) * std::sqrt (A) / Q;
|
||||
auto aminus1TimesCoso = aminus1 * coso;
|
||||
const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, minimumDecibels));
|
||||
const auto aminus1 = A - 1.0;
|
||||
const auto aplus1 = A + 1.0;
|
||||
const auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
|
||||
const auto coso = std::cos (omega);
|
||||
const auto beta = std::sin (omega) * std::sqrt (A) / Q;
|
||||
const auto aminus1TimesCoso = aminus1 * coso;
|
||||
|
||||
return IIRCoefficients (A * (aplus1 - aminus1TimesCoso + beta),
|
||||
A * 2.0 * (aminus1 - aplus1 * coso),
|
||||
|
|
@ -217,13 +219,13 @@ IIRCoefficients IIRCoefficients::makeHighShelf (double sampleRate,
|
|||
jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto A = jmax (0.0f, std::sqrt (gainFactor));
|
||||
auto aminus1 = A - 1.0;
|
||||
auto aplus1 = A + 1.0;
|
||||
auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
|
||||
auto coso = std::cos (omega);
|
||||
auto beta = std::sin (omega) * std::sqrt (A) / Q;
|
||||
auto aminus1TimesCoso = aminus1 * coso;
|
||||
const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, minimumDecibels));
|
||||
const auto aminus1 = A - 1.0;
|
||||
const auto aplus1 = A + 1.0;
|
||||
const auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
|
||||
const auto coso = std::cos (omega);
|
||||
const auto beta = std::sin (omega) * std::sqrt (A) / Q;
|
||||
const auto aminus1TimesCoso = aminus1 * coso;
|
||||
|
||||
return IIRCoefficients (A * (aplus1 + aminus1TimesCoso + beta),
|
||||
A * -2.0 * (aminus1 + aplus1 * coso),
|
||||
|
|
@ -242,12 +244,12 @@ IIRCoefficients IIRCoefficients::makePeakFilter (double sampleRate,
|
|||
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
|
||||
jassert (Q > 0.0);
|
||||
|
||||
auto A = jmax (0.0f, std::sqrt (gainFactor));
|
||||
auto omega = (MathConstants<double>::twoPi * jmax (frequency, 2.0)) / sampleRate;
|
||||
auto alpha = 0.5 * std::sin (omega) / Q;
|
||||
auto c2 = -2.0 * std::cos (omega);
|
||||
auto alphaTimesA = alpha * A;
|
||||
auto alphaOverA = alpha / A;
|
||||
const auto A = std::sqrt (Decibels::gainWithLowerBound (gainFactor, minimumDecibels));
|
||||
const auto omega = (MathConstants<double>::twoPi * jmax (frequency, 2.0)) / sampleRate;
|
||||
const auto alpha = 0.5 * std::sin (omega) / Q;
|
||||
const auto c2 = -2.0 * std::cos (omega);
|
||||
const auto alphaTimesA = alpha * A;
|
||||
const auto alphaOverA = alpha / A;
|
||||
|
||||
return IIRCoefficients (1.0 + alphaTimesA,
|
||||
c2,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue