OpenShot Audio Library | OpenShotAudio  0.3.0
juce_StateVariableFilter.h
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 
35 namespace StateVariableFilter
36 {
37  template <typename NumericType>
38  struct Parameters;
39 
53  template <typename SampleType>
54  class Filter
55  {
56  public:
57  //==============================================================================
61  using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
62 
65 
66  //==============================================================================
69 
70  Filter (ParametersPtr parametersToUse) : parameters (std::move (parametersToUse)) { reset(); }
71 
73  Filter (const Filter&) = default;
74 
76  Filter (Filter&&) = default;
77 
78  //==============================================================================
80  void prepare (const ProcessSpec&) noexcept { reset(); }
81 
83  void reset() noexcept { s1 = s2 = SampleType {0}; }
84 
89  void snapToZero() noexcept { util::snapToZero (s1); util::snapToZero (s2); }
90 
91  //==============================================================================
95 
96  //==============================================================================
97  template <typename ProcessContext>
98  void process (const ProcessContext& context) noexcept
99  {
100  static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,
101  "The sample-type of the filter must match the sample-type supplied to this process callback");
102 
103  if (context.isBypassed)
104  processInternal<true, ProcessContext> (context);
105  else
106  processInternal<false, ProcessContext> (context);
107  }
108 
111  SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType sample) noexcept
112  {
113  switch (parameters->type)
114  {
115  case Parameters<NumericType>::Type::lowPass: return processLoop<false, Parameters<NumericType>::Type::lowPass> (sample, *parameters); break;
116  case Parameters<NumericType>::Type::bandPass: return processLoop<false, Parameters<NumericType>::Type::bandPass> (sample, *parameters); break;
117  case Parameters<NumericType>::Type::highPass: return processLoop<false, Parameters<NumericType>::Type::highPass> (sample, *parameters); break;
118  default: jassertfalse;
119  }
120 
121  return SampleType{0};
122  }
123 
124  private:
125  //==============================================================================
126  template <bool isBypassed, typename Parameters<NumericType>::Type type>
127  SampleType JUCE_VECTOR_CALLTYPE processLoop (SampleType sample, Parameters<NumericType>& state) noexcept
128  {
129  y[2] = (sample - s1 * state.R2 - s1 * state.g - s2) * state.h;
130 
131  y[1] = y[2] * state.g + s1;
132  s1 = y[2] * state.g + y[1];
133 
134  y[0] = y[1] * state.g + s2;
135  s2 = y[1] * state.g + y[0];
136 
137  return isBypassed ? sample : y[static_cast<size_t> (type)];
138  }
139 
140  template <bool isBypassed, typename Parameters<NumericType>::Type type>
141  void processBlock (const SampleType* input, SampleType* output, size_t n) noexcept
142  {
143  auto state = *parameters;
144 
145  for (size_t i = 0 ; i < n; ++i)
146  output[i] = processLoop<isBypassed, type> (input[i], state);
147 
148  snapToZero();
149  *parameters = state;
150  }
151 
152  template <bool isBypassed, typename ProcessContext>
153  void processInternal (const ProcessContext& context) noexcept
154  {
155  auto&& inputBlock = context.getInputBlock();
156  auto&& outputBlock = context.getOutputBlock();
157 
158  // This class can only process mono signals. Use the ProcessorDuplicator class
159  // to apply this filter on a multi-channel audio stream.
160  jassert (inputBlock.getNumChannels() == 1);
161  jassert (outputBlock.getNumChannels() == 1);
162 
163  auto n = inputBlock.getNumSamples();
164  auto* src = inputBlock .getChannelPointer (0);
165  auto* dst = outputBlock.getChannelPointer (0);
166 
167  switch (parameters->type)
168  {
169  case Parameters<NumericType>::Type::lowPass: processBlock<isBypassed, Parameters<NumericType>::Type::lowPass> (src, dst, n); break;
170  case Parameters<NumericType>::Type::bandPass: processBlock<isBypassed, Parameters<NumericType>::Type::bandPass> (src, dst, n); break;
171  case Parameters<NumericType>::Type::highPass: processBlock<isBypassed, Parameters<NumericType>::Type::highPass> (src, dst, n); break;
172  default: jassertfalse;
173  }
174  }
175 
176  //==============================================================================
177  std::array<SampleType, 3> y;
178  SampleType s1, s2;
179 
180  //==============================================================================
181  JUCE_LEAK_DETECTOR (Filter)
182  };
183 
184  //==============================================================================
190  template <typename NumericType>
191  struct Parameters : public ProcessorState
192  {
193  //==============================================================================
194  enum class Type
195  {
196  lowPass,
197  bandPass,
198  highPass
199  };
200 
201  //==============================================================================
203  Type type = Type::lowPass;
204 
211  void setCutOffFrequency (double sampleRate, NumericType frequency,
212  NumericType resonance = static_cast<NumericType> (1.0 / MathConstants<double>::sqrt2)) noexcept
213  {
214  jassert (sampleRate > 0);
215  jassert (resonance > NumericType (0));
216  jassert (frequency > NumericType (0) && frequency <= NumericType (sampleRate * 0.5));
217 
218  g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * frequency / sampleRate));
219  R2 = static_cast<NumericType> (1.0 / resonance);
220  h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
221  }
222 
223  //==============================================================================
228 
229  //==============================================================================
230  Parameters() = default;
231  Parameters (const Parameters& o) : g (o.g), R2 (o.R2), h (o.h) {}
232  Parameters& operator= (const Parameters& o) noexcept { g = o.g; R2 = o.R2; h = o.h; return *this; }
233 
234  //==============================================================================
235  NumericType g = static_cast<NumericType> (std::tan (MathConstants<double>::pi * 200.0 / 44100.0));
236  NumericType R2 = static_cast<NumericType> (MathConstants<double>::sqrt2);
237  NumericType h = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));
238  };
239 }
240 
241 } // namespace dsp
242 } // namespace juce
Parameters< NumericType >::Ptr parameters
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