4 * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
28 #include "synthesizer.h"
30 #include "transportque.inc"
38 REGISTER_PLUGIN(Synth)
43 Synth::Synth(PluginServer *server)
44 : PluginAClient(server)
58 NEW_WINDOW_MACRO(Synth, SynthWindow);
60 const char* Synth::plugin_title() { return N_("Synthesizer"); }
61 int Synth::is_realtime() { return 1; }
62 int Synth::is_synthesis() { return 1; }
73 LOAD_CONFIGURATION_MACRO(Synth, SynthConfig)
80 void Synth::read_data(KeyFrame *keyframe)
83 char string[BCTEXTLEN];
84 // cause htal file to read directly from text
85 input.set_shared_input(keyframe->xbuf);
87 //printf("Synth::read_data %s\n", keyframe->get_data());
88 int result = 0, current_osc = 0;
91 result = input.read_tag();
95 if(input.tag.title_is("SYNTH"))
97 config.wetness = input.tag.get_property("WETNESS", config.wetness);
101 window_w = input.tag.get_property("WINDOW_W", window_w);
102 window_h = input.tag.get_property("WINDOW_H", window_h);
104 config.momentary_notes = input.tag.get_property("MOMENTARY_NOTES", config.momentary_notes);
106 //printf("Synth::read_data %d %d %d\n", __LINE__, window_w, window_h);
107 for(int i = 0; i < MAX_FREQS; i++)
109 sprintf(string, "BASEFREQ_%d", i);
110 config.base_freq[i] = input.tag.get_property(string, (double)0);
113 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
114 // int total_oscillators = input.tag.get_property("OSCILLATORS", 0);
117 if(input.tag.title_is("OSCILLATOR"))
119 if(current_osc >= config.oscillator_config.total)
120 config.oscillator_config.append(new SynthOscillatorConfig(current_osc));
122 config.oscillator_config.values[current_osc]->read_data(&input);
128 while(config.oscillator_config.total > current_osc)
129 config.oscillator_config.remove_object();
132 void Synth::save_data(KeyFrame *keyframe)
135 char string[BCTEXTLEN];
137 // cause htal file to store data directly in text
138 output.set_shared_output(keyframe->xbuf);
140 output.tag.set_title("SYNTH");
141 output.tag.set_property("WETNESS", config.wetness);
142 output.tag.set_property("WINDOW_W", window_w);
143 output.tag.set_property("WINDOW_H", window_h);
144 output.tag.set_property("MOMENTARY_NOTES", config.momentary_notes);
146 for(int i = 0; i < MAX_FREQS; i++)
148 // if(!EQUIV(config.base_freq[i], 0))
150 sprintf(string, "BASEFREQ_%d", i);
151 output.tag.set_property(string, config.base_freq[i]);
152 //printf("Synth::save_data %d %s\n", __LINE__, string);
156 output.tag.set_property("WAVEFUNCTION", config.wavefunction);
157 output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
159 output.append_newline();
161 for(int i = 0; i < config.oscillator_config.total; i++)
163 config.oscillator_config.values[i]->save_data(&output);
166 output.terminate_string();
167 //printf("Synth::save_data %d %s\n", __LINE__, output.string);
168 // data is now in *text
173 void Synth::update_gui()
177 if(load_configuration())
179 thread->window->lock_window();
180 ((SynthWindow*)thread->window)->update_gui();
181 thread->window->unlock_window();
187 void Synth::add_oscillator()
189 if(config.oscillator_config.total > MAX_OSCILLATORS) return;
191 config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
194 void Synth::delete_oscillator()
196 if(config.oscillator_config.total)
198 config.oscillator_config.remove_object();
203 double Synth::get_total_power()
207 if(config.wavefunction == DC) return 1.0;
209 for(int i = 0; i < config.oscillator_config.total; i++)
211 result += db.fromdb(config.oscillator_config.values[i]->level);
214 if(result == 0) result = 1; // prevent division by 0
219 double Synth::solve_eqn(double *output,
222 double normalize_constant,
225 SynthOscillatorConfig *config =
226 this->config.oscillator_config.values[oscillator];
227 if(config->level <= INFINITYGAIN) return 0;
229 double power = this->db.fromdb(config->level) * normalize_constant;
230 // Period of fundamental frequency in samples
231 double orig_period = (double)get_samplerate() /
233 // Starting sample in waveform
234 double x = waveform_sample;
235 //printf("Synth::solve_eqn %d %f\n", __LINE__, config->phase);
236 double phase_offset = config->phase * orig_period;
237 // Period of current oscillator
238 double period = orig_period / config->freq_factor;
241 if(get_direction() == PLAY_REVERSE) step = -1;
243 switch(this->config.wavefunction)
246 for(sample = 0; sample < length; sample++)
248 output[sample] += power;
253 for(sample = 0; sample < length; sample++)
255 output[sample] += sin((x + phase_offset) /
256 period * 2 * M_PI) * power;
262 for(sample = 0; sample < length; sample++)
264 output[sample] += function_sawtooth((x + phase_offset) /
271 for(sample = 0; sample < length; sample++)
273 output[sample] += function_square((x + phase_offset) /
280 for(sample = 0; sample < length; sample++)
282 output[sample] += function_triangle((x + phase_offset) /
289 for(sample = 0; sample < length; sample++)
291 output[sample] += function_pulse((x + phase_offset) /
298 for(sample = 0; sample < length; sample++)
300 output[sample] += function_noise() * power;
307 double Synth::get_point(float x, double normalize_constant)
310 for(int i = 0; i < config.oscillator_config.total; i++)
311 result += get_oscillator_point(x, normalize_constant, i);
316 double Synth::get_oscillator_point(float x,
317 double normalize_constant,
320 SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
321 double power = db.fromdb(config->level) * normalize_constant;
322 switch(this->config.wavefunction)
328 return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
331 return function_sawtooth((x + config->phase) * config->freq_factor) * power;
334 return function_square((x + config->phase) * config->freq_factor) * power;
337 return function_triangle((x + config->phase) * config->freq_factor) * power;
340 return function_pulse((x + config->phase) * config->freq_factor) * power;
343 return function_noise() * power;
349 double Synth::function_square(double x)
351 x -= (int)x; // only fraction counts
352 return (x < .5) ? -1 : 1;
355 double Synth::function_pulse(double x)
357 x -= (int)x; // only fraction counts
358 return (x < .5) ? 0 : 1;
361 double Synth::function_noise()
363 return (double)(rand() % 65536 - 32768) / 32768;
366 double Synth::function_sawtooth(double x)
372 double Synth::function_triangle(double x)
375 return (x < .5) ? 1 - x * 4 : -3 + x * 4;
378 int Synth::process_realtime(int64_t size,
382 // sample relative to start of plugin
383 waveform_sample = get_source_position();
385 need_reconfigure |= load_configuration();
386 if(need_reconfigure) reconfigure();
388 double wetness = DB::fromdb(config.wetness);
389 if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
392 double *output_samples = output_ptr->get_data();
393 double *input_samples = input_ptr->get_data();
394 for(int j = 0; j < size; j++)
395 output_samples[j] = input_samples[j] * wetness;
397 // Overlay each frequency
398 for(int j = 0; j < MAX_FREQS; j++)
400 if(!EQUIV(config.base_freq[j], 0))
407 input_ptr->get_data(),
408 output_ptr->get_data());
409 //printf("Synth::process_realtime 2\n");
413 // waveform_sample += size;
417 int Synth::overlay_synth(double freq,
422 double normalize_constant = 1.0 / get_total_power();
423 for(int i = 0; i < config.oscillator_config.total; i++)
424 solve_eqn(output, length, freq, normalize_constant, i);
428 void Synth::reconfigure()
430 need_reconfigure = 0;
431 // waveform_sample = 0;
434 int Synth::freq_exists(double freq)
436 for(int i = 0; i < MAX_FREQS; i++)
439 // printf("Synth::freq_exists %d %d %f %f\n",
443 // config.base_freq[i]);
444 if(fabs(freq - config.base_freq[i]) < 1.0)
451 void Synth::new_freq(double freq)
454 for(int i = 0; i < MAX_FREQS; i++)
456 if(EQUIV(config.base_freq[i], freq)) return;
459 for(int i = 0; i < MAX_FREQS; i++)
461 if(EQUIV(config.base_freq[i], 0))
463 config.base_freq[i] = freq;
464 //printf("Synth::new_freq %d\n", __LINE__);
470 void Synth::delete_freq(double freq)
472 for(int i = 0; i < MAX_FREQS; i++)
474 if(EQUIV(config.base_freq[i], freq))
476 //printf("Synth::delete_freq %d\n", __LINE__);
477 // Shift frequencies back
478 for(int j = i; j < MAX_FREQS - 1; j++)
480 config.base_freq[j] = config.base_freq[j + 1];
482 config.base_freq[MAX_FREQS - 1] = 0;
489 void Synth::delete_freqs()
491 for(int i = 0; i < MAX_FREQS; i++)
492 config.base_freq[i] = 0;
496 SynthWindow::SynthWindow(Synth *synth)
497 : PluginClientWindow(synth, synth->window_w, synth->window_h,
507 bzero(notes, sizeof(SynthNote*) * TOTALNOTES);
511 SynthWindow::~SynthWindow()
521 static const char *keyboard_map[] =
523 "q", "2", "w", "3", "e", "r", "5", "t", "6", "y", "7", "u",
524 "z", "s", "x", "d", "c", "v", "g", "b", "h", "n", "j", "m"
527 void SynthWindow::create_objects()
529 int margin = client->get_theme()->widget_border;
532 add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
534 BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
535 menu->add_menu(levelmenu = new BC_Menu(_("Level")));
536 menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
537 menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
539 levelmenu->add_item(new SynthLevelInvert(synth));
540 levelmenu->add_item(new SynthLevelMax(synth));
541 levelmenu->add_item(new SynthLevelRandom(synth));
542 levelmenu->add_item(new SynthLevelSine(synth));
543 levelmenu->add_item(new SynthLevelSlope(synth));
544 levelmenu->add_item(new SynthLevelZero(synth));
546 phasemenu->add_item(new SynthPhaseInvert(synth));
547 phasemenu->add_item(new SynthPhaseRandom(synth));
548 phasemenu->add_item(new SynthPhaseSine(synth));
549 phasemenu->add_item(new SynthPhaseZero(synth));
551 harmonicmenu->add_item(new SynthFreqMin(synth));
552 harmonicmenu->add_item(new SynthFreqEnum(synth));
553 harmonicmenu->add_item(new SynthFreqEven(synth));
554 harmonicmenu->add_item(new SynthFreqFibonacci(synth));
555 harmonicmenu->add_item(new SynthFreqOdd(synth));
556 harmonicmenu->add_item(new SynthFreqPrime(synth));
558 int xs10 = xS(10), xs20 = xS(20), xs50 = xS(50), xs70 = xS(70), xs75 = xS(75), xs240 = xS(240), xs265 = xS(265);
559 int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40), ys220 = yS(220);
560 int x = xs10, y = ys30;
562 add_subwindow(new BC_Title(x, y, _("Waveform")));
564 add_subwindow(new BC_Title(x, y, _("Wave Function")));
567 add_subwindow(canvas = new SynthCanvas(synth, this, x, y, xS(230), yS(160)));
571 char string[BCTEXTLEN];
572 waveform_to_text(string, synth->config.wavefunction);
574 add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
575 waveform->create_objects();
577 int x1 = x + waveform->get_w() + xs50;
580 add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
582 add_subwindow(base_freq = new SynthBaseFreq(synth, this, x, y));
583 base_freq->update((float)synth->config.base_freq[0]);
584 x += base_freq->get_w() + synth->get_theme()->widget_border;
585 add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - ys10));
586 base_freq->freq_pot = freqpot;
587 freqpot->freq_text = base_freq;
588 x -= base_freq->get_w() + synth->get_theme()->widget_border;
590 add_subwindow(new BC_Title(x, y, _("Wetness:")));
591 add_subwindow(wetness = new SynthWetness(synth, x + xs70, y - ys10));
594 add_subwindow(new SynthClear(synth, x, y));
599 add_subwindow(new BC_Title(x, y, _("Level")));
601 add_subwindow(new BC_Title(x, y, _("Phase")));
603 add_subwindow(new BC_Title(x, y, _("Harmonic")));
608 add_subwindow(osc_subwindow = new BC_SubWindow(x, y, xs265, get_h() - y));
610 add_subwindow(osc_scroll = new OscScroll(synth, this, x, y, get_h() - y));
614 add_subwindow(new SynthAddOsc(synth, this, x, y));
616 add_subwindow(new SynthDelOsc(synth, this, x, y));
621 #include "white_up_png.h"
622 #include "white_hi_png.h"
623 #include "white_dn_png.h"
624 #include "white_checked_png.h"
625 #include "white_checkedhi_png.h"
626 #include "black_up_png.h"
627 #include "black_hi_png.h"
628 #include "black_dn_png.h"
629 #include "black_checked_png.h"
630 #include "black_checkedhi_png.h"
631 white_key[0] = new VFramePng(white_up_png);
632 white_key[1] = new VFramePng(white_hi_png);
633 white_key[2] = new VFramePng(white_checked_png);
634 white_key[3] = new VFramePng(white_dn_png);
635 white_key[4] = new VFramePng(white_checkedhi_png);
636 black_key[0] = new VFramePng(black_up_png);
637 black_key[1] = new VFramePng(black_hi_png);
638 black_key[2] = new VFramePng(black_checked_png);
639 black_key[3] = new VFramePng(black_dn_png);
640 black_key[4] = new VFramePng(black_checkedhi_png);
643 add_subwindow(note_subwindow = new BC_SubWindow(x1+xS(20),
644 y, get_w() - (x1+xS(20)),
645 white_key[0]->get_h() + margin +
646 get_text_height(MEDIUMFONT) + margin +
647 get_text_height(MEDIUMFONT) + margin));
648 add_subwindow(note_scroll = new NoteScroll(synth, this, x1,
649 note_subwindow->get_y() + note_subwindow->get_h(),
650 note_subwindow->get_w()));
652 add_subwindow(momentary = new SynthMomentary(this, x1,
653 note_scroll->get_y() + note_scroll->get_h() + margin,
654 _("Momentary notes")));
657 add_subwindow(note_instructions = new BC_Title( x1,
658 momentary->get_y() + momentary->get_h() + margin,
659 _("Ctrl or Shift to select multiple notes.")));
662 update_oscillators();
668 int SynthWindow::keypress_event()
670 if(ctrl_down() && get_keypress() == 'w')
675 return context_help_check_and_show();
678 int SynthWindow::resize_event(int w, int h)
680 clear_box(0, 0, w, h);
681 osc_subwindow->reposition_window(osc_subwindow->get_x(),
682 osc_subwindow->get_y(),
683 osc_subwindow->get_w(),
684 h - osc_subwindow->get_y());
685 osc_subwindow->clear_box(0, 0, osc_subwindow->get_w(), osc_subwindow->get_h());
686 osc_scroll->reposition_window(osc_scroll->get_x(),
688 h - osc_scroll->get_y());
689 note_subwindow->reposition_window(note_subwindow->get_x(),
690 note_subwindow->get_y(),
691 w - note_subwindow->get_x(),
692 note_subwindow->get_h());
693 note_scroll->reposition_window(note_scroll->get_x(),
694 note_scroll->get_y(),
695 w - note_scroll->get_x());
696 note_scroll->update_length(white_key[0]->get_w() * TOTALNOTES * 7 / 12 +
697 white_key[0]->get_w(),
698 note_scroll->get_position(),
699 note_subwindow->get_w(),
704 update_oscillators();
710 void SynthWindow::update_gui()
712 char string[BCTEXTLEN];
713 freqpot->update((int)synth->config.base_freq[0]);
714 base_freq->update((float)synth->config.base_freq[0]);
715 wetness->update(synth->config.wetness);
716 waveform_to_text(string, synth->config.wavefunction);
717 waveform->set_text(string);
718 momentary->update(synth->config.momentary_notes);
721 update_oscillators();
723 update_note_selection();
727 void SynthWindow::update_scrollbar()
729 osc_scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
730 osc_scroll->get_position(),
731 osc_subwindow->get_h(),
736 void SynthWindow::update_whitekey(int number,
743 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
744 white_key, number, x, y));
745 if(number >= FIRST_TITLE && number < LAST_TITLE)
746 note_subwindow->add_subwindow(
747 note_titles[(*current_title)++] = new BC_Title(
748 x + text_white_margin, y2,
749 keyboard_map[number - FIRST_TITLE]));
750 //printf("SynthWindow::update_whitekey %d\n", __LINE__);
754 notes[number]->reposition_window(x, y);
755 if(number >= FIRST_TITLE && number < LAST_TITLE)
756 note_titles[(*current_title)++]->reposition_window(x + text_white_margin,
762 void SynthWindow::update_blackkey(int number,
769 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
770 black_key, number, x, y));
771 if(number >= FIRST_TITLE && number < LAST_TITLE)
772 note_subwindow->add_subwindow(
773 note_titles[(*current_title)++] = new BC_Title(x + text_black_margin,
774 y1, keyboard_map[number - FIRST_TITLE]));
778 notes[number]->reposition_window(x, y);
779 if(number >= FIRST_TITLE && number < LAST_TITLE)
780 note_titles[(*current_title)++]->reposition_window(x + text_black_margin, y1);
784 void SynthWindow::update_notes()
786 //int octave_w = white_key[0]->get_w() * 7;
787 int white_w = white_key[0]->get_w();
788 int black_w = black_key[0]->get_w();
789 int white_w1 = white_w - black_w / 2 - 2;
790 int white_w2 = white_w / 2;
791 int white_w3 = white_w * 2 / 3;
792 int x = 0, y = 0, ys5 = yS(5);
793 y1 = y + white_key[0]->get_h() + ys5;
794 y2 = y1 + get_text_height(MEDIUMFONT) + ys5;
795 y3 = y2 + get_text_height(MEDIUMFONT) + ys5;
796 text_black_margin = black_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
797 text_white_margin = white_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
800 //printf("SynthWindow::update_notes %d\n", __LINE__);
801 note_subwindow->clear_box(0, 0, get_w(), get_h());
803 note_subwindow->set_color(get_resources()->default_text_color);
806 // To get the stacking order:
807 // pass 0 is white keys
808 // pass 1 is black keys
809 int current_title = 0;
810 for(int pass = 0; pass < 2; pass++)
812 x = -note_scroll->get_position();
814 for(int i = 0; i < TOTALNOTES; i++)
816 int octave_note = i % 12;
823 update_whitekey(i, ¤t_title, x, y);
829 update_whitekey(i, ¤t_title, x, y);
835 update_whitekey(i, ¤t_title, x, y);
839 update_whitekey(i, ¤t_title, x, y);
845 update_whitekey(i, ¤t_title, x, y);
851 update_whitekey(i, ¤t_title, x, y);
857 update_whitekey(i, ¤t_title, x, y);
868 update_blackkey(i, ¤t_title, x + white_w2, y);
872 update_blackkey(i, ¤t_title, x + white_w3, y);
879 update_blackkey(i, ¤t_title, x + white_w2, y);
883 update_blackkey(i, ¤t_title, x + white_w1, y);
887 update_blackkey(i, ¤t_title, x + white_w3, y);
899 void SynthWindow::update_note_selection()
901 for(int i = 0; i < TOTALNOTES; i++)
904 for(int j = 0; j < MAX_FREQS; j++)
906 if(synth->freq_exists(keyboard_freqs[notes[i]->number]))
915 notes[i]->set_value(1);
918 notes[i]->set_value(0);
923 void SynthWindow::update_oscillators()
925 int i, y = -osc_scroll->get_position();
929 // Add new oscillators
931 i < synth->config.oscillator_config.total;
935 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
937 if(oscillators.total <= i)
939 oscillators.append(gui = new SynthOscGUI(this, i));
940 gui->create_objects(y);
944 gui = oscillators.values[i];
946 gui->title->reposition_window(gui->title->get_x(), y + yS(15));
948 gui->level->reposition_window(gui->level->get_x(), y);
949 gui->level->update(config->level);
951 gui->phase->reposition_window(gui->phase->get_x(), y);
952 gui->phase->update((int64_t)(config->phase * 360));
954 gui->freq->reposition_window(gui->freq->get_x(), y);
955 gui->freq->update(config->freq_factor);
957 y += OSCILLATORHEIGHT;
960 // Delete old oscillators
962 i < oscillators.total;
964 oscillators.remove_object();
968 int SynthWindow::waveform_to_text(char *text, int waveform)
972 case DC: sprintf(text, _("DC")); break;
973 case SINE: sprintf(text, _("Sine")); break;
974 case SAWTOOTH: sprintf(text, _("Sawtooth")); break;
975 case SQUARE: sprintf(text, _("Square")); break;
976 case TRIANGLE: sprintf(text, _("Triangle")); break;
977 case PULSE: sprintf(text, _("Pulse")); break;
978 case NOISE: sprintf(text, _("Noise")); break;
984 SynthMomentary::SynthMomentary(SynthWindow *window, int x, int y, char *text)
985 : BC_CheckBox(x, y, window->synth->config.momentary_notes, text)
987 this->window = window;
990 int SynthMomentary::handle_event()
992 window->synth->config.momentary_notes = get_value();
993 window->synth->send_configure_change();
1000 SynthNote::SynthNote(SynthWindow *window, VFrame **images, int number, int x, int y)
1001 : BC_Toggle(x, y, images, window->synth->freq_exists(keyboard_freqs[number]))
1003 this->window = window;
1004 this->number = number;
1010 void SynthNote::start_note()
1012 if(window->synth->config.momentary_notes) note_on = 1;
1014 //printf("SynthNote::start_note %d %d\n", __LINE__, ctrl_down());
1015 if(window->synth->config.momentary_notes || (!ctrl_down() && !shift_down()))
1017 // Kill all frequencies
1018 window->synth->delete_freqs();
1021 window->synth->new_freq(keyboard_freqs[number]);
1022 window->base_freq->update((float)window->synth->config.base_freq[0]);
1023 //printf("SynthNote::start_note %d %f\n", __LINE__, window->synth->config.base_freq[0]);
1024 window->freqpot->update(window->synth->config.base_freq[0]);
1025 window->synth->send_configure_change();
1026 window->update_note_selection();
1029 void SynthNote::stop_note()
1032 window->synth->delete_freq(keyboard_freqs[number]);
1033 window->base_freq->update((float)window->synth->config.base_freq[0]);
1034 window->freqpot->update(window->synth->config.base_freq[0]);
1035 window->synth->send_configure_change();
1036 window->update_note_selection();
1039 int SynthNote::keypress_event()
1042 if (get_keypress() == 'h' && alt_down())
1044 context_help_show();
1048 if(number >= FIRST_TITLE && number < LAST_TITLE)
1050 if(get_keypress() == keyboard_map[number - FIRST_TITLE][0])
1052 if((ctrl_down() || shift_down()) &&
1053 window->synth->freq_exists(keyboard_freqs[number]))
1063 // Key releases are repeated, so momentary notes may not work
1070 int SynthNote::keyrelease_event()
1072 if(note_on && window->synth->config.momentary_notes)
1081 int SynthNote::cursor_motion_event()
1084 if(window->current_note > -1)
1086 int cursor_x = get_relative_cursor_x();
1087 int cursor_y = get_relative_cursor_y();
1088 if(cursor_x >= 0 && cursor_x < get_w() &&
1089 cursor_y >= 0 && cursor_y < get_h())
1091 if(window->starting_notes)
1100 window->current_note = number;
1107 int SynthNote::button_press_event()
1109 if(BC_Toggle::button_press_event())
1111 // printf("SynthNote::button_press_event %d %d %d\n",
1114 // window->synth->freq_exists(keyboard_freqs[number]));
1115 window->starting_notes = 1;
1116 if((ctrl_down() || shift_down()) &&
1117 window->synth->freq_exists(keyboard_freqs[number]))
1119 //printf("SynthNote::button_press_event %d\n", __LINE__);
1121 window->starting_notes = 0;
1125 //printf("SynthNote::button_press_event %d\n", __LINE__);
1127 window->starting_notes = 1;
1129 window->current_note = number;
1135 int SynthNote::button_release_event()
1137 // Change frequency permanently
1138 if(window->current_note == number)
1140 if(window->synth->config.momentary_notes)
1142 // Mute on button release
1146 window->current_note = -1;
1149 return BC_Toggle::button_release_event();
1152 int SynthNote::draw_face(int flash, int flush)
1154 BC_Toggle::draw_face(0, 0);
1155 static const char *titles[] =
1172 const char *text = titles[number % (sizeof(titles) / sizeof(char*))];
1173 char string[BCTEXTLEN];
1174 sprintf(string, "%s%d", text, number / 12);
1175 //printf("SynthNote::draw_face %d %d %d %d %s\n", __LINE__, number, get_w(), get_h(), text);
1182 draw_text(get_w() / 2 - get_text_width(MEDIUMFONT, string) / 2,
1183 get_h() - get_text_height(MEDIUMFONT, string) - window->synth->get_theme()->widget_border,
1187 if(flash) this->flash(0);
1188 if(flush) this->flush();
1198 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
1200 this->window = window;
1201 this->number = number;
1204 SynthOscGUI::~SynthOscGUI()
1212 void SynthOscGUI::create_objects(int y)
1214 char text[BCTEXTLEN];
1215 sprintf(text, "%d:", number + 1);
1216 window->osc_subwindow->add_subwindow(title = new BC_Title(xS(10), y+yS(15), text));
1218 window->osc_subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
1219 window->osc_subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
1220 window->osc_subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
1226 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
1227 : BC_FPot(xS(50), y,
1228 synth->config.oscillator_config.values[gui->number]->level,
1231 this->synth = synth;
1235 SynthOscGUILevel::~SynthOscGUILevel()
1239 int SynthOscGUILevel::handle_event()
1241 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1242 config->level = get_value();
1243 gui->window->canvas->update();
1244 synth->send_configure_change();
1250 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
1251 : BC_IPot(xS(125), y,
1252 (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360),
1255 this->synth = synth;
1259 SynthOscGUIPhase::~SynthOscGUIPhase()
1263 int SynthOscGUIPhase::handle_event()
1265 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1266 config->phase = (float)get_value() / 360;
1267 gui->window->canvas->update();
1268 synth->send_configure_change();
1274 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
1275 : BC_FPot(xS(200), y,
1276 (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor),
1279 this->synth = synth;
1283 SynthOscGUIFreq::~SynthOscGUIFreq()
1287 int SynthOscGUIFreq::handle_event()
1289 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1290 config->freq_factor = get_value();
1291 gui->window->canvas->update();
1292 synth->send_configure_change();
1297 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
1298 : BC_GenericButton(x, y, _("Add"))
1300 this->synth = synth;
1301 this->window = window;
1304 SynthAddOsc::~SynthAddOsc()
1308 int SynthAddOsc::handle_event()
1310 synth->add_oscillator();
1311 synth->send_configure_change();
1312 window->update_gui();
1317 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
1318 : BC_GenericButton(x, y, _("Delete"))
1320 this->synth = synth;
1321 this->window = window;
1324 SynthDelOsc::~SynthDelOsc()
1328 int SynthDelOsc::handle_event()
1330 synth->delete_oscillator();
1331 synth->send_configure_change();
1332 window->update_gui();
1337 OscScroll::OscScroll(Synth *synth, SynthWindow *window,
1338 int x, int y, int h)
1339 : BC_ScrollBar(x, y, SCROLL_VERT, h,
1340 synth->config.oscillator_config.total * OSCILLATORHEIGHT,
1341 0, window->osc_subwindow->get_h())
1343 this->synth = synth;
1344 this->window = window;
1347 OscScroll::~OscScroll()
1351 int OscScroll::handle_event()
1353 window->update_oscillators();
1359 NoteScroll::NoteScroll(Synth *synth, SynthWindow *window,
1360 int x, int y, int w)
1361 : BC_ScrollBar(x, y, SCROLL_HORIZ, w,
1362 window->white_key[0]->get_w() * TOTALNOTES * 7 / 12 + window->white_key[0]->get_w(),
1363 0, window->note_subwindow->get_w())
1365 this->synth = synth;
1366 this->window = window;
1369 NoteScroll::~NoteScroll()
1373 int NoteScroll::handle_event()
1375 window->update_notes();
1380 SynthClear::SynthClear(Synth *synth, int x, int y)
1381 : BC_GenericButton(x, y, _("Clear"))
1383 this->synth = synth;
1385 SynthClear::~SynthClear()
1388 int SynthClear::handle_event()
1390 synth->config.reset();
1391 synth->send_configure_change();
1392 synth->update_gui();
1401 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
1402 : BC_PopupMenu(x, y, xS(120), text)
1404 this->synth = synth;
1407 SynthWaveForm::~SynthWaveForm()
1411 void SynthWaveForm::create_objects()
1413 // add_item(new SynthWaveFormItem(synth, _("DC"), DC));
1414 add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
1415 add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
1416 add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
1417 add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
1418 add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
1419 add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
1422 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1425 this->synth = synth;
1426 this->value = value;
1429 SynthWaveFormItem::~SynthWaveFormItem()
1433 int SynthWaveFormItem::handle_event()
1435 synth->config.wavefunction = value;
1436 ((SynthWindow*)synth->thread->window)->canvas->update();
1437 get_popup_menu()->set_text(get_text());
1438 synth->send_configure_change();
1443 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1444 : BC_FPot(x, y, synth->config.wetness, INFINITYGAIN, 0)
1446 this->synth = synth;
1449 int SynthWetness::handle_event()
1451 synth->config.wetness = get_value();
1452 synth->send_configure_change();
1458 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1459 : BC_QPot(x, y, synth->config.base_freq[0])
1461 this->synth = synth;
1462 this->window = window;
1464 SynthFreqPot::~SynthFreqPot()
1467 int SynthFreqPot::handle_event()
1469 if(get_value() > 0 && get_value() < 30000)
1471 synth->config.base_freq[0] = get_value();
1472 freq_text->update(get_value());
1473 synth->send_configure_change();
1474 window->update_note_selection();
1481 SynthBaseFreq::SynthBaseFreq(Synth *synth, SynthWindow *window, int x, int y)
1482 : BC_TextBox(x, y, xS(100), 1, (float)0)
1484 this->synth = synth;
1485 this->window = window;
1488 SynthBaseFreq::~SynthBaseFreq()
1491 int SynthBaseFreq::handle_event()
1493 double new_value = atof(get_text());
1495 if(new_value < 30000)
1497 synth->config.base_freq[0] = new_value;
1498 freq_pot->update(synth->config.base_freq[0]);
1499 synth->send_configure_change();
1500 window->update_note_selection();
1509 SynthCanvas::SynthCanvas(Synth *synth, SynthWindow *window,
1510 int x, int y, int w, int h)
1511 : BC_SubWindow(x, y, w, h, BLACK)
1513 this->synth = synth;
1514 this->window = window;
1517 SynthCanvas::~SynthCanvas()
1521 int SynthCanvas::update()
1525 clear_box(0, 0, get_w(), get_h());
1528 draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1532 double normalize_constant = (double)1 / synth->get_total_power();
1533 y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1535 for(int i = 1; i < get_w(); i++)
1537 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1538 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1546 // ======================= level calculations
1547 SynthLevelZero::SynthLevelZero(Synth *synth)
1548 : BC_MenuItem(_("Zero"))
1550 this->synth = synth;
1553 SynthLevelZero::~SynthLevelZero()
1557 int SynthLevelZero::handle_event()
1559 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1561 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1564 ((SynthWindow*)synth->thread->window)->update_gui();
1565 synth->send_configure_change();
1569 SynthLevelMax::SynthLevelMax(Synth *synth)
1570 : BC_MenuItem(_("Maximum"))
1572 this->synth = synth;
1575 SynthLevelMax::~SynthLevelMax()
1579 int SynthLevelMax::handle_event()
1581 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1583 synth->config.oscillator_config.values[i]->level = 0;
1585 ((SynthWindow*)synth->thread->window)->update_gui();
1586 synth->send_configure_change();
1590 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1591 : BC_MenuItem(_("Normalize"))
1593 this->synth = synth;
1596 SynthLevelNormalize::~SynthLevelNormalize()
1600 int SynthLevelNormalize::handle_event()
1605 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1607 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1610 float scale = 1 / total;
1613 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1615 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1617 new_value = synth->db.todb(new_value);
1619 synth->config.oscillator_config.values[i]->level = new_value;
1622 ((SynthWindow*)synth->thread->window)->update_gui();
1623 synth->send_configure_change();
1627 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1628 : BC_MenuItem(_("Slope"))
1630 this->synth = synth;
1633 SynthLevelSlope::~SynthLevelSlope()
1637 int SynthLevelSlope::handle_event()
1639 float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1641 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1643 synth->config.oscillator_config.values[i]->level = i * slope;
1646 ((SynthWindow*)synth->thread->window)->update_gui();
1647 synth->send_configure_change();
1651 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1652 : BC_MenuItem(_("Random"))
1654 this->synth = synth;
1656 SynthLevelRandom::~SynthLevelRandom()
1660 int SynthLevelRandom::handle_event()
1663 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1665 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1668 ((SynthWindow*)synth->thread->window)->update_gui();
1669 synth->send_configure_change();
1673 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1674 : BC_MenuItem(_("Invert"))
1676 this->synth = synth;
1678 SynthLevelInvert::~SynthLevelInvert()
1682 int SynthLevelInvert::handle_event()
1684 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1686 synth->config.oscillator_config.values[i]->level =
1687 INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1690 ((SynthWindow*)synth->thread->window)->update_gui();
1691 synth->send_configure_change();
1695 SynthLevelSine::SynthLevelSine(Synth *synth)
1696 : BC_MenuItem(_("Sine"))
1698 this->synth = synth;
1700 SynthLevelSine::~SynthLevelSine()
1704 int SynthLevelSine::handle_event()
1708 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1710 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1711 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1712 synth->config.oscillator_config.values[i]->level = new_value;
1715 ((SynthWindow*)synth->thread->window)->update_gui();
1716 synth->send_configure_change();
1720 // ============================ phase calculations
1722 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1723 : BC_MenuItem(_("Invert"))
1725 this->synth = synth;
1727 SynthPhaseInvert::~SynthPhaseInvert()
1731 int SynthPhaseInvert::handle_event()
1733 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1735 synth->config.oscillator_config.values[i]->phase =
1736 1 - synth->config.oscillator_config.values[i]->phase;
1739 ((SynthWindow*)synth->thread->window)->update_gui();
1740 synth->send_configure_change();
1744 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1745 : BC_MenuItem(_("Zero"))
1747 this->synth = synth;
1749 SynthPhaseZero::~SynthPhaseZero()
1753 int SynthPhaseZero::handle_event()
1755 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1757 synth->config.oscillator_config.values[i]->phase = 0;
1760 ((SynthWindow*)synth->thread->window)->update_gui();
1761 synth->send_configure_change();
1765 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1766 : BC_MenuItem(_("Sine"))
1768 this->synth = synth;
1770 SynthPhaseSine::~SynthPhaseSine()
1774 int SynthPhaseSine::handle_event()
1777 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1779 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1780 new_value = sin(new_value) / 2 + .5;
1781 synth->config.oscillator_config.values[i]->phase = new_value;
1784 ((SynthWindow*)synth->thread->window)->update_gui();
1785 synth->send_configure_change();
1789 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1790 : BC_MenuItem(_("Random"))
1792 this->synth = synth;
1794 SynthPhaseRandom::~SynthPhaseRandom()
1798 int SynthPhaseRandom::handle_event()
1801 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1803 synth->config.oscillator_config.values[i]->phase =
1804 (float)(rand() % 360) / 360;
1807 ((SynthWindow*)synth->thread->window)->update_gui();
1808 synth->send_configure_change();
1813 // ============================ freq calculations
1815 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1816 : BC_MenuItem(_("Random"))
1818 this->synth = synth;
1820 SynthFreqRandom::~SynthFreqRandom()
1824 int SynthFreqRandom::handle_event()
1827 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1829 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1832 ((SynthWindow*)synth->thread->window)->update_gui();
1833 synth->send_configure_change();
1837 SynthFreqPow1::SynthFreqPow1(Synth *synth)
1838 : BC_MenuItem(_("Powers of 1.4"))
1840 this->synth = synth;
1842 SynthFreqPow1::~SynthFreqPow1()
1846 int SynthFreqPow1::handle_event()
1848 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1850 synth->config.oscillator_config.values[i]->freq_factor = pow(sqrt(2), i);
1853 ((SynthWindow*)synth->thread->window)->update_gui();
1854 synth->send_configure_change();
1859 SynthFreqPow2::SynthFreqPow2(Synth *synth)
1860 : BC_MenuItem(_("Powers of 2"))
1862 this->synth = synth;
1864 SynthFreqPow2::~SynthFreqPow2()
1868 int SynthFreqPow2::handle_event()
1870 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1872 synth->config.oscillator_config.values[i]->freq_factor = pow(2, i);
1875 ((SynthWindow*)synth->thread->window)->update_gui();
1876 synth->send_configure_change();
1883 SynthFreqMin::SynthFreqMin(Synth *synth)
1884 : BC_MenuItem(_("Minimum"))
1886 this->synth = synth;
1888 SynthFreqMin::~SynthFreqMin()
1892 int SynthFreqMin::handle_event()
1894 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1896 synth->config.oscillator_config.values[i]->freq_factor = 1;
1899 ((SynthWindow*)synth->thread->window)->update_gui();
1900 synth->send_configure_change();
1905 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1906 : BC_MenuItem(_("Enumerate"))
1908 this->synth = synth;
1910 SynthFreqEnum::~SynthFreqEnum()
1914 int SynthFreqEnum::handle_event()
1916 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1918 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1921 ((SynthWindow*)synth->thread->window)->update_gui();
1922 synth->send_configure_change();
1926 SynthFreqEven::SynthFreqEven(Synth *synth)
1927 : BC_MenuItem(_("Even"))
1929 this->synth = synth;
1931 SynthFreqEven::~SynthFreqEven()
1935 int SynthFreqEven::handle_event()
1937 if(synth->config.oscillator_config.total)
1938 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1940 for(int i = 1; i < synth->config.oscillator_config.total; i++)
1942 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1945 ((SynthWindow*)synth->thread->window)->update_gui();
1946 synth->send_configure_change();
1950 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1951 : BC_MenuItem(_("Odd"))
1952 { this->synth = synth; }
1953 SynthFreqOdd::~SynthFreqOdd()
1957 int SynthFreqOdd::handle_event()
1959 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1961 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1964 ((SynthWindow*)synth->thread->window)->update_gui();
1965 synth->send_configure_change();
1969 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
1970 : BC_MenuItem(_("Fibonnacci"))
1972 this->synth = synth;
1974 SynthFreqFibonacci::~SynthFreqFibonacci()
1978 int SynthFreqFibonacci::handle_event()
1980 float last_value1 = 0, last_value2 = 1;
1981 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1983 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1984 if(synth->config.oscillator_config.values[i]->freq_factor > 100)
1985 synth->config.oscillator_config.values[i]->freq_factor = 100;
1986 last_value1 = last_value2;
1987 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1990 ((SynthWindow*)synth->thread->window)->update_gui();
1991 synth->send_configure_change();
1995 SynthFreqPrime::SynthFreqPrime(Synth *synth)
1996 : BC_MenuItem(_("Prime"))
1998 this->synth = synth;
2000 SynthFreqPrime::~SynthFreqPrime()
2004 int SynthFreqPrime::handle_event()
2007 for(int i = 0; i < synth->config.oscillator_config.total; i++)
2009 synth->config.oscillator_config.values[i]->freq_factor = number;
2010 number = get_next_prime(number);
2013 ((SynthWindow*)synth->thread->window)->update_gui();
2014 synth->send_configure_change();
2018 float SynthFreqPrime::get_next_prime(float number)
2027 for(float i = number - 1; i > 1 && !result; i--)
2029 if((number / i) - (int)(number / i) == 0) result = 1;
2043 SynthOscillatorConfig::SynthOscillatorConfig(int number)
2046 this->number = number;
2049 SynthOscillatorConfig::~SynthOscillatorConfig()
2053 void SynthOscillatorConfig::reset()
2061 void SynthOscillatorConfig::read_data(FileXML *file)
2063 level = file->tag.get_property("LEVEL", (float)level);
2064 phase = file->tag.get_property("PHASE", (float)phase);
2065 freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
2068 void SynthOscillatorConfig::save_data(FileXML *file)
2070 file->tag.set_title("OSCILLATOR");
2071 file->tag.set_property("LEVEL", (float)level);
2072 file->tag.set_property("PHASE", (float)phase);
2073 file->tag.set_property("FREQFACTOR", (float)freq_factor);
2075 file->tag.set_title("/OSCILLATOR");
2077 file->append_newline();
2080 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
2082 if(EQUIV(level, that.level) &&
2083 EQUIV(phase, that.phase) &&
2084 EQUIV(freq_factor, that.freq_factor))
2090 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
2094 freq_factor = that.freq_factor;
2098 SynthConfig::SynthConfig()
2103 SynthConfig::~SynthConfig()
2105 oscillator_config.remove_all_objects();
2108 void SynthConfig::reset()
2112 for(int i = 1; i < MAX_FREQS; i++)
2114 wavefunction = SINE;
2115 for(int i = 0; i < oscillator_config.total; i++)
2117 oscillator_config.values[i]->reset();
2120 momentary_notes = 0;
2123 int SynthConfig::equivalent(SynthConfig &that)
2125 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
2126 for(int i = 0; i < MAX_FREQS; i++)
2127 if(base_freq[i] != that.base_freq[i]) return 0;
2129 if(wavefunction != that.wavefunction ||
2130 oscillator_config.total != that.oscillator_config.total ||
2131 momentary_notes != that.momentary_notes) return 0;
2133 for(int i = 0; i < oscillator_config.total; i++)
2135 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
2142 void SynthConfig::copy_from(SynthConfig& that)
2144 wetness = that.wetness;
2145 for(int i = 0; i < MAX_FREQS; i++)
2146 base_freq[i] = that.base_freq[i];
2147 wavefunction = that.wavefunction;
2148 momentary_notes = that.momentary_notes;
2152 i < oscillator_config.total && i < that.oscillator_config.total;
2155 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2159 i < that.oscillator_config.total;
2162 oscillator_config.append(new SynthOscillatorConfig(i));
2163 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2167 i < oscillator_config.total;
2170 oscillator_config.remove_object();
2175 void SynthConfig::interpolate(SynthConfig &prev,
2179 int64_t current_frame)
2181 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
2182 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
2185 wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
2186 // base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);
2188 momentary_notes = prev.momentary_notes;