Vital
Loading...
Searching...
No Matches
synth_oscillator.cpp
Go to the documentation of this file.
1#include "synth_oscillator.h"
2
3#include "fourier_transform.h"
4#include "futils.h"
5#include "matrix.h"
6#include "wavetable.h"
7
8#include <climits>
9
10namespace vital {
11 namespace {
12 // Internal constants and inline functions used for phase distortion, interpolation, etc.
13 constexpr int kNumVoicesPerProcess = poly_float::kSize / 2;
14 constexpr int kWaveformBits = WaveFrame::kWaveformBits;
15 constexpr int kIntermediateBits = 8 * sizeof(uint32_t) - kWaveformBits;
16 constexpr int kHalfPhase = INT_MIN;
17 constexpr unsigned long long kFullPhase = 1ULL + (unsigned long long)(UINT_MAX);
18 constexpr mono_float kPhaseMult = kFullPhase;
19 constexpr mono_float kInvPhaseMult = 1.0f / kFullPhase;
20 constexpr mono_float kIntermediateMult = 1 << kIntermediateBits;
21 const poly_int kIntermediateMask = (1 << kIntermediateBits) - 1;
22
23 constexpr mono_float kPhaseBits = (8 * sizeof(uint32_t));
24 constexpr mono_float kDistortBits = kPhaseBits;
25 constexpr mono_float kMaxQuantize = 0.85f;
26
27 constexpr mono_float kMaxSqueezePercent = 0.95f;
28 constexpr mono_float kMaxAmplitude = 2.0f;
29
30 constexpr mono_float kCenterLowAmplitude = 0.4f;
31 constexpr mono_float kDetunedHighAmplitude = 0.6f;
32 constexpr mono_float kWavetableFadeTime = 0.007f;
33
34 constexpr int kMaxSyncPower = 4;
35 constexpr int kMaxSync = 1 << kMaxSyncPower;
36
37 constexpr mono_float kFifthMult = 1.49830707688f;
38 constexpr mono_float kMajorThirdMult = 1.25992104989f;
39 constexpr mono_float kMinorThirdMult = 1.189207115f;
40 constexpr mono_float kNoMidiTrackDefault = 48.0f;
41
42 const poly_float kFmPhaseMult = kPhaseMult / 8.0f;
43 const poly_int kMaxFmModulation = 48;
44
45 force_inline poly_int passThroughPhase(poly_int phase, poly_float, poly_int, const poly_float*, int) {
46 return phase;
47 }
48
49 force_inline poly_int quantizePhase(poly_int phase, poly_float distortion, poly_int distortion_phase,
50 const poly_float*, int) {
51 poly_float normal_phase = utils::toFloat(phase) * distortion * kInvPhaseMult;
52 poly_float adjustment = utils::toFloat(distortion_phase) * kInvPhaseMult;
53 poly_float floored_phase = utils::trunc(normal_phase + adjustment) - adjustment;
54 return utils::toInt((floored_phase / distortion) * kPhaseMult) - distortion_phase;
55 }
56
57 force_inline poly_int bendPhase(poly_int phase, poly_float distortion, poly_int distortion_phase,
58 const poly_float*, int) {
59 poly_float float_phase = utils::toFloat(phase - distortion_phase) * (1.0f / kPhaseMult) + 0.5f;
60
61 poly_float distortion_offset = (distortion - distortion * distortion) * 2.0f;
62 poly_float float_phase2 = float_phase * float_phase;
63 poly_float float_phase3 = float_phase * float_phase2;
64
65 poly_float distortion_scale = distortion * 3.0f;
66 poly_float middle_mult1 = distortion_scale + distortion_offset;
67 poly_float middle_mult2 = distortion_scale - distortion_offset;
68 poly_float middle1 = middle_mult1 * (float_phase2 - float_phase3);
69 poly_float middle2 = middle_mult2 * (float_phase - float_phase2 * 2.0f + float_phase3);
70 poly_float new_phase = float_phase3 + middle1 + middle2;
71 return utils::toInt((new_phase - 0.5f) * kPhaseMult);
72 }
73
74 force_inline poly_int squeezePhase(poly_int phase, poly_float distortion, poly_int distortion_phase,
75 const poly_float*, int) {
76 static const poly_float kCenterPhase = kPhaseMult / 4.0f;
77 static const poly_float kMaxPhase = kPhaseMult / 2.0f;
78 poly_float float_phase = utils::toFloat(phase - distortion_phase);
79 poly_mask positive_mask = poly_float::greaterThan(float_phase, 0.0f);
80 float_phase = poly_float::abs(float_phase);
81
82 poly_float pivot = distortion * kCenterPhase;
83 poly_mask right_half_mask = poly_float::greaterThan(float_phase, pivot);
84
85 poly_float left_phase = float_phase / distortion;
86 poly_float right_phase = kMaxPhase - (kMaxPhase - float_phase) / (poly_float(2.0f) - distortion);
87 poly_float new_phase = utils::maskLoad(left_phase, right_phase, right_half_mask);
88 new_phase = utils::maskLoad(-new_phase, new_phase, positive_mask);
89 return utils::toInt(new_phase);
90 }
91
92 force_inline poly_int syncPhase(poly_int phase, poly_float distortion, poly_int, const poly_float*, int) {
93 poly_float float_val = utils::toFloat(phase + kHalfPhase) * distortion;
94 return utils::toInt(float_val) * kMaxSync + kHalfPhase;
95 }
96
97 force_inline poly_int pulseWidthPhase(poly_int phase, poly_float distortion, poly_int distortion_phase,
98 const poly_float*, int) {
99 poly_float distorted_phase = utils::toFloat(phase) * distortion;
100 poly_float clamped_phase = utils::clamp(distorted_phase, INT_MIN, INT_MAX);
101 return utils::toInt(clamped_phase);
102 }
103
104 force_inline poly_int fmPhase(poly_int phase, poly_float distortion, poly_int,
105 const poly_float* modulation, int i) {
106 poly_float phase_offset = modulation[i] * distortion;
107 return phase + utils::toInt(phase_offset * kFmPhaseMult) * kMaxFmModulation;
108 }
109
110 force_inline poly_int fmPhaseLeft(poly_int phase, poly_float distortion, poly_int,
111 const poly_float* modulation, int i) {
112 poly_float mod = modulation[i] & constants::kFirstMask;
113 mod += utils::swapVoices(mod);
114 poly_float phase_offset = mod * distortion;
115 return phase + utils::toInt(phase_offset * kFmPhaseMult) * kMaxFmModulation;
116 }
117
118 force_inline poly_int fmPhaseRight(poly_int phase, poly_float distortion, poly_int,
119 const poly_float* modulation, int i) {
120 poly_float mod = modulation[i] & constants::kSecondMask;
121 mod += utils::swapVoices(mod);
122 poly_float phase_offset = mod * distortion;
123 return phase + utils::toInt(phase_offset * kFmPhaseMult) * kMaxFmModulation;
124 }
125
126 force_inline poly_float passThroughWindow(poly_int, poly_int, poly_float, const poly_float*, int) {
127 return 1.0f;
128 }
129
130 force_inline poly_float pulseWidthWindow(poly_int, poly_int distorted_phase, poly_float, const poly_float*, int) {
131 return poly_float(1.0f) & ~poly_int::equal(distorted_phase, INT_MIN);
132 }
133
134 force_inline poly_float halfSinWindow(poly_int phase, poly_int, poly_float, const poly_float*, int) {
135 poly_float normal_phase = utils::toFloat(phase + INT_MAX) * (kInvPhaseMult / 2.0f);
136 return futils::sin(normal_phase + 0.25f);
137 }
138
139 force_inline poly_float rmWindow(poly_int, poly_int, poly_float distortion, const poly_float* modulation, int i) {
140 return utils::interpolate(1.0f, modulation[i], distortion);
141 }
142
143 force_inline poly_float rmWindowLeft(poly_int, poly_int, poly_float distortion,
144 const poly_float* modulation, int i) {
145 poly_float mod = modulation[i] & constants::kFirstMask;
146 mod += utils::swapVoices(mod);
147 return utils::interpolate(1.0f, mod, distortion);
148 }
149
150 force_inline poly_float rmWindowRight(poly_int, poly_int, poly_float distortion,
151 const poly_float* modulation, int i) {
152 poly_float mod = modulation[i] & constants::kSecondMask;
153 mod += utils::swapVoices(mod);
154 return utils::interpolate(1.0f, mod, distortion);
155 }
156
157 force_inline poly_float noTransposeSnap(poly_float midi, poly_float transpose, float*) {
158 return midi + transpose;
159 }
160
161 force_inline poly_float localTransposeSnap(poly_float midi, poly_float transpose, float* snap_buffer) {
162 static constexpr float kScaleDown = 1.0f / kNotesPerOctave;
163 static constexpr float kScaleUp = kNotesPerOctave;
164
165 poly_float note_offset = utils::mod(transpose * kScaleDown) * kScaleUp;
166 poly_float octave_snap = transpose - note_offset;
167 poly_int int_snap = utils::roundToInt(note_offset);
168 poly_float result;
169 for (int i = 0; i < poly_float::kSize; ++i)
170 result.set(i, snap_buffer[int_snap[i]]);
171
172 return midi + octave_snap + result;
173 }
174
175 force_inline poly_float globalTransposeSnap(poly_float midi, poly_float transpose, float* snap_buffer) {
176 static constexpr float kScaleDown = 1.0f / kNotesPerOctave;
177 static constexpr float kScaleUp = kNotesPerOctave;
178
179 poly_float total = midi + transpose;
180 poly_float note_offset = utils::mod(total * kScaleDown) * kScaleUp;
181 poly_float octave_snap = total - note_offset;
182 poly_int int_snap = utils::roundToInt(note_offset);
183 poly_float result;
184 for (int i = 0; i < poly_float::kSize; ++i)
185 result.set(i, snap_buffer[int_snap[i]]);
186
187 return octave_snap + result;
188 }
189
190 force_inline poly_float getInterpolationValues(poly_int indices) {
191 return utils::toFloat(indices & kIntermediateMask) * (1.0f / kIntermediateMult);
192 }
193
194 force_inline poly_float linearlyInterpolateBuffer(const mono_float* buffer, const poly_int indices) {
195 poly_int start_indices = utils::shiftRight<kIntermediateBits>(indices);
196 poly_float t = getInterpolationValues(indices);
197 matrix interpolation_matrix = utils::getLinearInterpolationMatrix(t);
198 matrix value_matrix = utils::getValueMatrix(buffer, start_indices);
199 value_matrix.transpose();
200 return interpolation_matrix.multiplyAndSumRows(value_matrix);
201 }
202
203 force_inline poly_float interpolateBuffers(const mono_float* const* buffers, const poly_int indices) {
204 poly_int start_indices = utils::shiftRight<kIntermediateBits>(indices);
205 poly_float t = getInterpolationValues(indices);
206 matrix interpolation_matrix = utils::getCatmullInterpolationMatrix(t);
207 matrix value_matrix = utils::getValueMatrix(buffers, start_indices);
208 value_matrix.transpose();
209 return interpolation_matrix.multiplyAndSumRows(value_matrix);
210 }
211
212 force_inline poly_float interpolateBuffers(const mono_float* const* buffers,
213 const mono_float* const*,
214 const poly_int indices, poly_float) {
215 return interpolateBuffers(buffers, indices);
216 }
217
218 force_inline poly_float interpolateMultipleBuffers(const mono_float* const* buffers_from,
219 const mono_float* const* buffers_to,
220 const poly_int indices, poly_float buffer_t) {
221 poly_int start_indices = utils::shiftRight<kIntermediateBits>(indices);
222 poly_float t = getInterpolationValues(indices);
223 matrix interpolation_matrix = utils::getCatmullInterpolationMatrix(t);
224 matrix value_matrix = utils::getValueMatrix(buffers_from, start_indices);
225 value_matrix.interpolateRows(utils::getValueMatrix(buffers_to, start_indices), buffer_t);
226 value_matrix.transpose();
227 return interpolation_matrix.multiplyAndSumRows(value_matrix);
228 }
229
230 force_inline poly_float interpolateShepardBuffers(const mono_float* const* buffers_from,
231 const mono_float* const* buffers_to,
232 const poly_int indices, poly_float buffer_t,
233 poly_mask double_mask, poly_mask half_mask) {
234 poly_int adjusted_indices = utils::maskLoad(indices, indices * 2, double_mask);
235 adjusted_indices = utils::maskLoad(adjusted_indices, utils::shiftRight<1>(adjusted_indices), half_mask);
236 poly_float from = interpolateBuffers(buffers_from, adjusted_indices);
237 poly_float to = interpolateBuffers(buffers_to, indices);
238 return utils::interpolate(from, to, buffer_t);
239 }
240
241 poly_int processDetunedShepard(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out) {
242 const mono_float* const* from_buffers = voice_block.from_buffers;
243 const mono_float* const* to_buffers = voice_block.to_buffers;
244
245 int start = voice_block.start_sample;
246 poly_float t_inc = 1.0f / voice_block.num_buffer_samples;
247 poly_float t = utils::toFloat(voice_block.current_buffer_sample + 1) * t_inc;
248 mono_float sample_inc = (1.0f / voice_block.total_samples);
249
250 poly_int phase = voice_block.phase;
251 poly_float current_phase_inc_mult = voice_block.from_phase_inc_mult;
252 poly_float end_phase_inc_mult = voice_block.phase_inc_mult;
253 poly_float delta_phase_inc_mult = (end_phase_inc_mult - current_phase_inc_mult) * sample_inc;
254 current_phase_inc_mult += delta_phase_inc_mult * start;
255
256 poly_mask double_mask = voice_block.shepard_double_mask;
257 poly_mask half_mask = voice_block.shepard_half_mask;
258
259 const poly_float* phase_inc_buffer = voice_block.phase_inc_buffer + start;
260 const poly_int* phase_buffer = voice_block.phase_buffer + start;
261 int num_samples = voice_block.end_sample - start;
262 for (int i = 0; i < num_samples; ++i) {
263 current_phase_inc_mult += delta_phase_inc_mult;
264 phase += utils::toInt(phase_inc_buffer[i] * current_phase_inc_mult);
265 poly_int adjusted_phase = phase + phase_buffer[i];
266 audio_out[i] += interpolateShepardBuffers(from_buffers, to_buffers, adjusted_phase, t, double_mask, half_mask);
267 t += t_inc;
268 }
269
270 return phase;
271 }
272
273 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
274 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int),
275 poly_float(*interpolate)(const mono_float* const*, const mono_float* const*,
276 const poly_int, poly_float)>
277 poly_int processDetuned(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out) {
278 const mono_float* const* from_buffers = voice_block.from_buffers;
279 const mono_float* const* to_buffers = voice_block.to_buffers;
280
281 int start = voice_block.start_sample;
282 poly_float t_inc = 1.0f / voice_block.num_buffer_samples;
283 poly_float t = utils::toFloat(voice_block.current_buffer_sample + 1) * t_inc;
284 mono_float sample_inc = (1.0f / voice_block.total_samples);
285
286 poly_int phase = voice_block.phase;
287 poly_float current_phase_inc_mult = voice_block.from_phase_inc_mult;
288 poly_float end_phase_inc_mult = voice_block.phase_inc_mult;
289 poly_float delta_phase_inc_mult = (end_phase_inc_mult - current_phase_inc_mult) * sample_inc;
290 current_phase_inc_mult += delta_phase_inc_mult * start;
291
292 poly_int current_dist_phase = voice_block.last_distortion_phase;
293 poly_int end_dist_phase = voice_block.distortion_phase;
294 poly_int delta_dist_phase = utils::toInt(utils::toFloat(end_dist_phase - current_dist_phase) * sample_inc);
295 current_dist_phase += delta_dist_phase * start;
296
297 poly_float current_distortion = voice_block.last_distortion;
298 poly_float distortion_inc = (voice_block.distortion - current_distortion) * sample_inc;
299 current_distortion += distortion_inc * start;
300
301 const poly_float* modulation_buffer = voice_block.modulation_buffer + start;
302 const poly_float* phase_inc_buffer = voice_block.phase_inc_buffer + start;
303 const poly_int* phase_buffer = voice_block.phase_buffer + start;
304 int num_samples = voice_block.end_sample - start;
305 for (int i = 0; i < num_samples; ++i) {
306 current_phase_inc_mult += delta_phase_inc_mult;
307 phase += utils::toInt(phase_inc_buffer[i] * current_phase_inc_mult);
308 poly_int adjusted_phase = phase + phase_buffer[i];
309 current_distortion += distortion_inc;
310 current_dist_phase += delta_dist_phase;
311 poly_int distorted_phase = phaseDistort(adjusted_phase, current_distortion,
312 current_dist_phase, modulation_buffer, i);
313 poly_float result = interpolate(from_buffers, to_buffers, distorted_phase + current_dist_phase, t);
314 audio_out[i] += window(adjusted_phase, distorted_phase, current_distortion, modulation_buffer, i) * result;
315 t += t_inc;
316 }
317
318 return phase;
319 }
320
321 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
322 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int)>
323 force_inline poly_int processDetuned(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out) {
324 if (voice_block.isStatic())
325 return processDetuned<phaseDistort, window, interpolateBuffers>(voice_block, audio_out);
326 if (voice_block.shepard_double_mask.anyMask() || voice_block.shepard_half_mask.anyMask())
327 return processDetunedShepard(voice_block, audio_out);
328 return processDetuned<phaseDistort, window, interpolateMultipleBuffers>(voice_block, audio_out);
329 }
330
331 poly_int processCenterShepard(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out,
332 poly_float current_center_amplitude, poly_float delta_center_amplitude,
333 poly_float current_detuned_amplitude, poly_float delta_detuned_amplitude) {
334 const mono_float* const* from_buffers = voice_block.from_buffers;
335 const mono_float* const* to_buffers = voice_block.to_buffers;
336
337 int start = voice_block.start_sample;
338
339 poly_float t_inc = 1.0f / voice_block.num_buffer_samples;
340 poly_float t = utils::toFloat(voice_block.current_buffer_sample + 1) * t_inc;
341 mono_float sample_inc = (1.0f / voice_block.total_samples);
342
343 poly_int phase = voice_block.phase;
344 poly_float current_phase_inc_mult = voice_block.from_phase_inc_mult;
345 poly_float end_phase_inc_mult = voice_block.phase_inc_mult;
346 poly_float delta_phase_inc_mult = (end_phase_inc_mult - current_phase_inc_mult) * sample_inc;
347 current_phase_inc_mult += delta_phase_inc_mult * start;
348
349 poly_mask double_mask = voice_block.shepard_double_mask;
350 poly_mask half_mask = voice_block.shepard_half_mask;
351
352 const poly_float* phase_inc_buffer = voice_block.phase_inc_buffer + start;
353 const poly_int* phase_buffer = voice_block.phase_buffer + start;
354 int num_samples = voice_block.end_sample - start;
355 for (int i = 0; i < num_samples; ++i) {
356 current_phase_inc_mult += delta_phase_inc_mult;
357 phase += utils::toInt(phase_inc_buffer[i] * current_phase_inc_mult);
358 poly_int adjusted_phase = phase + phase_buffer[i];
359
360 current_center_amplitude += delta_center_amplitude;
361 current_detuned_amplitude += delta_detuned_amplitude;
362 poly_float read = interpolateShepardBuffers(from_buffers, to_buffers, adjusted_phase,
363 t, double_mask, half_mask);
364 audio_out[i] = current_center_amplitude * read + current_detuned_amplitude * audio_out[i];
365 t += t_inc;
366 }
367
368 return phase;
369 }
370
371 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
372 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int),
373 poly_float(*interpolate)(const mono_float* const*, const mono_float* const*,
374 const poly_int, poly_float)>
375 poly_int processCenter(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out,
376 poly_float current_center_amplitude, poly_float delta_center_amplitude,
377 poly_float current_detuned_amplitude, poly_float delta_detuned_amplitude) {
378 const mono_float* const* from_buffers = voice_block.from_buffers;
379 const mono_float* const* to_buffers = voice_block.to_buffers;
380
381 int start = voice_block.start_sample;
382
383 poly_float t_inc = 1.0f / voice_block.num_buffer_samples;
384 poly_float t = utils::toFloat(voice_block.current_buffer_sample + 1) * t_inc;
385 mono_float sample_inc = (1.0f / voice_block.total_samples);
386
387 poly_int phase = voice_block.phase;
388 poly_float current_phase_inc_mult = voice_block.from_phase_inc_mult;
389 poly_float end_phase_inc_mult = voice_block.phase_inc_mult;
390 poly_float delta_phase_inc_mult = (end_phase_inc_mult - current_phase_inc_mult) * sample_inc;
391 current_phase_inc_mult += delta_phase_inc_mult * start;
392
393 poly_int current_dist_phase = voice_block.last_distortion_phase;
394 poly_int end_dist_phase = voice_block.distortion_phase;
395 poly_int delta_dist_phase = utils::toInt(utils::toFloat(end_dist_phase - current_dist_phase) * sample_inc);
396 current_dist_phase += delta_dist_phase * start;
397
398 poly_float current_distortion = voice_block.last_distortion;
399 poly_float distortion_inc = (voice_block.distortion - current_distortion) * sample_inc;
400 current_distortion += distortion_inc * start;
401
402 const poly_float* modulation_buffer = voice_block.modulation_buffer + start;
403 const poly_float* phase_inc_buffer = voice_block.phase_inc_buffer + start;
404 const poly_int* phase_buffer = voice_block.phase_buffer + start;
405 int num_samples = voice_block.end_sample - start;
406 for (int i = 0; i < num_samples; ++i) {
407 current_phase_inc_mult += delta_phase_inc_mult;
408 phase += utils::toInt(phase_inc_buffer[i] * current_phase_inc_mult);
409 poly_int adjusted_phase = phase + phase_buffer[i];
410 current_distortion += distortion_inc;
411 current_dist_phase += delta_dist_phase;
412 current_center_amplitude += delta_center_amplitude;
413 current_detuned_amplitude += delta_detuned_amplitude;
414 poly_int distorted_phase = phaseDistort(adjusted_phase, current_distortion,
415 current_dist_phase, modulation_buffer, i);
416 poly_float mult = window(adjusted_phase, distorted_phase, current_distortion, modulation_buffer, i);
417 poly_float read = mult * interpolate(from_buffers, to_buffers, distorted_phase + current_dist_phase, t);
418 poly_float center_value = current_center_amplitude * read;
419 audio_out[i] = center_value + current_detuned_amplitude * audio_out[i];
420 VITAL_ASSERT(utils::isFinite(audio_out[i]));
421
422 t += t_inc;
423 }
424
425 return phase;
426 }
427
428 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
429 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int)>
430 force_inline poly_int processCenter(const SynthOscillator::VoiceBlock& voice_block, poly_float* audio_out,
431 poly_float current_center_amplitude, poly_float delta_center_amplitude,
432 poly_float current_detuned_amplitude, poly_float delta_detuned_amplitude) {
433 if (voice_block.isStatic()) {
434 return processCenter<phaseDistort, window, interpolateBuffers>(
435 voice_block, audio_out,
436 current_center_amplitude, delta_center_amplitude,
437 current_detuned_amplitude, delta_detuned_amplitude);
438 }
439 if (voice_block.shepard_double_mask.anyMask() || voice_block.shepard_half_mask.anyMask()) {
440 return processCenterShepard(
441 voice_block, audio_out,
442 current_center_amplitude, delta_center_amplitude,
443 current_detuned_amplitude, delta_detuned_amplitude);
444 }
445 return processCenter<phaseDistort, window, interpolateMultipleBuffers>(
446 voice_block, audio_out,
447 current_center_amplitude, delta_center_amplitude,
448 current_detuned_amplitude, delta_detuned_amplitude);
449 }
450
451 template<class T>
452 force_inline T compactAndLoadVoice(T* values, poly_mask active_mask) {
453 T one = values[0];
454 T two = utils::swapVoices(values[1]);
455 return utils::maskLoad(two, one, active_mask);
456 }
457
458 template<class T>
459 force_inline void expandAndWriteVoice(T* values, T value, poly_mask active_mask) {
460 T two = utils::swapVoices(value);
461 values[0] = utils::maskLoad(values[0], value, active_mask);
462 values[1] = utils::maskLoad(values[1], two, active_mask);
463 }
464
465 force_inline void compactAndLoadVoice(const mono_float** dest, const mono_float* const* values,
466 poly_mask active_mask) {
467 const mono_float* const* position1 = values;
468 const mono_float* const* position2 = values + poly_float::kSize;
469 int index = active_mask[0] ? 0 : 2;
470 dest[index] = position1[index];
471 dest[index + 1] = position1[index + 1];
472 dest[(index + 2) % poly_float::kSize] = position2[index];
473 dest[(index + 3) % poly_float::kSize] = position2[index + 1];
474 }
475
476 void setPowerDistortionValues(poly_float* values, int num_values, float exponent, bool spread) {
477 if (spread) {
478 for (int i = 0; i < num_values; ++i)
479 values[i] = futils::pow(2.0f, (values[i] - 0.5f) * 2.0f * exponent);
480 }
481 else {
482 poly_float value = futils::pow(2.0f, (values[0] - 0.5f) * 2.0f * exponent);
483 for (int i = 0; i < num_values; ++i)
484 values[i] = value;
485 }
486 }
487 }
488
489 // Static stack multipliers for unison modes defined here.
490 const mono_float SynthOscillator::kStackMultipliers[kNumUnisonStackTypes][kNumPolyPhase] = {
491 { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
492 { 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
493 { 0.25f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
494 { 1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f },
495 { 1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f, 1.0f, 2.0f },
496 { 1.0f, kFifthMult, 2.0f, 1.0f, kFifthMult, 2.0f, 1.0f, kFifthMult },
497 { 1.0f, kFifthMult, 2.0f, 2.0f * kFifthMult, 4.0f, 1.0f, kFifthMult, 2.0f },
498 { 1.0f, kMajorThirdMult, kFifthMult, 2.0f, 1.0f, kMajorThirdMult, kFifthMult, 2.0f },
499 { 1.0f, kMinorThirdMult, kFifthMult, 2.0f, 1.0f, kMinorThirdMult, kFifthMult, 2.0f },
500 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
501 { 1.0f, 3.0f, 5.0f, 7.0f, 9.0f, 11.0f, 13.0f, 15.0f }
502 };
503
504 SynthOscillator::VoiceBlock::VoiceBlock() : start_sample(0), end_sample(0), total_samples(0),
505 phase(0), phase_inc_mult(0.0f), from_phase_inc_mult(0.0f),
506 shepard_double_mask(0), shepard_half_mask(0),
507 distortion_phase(0), last_distortion_phase(0),
508 distortion(0.0f), last_distortion(0.0f),
509 num_buffer_samples(0), current_buffer_sample(0),
510 smoothing_enabled(false), spectral_morph(kNoSpectralMorph),
511 modulation_buffer(nullptr) {
512 const mono_float* default_buffer = Wavetable::null_waveform();
513 for (int i = 0; i < poly_int::kSize; ++i) {
514 from_buffers[i] = default_buffer;
515 to_buffers[i] = default_buffer;
516 }
517 }
518
520 Processor(kNumInputs, kNumOutputs), random_generator_(-1.0f, 1.0f),
521 transpose_quantize_(0), last_quantized_transpose_(0.0f), last_quantize_ratio_(1.0f),
522 unison_(1), active_oscillators_(2), wavetable_(wavetable), wavetable_version_(wavetable->getVersion()),
523 first_mod_oscillator_(nullptr), second_mod_oscillator_(nullptr), sample_(nullptr),
524 fourier_frames1_(), fourier_frames2_() {
525 // Initialization of oscillator states and buffers.
526 pan_amplitude_ = 0.0f;
527 center_amplitude_ = 0.0f;
528 detuned_amplitude_ = 0.0f;
529 distortion_phase_ = 0.0f;
530 blend_stereo_multiply_ = 0.0f;
531 blend_center_multiply_ = 0.0f;
532
533 for (int i = 0; i < kNumPolyPhase; ++i) {
534 phases_[i] = 0;
535 phase_inc_mults_[i] = 1.0f;
536 from_phase_inc_mults_[i] = 1.0f;
537 shepard_double_masks_[i] = 0;
538 shepard_half_masks_[i] = 0;
539 waiting_shepard_double_masks_[i] = 0;
540 waiting_shepard_half_masks_[i] = 0;
541 detunings_[i] = 1.0f;
542 spectral_morph_values_[i] = 0.0f;
543 last_spectral_morph_values_[i] = 1.0f;
544 distortion_values_[i] = 0.0f;
545 last_distortion_values_[i] = 0.0f;
546 }
547
548 resetWavetableBuffers();
549
550 fourier_transform_ = std::make_shared<FourierTransform>(kWaveformBits);
551 phase_inc_buffer_ = std::make_shared<Output>();
552 phase_buffer_ = std::make_shared<PhaseBuffer>();
553 voice_block_.phase_inc_buffer = phase_inc_buffer_->buffer;
554 voice_block_.phase_buffer = phase_buffer_->buffer;
556 }
557
558 void SynthOscillator::reset(poly_mask reset_mask, poly_int sample) {
559 // Resets oscillator states taking into account partial buffer processing.
560 reset(reset_mask);
561 voice_block_.current_buffer_sample = utils::maskLoad(voice_block_.current_buffer_sample, -sample, reset_mask);
562 }
563
565 // Simple version of reset that doesn't consider sample offsets.x
566 poly_float random_amount = input(kRandomPhase)->at(0);
567 last_quantize_ratio_ = utils::maskLoad(last_quantize_ratio_, 1.0f, reset_mask);
568
569 for (int v = 0; v < kNumVoicesPerProcess; ++v) {
570 if (reset_mask[v * 2]) {
571 for (int i = 0; i < kNumPolyPhase; ++i) {
572 uint32_t random_phase_left = random_generator_.next() * random_amount[2 * v] * INT_MAX;
573 uint32_t random_phase_right = random_generator_.next() * random_amount[2 * v + 1] * INT_MAX;
574 phases_[i].set(2 * v, random_phase_left);
575 phases_[i].set(2 * v + 1, random_phase_right);
576
577 int buffer_index = i * poly_float::kSize + 2 * v;
578 last_buffers_[buffer_index] = wave_buffers_[buffer_index];
579 last_buffers_[buffer_index + 1] = wave_buffers_[buffer_index + 1];
580 }
581
582 if (unison_ < active_oscillators_)
583 phases_[0].set(v * 2, phases_[0][v * 2 + 1]);
584 }
585 }
586
587 for (int i = 0; i < kNumPolyPhase; ++i) {
588 last_distortion_values_[i] = utils::maskLoad(last_distortion_values_[i], distortion_values_[i], reset_mask);
589 last_spectral_morph_values_[i] = utils::maskLoad(last_spectral_morph_values_[i],
590 spectral_morph_values_[i], reset_mask);
591 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i], phase_inc_mults_[i], reset_mask);
592 shepard_double_masks_[i] = shepard_double_masks_[i] & ~reset_mask;
593 shepard_half_masks_[i] = shepard_half_masks_[i] & ~reset_mask;
594 waiting_shepard_double_masks_[i] = waiting_shepard_double_masks_[i] & ~reset_mask;
595 waiting_shepard_half_masks_[i] = waiting_shepard_half_masks_[i] & ~reset_mask;
596 }
597 }
598
599 void SynthOscillator::setPhaseIncMults() {
600 poly_float range = input(kDetuneRange)->at(0);
601 poly_float cents = range * input(kUnisonDetune)->at(0);
602 poly_float power = input(kDetunePower)->at(0);
603 int stack_style = std::roundf(input(kStackStyle)->at(0)[0]);
604 const mono_float* stack_settings = kStackMultipliers[stack_style];
605
606 mono_float divisor = utils::max(1.0f, unison_ - 1.0f);
607 int bump = (unison_ % 2 == 0) ? 1 : 0;
608
609 poly_mask sharp_flat_mask = constants::kLeftMask;
610 int num_updates = active_oscillators_ / 2;
611 for (int i = 0; i < num_updates; ++i) {
612 mono_float t = (2 * i + bump) / divisor;
613 poly_float adjusted_t = futils::powerScale(t, power);
614 poly_float oscillator_cents = adjusted_t * cents;
615
616 poly_float up_ratio = utils::centsToRatio(oscillator_cents);
617 poly_float down_ratio = poly_float(1.0f) / up_ratio;
618 detunings_[i] = utils::maskLoad(up_ratio, down_ratio, sharp_flat_mask) * stack_settings[i];
619 from_phase_inc_mults_[i] = phase_inc_mults_[i];
620 phase_inc_mults_[i] = detunings_[i];
621
622 sharp_flat_mask = ~sharp_flat_mask;
623 }
624 }
625
626 force_inline void SynthOscillator::setupShepardWrap() {
627 int num_phase_updates = active_oscillators_ / 2;
628
629 poly_float ratio_div = poly_float(1.0f) / last_quantize_ratio_;
630 for (int i = 0; i < num_phase_updates; ++i) {
631 poly_float spectral_diff = last_spectral_morph_values_[i] - spectral_morph_values_[i];
632 poly_float mult = futils::exp2(-spectral_morph_values_[i]);
633 phase_inc_mults_[i] *= mult;
634 detunings_[i] *= mult;
635
636 poly_mask double_mask = waiting_shepard_double_masks_[i] | poly_float::lessThan(spectral_diff, -0.6f);
637 poly_mask half_mask = waiting_shepard_half_masks_[i] | poly_float::greaterThan(spectral_diff, 0.6f);
638
639 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 2.0f, double_mask);
640 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 0.5f, half_mask);
641 poly_float reset_phase_inc_mult = from_phase_inc_mults_[i] * ratio_div;
642 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i], reset_phase_inc_mult,
643 half_mask | double_mask);
644
645 waiting_shepard_double_masks_[i] = double_mask;
646 waiting_shepard_half_masks_[i] = half_mask;
647 }
648 }
649
650 force_inline void SynthOscillator::clearShepardWrap() {
651 int num_phase_updates = active_oscillators_ / 2;
652
653 for (int i = 0; i < num_phase_updates; ++i) {
654 shepard_double_masks_[i] = 0;
655 shepard_half_masks_[i] = 0;
656 waiting_shepard_double_masks_[i] = 0;
657 waiting_shepard_half_masks_[i] = 0;
658 }
659 }
660
661 force_inline void SynthOscillator::doShepardWrap(poly_mask new_buffer_mask, int quantize) {
662 int num_phase_updates = active_oscillators_ / 2;
663
664 if (quantize) {
665 for (int i = 0; i < num_phase_updates; ++i) {
666 poly_mask double_mask = waiting_shepard_double_masks_[i] & new_buffer_mask;
667 poly_mask half_mask = waiting_shepard_half_masks_[i] & new_buffer_mask;
668 waiting_shepard_double_masks_[i] = waiting_shepard_double_masks_[i] & ~new_buffer_mask;
669 waiting_shepard_half_masks_[i] = waiting_shepard_half_masks_[i] & ~new_buffer_mask;
670
671 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 0.5f, double_mask);
672 phases_[i] = utils::maskLoad(phases_[i], utils::shiftRight<1>(phases_[i]), double_mask);
673
674 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 2.0f, half_mask);
675 phases_[i] = utils::maskLoad(phases_[i], phases_[i] * 2, half_mask);
676 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i], phase_inc_mults_[i],
677 double_mask | half_mask);
678
679 shepard_double_masks_[i] = utils::maskLoad(shepard_double_masks_[i], double_mask, new_buffer_mask);
680 shepard_half_masks_[i] = utils::maskLoad(shepard_half_masks_[i], half_mask, new_buffer_mask);
681 }
682 }
683 else {
684 for (int i = 0; i < num_phase_updates; ++i) {
685 poly_mask double_mask = waiting_shepard_double_masks_[i] & new_buffer_mask;
686 poly_mask half_mask = waiting_shepard_half_masks_[i] & new_buffer_mask;
687 waiting_shepard_double_masks_[i] = waiting_shepard_double_masks_[i] & ~new_buffer_mask;
688 waiting_shepard_half_masks_[i] = waiting_shepard_half_masks_[i] & ~new_buffer_mask;
689
690 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 0.5f, double_mask);
691 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i],
692 from_phase_inc_mults_[i] * 0.5f, double_mask);
693 phases_[i] = utils::maskLoad(phases_[i], utils::shiftRight<1>(phases_[i]), double_mask);
694
695 phase_inc_mults_[i] = utils::maskLoad(phase_inc_mults_[i], phase_inc_mults_[i] * 2.0f, half_mask);
696 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i], from_phase_inc_mults_[i] * 2, half_mask);
697 phases_[i] = utils::maskLoad(phases_[i], phases_[i] * 2.0f, half_mask);
698
699 shepard_double_masks_[i] = utils::maskLoad(shepard_double_masks_[i], double_mask, new_buffer_mask);
700 shepard_half_masks_[i] = utils::maskLoad(shepard_half_masks_[i], half_mask, new_buffer_mask);
701 }
702 }
703 }
704
705 force_inline void SynthOscillator::setAmplitude() {
706 if (unison_ <= 2) {
707 center_amplitude_ = 1.0f;
708 detuned_amplitude_ = 0.0f;
709 return;
710 }
711
712 poly_float blend = input(kBlend)->at(0);
713 poly_float center = utils::interpolate(1.0f, kCenterLowAmplitude, blend);
714 poly_float detuned_blend = -blend + 1.0f;
715 detuned_blend *= detuned_blend;
716 poly_float detuned = utils::interpolate(kDetunedHighAmplitude, 0.0f, detuned_blend);
717
718 int half_oscillators = active_oscillators_ / 2;
719 poly_float square_sums = center * center + detuned * detuned * (half_oscillators - 1);
720 poly_float adjustment = poly_float(1.0f) / utils::sqrt(square_sums);
721 center_amplitude_ = adjustment * center;
722 detuned_amplitude_ = adjustment * detuned;
723 }
724
725 void SynthOscillator::setWaveBuffers(poly_float phase_inc, int index) {
726 if (voice_block_.spectral_morph == kShepardTone)
727 setFourierWaveBuffers<shepardMorph>(phase_inc, index, false);
728 else if (voice_block_.spectral_morph == kVocode)
729 setFourierWaveBuffers<evenOddVocodeMorph>(phase_inc, index, true);
730 else if (voice_block_.spectral_morph == kFormScale)
731 setFourierWaveBuffers<evenOddVocodeMorph>(phase_inc, index, false);
732 else if (voice_block_.spectral_morph == kHarmonicScale)
733 setFourierWaveBuffers<harmonicScaleMorph>(phase_inc, index, false);
734 else if (voice_block_.spectral_morph == kInharmonicScale)
735 setFourierWaveBuffers<inharmonicScaleMorph>(phase_inc, index, false);
736 else if (voice_block_.spectral_morph == kSmear)
737 setFourierWaveBuffers<smearMorph>(phase_inc, index, false);
738 else if (voice_block_.spectral_morph == kRandomAmplitudes)
739 setFourierWaveBuffers<randomAmplitudeMorph>(phase_inc, index, false);
740 else if (voice_block_.spectral_morph == kLowPass)
741 setFourierWaveBuffers<lowPassMorph>(phase_inc, index, false);
742 else if (voice_block_.spectral_morph == kHighPass)
743 setFourierWaveBuffers<highPassMorph>(phase_inc, index, false);
744 else if (voice_block_.spectral_morph == kPhaseDisperse)
745 setFourierWaveBuffers<phaseMorph>(phase_inc, index, false);
746 else if (voice_block_.spectral_morph == kSkew)
747 setFourierWaveBuffers<wavetableSkewMorph>(phase_inc, index, false);
748 else
749 setFourierWaveBuffers<passthroughMorph>(phase_inc, index, false);
750
751 voice_block_.current_buffer_sample.set(index, 0);
752 voice_block_.current_buffer_sample.set(index + 1, 0);
753 }
754
755 template<void(*spectralMorph)(const Wavetable::WavetableData*, int, poly_float*,
756 FourierTransform*, float, int, const poly_float*)>
757 void SynthOscillator::computeSpectralWaveBufferPair(int phase_update, int index, bool formant_shift,
758 float phase_adjustment, poly_int wave_index,
759 poly_float voice_increment, poly_float morph_amount) {
760 for (int i = index; i < index + 2; ++i) {
761 mono_float adjust_phase_inc = voice_increment[i] * phase_adjustment;
762 mono_float formant_adjustment = voice_increment[i] * Wavetable::kWaveformSize;
763 float bin = Wavetable::getFrequencyFloatBin(adjust_phase_inc);
764 int buffer_index = phase_update * poly_float::kSize + i;
765 last_buffers_[buffer_index] = wave_buffers_[buffer_index];
766
767 poly_float* fourier_buffer = fourier_frames1_[buffer_index];
768 mono_float* destination = ((mono_float*)fourier_buffer) + poly_float::kSize - 1;
769 if (destination == wave_buffers_[buffer_index])
770 fourier_buffer = fourier_frames2_[buffer_index];
771
772 float shift = morph_amount[i];
773 if (formant_shift)
774 shift *= formant_adjustment;
775 const Wavetable::WavetableData* wavetable_data = wavetable_->getAllActiveData();
776 int table_index = std::min<int>(wave_index[i], wavetable_data->num_frames - 1);
777
778 float bin_shift = Wavetable::kFrequencyBins + 1.0f - bin;
779 int last_harmonic = std::max<int>(0, WaveFrame::kWaveformSize * futils::exp2(-bin_shift));
780 last_harmonic = std::min(last_harmonic, WaveFrame::kWaveformSize / 2);
781
782 spectralMorph(wavetable_data, table_index, fourier_buffer,
783 fourier_transform_.get(), shift, last_harmonic, RandomValues::instance()->buffer());
784 wave_buffers_[buffer_index] = ((mono_float*)fourier_buffer) + poly_float::kSize - 1;
785
786 if (i == index && morph_amount[i] == morph_amount[i + 1] && wave_index[i] == wave_index[i + 1]) {
787 last_buffers_[buffer_index + 1] = wave_buffers_[buffer_index + 1];
788 wave_buffers_[buffer_index + 1] = wave_buffers_[buffer_index];
789 return;
790 }
791 }
792 }
793
794 template<void(*spectralMorph)(const Wavetable::WavetableData*, int, poly_float*,
795 FourierTransform*, float, int, const poly_float*)>
796 void SynthOscillator::setFourierWaveBuffers(poly_float phase_inc, int index, bool formant_shift) {
797 poly_float wave_frame = input(kWaveFrame)->at(0);
798 poly_float frame_spread = input(kUnisonFrameSpread)->at(0);
799 phase_inc = utils::max(0.0f, phase_inc);
800 float phase_inc_adjustment = getPhaseIncAdjustment();
801
802 DistortionType distortion_type = static_cast<DistortionType>((int)input(kDistortionType)->at(0)[0]);
803 poly_mask distortion_frequency_mask = 0;
804 mono_float distortion_mult = 1.0f;
805 if (distortion_type == kFormant || distortion_type == kSync) {
806 distortion_frequency_mask = constants::kFullMask;
807 distortion_mult = kMaxSync;
808 }
809
810 SpectralMorph spectral_morph = static_cast<SpectralMorph>((int)input(kSpectralMorphType)->at(0)[0]);
811 poly_mask spectral_unison_mask = poly_float::notEqual(input(kSpectralUnison)->at(0), 0.0f);
812 poly_mask spectral_morph_mask = poly_float::notEqual(spectral_morph_values_[0], spectral_morph_values_[1]);
813 poly_mask frame_spread_mask = poly_float::notEqual(frame_spread, 0.0f);
814 bool spectral_unison = spectral_unison_mask.anyMask() &&
815 (spectral_morph_mask.anyMask() || frame_spread_mask.anyMask() || spectral_morph == kVocode);
816
817 int num_phase_updates = active_oscillators_ / 2;
818 if (spectral_unison) {
819 float t_inc = 1.0f / (utils::imax(2, num_phase_updates) - 1.0f);
820 for (int v = 0; v < num_phase_updates; ++v) {
821 poly_float frequency_mult = distortion_values_[v] * distortion_mult;
822 frequency_mult = utils::maskLoad(1.0f, frequency_mult, distortion_frequency_mask);
823
824 poly_float morph_amount = spectral_morph_values_[v];
825 poly_float voice_increment = phase_inc * detunings_[v] * frequency_mult;
826 poly_float t = v * t_inc;
827 poly_float frame = wave_frame + t * frame_spread;
828 poly_int wave_index = utils::toInt(utils::clamp(frame, 0.0f, kNumOscillatorWaveFrames - 1));
829
830 computeSpectralWaveBufferPair<spectralMorph>(v, index, formant_shift, phase_inc_adjustment,
831 wave_index, voice_increment, morph_amount);
832 }
833 }
834 else {
835 poly_float frequency_mult = distortion_values_[0] * distortion_mult;
836 frequency_mult = utils::maskLoad(1.0f, frequency_mult, distortion_frequency_mask);
837
838 poly_float morph_amount = spectral_morph_values_[0];
839 poly_float voice_increment = phase_inc * detunings_[0] * frequency_mult;
840 poly_int wave_index = utils::toInt(utils::clamp(wave_frame, 0.0f, kNumOscillatorWaveFrames - 1));
841
842 computeSpectralWaveBufferPair<spectralMorph>(0, index, formant_shift, phase_inc_adjustment,
843 wave_index, voice_increment, morph_amount);
844
845 for (int v = 1; v < num_phase_updates; ++v) {
846 for (int i = index; i < index + 2; ++i) {
847 int buffer_index = v * poly_float::kSize + i;
848 last_buffers_[buffer_index] = wave_buffers_[buffer_index];
849 wave_buffers_[buffer_index] = wave_buffers_[i];
850 }
851 }
852 }
853 }
854
855 void SynthOscillator::stereoBlend(poly_float* audio_out, int num_samples, poly_mask reset_mask) {
856 poly_float stereo_spread = utils::clamp(input(kStereoSpread)->at(0), 0.0f, 1.0f);
857
858 poly_float current_stereo_mult = blend_stereo_multiply_;
859 poly_float current_center_mult = blend_center_multiply_;
860 blend_stereo_multiply_ = futils::equalPowerFade(stereo_spread * 0.5f + 0.5f);
861 blend_center_multiply_ = futils::equalPowerFadeInverse(stereo_spread * 0.5f + 0.5f);
862
863 current_stereo_mult = utils::maskLoad(current_stereo_mult, blend_stereo_multiply_, reset_mask);
864 current_center_mult = utils::maskLoad(current_center_mult, blend_center_multiply_, reset_mask);
865 poly_float delta_stereo_mult = (blend_stereo_multiply_ - current_stereo_mult) * (1.0f / num_samples);
866 poly_float delta_center_mult = (blend_center_multiply_ - current_center_mult) * (1.0f / num_samples);
867
868 if (delta_stereo_mult.sum() + delta_center_mult.sum() == 0.0f && utils::equal(stereo_spread, 1.0f))
869 return;
870
871 for (int i = 0; i < num_samples; ++i) {
872 current_stereo_mult += delta_stereo_mult;
873 current_center_mult += delta_center_mult;
874 poly_float val = audio_out[i];
875 poly_float swap = utils::swapStereo(val);
876 audio_out[i] = val * current_stereo_mult + swap * current_center_mult;
877 }
878 }
879
880 void SynthOscillator::levelOutput(poly_float* audio_out, const poly_float* raw_out,
881 int num_samples, poly_mask reset_mask) {
883
884 poly_float current_pan_amplitude = pan_amplitude_;
885 pan_amplitude_ = futils::panAmplitude(utils::clamp(input(kPan)->at(0), -1.0f, 1.0f));
886
887 current_pan_amplitude = utils::maskLoad(current_pan_amplitude, pan_amplitude_, reset_mask);
888 poly_float delta_pan_amplitude = (pan_amplitude_ - current_pan_amplitude) * (1.0f / num_samples);
889
890 const poly_float* amplitude = input(kAmplitude)->source->buffer;
891 poly_float zero = 0.0f;
892 for (int i = 0; i < num_samples; ++i) {
893 poly_float amp = utils::max(amplitude[i], zero);
894 current_pan_amplitude += delta_pan_amplitude;
895 audio_out[i] = current_pan_amplitude * raw_out[i] * amp * amp;
896
897 VITAL_ASSERT(utils::isFinite(audio_out[i]));
898 }
899 }
900
901 void SynthOscillator::convertVoiceChannels(int num_samples, poly_float* audio_out, poly_mask active_mask) {
902 for (int i = 0; i < num_samples; ++i)
903 audio_out[i] += utils::swapVoices(audio_out[i]);
904 }
905
906 force_inline void SynthOscillator::resetWavetableBuffers() {
907 const mono_float* default_buffer = Wavetable::null_waveform();
908 for (int i = 0; i < kNumBuffers; ++i) {
909 last_buffers_[i] = default_buffer;
910 wave_buffers_[i] = default_buffer;
911 }
912 }
913
914 force_inline void SynthOscillator::loadVoiceBlock(VoiceBlock& voice_block, int index, poly_mask active_mask) {
915 bool single_voice = (~active_mask).anyMask();
916 if (single_voice) {
917 voice_block.phase = compactAndLoadVoice(phases_ + 2 * index, active_mask);
918 voice_block.phase_inc_mult = compactAndLoadVoice(phase_inc_mults_ + 2 * index, active_mask);
919 voice_block.from_phase_inc_mult = compactAndLoadVoice(from_phase_inc_mults_ + 2 * index, active_mask);
920 voice_block.shepard_double_mask = compactAndLoadVoice(shepard_double_masks_ + 2 * index, active_mask);
921 voice_block.shepard_half_mask = compactAndLoadVoice(shepard_half_masks_ + 2 * index, active_mask);
922 voice_block.distortion = compactAndLoadVoice(distortion_values_ + 2 * index, active_mask);
923 voice_block.last_distortion = compactAndLoadVoice(last_distortion_values_ + 2 * index, active_mask);
924 poly_int distortion_phase_swap = utils::swapVoices(voice_block.distortion_phase);
925 voice_block.distortion_phase = utils::maskLoad(distortion_phase_swap, voice_block.distortion_phase, active_mask);
926 poly_int last_distortion_phase_swap = utils::swapVoices(voice_block.last_distortion_phase);
927 voice_block.last_distortion_phase = utils::maskLoad(last_distortion_phase_swap, voice_block.last_distortion_phase,
928 active_mask);
929
930 int buffer_index = 2 * index * poly_float::kSize;
931 compactAndLoadVoice(voice_block.from_buffers, last_buffers_ + buffer_index, active_mask);
932 compactAndLoadVoice(voice_block.to_buffers, wave_buffers_ + buffer_index, active_mask);
933
934 if ((index + 1) * poly_float::kSize > active_oscillators_) {
935 int zero_index = active_mask[0] ? 2 : 0;
936 voice_block.from_buffers[zero_index] = Wavetable::null_waveform();
937 voice_block.from_buffers[zero_index + 1] = Wavetable::null_waveform();
938 voice_block.to_buffers[zero_index] = Wavetable::null_waveform();
939 voice_block.to_buffers[zero_index + 1] = Wavetable::null_waveform();
940 }
941 }
942 else {
943 voice_block.phase = phases_[index];
944 voice_block.phase_inc_mult = phase_inc_mults_[index];
945 voice_block.from_phase_inc_mult = from_phase_inc_mults_[index];
946 voice_block.shepard_double_mask = shepard_double_masks_[index];
947 voice_block.shepard_half_mask = shepard_half_masks_[index];
948 voice_block.distortion = distortion_values_[index];
949 voice_block.last_distortion = last_distortion_values_[index];
950
951 int buffer_index = index * poly_float::kSize;
952 memcpy(voice_block.from_buffers, last_buffers_ + buffer_index, poly_float::kSize * sizeof(mono_float*));
953 memcpy(voice_block.to_buffers, wave_buffers_ + buffer_index, poly_float::kSize * sizeof(mono_float*));
954 }
955 }
956
958 // Sets spectral morph parameters based on the current morph type.
959 static constexpr float kModMult = 0.99f;
960 poly_float spectral_morph_amount = input(kSpectralMorphAmount)->at(0);
961 poly_float morph_spread = input(kUnisonSpectralMorphSpread)->at(0);
962 int num_phase_updates = active_oscillators_ / 2;
963
964 for (int v = 0; v < kNumPolyPhase; ++v) {
965 poly_float t = (v / (utils::imax(2, num_phase_updates) - 1.0f)) * 2.0f;
966 last_spectral_morph_values_[v] = spectral_morph_values_[v];
967 spectral_morph_values_[v] = spectral_morph_amount + t * morph_spread;
968 }
969
970 if (spectral_morph == kShepardTone) {
971 for (int v = 0; v < kNumPolyPhase; ++v)
972 spectral_morph_values_[v] = utils::mod(spectral_morph_values_[v] * kModMult) * (1.0f / kModMult);
973 }
974 else {
975 for (int v = 0; v < kNumPolyPhase; ++v)
976 spectral_morph_values_[v] = utils::clamp(spectral_morph_values_[v], 0.0f, 1.0f);
977 }
978
979 bool is_spread = poly_float::notEqual(morph_spread, 0.0f).anyMask() != 0;
980 setSpectralMorphValues(spectral_morph, spectral_morph_values_, kNumPolyPhase, is_spread);
981 if (spectral_morph == kVocode) {
982 static constexpr float kDefaultSampleRate = 88200;
983 float sample_rate = wavetable_->getActiveSampleRate();
984 if (sample_rate <= 0.0f)
985 sample_rate = kDefaultSampleRate;
986 float sample_rate_ratio = getSampleRate() / sample_rate;
987 float frequency_ratio = sample_rate_ratio * wavetable_->getActiveFrequencyRatio();
988
989 for (int i = 0; i < kNumPolyPhase; ++i)
990 spectral_morph_values_[i] *= frequency_ratio;
991 }
992 }
993
995 // Sets distortion parameters based on the current distortion type.
996 poly_float distortion_amount = input(kDistortionAmount)->at(0);
997 poly_float distortion_spread = input(kUnisonDistortionSpread)->at(0);
998 int num_phase_updates = active_oscillators_ / 2;
999 for (int v = 0; v < kNumPolyPhase; ++v) {
1000 poly_float t = (v / (utils::imax(2, num_phase_updates) - 1.0f) * 2.0f);
1001 last_distortion_values_[v] = distortion_values_[v];
1002 distortion_values_[v] = utils::clamp(distortion_amount + t * distortion_spread, 0.0f, 1.0f);
1003 }
1004
1005 if (distortion_type == kQuantize) {
1006 for (int i = 0; i < kNumPolyPhase; ++i)
1007 last_distortion_values_[i] = utils::max(1.5f, last_distortion_values_[i]);
1008 }
1009
1010 bool is_spread = poly_float::notEqual(distortion_spread, 0.0f).anyMask() != 0;
1011 setDistortionValues(distortion_type, distortion_values_, kNumPolyPhase, is_spread);
1012 }
1013
1015 poly_float* values, int num_values, bool spread) {
1016 switch (distortion_type) {
1017 case kFmOscillatorA:
1018 case kFmOscillatorB:
1019 case kFmSample:
1020 for (int i = 0; i < num_values; ++i)
1021 values[i] *= values[i];
1022 break;
1023 case kSync:
1024 case kFormant:
1025 setPowerDistortionValues(values, num_values, kMaxSyncPower, spread);
1026 for (int i = 0; i < num_values; ++i)
1027 values[i] *= (1.0f / kMaxSync);
1028 break;
1029 case kQuantize:
1030 if (spread) {
1031 for (int i = 0; i < num_values; ++i) {
1032 poly_float distortion = poly_float(1.0f) - values[i];
1033 distortion *= distortion * distortion;
1034 distortion = distortion * kMaxQuantize;
1035 values[i] = futils::pow(2.0f, distortion * kDistortBits + 1.0f);
1036 }
1037 }
1038 else {
1039 poly_float distortion = poly_float(1.0f) - values[0];
1040 distortion *= distortion * distortion;
1041 distortion = distortion * kMaxQuantize;
1042 distortion = futils::pow(2.0f, distortion * kDistortBits + 1.0f);
1043 for (int i = 0; i < num_values; ++i)
1044 values[i] = distortion;
1045 }
1046 break;
1047 case kSqueeze:
1048 for (int i = 0; i < num_values; ++i)
1049 values[i] = values[i] * 2.0f * kMaxSqueezePercent + (1.0f - kMaxSqueezePercent);
1050 break;
1051 case kPulseWidth:
1052 if (spread) {
1053 for (int i = 0; i < num_values; ++i) {
1054 poly_float distortion = utils::max(poly_float(1.0f) - values[i], 1.0f / UINT_MAX);
1055 values[i] = poly_float(1.0f) / distortion;
1056 }
1057 }
1058 else {
1059 poly_float distortion = utils::max(poly_float(1.0f) - values[0], 1.0f / UINT_MAX);
1060 distortion = poly_float(1.0f) / distortion;
1061 for (int i = 0; i < num_values; ++i)
1062 values[i] = distortion;
1063 }
1064 break;
1065 default:
1066 break;
1067 }
1068 }
1069
1071 poly_float* values, int num_values, bool spread) {
1072 switch (spectral_morph) {
1073 case kVocode:
1074 setPowerDistortionValues(values, num_values, -kMaxFormantShift, spread);
1075 break;
1076 case kFormScale:
1077 setPowerDistortionValues(values, num_values, -kMaxEvenOddFormantShift, spread);
1078 break;
1079 case kHarmonicScale:
1080 setPowerDistortionValues(values, num_values, kMaxHarmonicScale, spread);
1081 break;
1082 case kInharmonicScale:
1083 setPowerDistortionValues(values, num_values, kMaxInharmonicScale, spread);
1084 break;
1085 case kSmear:
1086 for (int i = 0; i < num_values; ++i) {
1087 poly_float invert = poly_float(1.0f) - values[i];
1088 values[i] = poly_float(1.0f) - invert * invert * invert;
1089 }
1090 break;
1091 case kRandomAmplitudes:
1092 for (int i = 0; i < num_values; ++i)
1093 values[i] = values[i] * (kRandomAmplitudeStages - 1);
1094 break;
1095 case kPhaseDisperse:
1096 for (int i = 0; i < num_values; ++i)
1097 values[i] = -(values[i] * 2.0f - 1.0f) * kPhaseDisperseScale;
1098 break;
1099 case kSkew:
1100 for (int i = 0; i < num_values; ++i)
1101 values[i] = values[i] * values[i] * kSkewScale;
1102 break;
1103 case kShepardTone:
1104 for (int i = 0; i < num_values; ++i)
1105 values[i] = poly_float(1.0f) - values[i];
1106 break;
1107 default:
1108 break;
1109 }
1110 }
1111
1112 void SynthOscillator::runSpectralMorph(SpectralMorph morph_type, float morph_amount,
1113 const Wavetable::WavetableData* wavetable_data,
1114 int wavetable_index, poly_float* dest, FourierTransform* transform) {
1116 switch (morph_type) {
1117 case kVocode:
1118 case kFormScale:
1119 evenOddVocodeMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1120 break;
1121 case kHarmonicScale:
1122 harmonicScaleMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1123 break;
1124 case kInharmonicScale:
1125 inharmonicScaleMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1126 break;
1127 case kSmear:
1128 smearMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1129 break;
1130 case kRandomAmplitudes:
1131 randomAmplitudeMorph(wavetable_data, wavetable_index,
1132 dest, transform, morph_amount, h, RandomValues::instance()->buffer());
1133 break;
1134 case kShepardTone:
1135 shepardMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1136 break;
1137 case kLowPass:
1138 lowPassMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1139 break;
1140 case kHighPass:
1141 highPassMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1142 break;
1143 case kPhaseDisperse:
1144 phaseMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1145 break;
1146 case kSkew:
1147 wavetableSkewMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1148 break;
1149 default:
1150 passthroughMorph(wavetable_data, wavetable_index, dest, transform, morph_amount, h, nullptr);
1151 }
1152 }
1153
1155 poly_float distortion_amount, poly_int distortion_phase) {
1156 switch (distortion_type) {
1157 case kSync:
1158 case kFormant:
1159 return syncPhase(phase, distortion_amount, distortion_phase, nullptr, 0);
1160 case kQuantize:
1161 return quantizePhase(phase, distortion_amount, distortion_phase, nullptr, 0);
1162 case kBend:
1163 return bendPhase(phase, distortion_amount, distortion_phase, nullptr, 0);
1164 case kSqueeze:
1165 return squeezePhase(phase, distortion_amount, distortion_phase, nullptr, 0);
1166 case kPulseWidth:
1167 return pulseWidthPhase(phase, distortion_amount, distortion_phase, nullptr, 0);
1168 default:
1169 return phase;
1170 }
1171 }
1172
1174 poly_int distorted_phase) {
1175 switch (distortion_type) {
1176 case kFormant:
1177 return halfSinWindow(phase, distorted_phase, 0.0f, nullptr, 0);
1178 case kPulseWidth:
1179 return pulseWidthWindow(phase, distorted_phase, 0.0f, nullptr, 0);
1180 default:
1181 return 1.0f;
1182 }
1183 }
1184
1186 return linearlyInterpolateBuffer(buffer, indices);
1187 }
1188
1190 return distortion_type == kSync || distortion_type == kFormant || distortion_type == kQuantize ||
1191 distortion_type == kBend || distortion_type == kSqueeze || distortion_type == kPulseWidth;
1192 }
1193
1194 void SynthOscillator::process(int num_samples) {
1195 // Main processing routine that handles wavetable lookup, spectral morphing,
1196 wavetable_->markUsed();
1197 int wavetable_version = wavetable_->getActiveVersion();
1198 if (wavetable_version != wavetable_version_) {
1199 wavetable_version_ = wavetable_version;
1200 resetWavetableBuffers();
1201 }
1202
1203 poly_float active_voice = input(kActiveVoices)->at(0);
1204 bool left_active = active_voice[0] == 1.0f;
1205 bool right_active = active_voice[2] == 1.0f;
1206
1207 unison_ = utils::clamp(roundf(input(kUnisonVoices)->at(0)[0]), 1.0f, kMaxUnison);
1208 setActiveOscillators(unison_ + (unison_ % 2));
1209
1210 SpectralMorph spectral_morph = static_cast<SpectralMorph>((int)input(kSpectralMorphType)->at(0)[0]);
1211 DistortionType distortion_type = static_cast<DistortionType>((int)input(kDistortionType)->at(0)[0]);
1212 setSpectralMorphValues(spectral_morph);
1213 setDistortionValues(distortion_type);
1214 voice_block_.phase_inc_buffer = phase_inc_buffer_->buffer;
1215 voice_block_.spectral_morph = spectral_morph;
1216
1217 switch (distortion_type) {
1218 case kSync:
1219 processOscillators<syncPhase, passThroughWindow>(num_samples, distortion_type);
1220 break;
1221 case kFormant:
1222 processOscillators<syncPhase, halfSinWindow>(num_samples, distortion_type);
1223 break;
1224 case kQuantize:
1225 processOscillators<quantizePhase, passThroughWindow>(num_samples, distortion_type);
1226 break;
1227 case kBend:
1228 processOscillators<bendPhase, passThroughWindow>(num_samples, distortion_type);
1229 break;
1230 case kSqueeze:
1231 processOscillators<squeezePhase, passThroughWindow>(num_samples, distortion_type);
1232 break;
1233 case kPulseWidth:
1234 processOscillators<pulseWidthPhase, pulseWidthWindow>(num_samples, distortion_type);
1235 break;
1236 case kFmOscillatorA:
1237 case kFmOscillatorB:
1238 case kFmSample:
1239 if (distortion_type == kFmOscillatorB)
1240 voice_block_.modulation_buffer = second_mod_oscillator_->buffer;
1241 else if (distortion_type == kFmSample)
1242 voice_block_.modulation_buffer = sample_->buffer;
1243 else
1244 voice_block_.modulation_buffer = first_mod_oscillator_->buffer;
1245
1246 if (left_active && right_active)
1247 processOscillators<fmPhase, passThroughWindow>(num_samples, distortion_type);
1248 else if (left_active)
1249 processOscillators<fmPhaseLeft, passThroughWindow>(num_samples, distortion_type);
1250 else
1251 processOscillators<fmPhaseRight, passThroughWindow>(num_samples, distortion_type);
1252 break;
1253 case kRmOscillatorA:
1254 case kRmOscillatorB:
1255 case kRmSample:
1256 if (distortion_type == kRmOscillatorB)
1257 voice_block_.modulation_buffer = second_mod_oscillator_->buffer;
1258 else if (distortion_type == kRmSample)
1259 voice_block_.modulation_buffer = sample_->buffer;
1260 else
1261 voice_block_.modulation_buffer = first_mod_oscillator_->buffer;
1262
1263 if (left_active && right_active)
1264 processOscillators<passThroughPhase, rmWindow>(num_samples, distortion_type);
1265 else if (left_active)
1266 processOscillators<passThroughPhase, rmWindowLeft>(num_samples, distortion_type);
1267 else
1268 processOscillators<passThroughPhase, rmWindowRight>(num_samples, distortion_type);
1269 break;
1270 default:
1271 processOscillators<passThroughPhase, passThroughWindow>(num_samples, distortion_type);
1272 break;
1273 }
1274
1275 wavetable_->markUnused();
1276 }
1277
1278 force_inline void SynthOscillator::setActiveOscillators(int new_active_oscillators) {
1279 for (int i = active_oscillators_; i < new_active_oscillators; ++i) {
1280 wave_buffers_[2 * i] = Wavetable::null_waveform();
1281 wave_buffers_[2 * i + 1] = Wavetable::null_waveform();
1282 }
1283
1284 active_oscillators_ = new_active_oscillators;
1285 }
1286
1287 template<poly_float(*snapTranspose)(poly_float, poly_float, float*)>
1288 void SynthOscillator::setPhaseIncBufferSnap(int num_samples, poly_mask reset_mask,
1289 poly_int trigger_sample, poly_mask active_mask, float* snap_buffer) {
1290 bool midi_track = poly_float::notEqual(input(kMidiTrack)->at(0), 0.0f).anyMask();
1291 poly_float current_midi = midi_note_;
1292 midi_note_ = kNoMidiTrackDefault;
1293 if (midi_track)
1294 midi_note_ = input(kMidiNote)->at(0);
1295
1296 float sample_inc = 1.0f / num_samples;
1297 current_midi = utils::maskLoad(current_midi, midi_note_, reset_mask);
1298 poly_float delta_midi = (midi_note_ - current_midi) * sample_inc;
1299 current_midi = utils::maskLoad(utils::swapVoices(current_midi), current_midi, active_mask);
1300 delta_midi = utils::maskLoad(utils::swapVoices(delta_midi), delta_midi, active_mask);
1301
1302 const poly_float* transpose_buffer = input(kTranspose)->source->buffer;
1303 const poly_float* tune_buffer = input(kTune)->source->buffer;
1304 const poly_float* phase_buffer = input(kPhase)->source->buffer;
1305
1306 poly_float base_midi = current_midi + transpose_buffer[0] + tune_buffer[0];
1307 poly_float base_frequency = utils::midiNoteToFrequency(base_midi);
1308
1309 poly_float sample_rate_scale = kPhaseMult / getSampleRate();
1310 poly_float phase_scale = kPhaseMult;
1311
1312 poly_float* inc_dest = phase_inc_buffer_->buffer;
1313 poly_int* phase_dest = phase_buffer_->buffer;
1314
1315 for (int i = 0; i < num_samples; ++i) {
1316 poly_float shift_phase = utils::mod(phase_buffer[i]) - 0.5f;
1317 poly_int phase = utils::toInt(shift_phase * phase_scale);
1318 phase_dest[i] = utils::maskLoad(utils::swapVoices(phase), phase, active_mask);
1319
1320 current_midi += delta_midi;
1321
1322 poly_float midi = snapTranspose(current_midi, transpose_buffer[i], snap_buffer) + tune_buffer[i];
1323 poly_float frequency = base_frequency * futils::midiOffsetToRatio(midi - base_midi);
1324 poly_mask zero_mask = poly_int::lessThan(i, trigger_sample) & reset_mask;
1325 poly_float result = (frequency * sample_rate_scale) & ~zero_mask;
1326 inc_dest[i] = utils::maskLoad(utils::swapVoices(result), result, active_mask);
1327 }
1328 }
1329
1330 void SynthOscillator::setPhaseIncBuffer(int num_samples, poly_mask reset_mask,
1331 poly_int trigger_sample, poly_mask active_mask) {
1332 int transpose_quantize = static_cast<int>(input(kTransposeQuantize)->at(0)[0]);
1333 if (!utils::isTransposeSnapping(transpose_quantize)) {
1334 setPhaseIncBufferSnap<noTransposeSnap>(num_samples, reset_mask, trigger_sample, active_mask, nullptr);
1335 return;
1336 }
1337
1338 float snap_buffer[kNotesPerOctave + 1];
1339 utils::fillSnapBuffer(transpose_quantize, snap_buffer);
1340 if (utils::isTransposeQuantizeGlobal(transpose_quantize))
1341 setPhaseIncBufferSnap<globalTransposeSnap>(num_samples, reset_mask, trigger_sample, active_mask, snap_buffer);
1342 else
1343 setPhaseIncBufferSnap<localTransposeSnap>(num_samples, reset_mask, trigger_sample, active_mask, snap_buffer);
1344 }
1345
1346 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
1347 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int)>
1348 void SynthOscillator::processOscillators(int num_samples, DistortionType distortion_type) {
1349 poly_mask active_voice_mask = poly_float::equal(input(kActiveVoices)->at(0), 1.0f);
1350 poly_float current_center_amplitude = center_amplitude_;
1351 poly_float current_detuned_amplitude = detuned_amplitude_;
1352 setAmplitude();
1353
1354 poly_mask reset_mask = getResetMask(kReset);
1355 poly_int trigger_offset = input(kReset)->source->trigger_offset;
1356 poly_mask retrigger_mask = getResetMask(kRetrigger) & ~reset_mask;
1357
1358 current_center_amplitude = utils::maskLoad(current_center_amplitude, center_amplitude_, reset_mask);
1359 current_detuned_amplitude = utils::maskLoad(current_detuned_amplitude, detuned_amplitude_, reset_mask);
1360
1361 setPhaseIncMults();
1362 setPhaseIncBuffer(num_samples, reset_mask, trigger_offset, active_voice_mask);
1363
1364 poly_float current_distortion_phase = distortion_phase_;
1365 distortion_phase_ = 0.0f;
1366 if (usesDistortionPhase(distortion_type))
1367 distortion_phase_ = input(kDistortionPhase)->at(0) - 0.5f;
1368 current_distortion_phase = utils::maskLoad(current_distortion_phase, distortion_phase_, reset_mask);
1369
1370 voice_block_.last_distortion_phase = utils::toInt(current_distortion_phase * kPhaseMult);
1371 voice_block_.distortion_phase = utils::toInt(distortion_phase_ * kPhaseMult);
1372
1373 poly_mask wave_buffer_mask = reset_mask | retrigger_mask;
1374 poly_float buffer_phase_inc = phase_inc_buffer_->buffer[num_samples - 1] * (1.0f / kPhaseMult);
1375 if (wave_buffer_mask[0])
1376 setWaveBuffers(buffer_phase_inc, 0);
1377 if (wave_buffer_mask[2])
1378 setWaveBuffers(buffer_phase_inc, 2);
1379
1380 if (reset_mask.anyMask())
1381 reset(reset_mask, trigger_offset);
1382
1383 if (retrigger_mask.anyMask()) {
1384 for (int i = 0; i < kNumPolyPhase; ++i)
1385 from_phase_inc_mults_[i] = utils::maskLoad(from_phase_inc_mults_[i], phase_inc_mults_[i], retrigger_mask);
1386 }
1387
1388 voice_block_.start_sample = 0;
1389 voice_block_.total_samples = num_samples;
1390 int num_buffer_samples = kWavetableFadeTime * getSampleRate();
1391 if (voice_block_.num_buffer_samples != num_buffer_samples) {
1392 voice_block_.num_buffer_samples = num_buffer_samples;
1393 voice_block_.current_buffer_sample = 0;
1394 }
1395
1396 bool shepard = voice_block_.spectral_morph == kShepardTone;
1397 if (shepard)
1398 setupShepardWrap();
1399 else
1400 clearShepardWrap();
1401
1402 voice_block_.current_buffer_sample &= active_voice_mask;
1403 while (voice_block_.start_sample < num_samples) {
1404 poly_int remaining_fade_samples = poly_int(voice_block_.num_buffer_samples) - voice_block_.current_buffer_sample;
1405 int min_remaining_fade_samples = std::min(remaining_fade_samples[0], remaining_fade_samples[2]);
1406 int samples = std::min(min_remaining_fade_samples, num_samples - voice_block_.start_sample);
1407 voice_block_.end_sample = voice_block_.start_sample + samples;
1408 processChunk<phaseDistort, window>(current_center_amplitude, current_detuned_amplitude);
1409
1410 voice_block_.current_buffer_sample += samples;
1411 voice_block_.start_sample = voice_block_.end_sample;
1412
1413 poly_mask new_buffer_mask = poly_int::equal(voice_block_.current_buffer_sample, voice_block_.num_buffer_samples);
1414 if (shepard && new_buffer_mask.anyMask())
1415 doShepardWrap(new_buffer_mask, transpose_quantize_);
1416
1417 if (new_buffer_mask[0])
1418 setWaveBuffers(buffer_phase_inc, 0);
1419 if (new_buffer_mask[2])
1420 setWaveBuffers(buffer_phase_inc, 2);
1421
1422 VITAL_ASSERT((int)voice_block_.current_buffer_sample[0] < voice_block_.num_buffer_samples);
1423 VITAL_ASSERT((int)voice_block_.current_buffer_sample[2] < voice_block_.num_buffer_samples);
1424 }
1425
1426 if (reset_mask.anyMask())
1427 clearOutputBufferForReset(reset_mask, kReset, kRaw);
1428
1429 processBlend(num_samples, reset_mask);
1430 }
1431
1432 template<poly_int(*phaseDistort)(poly_int, poly_float, poly_int, const poly_float*, int),
1433 poly_float(*window)(poly_int, poly_int, poly_float, const poly_float*, int)>
1434 void SynthOscillator::processChunk(poly_float current_center_amplitude, poly_float current_detuned_amplitude) {
1435 int active_channels = input(kActiveVoices)->at(0).sum();
1436 if (active_channels < 2)
1437 return;
1438
1439 VITAL_ASSERT(active_channels == 2 || active_channels == 4);
1440 int num_active_voices = active_channels / 2;
1441 poly_mask active_voice_mask = poly_float::equal(input(kActiveVoices)->at(0), 1.0f);
1442 int num_samples = voice_block_.end_sample - voice_block_.start_sample;
1443
1444 poly_float* audio_out = output(kRaw)->buffer + voice_block_.start_sample;
1445 utils::zeroBuffer(audio_out, num_samples);
1446
1447 poly_float center_amplitude = center_amplitude_;
1448 poly_float detuned_amplitude = detuned_amplitude_;
1449
1450 if (num_active_voices < 2) {
1451 poly_float current_detuned_swap = utils::swapVoices(current_detuned_amplitude);
1452 current_detuned_amplitude = utils::maskLoad(current_detuned_swap, current_detuned_amplitude, active_voice_mask);
1453 current_center_amplitude = utils::maskLoad(current_detuned_amplitude,
1454 current_center_amplitude, active_voice_mask);
1455
1456 poly_float detuned_swap = utils::swapVoices(detuned_amplitude);
1457 detuned_amplitude = utils::maskLoad(detuned_swap, detuned_amplitude, active_voice_mask);
1458 center_amplitude = utils::maskLoad(detuned_amplitude, center_amplitude, active_voice_mask);
1459
1460 poly_float distortion_swap = utils::swapVoices(voice_block_.distortion);
1461 voice_block_.distortion = utils::maskLoad(distortion_swap, voice_block_.distortion, active_voice_mask);
1462
1463 poly_float last_distortion_swap = utils::swapVoices(voice_block_.last_distortion);
1464 voice_block_.last_distortion = utils::maskLoad(last_distortion_swap, voice_block_.last_distortion,
1465 active_voice_mask);
1466 poly_int swap_buffer_sample = utils::swapVoices(voice_block_.current_buffer_sample);
1467 voice_block_.current_buffer_sample = utils::maskLoad(swap_buffer_sample, voice_block_.current_buffer_sample,
1468 active_voice_mask);
1469 }
1470
1471 int num_phase_updates = (poly_float::kSize - 1 + num_active_voices * active_oscillators_) / poly_float::kSize;
1472 for (int p = 1; p < num_phase_updates; ++p) {
1473 loadVoiceBlock(voice_block_, p, active_voice_mask);
1474
1475 poly_int phase = processDetuned<phaseDistort, window>(voice_block_, audio_out);
1476 if (num_active_voices < 2)
1477 expandAndWriteVoice(phases_ + 2 * p, phase, active_voice_mask);
1478 else
1479 phases_[p] = phase;
1480 }
1481
1482 loadVoiceBlock(voice_block_, 0, active_voice_mask);
1483
1484 mono_float sample_inc = 1.0f / voice_block_.total_samples;
1485 poly_float delta_center_amplitude = (center_amplitude - current_center_amplitude) * sample_inc;
1486 poly_float delta_detuned_amplitude = (detuned_amplitude - current_detuned_amplitude) * sample_inc;
1487 current_center_amplitude += delta_center_amplitude * voice_block_.start_sample;
1488 current_detuned_amplitude += delta_detuned_amplitude * voice_block_.start_sample;
1489 poly_int center_phase = processCenter<phaseDistort, window>(voice_block_, audio_out,
1490 current_center_amplitude, delta_center_amplitude,
1491 current_detuned_amplitude, delta_detuned_amplitude);
1492
1493 if (num_active_voices < 2) {
1494 expandAndWriteVoice(phases_, center_phase, active_voice_mask);
1495 convertVoiceChannels(num_samples, audio_out, active_voice_mask);
1496 }
1497 else
1498 phases_[0] = center_phase;
1499 }
1500
1501 void SynthOscillator::processBlend(int num_samples, poly_mask reset_mask) {
1502 poly_float* audio_out = output(kRaw)->buffer;
1503 stereoBlend(audio_out, num_samples, reset_mask);
1504 levelOutput(output(kLevelled)->buffer, audio_out, num_samples, reset_mask);
1505 }
1506} // namespace vital
A Fourier transform implementation using KissFFT for platforms where other accelerations are unavaila...
Definition fourier_transform.h:210
Base class for all signal-processing units in Vital.
Definition processor.h:212
force_inline Input * input(unsigned int index=0) const
Retrieves the Input pointer at a given index.
Definition processor.h:587
force_inline int getSampleRate() const
Retrieves the current (effective) sample rate.
Definition processor.h:326
bool inputMatchesBufferSize(int input=0)
Checks whether the buffer size of a particular input matches the size needed by this Processor.
Definition processor.cpp:42
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
const poly_float * buffer()
Get the internal random data buffer.
Definition synth_oscillator.h:48
static RandomValues * instance()
Retrieve the singleton instance of RandomValues.
Definition synth_oscillator.h:38
void process(int num_samples) override
Processes the oscillator for a given number of samples, writing to the output buffers.
Definition synth_oscillator.cpp:1194
SynthOscillator(Wavetable *wavetable)
Constructs a SynthOscillator with the specified Wavetable.
Definition synth_oscillator.cpp:519
DistortionType
Types of distortion/waveshaping used by the oscillator.
Definition synth_oscillator.h:145
@ kRmOscillatorB
RM using oscillator B.
Definition synth_oscillator.h:157
@ kFmOscillatorA
FM using oscillator A.
Definition synth_oscillator.h:153
@ kFmSample
FM using sample.
Definition synth_oscillator.h:155
@ kFmOscillatorB
FM using oscillator B.
Definition synth_oscillator.h:154
@ kSqueeze
Squeeze distortion.
Definition synth_oscillator.h:151
@ kRmSample
RM using sample.
Definition synth_oscillator.h:158
@ kFormant
Formant shifting.
Definition synth_oscillator.h:148
@ kPulseWidth
Pulse width distortion.
Definition synth_oscillator.h:152
@ kRmOscillatorA
RM using oscillator A.
Definition synth_oscillator.h:156
@ kQuantize
Quantization.
Definition synth_oscillator.h:149
@ kBend
Bend distortion.
Definition synth_oscillator.h:150
@ kSync
Sync distortion.
Definition synth_oscillator.h:147
static void setDistortionValues(DistortionType distortion_type, poly_float *values, int num_values, bool spread)
Sets distortion values for an array of poly_float, handling unison spread if necessary.
Definition synth_oscillator.cpp:1014
static bool usesDistortionPhase(DistortionType distortion_type)
Checks if a given distortion type uses a separate distortion_phase (kSync, kQuantize,...
Definition synth_oscillator.cpp:1189
@ kMidiTrack
MIDI tracking toggle.
Definition synth_oscillator.h:83
@ kPhase
Phase offset.
Definition synth_oscillator.h:92
@ kDistortionAmount
Distortion amount.
Definition synth_oscillator.h:107
@ kRandomPhase
Random phase amount.
Definition synth_oscillator.h:94
@ kStereoSpread
Stereo spread amount.
Definition synth_oscillator.h:96
@ kMidiNote
MIDI note (for pitch)
Definition synth_oscillator.h:82
@ kBlend
Blend between center voice and detuned voices.
Definition synth_oscillator.h:95
@ kSpectralMorphType
Spectral morph type.
Definition synth_oscillator.h:103
@ kTune
Fine tune.
Definition synth_oscillator.h:87
@ kUnisonVoices
Number of unison voices.
Definition synth_oscillator.h:90
@ kDetuneRange
Detune range.
Definition synth_oscillator.h:99
@ kUnisonDistortionSpread
Unison distortion spread.
Definition synth_oscillator.h:101
@ kPan
Stereo panning.
Definition synth_oscillator.h:89
@ kTranspose
Transpose amount.
Definition synth_oscillator.h:85
@ kDistortionType
Distortion type.
Definition synth_oscillator.h:106
@ kUnisonDetune
Unison detune amount.
Definition synth_oscillator.h:91
@ kSpectralMorphAmount
Spectral morph amount.
Definition synth_oscillator.h:104
@ kDetunePower
Detune power exponent.
Definition synth_oscillator.h:98
@ kAmplitude
Output amplitude.
Definition synth_oscillator.h:88
@ kUnisonSpectralMorphSpread
Unison spectral morph spread.
Definition synth_oscillator.h:102
@ kStackStyle
Unison stack style.
Definition synth_oscillator.h:97
@ kNumInputs
Number of inputs.
Definition synth_oscillator.h:111
@ kActiveVoices
Active voice mask.
Definition synth_oscillator.h:108
@ kTransposeQuantize
Transpose quantize setting.
Definition synth_oscillator.h:86
static vital::poly_float getPhaseWindow(DistortionType distortion_type, poly_int phase, poly_int distorted_phase)
Retrieves a window multiplier (for example, half-sin window in formant mode).
Definition synth_oscillator.cpp:1173
SpectralMorph
Types of spectral morph effects that can be applied to the wavetable.
Definition synth_oscillator.h:126
@ kSmear
Smear morph.
Definition synth_oscillator.h:132
@ kRandomAmplitudes
Random amplitudes morph.
Definition synth_oscillator.h:133
@ kSkew
Skew morph.
Definition synth_oscillator.h:138
@ kFormScale
Formant scaling.
Definition synth_oscillator.h:129
@ kHarmonicScale
Harmonic scaling.
Definition synth_oscillator.h:130
@ kHighPass
Highpass morph.
Definition synth_oscillator.h:135
@ kInharmonicScale
Inharmonic scaling.
Definition synth_oscillator.h:131
@ kLowPass
Lowpass morph.
Definition synth_oscillator.h:134
@ kShepardTone
Shepard tone morph.
Definition synth_oscillator.h:137
@ kPhaseDisperse
Phase dispersion.
Definition synth_oscillator.h:136
@ kVocode
Vocode morph.
Definition synth_oscillator.h:128
static constexpr int kNumBuffers
Number of buffers to store waveforms, based on the number of poly phases.
Definition synth_oscillator.h:205
static void runSpectralMorph(SpectralMorph morph_type, float morph_amount, const Wavetable::WavetableData *wavetable_data, int wavetable_index, poly_float *dest, FourierTransform *transform)
Applies a spectral morph operation (e.g., vocode, smear) directly on a buffer.
Definition synth_oscillator.cpp:1112
static void setSpectralMorphValues(SpectralMorph spectral_morph, poly_float *values, int num_values, bool spread)
Sets spectral morph values for an array of poly_float, handling unison spread if necessary.
Definition synth_oscillator.cpp:1070
@ kNumOutputs
Number of outputs.
Definition synth_oscillator.h:120
@ kLevelled
Output after amplitude leveling/panning.
Definition synth_oscillator.h:119
@ kRaw
Unleveled or "raw" output.
Definition synth_oscillator.h:118
static poly_float interpolate(const mono_float *buffer, const poly_int indices)
Performs linear interpolation on a single wave buffer.
Definition synth_oscillator.cpp:1185
static vital::poly_int adjustPhase(DistortionType distortion_type, poly_int phase, poly_float distortion_amount, poly_int distortion_phase)
Adjusts phase for sync, formant, quantize, etc.
Definition synth_oscillator.cpp:1154
void reset(poly_mask reset_mask, poly_int sample)
Resets oscillator state with an offset sample count.
Definition synth_oscillator.cpp:558
static constexpr int kMaxUnison
Maximum number of unison voices.
Definition synth_oscillator.h:199
static const mono_float kStackMultipliers[kNumUnisonStackTypes][kNumPolyPhase]
Precomputed multipliers used for stacking unison voices into intervals.
Definition synth_oscillator.h:210
static constexpr int kNumPolyPhase
Number of poly phases total.
Definition synth_oscillator.h:203
static constexpr int kWaveformBits
The number of bits that define the size of the waveform (2^kWaveformBits = kWaveformSize).
Definition wave_frame.h:19
static constexpr int kWaveformSize
The size of the waveform (number of samples per frame).
Definition wave_frame.h:21
A class representing a wavetable, holding multiple frames of waveforms and their frequency-domain rep...
Definition wavetable.h:20
force_inline float getActiveFrequencyRatio() const
Get the frequency ratio of the active wavetable data.
Definition wavetable.h:232
force_inline void markUnused()
Mark the active wavetable data as unused, allowing for changes.
Definition wavetable.h:329
force_inline float getActiveSampleRate() const
Get the sample rate of the active wavetable data.
Definition wavetable.h:241
static constexpr int kNumHarmonics
Number of harmonics in the waveform (half the size plus one).
Definition wavetable.h:29
static constexpr int kFrequencyBins
Number of frequency bins (equal to number of wave bits in a frame).
Definition wavetable.h:23
force_inline int getActiveVersion()
Get the version number of the active wavetable data.
Definition wavetable.h:279
static constexpr const mono_float * null_waveform()
Returns a constant pointer to a zeroed waveform.
Definition wavetable.h:71
static force_inline mono_float getFrequencyFloatBin(mono_float phase_increment)
Compute a float-based frequency bin from a phase increment.
Definition wavetable.h:144
force_inline void markUsed()
Mark the current wavetable data as used (active).
Definition wavetable.h:324
static constexpr int kWaveformSize
Size of each waveform frame.
Definition wavetable.h:25
force_inline mono_float next()
Returns the next random float in [min, max].
Definition utils.h:85
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
Contains faster but less accurate versions of utility math functions, such as exponential,...
const poly_mask kFullMask
A mask covering all lanes of a poly_float vector.
Definition synth_constants.h:257
const poly_mask kFirstMask
A mask identifying the first voice slots in a polyphonic vector.
Definition synth_constants.h:266
@ kRetrigger
LFO restarts phase on note-on.
Definition synth_constants.h:212
const poly_mask kLeftMask
A mask identifying the left channel when comparing to kLeftOne.
Definition synth_constants.h:260
@ kFormant
Definition synth_constants.h:200
const poly_mask kSecondMask
A mask identifying the second voice slots in a polyphonic vector.
Definition synth_constants.h:269
force_inline poly_float equalPowerFadeInverse(poly_float t)
The inverse equal-power fade from t to t+1.0.
Definition futils.h:448
force_inline poly_float exp2(poly_float exponent)
Approximates 2^exponent for poly_float values using a polynomial approximation.
Definition futils.h:45
force_inline poly_float equalPowerFade(poly_float t)
Produces an equal-power crossfade (sin-based) between 0.0 and 1.0.
Definition futils.h:436
force_inline mono_float sin(mono_float phase)
Definition futils.h:401
force_inline mono_float powerScale(mono_float value, mono_float power)
A power-scaling function to map a linear range to a curved response.
Definition futils.h:455
force_inline poly_float midiOffsetToRatio(poly_float note_offset)
Converts a MIDI note offset to a frequency ratio.
Definition futils.h:184
force_inline mono_float pow(mono_float base, mono_float exponent)
Definition futils.h:141
force_inline poly_float panAmplitude(poly_float pan)
Definition futils.h:439
force_inline poly_float mod(poly_float value)
Returns the fractional part of each lane by subtracting the floored value.
Definition poly_utils.h:814
force_inline poly_float clamp(poly_float value, mono_float min, mono_float max)
Clamps each lane of a vector to [min, max].
Definition poly_utils.h:306
force_inline poly_float trunc(poly_float value)
Returns the truncated value of each lane in value.
Definition poly_utils.h:770
force_inline bool isFinite(poly_float value)
Checks if all lanes in a poly_float are finite.
Definition poly_utils.h:610
force_inline void zeroBuffer(mono_float *buffer, int size)
Zeros a mono buffer (standard array).
Definition poly_utils.h:570
force_inline poly_float toFloat(poly_int integers)
Casts a poly_int to poly_float lane-by-lane.
Definition poly_utils.h:733
force_inline bool isTransposeQuantizeGlobal(int quantize)
Checks if the transpose quantize mask applies globally (over multiple octaves).
Definition poly_utils.h:964
force_inline void fillSnapBuffer(int transpose_quantize, float *snap_buffer)
Fills a buffer with snap offsets for a given quantize mask.
Definition poly_utils.h:928
force_inline int imax(int one, int two)
Returns the maximum of two integers.
Definition utils.h:205
force_inline poly_int roundToInt(poly_float value)
Rounds each lane to the nearest integer.
Definition poly_utils.h:792
force_inline poly_int shiftRight(poly_int integer)
Definition poly_utils.h:845
force_inline matrix getLinearInterpolationMatrix(poly_float t)
Creates a matrix for simple linear interpolation using scalar or vector t.
Definition poly_utils.h:242
force_inline poly_float max(poly_float left, poly_float right)
Returns the maximum of two poly_floats lane-by-lane.
Definition poly_utils.h:327
force_inline bool equal(poly_float left, poly_float right)
Checks if two poly_floats are equal lane-by-lane. Returns true if all lanes match.
Definition poly_utils.h:341
force_inline poly_float swapVoices(poly_float value)
Swaps the first half of the lanes with the second half.
Definition poly_utils.h:437
force_inline matrix getCatmullInterpolationMatrix(poly_float t)
Creates a Catmull-Rom interpolation matrix from a poly_float t.
Definition poly_utils.h:227
force_inline matrix getValueMatrix(const mono_float *buffer, poly_int indices)
Creates a matrix of 4 poly_float lanes from a single buffer at varying indices.
Definition poly_utils.h:262
force_inline poly_float snapTranspose(poly_float transpose, int quantize)
Snaps a MIDI transpose value to a quantization mask (e.g., scale degrees).
Definition poly_utils.h:908
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
force_inline poly_float midiNoteToFrequency(poly_float value)
Converts a MIDI note to a frequency (vectorized).
Definition poly_utils.h:123
force_inline poly_int toInt(poly_float floats)
Casts a poly_float to poly_int by truncation.
Definition poly_utils.h:748
force_inline poly_float sqrt(poly_float value)
Computes the square root of each element in a poly_float.
Definition poly_utils.h:169
force_inline poly_float interpolate(poly_float from, poly_float to, mono_float t)
Performs a linear interpolation between two poly_floats using a scalar t in [0..1].
Definition poly_utils.h:182
force_inline bool isTransposeSnapping(int quantize)
Checks if any snapping bits are set in the transpose quantize mask.
Definition poly_utils.h:971
force_inline poly_float swapStereo(poly_float value)
Swaps the left and right channels of a stereo poly_float.
Definition poly_utils.h:411
force_inline poly_float centsToRatio(poly_float value)
Converts semitone cents to a linear frequency ratio (vectorized).
Definition poly_utils.h:95
Contains classes and functions used within the Vital synthesizer framework.
constexpr int kDefaultSampleRate
Default sample rate in Hz.
Definition common.h:41
constexpr int kNotesPerOctave
Number of semitones per octave.
Definition common.h:51
poly_int poly_mask
Alias for clarity; used as a mask type in poly_float.
Definition poly_values.h:590
constexpr int kNumOscillatorWaveFrames
Number of wave frames in each oscillator’s wavetable.
Definition synth_constants.h:19
float mono_float
Definition common.h:33
force_inline poly_float at(int i) const
Returns the sample at index i from the source buffer.
Definition processor.h:141
const Output * source
The output from which this input reads samples.
Definition processor.h:134
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
const mono_float * to_buffers[poly_float::kSize]
Definition synth_oscillator.h:257
const poly_float * modulation_buffer
Buffer for FM/RM modulation values.
Definition synth_oscillator.h:251
const mono_float * from_buffers[poly_float::kSize]
Buffers used for crossfading from one wave to another.
Definition synth_oscillator.h:256
const poly_float * phase_inc_buffer
Phase increment buffer.
Definition synth_oscillator.h:252
const poly_int * phase_buffer
Phase buffer to add to 'phase' each sample.
Definition synth_oscillator.h:253
poly_int current_buffer_sample
Keeps track of fade progress.
Definition synth_oscillator.h:247
VoiceBlock()
Default constructor. Initializes all values to a safe default.
Definition synth_oscillator.cpp:504
SpectralMorph spectral_morph
The current spectral morph type.
Definition synth_oscillator.h:250
Struct holding all necessary data for the Wavetable, including multiple frames.
Definition wavetable.h:41
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline mask_simd_type vector_call equal(simd_type one, simd_type two)
Compares two SIMD float registers for equality, element-wise.
Definition poly_values.h:954
static force_inline poly_mask vector_call lessThan(poly_float one, poly_float two)
Definition poly_values.h:1105
static force_inline simd_type vector_call abs(simd_type value)
Computes the absolute value of each element in the SIMD float register.
Definition poly_values.h:935
static force_inline mask_simd_type vector_call notEqual(simd_type one, simd_type two)
Compares two SIMD float registers for non-equality, element-wise.
Definition poly_values.h:1003
static force_inline mask_simd_type vector_call greaterThan(simd_type one, simd_type two)
Compares two SIMD float registers, element-wise, for greater than.
Definition poly_values.h:971
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
force_inline void vector_call set(size_t index, uint32_t new_value) noexcept
Sets a specific element in the SIMD register.
Definition poly_values.h:453
static force_inline simd_type vector_call equal(simd_type one, simd_type two)
Compares two SIMD integer registers for equality, element-wise.
Definition poly_values.h:291
static force_inline poly_int vector_call lessThan(poly_int one, poly_int two)
Definition poly_values.h:378