4 * Copyright (C) 1997-2011 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 _("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->get_data(), strlen(keyframe->get_data()));
87 //printf("Synth::read_data %s\n", keyframe->get_data());
88 int result = 0, current_osc = 0;
89 //int total_oscillators = 0;
92 result = input.read_tag();
96 if(input.tag.title_is("SYNTH"))
98 config.wetness = input.tag.get_property("WETNESS", config.wetness);
102 window_w = input.tag.get_property("WINDOW_W", window_w);
103 window_h = input.tag.get_property("WINDOW_H", window_h);
105 config.momentary_notes = input.tag.get_property("MOMENTARY_NOTES", config.momentary_notes);
107 //printf("Synth::read_data %d %d %d\n", __LINE__, window_w, window_h);
108 for(int i = 0; i < MAX_FREQS; i++)
110 sprintf(string, "BASEFREQ_%d", i);
111 config.base_freq[i] = input.tag.get_property(string, (double)0);
114 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
115 //total_oscillators = input.tag.get_property("OSCILLATORS", 0);
118 if(input.tag.title_is("OSCILLATOR"))
120 if(current_osc >= config.oscillator_config.total)
121 config.oscillator_config.append(new SynthOscillatorConfig(current_osc));
123 config.oscillator_config.values[current_osc]->read_data(&input);
129 while(config.oscillator_config.total > current_osc)
130 config.oscillator_config.remove_object();
133 void Synth::save_data(KeyFrame *keyframe)
136 char string[BCTEXTLEN];
138 // cause htal file to store data directly in text
139 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
141 output.tag.set_title("SYNTH");
142 output.tag.set_property("WETNESS", config.wetness);
143 output.tag.set_property("WINDOW_W", window_w);
144 output.tag.set_property("WINDOW_H", window_h);
145 output.tag.set_property("MOMENTARY_NOTES", config.momentary_notes);
147 for(int i = 0; i < MAX_FREQS; i++)
149 // if(!EQUIV(config.base_freq[i], 0))
151 sprintf(string, "BASEFREQ_%d", i);
152 output.tag.set_property(string, config.base_freq[i]);
153 //printf("Synth::save_data %d %s\n", __LINE__, string);
157 output.tag.set_property("WAVEFUNCTION", config.wavefunction);
158 output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
160 output.append_newline();
162 for(int i = 0; i < config.oscillator_config.total; i++)
164 config.oscillator_config.values[i]->save_data(&output);
167 output.tag.set_title("/SYNTH");
169 output.append_newline();
170 output.terminate_string();
171 //printf("Synth::save_data %d %s\n", __LINE__, output.string);
172 // data is now in *text
177 void Synth::update_gui()
181 if(load_configuration())
183 thread->window->lock_window();
184 ((SynthWindow*)thread->window)->update_gui();
185 thread->window->unlock_window();
191 void Synth::add_oscillator()
193 if(config.oscillator_config.total > 20) return;
195 config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
198 void Synth::delete_oscillator()
200 if(config.oscillator_config.total)
202 config.oscillator_config.remove_object();
207 double Synth::get_total_power()
211 if(config.wavefunction == DC) return 1.0;
213 for(int i = 0; i < config.oscillator_config.total; i++)
215 result += db.fromdb(config.oscillator_config.values[i]->level);
218 if(result == 0) result = 1; // prevent division by 0
223 double Synth::solve_eqn(double *output,
226 double normalize_constant,
229 SynthOscillatorConfig *config =
230 this->config.oscillator_config.values[oscillator];
231 if(config->level <= INFINITYGAIN) return 0;
233 double power = this->db.fromdb(config->level) * normalize_constant;
234 // Period of fundamental frequency in samples
235 double orig_period = (double)get_samplerate() /
237 // Starting sample in waveform
238 double x = waveform_sample;
239 double phase_offset = config->phase * orig_period;
240 //printf("Synth::solve_eqn %d %f\n", __LINE__, config->phase);
241 // Period of current oscillator
242 double period = orig_period / config->freq_factor;
245 if(get_direction() == PLAY_REVERSE) step = -1;
247 switch(this->config.wavefunction)
250 for(sample = 0; sample < length; sample++)
252 output[sample] += power;
257 for(sample = 0; sample < length; sample++)
259 output[sample] += sin((x + phase_offset) /
268 for(sample = 0; sample < length; sample++)
270 output[sample] += function_sawtooth((x + phase_offset) /
277 for(sample = 0; sample < length; sample++)
279 output[sample] += function_square((x + phase_offset) /
286 for(sample = 0; sample < length; sample++)
288 output[sample] += function_triangle((x + phase_offset) /
295 for(sample = 0; sample < length; sample++)
297 output[sample] += function_pulse((x + phase_offset) /
304 for(sample = 0; sample < length; sample++)
306 output[sample] += function_noise() * power;
313 double Synth::get_point(float x, double normalize_constant)
316 for(int i = 0; i < config.oscillator_config.total; i++)
317 result += get_oscillator_point(x, normalize_constant, i);
322 double Synth::get_oscillator_point(float x,
323 double normalize_constant,
326 SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
327 double power = db.fromdb(config->level) * normalize_constant;
328 switch(this->config.wavefunction)
334 return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
337 return function_sawtooth((x + config->phase) * config->freq_factor) * power;
340 return function_square((x + config->phase) * config->freq_factor) * power;
343 return function_triangle((x + config->phase) * config->freq_factor) * power;
346 return function_pulse((x + config->phase) * config->freq_factor) * power;
349 return function_noise() * power;
355 double Synth::function_square(double x)
357 x -= (int)x; // only fraction counts
358 return (x < .5) ? -1 : 1;
361 double Synth::function_pulse(double x)
363 x -= (int)x; // only fraction counts
364 return (x < .5) ? 0 : 1;
367 double Synth::function_noise()
369 return (double)(rand() % 65536 - 32768) / 32768;
372 double Synth::function_sawtooth(double x)
378 double Synth::function_triangle(double x)
381 return (x < .5) ? 1 - x * 4 : -3 + x * 4;
384 int Synth::process_realtime(int64_t size,
388 // sample relative to start of plugin
389 waveform_sample = get_source_position();
391 need_reconfigure |= load_configuration();
392 if(need_reconfigure) reconfigure();
394 double wetness = DB::fromdb(config.wetness);
395 if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
398 double *output_samples = output_ptr->get_data();
399 double *input_samples = input_ptr->get_data();
400 for(int j = 0; j < size; j++)
401 output_samples[j] = input_samples[j] * wetness;
403 // Overlay each frequency
404 for(int j = 0; j < MAX_FREQS; j++)
406 if(!EQUIV(config.base_freq[j], 0))
413 input_ptr->get_data(),
414 output_ptr->get_data());
415 //printf("Synth::process_realtime 2\n");
419 // waveform_sample += size;
423 int Synth::overlay_synth(double freq,
428 double normalize_constant = 1.0 / get_total_power();
429 for(int i = 0; i < config.oscillator_config.total; i++)
438 void Synth::reconfigure()
440 need_reconfigure = 0;
441 // waveform_sample = 0;
444 int Synth::freq_exists(double freq)
446 for(int i = 0; i < MAX_FREQS; i++)
449 // printf("Synth::freq_exists %d %d %f %f\n",
453 // config.base_freq[i]);
454 if(fabs(freq - config.base_freq[i]) < 1.0)
461 void Synth::new_freq(double freq)
464 for(int i = 0; i < MAX_FREQS; i++)
466 if(EQUIV(config.base_freq[i], freq)) return;
469 for(int i = 0; i < MAX_FREQS; i++)
471 if(EQUIV(config.base_freq[i], 0))
473 config.base_freq[i] = freq;
474 //printf("Synth::new_freq %d\n", __LINE__);
480 void Synth::delete_freq(double freq)
482 for(int i = 0; i < MAX_FREQS; i++)
484 if(EQUIV(config.base_freq[i], freq))
486 //printf("Synth::delete_freq %d\n", __LINE__);
487 // Shift frequencies back
488 for(int j = i; j < MAX_FREQS - 1; j++)
490 config.base_freq[j] = config.base_freq[j + 1];
492 config.base_freq[MAX_FREQS - 1] = 0;
499 void Synth::delete_freqs()
501 for(int i = 0; i < MAX_FREQS; i++)
502 config.base_freq[i] = 0;
532 SynthWindow::SynthWindow(Synth *synth)
533 : PluginClientWindow(synth,
547 bzero(notes, sizeof(SynthNote*) * TOTALNOTES);
551 SynthWindow::~SynthWindow()
561 static const char *keyboard_map[] =
563 "q", "2", "w", "3", "e", "r", "5", "t", "6", "y", "7", "u",
564 "z", "s", "x", "d", "c", "v", "g", "b", "h", "n", "j", "m"
567 void SynthWindow::create_objects()
570 add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
572 BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
573 menu->add_menu(levelmenu = new BC_Menu(_("Level")));
574 menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
575 menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
577 levelmenu->add_item(new SynthLevelInvert(synth));
578 levelmenu->add_item(new SynthLevelMax(synth));
579 levelmenu->add_item(new SynthLevelRandom(synth));
580 levelmenu->add_item(new SynthLevelSine(synth));
581 levelmenu->add_item(new SynthLevelSlope(synth));
582 levelmenu->add_item(new SynthLevelZero(synth));
584 phasemenu->add_item(new SynthPhaseInvert(synth));
585 phasemenu->add_item(new SynthPhaseRandom(synth));
586 phasemenu->add_item(new SynthPhaseSine(synth));
587 phasemenu->add_item(new SynthPhaseZero(synth));
589 harmonicmenu->add_item(new SynthFreqEnum(synth));
590 harmonicmenu->add_item(new SynthFreqEven(synth));
591 harmonicmenu->add_item(new SynthFreqFibonacci(synth));
592 harmonicmenu->add_item(new SynthFreqOdd(synth));
593 harmonicmenu->add_item(new SynthFreqPrime(synth));
597 add_subwindow(new BC_Title(x, y, _("Waveform")));
599 add_subwindow(new BC_Title(x, y, _("Wave Function")));
602 add_subwindow(canvas = new SynthCanvas(synth, this, x, y, 230, 160));
606 char string[BCTEXTLEN];
607 waveform_to_text(string, synth->config.wavefunction);
609 add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
610 waveform->create_objects();
612 int x1 = x + waveform->get_w() + 10;
615 add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
617 add_subwindow(base_freq = new SynthBaseFreq(synth, this, x, y));
618 base_freq->update((float)synth->config.base_freq[0]);
619 x += base_freq->get_w() + synth->get_theme()->widget_border;
620 add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - 10));
621 base_freq->freq_pot = freqpot;
622 freqpot->freq_text = base_freq;
623 x -= base_freq->get_w() + synth->get_theme()->widget_border;
625 add_subwindow(new BC_Title(x, y, _("Wetness:")));
626 add_subwindow(wetness = new SynthWetness(synth, x + 70, y - 10));
629 add_subwindow(new SynthClear(synth, x, y));
634 add_subwindow(new BC_Title(x, y, _("Level")));
636 add_subwindow(new BC_Title(x, y, _("Phase")));
638 add_subwindow(new BC_Title(x, y, _("Harmonic")));
643 add_subwindow(osc_subwindow = new BC_SubWindow(x, y, 265, get_h() - y));
645 add_subwindow(osc_scroll = new OscScroll(synth, this, x, y, get_h() - y));
649 add_subwindow(new SynthAddOsc(synth, this, x, y));
651 add_subwindow(new SynthDelOsc(synth, this, x, y));
656 #include "white_up_png.h"
657 #include "white_hi_png.h"
658 #include "white_dn_png.h"
659 #include "white_checked_png.h"
660 #include "white_checkedhi_png.h"
661 #include "black_up_png.h"
662 #include "black_hi_png.h"
663 #include "black_dn_png.h"
664 #include "black_checked_png.h"
665 #include "black_checkedhi_png.h"
666 white_key[0] = new VFramePng(white_up_png);
667 white_key[1] = new VFramePng(white_hi_png);
668 white_key[2] = new VFramePng(white_checked_png);
669 white_key[3] = new VFramePng(white_dn_png);
670 white_key[4] = new VFramePng(white_checkedhi_png);
671 black_key[0] = new VFramePng(black_up_png);
672 black_key[1] = new VFramePng(black_hi_png);
673 black_key[2] = new VFramePng(black_checked_png);
674 black_key[3] = new VFramePng(black_dn_png);
675 black_key[4] = new VFramePng(black_checkedhi_png);
678 add_subwindow(note_subwindow = new BC_SubWindow(x1,
681 white_key[0]->get_h() + MARGIN +
682 get_text_height(MEDIUMFONT) + MARGIN +
683 get_text_height(MEDIUMFONT) + MARGIN));
684 add_subwindow(note_scroll = new NoteScroll(synth,
687 note_subwindow->get_y() + note_subwindow->get_h(),
688 note_subwindow->get_w()));
690 add_subwindow(momentary = new SynthMomentary(this,
692 note_scroll->get_y() + note_scroll->get_h() + MARGIN,
693 _("Momentary notes")));
696 add_subwindow(note_instructions = new BC_Title(
698 momentary->get_y() + momentary->get_h() + MARGIN,
699 _("Ctrl or Shift to select multiple notes.")));
702 update_oscillators();
708 int SynthWindow::keypress_event()
710 if(ctrl_down() && get_keypress() == 'w')
718 int SynthWindow::resize_event(int w, int h)
720 clear_box(0, 0, w, h);
721 osc_subwindow->reposition_window(osc_subwindow->get_x(),
722 osc_subwindow->get_y(),
723 osc_subwindow->get_w(),
724 h - osc_subwindow->get_y());
725 osc_subwindow->clear_box(0, 0, osc_subwindow->get_w(), osc_subwindow->get_h());
726 osc_scroll->reposition_window(osc_scroll->get_x(),
728 h - osc_scroll->get_y());
729 note_subwindow->reposition_window(note_subwindow->get_x(),
730 note_subwindow->get_y(),
731 w - note_subwindow->get_x(),
732 note_subwindow->get_h());
733 note_scroll->reposition_window(note_scroll->get_x(),
734 note_scroll->get_y(),
735 w - note_scroll->get_x());
736 note_scroll->update_length(white_key[0]->get_w() * TOTALNOTES * 7 / 12 +
737 white_key[0]->get_w(),
738 note_scroll->get_position(),
739 note_subwindow->get_w(),
744 update_oscillators();
750 void SynthWindow::update_gui()
752 char string[BCTEXTLEN];
753 freqpot->update((int)synth->config.base_freq[0]);
754 base_freq->update((float)synth->config.base_freq[0]);
755 wetness->update(synth->config.wetness);
756 waveform_to_text(string, synth->config.wavefunction);
757 waveform->set_text(string);
758 momentary->update(synth->config.momentary_notes);
761 update_oscillators();
763 update_note_selection();
767 void SynthWindow::update_scrollbar()
769 osc_scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
770 osc_scroll->get_position(),
771 osc_subwindow->get_h(),
776 void SynthWindow::update_whitekey(int number,
783 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
784 white_key, number, x, y));
785 if(number >= FIRST_TITLE && number < LAST_TITLE)
786 note_subwindow->add_subwindow(
787 note_titles[(*current_title)++] = new BC_Title(
788 x + text_white_margin,
790 keyboard_map[number - FIRST_TITLE]));
791 //printf("SynthWindow::update_whitekey %d\n", __LINE__);
795 notes[number]->reposition_window(x, y);
796 if(number >= FIRST_TITLE && number < LAST_TITLE)
797 note_titles[(*current_title)++]->reposition_window(x + text_white_margin,
803 void SynthWindow::update_blackkey(int number,
810 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
811 black_key, number, x, y));
812 if(number >= FIRST_TITLE && number < LAST_TITLE)
813 note_subwindow->add_subwindow(
814 note_titles[(*current_title)++] = new BC_Title(x + text_black_margin,
816 keyboard_map[number - FIRST_TITLE]));
820 notes[number]->reposition_window(x, y);
821 if(number >= FIRST_TITLE && number < LAST_TITLE)
822 note_titles[(*current_title)++]->reposition_window(x + text_black_margin,
827 void SynthWindow::update_notes()
829 //int octave_w = white_key[0]->get_w() * 7;
830 int white_w = white_key[0]->get_w();
831 int black_w = black_key[0]->get_w();
832 int white_w1 = white_w - black_w / 2 - 2;
833 int white_w2 = white_w / 2;
834 int white_w3 = white_w * 2 / 3;
837 y1 = y + white_key[0]->get_h() + 10;
838 y2 = y1 + get_text_height(MEDIUMFONT) + 10;
839 y3 = y2 + get_text_height(MEDIUMFONT) + 10;
840 text_black_margin = black_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
841 text_white_margin = white_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
844 //printf("SynthWindow::update_notes %d\n", __LINE__);
845 note_subwindow->clear_box(0, 0, get_w(), get_h());
847 note_subwindow->set_color(get_resources()->default_text_color);
850 // To get the stacking order:
851 // pass 0 is white keys
852 // pass 1 is black keys
853 int current_title = 0;
854 for(int pass = 0; pass < 2; pass++)
856 x = -note_scroll->get_position();
858 for(int i = 0; i < TOTALNOTES; i++)
860 int octave_note = i % 12;
867 update_whitekey(i, ¤t_title, x, y);
873 update_whitekey(i, ¤t_title, x, y);
879 update_whitekey(i, ¤t_title, x, y);
883 update_whitekey(i, ¤t_title, x, y);
889 update_whitekey(i, ¤t_title, x, y);
895 update_whitekey(i, ¤t_title, x, y);
901 update_whitekey(i, ¤t_title, x, y);
912 update_blackkey(i, ¤t_title, x + white_w2, y);
916 update_blackkey(i, ¤t_title, x + white_w3, y);
923 update_blackkey(i, ¤t_title, x + white_w2, y);
927 update_blackkey(i, ¤t_title, x + white_w1, y);
931 update_blackkey(i, ¤t_title, x + white_w3, y);
943 void SynthWindow::update_note_selection()
945 for(int i = 0; i < TOTALNOTES; i++)
948 for(int j = 0; j < MAX_FREQS; j++)
950 if(synth->freq_exists(keyboard_freqs[notes[i]->number]))
959 notes[i]->set_value(1);
962 notes[i]->set_value(0);
967 void SynthWindow::update_oscillators()
969 int i, y = -osc_scroll->get_position();
973 // Add new oscillators
975 i < synth->config.oscillator_config.total;
979 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
981 if(oscillators.total <= i)
983 oscillators.append(gui = new SynthOscGUI(this, i));
984 gui->create_objects(y);
988 gui = oscillators.values[i];
990 gui->title->reposition_window(gui->title->get_x(), y + 15);
992 gui->level->reposition_window(gui->level->get_x(), y);
993 gui->level->update(config->level);
995 gui->phase->reposition_window(gui->phase->get_x(), y);
996 gui->phase->update((int64_t)(config->phase * 360));
998 gui->freq->reposition_window(gui->freq->get_x(), y);
999 gui->freq->update((int64_t)(config->freq_factor));
1001 y += OSCILLATORHEIGHT;
1004 // Delete old oscillators
1006 i < oscillators.total;
1008 oscillators.remove_object();
1012 int SynthWindow::waveform_to_text(char *text, int waveform)
1016 case DC: sprintf(text, _("DC")); break;
1017 case SINE: sprintf(text, _("Sine")); break;
1018 case SAWTOOTH: sprintf(text, _("Sawtooth")); break;
1019 case SQUARE: sprintf(text, _("Square")); break;
1020 case TRIANGLE: sprintf(text, _("Triangle")); break;
1021 case PULSE: sprintf(text, _("Pulse")); break;
1022 case NOISE: sprintf(text, _("Noise")); break;
1028 SynthMomentary::SynthMomentary(SynthWindow *window, int x, int y, char *text)
1031 window->synth->config.momentary_notes,
1034 this->window = window;
1037 int SynthMomentary::handle_event()
1039 window->synth->config.momentary_notes = get_value();
1040 window->synth->send_configure_change();
1047 SynthNote::SynthNote(SynthWindow *window,
1055 window->synth->freq_exists(keyboard_freqs[number]))
1057 this->window = window;
1058 this->number = number;
1064 void SynthNote::start_note()
1066 if(window->synth->config.momentary_notes) note_on = 1;
1068 //printf("SynthNote::start_note %d %d\n", __LINE__, ctrl_down());
1069 if(window->synth->config.momentary_notes || (!ctrl_down() && !shift_down()))
1071 // Kill all frequencies
1072 window->synth->delete_freqs();
1075 window->synth->new_freq(keyboard_freqs[number]);
1076 window->base_freq->update((float)window->synth->config.base_freq[0]);
1077 //printf("SynthNote::start_note %d %f\n", __LINE__, window->synth->config.base_freq[0]);
1078 window->freqpot->update(window->synth->config.base_freq[0]);
1079 window->synth->send_configure_change();
1080 window->update_note_selection();
1083 void SynthNote::stop_note()
1086 window->synth->delete_freq(keyboard_freqs[number]);
1087 window->base_freq->update((float)window->synth->config.base_freq[0]);
1088 window->freqpot->update(window->synth->config.base_freq[0]);
1089 window->synth->send_configure_change();
1090 window->update_note_selection();
1093 int SynthNote::keypress_event()
1095 if(number >= FIRST_TITLE && number < LAST_TITLE)
1097 if(get_keypress() == keyboard_map[number - FIRST_TITLE][0])
1099 if((ctrl_down() || shift_down()) &&
1100 window->synth->freq_exists(keyboard_freqs[number]))
1110 // Key releases are repeated, so momentary notes may not work
1117 int SynthNote::keyrelease_event()
1119 if(note_on && window->synth->config.momentary_notes)
1128 int SynthNote::cursor_motion_event()
1131 if(window->current_note > -1)
1133 int cursor_x = get_relative_cursor_x();
1134 int cursor_y = get_relative_cursor_y();
1135 if(cursor_x >= 0 && cursor_x < get_w() &&
1136 cursor_y >= 0 && cursor_y < get_h())
1138 if(window->starting_notes)
1147 window->current_note = number;
1154 int SynthNote::button_press_event()
1156 if(BC_Toggle::button_press_event())
1158 // printf("SynthNote::button_press_event %d %d %d\n",
1161 // window->synth->freq_exists(keyboard_freqs[number]));
1162 window->starting_notes = 1;
1163 if((ctrl_down() || shift_down()) &&
1164 window->synth->freq_exists(keyboard_freqs[number]))
1166 //printf("SynthNote::button_press_event %d\n", __LINE__);
1168 window->starting_notes = 0;
1172 //printf("SynthNote::button_press_event %d\n", __LINE__);
1174 window->starting_notes = 1;
1176 window->current_note = number;
1182 int SynthNote::button_release_event()
1184 // Change frequency permanently
1185 if(window->current_note == number)
1187 if(window->synth->config.momentary_notes)
1189 // Mute on button release
1193 window->current_note = -1;
1196 return BC_Toggle::button_release_event();
1199 int SynthNote::draw_face(int flash, int flush)
1201 BC_Toggle::draw_face(0, 0);
1202 static const char *titles[] =
1219 const char *text = titles[number % (sizeof(titles) / sizeof(char*))];
1220 char string[BCTEXTLEN];
1221 sprintf(string, "%s%d", text, number / 12);
1222 //printf("SynthNote::draw_face %d %d %d %d %s\n", __LINE__, number, get_w(), get_h(), text);
1229 draw_text(get_w() / 2 - get_text_width(MEDIUMFONT, string) / 2,
1230 get_h() - get_text_height(MEDIUMFONT, string) - window->synth->get_theme()->widget_border,
1234 if(flash) this->flash(0);
1235 if(flush) this->flush();
1245 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
1247 this->window = window;
1248 this->number = number;
1251 SynthOscGUI::~SynthOscGUI()
1259 void SynthOscGUI::create_objects(int y)
1261 char text[BCTEXTLEN];
1262 sprintf(text, "%d:", number + 1);
1263 window->osc_subwindow->add_subwindow(title = new BC_Title(10, y + 15, text));
1265 window->osc_subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
1266 window->osc_subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
1267 window->osc_subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
1273 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
1276 synth->config.oscillator_config.values[gui->number]->level,
1280 this->synth = synth;
1284 SynthOscGUILevel::~SynthOscGUILevel()
1288 int SynthOscGUILevel::handle_event()
1290 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1291 config->level = get_value();
1292 gui->window->canvas->update();
1293 synth->send_configure_change();
1299 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
1302 (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360),
1306 this->synth = synth;
1310 SynthOscGUIPhase::~SynthOscGUIPhase()
1314 int SynthOscGUIPhase::handle_event()
1316 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1317 config->phase = (float)get_value() / 360;
1318 gui->window->canvas->update();
1319 synth->send_configure_change();
1325 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
1328 (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor),
1332 this->synth = synth;
1336 SynthOscGUIFreq::~SynthOscGUIFreq()
1340 int SynthOscGUIFreq::handle_event()
1342 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1343 config->freq_factor = get_value();
1344 gui->window->canvas->update();
1345 synth->send_configure_change();
1355 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
1356 : BC_GenericButton(x, y, _("Add"))
1358 this->synth = synth;
1359 this->window = window;
1362 SynthAddOsc::~SynthAddOsc()
1366 int SynthAddOsc::handle_event()
1368 synth->add_oscillator();
1369 synth->send_configure_change();
1370 window->update_gui();
1376 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
1377 : BC_GenericButton(x, y, _("Delete"))
1379 this->synth = synth;
1380 this->window = window;
1383 SynthDelOsc::~SynthDelOsc()
1387 int SynthDelOsc::handle_event()
1389 synth->delete_oscillator();
1390 synth->send_configure_change();
1391 window->update_gui();
1396 OscScroll::OscScroll(Synth *synth,
1397 SynthWindow *window,
1405 synth->config.oscillator_config.total * OSCILLATORHEIGHT,
1407 window->osc_subwindow->get_h())
1409 this->synth = synth;
1410 this->window = window;
1413 OscScroll::~OscScroll()
1417 int OscScroll::handle_event()
1419 window->update_oscillators();
1425 NoteScroll::NoteScroll(Synth *synth,
1426 SynthWindow *window,
1434 window->white_key[0]->get_w() * TOTALNOTES * 7 / 12 + window->white_key[0]->get_w(),
1436 window->note_subwindow->get_w())
1438 this->synth = synth;
1439 this->window = window;
1442 NoteScroll::~NoteScroll()
1446 int NoteScroll::handle_event()
1448 window->update_notes();
1465 SynthClear::SynthClear(Synth *synth, int x, int y)
1466 : BC_GenericButton(x, y, _("Clear"))
1468 this->synth = synth;
1470 SynthClear::~SynthClear()
1473 int SynthClear::handle_event()
1475 synth->config.reset();
1476 synth->send_configure_change();
1477 synth->update_gui();
1486 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
1487 : BC_PopupMenu(x, y, 120, text)
1489 this->synth = synth;
1492 SynthWaveForm::~SynthWaveForm()
1496 void SynthWaveForm::create_objects()
1498 // add_item(new SynthWaveFormItem(synth, _("DC"), DC));
1499 add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
1500 add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
1501 add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
1502 add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
1503 add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
1504 add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
1507 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1510 this->synth = synth;
1511 this->value = value;
1514 SynthWaveFormItem::~SynthWaveFormItem()
1518 int SynthWaveFormItem::handle_event()
1520 synth->config.wavefunction = value;
1521 ((SynthWindow*)synth->thread->window)->canvas->update();
1522 get_popup_menu()->set_text(get_text());
1523 synth->send_configure_change();
1528 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1531 synth->config.wetness,
1535 this->synth = synth;
1538 int SynthWetness::handle_event()
1540 synth->config.wetness = get_value();
1541 synth->send_configure_change();
1547 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1548 : BC_QPot(x, y, synth->config.base_freq[0])
1550 this->synth = synth;
1551 this->window = window;
1553 SynthFreqPot::~SynthFreqPot()
1556 int SynthFreqPot::handle_event()
1558 if(get_value() > 0 && get_value() < 30000)
1560 synth->config.base_freq[0] = get_value();
1561 freq_text->update(get_value());
1562 synth->send_configure_change();
1563 window->update_note_selection();
1570 SynthBaseFreq::SynthBaseFreq(Synth *synth, SynthWindow *window, int x, int y)
1571 : BC_TextBox(x, y, 100, 1, (float)0)
1573 this->synth = synth;
1574 this->window = window;
1577 SynthBaseFreq::~SynthBaseFreq()
1580 int SynthBaseFreq::handle_event()
1582 double new_value = atof(get_text());
1584 if(new_value < 30000)
1586 synth->config.base_freq[0] = new_value;
1587 freq_pot->update(synth->config.base_freq[0]);
1588 synth->send_configure_change();
1589 window->update_note_selection();
1598 SynthCanvas::SynthCanvas(Synth *synth,
1599 SynthWindow *window,
1610 this->synth = synth;
1611 this->window = window;
1614 SynthCanvas::~SynthCanvas()
1618 int SynthCanvas::update()
1622 clear_box(0, 0, get_w(), get_h());
1625 draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1629 double normalize_constant = (double)1 / synth->get_total_power();
1630 y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1632 for(int i = 1; i < get_w(); i++)
1634 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1635 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1649 // ======================= level calculations
1650 SynthLevelZero::SynthLevelZero(Synth *synth)
1651 : BC_MenuItem(_("Zero"))
1653 this->synth = synth;
1656 SynthLevelZero::~SynthLevelZero()
1660 int SynthLevelZero::handle_event()
1662 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1664 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1667 ((SynthWindow*)synth->thread->window)->update_gui();
1668 synth->send_configure_change();
1672 SynthLevelMax::SynthLevelMax(Synth *synth)
1673 : BC_MenuItem(_("Maximum"))
1675 this->synth = synth;
1678 SynthLevelMax::~SynthLevelMax()
1682 int SynthLevelMax::handle_event()
1684 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1686 synth->config.oscillator_config.values[i]->level = 0;
1688 ((SynthWindow*)synth->thread->window)->update_gui();
1689 synth->send_configure_change();
1693 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1694 : BC_MenuItem(_("Normalize"))
1696 this->synth = synth;
1699 SynthLevelNormalize::~SynthLevelNormalize()
1703 int SynthLevelNormalize::handle_event()
1708 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1710 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1713 float scale = 1 / total;
1716 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1718 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1720 new_value = synth->db.todb(new_value);
1722 synth->config.oscillator_config.values[i]->level = new_value;
1725 ((SynthWindow*)synth->thread->window)->update_gui();
1726 synth->send_configure_change();
1730 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1731 : BC_MenuItem(_("Slope"))
1733 this->synth = synth;
1736 SynthLevelSlope::~SynthLevelSlope()
1740 int SynthLevelSlope::handle_event()
1742 float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1744 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1746 synth->config.oscillator_config.values[i]->level = i * slope;
1749 ((SynthWindow*)synth->thread->window)->update_gui();
1750 synth->send_configure_change();
1754 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1755 : BC_MenuItem(_("Random"))
1757 this->synth = synth;
1759 SynthLevelRandom::~SynthLevelRandom()
1763 int SynthLevelRandom::handle_event()
1766 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1768 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1771 ((SynthWindow*)synth->thread->window)->update_gui();
1772 synth->send_configure_change();
1776 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1777 : BC_MenuItem(_("Invert"))
1779 this->synth = synth;
1781 SynthLevelInvert::~SynthLevelInvert()
1785 int SynthLevelInvert::handle_event()
1787 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1789 synth->config.oscillator_config.values[i]->level =
1790 INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1793 ((SynthWindow*)synth->thread->window)->update_gui();
1794 synth->send_configure_change();
1798 SynthLevelSine::SynthLevelSine(Synth *synth)
1799 : BC_MenuItem(_("Sine"))
1801 this->synth = synth;
1803 SynthLevelSine::~SynthLevelSine()
1807 int SynthLevelSine::handle_event()
1811 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1813 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1814 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1815 synth->config.oscillator_config.values[i]->level = new_value;
1818 ((SynthWindow*)synth->thread->window)->update_gui();
1819 synth->send_configure_change();
1823 // ============================ phase calculations
1825 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1826 : BC_MenuItem(_("Invert"))
1828 this->synth = synth;
1830 SynthPhaseInvert::~SynthPhaseInvert()
1834 int SynthPhaseInvert::handle_event()
1836 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1838 synth->config.oscillator_config.values[i]->phase =
1839 1 - synth->config.oscillator_config.values[i]->phase;
1842 ((SynthWindow*)synth->thread->window)->update_gui();
1843 synth->send_configure_change();
1847 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1848 : BC_MenuItem(_("Zero"))
1850 this->synth = synth;
1852 SynthPhaseZero::~SynthPhaseZero()
1856 int SynthPhaseZero::handle_event()
1858 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1860 synth->config.oscillator_config.values[i]->phase = 0;
1863 ((SynthWindow*)synth->thread->window)->update_gui();
1864 synth->send_configure_change();
1868 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1869 : BC_MenuItem(_("Sine"))
1871 this->synth = synth;
1873 SynthPhaseSine::~SynthPhaseSine()
1877 int SynthPhaseSine::handle_event()
1880 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1882 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1883 new_value = sin(new_value) / 2 + .5;
1884 synth->config.oscillator_config.values[i]->phase = new_value;
1887 ((SynthWindow*)synth->thread->window)->update_gui();
1888 synth->send_configure_change();
1892 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1893 : BC_MenuItem(_("Random"))
1895 this->synth = synth;
1897 SynthPhaseRandom::~SynthPhaseRandom()
1901 int SynthPhaseRandom::handle_event()
1904 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1906 synth->config.oscillator_config.values[i]->phase =
1907 (float)(rand() % 360) / 360;
1910 ((SynthWindow*)synth->thread->window)->update_gui();
1911 synth->send_configure_change();
1916 // ============================ freq calculations
1918 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1919 : BC_MenuItem(_("Random"))
1921 this->synth = synth;
1923 SynthFreqRandom::~SynthFreqRandom()
1927 int SynthFreqRandom::handle_event()
1930 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1932 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1935 ((SynthWindow*)synth->thread->window)->update_gui();
1936 synth->send_configure_change();
1940 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1941 : BC_MenuItem(_("Enumerate"))
1943 this->synth = synth;
1945 SynthFreqEnum::~SynthFreqEnum()
1949 int SynthFreqEnum::handle_event()
1951 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1953 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1956 ((SynthWindow*)synth->thread->window)->update_gui();
1957 synth->send_configure_change();
1961 SynthFreqEven::SynthFreqEven(Synth *synth)
1962 : BC_MenuItem(_("Even"))
1964 this->synth = synth;
1966 SynthFreqEven::~SynthFreqEven()
1970 int SynthFreqEven::handle_event()
1972 if(synth->config.oscillator_config.total)
1973 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1975 for(int i = 1; i < synth->config.oscillator_config.total; i++)
1977 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1980 ((SynthWindow*)synth->thread->window)->update_gui();
1981 synth->send_configure_change();
1985 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1986 : BC_MenuItem(_("Odd"))
1987 { this->synth = synth; }
1988 SynthFreqOdd::~SynthFreqOdd()
1992 int SynthFreqOdd::handle_event()
1994 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1996 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1999 ((SynthWindow*)synth->thread->window)->update_gui();
2000 synth->send_configure_change();
2004 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
2005 : BC_MenuItem(_("Fibonnacci"))
2007 this->synth = synth;
2009 SynthFreqFibonacci::~SynthFreqFibonacci()
2013 int SynthFreqFibonacci::handle_event()
2015 float last_value1 = 0, last_value2 = 1;
2016 for(int i = 0; i < synth->config.oscillator_config.total; i++)
2018 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
2019 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
2020 last_value1 = last_value2;
2021 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
2024 ((SynthWindow*)synth->thread->window)->update_gui();
2025 synth->send_configure_change();
2029 SynthFreqPrime::SynthFreqPrime(Synth *synth)
2030 : BC_MenuItem(_("Prime"))
2032 this->synth = synth;
2034 SynthFreqPrime::~SynthFreqPrime()
2038 int SynthFreqPrime::handle_event()
2041 for(int i = 0; i < synth->config.oscillator_config.total; i++)
2043 synth->config.oscillator_config.values[i]->freq_factor = number;
2044 number = get_next_prime(number);
2047 ((SynthWindow*)synth->thread->window)->update_gui();
2048 synth->send_configure_change();
2052 float SynthFreqPrime::get_next_prime(float number)
2061 for(float i = number - 1; i > 1 && !result; i--)
2063 if((number / i) - (int)(number / i) == 0) result = 1;
2077 SynthOscillatorConfig::SynthOscillatorConfig(int number)
2080 this->number = number;
2083 SynthOscillatorConfig::~SynthOscillatorConfig()
2087 void SynthOscillatorConfig::reset()
2095 void SynthOscillatorConfig::read_data(FileXML *file)
2097 level = file->tag.get_property("LEVEL", (float)level);
2098 phase = file->tag.get_property("PHASE", (float)phase);
2099 freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
2102 void SynthOscillatorConfig::save_data(FileXML *file)
2104 file->tag.set_title("OSCILLATOR");
2105 file->tag.set_property("LEVEL", (float)level);
2106 file->tag.set_property("PHASE", (float)phase);
2107 file->tag.set_property("FREQFACTOR", (float)freq_factor);
2109 file->append_newline();
2112 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
2114 if(EQUIV(level, that.level) &&
2115 EQUIV(phase, that.phase) &&
2116 EQUIV(freq_factor, that.freq_factor))
2122 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
2126 freq_factor = that.freq_factor;
2130 SynthConfig::SynthConfig()
2135 SynthConfig::~SynthConfig()
2137 oscillator_config.remove_all_objects();
2140 void SynthConfig::reset()
2144 for(int i = 1; i < MAX_FREQS; i++)
2146 wavefunction = SINE;
2147 for(int i = 0; i < oscillator_config.total; i++)
2149 oscillator_config.values[i]->reset();
2152 momentary_notes = 0;
2155 int SynthConfig::equivalent(SynthConfig &that)
2157 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
2158 for(int i = 0; i < MAX_FREQS; i++)
2159 if(base_freq[i] != that.base_freq[i]) return 0;
2161 if(wavefunction != that.wavefunction ||
2162 oscillator_config.total != that.oscillator_config.total ||
2163 momentary_notes != that.momentary_notes) return 0;
2165 for(int i = 0; i < oscillator_config.total; i++)
2167 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
2174 void SynthConfig::copy_from(SynthConfig& that)
2176 wetness = that.wetness;
2177 for(int i = 0; i < MAX_FREQS; i++)
2178 base_freq[i] = that.base_freq[i];
2179 wavefunction = that.wavefunction;
2180 momentary_notes = that.momentary_notes;
2184 i < oscillator_config.total && i < that.oscillator_config.total;
2187 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2191 i < that.oscillator_config.total;
2194 oscillator_config.append(new SynthOscillatorConfig(i));
2195 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2199 i < oscillator_config.total;
2202 oscillator_config.remove_object();
2207 void SynthConfig::interpolate(SynthConfig &prev,
2211 int64_t current_frame)
2213 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
2214 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
2217 wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
2218 // base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);
2220 momentary_notes = prev.momentary_notes;