OpenShot Audio Library | OpenShotAudio  0.6.0
juce_LadderFilter.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
11  Agreement and JUCE Privacy Policy.
12 
13  End User License Agreement: www.juce.com/juce-7-licence
14  Privacy Policy: www.juce.com/juce-privacy-policy
15 
16  Or: You may also use this code under the terms of the GPL v3 (see
17  www.gnu.org/licenses).
18 
19  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21  DISCLAIMED.
22 
23  ==============================================================================
24 */
25 
26 namespace juce::dsp
27 {
28 
29 //==============================================================================
30 template <typename SampleType>
32 {
33  setSampleRate (SampleType (1000)); // intentionally setting unrealistic default
34  // sample rate to catch missing initialisation bugs
35  setResonance (SampleType (0));
36  setDrive (SampleType (1.2));
37 
38  mode = Mode::LPF24;
39  setMode (Mode::LPF12);
40 }
41 
42 //==============================================================================
43 template <typename SampleType>
44 void LadderFilter<SampleType>::setMode (Mode newMode) noexcept
45 {
46  if (newMode == mode)
47  return;
48 
49  switch (newMode)
50  {
51  case Mode::LPF12: A = {{ SampleType (0), SampleType (0), SampleType (1), SampleType (0), SampleType (0) }}; comp = SampleType (0.5); break;
52  case Mode::HPF12: A = {{ SampleType (1), SampleType (-2), SampleType (1), SampleType (0), SampleType (0) }}; comp = SampleType (0); break;
53  case Mode::BPF12: A = {{ SampleType (0), SampleType (0), SampleType (-1), SampleType (1), SampleType (0) }}; comp = SampleType (0.5); break;
54  case Mode::LPF24: A = {{ SampleType (0), SampleType (0), SampleType (0), SampleType (0), SampleType (1) }}; comp = SampleType (0.5); break;
55  case Mode::HPF24: A = {{ SampleType (1), SampleType (-4), SampleType (6), SampleType (-4), SampleType (1) }}; comp = SampleType (0); break;
56  case Mode::BPF24: A = {{ SampleType (0), SampleType (0), SampleType (1), SampleType (-2), SampleType (1) }}; comp = SampleType (0.5); break;
57  default: jassertfalse; break;
58  }
59 
60  static constexpr auto outputGain = SampleType (1.2);
61 
62  for (auto& a : A)
63  a *= outputGain;
64 
65  mode = newMode;
66  reset();
67 }
68 
69 //==============================================================================
70 template <typename SampleType>
72 {
73  setSampleRate (SampleType (spec.sampleRate));
74  setNumChannels (spec.numChannels);
75  reset();
76 }
77 
78 //==============================================================================
79 template <typename SampleType>
81 {
82  for (auto& s : state)
83  s.fill (SampleType (0));
84 
85  cutoffTransformSmoother.setCurrentAndTargetValue (cutoffTransformSmoother.getTargetValue());
86  scaledResonanceSmoother.setCurrentAndTargetValue (scaledResonanceSmoother.getTargetValue());
87 }
88 
89 //==============================================================================
90 template <typename SampleType>
91 void LadderFilter<SampleType>::setCutoffFrequencyHz (SampleType newCutoff) noexcept
92 {
93  jassert (newCutoff > SampleType (0));
94  cutoffFreqHz = newCutoff;
95  updateCutoffFreq();
96 }
97 
98 //==============================================================================
99 template <typename SampleType>
100 void LadderFilter<SampleType>::setResonance (SampleType newResonance) noexcept
101 {
102  jassert (newResonance >= SampleType (0) && newResonance <= SampleType (1));
103  resonance = newResonance;
104  updateResonance();
105 }
106 
107 //==============================================================================
108 template <typename SampleType>
109 void LadderFilter<SampleType>::setDrive (SampleType newDrive) noexcept
110 {
111  jassert (newDrive >= SampleType (1));
112 
113  drive = newDrive;
114  gain = std::pow (drive, SampleType (-2.642)) * SampleType (0.6103) + SampleType (0.3903);
115  drive2 = drive * SampleType (0.04) + SampleType (0.96);
116  gain2 = std::pow (drive2, SampleType (-2.642)) * SampleType (0.6103) + SampleType (0.3903);
117 }
118 
119 //==============================================================================
120 template <typename SampleType>
121 SampleType LadderFilter<SampleType>::processSample (SampleType inputValue, size_t channelToUse) noexcept
122 {
123  auto& s = state[channelToUse];
124 
125  const auto a1 = cutoffTransformValue;
126  const auto g = a1 * SampleType (-1) + SampleType (1);
127  const auto b0 = g * SampleType (0.76923076923);
128  const auto b1 = g * SampleType (0.23076923076);
129 
130  const auto dx = gain * saturationLUT (drive * inputValue);
131  const auto a = dx + scaledResonanceValue * SampleType (-4) * (gain2 * saturationLUT (drive2 * s[4]) - dx * comp);
132 
133  const auto b = b1 * s[0] + a1 * s[1] + b0 * a;
134  const auto c = b1 * s[1] + a1 * s[2] + b0 * b;
135  const auto d = b1 * s[2] + a1 * s[3] + b0 * c;
136  const auto e = b1 * s[3] + a1 * s[4] + b0 * d;
137 
138  s[0] = a;
139  s[1] = b;
140  s[2] = c;
141  s[3] = d;
142  s[4] = e;
143 
144  return a * A[0] + b * A[1] + c * A[2] + d * A[3] + e * A[4];
145 }
146 
147 //==============================================================================
148 template <typename SampleType>
149 void LadderFilter<SampleType>::updateSmoothers() noexcept
150 {
151  cutoffTransformValue = cutoffTransformSmoother.getNextValue();
152  scaledResonanceValue = scaledResonanceSmoother.getNextValue();
153 }
154 
155 //==============================================================================
156 template <typename SampleType>
157 void LadderFilter<SampleType>::setSampleRate (SampleType newValue) noexcept
158 {
159  jassert (newValue > SampleType (0));
160  cutoffFreqScaler = SampleType (-2.0 * juce::MathConstants<double>::pi) / newValue;
161 
162  static constexpr SampleType smootherRampTimeSec = SampleType (0.05);
163  cutoffTransformSmoother.reset (newValue, smootherRampTimeSec);
164  scaledResonanceSmoother.reset (newValue, smootherRampTimeSec);
165 
166  updateCutoffFreq();
167 }
168 
169 //==============================================================================
170 template class LadderFilter<float>;
171 template class LadderFilter<double>;
172 
173 } // namespace juce::dsp
void setCutoffFrequencyHz(SampleType newCutoff) noexcept
void prepare(const ProcessSpec &spec)
void setDrive(SampleType newDrive) noexcept
void setMode(Mode newMode) noexcept
void setResonance(SampleType newResonance) noexcept