OpenShot Audio Library | OpenShotAudio  0.6.0
juce_StateVariableFilter.h
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 
30 {
31  template <typename NumericType>
32  struct Parameters;
33 
54  template <typename SampleType>
55  class Filter
56  {
57  public:
58  //==============================================================================
62  using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
63 
66 
67  //==============================================================================
68  #ifndef DOXYGEN
70  [[deprecated ("The classes in the StateVariableFilter namespace are deprecated. you should "
71  "use the equivalent functionality in the StateVariableTPTFilter class.")]]
73 
75  [[deprecated ("The classes in the StateVariableFilter namespace are deprecated. you should "
76  "use the equivalent functionality in the StateVariableTPTFilter class.")]]
77  Filter (ParametersPtr parametersToUse) : parameters (std::move (parametersToUse)) { reset(); }
78  #endif
79 
81  Filter (const Filter&) = default;
82 
84  Filter (Filter&&) = default;
85 
86  //==============================================================================
88  void prepare (const ProcessSpec&) noexcept { reset(); }
89 
91  void reset() noexcept { s1 = s2 = SampleType {0}; }
92 
97  void snapToZero() noexcept { util::snapToZero (s1); util::snapToZero (s2); }
98 
99  //==============================================================================
103 
104  //==============================================================================
105  template <typename ProcessContext>
106  void process (const ProcessContext& context) noexcept
107  {
108  static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
109  "The sample-type of the filter must match the sample-type supplied to this process callback");
110 
111  if (context.isBypassed)
112  processInternal<true, ProcessContext> (context);
113  else
114  processInternal<false, ProcessContext> (context);
115  }
116 
119  SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType sample) noexcept
120  {
121  switch (parameters->type)
122  {
123  case Parameters<NumericType>::Type::lowPass: return processLoop<false, Parameters<NumericType>::Type::lowPass> (sample, *parameters); break;
124  case Parameters<NumericType>::Type::bandPass: return processLoop<false, Parameters<NumericType>::Type::bandPass> (sample, *parameters); break;
125  case Parameters<NumericType>::Type::highPass: return processLoop<false, Parameters<NumericType>::Type::highPass> (sample, *parameters); break;
126  default: jassertfalse;
127  }
128 
129  return SampleType{0};
130  }
131 
132  private:
133  //==============================================================================
134  template <bool isBypassed, typename Parameters<NumericType>::Type type>
135  SampleType JUCE_VECTOR_CALLTYPE processLoop (SampleType sample, Parameters<NumericType>& state) noexcept
136  {
137  y[2] = (sample - s1 * state.R2 - s1 * state.g - s2) * state.h;
138 
139  y[1] = y[2] * state.g + s1;
140  s1 = y[2] * state.g + y[1];
141 
142  y[0] = y[1] * state.g + s2;
143  s2 = y[1] * state.g + y[0];
144 
145  return isBypassed ? sample : y[static_cast<size_t> (type)];
146  }
147 
148  template <bool isBypassed, typename Parameters<NumericType>::Type type>
149  void processBlock (const SampleType* input, SampleType* output, size_t n) noexcept
150  {
151  auto state = *parameters;
152 
153  for (size_t i = 0 ; i < n; ++i)
154  output[i] = processLoop<isBypassed, type> (input[i], state);
155 
156  #if JUCE_DSP_ENABLE_SNAP_TO_ZERO
157  snapToZero();
158  #endif
159 
160  *parameters = state;
161  }
162 
163  template <bool isBypassed, typename ProcessContext>
164  void processInternal (const ProcessContext& context) noexcept
165  {
166  auto&& inputBlock = context.getInputBlock();
167  auto&& outputBlock = context.getOutputBlock();
168 
169  // This class can only process mono signals. Use the ProcessorDuplicator class
170  // to apply this filter on a multi-channel audio stream.
171  jassert (inputBlock.getNumChannels() == 1);
172  jassert (outputBlock.getNumChannels() == 1);
173 
174  auto n = inputBlock.getNumSamples();
175  auto* src = inputBlock .getChannelPointer (0);
176  auto* dst = outputBlock.getChannelPointer (0);
177 
178  switch (parameters->type)
179  {
180  case Parameters<NumericType>::Type::lowPass: processBlock<isBypassed, Parameters<NumericType>::Type::lowPass> (src, dst, n); break;
181  case Parameters<NumericType>::Type::bandPass: processBlock<isBypassed, Parameters<NumericType>::Type::bandPass> (src, dst, n); break;
182  case Parameters<NumericType>::Type::highPass: processBlock<isBypassed, Parameters<NumericType>::Type::highPass> (src, dst, n); break;
183  default: jassertfalse;
184  }
185  }
186 
187  //==============================================================================
188  std::array<SampleType, 3> y;
189  SampleType s1, s2;
190 
191  //==============================================================================
192  JUCE_LEAK_DETECTOR (Filter)
193  };
194 
195  enum class StateVariableFilterType
196  {
197  lowPass,
198  bandPass,
199  highPass
200  };
201 
202  //==============================================================================
208  template <typename NumericType>
209  struct Parameters : public ProcessorState
210  {
211  //==============================================================================
212  using Type = StateVariableFilterType;
213 
214  //==============================================================================
216  Type type = Type::lowPass;
217 
224  void setCutOffFrequency (double sampleRate, NumericType frequency,
225  NumericType resonance = static_cast<NumericType> (1.0 / MathConstants<double>::sqrt2)) noexcept
226  {
227  jassert (sampleRate > 0);
228  jassert (resonance > NumericType (0));
229  jassert (frequency > NumericType (0) && frequency <= NumericType (sampleRate * 0.5));
230 
231  g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * frequency / sampleRate));
232  R2 = static_cast<NumericType> (1.0 / resonance);
233  h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
234  }
235 
236  //==============================================================================
241 
242  //==============================================================================
243  Parameters() = default;
244  Parameters (const Parameters& o) : g (o.g), R2 (o.R2), h (o.h) {}
245  Parameters& operator= (const Parameters& o) noexcept { g = o.g; R2 = o.R2; h = o.h; return *this; }
246 
247  //==============================================================================
248  NumericType g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * 200.0 / 44100.0));
249  NumericType R2 = static_cast<NumericType> (MathConstants<double>::sqrt2);
250  NumericType h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
251  };
252 
253 } // namespace juce::dsp::StateVariableFilter
typename Parameters< NumericType >::Ptr ParametersPtr
void prepare(const ProcessSpec &) noexcept
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType sample) noexcept
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
void setCutOffFrequency(double sampleRate, NumericType frequency, NumericType resonance=static_cast< NumericType >(1.0/MathConstants< double >::sqrt2)) noexcept