1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

dsp::IIRFilter: Allow computing filter coefficients without allocating

This commit is contained in:
reuk 2021-06-16 19:30:57 +01:00
parent ba2cd6cc34
commit 22d935ad3e
No known key found for this signature in database
GPG key ID: 9ADCD339CFC98A11
5 changed files with 364 additions and 152 deletions

View file

@ -83,9 +83,9 @@ struct IIRFilterDemoDSP
switch (typeParam.getCurrentSelectedID())
{
case 1: *iir.state = *IIR::Coefficients<float>::makeLowPass (sampleRate, cutoff, qVal); break;
case 2: *iir.state = *IIR::Coefficients<float>::makeHighPass (sampleRate, cutoff, qVal); break;
case 3: *iir.state = *IIR::Coefficients<float>::makeBandPass (sampleRate, cutoff, qVal); break;
case 1: *iir.state = IIR::ArrayCoefficients<float>::makeLowPass (sampleRate, cutoff, qVal); break;
case 2: *iir.state = IIR::ArrayCoefficients<float>::makeHighPass (sampleRate, cutoff, qVal); break;
case 3: *iir.state = IIR::ArrayCoefficients<float>::makeBandPass (sampleRate, cutoff, qVal); break;
default: break;
}
}

View file

@ -116,9 +116,9 @@ struct SIMDRegisterDemoDSP
switch (typeParam.getCurrentSelectedID())
{
case 1: *iirCoefficients = *IIR::Coefficients<float>::makeLowPass (sampleRate, cutoff, qVal); break;
case 2: *iirCoefficients = *IIR::Coefficients<float>::makeHighPass (sampleRate, cutoff, qVal); break;
case 3: *iirCoefficients = *IIR::Coefficients<float>::makeBandPass (sampleRate, cutoff, qVal); break;
case 1: *iirCoefficients = IIR::ArrayCoefficients<float>::makeLowPass (sampleRate, cutoff, qVal); break;
case 2: *iirCoefficients = IIR::ArrayCoefficients<float>::makeHighPass (sampleRate, cutoff, qVal); break;
case 3: *iirCoefficients = IIR::ArrayCoefficients<float>::makeBandPass (sampleRate, cutoff, qVal); break;
default: break;
}
}

View file

