OpenShot Audio Library | OpenShotAudio  0.6.0
juce_Oscillator.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 
34 template <typename SampleType>
36 {
37 public:
41  using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
42 
44  Oscillator() = default;
45 
51  Oscillator (const std::function<NumericType (NumericType)>& function,
52  size_t lookupTableNumPoints = 0)
53  {
54  initialise (function, lookupTableNumPoints);
55  }
56 
58  bool isInitialised() const noexcept { return static_cast<bool> (generator); }
59 
61  void initialise (const std::function<NumericType (NumericType)>& function,
62  size_t lookupTableNumPoints = 0)
63  {
64  if (lookupTableNumPoints != 0)
65  {
66  auto* table = new LookupTableTransform<NumericType> (function,
69  lookupTableNumPoints);
70 
71  lookupTable.reset (table);
72  generator = [table] (NumericType x) { return (*table) (x); };
73  }
74  else
75  {
76  generator = function;
77  }
78  }
79 
80  //==============================================================================
82  void setFrequency (NumericType newFrequency, bool force = false) noexcept
83  {
84  if (force)
85  {
86  frequency.setCurrentAndTargetValue (newFrequency);
87  return;
88  }
89 
90  frequency.setTargetValue (newFrequency);
91  }
92 
94  NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
95 
96  //==============================================================================
98  void prepare (const ProcessSpec& spec) noexcept
99  {
100  sampleRate = static_cast<NumericType> (spec.sampleRate);
101  rampBuffer.resize ((int) spec.maximumBlockSize);
102 
103  reset();
104  }
105 
107  void reset() noexcept
108  {
109  phase.reset();
110 
111  if (sampleRate > 0)
112  frequency.reset (sampleRate, 0.05);
113  }
114 
115  //==============================================================================
117  SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType input) noexcept
118  {
119  jassert (isInitialised());
120  auto increment = MathConstants<NumericType>::twoPi * frequency.getNextValue() / sampleRate;
121  return input + generator (phase.advance (increment) - MathConstants<NumericType>::pi);
122  }
123 
125  template <typename ProcessContext>
126  void process (const ProcessContext& context) noexcept
127  {
128  jassert (isInitialised());
129  auto&& outBlock = context.getOutputBlock();
130  auto&& inBlock = context.getInputBlock();
131 
132  // this is an output-only processor
133  jassert (outBlock.getNumSamples() <= static_cast<size_t> (rampBuffer.size()));
134 
135  auto len = outBlock.getNumSamples();
136  auto numChannels = outBlock.getNumChannels();
137  auto inputChannels = inBlock.getNumChannels();
138  auto baseIncrement = MathConstants<NumericType>::twoPi / sampleRate;
139 
140  if (context.isBypassed)
141  context.getOutputBlock().clear();
142 
143  if (frequency.isSmoothing())
144  {
145  auto* buffer = rampBuffer.getRawDataPointer();
146 
147  for (size_t i = 0; i < len; ++i)
148  buffer[i] = phase.advance (baseIncrement * frequency.getNextValue())
150 
151  if (! context.isBypassed)
152  {
153  size_t ch;
154 
155  if (context.usesSeparateInputAndOutputBlocks())
156  {
157  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
158  {
159  auto* dst = outBlock.getChannelPointer (ch);
160  auto* src = inBlock.getChannelPointer (ch);
161 
162  for (size_t i = 0; i < len; ++i)
163  dst[i] = src[i] + generator (buffer[i]);
164  }
165  }
166  else
167  {
168  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
169  {
170  auto* dst = outBlock.getChannelPointer (ch);
171 
172  for (size_t i = 0; i < len; ++i)
173  dst[i] += generator (buffer[i]);
174  }
175  }
176 
177  for (; ch < numChannels; ++ch)
178  {
179  auto* dst = outBlock.getChannelPointer (ch);
180 
181  for (size_t i = 0; i < len; ++i)
182  dst[i] = generator (buffer[i]);
183  }
184  }
185  }
186  else
187  {
188  auto freq = baseIncrement * frequency.getNextValue();
189  auto p = phase;
190 
191  if (context.isBypassed)
192  {
193  frequency.skip (static_cast<int> (len));
194  p.advance (freq * static_cast<NumericType> (len));
195  }
196  else
197  {
198  size_t ch;
199 
200  if (context.usesSeparateInputAndOutputBlocks())
201  {
202  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
203  {
204  p = phase;
205  auto* dst = outBlock.getChannelPointer (ch);
206  auto* src = inBlock.getChannelPointer (ch);
207 
208  for (size_t i = 0; i < len; ++i)
209  dst[i] = src[i] + generator (p.advance (freq) - MathConstants<NumericType>::pi);
210  }
211  }
212  else
213  {
214  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
215  {
216  p = phase;
217  auto* dst = outBlock.getChannelPointer (ch);
218 
219  for (size_t i = 0; i < len; ++i)
220  dst[i] += generator (p.advance (freq) - MathConstants<NumericType>::pi);
221  }
222  }
223 
224  for (; ch < numChannels; ++ch)
225  {
226  p = phase;
227  auto* dst = outBlock.getChannelPointer (ch);
228 
229  for (size_t i = 0; i < len; ++i)
230  dst[i] = generator (p.advance (freq) - MathConstants<NumericType>::pi);
231  }
232  }
233 
234  phase = p;
235  }
236  }
237 
238 private:
239  //==============================================================================
240  std::function<NumericType (NumericType)> generator;
241  std::unique_ptr<LookupTableTransform<NumericType>> lookupTable;
242  Array<NumericType> rampBuffer;
243  SmoothedValue<NumericType> frequency { static_cast<NumericType> (440.0) };
244  NumericType sampleRate = 48000.0;
245  Phase<NumericType> phase;
246 };
247 
248 } // namespace juce::dsp
int size() const noexcept
Definition: juce_Array.h:215
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:310
void resize(int targetNumItems)
Definition: juce_Array.h:670
bool isSmoothing() const noexcept
void setCurrentAndTargetValue(FloatType newValue)
FloatType getTargetValue() const noexcept
FloatType skip(int numSamples) noexcept
FloatType getNextValue() noexcept
void reset(double sampleRate, double rampLengthInSeconds) noexcept
void setTargetValue(FloatType newValue) noexcept
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType input) noexcept
Oscillator(const std::function< NumericType(NumericType)> &function, size_t lookupTableNumPoints=0)
void prepare(const ProcessSpec &spec) noexcept
bool isInitialised() const noexcept
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
void reset() noexcept
NumericType getFrequency() const noexcept
void process(const ProcessContext &context) noexcept
void setFrequency(NumericType newFrequency, bool force=false) noexcept
void initialise(const std::function< NumericType(NumericType)> &function, size_t lookupTableNumPoints=0)
void reset() noexcept
Definition: juce_Phase.h:41
Type advance(Type increment) noexcept
Definition: juce_Phase.h:47