OpenShot Audio Library | OpenShotAudio  0.6.0
juce_IIRFilter_Impl.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 
26 namespace juce::dsp::IIR
27 {
28 
29 #ifndef DOXYGEN
30 
31 template <typename NumericType>
32 template <size_t Num>
33 Coefficients<NumericType>& Coefficients<NumericType>::assignImpl (const NumericType* values)
34 {
35  static_assert (Num % 2 == 0, "Must supply an even number of coefficients");
36  const auto a0Index = Num / 2;
37  const auto a0 = values[a0Index];
38  const auto a0Inv = ! approximatelyEqual (a0, NumericType())
39  ? static_cast<NumericType> (1) / values[a0Index]
40  : NumericType();
41 
42  coefficients.clearQuick();
43  coefficients.ensureStorageAllocated ((int) jmax ((size_t) 8, Num));
44 
45  for (size_t i = 0; i < Num; ++i)
46  if (i != a0Index)
47  coefficients.add (values[i] * a0Inv);
48 
49  return *this;
50 }
51 
52 //==============================================================================
53 template <typename SampleType>
55  : coefficients (new Coefficients<typename Filter<SampleType>::NumericType> (1, 0, 1, 0))
56 {
57  reset();
58 }
59 
60 template <typename SampleType>
61 Filter<SampleType>::Filter (CoefficientsPtr c) : coefficients (std::move (c))
62 {
63  reset();
64 }
65 
66 template <typename SampleType>
67 void Filter<SampleType>::reset (SampleType resetToValue)
68 {
69  auto newOrder = coefficients->getFilterOrder();
70 
71  if (newOrder != order)
72  {
73  memory.malloc (jmax (order, newOrder, static_cast<size_t> (3)) + 1);
74  state = snapPointerToAlignment (memory.getData(), sizeof (SampleType));
75  order = newOrder;
76  }
77 
78  for (size_t i = 0; i < order; ++i)
79  state[i] = resetToValue;
80 }
81 
82 template <typename SampleType>
83 void Filter<SampleType>::prepare (const ProcessSpec&) noexcept { reset(); }
84 
85 template <typename SampleType>
86 template <typename ProcessContext, bool bypassed>
87 void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept
88 {
89  static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
90  "The sample-type of the IIR filter must match the sample-type supplied to this process callback");
91  check();
92 
93  auto&& inputBlock = context.getInputBlock();
94  auto&& outputBlock = context.getOutputBlock();
95 
96  // This class can only process mono signals. Use the ProcessorDuplicator class
97  // to apply this filter on a multi-channel audio stream.
98  jassert (inputBlock.getNumChannels() == 1);
99  jassert (outputBlock.getNumChannels() == 1);
100 
101  auto numSamples = inputBlock.getNumSamples();
102  auto* src = inputBlock .getChannelPointer (0);
103  auto* dst = outputBlock.getChannelPointer (0);
104  auto* coeffs = coefficients->getRawCoefficients();
105 
106  switch (order)
107  {
108  case 1:
109  {
110  auto b0 = coeffs[0];
111  auto b1 = coeffs[1];
112  auto a1 = coeffs[2];
113 
114  auto lv1 = state[0];
115 
116  for (size_t i = 0; i < numSamples; ++i)
117  {
118  auto input = src[i];
119  auto output = input * b0 + lv1;
120 
121  dst[i] = bypassed ? input : output;
122 
123  lv1 = (input * b1) - (output * a1);
124  }
125 
126  util::snapToZero (lv1); state[0] = lv1;
127  }
128  break;
129 
130  case 2:
131  {
132  auto b0 = coeffs[0];
133  auto b1 = coeffs[1];
134  auto b2 = coeffs[2];
135  auto a1 = coeffs[3];
136  auto a2 = coeffs[4];
137 
138  auto lv1 = state[0];
139  auto lv2 = state[1];
140 
141  for (size_t i = 0; i < numSamples; ++i)
142  {
143  auto input = src[i];
144  auto output = (input * b0) + lv1;
145  dst[i] = bypassed ? input : output;
146 
147  lv1 = (input * b1) - (output* a1) + lv2;
148  lv2 = (input * b2) - (output* a2);
149  }
150 
151  util::snapToZero (lv1); state[0] = lv1;
152  util::snapToZero (lv2); state[1] = lv2;
153  }
154  break;
155 
156  case 3:
157  {
158  auto b0 = coeffs[0];
159  auto b1 = coeffs[1];
160  auto b2 = coeffs[2];
161  auto b3 = coeffs[3];
162  auto a1 = coeffs[4];
163  auto a2 = coeffs[5];
164  auto a3 = coeffs[6];
165 
166  auto lv1 = state[0];
167  auto lv2 = state[1];
168  auto lv3 = state[2];
169 
170  for (size_t i = 0; i < numSamples; ++i)
171  {
172  auto input = src[i];
173  auto output = (input * b0) + lv1;
174  dst[i] = bypassed ? input : output;
175 
176  lv1 = (input * b1) - (output* a1) + lv2;
177  lv2 = (input * b2) - (output* a2) + lv3;
178  lv3 = (input * b3) - (output* a3);
179  }
180 
181  util::snapToZero (lv1); state[0] = lv1;
182  util::snapToZero (lv2); state[1] = lv2;
183  util::snapToZero (lv3); state[2] = lv3;
184  }
185  break;
186 
187  default:
188  {
189  for (size_t i = 0; i < numSamples; ++i)
190  {
191  auto input = src[i];
192  auto output= (input * coeffs[0]) + state[0];
193  dst[i] = bypassed ? input : output;
194 
195  for (size_t j = 0; j < order - 1; ++j)
196  state[j] = (input * coeffs[j + 1]) - (output* coeffs[order + j + 1]) + state[j + 1];
197 
198  state[order - 1] = (input * coeffs[order]) - (output* coeffs[order * 2]);
199  }
200 
201  snapToZero();
202  }
203  }
204 }
205 
206 template <typename SampleType>
207 SampleType JUCE_VECTOR_CALLTYPE Filter<SampleType>::processSample (SampleType sample) noexcept
208 {
209  check();
210  auto* c = coefficients->getRawCoefficients();
211 
212  auto output = (c[0] * sample) + state[0];
213 
214  for (size_t j = 0; j < order - 1; ++j)
215  state[j] = (c[j + 1] * sample) - (c[order + j + 1] * output) + state[j + 1];
216 
217  state[order - 1] = (c[order] * sample) - (c[order * 2] * output);
218 
219  return output;
220 }
221 
222 template <typename SampleType>
224 {
225  for (size_t i = 0; i < order; ++i)
226  util::snapToZero (state[i]);
227 }
228 
229 template <typename SampleType>
231 {
232  jassert (coefficients != nullptr);
233 
234  if (order != coefficients->getFilterOrder())
235  reset();
236 }
237 
238 #endif
239 
240 } // namespace juce::dsp::IIR
void prepare(const ProcessSpec &) noexcept
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType sample) noexcept
typename Coefficients< NumericType >::Ptr CoefficientsPtr
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType