LMMS
Loading...
Searching...
No Matches
Oscillator.h
Go to the documentation of this file.
1/*
2 * Oscillator.h - declaration of class Oscillator
3 *
4 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5 * 2018 Dave French <dave/dot/french3/at/googlemail/dot/com>
6 *
7 * This file is part of LMMS - https://lmms.io
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program (see COPYING); if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA.
23 *
24 */
25
26#ifndef LMMS_OSCILLATOR_H
27#define LMMS_OSCILLATOR_H
28
29#include <cassert>
30#include <fftw3.h>
31#include <memory>
32#include <cstdlib>
33#include <cmath>
34
35#include "Engine.h"
36#include "lmms_math.h"
37#include "AudioEngine.h"
38#include "OscillatorConstants.h"
39#include "SampleBuffer.h"
40
41namespace lmms
42{
43
44
45class IntModel;
46
47
48class LMMS_EXPORT Oscillator
49{
50public:
51 enum class WaveShape
52 {
54 Triangle,
57 MoogSaw,
58 Exponential,
60 UserDefined,
62 };
63 constexpr static auto NumWaveShapes = static_cast<std::size_t>(WaveShape::Count);
65 constexpr static auto FirstWaveShapeTable = static_cast<std::size_t>(WaveShape::Triangle);
67 constexpr static auto NumWaveShapeTables = static_cast<std::size_t>(WaveShape::WhiteNoise) - FirstWaveShapeTable;
68
69 enum class ModulationAlgo
70 {
71 PhaseModulation,
72 AmplitudeModulation,
73 SignalMix,
74 SynchronizedBySubOsc,
75 FrequencyModulation,
77 } ;
78 constexpr static auto NumModulationAlgos = static_cast<std::size_t>(ModulationAlgo::Count);
79
80 Oscillator( const IntModel *wave_shape_model,
81 const IntModel *mod_algo_model,
82 const float &freq,
83 const float &detuning_div_samplerate,
84 const float &phase_offset,
85 const float &volume,
86 Oscillator *m_subOsc = nullptr);
87 virtual ~Oscillator()
88 {
89 delete m_subOsc;
90 }
91
92 static void waveTableInit();
93 static void destroyFFTPlans();
94 static std::unique_ptr<OscillatorConstants::waveform_t> generateAntiAliasUserWaveTable(const SampleBuffer* sampleBuffer);
95
96 inline void setUseWaveTable(bool n)
97 {
99 }
100
101 void setUserWave(std::shared_ptr<const SampleBuffer> _wave)
102 {
103 m_userWave = _wave;
104 }
105
106 void setUserAntiAliasWaveTable(std::shared_ptr<const OscillatorConstants::waveform_t> waveform)
107 {
109 }
110
111 void update(SampleFrame* ab, const f_cnt_t frames, const ch_cnt_t chnl, bool modulator = false);
112
113 // now follow the wave-shape-routines...
114 static inline sample_t sinSample( const float _sample )
115 {
116 return std::sin(_sample * 2 * std::numbers::pi_v<float>);
117 }
118
119 static inline sample_t triangleSample( const float _sample )
120 {
121 const float ph = absFraction( _sample );
122 if( ph <= 0.25f )
123 {
124 return ph * 4.0f;
125 }
126 else if( ph <= 0.75f )
127 {
128 return 2.0f - ph * 4.0f;
129 }
130 return ph * 4.0f - 4.0f;
131 }
132
133 static inline sample_t sawSample( const float _sample )
134 {
135 return -1.0f + absFraction( _sample ) * 2.0f;
136 }
137
138 static inline sample_t squareSample( const float _sample )
139 {
140 return ( absFraction( _sample ) > 0.5f ) ? -1.0f : 1.0f;
141 }
142
143 static inline sample_t moogSawSample( const float _sample )
144 {
145 const float ph = absFraction( _sample );
146 if( ph < 0.5f )
147 {
148 return -1.0f + ph * 4.0f;
149 }
150 return 1.0f - 2.0f * ph;
151 }
152
153 static inline sample_t expSample( const float _sample )
154 {
155 float ph = absFraction( _sample );
156 if( ph > 0.5f )
157 {
158 ph = 1.0f - ph;
159 }
160 return -1.0f + 8.0f * ph * ph;
161 }
162
163 static inline sample_t noiseSample( const float )
164 {
165 return fastRandInc(-1.f, 1.f);
166 }
167
168 static sample_t userWaveSample(const SampleBuffer* buffer, const float sample)
169 {
170 if (buffer == nullptr || buffer->size() == 0) { return 0; }
171 const auto frames = buffer->size();
172 const auto frame = absFraction(sample) * frames;
173 const auto f1 = static_cast<f_cnt_t>(frame);
174
175 return std::lerp(buffer->data()[f1][0], buffer->data()[(f1 + 1) % frames][0], fraction(frame));
176 }
177
184
185 inline wtSampleControl getWtSampleControl(const float sample) const
186 {
189 control.f1 = static_cast<f_cnt_t>(control.frame);
191 control.f1 + 1 :
192 0;
194 m_freq * m_detuning_div_samplerate * Engine::audioEngine()->outputSampleRate());
195 return control;
196 }
197
200 const float sample) const
201 {
202 assert(table != nullptr);
204 return std::lerp(table[control.band][control.f1], table[control.band][control.f2], fraction(control.frame));
205 }
206
208 {
209 assert(table != nullptr);
211 return std::lerp(
212 (*table)[control.band][control.f1],
213 (*table)[control.band][control.f2],
214 fraction(control.frame)
215 );
216 }
217
218 inline sample_t wtSample(sample_t **table, const float sample) const
219 {
220 assert(table != nullptr);
222 return std::lerp(table[control.band][control.f1], table[control.band][control.f2], fraction(control.frame));
223 }
224
225 static inline int waveTableBandFromFreq(float freq)
226 {
227 // Frequency bands are indexed relative to default MIDI key frequencies.
228 // I.e., 440 Hz (A4, key 69): 69 + 12 * log2(1) = 69
229 // To always avoid aliasing, ceil() is used instead of round(). It ensures that the nearest wavetable with
230 // lower than optimal number of harmonics is used when exactly matching wavetable is not available.
231 int band = (69 + static_cast<int>(std::ceil(12.0f * std::log2(freq / 440.0f)))) / OscillatorConstants::SEMITONES_PER_TABLE;
232 // Limit the returned value to a valid wavetable index range.
233 // (qBound would bring Qt into the audio code, which not a preferable option due to realtime safety.
234 // C++17 std::clamp() could be used in the future.)
236 }
237
238 static inline float freqFromWaveTableBand(int band)
239 {
240 return 440.0f * std::exp2((band * OscillatorConstants::SEMITONES_PER_TABLE - 69.0f) / 12.0f);
241 }
242
243private:
246 const float & m_freq;
248 const float & m_volume;
249 const float & m_ext_phaseOffset;
252 float m_phase;
253 std::shared_ptr<const SampleBuffer> m_userWave = SampleBuffer::emptyBuffer();
254 std::shared_ptr<const OscillatorConstants::waveform_t> m_userAntiAliasWaveTable;
256 // There are many update*() variants; the modulator flag is stored as a member variable to avoid
257 // adding more explicit parameters to all of them. Can be converted to a parameter if needed.
259
260 /* Multiband WaveTable */
262 static fftwf_plan s_fftPlan;
263 static fftwf_plan s_ifftPlan;
264 static fftwf_complex * s_specBuf;
265 static std::array<float, OscillatorConstants::WAVETABLE_LENGTH> s_sampleBuffer;
266
267 static void generateSawWaveTable(int bands, sample_t* table, int firstBand = 1);
268 static void generateTriangleWaveTable(int bands, sample_t* table, int firstBand = 1);
269 static void generateSquareWaveTable(int bands, sample_t* table, int firstBand = 1);
270 static void generateFromFFT(int bands, sample_t* table);
271 static void generateWaveTables();
272 static void createFFTPlans();
273
274 /* End Multiband wavetable */
275
276
277 void updateNoSub( SampleFrame* _ab, const f_cnt_t _frames,
278 const ch_cnt_t _chnl );
279 void updatePM( SampleFrame* _ab, const f_cnt_t _frames,
280 const ch_cnt_t _chnl );
281 void updateAM( SampleFrame* _ab, const f_cnt_t _frames,
282 const ch_cnt_t _chnl );
283 void updateMix( SampleFrame* _ab, const f_cnt_t _frames,
284 const ch_cnt_t _chnl );
285 void updateSync( SampleFrame* _ab, const f_cnt_t _frames,
286 const ch_cnt_t _chnl );
287 void updateFM( SampleFrame* _ab, const f_cnt_t _frames,
288 const ch_cnt_t _chnl );
289
290 float syncInit( SampleFrame* _ab, const f_cnt_t _frames,
291 const ch_cnt_t _chnl );
292 inline bool syncOk( float _osc_coeff );
293
294 template<WaveShape W>
295 void updateNoSub( SampleFrame* _ab, const f_cnt_t _frames,
296 const ch_cnt_t _chnl );
297 template<WaveShape W>
298 void updatePM( SampleFrame* _ab, const f_cnt_t _frames,
299 const ch_cnt_t _chnl );
300 template<WaveShape W>
301 void updateAM( SampleFrame* _ab, const f_cnt_t _frames,
302 const ch_cnt_t _chnl );
303 template<WaveShape W>
304 void updateMix( SampleFrame* _ab, const f_cnt_t _frames,
305 const ch_cnt_t _chnl );
306 template<WaveShape W>
307 void updateSync( SampleFrame* _ab, const f_cnt_t _frames,
308 const ch_cnt_t _chnl );
309 template<WaveShape W>
310 void updateFM( SampleFrame* _ab, const f_cnt_t _frames,
311 const ch_cnt_t _chnl );
312
313 template<WaveShape W>
314 inline sample_t getSample( const float _sample );
315
316 inline void recalcPhase();
317
318} ;
319
320
321} // namespace lmms
322
323#endif // LMMS_OSCILLATOR_H
assert(0)
static long waveform[8]
Definition adlibemu.c:197
Definition noise.cpp:45
static AudioEngine * audioEngine()
Definition Engine.h:59
Definition AutomatableModel.h:481
const float & m_ext_phaseOffset
Definition Oscillator.h:249
static fftwf_plan s_ifftPlan
Definition Oscillator.h:263
static constexpr auto NumWaveShapes
Definition Oscillator.h:63
bool m_useWaveTable
Definition Oscillator.h:255
std::shared_ptr< const OscillatorConstants::waveform_t > m_userAntiAliasWaveTable
Definition Oscillator.h:254
sample_t getSample(const float _sample)
const IntModel * m_waveShapeModel
Definition Oscillator.h:244
static constexpr auto NumModulationAlgos
Definition Oscillator.h:78
sample_t wtSample(const OscillatorConstants::waveform_t *table, const float sample) const
Definition Oscillator.h:207
static sample_t squareSample(const float _sample)
Definition Oscillator.h:138
static sample_t expSample(const float _sample)
Definition Oscillator.h:153
bool syncOk(float _osc_coeff)
Definition Oscillator.cpp:556
Oscillator * m_subOsc
Definition Oscillator.h:250
static sample_t userWaveSample(const SampleBuffer *buffer, const float sample)
Definition Oscillator.h:168
static constexpr auto NumWaveShapeTables
Number of band-limited wave shapes to be generated.
Definition Oscillator.h:67
static void generateSquareWaveTable(int bands, sample_t *table, int firstBand=1)
Definition Oscillator.cpp:155
static sample_t sawSample(const float _sample)
Definition Oscillator.h:133
void updateMix(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:433
static constexpr auto FirstWaveShapeTable
First wave shape that has a pre-generated table.
Definition Oscillator.h:65
void updatePM(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:361
static float freqFromWaveTableBand(int band)
Definition Oscillator.h:238
static void generateSawWaveTable(int bands, sample_t *table, int firstBand=1)
Definition Oscillator.cpp:119
static void generateFromFFT(int bands, sample_t *table)
Definition Oscillator.cpp:175
std::shared_ptr< const SampleBuffer > m_userWave
Definition Oscillator.h:253
static fftwf_plan s_fftPlan
Definition Oscillator.h:262
sample_t wtSample(const sample_t table[OscillatorConstants::WAVE_TABLES_PER_WAVEFORM_COUNT][OscillatorConstants::WAVETABLE_LENGTH], const float sample) const
Definition Oscillator.h:198
void recalcPhase()
Definition Oscillator.cpp:542
const float & m_volume
Definition Oscillator.h:248
static sample_t noiseSample(const float)
Definition Oscillator.h:163
void updateNoSub(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:325
void setUseWaveTable(bool n)
Definition Oscillator.h:96
const IntModel * m_modulationAlgoModel
Definition Oscillator.h:245
bool m_isModulator
Definition Oscillator.h:258
static sample_t triangleSample(const float _sample)
Definition Oscillator.h:119
void setUserWave(std::shared_ptr< const SampleBuffer > _wave)
Definition Oscillator.h:101
const float & m_freq
Definition Oscillator.h:246
void updateSync(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:469
virtual ~Oscillator()
Definition Oscillator.h:87
static void createFFTPlans()
Definition Oscillator.cpp:223
const float & m_detuning_div_samplerate
Definition Oscillator.h:247
wtSampleControl getWtSampleControl(const float sample) const
Definition Oscillator.h:185
float m_phaseOffset
Definition Oscillator.h:251
static sample_t s_waveTables[NumWaveShapeTables][OscillatorConstants::WAVE_TABLES_PER_WAVEFORM_COUNT][OscillatorConstants::WAVETABLE_LENGTH]
Definition Oscillator.h:261
static void generateTriangleWaveTable(int bands, sample_t *table, int firstBand=1)
Definition Oscillator.cpp:137
static sample_t sinSample(const float _sample)
Definition Oscillator.h:114
ModulationAlgo
Definition Oscillator.h:70
@ Count
Definition Oscillator.h:76
static fftwf_complex * s_specBuf
Definition Oscillator.h:264
float m_phase
Definition Oscillator.h:252
float syncInit(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:567
static void generateWaveTables()
Definition Oscillator.cpp:243
static std::array< float, OscillatorConstants::WAVETABLE_LENGTH > s_sampleBuffer
Definition Oscillator.h:265
WaveShape
Definition Oscillator.h:52
@ Triangle
Definition Oscillator.h:54
@ WhiteNoise
Definition Oscillator.h:59
@ Count
Number of all available wave shapes.
Definition Oscillator.h:61
void updateAM(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:397
void updateFM(SampleFrame *_ab, const f_cnt_t _frames, const ch_cnt_t _chnl)
Definition Oscillator.cpp:505
sample_t wtSample(sample_t **table, const float sample) const
Definition Oscillator.h:218
Oscillator(const IntModel *wave_shape_model, const IntModel *mod_algo_model, const float &freq, const float &detuning_div_samplerate, const float &phase_offset, const float &volume, Oscillator *m_subOsc=nullptr)
Definition Oscillator.cpp:55
static int waveTableBandFromFreq(float freq)
Definition Oscillator.h:225
void setUserAntiAliasWaveTable(std::shared_ptr< const OscillatorConstants::waveform_t > waveform)
Definition Oscillator.h:106
static sample_t moogSawSample(const float _sample)
Definition Oscillator.h:143
Definition SampleBuffer.h:39
static auto emptyBuffer() -> std::shared_ptr< const SampleBuffer >
Definition SampleBuffer.cpp:67
Definition SampleFrame.h:41
JHUFF_TBL long freq[]
Definition jchuff.h:50
float control
Definition lilv_test.c:1462
const int SEMITONES_PER_TABLE
Definition OscillatorConstants.h:45
constexpr int WAVETABLE_LENGTH
Definition OscillatorConstants.h:39
std::array< wavetable_t, WAVE_TABLES_PER_WAVEFORM_COUNT > waveform_t
Definition OscillatorConstants.h:54
const int WAVE_TABLES_PER_WAVEFORM_COUNT
Definition OscillatorConstants.h:46
Definition AudioAlsa.cpp:35
T fastRandInc(T upper) noexcept
Returns a pseudorandom number within [0, upper] (inclusive upper bound).
Definition lmms_math.h:126
std::uint16_t ch_cnt_t
Definition LmmsTypes.h:44
float sample_t
Definition LmmsTypes.h:39
auto absFraction(std::floating_point auto x) noexcept
Returns the wrapped fractional part of a float, a value between 0.0f and 1.0f.
Definition lmms_math.h:80
@ Sine
Definition Sfxr.h:43
@ Saw
Definition Sfxr.h:43
@ Square
Definition Sfxr.h:43
@ Count
Definition Sfxr.h:43
std::uint64_t f_cnt_t
Definition LmmsTypes.h:43
auto fraction(std::floating_point auto x) noexcept
Returns the fractional part of a float, a value between -1.0f and 1.0f.
Definition lmms_math.h:63
static float volume(float level)
Definition nekobee_voice_render.c:99
Definition Oscillator.h:178
f_cnt_t f1
Definition Oscillator.h:180
int band
Definition Oscillator.h:182
f_cnt_t f2
Definition Oscillator.h:181
float frame
Definition Oscillator.h:179
signed int sample
Definition tap_dynamics_m.c:41
int n
Definition crypt.c:458