Loading...
Searching...
No Matches
juce_StateVariableFilter.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce::dsp::StateVariableFilter
{
template <typename NumericType>
struct Parameters;
template <typename SampleType>
class Filter
{
public:
//==============================================================================
using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
using ParametersPtr = typename Parameters<NumericType>::Ptr;
//==============================================================================
#ifndef DOXYGEN
[[deprecated ("The classes in the StateVariableFilter namespace are deprecated. you should "
"use the equivalent functionality in the StateVariableTPTFilter class.")]]
Filter() : parameters (new Parameters<NumericType>) { reset(); }
[[deprecated ("The classes in the StateVariableFilter namespace are deprecated. you should "
"use the equivalent functionality in the StateVariableTPTFilter class.")]]
Filter (ParametersPtr parametersToUse) : parameters (std::move (parametersToUse)) { reset(); }
#endif
Filter (const Filter&) = default;
Filter (Filter&&) = default;
//==============================================================================
void prepare (const ProcessSpec&) noexcept { reset(); }
void reset() noexcept { s1 = s2 = SampleType {0}; }
void snapToZero() noexcept { util::snapToZero (s1); util::snapToZero (s2); }
//==============================================================================
typename Parameters<NumericType>::Ptr parameters;
//==============================================================================
template <typename ProcessContext>
void process (const ProcessContext& context) noexcept
{
static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
"The sample-type of the filter must match the sample-type supplied to this process callback");
if (context.isBypassed)
processInternal<true, ProcessContext> (context);
else
processInternal<false, ProcessContext> (context);
}
SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType sample) noexcept
{
switch (parameters->type)
{
case Parameters<NumericType>::Type::lowPass: return processLoop<false, Parameters<NumericType>::Type::lowPass> (sample, *parameters); break;
case Parameters<NumericType>::Type::bandPass: return processLoop<false, Parameters<NumericType>::Type::bandPass> (sample, *parameters); break;
case Parameters<NumericType>::Type::highPass: return processLoop<false, Parameters<NumericType>::Type::highPass> (sample, *parameters); break;
default: jassertfalse;
}
return SampleType{0};
}
private:
//==============================================================================
template <bool isBypassed, typename Parameters<NumericType>::Type type>
SampleType JUCE_VECTOR_CALLTYPE processLoop (SampleType sample, Parameters<NumericType>& state) noexcept
{
y[2] = (sample - s1 * state.R2 - s1 * state.g - s2) * state.h;
y[1] = y[2] * state.g + s1;
s1 = y[2] * state.g + y[1];
y[0] = y[1] * state.g + s2;
s2 = y[1] * state.g + y[0];
return isBypassed ? sample : y[static_cast<size_t> (type)];
}
template <bool isBypassed, typename Parameters<NumericType>::Type type>
void processBlock (const SampleType* input, SampleType* output, size_t n) noexcept
{
auto state = *parameters;
for (size_t i = 0 ; i < n; ++i)
output[i] = processLoop<isBypassed, type> (input[i], state);
#if JUCE_DSP_ENABLE_SNAP_TO_ZERO
snapToZero();
#endif
*parameters = state;
}
template <bool isBypassed, typename ProcessContext>
void processInternal (const ProcessContext& context) noexcept
{
auto&& inputBlock = context.getInputBlock();
auto&& outputBlock = context.getOutputBlock();
// This class can only process mono signals. Use the ProcessorDuplicator class
// to apply this filter on a multi-channel audio stream.
jassert (inputBlock.getNumChannels() == 1);
jassert (outputBlock.getNumChannels() == 1);
auto n = inputBlock.getNumSamples();
auto* src = inputBlock .getChannelPointer (0);
auto* dst = outputBlock.getChannelPointer (0);
switch (parameters->type)
{
case Parameters<NumericType>::Type::lowPass: processBlock<isBypassed, Parameters<NumericType>::Type::lowPass> (src, dst, n); break;
case Parameters<NumericType>::Type::bandPass: processBlock<isBypassed, Parameters<NumericType>::Type::bandPass> (src, dst, n); break;
case Parameters<NumericType>::Type::highPass: processBlock<isBypassed, Parameters<NumericType>::Type::highPass> (src, dst, n); break;
default: jassertfalse;
}
}
//==============================================================================
std::array<SampleType, 3> y;
SampleType s1, s2;
//==============================================================================
JUCE_LEAK_DETECTOR (Filter)
};
enum class StateVariableFilterType
{
lowPass,
bandPass,
highPass
};
//==============================================================================
template <typename NumericType>
struct Parameters : public ProcessorState
{
//==============================================================================
using Type = StateVariableFilterType;
//==============================================================================
Type type = Type::lowPass;
void setCutOffFrequency (double sampleRate, NumericType frequency,
NumericType resonance = static_cast<NumericType> (1.0 / MathConstants<double>::sqrt2)) noexcept
{
jassert (sampleRate > 0);
jassert (resonance > NumericType (0));
jassert (frequency > NumericType (0) && frequency <= NumericType (sampleRate * 0.5));
g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * frequency / sampleRate));
R2 = static_cast<NumericType> (1.0 / resonance);
h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
}
//==============================================================================
using Ptr = ReferenceCountedObjectPtr<Parameters>;
//==============================================================================
Parameters() = default;
Parameters (const Parameters& o) : g (o.g), R2 (o.R2), h (o.h) {}
Parameters& operator= (const Parameters& o) noexcept { g = o.g; R2 = o.R2; h = o.h; return *this; }
//==============================================================================
NumericType g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * 200.0 / 44100.0));
NumericType R2 = static_cast<NumericType> (MathConstants<double>::sqrt2);
NumericType h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
};
} // namespace juce::dsp::StateVariableFilter
juce::ReferenceCountedObjectPtr
Definition juce_ReferenceCountedObject.h:247
juce::dsp::StateVariableFilter::Filter::Filter
Filter()
Definition juce_StateVariableFilter.h:72
juce::dsp::StateVariableFilter::Filter::parameters
Parameters< NumericType >::Ptr parameters
Definition juce_StateVariableFilter.h:102
juce::dsp::StateVariableFilter::Filter::ParametersPtr
typename Parameters< NumericType >::Ptr ParametersPtr
Definition juce_StateVariableFilter.h:65
juce::dsp::StateVariableFilter::Filter::prepare
void prepare(const ProcessSpec &) noexcept
Definition juce_StateVariableFilter.h:88
juce::dsp::StateVariableFilter::Filter::reset
void reset() noexcept
Definition juce_StateVariableFilter.h:91
juce::dsp::StateVariableFilter::Filter::Filter
Filter(ParametersPtr parametersToUse)
Definition juce_StateVariableFilter.h:77
juce::dsp::StateVariableFilter::Filter::processSample
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType sample) noexcept
Definition juce_StateVariableFilter.h:119
juce::dsp::StateVariableFilter::Filter::Filter
Filter(const Filter &)=default
juce::dsp::StateVariableFilter::Filter::snapToZero
void snapToZero() noexcept
Definition juce_StateVariableFilter.h:97
juce::dsp::StateVariableFilter::Filter::NumericType
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
Definition juce_StateVariableFilter.h:62
juce::dsp::StateVariableFilter::Filter::Filter
Filter(Filter &&)=default
juce::dsp::StateVariableFilter
Definition juce_StateVariableFilter.h:30
juce::MathConstants::sqrt2
static constexpr FloatType sqrt2
Definition juce_MathsFunctions.h:153
juce::MathConstants::pi
static constexpr FloatType pi
Definition juce_MathsFunctions.h:141
juce::dsp::ProcessSpec
Definition juce_ProcessContext.h:36
juce::dsp::ProcessorState
Definition juce_ProcessContext.h:68
juce::dsp::StateVariableFilter::Parameters
Definition juce_StateVariableFilter.h:210
juce::dsp::StateVariableFilter::Parameters::setCutOffFrequency
void setCutOffFrequency(double sampleRate, NumericType frequency, NumericType resonance=static_cast< NumericType >(1.0/MathConstants< double >::sqrt2)) noexcept
Definition juce_StateVariableFilter.h:224
juce::dsp::StateVariableFilter::Parameters::type
Type type
Definition juce_StateVariableFilter.h:216
juce::dsp::StateVariableFilter::Parameters::Ptr
ReferenceCountedObjectPtr< Parameters > Ptr
Definition juce_StateVariableFilter.h:240