@ -27,115 +27,56 @@ namespace juce
{
namespace dsp
{
template <typename NumericType>
IIR::Coefficients<NumericType>::Coefficients()
: coefficients ({ NumericType(),
NumericType(),
NumericType(),
NumericType(),
NumericType() })
namespace IIR
{
}
template <typename NumericType>
IIR::Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1,
NumericType a0, NumericType a1)
{
jassert (a0 != 0);
coefficients.clear();
auto a0inv = static_cast<NumericType> (1) / a0;
coefficients.add (b0 * a0inv,
b1 * a0inv,
a1 * a0inv);
}
template <typename NumericType>
IIR::Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2,
NumericType a0, NumericType a1, NumericType a2)
{
jassert (a0 != 0);
coefficients.clear();
auto a0inv = static_cast<NumericType> (1) / a0;
coefficients.add (b0 * a0inv,
b1 * a0inv,
b2 * a0inv,
a1 * a0inv,
a2 * a0inv);
}
template <typename NumericType>
IIR::Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2, NumericType b3,
NumericType a0, NumericType a1, NumericType a2, NumericType a3)
{
jassert (a0 != 0);
coefficients.clear();
auto a0inv = static_cast<NumericType> (1) / a0;
coefficients.add (b0 * a0inv,
b1 * a0inv,
b2 * a0inv,
b3 * a0inv,
a1 * a0inv,
a2 * a0inv,
a3 * a0inv);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeFirstOrderLowPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderLowPass (double sampleRate,
NumericType frequency)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
return *new Coefficients (n, n, n + 1, n - 1);
return { { n, n, n + 1, n - 1 } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeFirstOrderHighPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderHighPass (double sampleRate,
NumericType frequency)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
return *new Coefficients (1, -1, n + 1, n - 1);
return { { 1, -1, n + 1, n - 1 } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeFirstOrderAllPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 4> ArrayCoefficients<NumericType>::makeFirstOrderAllPass (double sampleRate,
NumericType frequency)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
auto n = std::tan (MathConstants<NumericType>::pi * frequency / static_cast<NumericType> (sampleRate));
return *new Coefficients (n - 1, n + 1, n + 1, n - 1);
return { { n - 1, n + 1, n + 1, n - 1 } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency)
{
return makeLowPass (sampleRate, frequency, inverseRootTwo);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency,
NumericType Q)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
@ -146,22 +87,22 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto invQ = 1 / Q;
auto c1 = 1 / (1 + invQ * n + nSquared);
return *new Coefficients (c1, c1 * 2, c1,
1, c1 * 2 * (1 - nSquared),
c1 * (1 - invQ * n + nSquared));
return { { c1, c1 * 2, c1,
1, c1 * 2 * (1 - nSquared),
c1 * (1 - invQ * n + nSquared) } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency)
{
return makeHighPass (sampleRate, frequency, inverseRootTwo);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency,
NumericType Q)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
@ -172,22 +113,22 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto invQ = 1 / Q;
auto c1 = 1 / (1 + invQ * n + nSquared);
return *new Coefficients (c1, c1 * -2, c1,
1, c1 * 2 * (nSquared - 1),
c1 * (1 - invQ * n + nSquared));
return { { c1, c1 * -2, c1,
1, c1 * 2 * (nSquared - 1),
c1 * (1 - invQ * n + nSquared) } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency)
{
return makeBandPass (sampleRate, frequency, inverseRootTwo);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency,
NumericType Q)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
@ -198,23 +139,23 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto invQ = 1 / Q;
auto c1 = 1 / (1 + invQ * n + nSquared);
return *new Coefficients (c1 * n * invQ, 0,
-c1 * n * invQ, 1,
c1 * 2 * (1 - nSquared),
c1 * (1 - invQ * n + nSquared));
return { { c1 * n * invQ, 0,
-c1 * n * invQ, 1,
c1 * 2 * (1 - nSquared),
c1 * (1 - invQ * n + nSquared) } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency)
{
return makeNotch (sampleRate, frequency, inverseRootTwo);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency,
NumericType Q)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency,
NumericType Q)
{
jassert (sampleRate > 0.0);
jassert (frequency > 0 && frequency <= static_cast<float> (sampleRate * 0.5));
@ -227,20 +168,20 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto b0 = c1 * (1 + nSquared);
auto b1 = 2 * c1 * (1 - nSquared);
return *new Coefficients (b0, b1, b0, 1, b1, c1 * (1 - n * invQ + nSquared));
return { { b0, b1, b0, 1, b1, c1 * (1 - n * invQ + nSquared) } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency)
{
return makeAllPass (sampleRate, frequency, inverseRootTwo);
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency,
NumericType Q)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
jassert (sampleRate > 0);
jassert (frequency > 0 && frequency <= sampleRate * 0.5);
@ -253,14 +194,14 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto b0 = c1 * (1 - n * invQ + nSquared);
auto b1 = c1 * 2 * (1 - nSquared);
return *new Coefficients (b0, b1, 1, 1, b1, b0);
return { { b0, b1, 1, 1, b1, b0 } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeLowShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeLowShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
{
jassert (sampleRate > 0.0);
jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
@ -274,19 +215,19 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto beta = std::sin (omega) * std::sqrt (A) / Q;
auto aminus1TimesCoso = aminus1 * coso;
return *new Coefficients (A * (aplus1 - aminus1TimesCoso + beta),
A * 2 * (aminus1 - aplus1 * coso),
A * (aplus1 - aminus1TimesCoso - beta),
aplus1 + aminus1TimesCoso + beta,
-2 * (aminus1 + aplus1 * coso),
aplus1 + aminus1TimesCoso - beta);
return { { A * (aplus1 - aminus1TimesCoso + beta),
A * 2 * (aminus1 - aplus1 * coso),
A * (aplus1 - aminus1TimesCoso - beta),
aplus1 + aminus1TimesCoso + beta,
-2 * (aminus1 + aplus1 * coso),
aplus1 + aminus1TimesCoso - beta } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makeHighShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makeHighShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
{
jassert (sampleRate > 0);
jassert (cutOffFrequency > 0 && cutOffFrequency <= static_cast<NumericType> (sampleRate * 0.5));
@ -300,19 +241,19 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto beta = std::sin (omega) * std::sqrt (A) / Q;
auto aminus1TimesCoso = aminus1 * coso;
return *new Coefficients (A * (aplus1 + aminus1TimesCoso + beta),
A * -2 * (aminus1 + aplus1 * coso),
A * (aplus1 + aminus1TimesCoso - beta),
aplus1 - aminus1TimesCoso + beta,
2 * (aminus1 - aplus1 * coso),
aplus1 - aminus1TimesCoso - beta);
return { { A * (aplus1 + aminus1TimesCoso + beta),
A * -2 * (aminus1 + aplus1 * coso),
A * (aplus1 + aminus1TimesCoso - beta),
aplus1 - aminus1TimesCoso + beta,
2 * (aminus1 - aplus1 * coso),
aplus1 - aminus1TimesCoso - beta } };
}
template <typename NumericType>
typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::makePeakFilter (double sampleRate,
NumericType frequency,
NumericType Q,
NumericType gainFactor)
std::array<NumericType, 6> ArrayCoefficients<NumericType>::makePeakFilter (double sampleRate,
NumericType frequency,
NumericType Q,
NumericType gainFactor)
{
jassert (sampleRate > 0);
jassert (frequency > 0 && frequency <= static_cast<NumericType> (sampleRate * 0.5));
@ -326,20 +267,175 @@ typename IIR::Coefficients<NumericType>::Ptr IIR::Coefficients<NumericType>::mak
auto alphaTimesA = alpha * A;
auto alphaOverA = alpha / A;
return *new Coefficients (1 + alphaTimesA, c2,
1 - alphaTimesA,
1 + alphaOverA, c2,
1 - alphaOverA);
return { { 1 + alphaTimesA, c2, 1 - alphaTimesA, 1 + alphaOverA, c2, 1 - alphaOverA } };
}
template struct ArrayCoefficients<float>;
template struct ArrayCoefficients<double>;
//==============================================================================
template <typename NumericType>
Coefficients<NumericType>::Coefficients()
{
assign ({ NumericType(), NumericType(), NumericType(),
NumericType(), NumericType(), NumericType() });
}
template <typename NumericType>
size_t IIR::Coefficients<NumericType>::getFilterOrder() const noexcept
Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1,
NumericType a0, NumericType a1)
{
assign ({ b0, b1,
a0, a1 });
}
template <typename NumericType>
Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2,
NumericType a0, NumericType a1, NumericType a2)
{
assign ({ b0, b1, b2,
a0, a1, a2 });
}
template <typename NumericType>
Coefficients<NumericType>::Coefficients (NumericType b0, NumericType b1, NumericType b2, NumericType b3,
NumericType a0, NumericType a1, NumericType a2, NumericType a3)
{
assign ({ b0, b1, b2, b3,
a0, a1, a2, a3 });
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeFirstOrderLowPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeFirstOrderLowPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeFirstOrderHighPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeFirstOrderHighPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeFirstOrderAllPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeFirstOrderAllPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeLowPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency, Q));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeHighPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency, Q));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeBandPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency, Q));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeNotch (double sampleRate,
NumericType frequency,
NumericType Q)
{
return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency, Q));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency)
{
return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeAllPass (double sampleRate,
NumericType frequency,
NumericType Q)
{
return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency, Q));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeLowShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
{
return *new Coefficients (ArrayCoeffs::makeLowShelf (sampleRate, cutOffFrequency, Q, gainFactor));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makeHighShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor)
{
return *new Coefficients (ArrayCoeffs::makeHighShelf (sampleRate, cutOffFrequency, Q, gainFactor));
}
template <typename NumericType>
typename Coefficients<NumericType>::Ptr Coefficients<NumericType>::makePeakFilter (double sampleRate,
NumericType frequency,
NumericType Q,
NumericType gainFactor)
{
return *new Coefficients (ArrayCoeffs::makePeakFilter (sampleRate, frequency, Q, gainFactor));
}
template <typename NumericType>
size_t Coefficients<NumericType>::getFilterOrder() const noexcept
{
return (static_cast<size_t> (coefficients.size()) - 1) / 2;
}
template <typename NumericType>
double IIR::Coefficients<NumericType>::getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept
double Coefficients<NumericType>::getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept
{
constexpr Complex<double> j (0, 1);
const auto order = getFilterOrder();
@ -369,8 +465,8 @@ double IIR::Coefficients<NumericType>::getMagnitudeForFrequency (double frequenc
}
template <typename NumericType>
void IIR::Coefficients<NumericType>::getMagnitudeForFrequencyArray (const double* frequencies, double* magnitudes,
size_t numSamples, double sampleRate) const noexcept
void Coefficients<NumericType>::getMagnitudeForFrequencyArray (const double* frequencies, double* magnitudes,
size_t numSamples, double sampleRate) const noexcept
{
constexpr Complex<double> j (0, 1);
const auto order = getFilterOrder();
@ -405,7 +501,7 @@ void IIR::Coefficients<NumericType>::getMagnitudeForFrequencyArray (const double
}
template <typename NumericType>
double IIR::Coefficients<NumericType>::getPhaseForFrequency (double frequency, double sampleRate) const noexcept
double Coefficients<NumericType>::getPhaseForFrequency (double frequency, double sampleRate) const noexcept
{
constexpr Complex<double> j (0, 1);
const auto order = getFilterOrder();
@ -435,8 +531,8 @@ double IIR::Coefficients<NumericType>::getPhaseForFrequency (double frequency, d
}
template <typename NumericType>
void IIR::Coefficients<NumericType>::getPhaseForFrequencyArray (double* frequencies, double* phases,
size_t numSamples, double sampleRate) const noexcept
void Coefficients<NumericType>::getPhaseForFrequencyArray (double* frequencies, double* phases,
size_t numSamples, double sampleRate) const noexcept
{
jassert (sampleRate > 0);
@ -473,8 +569,9 @@ void IIR::Coefficients<NumericType>::getPhaseForFrequencyArray (double* frequenc
}
}
template struct IIR::Coefficients<float>;
template struct IIR::Coefficients<double>;
template struct Coefficients<float>;
template struct Coefficients<double>;
} // namespace IIR
} // namespace dsp
} // namespace juce

