OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
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
26namespace juce::dsp
27{
28
34template <typename SampleType>
36{
37public:
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 {
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,
70
71 lookupTable.reset (table);
72 generator = [table] (NumericType x) { return (*table) (x); };
73 }
74 else
75 {
76 generator = function;
77 }
78 }
79
80 //==============================================================================
83 {
84 if (force)
85 {
87 return;
88 }
89
90 frequency.setTargetValue (newFrequency);
91 }
92
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
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();
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
238private:
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
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