From ba2cd6cc34f934dd54b96687282a88a58ac675f3 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 16 Jun 2021 18:12:24 +0100 Subject: [PATCH] IIRFilter: Provide a new SingleThreadedIIRFilter which does not lock internally --- .../utilities/juce_IIRFilter.cpp | 40 ++++++++------- .../utilities/juce_IIRFilter.h | 51 ++++++++++++++++--- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/modules/juce_audio_basics/utilities/juce_IIRFilter.cpp b/modules/juce_audio_basics/utilities/juce_IIRFilter.cpp index a1dc2526e2..fae0c9f961 100644 --- a/modules/juce_audio_basics/utilities/juce_IIRFilter.cpp +++ b/modules/juce_audio_basics/utilities/juce_IIRFilter.cpp @@ -258,42 +258,42 @@ IIRCoefficients IIRCoefficients::makePeakFilter (double sampleRate, } //============================================================================== -IIRFilter::IIRFilter() noexcept -{ -} +template +IIRFilterBase::IIRFilterBase() noexcept = default; -IIRFilter::IIRFilter (const IIRFilter& other) noexcept : active (other.active) +template +IIRFilterBase::IIRFilterBase (const IIRFilterBase& other) noexcept : active (other.active) { - const SpinLock::ScopedLockType sl (other.processLock); + const typename Mutex::ScopedLockType sl (other.processLock); coefficients = other.coefficients; } -IIRFilter::~IIRFilter() noexcept -{ -} - //============================================================================== -void IIRFilter::makeInactive() noexcept +template +void IIRFilterBase::makeInactive() noexcept { - const SpinLock::ScopedLockType sl (processLock); + const typename Mutex::ScopedLockType sl (processLock); active = false; } -void IIRFilter::setCoefficients (const IIRCoefficients& newCoefficients) noexcept +template +void IIRFilterBase::setCoefficients (const IIRCoefficients& newCoefficients) noexcept { - const SpinLock::ScopedLockType sl (processLock); + const typename Mutex::ScopedLockType sl (processLock); coefficients = newCoefficients; active = true; } //============================================================================== -void IIRFilter::reset() noexcept +template +void IIRFilterBase::reset() noexcept { - const SpinLock::ScopedLockType sl (processLock); + const typename Mutex::ScopedLockType sl (processLock); v1 = v2 = 0.0; } -float IIRFilter::processSingleSampleRaw (float in) noexcept +template +float IIRFilterBase::processSingleSampleRaw (float in) noexcept { auto out = coefficients.coefficients[0] * in + v1; @@ -305,9 +305,10 @@ float IIRFilter::processSingleSampleRaw (float in) noexcept return out; } -void IIRFilter::processSamples (float* const samples, const int numSamples) noexcept +template +void IIRFilterBase::processSamples (float* const samples, const int numSamples) noexcept { - const SpinLock::ScopedLockType sl (processLock); + const typename Mutex::ScopedLockType sl (processLock); if (active) { @@ -333,4 +334,7 @@ void IIRFilter::processSamples (float* const samples, const int numSamples) noex } } +template class IIRFilterBase; +template class IIRFilterBase; + } // namespace juce diff --git a/modules/juce_audio_basics/utilities/juce_IIRFilter.h b/modules/juce_audio_basics/utilities/juce_IIRFilter.h index 2246d87244..9f6dcc04c1 100644 --- a/modules/juce_audio_basics/utilities/juce_IIRFilter.h +++ b/modules/juce_audio_basics/utilities/juce_IIRFilter.h @@ -153,7 +153,8 @@ public: @tags{Audio} */ -class JUCE_API IIRFilter +template +class JUCE_API IIRFilterBase { public: //============================================================================== @@ -163,13 +164,10 @@ public: you process with it. Use the setCoefficients() method to turn it into the type of filter needed. */ - IIRFilter() noexcept; + IIRFilterBase() noexcept; /** Creates a copy of another filter. */ - IIRFilter (const IIRFilter&) noexcept; - - /** Destructor. */ - ~IIRFilter() noexcept; + IIRFilterBase (const IIRFilterBase&) noexcept; //============================================================================== /** Clears the filter so that any incoming data passes through unchanged. */ @@ -202,7 +200,7 @@ public: protected: //============================================================================== - SpinLock processLock; + Mutex processLock; IIRCoefficients coefficients; float v1 = 0, v2 = 0; bool active = false; @@ -214,4 +212,43 @@ protected: JUCE_LEAK_DETECTOR (IIRFilter) }; +/** + An IIR filter that can perform low, high, or band-pass filtering on an + audio signal, and which attempts to implement basic thread-safety. + + This class synchronises calls to some of its member functions, making it + safe (although not necessarily real-time-safe) to reset the filter or + apply new coefficients while the filter is processing on another thread. + In most cases this style of internal locking should not be used, and you + should attempt to provide thread-safety at a higher level in your program. + If you can guarantee that calls to the filter will be synchronised externally, + you could consider switching to SingleThreadedIIRFilter instead. + + @see SingleThreadedIIRFilter, IIRCoefficient, IIRFilterAudioSource + + @tags{Audio} +*/ +class IIRFilter : public IIRFilterBase +{ +public: + using IIRFilterBase::IIRFilterBase; +}; + +/** + An IIR filter that can perform low, high, or band-pass filtering on an + audio signal, with no thread-safety guarantees. + + You should use this class if you need an IIR filter, and don't plan to + call its member functions from multiple threads at once. + + @see IIRFilter, IIRCoefficient, IIRFilterAudioSource + + @tags{Audio} +*/ +class SingleThreadedIIRFilter : public IIRFilterBase +{ +public: + using IIRFilterBase::IIRFilterBase; +}; + } // namespace juce