View file

@ -33,6 +33,88 @@ namespace dsp
*/
namespace IIR
{
template <typename NumericType>
struct ArrayCoefficients
{
/** Returns the coefficients for a first order low-pass filter. */
static std::array<NumericType, 4> makeFirstOrderLowPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a first order high-pass filter. */
static std::array<NumericType, 4> makeFirstOrderHighPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a first order all-pass filter. */
static std::array<NumericType, 4> makeFirstOrderAllPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a low-pass filter. */
static std::array<NumericType, 6> makeLowPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a low-pass filter with variable Q. */
static std::array<NumericType, 6> makeLowPass (double sampleRate, NumericType frequency, NumericType Q);
/** Returns the coefficients for a high-pass filter. */
static std::array<NumericType, 6> makeHighPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a high-pass filter with variable Q. */
static std::array<NumericType, 6> makeHighPass (double sampleRate, NumericType frequency, NumericType Q);
/** Returns the coefficients for a band-pass filter. */
static std::array<NumericType, 6> makeBandPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for a band-pass filter with variable Q. */
static std::array<NumericType, 6> makeBandPass (double sampleRate, NumericType frequency, NumericType Q);
/** Returns the coefficients for a notch filter. */
static std::array<NumericType, 6> makeNotch (double sampleRate, NumericType frequency);
/** Returns the coefficients for a notch filter with variable Q. */
static std::array<NumericType, 6> makeNotch (double sampleRate, NumericType frequency, NumericType Q);
/** Returns the coefficients for an all-pass filter. */
static std::array<NumericType, 6> makeAllPass (double sampleRate, NumericType frequency);
/** Returns the coefficients for an all-pass filter with variable Q. */
static std::array<NumericType, 6> makeAllPass (double sampleRate, NumericType frequency, NumericType Q);
/** Returns the coefficients for a low-pass shelf filter with variable Q and gain.
The gain is a scale factor that the low frequencies are multiplied by, so values
greater than 1.0 will boost the low frequencies, values less than 1.0 will
attenuate them.
*/
static std::array<NumericType, 6> makeLowShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor);
/** Returns the coefficients for a high-pass shelf filter with variable Q and gain.
The gain is a scale factor that the high frequencies are multiplied by, so values
greater than 1.0 will boost the high frequencies, values less than 1.0 will
attenuate them.
*/
static std::array<NumericType, 6> makeHighShelf (double sampleRate,
NumericType cutOffFrequency,
NumericType Q,
NumericType gainFactor);
/** Returns the coefficients for a peak filter centred around a
given frequency, with a variable Q and gain.
The gain is a scale factor that the centre frequencies are multiplied by, so
values greater than 1.0 will boost the centre frequencies, values less than
1.0 will attenuate them.
*/
static std::array<NumericType, 6> makePeakFilter (double sampleRate,
NumericType centreFrequency,
NumericType Q,
NumericType gainFactor);
private:
// Unfortunately, std::sqrt is not marked as constexpr just yet in all compilers
static constexpr NumericType inverseRootTwo = static_cast<NumericType> (0.70710678118654752440L);
};
//==============================================================================
/** A set of coefficients for use in an Filter object.
@see IIR::Filter
@ -62,6 +144,14 @@ namespace IIR
Coefficients& operator= (const Coefficients&) = default;
Coefficients& operator= (Coefficients&&) = default;
/** Constructs from an array. */
template <size_t Num>
explicit Coefficients (const std::array<NumericType, Num>& values) { assignImpl<Num> (values.data()); }
/** Assigns contents from an array. */
template <size_t Num>
Coefficients& operator= (const std::array<NumericType, Num>& values) { return assignImpl<Num> (values.data()); }
/** The Coefficients structure is ref-counted, so this is a handy type that can be used
as a pointer to one.
*/
@ -180,8 +270,13 @@ namespace IIR
Array<NumericType> coefficients;
private:
// Unfortunately, std::sqrt is not marked as constexpr just yet in all compilers
static constexpr NumericType inverseRootTwo = static_cast<NumericType> (0.70710678118654752440L);
using ArrayCoeffs = ArrayCoefficients<NumericType>;
template <size_t Num>
Coefficients& assignImpl (const NumericType* values);
template <size_t Num>
Coefficients& assign (const NumericType (& values)[Num]) { return assignImpl<Num> (values); }
};
//==============================================================================

