OpenShot Audio Library | OpenShotAudio  0.6.0
juce_Phaser.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
27 {
28 
39 template <typename SampleType>
40 class Phaser
41 {
42 public:
43  //==============================================================================
45  Phaser();
46 
47  //==============================================================================
51  void setRate (SampleType newRateHz);
52 
56  void setDepth (SampleType newDepth);
57 
60  void setCentreFrequency (SampleType newCentreHz);
61 
65  void setFeedback (SampleType newFeedback);
66 
70  void setMix (SampleType newMix);
71 
72  //==============================================================================
74  void prepare (const ProcessSpec& spec);
75 
77  void reset();
78 
79  //==============================================================================
81  template <typename ProcessContext>
82  void process (const ProcessContext& context) noexcept
83  {
84  const auto& inputBlock = context.getInputBlock();
85  auto& outputBlock = context.getOutputBlock();
86  const auto numChannels = outputBlock.getNumChannels();
87  const auto numSamples = outputBlock.getNumSamples();
88 
89  jassert (inputBlock.getNumChannels() == numChannels);
90  jassert (inputBlock.getNumChannels() == lastOutput.size());
91  jassert (inputBlock.getNumSamples() == numSamples);
92 
93  if (context.isBypassed)
94  {
95  outputBlock.copyFrom (inputBlock);
96  return;
97  }
98 
99  int numSamplesDown = 0;
100  auto counter = updateCounter;
101 
102  for (size_t i = 0; i < numSamples; ++i)
103  {
104  if (counter == 0)
105  numSamplesDown++;
106 
107  counter++;
108 
109  if (counter == maxUpdateCounter)
110  counter = 0;
111  }
112 
113  if (numSamplesDown > 0)
114  {
115  auto freqBlock = AudioBlock<SampleType> (bufferFrequency).getSubBlock (0, (size_t) numSamplesDown);
116  auto contextFreq = ProcessContextReplacing<SampleType> (freqBlock);
117  freqBlock.clear();
118 
119  osc.process (contextFreq);
120  freqBlock.multiplyBy (oscVolume);
121  }
122 
123  auto* freqSamples = bufferFrequency.getWritePointer (0);
124 
125  for (int i = 0; i < numSamplesDown; ++i)
126  {
127  auto lfo = jlimit (static_cast<SampleType> (0.0),
128  static_cast<SampleType> (1.0),
129  freqSamples[i] + normCentreFrequency);
130 
131  freqSamples[i] = mapToLog10 (lfo, static_cast<SampleType> (20.0),
132  static_cast<SampleType> (jmin (20000.0, 0.49 * sampleRate)));
133  }
134 
135  auto currentFrequency = filters[0]->getCutoffFrequency();
136  dryWet.pushDrySamples (inputBlock);
137 
138  for (size_t channel = 0; channel < numChannels; ++channel)
139  {
140  counter = updateCounter;
141  int k = 0;
142 
143  auto* inputSamples = inputBlock .getChannelPointer (channel);
144  auto* outputSamples = outputBlock.getChannelPointer (channel);
145 
146  for (size_t i = 0; i < numSamples; ++i)
147  {
148  auto input = inputSamples[i];
149  auto output = input - lastOutput[channel];
150 
151  if (i == 0 && counter != 0)
152  for (int n = 0; n < numStages; ++n)
153  filters[n]->setCutoffFrequency (currentFrequency);
154 
155  if (counter == 0)
156  {
157  for (int n = 0; n < numStages; ++n)
158  filters[n]->setCutoffFrequency (freqSamples[k]);
159 
160  k++;
161  }
162 
163  for (int n = 0; n < numStages; ++n)
164  output = filters[n]->processSample ((int) channel, output);
165 
166  outputSamples[i] = output;
167  lastOutput[channel] = output * feedbackVolume[channel].getNextValue();
168 
169  counter++;
170 
171  if (counter == maxUpdateCounter)
172  counter = 0;
173  }
174  }
175 
176  dryWet.mixWetSamples (outputBlock);
177  updateCounter = (updateCounter + (int) numSamples) % maxUpdateCounter;
178  }
179 
180 private:
181  //==============================================================================
182  void update();
183 
184  //==============================================================================
188  std::vector<SmoothedValue<SampleType, ValueSmoothingTypes::Linear>> feedbackVolume { 2 };
189  DryWetMixer<SampleType> dryWet;
190  std::vector<SampleType> lastOutput { 2 };
191  AudioBuffer<SampleType> bufferFrequency;
192  SampleType normCentreFrequency = 0.5;
193  double sampleRate = 44100.0;
194 
195  int updateCounter = 0;
196  static constexpr int maxUpdateCounter = 4;
197 
198  SampleType rate = 1.0, depth = 0.5, feedback = 0.0, mix = 0.5;
199  SampleType centreFrequency = 1300.0;
200  static constexpr int numStages = 6;
201 };
202 
203 } // namespace juce::dsp
Type * getWritePointer(int channelNumber) noexcept
AudioBlock getSubBlock(size_t newOffset, size_t newLength) const noexcept
void prepare(const ProcessSpec &spec)
Definition: juce_Phaser.cpp:92
void process(const ProcessContext &context) noexcept
Definition: juce_Phaser.h:82
void setDepth(SampleType newDepth)
Definition: juce_Phaser.cpp:55
void setFeedback(SampleType newFeedback)
Definition: juce_Phaser.cpp:73
void setMix(SampleType newMix)
Definition: juce_Phaser.cpp:82
void setRate(SampleType newRateHz)
Definition: juce_Phaser.cpp:46
void setCentreFrequency(SampleType newCentreHz)
Definition: juce_Phaser.cpp:64