18 static const int WIDTH = 13;
19 static const int WSHIFT = 6;
20 static const int OVERSAMPLE = 64;
22 static const float blep_table[WIDTH * OVERSAMPLE + 1];
25 double frequency_base = 440;
26 double frequency_factor = 1;
28 double freq_mod_octaves = 0;
30 double shape_base = 0;
31 double shape_mod = 1.0;
33 double pulse_width_base = 0.5;
34 double pulse_width_mod = 0.0;
42 double sub_width_base = 0.5;
43 double sub_width_mod = 0.0;
45 bool need_reset_voice_state;
56 double freq_factor = 1;
57 double left_factor = 1;
58 double right_factor = 0;
60 double master_phase = 0;
61 double slave_phase = 0;
63 double last_value = 0;
64 double current_level = 0;
73 State state = State::A;
87 const float f = future[future_pos++];
88 if (future_pos == WIDTH)
91 for (
int i = 0; i < WIDTH; i++)
93 future[i] = future[WIDTH + i];
94 future[WIDTH + i] = 0;
106 set_unison (1, 0, 0);
111 const bool randomize_phase = unison_voices.size() > 1;
113 for (
auto& voice : unison_voices)
125 reset_master (voice, 0);
130 reset_master (UnisonVoice& voice,
double master_phase)
132 voice.master_phase = master_phase;
133 need_reset_voice_state =
true;
136 set_unison (
size_t n_voices,
float detune,
float stereo)
138 const bool unison_voices_changed = unison_voices.size() != n_voices;
140 unison_voices.resize (n_voices);
142 bool left_channel =
true;
143 for (
size_t i = 0; i < unison_voices.size(); i++)
146 unison_voices[i].freq_factor = 1;
149 const float detune_cent = -detune / 2.0 + i /
float (n_voices - 1) * detune;
150 unison_voices[i].freq_factor =
pow (2, detune_cent / 1200);
153 double left_factor, right_factor;
154 bool odd_n_voices = unison_voices.size() & 1;
155 if (odd_n_voices && i == unison_voices.size() / 2)
157 left_factor = (1 - stereo) + stereo * 0.5;
158 right_factor = (1 - stereo) + stereo * 0.5;
160 else if (left_channel)
162 left_factor = 0.5 + stereo / 2;
163 right_factor = 0.5 - stereo / 2;
164 left_channel =
false;
168 left_factor = 0.5 - stereo / 2;
169 right_factor = 0.5 + stereo / 2;
180 const double norm =
sqrt (left_factor * left_factor + right_factor * right_factor) *
sqrt (n_voices / 2.0);
181 unison_voices[i].left_factor = left_factor / norm;
182 unison_voices[i].right_factor = right_factor / norm;
184 if (unison_voices_changed)
188 set_rate (
double rate)
193 const double leaky_ms = 10;
194 leaky_a =
pow (2.0, -1000.0 / (rate_ * leaky_ms));
202 estimate_dc (
double shape,
208 const double bound_a = sub_width * pulse_width;
209 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
210 const double bound_c = sub_width * pulse_width + (1 - sub_width);
211 const double bound_d = 1.0;
213 const double saw_slope = -4.0 * (shape + 1) * (1 - sub);
216 const double a2 = a1 + saw_slope * bound_a;
218 const double b1 = a2 + 2.0 * (shape * (1 - sub) - sub);
219 const double b2 = b1 + saw_slope * (bound_b - bound_a);
221 const double c1 = b2 + 2 * (1 - sub);
222 const double c2 = c1 + saw_slope * (bound_c - bound_b);
224 const double d1 = c2 + 2.0 * (shape * (1 - sub) + sub);
225 const double d2 = d1 + saw_slope * (bound_d - bound_c);
228 const double dc_base = (a1 + a2) / 2 * bound_a
229 + (b1 + b2) / 2 * (bound_b - bound_a)
230 + (c1 + c2) / 2 * (bound_c - bound_b)
231 + (d1 + d2) / 2 * (bound_d - bound_c);
234 if (sync_factor < 1.01)
238 const double sync_phase = sync_factor -
int (sync_factor);
240 double a_avg = (a1 + a2) / 2;
241 double b_avg = (b1 + b2) / 2;
242 double c_avg = (c1 + c2) / 2;
243 double d_avg = (d1 + d2) / 2;
245 if (sync_phase < bound_a)
247 const double frac = (bound_a - sync_phase) / bound_a;
248 const double sync_a2 = a1 * frac + a2 * (1 - frac);
250 a_avg = (1 - frac) * (a1 + sync_a2) / 2;
251 b_avg = c_avg = d_avg = 0;
253 else if (sync_phase < bound_b)
255 const double frac = (bound_b - sync_phase) / (bound_b - bound_a);
256 const double sync_b2 = b1 * frac + b2 * (1 - frac);
258 b_avg = (1 - frac) * (b1 + sync_b2) / 2;
261 else if (sync_phase < bound_c)
263 const double frac = (bound_c - sync_phase) / (bound_c - bound_b);
264 const double sync_c2 = c1 * frac + c2 * (1 - frac);
266 c_avg = (1 - frac) * (c1 + sync_c2) / 2;
271 const double frac = (bound_d - sync_phase) / (bound_d - bound_c);
272 const double sync_d2 = d1 * frac + d2 * (1 - frac);
274 d_avg = (1 - frac) * (d1 + sync_d2) / 2;
278 const double dc_sync = a_avg * bound_a
279 + b_avg * (bound_b - bound_a)
280 + c_avg * (bound_c - bound_b)
281 + d_avg * (bound_d - bound_c);
282 const double dc = (dc_base * (
int) sync_factor + dc_sync) / sync_factor;
288 reset_voice_state (
double shape,
294 const double bound_a = sub_width * pulse_width;
295 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
296 const double bound_c = sub_width * pulse_width + (1 - sub_width);
297 const double bound_d = 1.0;
299 const double saw_slope = -4.0 * (shape + 1) * (1 - sub);
302 const double a2 = a1 + saw_slope * bound_a;
304 const double b1 = a2 + 2.0 * (shape * (1 - sub) - sub);
305 const double b2 = b1 + saw_slope * (bound_b - bound_a);
307 const double c1 = b2 + 2 * (1 - sub);
308 const double c2 = c1 + saw_slope * (bound_c - bound_b);
310 const double d1 = c2 + 2.0 * (shape * (1 - sub) + sub);
311 const double d2 = d1 + saw_slope * (bound_d - bound_c);
314 const double dc_base = (a1 + a2) / 2 * bound_a
315 + (b1 + b2) / 2 * (bound_b - bound_a)
316 + (c1 + c2) / 2 * (bound_c - bound_b)
317 + (d1 + d2) / 2 * (bound_d - bound_c);
320 const double sync_phase = sync_factor -
int (sync_factor);
322 double a_avg = (a1 + a2) / 2;
323 double b_avg = (b1 + b2) / 2;
324 double c_avg = (c1 + c2) / 2;
325 double d_avg = (d1 + d2) / 2;
327 if (sync_phase < bound_a)
329 const double frac = (bound_a - sync_phase) / bound_a;
330 const double sync_a2 = a1 * frac + a2 * (1 - frac);
332 a_avg = (1 - frac) * (a1 + sync_a2) / 2;
333 b_avg = c_avg = d_avg = 0;
335 else if (sync_phase < bound_b)
337 const double frac = (bound_b - sync_phase) / (bound_b - bound_a);
338 const double sync_b2 = b1 * frac + b2 * (1 - frac);
340 b_avg = (1 - frac) * (b1 + sync_b2) / 2;
343 else if (sync_phase < bound_c)
345 const double frac = (bound_c - sync_phase) / (bound_c - bound_b);
346 const double sync_c2 = c1 * frac + c2 * (1 - frac);
348 c_avg = (1 - frac) * (c1 + sync_c2) / 2;
353 const double frac = (bound_d - sync_phase) / (bound_d - bound_c);
354 const double sync_d2 = d1 * frac + d2 * (1 - frac);
356 d_avg = (1 - frac) * (d1 + sync_d2) / 2;
360 double dc_sync = a_avg * bound_a
361 + b_avg * (bound_b - bound_a)
362 + c_avg * (bound_c - bound_b)
363 + d_avg * (bound_d - bound_c);
365 const double dc = (dc_base * (
int) sync_factor + dc_sync) / sync_factor;
367 for (
auto& voice : unison_voices)
369 double dest_phase = voice.master_phase;
373 dest_phase *= sync_factor;
374 dest_phase -= (
int) dest_phase;
376 voice.slave_phase = dest_phase;
379 if (dest_phase < bound_a)
381 double frac = (bound_a - dest_phase) / bound_a;
382 last_value = a1 * frac + a2 * (1 - frac);
384 voice.state = State::A;
386 else if (dest_phase < bound_b)
388 double frac = (bound_b - dest_phase) / (bound_b - bound_a);
389 last_value = b1 * frac + b2 * (1 - frac);
391 voice.state = State::B;
393 else if (dest_phase < bound_c)
395 double frac = (bound_c - dest_phase) / (bound_c - bound_b);
396 last_value = c1 * frac + c2 * (1 - frac);
398 voice.state = State::C;
402 double frac = (bound_d - dest_phase) / (bound_d - bound_c);
403 last_value = d1 * frac + d2 * (1 - frac);
405 voice.state = State::D;
407 voice.last_value = last_value - dc;
409 voice.current_level = last_value - 1;
413 insert_blep (UnisonVoice& voice,
double frac,
double weight)
415 int pos = frac * OVERSAMPLE;
416 const float inter_frac = frac * OVERSAMPLE - pos;
417 const float weight_left = (1 - inter_frac) * weight;
418 const float weight_right = inter_frac * weight;
421 pos =
std::min (pos, OVERSAMPLE - 1);
423 for (
int i = 0; i < WIDTH; i++)
425 voice.future[i + voice.future_pos] += blep_table[pos] * weight_left + blep_table[pos + 1] * weight_right;
431 insert_future_delta (UnisonVoice& voice,
double weight)
433 voice.future[voice.future_pos + WSHIFT] += weight;
437 clamp (
double d,
double min,
double max)
448 check_slave_before_master (UnisonVoice& voice,
double target_phase,
double sync_factor)
450 if (voice.slave_phase > target_phase)
452 if (voice.master_phase > 1)
454 const double slave_frac = (voice.slave_phase - target_phase) / sync_factor;
455 const double master_frac = voice.master_phase - 1;
457 return master_frac < slave_frac;
465 process_sample_stereo (
float *left_out,
float *right_out,
unsigned int n_values,
466 const float *freq_in =
nullptr,
467 const float *freq_mod_in =
nullptr,
468 const float *shape_mod_in =
nullptr,
469 const float *sub_mod_in =
nullptr,
470 const float *sync_mod_in =
nullptr,
471 const float *pulse_mod_in =
nullptr,
472 const float *sub_width_mod_in =
nullptr)
477 double master_freq = frequency_factor * frequency_base;
478 double pulse_width = clamp (pulse_width_base, 0.01, 0.99);
479 double sub = clamp (sub_base, 0.0, 1.0);
480 double sub_width = clamp (sub_width_base, 0.01, 0.99);
481 double shape = clamp (shape_base, -1.0, 1.0);
482 double sync_factor =
fast_exp2 (clamp (sync_base, 0.0, 60.0) / 12);
485 const int dc_steps =
max (
irintf (rate_ / 4000), 1);
487 for (
auto& voice : unison_voices)
489 const double master_freq2inc = 0.5 / rate_ * voice.freq_factor;
491 for (
unsigned int n = 0; n < n_values; n++)
496 double master_inc = master_freq * master_freq2inc;
498 master_inc *=
fast_exp2 (freq_mod_in[n] * freq_mod_octaves);
501 shape = clamp (shape_base + shape_mod * shape_mod_in[n], -1.0, 1.0);
504 sub = clamp (sub_base + sub_mod * sub_mod_in[n], 0.0, 1.0);
507 sync_factor =
fast_exp2 (clamp (sync_base + sync_mod * sync_mod_in[n], 0.0, 60.0) / 12);
510 pulse_width = clamp (pulse_width_base + pulse_width_mod * pulse_mod_in[n], 0.01, 0.99);
512 if (sub_width_mod_in)
513 sub_width = clamp (sub_width_base + sub_width_mod * sub_width_mod_in[n], 0.01, 0.99);
516 if (need_reset_voice_state)
518 reset_voice_state (shape, pulse_width, sub, sub_width, sync_factor);
519 need_reset_voice_state =
false;
522 const double slave_inc = master_inc * sync_factor;
523 const double saw_delta = -4.0 * slave_inc * (shape + 1) * (1 - sub);
525 voice.master_phase += master_inc;
526 voice.slave_phase += slave_inc;
531 state_changed =
false;
533 if (voice.state == State::A)
535 const double bound_a = sub_width * pulse_width;
537 if (check_slave_before_master (voice, bound_a, sync_factor))
539 const double slave_frac = (voice.slave_phase - bound_a) / slave_inc;
541 const double jump_a = 2.0 * (shape * (1 - sub) - sub);
542 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_a;
543 const double blep_height = jump_a + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
545 insert_blep (voice, slave_frac, blep_height);
546 voice.current_level += blep_height;
547 voice.state = State::B;
548 state_changed =
true;
551 if (voice.state == State::B)
553 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
555 if (check_slave_before_master (voice, bound_b, sync_factor))
557 const double slave_frac = (voice.slave_phase - bound_b) / slave_inc;
559 const double jump_ab = 2.0 * ((shape + 1) * (1 - sub) - sub);
560 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_b;
561 const double blep_height = jump_ab + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
563 insert_blep (voice, slave_frac, blep_height);
564 voice.current_level += blep_height;
565 voice.state = State::C;
566 state_changed =
true;
569 if (voice.state == State::C)
571 const double bound_c = sub_width * pulse_width + (1 - sub_width);
573 if (check_slave_before_master (voice, bound_c, sync_factor))
575 const double slave_frac = (voice.slave_phase - bound_c) / slave_inc;
577 const double jump_abc = 2.0 * (2 * shape + 1) * (1 - sub);
578 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_c;
579 const double blep_height = jump_abc + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
581 insert_blep (voice, slave_frac, blep_height);
582 voice.current_level += blep_height;
583 voice.state = State::D;
584 state_changed =
true;
587 if (voice.state == State::D)
589 if (check_slave_before_master (voice, 1, sync_factor))
591 voice.slave_phase -= 1;
593 const double slave_frac = voice.slave_phase / slave_inc;
595 voice.current_level += (1 - slave_frac) * saw_delta;
597 insert_blep (voice, slave_frac, -voice.current_level);
599 voice.current_level = saw_delta * slave_frac - saw_delta;
600 voice.state = State::A;
601 state_changed =
true;
604 if (!state_changed && voice.master_phase > 1)
606 voice.master_phase -= 1;
608 const double master_frac = voice.master_phase / master_inc;
610 const double new_slave_phase = voice.master_phase * sync_factor;
612 voice.current_level += (1 - master_frac) * saw_delta;
614 insert_blep (voice, master_frac, -voice.current_level);
616 voice.current_level = saw_delta * master_frac - saw_delta;
617 voice.slave_phase = new_slave_phase;
619 voice.state = State::A;
620 state_changed =
true;
623 while (state_changed);
625 if (voice.dc_steps > 0)
631 const double dc = estimate_dc (shape, pulse_width, sub, sub_width, sync_factor);
633 voice.dc_steps = dc_steps - 1;
634 voice.dc_delta = (voice.last_dc - dc) / dc_steps;
638 voice.current_level += saw_delta;
639 insert_future_delta (voice, saw_delta + voice.dc_delta);
642 double value = leaky_a * voice.last_value + voice.pop_future();
643 voice.last_value = value;
645 left_out[n] += value * voice.left_factor;
646 right_out[n] += value * voice.right_factor;