OpenShot Library | OpenShotAudio  0.2.2
juce_Oscillator.h
1 
2 /** @weakgroup juce_dsp-processors
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  By using JUCE, you agree to the terms of both the JUCE 5 End-User License
15  Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
16  27th April 2017).
17 
18  End User License Agreement: www.juce.com/juce-5-licence
19  Privacy Policy: www.juce.com/juce-5-privacy-policy
20 
21  Or: You may also use this code under the terms of the GPL v3 (see
22  www.gnu.org/licenses).
23 
24  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
25  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
26  DISCLAIMED.
27 
28  ==============================================================================
29 */
30 
31 namespace juce
32 {
33 namespace dsp
34 {
35 
36 /**
37  Generates a signal based on a user-supplied function.
38 
39  @tags{DSP}
40 */
41 template <typename SampleType>
43 {
44 public:
45  /** The NumericType is the underlying primitive type used by the SampleType (which
46  could be either a primitive or vector)
47  */
48  using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
49 
50  /** Creates an uninitialised oscillator. Call initialise before first use. */
51  Oscillator() = default;
52 
53  /** Creates an oscillator with a periodic input function (-pi..pi).
54 
55  If lookup table is not zero, then the function will be approximated
56  with a lookup table.
57  */
58  Oscillator (const std::function<NumericType(NumericType)>& function,
59  size_t lookupTableNumPoints = 0)
60  {
61  initialise (function, lookupTableNumPoints);
62  }
63 
64  /** Returns true if the Oscillator has been initialised. */
65  bool isInitialised() const noexcept { return static_cast<bool> (generator); }
66 
67  /** Initialises the oscillator with a waveform. */
68  void initialise (const std::function<NumericType(NumericType)>& function,
69  size_t lookupTableNumPoints = 0)
70  {
71  if (lookupTableNumPoints != 0)
72  {
73  auto* table = new LookupTableTransform<NumericType> (function,
75  MathConstants<NumericType>::pi,
76  lookupTableNumPoints);
77 
78  lookupTable.reset (table);
79  generator = [table] (NumericType x) { return (*table) (x); };
80  }
81  else
82  {
83  generator = function;
84  }
85  }
86 
87  //==============================================================================
88  /** Sets the frequency of the oscillator. */
89  void setFrequency (NumericType newFrequency, bool force = false) noexcept
90  {
91  if (force)
92  {
93  frequency.setCurrentAndTargetValue (newFrequency);
94  return;
95  }
96 
97  frequency.setTargetValue (newFrequency);
98  }
99 
100  /** Returns the current frequency of the oscillator. */
101  NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
102 
103  //==============================================================================
104  /** Called before processing starts. */
105  void prepare (const ProcessSpec& spec) noexcept
106  {
107  sampleRate = static_cast<NumericType> (spec.sampleRate);
108  rampBuffer.resize ((int) spec.maximumBlockSize);
109 
110  reset();
111  }
112 
113  /** Resets the internal state of the oscillator */
114  void reset() noexcept
115  {
116  phase.reset();
117 
118  if (sampleRate > 0)
119  frequency.reset (sampleRate, 0.05);
120  }
121 
122  //==============================================================================
123  /** Returns the result of processing a single sample. */
124  SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType input) noexcept
125  {
126  jassert (isInitialised());
127  auto increment = MathConstants<NumericType>::twoPi * frequency.getNextValue() / sampleRate;
128  return input + generator (phase.advance (increment) - MathConstants<NumericType>::pi);
129  }
130 
131  /** Processes the input and output buffers supplied in the processing context. */
132  template <typename ProcessContext>
133  void process (const ProcessContext& context) noexcept
134  {
135  jassert (isInitialised());
136  auto&& outBlock = context.getOutputBlock();
137  auto&& inBlock = context.getInputBlock();
138 
139  // this is an output-only processor
140  jassert (outBlock.getNumSamples() <= static_cast<size_t> (rampBuffer.size()));
141 
142  auto len = outBlock.getNumSamples();
143  auto numChannels = outBlock.getNumChannels();
144  auto inputChannels = inBlock.getNumChannels();
145  auto baseIncrement = MathConstants<NumericType>::twoPi / sampleRate;
146 
147  if (context.isBypassed)
148  context.getOutputBlock().clear();
149 
150  if (frequency.isSmoothing())
151  {
152  auto* buffer = rampBuffer.getRawDataPointer();
153 
154  for (size_t i = 0; i < len; ++i)
155  buffer[i] = phase.advance (baseIncrement * frequency.getNextValue())
157 
158  if (! context.isBypassed)
159  {
160  size_t ch;
161 
162  if (context.usesSeparateInputAndOutputBlocks())
163  {
164  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
165  {
166  auto* dst = outBlock.getChannelPointer (ch);
167  auto* src = inBlock.getChannelPointer (ch);
168 
169  for (size_t i = 0; i < len; ++i)
170  dst[i] = src[i] + generator (buffer[i]);
171  }
172  }
173  else
174  {
175  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
176  {
177  auto* dst = outBlock.getChannelPointer (ch);
178 
179  for (size_t i = 0; i < len; ++i)
180  dst[i] += generator (buffer[i]);
181  }
182  }
183 
184  for (; ch < numChannels; ++ch)
185  {
186  auto* dst = outBlock.getChannelPointer (ch);
187 
188  for (size_t i = 0; i < len; ++i)
189  dst[i] = generator (buffer[i]);
190  }
191  }
192  }
193  else
194  {
195  auto freq = baseIncrement * frequency.getNextValue();
196  auto p = phase;
197 
198  if (context.isBypassed)
199  {
200  frequency.skip (static_cast<int> (len));
201  p.advance (freq * static_cast<NumericType> (len));
202  }
203  else
204  {
205  size_t ch;
206 
207  if (context.usesSeparateInputAndOutputBlocks())
208  {
209  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
210  {
211  p = phase;
212  auto* dst = outBlock.getChannelPointer (ch);
213  auto* src = inBlock.getChannelPointer (ch);
214 
215  for (size_t i = 0; i < len; ++i)
216  dst[i] = src[i] + generator (p.advance (freq) - MathConstants<NumericType>::pi);
217  }
218  }
219  else
220  {
221  for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
222  {
223  p = phase;
224  auto* dst = outBlock.getChannelPointer (ch);
225 
226  for (size_t i = 0; i < len; ++i)
227  dst[i] += generator (p.advance (freq) - MathConstants<NumericType>::pi);
228  }
229  }
230 
231  for (; ch < numChannels; ++ch)
232  {
233  p = phase;
234  auto* dst = outBlock.getChannelPointer (ch);
235 
236  for (size_t i = 0; i < len; ++i)
237  dst[i] = generator (p.advance (freq) - MathConstants<NumericType>::pi);
238  }
239  }
240 
241  phase = p;
242  }
243  }
244 
245 private:
246  //==============================================================================
247  std::function<NumericType(NumericType)> generator;
248  std::unique_ptr<LookupTableTransform<NumericType>> lookupTable;
249  Array<NumericType> rampBuffer;
250  SmoothedValue<NumericType> frequency { static_cast<NumericType> (440.0) };
251  NumericType sampleRate = 48000.0;
252  Phase<NumericType> phase;
253 };
254 
255 } // namespace dsp
256 } // namespace juce
257 
258 /** @}*/
FloatType getNextValue() noexcept
Compute the next value.
FloatType getTargetValue() const noexcept
Returns the target value towards which the smoothed value is currently moving.
void reset() noexcept
Resets the phase to 0.
Definition: juce_Phase.h:48
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
The NumericType is the underlying primitive type used by the SampleType (which could be either a prim...
FloatType skip(int numSamples) noexcept
Skip the next numSamples samples.
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
void setFrequency(NumericType newFrequency, bool force=false) noexcept
Sets the frequency of the oscillator.
Oscillator()=default
Creates an uninitialised oscillator.
bool isSmoothing() const noexcept
Returns true if the current value is currently being interpolated.
void resize(int targetNumItems)
This will enlarge or shrink the array to the given number of elements, by adding or removing items fr...
Definition: juce_Array.h:674
Generates a signal based on a user-supplied function.
bool isInitialised() const noexcept
Returns true if the Oscillator has been initialised.
Type advance(Type increment) noexcept
Returns the current value, and increments the phase by the given increment.
Definition: juce_Phase.h:54
SampleType JUCE_VECTOR_CALLTYPE processSample(SampleType input) noexcept
Returns the result of processing a single sample.
Oscillator(const std::function< NumericType(NumericType)> &function, size_t lookupTableNumPoints=0)
Creates an oscillator with a periodic input function (-pi..pi).
void prepare(const ProcessSpec &spec) noexcept
Called before processing starts.
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
void reset() noexcept
Resets the internal state of the oscillator.
ElementType * getRawDataPointer() noexcept
Returns a pointer to the actual array data.
Definition: juce_Array.h:314
void setTargetValue(FloatType newValue) noexcept
Set the next value to ramp towards.
This structure is passed into a DSP algorithm&#39;s prepare() method, and contains information about vari...
NumericType getFrequency() const noexcept
Returns the current frequency of the oscillator.
void setCurrentAndTargetValue(FloatType newValue)
Sets the current value and the target value.
Commonly used mathematical constants.
void process(const ProcessContext &context) noexcept
Processes the input and output buffers supplied in the processing context.
void initialise(const std::function< NumericType(NumericType)> &function, size_t lookupTableNumPoints=0)
Initialises the oscillator with a waveform.