OpenShot Library | OpenShotAudio  0.2.1
juce_LadderFilter.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11  Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12  27th April 2017).
13 
14  End User License Agreement: www.juce.com/juce-5-licence
15  Privacy Policy: www.juce.com/juce-5-privacy-policy
16 
17  Or: You may also use this code under the terms of the GPL v3 (see
18  www.gnu.org/licenses).
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 namespace dsp
30 {
31 
32 //==============================================================================
33 template <typename Type>
35 {
36  setSampleRate (Type (1000)); // intentionally setting unrealistic default
37  // sample rate to catch missing initialisation bugs
38  setResonance (Type (0));
39  setDrive (Type (1.2));
40  setMode (Mode::LPF12);
41 }
42 
43 //==============================================================================
44 template <typename Type>
45 void LadderFilter<Type>::setMode (Mode newValue) noexcept
46 {
47  switch (newValue)
48  {
49  case Mode::LPF12: A = {{ Type (0), Type (0), Type (1), Type (0), Type (0) }}; comp = Type (0.5); break;
50  case Mode::HPF12: A = {{ Type (1), Type (-2), Type (1), Type (0), Type (0) }}; comp = Type (0); break;
51  case Mode::LPF24: A = {{ Type (0), Type (0), Type (0), Type (0), Type (1) }}; comp = Type (0.5); break;
52  case Mode::HPF24: A = {{ Type (1), Type (-4), Type (6), Type (-4), Type (1) }}; comp = Type (0); break;
53  default: jassertfalse; break;
54  }
55 
56  static constexpr auto outputGain = Type (1.2);
57 
58  for (auto& a : A)
59  a *= outputGain;
60 
61  mode = newValue;
62  reset();
63 }
64 
65 //==============================================================================
66 template <typename Type>
68 {
69  setSampleRate (Type (spec.sampleRate));
70  setNumChannels (spec.numChannels);
71  reset();
72 }
73 
74 //==============================================================================
75 template <typename Type>
77 {
78  for (auto& s : state)
79  s.fill (Type (0));
80 
81  cutoffTransformSmoother.setCurrentAndTargetValue (cutoffTransformSmoother.getTargetValue());
82  scaledResonanceSmoother.setCurrentAndTargetValue (scaledResonanceSmoother.getTargetValue());
83 }
84 
85 //==============================================================================
86 template <typename Type>
87 void LadderFilter<Type>::setCutoffFrequencyHz (Type newValue) noexcept
88 {
89  jassert (newValue > Type (0));
90  cutoffFreqHz = newValue;
91  updateCutoffFreq();
92 }
93 
94 //==============================================================================
95 template <typename Type>
96 void LadderFilter<Type>::setResonance (Type newValue) noexcept
97 {
98  jassert (newValue >= Type (0) && newValue <= Type (1));
99  resonance = newValue;
100  updateResonance();
101 }
102 
103 //==============================================================================
104 template <typename Type>
105 void LadderFilter<Type>::setDrive (Type newValue) noexcept
106 {
107  jassert (newValue >= Type (1));
108 
109  drive = newValue;
110  gain = std::pow (drive, Type (-2.642)) * Type (0.6103) + Type (0.3903);
111  drive2 = drive * Type (0.04) + Type (0.96);
112  gain2 = std::pow (drive2, Type (-2.642)) * Type (0.6103) + Type (0.3903);
113 }
114 
115 //==============================================================================
116 template <typename Type>
117 Type LadderFilter<Type>::processSample (Type inputValue, size_t channelToUse) noexcept
118 {
119  auto& s = state[channelToUse];
120 
121  const auto a1 = cutoffTransformValue;
122  const auto g = a1 * Type (-1) + Type (1);
123  const auto b0 = g * Type (0.76923076923);
124  const auto b1 = g * Type (0.23076923076);
125 
126  const auto dx = gain * saturationLUT (drive * inputValue);
127  const auto a = dx + scaledResonanceValue * Type (-4) * (gain2 * saturationLUT (drive2 * s[4]) - dx * comp);
128 
129  const auto b = b1 * s[0] + a1 * s[1] + b0 * a;
130  const auto c = b1 * s[1] + a1 * s[2] + b0 * b;
131  const auto d = b1 * s[2] + a1 * s[3] + b0 * c;
132  const auto e = b1 * s[3] + a1 * s[4] + b0 * d;
133 
134  s[0] = a;
135  s[1] = b;
136  s[2] = c;
137  s[3] = d;
138  s[4] = e;
139 
140  return a * A[0] + b * A[1] + c * A[2] + d * A[3] + e * A[4];
141 }
142 
143 //==============================================================================
144 template <typename Type>
146 {
147  cutoffTransformValue = cutoffTransformSmoother.getNextValue();
148  scaledResonanceValue = scaledResonanceSmoother.getNextValue();
149 }
150 
151 //==============================================================================
152 template <typename Type>
153 void LadderFilter<Type>::setSampleRate (Type newValue) noexcept
154 {
155  jassert (newValue > Type (0));
156  cutoffFreqScaler = Type (-2.0 * juce::MathConstants<double>::pi) / newValue;
157 
158  static constexpr Type smootherRampTimeSec = Type (0.05);
159  cutoffTransformSmoother.reset (newValue, smootherRampTimeSec);
160  scaledResonanceSmoother.reset (newValue, smootherRampTimeSec);
161 
162  updateCutoffFreq();
163 }
164 
165 //==============================================================================
166 template class LadderFilter<float>;
167 template class LadderFilter<double>;
168 
169 } // namespace dsp
170 } // namespace juce
FloatType getNextValue() noexcept
Compute the next value.
void setCutoffFrequencyHz(Type newValue) noexcept
Sets the cutoff frequency of the filter.
FloatType getTargetValue() const noexcept
Returns the target value towards which the smoothed value is currently moving.
void prepare(const juce::dsp::ProcessSpec &spec)
Initialises the filter.
uint32 numChannels
The number of channels that the process() method will be expected to handle.
Multi-mode filter based on the Moog ladder filter.
double sampleRate
The sample rate that will be used for the data that is sent to the processor.
LadderFilter()
Creates an uninitialised filter.
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
void setDrive(Type newValue) noexcept
Sets the amount of saturation in the filter.
void setMode(Mode newValue) noexcept
Sets filter mode.
This structure is passed into a DSP algorithm&#39;s prepare() method, and contains information about vari...
void setCurrentAndTargetValue(FloatType newValue)
Sets the current value and the target value.
void setResonance(Type newValue) noexcept
Sets the resonance of the filter.
Commonly used mathematical constants.
void reset() noexcept
Resets the internal state variables of the filter.