View file

@ -32,6 +32,26 @@ namespace IIR
#ifndef DOXYGEN
template <typename NumericType>
template <size_t Num>
Coefficients<NumericType>& Coefficients<NumericType>::assignImpl (const NumericType* values)
{
static_assert (Num % 2 == 0, "Must supply an even number of coefficients");
const auto a0Index = Num / 2;
const auto a0 = values[a0Index];
const auto a0Inv = a0 != NumericType() ? static_cast<NumericType> (1) / values[a0Index]
: NumericType();
coefficients.clearQuick();
coefficients.ensureStorageAllocated ((int) jmax ((size_t) 8, Num));
for (size_t i = 0; i < Num; ++i)
if (i != a0Index)
coefficients.add (values[i] * a0Inv);
return *this;
}
//==============================================================================
template <typename SampleType>
Filter<SampleType>::Filter()
@ -192,7 +212,7 @@ SampleType JUCE_VECTOR_CALLTYPE Filter<SampleType>::processSample (SampleType sa
check();
auto* c = coefficients->getRawCoefficients();
auto output= (c[0] * sample) + state[0];
auto output = (c[0] * sample) + state[0];
for (size_t j = 0; j < order - 1; ++j)
state[j] = (c[j + 1] * sample) - (c[order + j + 1] * output) + state[j + 1];