OpenShot Audio Library | OpenShotAudio  0.6.0
juce_FIRFilter.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 
29 namespace juce::dsp::FIR
30 {
31  template <typename NumericType>
32  struct Coefficients;
33 
34  //==============================================================================
48  template <typename SampleType>
49  class Filter
50  {
51  public:
55  using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
56 
59 
60  //==============================================================================
63 
65  Filter (CoefficientsPtr coefficientsToUse) : coefficients (std::move (coefficientsToUse)) { reset(); }
66 
67  Filter (const Filter&) = default;
68  Filter (Filter&&) = default;
69  Filter& operator= (const Filter&) = default;
70  Filter& operator= (Filter&&) = default;
71 
72  //==============================================================================
74  inline void prepare ([[maybe_unused]] const ProcessSpec& spec) noexcept
75  {
76  // This class can only process mono signals. Use the ProcessorDuplicator class
77  // to apply this filter on a multi-channel audio stream.
78  jassert (spec.numChannels == 1);
79  reset();
80  }
81 
87  void reset()
88  {
89  if (coefficients != nullptr)
90  {
91  auto newSize = coefficients->getFilterOrder() + 1;
92 
93  if (newSize != size)
94  {
95  memory.malloc (1 + jmax (newSize, size, static_cast<size_t> (128)));
96 
97  fifo = snapPointerToAlignment (memory.getData(), sizeof (SampleType));
98  size = newSize;
99  }
100 
101  for (size_t i = 0; i < size; ++i)
102  fifo[i] = SampleType {0};
103  }
104  }
105 
106  //==============================================================================
114 
115  //==============================================================================
117  template <typename ProcessContext>
118  void process (const ProcessContext& context) noexcept
119  {
120  static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
121  "The sample-type of the FIR filter must match the sample-type supplied to this process callback");
122  check();
123 
124  auto&& inputBlock = context.getInputBlock();
125  auto&& outputBlock = context.getOutputBlock();
126 
127  // This class can only process mono signals. Use the ProcessorDuplicator class
128  // to apply this filter on a multi-channel audio stream.
129  jassert (inputBlock.getNumChannels() == 1);
130  jassert (outputBlock.getNumChannels() == 1);
131 
132  auto numSamples = inputBlock.getNumSamples();
133  auto* src = inputBlock .getChannelPointer (0);
134  auto* dst = outputBlock.getChannelPointer (0);
135 
136  auto* fir = coefficients->getRawCoefficients();
137  size_t p = pos;
138 
139  if (context.isBypassed)
140  {
141  for (size_t i = 0; i < numSamples; ++i)
142  {
143  fifo[p] = dst[i] = src[i];
144  p = (p == 0 ? size - 1 : p - 1);
145  }
146  }
147  else
148  {
149  for (size_t i = 0; i < numSamples; ++i)
150  dst[i] = processSingleSample (src[i], fifo, fir, size, p);
151  }
152 
153  pos = p;
154  }
155 
156 
160  SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType sample) noexcept
161  {
162  check();
163  return processSingleSample (sample, fifo, coefficients->getRawCoefficients(), size, pos);
164  }
165 
166  private:
167  //==============================================================================
168  HeapBlock<SampleType> memory;
169  SampleType* fifo = nullptr;
170  size_t pos = 0, size = 0;
171 
172  //==============================================================================
173  void check()
174  {
175  jassert (coefficients != nullptr);
176 
177  if (size != (coefficients->getFilterOrder() + 1))
178  reset();
179  }
180 
181  static SampleType JUCE_VECTOR_CALLTYPE processSingleSample (SampleType sample, SampleType* buf,
182  const NumericType* fir, size_t m, size_t& p) noexcept
183  {
184  SampleType out (0);
185 
186  buf[p] = sample;
187 
188  size_t k;
189  for (k = 0; k < m - p; ++k)
190  out += buf[(p + k)] * fir[k];
191 
192  for (size_t j = 0; j < p; ++j)
193  out += buf[j] * fir[j + k];
194 
195  p = (p == 0 ? m - 1 : p - 1);
196 
197  return out;
198  }
199 
200 
201  JUCE_LEAK_DETECTOR (Filter)
202  };
203 
204  //==============================================================================
212  template <typename NumericType>
213  struct Coefficients : public ProcessorState
214  {
215  //==============================================================================
217  Coefficients() : coefficients ({ NumericType() }) {}
218 
220  Coefficients (size_t size) { coefficients.resize ((int) size); }
221 
223  Coefficients (const NumericType* samples, size_t numSamples) : coefficients (samples, (int) numSamples) {}
224 
225  Coefficients (const Coefficients&) = default;
226  Coefficients (Coefficients&&) = default;
227  Coefficients& operator= (const Coefficients&) = default;
228  Coefficients& operator= (Coefficients&&) = default;
229 
234 
235  //==============================================================================
237  size_t getFilterOrder() const noexcept { return static_cast<size_t> (coefficients.size()) - 1; }
238 
242  double getMagnitudeForFrequency (double frequency, double sampleRate) const noexcept;
243 
247  void getMagnitudeForFrequencyArray (double* frequencies, double* magnitudes,
248  size_t numSamples, double sampleRate) const noexcept;
249 
253  double getPhaseForFrequency (double frequency, double sampleRate) const noexcept;
254 
258  void getPhaseForFrequencyArray (double* frequencies, double* phases,
259  size_t numSamples, double sampleRate) const noexcept;
260 
262  NumericType* getRawCoefficients() noexcept { return coefficients.getRawDataPointer(); }
263 
265  const NumericType* getRawCoefficients() const noexcept { return coefficients.begin(); }
266 
267  //==============================================================================
269  void normalise() noexcept;
270 
271  //==============================================================================
275  Array<NumericType> coefficients;
276  };
277 
278 } // namespace juce::dsp::FIR
int size() const noexcept
Definition: juce_Array.h:215
ElementType * begin() noexcept
Definition: juce_Array.h:328
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:310
void resize(int targetNumItems)
Definition: juce_Array.h:670
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
ElementType * getData() const noexcept
Coefficients< NumericType >::Ptr coefficients
typename Coefficients< NumericType >::Ptr CoefficientsPtr
void process(const ProcessContext &context) noexcept
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType sample) noexcept
Filter(CoefficientsPtr coefficientsToUse)
void prepare([[maybe_unused]] const ProcessSpec &spec) noexcept
void getMagnitudeForFrequencyArray(double *frequencies, double *magnitudes, size_t numSamples, double sampleRate) const noexcept
NumericType * getRawCoefficients() noexcept
size_t getFilterOrder() const noexcept
Coefficients(const NumericType *samples, size_t numSamples)
double getMagnitudeForFrequency(double frequency, double sampleRate) const noexcept
Array< NumericType > coefficients
double getPhaseForFrequency(double frequency, double sampleRate) const noexcept
const NumericType * getRawCoefficients() const noexcept
void getPhaseForFrequencyArray(double *frequencies, double *phases, size_t numSamples, double sampleRate) const noexcept