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 {
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
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
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)
static constexpr FloatType twoPi
static constexpr FloatType pi