17 static const int WIDTH = 13;
18 static const int WSHIFT = 6;
19 static const int OVERSAMPLE = 64;
21 static const float blep_table[WIDTH * OVERSAMPLE + 1];
24 double frequency_base = 440;
25 double frequency_factor = 1;
27 double freq_mod_octaves = 0;
29 double shape_base = 0;
30 double shape_mod = 1.0;
32 double pulse_width_base = 0.5;
33 double pulse_width_mod = 0.0;
41 double sub_width_base = 0.5;
42 double sub_width_mod = 0.0;
44 bool need_reset_voice_state;
55 double freq_factor = 1;
56 double left_factor = 1;
57 double right_factor = 0;
59 double master_phase = 0;
60 double slave_phase = 0;
62 double last_value = 0;
63 double current_level = 0;
72 State state = State::A;
86 const float f = future[future_pos++];
87 if (future_pos == WIDTH)
90 for (
int i = 0; i < WIDTH; i++)
92 future[i] = future[WIDTH + i];
93 future[WIDTH + i] = 0;
105 set_unison (1, 0, 0);
110 const bool randomize_phase = unison_voices.size() > 1;
112 for (
auto& voice : unison_voices)
124 reset_master (voice, 0);
129 reset_master (UnisonVoice& voice,
double master_phase)
131 voice.master_phase = master_phase;
132 need_reset_voice_state =
true;
135 set_unison (
size_t n_voices,
float detune,
float stereo)
137 const bool unison_voices_changed = unison_voices.size() != n_voices;
139 unison_voices.resize (n_voices);
141 bool left_channel =
true;
142 for (
size_t i = 0; i < unison_voices.size(); i++)
145 unison_voices[i].freq_factor = 1;
148 const float detune_cent = -detune / 2.0 + i /
float (n_voices - 1) * detune;
149 unison_voices[i].freq_factor =
pow (2, detune_cent / 1200);
152 double left_factor, right_factor;
153 bool odd_n_voices = unison_voices.size() & 1;
154 if (odd_n_voices && i == unison_voices.size() / 2)
156 left_factor = (1 - stereo) + stereo * 0.5;
157 right_factor = (1 - stereo) + stereo * 0.5;
159 else if (left_channel)
161 left_factor = 0.5 + stereo / 2;
162 right_factor = 0.5 - stereo / 2;
163 left_channel =
false;
167 left_factor = 0.5 - stereo / 2;
168 right_factor = 0.5 + stereo / 2;
179 const double norm =
sqrt (left_factor * left_factor + right_factor * right_factor) *
sqrt (n_voices / 2.0);
180 unison_voices[i].left_factor = left_factor / norm;
181 unison_voices[i].right_factor = right_factor / norm;
183 if (unison_voices_changed)
187 set_rate (
double rate)
192 const double leaky_ms = 10;
193 leaky_a =
pow (2.0, -1000.0 / (rate_ * leaky_ms));
201 estimate_dc (
double shape,
207 const double bound_a = sub_width * pulse_width;
208 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
209 const double bound_c = sub_width * pulse_width + (1 - sub_width);
210 const double bound_d = 1.0;
212 const double saw_slope = -4.0 * (shape + 1) * (1 - sub);
215 const double a2 = a1 + saw_slope * bound_a;
217 const double b1 = a2 + 2.0 * (shape * (1 - sub) - sub);
218 const double b2 = b1 + saw_slope * (bound_b - bound_a);
220 const double c1 = b2 + 2 * (1 - sub);
221 const double c2 = c1 + saw_slope * (bound_c - bound_b);
223 const double d1 = c2 + 2.0 * (shape * (1 - sub) + sub);
224 const double d2 = d1 + saw_slope * (bound_d - bound_c);
227 const double dc_base = (a1 + a2) / 2 * bound_a
228 + (b1 + b2) / 2 * (bound_b - bound_a)
229 + (c1 + c2) / 2 * (bound_c - bound_b)
230 + (d1 + d2) / 2 * (bound_d - bound_c);
233 if (sync_factor < 1.01)
237 const double sync_phase = sync_factor -
int (sync_factor);
239 double a_avg = (a1 + a2) / 2;
240 double b_avg = (b1 + b2) / 2;
241 double c_avg = (c1 + c2) / 2;
242 double d_avg = (d1 + d2) / 2;
244 if (sync_phase < bound_a)
246 const double frac = (bound_a - sync_phase) / bound_a;
247 const double sync_a2 = a1 * frac + a2 * (1 - frac);
249 a_avg = (1 - frac) * (a1 + sync_a2) / 2;
250 b_avg = c_avg = d_avg = 0;
252 else if (sync_phase < bound_b)
254 const double frac = (bound_b - sync_phase) / (bound_b - bound_a);
255 const double sync_b2 = b1 * frac + b2 * (1 - frac);
257 b_avg = (1 - frac) * (b1 + sync_b2) / 2;
260 else if (sync_phase < bound_c)
262 const double frac = (bound_c - sync_phase) / (bound_c - bound_b);
263 const double sync_c2 = c1 * frac + c2 * (1 - frac);
265 c_avg = (1 - frac) * (c1 + sync_c2) / 2;
270 const double frac = (bound_d - sync_phase) / (bound_d - bound_c);
271 const double sync_d2 = d1 * frac + d2 * (1 - frac);
273 d_avg = (1 - frac) * (d1 + sync_d2) / 2;
277 const double dc_sync = a_avg * bound_a
278 + b_avg * (bound_b - bound_a)
279 + c_avg * (bound_c - bound_b)
280 + d_avg * (bound_d - bound_c);
281 const double dc = (dc_base * (
int) sync_factor + dc_sync) / sync_factor;
287 reset_voice_state (
double shape,
293 const double bound_a = sub_width * pulse_width;
294 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
295 const double bound_c = sub_width * pulse_width + (1 - sub_width);
296 const double bound_d = 1.0;
298 const double saw_slope = -4.0 * (shape + 1) * (1 - sub);
301 const double a2 = a1 + saw_slope * bound_a;
303 const double b1 = a2 + 2.0 * (shape * (1 - sub) - sub);
304 const double b2 = b1 + saw_slope * (bound_b - bound_a);
306 const double c1 = b2 + 2 * (1 - sub);
307 const double c2 = c1 + saw_slope * (bound_c - bound_b);
309 const double d1 = c2 + 2.0 * (shape * (1 - sub) + sub);
310 const double d2 = d1 + saw_slope * (bound_d - bound_c);
313 const double dc_base = (a1 + a2) / 2 * bound_a
314 + (b1 + b2) / 2 * (bound_b - bound_a)
315 + (c1 + c2) / 2 * (bound_c - bound_b)
316 + (d1 + d2) / 2 * (bound_d - bound_c);
319 const double sync_phase = sync_factor -
int (sync_factor);
321 double a_avg = (a1 + a2) / 2;
322 double b_avg = (b1 + b2) / 2;
323 double c_avg = (c1 + c2) / 2;
324 double d_avg = (d1 + d2) / 2;
326 if (sync_phase < bound_a)
328 const double frac = (bound_a - sync_phase) / bound_a;
329 const double sync_a2 = a1 * frac + a2 * (1 - frac);
331 a_avg = (1 - frac) * (a1 + sync_a2) / 2;
332 b_avg = c_avg = d_avg = 0;
334 else if (sync_phase < bound_b)
336 const double frac = (bound_b - sync_phase) / (bound_b - bound_a);
337 const double sync_b2 = b1 * frac + b2 * (1 - frac);
339 b_avg = (1 - frac) * (b1 + sync_b2) / 2;
342 else if (sync_phase < bound_c)
344 const double frac = (bound_c - sync_phase) / (bound_c - bound_b);
345 const double sync_c2 = c1 * frac + c2 * (1 - frac);
347 c_avg = (1 - frac) * (c1 + sync_c2) / 2;
352 const double frac = (bound_d - sync_phase) / (bound_d - bound_c);
353 const double sync_d2 = d1 * frac + d2 * (1 - frac);
355 d_avg = (1 - frac) * (d1 + sync_d2) / 2;
359 double dc_sync = a_avg * bound_a
360 + b_avg * (bound_b - bound_a)
361 + c_avg * (bound_c - bound_b)
362 + d_avg * (bound_d - bound_c);
364 const double dc = (dc_base * (
int) sync_factor + dc_sync) / sync_factor;
366 for (
auto& voice : unison_voices)
368 double dest_phase = voice.master_phase;
372 dest_phase *= sync_factor;
373 dest_phase -= (
int) dest_phase;
375 voice.slave_phase = dest_phase;
378 if (dest_phase < bound_a)
380 double frac = (bound_a - dest_phase) / bound_a;
381 last_value = a1 * frac + a2 * (1 - frac);
383 voice.state = State::A;
385 else if (dest_phase < bound_b)
387 double frac = (bound_b - dest_phase) / (bound_b - bound_a);
388 last_value = b1 * frac + b2 * (1 - frac);
390 voice.state = State::B;
392 else if (dest_phase < bound_c)
394 double frac = (bound_c - dest_phase) / (bound_c - bound_b);
395 last_value = c1 * frac + c2 * (1 - frac);
397 voice.state = State::C;
401 double frac = (bound_d - dest_phase) / (bound_d - bound_c);
402 last_value = d1 * frac + d2 * (1 - frac);
404 voice.state = State::D;
406 voice.last_value = last_value - dc;
408 voice.current_level = last_value - 1;
412 insert_blep (UnisonVoice& voice,
double frac,
double weight)
414 int pos = frac * OVERSAMPLE;
415 const float inter_frac = frac * OVERSAMPLE - pos;
416 const float weight_left = (1 - inter_frac) * weight;
417 const float weight_right = inter_frac * weight;
420 pos =
std::min (pos, OVERSAMPLE - 1);
422 for (
int i = 0; i < WIDTH; i++)
424 voice.future[i + voice.future_pos] += blep_table[pos] * weight_left + blep_table[pos + 1] * weight_right;
430 insert_future_delta (UnisonVoice& voice,
double weight)
432 voice.future[voice.future_pos + WSHIFT] += weight;
436 clamp (
double d,
double min,
double max)
447 check_slave_before_master (UnisonVoice& voice,
double target_phase,
double sync_factor)
449 if (voice.slave_phase > target_phase)
451 if (voice.master_phase > 1)
453 const double slave_frac = (voice.slave_phase - target_phase) / sync_factor;
454 const double master_frac = voice.master_phase - 1;
456 return master_frac < slave_frac;
464 process_sample_stereo (
float *left_out,
float *right_out,
unsigned int n_values,
465 const float *freq_in =
nullptr,
466 const float *freq_mod_in =
nullptr,
467 const float *shape_mod_in =
nullptr,
468 const float *sub_mod_in =
nullptr,
469 const float *sync_mod_in =
nullptr,
470 const float *pulse_mod_in =
nullptr,
471 const float *sub_width_mod_in =
nullptr)
476 double master_freq = frequency_factor * frequency_base;
477 double pulse_width = clamp (pulse_width_base, 0.01, 0.99);
478 double sub = clamp (sub_base, 0.0, 1.0);
479 double sub_width = clamp (sub_width_base, 0.01, 0.99);
480 double shape = clamp (shape_base, -1.0, 1.0);
481 double sync_factor =
fast_exp2 (clamp (sync_base, 0.0, 60.0) / 12);
484 const int dc_steps =
max (
irintf (rate_ / 4000), 1);
486 for (
auto& voice : unison_voices)
488 const double master_freq2inc = 0.5 / rate_ * voice.freq_factor;
490 for (
unsigned int n = 0; n < n_values; n++)
495 double master_inc = master_freq * master_freq2inc;
497 master_inc *=
fast_exp2 (freq_mod_in[n] * freq_mod_octaves);
500 shape = clamp (shape_base + shape_mod * shape_mod_in[n], -1.0, 1.0);
503 sub = clamp (sub_base + sub_mod * sub_mod_in[n], 0.0, 1.0);
506 sync_factor =
fast_exp2 (clamp (sync_base + sync_mod * sync_mod_in[n], 0.0, 60.0) / 12);
509 pulse_width = clamp (pulse_width_base + pulse_width_mod * pulse_mod_in[n], 0.01, 0.99);
511 if (sub_width_mod_in)
512 sub_width = clamp (sub_width_base + sub_width_mod * sub_width_mod_in[n], 0.01, 0.99);
515 if (need_reset_voice_state)
517 reset_voice_state (shape, pulse_width, sub, sub_width, sync_factor);
518 need_reset_voice_state =
false;
521 const double slave_inc = master_inc * sync_factor;
522 const double saw_delta = -4.0 * slave_inc * (shape + 1) * (1 - sub);
524 voice.master_phase += master_inc;
525 voice.slave_phase += slave_inc;
530 state_changed =
false;
532 if (voice.state == State::A)
534 const double bound_a = sub_width * pulse_width;
536 if (check_slave_before_master (voice, bound_a, sync_factor))
538 const double slave_frac = (voice.slave_phase - bound_a) / slave_inc;
540 const double jump_a = 2.0 * (shape * (1 - sub) - sub);
541 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_a;
542 const double blep_height = jump_a + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
544 insert_blep (voice, slave_frac, blep_height);
545 voice.current_level += blep_height;
546 voice.state = State::B;
547 state_changed =
true;
550 if (voice.state == State::B)
552 const double bound_b = 2 * sub_width * pulse_width + 1 - sub_width - pulse_width;
554 if (check_slave_before_master (voice, bound_b, sync_factor))
556 const double slave_frac = (voice.slave_phase - bound_b) / slave_inc;
558 const double jump_ab = 2.0 * ((shape + 1) * (1 - sub) - sub);
559 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_b;
560 const double blep_height = jump_ab + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
562 insert_blep (voice, slave_frac, blep_height);
563 voice.current_level += blep_height;
564 voice.state = State::C;
565 state_changed =
true;
568 if (voice.state == State::C)
570 const double bound_c = sub_width * pulse_width + (1 - sub_width);
572 if (check_slave_before_master (voice, bound_c, sync_factor))
574 const double slave_frac = (voice.slave_phase - bound_c) / slave_inc;
576 const double jump_abc = 2.0 * (2 * shape + 1) * (1 - sub);
577 const double saw = -4.0 * (shape + 1) * (1 - sub) * bound_c;
578 const double blep_height = jump_abc + saw - (voice.current_level + (1 - slave_frac) * saw_delta);
580 insert_blep (voice, slave_frac, blep_height);
581 voice.current_level += blep_height;
582 voice.state = State::D;
583 state_changed =
true;
586 if (voice.state == State::D)
588 if (check_slave_before_master (voice, 1, sync_factor))
590 voice.slave_phase -= 1;
592 const double slave_frac = voice.slave_phase / slave_inc;
594 voice.current_level += (1 - slave_frac) * saw_delta;
596 insert_blep (voice, slave_frac, -voice.current_level);
598 voice.current_level = saw_delta * slave_frac - saw_delta;
599 voice.state = State::A;
600 state_changed =
true;
603 if (!state_changed && voice.master_phase > 1)
605 voice.master_phase -= 1;
607 const double master_frac = voice.master_phase / master_inc;
609 const double new_slave_phase = voice.master_phase * sync_factor;
611 voice.current_level += (1 - master_frac) * saw_delta;
613 insert_blep (voice, master_frac, -voice.current_level);
615 voice.current_level = saw_delta * master_frac - saw_delta;
616 voice.slave_phase = new_slave_phase;
618 voice.state = State::A;
619 state_changed =
true;
622 while (state_changed);
624 if (voice.dc_steps > 0)
630 const double dc = estimate_dc (shape, pulse_width, sub, sub_width, sync_factor);
632 voice.dc_steps = dc_steps - 1;
633 voice.dc_delta = (voice.last_dc - dc) / dc_steps;
637 voice.current_level += saw_delta;
638 insert_future_delta (voice, saw_delta + voice.dc_delta);
641 double value = leaky_a * voice.last_value + voice.pop_future();
642 voice.last_value = value;
644 left_out[n] += value * voice.left_factor;
645 right_out[n] += value * voice.right_factor;