mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
DSP module: Various fixes and features including new LadderFilter
This commit is contained in:
parent
fedbb67452
commit
8bcb06ce6c
9 changed files with 461 additions and 6 deletions
|
|
@ -61,9 +61,17 @@ public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Set a new target value.
|
/** Set a new target value.
|
||||||
@param newValue New target value
|
@param newValue New target value
|
||||||
|
@force if true, the value will be set immediately, bypassing the ramp
|
||||||
*/
|
*/
|
||||||
void setValue (FloatType newValue) noexcept
|
void setValue (FloatType newValue, bool force = false) noexcept
|
||||||
{
|
{
|
||||||
|
if (force)
|
||||||
|
{
|
||||||
|
target = currentValue = newValue;
|
||||||
|
countdown = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (target != newValue)
|
if (target != newValue)
|
||||||
{
|
{
|
||||||
target = newValue;
|
target = newValue;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ namespace juce
|
||||||
|
|
||||||
MPESynthesiser::MPESynthesiser()
|
MPESynthesiser::MPESynthesiser()
|
||||||
{
|
{
|
||||||
|
MPEZoneLayout zoneLayout;
|
||||||
|
zoneLayout.addZone (MPEZone (1, 15));
|
||||||
|
setZoneLayout (zoneLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPESynthesiser::MPESynthesiser (MPEInstrument* mpeInstrument) : MPESynthesiserBase (mpeInstrument)
|
MPESynthesiser::MPESynthesiser (MPEInstrument* mpeInstrument) : MPESynthesiserBase (mpeInstrument)
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
bool shouldStealVoices;
|
bool shouldStealVoices = false;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
|
|
||||||
#include "processors/juce_FIRFilter.cpp"
|
#include "processors/juce_FIRFilter.cpp"
|
||||||
#include "processors/juce_IIRFilter.cpp"
|
#include "processors/juce_IIRFilter.cpp"
|
||||||
|
#include "processors/juce_LadderFilter.cpp"
|
||||||
#include "processors/juce_Oversampling.cpp"
|
#include "processors/juce_Oversampling.cpp"
|
||||||
#include "maths/juce_SpecialFunctions.cpp"
|
#include "maths/juce_SpecialFunctions.cpp"
|
||||||
#include "maths/juce_Matrix.cpp"
|
#include "maths/juce_Matrix.cpp"
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,10 @@ namespace juce
|
||||||
#include "processors/juce_IIRFilter.h"
|
#include "processors/juce_IIRFilter.h"
|
||||||
#include "processors/juce_FIRFilter.h"
|
#include "processors/juce_FIRFilter.h"
|
||||||
#include "processors/juce_Oscillator.h"
|
#include "processors/juce_Oscillator.h"
|
||||||
|
#include "processors/juce_LadderFilter.h"
|
||||||
#include "processors/juce_StateVariableFilter.h"
|
#include "processors/juce_StateVariableFilter.h"
|
||||||
#include "processors/juce_Oversampling.h"
|
#include "processors/juce_Oversampling.h"
|
||||||
|
#include "processors/juce_Reverb.h"
|
||||||
#include "frequency/juce_FFT.h"
|
#include "frequency/juce_FFT.h"
|
||||||
#include "frequency/juce_Convolution.h"
|
#include "frequency/juce_Convolution.h"
|
||||||
#include "frequency/juce_Windowing.h"
|
#include "frequency/juce_Windowing.h"
|
||||||
|
|
|
||||||
171
modules/juce_dsp/processors/juce_LadderFilter.cpp
Normal file
171
modules/juce_dsp/processors/juce_LadderFilter.cpp
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file is part of the JUCE library.
|
||||||
|
Copyright (c) 2017 - ROLI Ltd.
|
||||||
|
|
||||||
|
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 5 End-User License
|
||||||
|
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||||
|
27th April 2017).
|
||||||
|
|
||||||
|
End User License Agreement: www.juce.com/juce-5-licence
|
||||||
|
Privacy Policy: www.juce.com/juce-5-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
|
||||||
|
{
|
||||||
|
namespace dsp
|
||||||
|
{
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
LadderFilter<Type>::LadderFilter()
|
||||||
|
: state (2)
|
||||||
|
{
|
||||||
|
setSampleRate (Type (1000)); // intentionally setting unrealistic default
|
||||||
|
// sample rate to catch missing initialisation bugs
|
||||||
|
setResonance (Type (0));
|
||||||
|
setDrive (Type (1.2));
|
||||||
|
setMode (Mode::LPF12);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::setMode (Mode newValue) noexcept
|
||||||
|
{
|
||||||
|
switch (newValue)
|
||||||
|
{
|
||||||
|
case Mode::LPF12: A = { Type (0), Type (0), Type (1), Type (0), Type (0) }; comp = Type (0.5); break;
|
||||||
|
case Mode::HPF12: A = { Type (1), Type (-2), Type (1), Type (0), Type (0) }; comp = Type (0); break;
|
||||||
|
case Mode::LPF24: A = { Type (0), Type (0), Type (0), Type (0), Type (1) }; comp = Type (0.5); break;
|
||||||
|
case Mode::HPF24: A = { Type (1), Type (-4), Type (6), Type (-4), Type (1) }; comp = Type (0); break;
|
||||||
|
default: jassertfalse; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto outputGain = Type (1.2);
|
||||||
|
|
||||||
|
for (auto& a : A)
|
||||||
|
a *= outputGain;
|
||||||
|
|
||||||
|
mode = newValue;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::prepare (const juce::dsp::ProcessSpec& spec)
|
||||||
|
{
|
||||||
|
setSampleRate (Type (spec.sampleRate));
|
||||||
|
setNumChannels (spec.numChannels);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::reset() noexcept
|
||||||
|
{
|
||||||
|
for (auto& s : state)
|
||||||
|
s.fill (Type (0));
|
||||||
|
|
||||||
|
cutoffTransformSmoother.setValue (cutoffTransformSmoother.getTargetValue(), true);
|
||||||
|
scaledResonanceSmoother.setValue (scaledResonanceSmoother.getTargetValue(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::setCutoffFrequencyHz (Type newValue) noexcept
|
||||||
|
{
|
||||||
|
jassert (newValue > Type (0));
|
||||||
|
cutoffFreqHz = newValue;
|
||||||
|
updateCutoffFreq();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::setResonance (Type newValue) noexcept
|
||||||
|
{
|
||||||
|
jassert (newValue >= Type (0) && newValue <= Type (1));
|
||||||
|
resonance = newValue;
|
||||||
|
updateResonance();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::setDrive (Type newValue) noexcept
|
||||||
|
{
|
||||||
|
jassert (newValue >= Type (1));
|
||||||
|
|
||||||
|
drive = newValue;
|
||||||
|
gain = std::pow (drive, Type (-2.642)) * Type (0.6103) + Type (0.3903);
|
||||||
|
drive2 = drive * Type (0.04) + Type (0.96);
|
||||||
|
gain2 = std::pow (drive2, Type (-2.642)) * Type (0.6103) + Type (0.3903);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
Type LadderFilter<Type>::processSample (Type inputValue, size_t channelToUse) noexcept
|
||||||
|
{
|
||||||
|
auto& s = state[channelToUse];
|
||||||
|
|
||||||
|
const auto a1 = cutoffTransformValue;
|
||||||
|
const auto g = a1 * Type (-1) + Type (1);
|
||||||
|
const auto b0 = g * Type (0.76923076923);
|
||||||
|
const auto b1 = g * Type (0.23076923076);
|
||||||
|
|
||||||
|
const auto dx = gain * saturationLUT (drive * inputValue);
|
||||||
|
const auto a = dx + scaledResonanceValue * Type (-4) * (gain2 * saturationLUT (drive2 * s[4]) - dx * comp);
|
||||||
|
|
||||||
|
const auto b = b1 * s[0] + a1 * s[1] + b0 * a;
|
||||||
|
const auto c = b1 * s[1] + a1 * s[2] + b0 * b;
|
||||||
|
const auto d = b1 * s[2] + a1 * s[3] + b0 * c;
|
||||||
|
const auto e = b1 * s[3] + a1 * s[4] + b0 * d;
|
||||||
|
|
||||||
|
s[0] = a;
|
||||||
|
s[1] = b;
|
||||||
|
s[2] = c;
|
||||||
|
s[3] = d;
|
||||||
|
s[4] = e;
|
||||||
|
|
||||||
|
return a * A[0] + b * A[1] + c * A[2] + d * A[3] + e * A[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::updateSmoothers() noexcept
|
||||||
|
{
|
||||||
|
cutoffTransformValue = cutoffTransformSmoother.getNextValue();
|
||||||
|
scaledResonanceValue = scaledResonanceSmoother.getNextValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Type>
|
||||||
|
void LadderFilter<Type>::setSampleRate (Type newValue) noexcept
|
||||||
|
{
|
||||||
|
jassert (newValue > Type (0));
|
||||||
|
cutoffFreqScaler = Type (-2 * juce::double_Pi) / newValue;
|
||||||
|
|
||||||
|
static constexpr auto smootherRampTimeSec = Type (5e-2);
|
||||||
|
cutoffTransformSmoother.reset (newValue, smootherRampTimeSec);
|
||||||
|
scaledResonanceSmoother.reset (newValue, smootherRampTimeSec);
|
||||||
|
|
||||||
|
updateCutoffFreq();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template class LadderFilter<float>;
|
||||||
|
template class LadderFilter<double>;
|
||||||
|
|
||||||
|
} // namespace dsp
|
||||||
|
} // namespace juce
|
||||||
142
modules/juce_dsp/processors/juce_LadderFilter.h
Normal file
142
modules/juce_dsp/processors/juce_LadderFilter.h
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file is part of the JUCE library.
|
||||||
|
Copyright (c) 2017 - ROLI Ltd.
|
||||||
|
|
||||||
|
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 5 End-User License
|
||||||
|
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||||
|
27th April 2017).
|
||||||
|
|
||||||
|
End User License Agreement: www.juce.com/juce-5-licence
|
||||||
|
Privacy Policy: www.juce.com/juce-5-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
|
||||||
|
{
|
||||||
|
namespace dsp
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
Multi-mode filter based on the Moog ladder filter.
|
||||||
|
*/
|
||||||
|
template <typename Type>
|
||||||
|
class LadderFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Mode
|
||||||
|
{
|
||||||
|
LPF12, // low-pass 12 dB/octave
|
||||||
|
HPF12, // high-pass 12 dB/octave
|
||||||
|
LPF24, // low-pass 24 dB/octave
|
||||||
|
HPF24 // high-pass 24 dB/octave
|
||||||
|
};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Creates an uninitialised filter. Call prepare() before first use. */
|
||||||
|
LadderFilter();
|
||||||
|
|
||||||
|
/** Enables or disables the filter. If disabled it will simply pass through the input signal. */
|
||||||
|
void setEnabled (bool newValue) noexcept { enabled = newValue; }
|
||||||
|
|
||||||
|
/** Sets filter mode. */
|
||||||
|
void setMode (Mode newValue) noexcept;
|
||||||
|
|
||||||
|
/** Initialises the filter. */
|
||||||
|
void prepare (const juce::dsp::ProcessSpec& spec);
|
||||||
|
|
||||||
|
/** Returns the current number of channels. */
|
||||||
|
size_t getNumChannels() const noexcept { return state.size(); }
|
||||||
|
|
||||||
|
/** Resets the internal state variables of the filter. */
|
||||||
|
void reset() noexcept;
|
||||||
|
|
||||||
|
/** Sets the cutoff frequency of the filter.
|
||||||
|
@param newValue cutoff frequency in Hz */
|
||||||
|
void setCutoffFrequencyHz (Type newValue) noexcept;
|
||||||
|
|
||||||
|
/** Sets the resonance of the filter.
|
||||||
|
@param newValue a value between 0 and 1; higher values increase the resonance and can result in self oscillation! */
|
||||||
|
void setResonance (Type newValue) noexcept;
|
||||||
|
|
||||||
|
/** Sets the amound of saturation in the filter.
|
||||||
|
@param newValue saturation amount; it can be any number greater than or equal to one. Higher values result in more distortion.*/
|
||||||
|
void setDrive (Type newValue) noexcept;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
template <typename ProcessContext>
|
||||||
|
void process (const ProcessContext& context) noexcept
|
||||||
|
{
|
||||||
|
const auto& inputBlock = context.getInputBlock();
|
||||||
|
auto& outputBlock = context.getOutputBlock();
|
||||||
|
const auto numChannels = outputBlock.getNumChannels();
|
||||||
|
const auto numSamples = outputBlock.getNumSamples();
|
||||||
|
|
||||||
|
jassert (inputBlock.getNumChannels() <= getNumChannels());
|
||||||
|
jassert (inputBlock.getNumChannels() == numChannels);
|
||||||
|
jassert (inputBlock.getNumSamples() == numSamples);
|
||||||
|
|
||||||
|
if (! enabled || context.isBypassed)
|
||||||
|
{
|
||||||
|
outputBlock.copy (inputBlock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t n = 0; n < numSamples; ++n)
|
||||||
|
{
|
||||||
|
updateSmoothers();
|
||||||
|
|
||||||
|
for (size_t ch = 0; ch < numChannels; ++ch)
|
||||||
|
outputBlock.getChannelPointer (ch)[n] = processSample (inputBlock.getChannelPointer (ch)[n], ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//==============================================================================
|
||||||
|
Type processSample (Type inputValue, size_t channelToUse) noexcept;
|
||||||
|
void updateSmoothers() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
Type drive, drive2, gain, gain2, comp;
|
||||||
|
|
||||||
|
static constexpr size_t numStates = 5;
|
||||||
|
std::vector<std::array<Type, numStates>> state;
|
||||||
|
std::array<Type, numStates> A;
|
||||||
|
|
||||||
|
LinearSmoothedValue<Type> cutoffTransformSmoother;
|
||||||
|
LinearSmoothedValue<Type> scaledResonanceSmoother;
|
||||||
|
Type cutoffTransformValue;
|
||||||
|
Type scaledResonanceValue;
|
||||||
|
|
||||||
|
LookupTableTransform<Type> saturationLUT { [] (Type x) { return std::tanh (x); }, Type (-5), Type (5), 128 };
|
||||||
|
|
||||||
|
Type cutoffFreqHz { Type (200) };
|
||||||
|
Type resonance;
|
||||||
|
|
||||||
|
Type cutoffFreqScaler;
|
||||||
|
|
||||||
|
Mode mode;
|
||||||
|
bool enabled = true;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void setSampleRate (Type newValue) noexcept;
|
||||||
|
void setNumChannels (size_t newValue) { state.resize (newValue); }
|
||||||
|
void updateCutoffFreq() noexcept { cutoffTransformSmoother.setValue (std::exp (cutoffFreqHz * cutoffFreqScaler)); }
|
||||||
|
void updateResonance() noexcept { scaledResonanceSmoother.setValue (jmap (resonance, Type (0.1), Type (1.0))); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dsp
|
||||||
|
} // namespace juce
|
||||||
|
|
@ -41,27 +41,40 @@ public:
|
||||||
*/
|
*/
|
||||||
using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
|
using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
|
||||||
|
|
||||||
|
/** Creates an uninitialised oscillator. Call initialise before first use. */
|
||||||
|
Oscillator()
|
||||||
|
{}
|
||||||
|
|
||||||
/** Creates an oscillator with a periodic input function (-pi..pi).
|
/** Creates an oscillator with a periodic input function (-pi..pi).
|
||||||
|
|
||||||
If lookup table is not zero, then the function will be approximated
|
If lookup table is not zero, then the function will be approximated
|
||||||
with a lookup table.
|
with a lookup table.
|
||||||
*/
|
*/
|
||||||
Oscillator (const std::function<NumericType (NumericType)>& function, size_t lookupTableNumPoints = 0)
|
Oscillator (const std::function<NumericType (NumericType)>& function, size_t lookupTableNumPoints = 0)
|
||||||
: generator (function), frequency (440.0f)
|
{
|
||||||
|
initialise (function, lookupTableNumPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialises the oscillator with a waveform. */
|
||||||
|
void initialise (const std::function<NumericType (NumericType)>& function, size_t lookupTableNumPoints = 0)
|
||||||
{
|
{
|
||||||
if (lookupTableNumPoints != 0)
|
if (lookupTableNumPoints != 0)
|
||||||
{
|
{
|
||||||
auto table = new LookupTableTransform<NumericType> (generator, static_cast <NumericType> (-1.0 * double_Pi),
|
auto* table = new LookupTableTransform<NumericType> (function, static_cast <NumericType> (-1.0 * double_Pi),
|
||||||
static_cast<NumericType> (double_Pi), lookupTableNumPoints);
|
static_cast<NumericType> (double_Pi), lookupTableNumPoints);
|
||||||
|
|
||||||
lookupTable = table;
|
lookupTable = table;
|
||||||
generator = [table] (NumericType x) { return (*table) (x); };
|
generator = [table] (NumericType x) { return (*table) (x); };
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generator = function;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Sets the frequency of the oscillator. */
|
/** Sets the frequency of the oscillator. */
|
||||||
void setFrequency (NumericType newGain) noexcept { frequency.setValue (newGain); }
|
void setFrequency (NumericType newGain, bool force = false) noexcept { frequency.setValue (newGain, force); }
|
||||||
|
|
||||||
/** Returns the current frequency of the oscillator. */
|
/** Returns the current frequency of the oscillator. */
|
||||||
NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
|
NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
|
||||||
|
|
|
||||||
115
modules/juce_dsp/processors/juce_Reverb.h
Normal file
115
modules/juce_dsp/processors/juce_Reverb.h
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file is part of the JUCE library.
|
||||||
|
Copyright (c) 2017 - ROLI Ltd.
|
||||||
|
|
||||||
|
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 5 End-User License
|
||||||
|
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||||
|
27th April 2017).
|
||||||
|
|
||||||
|
End User License Agreement: www.juce.com/juce-5-licence
|
||||||
|
Privacy Policy: www.juce.com/juce-5-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
|
||||||
|
{
|
||||||
|
namespace dsp
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
Processor wrapper around juce::Reverb for easy integration into ProcessorChain.
|
||||||
|
*/
|
||||||
|
class Reverb
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
/** Creates an uninitialised Reverb processor. Call prepare() before first use. */
|
||||||
|
Reverb()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
using Parameters = juce::Reverb::Parameters;
|
||||||
|
|
||||||
|
/** Returns the reverb's current parameters. */
|
||||||
|
const Parameters& getParameters() const noexcept { return reverb.getParameters(); }
|
||||||
|
|
||||||
|
/** Applies a new set of parameters to the reverb.
|
||||||
|
Note that this doesn't attempt to lock the reverb, so if you call this in parallel with
|
||||||
|
the process method, you may get artifacts.
|
||||||
|
*/
|
||||||
|
void setParameters (const Parameters& newParams) { reverb.setParameters (newParams); }
|
||||||
|
|
||||||
|
/** Returns true if the reverb is enabled. */
|
||||||
|
bool isEnabled() const noexcept { return enabled; }
|
||||||
|
|
||||||
|
/** Enables/disables the reverb. */
|
||||||
|
void setEnabled (bool newValue) noexcept { enabled = newValue; }
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Initialises the reverb. */
|
||||||
|
void prepare (const juce::dsp::ProcessSpec& spec)
|
||||||
|
{
|
||||||
|
reverb.setSampleRate (spec.sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets the reverb's internal state. */
|
||||||
|
void reset() noexcept
|
||||||
|
{
|
||||||
|
reverb.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Applies the reverb to a mono or stereo buffer. */
|
||||||
|
template <typename ProcessContext>
|
||||||
|
void process (const ProcessContext& context) noexcept
|
||||||
|
{
|
||||||
|
const auto& inputBlock = context.getInputBlock();
|
||||||
|
auto& outputBlock = context.getOutputBlock();
|
||||||
|
const auto numInChannels = inputBlock.getNumChannels();
|
||||||
|
const auto numOutChannels = outputBlock.getNumChannels();
|
||||||
|
const auto numSamples = outputBlock.getNumSamples();
|
||||||
|
|
||||||
|
jassert (inputBlock.getNumSamples() == numSamples);
|
||||||
|
|
||||||
|
outputBlock.copy (inputBlock);
|
||||||
|
|
||||||
|
if (! enabled || context.isBypassed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (numInChannels == 1 && numOutChannels == 1)
|
||||||
|
{
|
||||||
|
reverb.processMono (outputBlock.getChannelPointer (0), (int) numSamples);
|
||||||
|
}
|
||||||
|
else if (numInChannels == 2 && numOutChannels == 2)
|
||||||
|
{
|
||||||
|
reverb.processStereo (outputBlock.getChannelPointer (0),
|
||||||
|
outputBlock.getChannelPointer (1),
|
||||||
|
(int) numSamples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jassertfalse; // invalid channel configuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
juce::Reverb reverb;
|
||||||
|
bool enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dsp
|
||||||
|
} // namespace juce
|
||||||
Loading…
Add table
Add a link
Reference in a new issue