diff --git a/examples/DSP/IIRFilterDemo.h b/examples/DSP/IIRFilterDemo.h index 1234b3a07e..3e20ba94c8 100644 --- a/examples/DSP/IIRFilterDemo.h +++ b/examples/DSP/IIRFilterDemo.h @@ -83,9 +83,9 @@ struct IIRFilterDemoDSP switch (typeParam.getCurrentSelectedID()) { - case 1: *iir.state = *IIR::Coefficients::makeLowPass (sampleRate, cutoff, qVal); break; - case 2: *iir.state = *IIR::Coefficients::makeHighPass (sampleRate, cutoff, qVal); break; - case 3: *iir.state = *IIR::Coefficients::makeBandPass (sampleRate, cutoff, qVal); break; + case 1: *iir.state = IIR::ArrayCoefficients::makeLowPass (sampleRate, cutoff, qVal); break; + case 2: *iir.state = IIR::ArrayCoefficients::makeHighPass (sampleRate, cutoff, qVal); break; + case 3: *iir.state = IIR::ArrayCoefficients::makeBandPass (sampleRate, cutoff, qVal); break; default: break; } } diff --git a/examples/DSP/SIMDRegisterDemo.h b/examples/DSP/SIMDRegisterDemo.h index c327b61bd1..3bf5e8a8cb 100644 --- a/examples/DSP/SIMDRegisterDemo.h +++ b/examples/DSP/SIMDRegisterDemo.h @@ -116,9 +116,9 @@ struct SIMDRegisterDemoDSP switch (typeParam.getCurrentSelectedID()) { - case 1: *iirCoefficients = *IIR::Coefficients::makeLowPass (sampleRate, cutoff, qVal); break; - case 2: *iirCoefficients = *IIR::Coefficients::makeHighPass (sampleRate, cutoff, qVal); break; - case 3: *iirCoefficients = *IIR::Coefficients::makeBandPass (sampleRate, cutoff, qVal); break; + case 1: *iirCoefficients = IIR::ArrayCoefficients::makeLowPass (sampleRate, cutoff, qVal); break; + case 2: *iirCoefficients = IIR::ArrayCoefficients::makeHighPass (sampleRate, cutoff, qVal); break; + case 3: *iirCoefficients = IIR::ArrayCoefficients::makeBandPass (sampleRate, cutoff, qVal); break; default: break; } } diff --git a/modules/juce_dsp/processors/juce_IIRFilter.cpp b/modules/juce_dsp/processors/juce_IIRFilter.cpp index 59b51fdb8f..0183300ee4 100644 --- a/modules/juce_dsp/processors/juce_IIRFilter.cpp +++ b/modules/juce_dsp/processors/juce_IIRFilter.cpp @@ -27,115 +27,56 @@ namespace juce { namespace dsp { - -template -IIR::Coefficients::Coefficients() - : coefficients ({ NumericType(), - NumericType(), - NumericType(), - NumericType(), - NumericType() }) +namespace IIR { -} template -IIR::Coefficients::Coefficients (NumericType b0, NumericType b1, - NumericType a0, NumericType a1) -{ - jassert (a0 != 0); - - coefficients.clear(); - - auto a0inv = static_cast (1) / a0; - - coefficients.add (b0 * a0inv, - b1 * a0inv, - a1 * a0inv); -} - -template -IIR::Coefficients::Coefficients (NumericType b0, NumericType b1, NumericType b2, - NumericType a0, NumericType a1, NumericType a2) -{ - jassert (a0 != 0); - - coefficients.clear(); - - auto a0inv = static_cast (1) / a0; - - coefficients.add (b0 * a0inv, - b1 * a0inv, - b2 * a0inv, - a1 * a0inv, - a2 * a0inv); -} - -template -IIR::Coefficients::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 (1) / a0; - - coefficients.add (b0 * a0inv, - b1 * a0inv, - b2 * a0inv, - b3 * a0inv, - a1 * a0inv, - a2 * a0inv, - a3 * a0inv); -} - -template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeFirstOrderLowPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeFirstOrderLowPass (double sampleRate, + NumericType frequency) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); auto n = std::tan (MathConstants::pi * frequency / static_cast (sampleRate)); - return *new Coefficients (n, n, n + 1, n - 1); + return { { n, n, n + 1, n - 1 } }; } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeFirstOrderHighPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeFirstOrderHighPass (double sampleRate, + NumericType frequency) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); auto n = std::tan (MathConstants::pi * frequency / static_cast (sampleRate)); - return *new Coefficients (1, -1, n + 1, n - 1); + return { { 1, -1, n + 1, n - 1 } }; } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeFirstOrderAllPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeFirstOrderAllPass (double sampleRate, + NumericType frequency) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); auto n = std::tan (MathConstants::pi * frequency / static_cast (sampleRate)); - return *new Coefficients (n - 1, n + 1, n + 1, n - 1); + return { { n - 1, n + 1, n + 1, n - 1 } }; } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeLowPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeLowPass (double sampleRate, + NumericType frequency) { return makeLowPass (sampleRate, frequency, inverseRootTwo); } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeLowPass (double sampleRate, - NumericType frequency, - NumericType Q) +std::array ArrayCoefficients::makeLowPass (double sampleRate, + NumericType frequency, + NumericType Q) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); @@ -146,22 +87,22 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeHighPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeHighPass (double sampleRate, + NumericType frequency) { return makeHighPass (sampleRate, frequency, inverseRootTwo); } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeHighPass (double sampleRate, - NumericType frequency, - NumericType Q) +std::array ArrayCoefficients::makeHighPass (double sampleRate, + NumericType frequency, + NumericType Q) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); @@ -172,22 +113,22 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeBandPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeBandPass (double sampleRate, + NumericType frequency) { return makeBandPass (sampleRate, frequency, inverseRootTwo); } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeBandPass (double sampleRate, - NumericType frequency, - NumericType Q) +std::array ArrayCoefficients::makeBandPass (double sampleRate, + NumericType frequency, + NumericType Q) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); @@ -198,23 +139,23 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeNotch (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeNotch (double sampleRate, + NumericType frequency) { return makeNotch (sampleRate, frequency, inverseRootTwo); } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeNotch (double sampleRate, - NumericType frequency, - NumericType Q) +std::array ArrayCoefficients::makeNotch (double sampleRate, + NumericType frequency, + NumericType Q) { jassert (sampleRate > 0.0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); @@ -227,20 +168,20 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeAllPass (double sampleRate, - NumericType frequency) +std::array ArrayCoefficients::makeAllPass (double sampleRate, + NumericType frequency) { return makeAllPass (sampleRate, frequency, inverseRootTwo); } template -typename IIR::Coefficients::Ptr IIR::Coefficients::makeAllPass (double sampleRate, - NumericType frequency, - NumericType Q) +std::array ArrayCoefficients::makeAllPass (double sampleRate, + NumericType frequency, + NumericType Q) { jassert (sampleRate > 0); jassert (frequency > 0 && frequency <= sampleRate * 0.5); @@ -253,14 +194,14 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeLowShelf (double sampleRate, - NumericType cutOffFrequency, - NumericType Q, - NumericType gainFactor) +std::array ArrayCoefficients::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::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makeHighShelf (double sampleRate, - NumericType cutOffFrequency, - NumericType Q, - NumericType gainFactor) +std::array ArrayCoefficients::makeHighShelf (double sampleRate, + NumericType cutOffFrequency, + NumericType Q, + NumericType gainFactor) { jassert (sampleRate > 0); jassert (cutOffFrequency > 0 && cutOffFrequency <= static_cast (sampleRate * 0.5)); @@ -300,19 +241,19 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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 IIR::Coefficients::Ptr IIR::Coefficients::makePeakFilter (double sampleRate, - NumericType frequency, - NumericType Q, - NumericType gainFactor) +std::array ArrayCoefficients::makePeakFilter (double sampleRate, + NumericType frequency, + NumericType Q, + NumericType gainFactor) { jassert (sampleRate > 0); jassert (frequency > 0 && frequency <= static_cast (sampleRate * 0.5)); @@ -326,20 +267,175 @@ typename IIR::Coefficients::Ptr IIR::Coefficients::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; +template struct ArrayCoefficients; + +//============================================================================== +template +Coefficients::Coefficients() +{ + assign ({ NumericType(), NumericType(), NumericType(), + NumericType(), NumericType(), NumericType() }); } template -size_t IIR::Coefficients::getFilterOrder() const noexcept +Coefficients::Coefficients (NumericType b0, NumericType b1, + NumericType a0, NumericType a1) +{ + assign ({ b0, b1, + a0, a1 }); +} + +template +Coefficients::Coefficients (NumericType b0, NumericType b1, NumericType b2, + NumericType a0, NumericType a1, NumericType a2) +{ + assign ({ b0, b1, b2, + a0, a1, a2 }); +} + +template +Coefficients::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 Coefficients::Ptr Coefficients::makeFirstOrderLowPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeFirstOrderLowPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeFirstOrderHighPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeFirstOrderHighPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeFirstOrderAllPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeFirstOrderAllPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeLowPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeLowPass (double sampleRate, + NumericType frequency, + NumericType Q) +{ + return *new Coefficients (ArrayCoeffs::makeLowPass (sampleRate, frequency, Q)); +} + +template +typename Coefficients::Ptr Coefficients::makeHighPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeHighPass (double sampleRate, + NumericType frequency, + NumericType Q) +{ + return *new Coefficients (ArrayCoeffs::makeHighPass (sampleRate, frequency, Q)); +} + +template +typename Coefficients::Ptr Coefficients::makeBandPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeBandPass (double sampleRate, + NumericType frequency, + NumericType Q) +{ + return *new Coefficients (ArrayCoeffs::makeBandPass (sampleRate, frequency, Q)); +} + +template +typename Coefficients::Ptr Coefficients::makeNotch (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeNotch (double sampleRate, + NumericType frequency, + NumericType Q) +{ + return *new Coefficients (ArrayCoeffs::makeNotch (sampleRate, frequency, Q)); +} + +template +typename Coefficients::Ptr Coefficients::makeAllPass (double sampleRate, + NumericType frequency) +{ + return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency)); +} + +template +typename Coefficients::Ptr Coefficients::makeAllPass (double sampleRate, + NumericType frequency, + NumericType Q) +{ + return *new Coefficients (ArrayCoeffs::makeAllPass (sampleRate, frequency, Q)); +} + +template +typename Coefficients::Ptr Coefficients::makeLowShelf (double sampleRate, + NumericType cutOffFrequency, + NumericType Q, + NumericType gainFactor) +{ + return *new Coefficients (ArrayCoeffs::makeLowShelf (sampleRate, cutOffFrequency, Q, gainFactor)); +} + +template +typename Coefficients::Ptr Coefficients::makeHighShelf (double sampleRate, + NumericType cutOffFrequency, + NumericType Q, + NumericType gainFactor) +{ + return *new Coefficients (ArrayCoeffs::makeHighShelf (sampleRate, cutOffFrequency, Q, gainFactor)); +} + +template +typename Coefficients::Ptr Coefficients::makePeakFilter (double sampleRate, + NumericType frequency, + NumericType Q, + NumericType gainFactor) +{ + return *new Coefficients (ArrayCoeffs::makePeakFilter (sampleRate, frequency, Q, gainFactor)); +} + +template +size_t Coefficients::getFilterOrder() const noexcept { return (static_cast (coefficients.size()) - 1) / 2; } template -double IIR::Coefficients::getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept +double Coefficients::getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept { constexpr Complex j (0, 1); const auto order = getFilterOrder(); @@ -369,8 +465,8 @@ double IIR::Coefficients::getMagnitudeForFrequency (double frequenc } template -void IIR::Coefficients::getMagnitudeForFrequencyArray (const double* frequencies, double* magnitudes, - size_t numSamples, double sampleRate) const noexcept +void Coefficients::getMagnitudeForFrequencyArray (const double* frequencies, double* magnitudes, + size_t numSamples, double sampleRate) const noexcept { constexpr Complex j (0, 1); const auto order = getFilterOrder(); @@ -405,7 +501,7 @@ void IIR::Coefficients::getMagnitudeForFrequencyArray (const double } template -double IIR::Coefficients::getPhaseForFrequency (double frequency, double sampleRate) const noexcept +double Coefficients::getPhaseForFrequency (double frequency, double sampleRate) const noexcept { constexpr Complex j (0, 1); const auto order = getFilterOrder(); @@ -435,8 +531,8 @@ double IIR::Coefficients::getPhaseForFrequency (double frequency, d } template -void IIR::Coefficients::getPhaseForFrequencyArray (double* frequencies, double* phases, - size_t numSamples, double sampleRate) const noexcept +void Coefficients::getPhaseForFrequencyArray (double* frequencies, double* phases, + size_t numSamples, double sampleRate) const noexcept { jassert (sampleRate > 0); @@ -473,8 +569,9 @@ void IIR::Coefficients::getPhaseForFrequencyArray (double* frequenc } } -template struct IIR::Coefficients; -template struct IIR::Coefficients; +template struct Coefficients; +template struct Coefficients; +} // namespace IIR } // namespace dsp } // namespace juce diff --git a/modules/juce_dsp/processors/juce_IIRFilter.h b/modules/juce_dsp/processors/juce_IIRFilter.h index d93965a6f6..f7b193fe49 100644 --- a/modules/juce_dsp/processors/juce_IIRFilter.h +++ b/modules/juce_dsp/processors/juce_IIRFilter.h @@ -33,6 +33,88 @@ namespace dsp */ namespace IIR { + template + struct ArrayCoefficients + { + /** Returns the coefficients for a first order low-pass filter. */ + static std::array makeFirstOrderLowPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a first order high-pass filter. */ + static std::array makeFirstOrderHighPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a first order all-pass filter. */ + static std::array makeFirstOrderAllPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a low-pass filter. */ + static std::array makeLowPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a low-pass filter with variable Q. */ + static std::array makeLowPass (double sampleRate, NumericType frequency, NumericType Q); + + /** Returns the coefficients for a high-pass filter. */ + static std::array makeHighPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a high-pass filter with variable Q. */ + static std::array makeHighPass (double sampleRate, NumericType frequency, NumericType Q); + + /** Returns the coefficients for a band-pass filter. */ + static std::array makeBandPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a band-pass filter with variable Q. */ + static std::array makeBandPass (double sampleRate, NumericType frequency, NumericType Q); + + /** Returns the coefficients for a notch filter. */ + static std::array makeNotch (double sampleRate, NumericType frequency); + + /** Returns the coefficients for a notch filter with variable Q. */ + static std::array makeNotch (double sampleRate, NumericType frequency, NumericType Q); + + /** Returns the coefficients for an all-pass filter. */ + static std::array makeAllPass (double sampleRate, NumericType frequency); + + /** Returns the coefficients for an all-pass filter with variable Q. */ + static std::array 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 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 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 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 (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 + explicit Coefficients (const std::array& values) { assignImpl (values.data()); } + + /** Assigns contents from an array. */ + template + Coefficients& operator= (const std::array& values) { return assignImpl (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 coefficients; private: - // Unfortunately, std::sqrt is not marked as constexpr just yet in all compilers - static constexpr NumericType inverseRootTwo = static_cast (0.70710678118654752440L); + using ArrayCoeffs = ArrayCoefficients; + + template + Coefficients& assignImpl (const NumericType* values); + + template + Coefficients& assign (const NumericType (& values)[Num]) { return assignImpl (values); } }; //============================================================================== diff --git a/modules/juce_dsp/processors/juce_IIRFilter_Impl.h b/modules/juce_dsp/processors/juce_IIRFilter_Impl.h index 2cef601463..604d26692a 100644 --- a/modules/juce_dsp/processors/juce_IIRFilter_Impl.h +++ b/modules/juce_dsp/processors/juce_IIRFilter_Impl.h @@ -32,6 +32,26 @@ namespace IIR #ifndef DOXYGEN +template +template +Coefficients& Coefficients::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 (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 Filter::Filter() @@ -192,7 +212,7 @@ SampleType JUCE_VECTOR_CALLTYPE Filter::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];