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
31namespace juce
32{
33namespace dsp
34{
35
36/**
37 Generates a signal based on a user-supplied function.
38
39 @tags{DSP}
40*/
41template <typename SampleType>
43{
44public:
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,
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
245private:
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/** @}*/
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
ElementType * getRawDataPointer() noexcept
Returns a pointer to the actual array data.
Definition: juce_Array.h:314
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
bool isSmoothing() const noexcept
Returns true if the current value is currently being interpolated.
void setCurrentAndTargetValue(FloatType newValue)
Sets the current value and the target value.
FloatType getTargetValue() const noexcept
Returns the target value towards which the smoothed value is currently moving.
FloatType skip(int numSamples) noexcept
Skip the next numSamples samples.
FloatType getNextValue() noexcept
Compute the next value.
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
void setTargetValue(FloatType newValue) noexcept
Set the next value to ramp towards.
Generates a signal based on a user-supplied function.
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).
Oscillator()=default
Creates an uninitialised oscillator.
void prepare(const ProcessSpec &spec) noexcept
Called before processing starts.
bool isInitialised() const noexcept
Returns true if the Oscillator has been initialised.
typename SampleTypeHelpers::ElementType< SampleType >::Type NumericType
The NumericType is the underlying primitive type used by the SampleType (which could be either a prim...
void reset() noexcept
Resets the internal state of the oscillator.
NumericType getFrequency() const noexcept
Returns the current frequency of the oscillator.
void process(const ProcessContext &context) noexcept
Processes the input and output buffers supplied in the processing context.
void setFrequency(NumericType newFrequency, bool force=false) noexcept
Sets the frequency of the oscillator.
void initialise(const std::function< NumericType(NumericType)> &function, size_t lookupTableNumPoints=0)
Initialises the oscillator with a waveform.
This structure is passed into a DSP algorithm's prepare() method, and contains information about vari...
Commonly used mathematical constants.
void reset() noexcept
Resets the phase to 0.
Definition: juce_Phase.h:48
Type advance(Type increment) noexcept
Returns the current value, and increments the phase by the given increment.
Definition: juce_Phase.h:54