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 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;
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->xbuf);
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()
179 if( !thread ) return;
180 SynthWindow *window = (SynthWindow*)thread->window;
181 // load_configuration,read_data deletes oscillator_config
182 window->lock_window("Synth::update_gui");
183 if( load_configuration() )
184 window->update_gui();
185 window->unlock_window();
189 void Synth::add_oscillator()
191 if(config.oscillator_config.total > 20) return;
193 config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
196 void Synth::delete_oscillator()
198 if(config.oscillator_config.total)
200 config.oscillator_config.remove_object();
205 double Synth::get_total_power()
209 if(config.wavefunction == DC) return 1.0;
211 for(int i = 0; i < config.oscillator_config.total; i++)
213 result += db.fromdb(config.oscillator_config.values[i]->level);
216 if(result == 0) result = 1; // prevent division by 0
221 double Synth::solve_eqn(double *output,
224 double normalize_constant,
227 SynthOscillatorConfig *config =
228 this->config.oscillator_config.values[oscillator];
229 if(config->level <= INFINITYGAIN) return 0;
231 double power = this->db.fromdb(config->level) * normalize_constant;
232 // Period of fundamental frequency in samples
233 double orig_period = (double)get_samplerate() /
235 // Starting sample in waveform
236 double x = waveform_sample;
237 double phase_offset = config->phase * orig_period;
238 //printf("Synth::solve_eqn %d %f\n", __LINE__, config->phase);
239 // Period of current oscillator
240 double period = orig_period / config->freq_factor;
243 if(get_direction() == PLAY_REVERSE) step = -1;
245 switch(this->config.wavefunction)
248 for(sample = 0; sample < length; sample++)
250 output[sample] += power;
255 for(sample = 0; sample < length; sample++)
257 output[sample] += sin((x + phase_offset) /
258 period * 2 * M_PI) * power;
264 for(sample = 0; sample < length; sample++)
266 output[sample] += function_sawtooth((x + phase_offset) /
273 for(sample = 0; sample < length; sample++)
275 output[sample] += function_square((x + phase_offset) /
282 for(sample = 0; sample < length; sample++)
284 output[sample] += function_triangle((x + phase_offset) /
291 for(sample = 0; sample < length; sample++)
293 output[sample] += function_pulse((x + phase_offset) /
300 for(sample = 0; sample < length; sample++)
302 output[sample] += function_noise() * power;
309 double Synth::get_point(float x, double normalize_constant)
312 for(int i = 0; i < config.oscillator_config.total; i++)
313 result += get_oscillator_point(x, normalize_constant, i);
318 double Synth::get_oscillator_point(float x,
319 double normalize_constant,
322 SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
323 double power = db.fromdb(config->level) * normalize_constant;
324 switch(this->config.wavefunction)
329 return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
331 return function_sawtooth((x + config->phase) * config->freq_factor) * power;
333 return function_square((x + config->phase) * config->freq_factor) * power;
335 return function_triangle((x + config->phase) * config->freq_factor) * power;
337 return function_pulse((x + config->phase) * config->freq_factor) * power;
339 return function_noise() * power;
344 double Synth::function_square(double x)
346 x -= (int)x; // only fraction counts
347 return (x < .5) ? -1 : 1;
350 double Synth::function_pulse(double x)
352 x -= (int)x; // only fraction counts
353 return (x < .5) ? 0 : 1;
356 double Synth::function_noise()
358 return (double)(rand() % 65536 - 32768) / 32768;
361 double Synth::function_sawtooth(double x)
367 double Synth::function_triangle(double x)
370 return (x < .5) ? 1 - x * 4 : -3 + x * 4;
373 int Synth::process_realtime(int64_t size,
377 // sample relative to start of plugin
378 waveform_sample = get_source_position();
380 need_reconfigure |= load_configuration();
381 if(need_reconfigure) reconfigure();
383 double wetness = DB::fromdb(config.wetness);
384 if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
387 double *output_samples = output_ptr->get_data();
388 double *input_samples = input_ptr->get_data();
389 for(int j = 0; j < size; j++)
390 output_samples[j] = input_samples[j] * wetness;
392 // Overlay each frequency
393 for(int j = 0; j < MAX_FREQS; j++)
395 if(!EQUIV(config.base_freq[j], 0))
402 input_ptr->get_data(),
403 output_ptr->get_data());
404 //printf("Synth::process_realtime 2\n");
408 // waveform_sample += size;
412 int Synth::overlay_synth(double freq,
417 double normalize_constant = 1.0 / get_total_power();
418 for(int i = 0; i < config.oscillator_config.total; i++)
419 solve_eqn(output, length, freq, normalize_constant, i);
423 void Synth::reconfigure()
425 need_reconfigure = 0;
426 // waveform_sample = 0;
429 int Synth::freq_exists(double freq)
431 for(int i = 0; i < MAX_FREQS; i++)
434 // printf("Synth::freq_exists %d %d %f %f\n",
438 // config.base_freq[i]);
439 if(fabs(freq - config.base_freq[i]) < 1.0)
446 void Synth::new_freq(double freq)
449 for(int i = 0; i < MAX_FREQS; i++)
451 if(EQUIV(config.base_freq[i], freq)) return;
454 for(int i = 0; i < MAX_FREQS; i++)
456 if(EQUIV(config.base_freq[i], 0))
458 config.base_freq[i] = freq;
459 //printf("Synth::new_freq %d\n", __LINE__);
465 void Synth::delete_freq(double freq)
467 for(int i = 0; i < MAX_FREQS; i++)
469 if(EQUIV(config.base_freq[i], freq))
471 //printf("Synth::delete_freq %d\n", __LINE__);
472 // Shift frequencies back
473 for(int j = i; j < MAX_FREQS - 1; j++)
475 config.base_freq[j] = config.base_freq[j + 1];
477 config.base_freq[MAX_FREQS - 1] = 0;
484 void Synth::delete_freqs()
486 for(int i = 0; i < MAX_FREQS; i++)
487 config.base_freq[i] = 0;
491 SynthWindow::SynthWindow(Synth *synth)
492 : PluginClientWindow(synth, synth->window_w, synth->window_h,
502 bzero(notes, sizeof(SynthNote*) * TOTALNOTES);
506 SynthWindow::~SynthWindow()
516 static const char *keyboard_map[] =
518 "q", "2", "w", "3", "e", "r", "5", "t", "6", "y", "7", "u",
519 "z", "s", "x", "d", "c", "v", "g", "b", "h", "n", "j", "m"
522 void SynthWindow::create_objects()
525 add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
527 BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
528 menu->add_menu(levelmenu = new BC_Menu(_("Level")));
529 menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
530 menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
532 levelmenu->add_item(new SynthLevelInvert(synth));
533 levelmenu->add_item(new SynthLevelMax(synth));
534 levelmenu->add_item(new SynthLevelRandom(synth));
535 levelmenu->add_item(new SynthLevelSine(synth));
536 levelmenu->add_item(new SynthLevelSlope(synth));
537 levelmenu->add_item(new SynthLevelZero(synth));
539 phasemenu->add_item(new SynthPhaseInvert(synth));
540 phasemenu->add_item(new SynthPhaseRandom(synth));
541 phasemenu->add_item(new SynthPhaseSine(synth));
542 phasemenu->add_item(new SynthPhaseZero(synth));
544 harmonicmenu->add_item(new SynthFreqEnum(synth));
545 harmonicmenu->add_item(new SynthFreqEven(synth));
546 harmonicmenu->add_item(new SynthFreqFibonacci(synth));
547 harmonicmenu->add_item(new SynthFreqOdd(synth));
548 harmonicmenu->add_item(new SynthFreqPrime(synth));
550 int xs10 = xS(10), xs20 = xS(20), xs50 = xS(50), xs70 = xS(70), xs75 = xS(75), xs240 = xS(240), xs265 = xS(265);
551 int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40), ys220 = yS(220);
552 int x = xs10, y = ys30;
554 add_subwindow(new BC_Title(x, y, _("Waveform")));
556 add_subwindow(new BC_Title(x, y, _("Wave Function")));
559 add_subwindow(canvas = new SynthCanvas(synth, this, x, y, xS(230), yS(160)));
563 char string[BCTEXTLEN];
564 waveform_to_text(string, synth->config.wavefunction);
566 add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
567 waveform->create_objects();
569 int x1 = x + waveform->get_w() + xs10;
572 add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
574 add_subwindow(base_freq = new SynthBaseFreq(synth, this, x, y));
575 base_freq->update((float)synth->config.base_freq[0]);
576 x += base_freq->get_w() + synth->get_theme()->widget_border;
577 add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - ys10));
578 base_freq->freq_pot = freqpot;
579 freqpot->freq_text = base_freq;
580 x -= base_freq->get_w() + synth->get_theme()->widget_border;
582 add_subwindow(new BC_Title(x, y, _("Wetness:")));
583 add_subwindow(wetness = new SynthWetness(synth, x + xs70, y - ys10));
586 add_subwindow(new SynthClear(synth, x, y));
591 add_subwindow(new BC_Title(x, y, _("Level")));
593 add_subwindow(new BC_Title(x, y, _("Phase")));
595 add_subwindow(new BC_Title(x, y, _("Harmonic")));
600 add_subwindow(osc_subwindow = new BC_SubWindow(x, y, xs265, get_h() - y));
602 add_subwindow(osc_scroll = new OscScroll(synth, this, x, y, get_h() - y));
606 add_subwindow(new SynthAddOsc(synth, this, x, y));
608 add_subwindow(new SynthDelOsc(synth, this, x, y));
613 #include "white_up_png.h"
614 #include "white_hi_png.h"
615 #include "white_dn_png.h"
616 #include "white_checked_png.h"
617 #include "white_checkedhi_png.h"
618 #include "black_up_png.h"
619 #include "black_hi_png.h"
620 #include "black_dn_png.h"
621 #include "black_checked_png.h"
622 #include "black_checkedhi_png.h"
623 white_key[0] = new VFramePng(white_up_png);
624 white_key[1] = new VFramePng(white_hi_png);
625 white_key[2] = new VFramePng(white_checked_png);
626 white_key[3] = new VFramePng(white_dn_png);
627 white_key[4] = new VFramePng(white_checkedhi_png);
628 black_key[0] = new VFramePng(black_up_png);
629 black_key[1] = new VFramePng(black_hi_png);
630 black_key[2] = new VFramePng(black_checked_png);
631 black_key[3] = new VFramePng(black_dn_png);
632 black_key[4] = new VFramePng(black_checkedhi_png);
635 add_subwindow(note_subwindow = new BC_SubWindow(x1+xS(20),
637 get_w() - (x1+xS(20)),
638 white_key[0]->get_h() + MARGIN +
639 get_text_height(MEDIUMFONT) + MARGIN +
640 get_text_height(MEDIUMFONT) + MARGIN));
641 add_subwindow(note_scroll = new NoteScroll(synth,
644 note_subwindow->get_y() + note_subwindow->get_h(),
645 note_subwindow->get_w()));
647 add_subwindow(momentary = new SynthMomentary(this, x1,
648 note_scroll->get_y() + note_scroll->get_h() + MARGIN,
649 _("Momentary notes")));
652 add_subwindow(note_instructions = new BC_Title( x1,
653 momentary->get_y() + momentary->get_h() + MARGIN,
654 _("Ctrl or Shift to select multiple notes.")));
657 update_oscillators();
663 int SynthWindow::keypress_event()
665 if(ctrl_down() && get_keypress() == 'w')
673 int SynthWindow::resize_event(int w, int h)
675 clear_box(0, 0, w, h);
676 osc_subwindow->reposition_window(osc_subwindow->get_x(),
677 osc_subwindow->get_y(),
678 osc_subwindow->get_w(),
679 h - osc_subwindow->get_y());
680 osc_subwindow->clear_box(0, 0, osc_subwindow->get_w(), osc_subwindow->get_h());
681 osc_scroll->reposition_window(osc_scroll->get_x(),
683 h - osc_scroll->get_y());
684 note_subwindow->reposition_window(note_subwindow->get_x(),
685 note_subwindow->get_y(),
686 w - note_subwindow->get_x(),
687 note_subwindow->get_h());
688 note_scroll->reposition_window(note_scroll->get_x(),
689 note_scroll->get_y(),
690 w - note_scroll->get_x());
691 note_scroll->update_length(white_key[0]->get_w() * TOTALNOTES * 7 / 12 +
692 white_key[0]->get_w(),
693 note_scroll->get_position(),
694 note_subwindow->get_w(),
699 update_oscillators();
705 void SynthWindow::update_gui()
707 char string[BCTEXTLEN];
708 freqpot->update((int)synth->config.base_freq[0]);
709 base_freq->update((float)synth->config.base_freq[0]);
710 wetness->update(synth->config.wetness);
711 waveform_to_text(string, synth->config.wavefunction);
712 waveform->set_text(string);
713 momentary->update(synth->config.momentary_notes);
716 update_oscillators();
718 update_note_selection();
722 void SynthWindow::update_scrollbar()
724 osc_scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
725 osc_scroll->get_position(),
726 osc_subwindow->get_h(),
731 void SynthWindow::update_whitekey(int number,
738 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
739 white_key, number, x, y));
740 if(number >= FIRST_TITLE && number < LAST_TITLE)
741 note_subwindow->add_subwindow(
742 note_titles[(*current_title)++] = new BC_Title(
743 x + text_white_margin,
745 keyboard_map[number - FIRST_TITLE]));
746 //printf("SynthWindow::update_whitekey %d\n", __LINE__);
750 notes[number]->reposition_window(x, y);
751 if(number >= FIRST_TITLE && number < LAST_TITLE)
752 note_titles[(*current_title)++]->reposition_window(x + text_white_margin,
758 void SynthWindow::update_blackkey(int number,
765 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
766 black_key, number, x, y));
767 if(number >= FIRST_TITLE && number < LAST_TITLE)
768 note_subwindow->add_subwindow(
769 note_titles[(*current_title)++] = new BC_Title(x + text_black_margin,
771 keyboard_map[number - FIRST_TITLE]));
775 notes[number]->reposition_window(x, y);
776 if(number >= FIRST_TITLE && number < LAST_TITLE)
777 note_titles[(*current_title)++]->reposition_window(x + text_black_margin,
782 void SynthWindow::update_notes()
784 //int octave_w = white_key[0]->get_w() * 7;
785 int white_w = white_key[0]->get_w();
786 int black_w = black_key[0]->get_w();
787 int white_w1 = white_w - black_w / 2 - 2;
788 int white_w2 = white_w / 2;
789 int white_w3 = white_w * 2 / 3;
792 y1 = y + white_key[0]->get_h() + 10;
793 y2 = y1 + get_text_height(MEDIUMFONT) + 10;
794 y3 = y2 + get_text_height(MEDIUMFONT) + 10;
795 text_black_margin = black_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
796 text_white_margin = white_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
799 //printf("SynthWindow::update_notes %d\n", __LINE__);
800 note_subwindow->clear_box(0, 0, get_w(), get_h());
802 note_subwindow->set_color(get_resources()->default_text_color);
805 // To get the stacking order:
806 // pass 0 is white keys
807 // pass 1 is black keys
808 int current_title = 0;
809 for(int pass = 0; pass < 2; pass++)
811 x = -note_scroll->get_position();
813 for(int i = 0; i < TOTALNOTES; i++)
815 int octave_note = i % 12;
822 update_whitekey(i, ¤t_title, x, y);
828 update_whitekey(i, ¤t_title, x, y);
834 update_whitekey(i, ¤t_title, x, y);
838 update_whitekey(i, ¤t_title, x, y);
844 update_whitekey(i, ¤t_title, x, y);
850 update_whitekey(i, ¤t_title, x, y);
856 update_whitekey(i, ¤t_title, x, y);
867 update_blackkey(i, ¤t_title, x + white_w2, y);
871 update_blackkey(i, ¤t_title, x + white_w3, y);
878 update_blackkey(i, ¤t_title, x + white_w2, y);
882 update_blackkey(i, ¤t_title, x + white_w1, y);
886 update_blackkey(i, ¤t_title, x + white_w3, y);
898 void SynthWindow::update_note_selection()
900 for(int i = 0; i < TOTALNOTES; i++)
903 for(int j = 0; j < MAX_FREQS; j++)
905 if(synth->freq_exists(keyboard_freqs[notes[i]->number]))
914 notes[i]->set_value(1);
917 notes[i]->set_value(0);
922 void SynthWindow::update_oscillators()
924 int i, y = -osc_scroll->get_position();
928 // Add new oscillators
930 i < synth->config.oscillator_config.total;
934 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
936 if(oscillators.total <= i)
938 oscillators.append(gui = new SynthOscGUI(this, i));
939 gui->create_objects(y);
943 gui = oscillators.values[i];
945 gui->title->reposition_window(gui->title->get_x(), y + yS(15));
947 gui->level->reposition_window(gui->level->get_x(), y);
948 gui->level->update(config->level);
950 gui->phase->reposition_window(gui->phase->get_x(), y);
951 gui->phase->update((int64_t)(config->phase * 360));
953 gui->freq->reposition_window(gui->freq->get_x(), y);
954 gui->freq->update((int64_t)(config->freq_factor));
956 y += OSCILLATORHEIGHT;
959 // Delete old oscillators
961 i < oscillators.total;
963 oscillators.remove_object();
967 int SynthWindow::waveform_to_text(char *text, int waveform)
971 case DC: sprintf(text, _("DC")); break;
972 case SINE: sprintf(text, _("Sine")); break;
973 case SAWTOOTH: sprintf(text, _("Sawtooth")); break;
974 case SQUARE: sprintf(text, _("Square")); break;
975 case TRIANGLE: sprintf(text, _("Triangle")); break;
976 case PULSE: sprintf(text, _("Pulse")); break;
977 case NOISE: sprintf(text, _("Noise")); break;
983 SynthMomentary::SynthMomentary(SynthWindow *window, int x, int y, char *text)
984 : BC_CheckBox(x, y, window->synth->config.momentary_notes, text)
986 this->window = window;
989 int SynthMomentary::handle_event()
991 window->synth->config.momentary_notes = get_value();
992 window->synth->send_configure_change();
999 SynthNote::SynthNote(SynthWindow *window, VFrame **images, int number, int x, int y)
1000 : BC_Toggle(x, y, images, window->synth->freq_exists(keyboard_freqs[number]))
1002 this->window = window;
1003 this->number = number;
1009 void SynthNote::start_note()
1011 if(window->synth->config.momentary_notes) note_on = 1;
1013 //printf("SynthNote::start_note %d %d\n", __LINE__, ctrl_down());
1014 if(window->synth->config.momentary_notes || (!ctrl_down() && !shift_down()))
1016 // Kill all frequencies
1017 window->synth->delete_freqs();
1020 window->synth->new_freq(keyboard_freqs[number]);
1021 window->base_freq->update((float)window->synth->config.base_freq[0]);
1022 //printf("SynthNote::start_note %d %f\n", __LINE__, window->synth->config.base_freq[0]);
1023 window->freqpot->update(window->synth->config.base_freq[0]);
1024 window->synth->send_configure_change();
1025 window->update_note_selection();
1028 void SynthNote::stop_note()
1031 window->synth->delete_freq(keyboard_freqs[number]);
1032 window->base_freq->update((float)window->synth->config.base_freq[0]);
1033 window->freqpot->update(window->synth->config.base_freq[0]);
1034 window->synth->send_configure_change();
1035 window->update_note_selection();
1038 int SynthNote::keypress_event()
1040 if(number >= FIRST_TITLE && number < LAST_TITLE)
1042 if(get_keypress() == keyboard_map[number - FIRST_TITLE][0])
1044 if((ctrl_down() || shift_down()) &&
1045 window->synth->freq_exists(keyboard_freqs[number]))
1055 // Key releases are repeated, so momentary notes may not work
1062 int SynthNote::keyrelease_event()
1064 if(note_on && window->synth->config.momentary_notes)
1073 int SynthNote::cursor_motion_event()
1076 if(window->current_note > -1)
1078 int cursor_x = get_relative_cursor_x();
1079 int cursor_y = get_relative_cursor_y();
1080 if(cursor_x >= 0 && cursor_x < get_w() &&
1081 cursor_y >= 0 && cursor_y < get_h())
1083 if(window->starting_notes)
1092 window->current_note = number;
1099 int SynthNote::button_press_event()
1101 if(BC_Toggle::button_press_event())
1103 // printf("SynthNote::button_press_event %d %d %d\n",
1106 // window->synth->freq_exists(keyboard_freqs[number]));
1107 window->starting_notes = 1;
1108 if((ctrl_down() || shift_down()) &&
1109 window->synth->freq_exists(keyboard_freqs[number]))
1111 //printf("SynthNote::button_press_event %d\n", __LINE__);
1113 window->starting_notes = 0;
1117 //printf("SynthNote::button_press_event %d\n", __LINE__);
1119 window->starting_notes = 1;
1121 window->current_note = number;
1127 int SynthNote::button_release_event()
1129 // Change frequency permanently
1130 if(window->current_note == number)
1132 if(window->synth->config.momentary_notes)
1134 // Mute on button release
1138 window->current_note = -1;
1141 return BC_Toggle::button_release_event();
1144 int SynthNote::draw_face(int flash, int flush)
1146 BC_Toggle::draw_face(0, 0);
1147 static const char *titles[] =
1164 const char *text = titles[number % (sizeof(titles) / sizeof(char*))];
1165 char string[BCTEXTLEN];
1166 sprintf(string, "%s%d", text, number / 12);
1167 //printf("SynthNote::draw_face %d %d %d %d %s\n", __LINE__, number, get_w(), get_h(), text);
1174 draw_text(get_w() / 2 - get_text_width(MEDIUMFONT, string) / 2,
1175 get_h() - get_text_height(MEDIUMFONT, string) - window->synth->get_theme()->widget_border,
1179 if(flash) this->flash(0);
1180 if(flush) this->flush();
1185 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
1187 this->window = window;
1188 this->number = number;
1191 SynthOscGUI::~SynthOscGUI()
1199 void SynthOscGUI::create_objects(int y)
1201 char text[BCTEXTLEN];
1202 sprintf(text, "%d:", number + 1);
1203 window->osc_subwindow->add_subwindow(title = new BC_Title(xS(10), y+yS(15), text));
1205 window->osc_subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
1206 window->osc_subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
1207 window->osc_subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
1213 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
1214 : BC_FPot(xS(50), y,
1215 synth->config.oscillator_config.values[gui->number]->level,
1218 this->synth = synth;
1222 SynthOscGUILevel::~SynthOscGUILevel()
1226 int SynthOscGUILevel::handle_event()
1228 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1229 config->level = get_value();
1230 gui->window->canvas->update();
1231 synth->send_configure_change();
1237 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
1238 : BC_IPot(xS(125), y,
1239 (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360),
1242 this->synth = synth;
1246 SynthOscGUIPhase::~SynthOscGUIPhase()
1250 int SynthOscGUIPhase::handle_event()
1252 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1253 config->phase = (float)get_value() / 360;
1254 gui->window->canvas->update();
1255 synth->send_configure_change();
1261 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
1262 : BC_IPot(xS(200), y,
1263 (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor),
1266 this->synth = synth;
1270 SynthOscGUIFreq::~SynthOscGUIFreq()
1274 int SynthOscGUIFreq::handle_event()
1276 SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1277 config->freq_factor = get_value();
1278 gui->window->canvas->update();
1279 synth->send_configure_change();
1284 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
1285 : BC_GenericButton(x, y, _("Add"))
1287 this->synth = synth;
1288 this->window = window;
1291 SynthAddOsc::~SynthAddOsc()
1295 int SynthAddOsc::handle_event()
1297 synth->add_oscillator();
1298 synth->send_configure_change();
1299 window->update_gui();
1304 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
1305 : BC_GenericButton(x, y, _("Delete"))
1307 this->synth = synth;
1308 this->window = window;
1311 SynthDelOsc::~SynthDelOsc()
1315 int SynthDelOsc::handle_event()
1317 synth->delete_oscillator();
1318 synth->send_configure_change();
1319 window->update_gui();
1324 OscScroll::OscScroll(Synth *synth, SynthWindow *window,
1325 int x, int y, int h)
1326 : BC_ScrollBar(x, y, SCROLL_VERT, h,
1327 synth->config.oscillator_config.total * OSCILLATORHEIGHT,
1328 0, window->osc_subwindow->get_h())
1330 this->synth = synth;
1331 this->window = window;
1334 OscScroll::~OscScroll()
1338 int OscScroll::handle_event()
1340 window->update_oscillators();
1346 NoteScroll::NoteScroll(Synth *synth, SynthWindow *window,
1347 int x, int y, int w)
1348 : BC_ScrollBar(x, y, SCROLL_HORIZ, w,
1349 window->white_key[0]->get_w() * TOTALNOTES * 7 / 12 + window->white_key[0]->get_w(),
1350 0, window->note_subwindow->get_w())
1352 this->synth = synth;
1353 this->window = window;
1356 NoteScroll::~NoteScroll()
1360 int NoteScroll::handle_event()
1362 window->update_notes();
1367 SynthClear::SynthClear(Synth *synth, int x, int y)
1368 : BC_GenericButton(x, y, _("Clear"))
1370 this->synth = synth;
1372 SynthClear::~SynthClear()
1375 int SynthClear::handle_event()
1377 synth->config.reset();
1378 synth->send_configure_change();
1379 synth->update_gui();
1384 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
1385 : BC_PopupMenu(x, y, xS(120), text)
1387 this->synth = synth;
1390 SynthWaveForm::~SynthWaveForm()
1394 void SynthWaveForm::create_objects()
1396 // add_item(new SynthWaveFormItem(synth, _("DC"), DC));
1397 add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
1398 add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
1399 add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
1400 add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
1401 add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
1402 add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
1405 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1408 this->synth = synth;
1409 this->value = value;
1412 SynthWaveFormItem::~SynthWaveFormItem()
1416 int SynthWaveFormItem::handle_event()
1418 synth->config.wavefunction = value;
1419 ((SynthWindow*)synth->thread->window)->canvas->update();
1420 get_popup_menu()->set_text(get_text());
1421 synth->send_configure_change();
1426 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1427 : BC_FPot(x, y, synth->config.wetness, INFINITYGAIN, 0)
1429 this->synth = synth;
1432 int SynthWetness::handle_event()
1434 synth->config.wetness = get_value();
1435 synth->send_configure_change();
1441 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1442 : BC_QPot(x, y, synth->config.base_freq[0])
1444 this->synth = synth;
1445 this->window = window;
1447 SynthFreqPot::~SynthFreqPot()
1450 int SynthFreqPot::handle_event()
1452 if(get_value() > 0 && get_value() < 30000)
1454 synth->config.base_freq[0] = get_value();
1455 freq_text->update(get_value());
1456 synth->send_configure_change();
1457 window->update_note_selection();
1464 SynthBaseFreq::SynthBaseFreq(Synth *synth, SynthWindow *window, int x, int y)
1465 : BC_TextBox(x, y, xS(100), 1, (float)0)
1467 this->synth = synth;
1468 this->window = window;
1471 SynthBaseFreq::~SynthBaseFreq()
1474 int SynthBaseFreq::handle_event()
1476 double new_value = atof(get_text());
1478 if(new_value < 30000)
1480 synth->config.base_freq[0] = new_value;
1481 freq_pot->update(synth->config.base_freq[0]);
1482 synth->send_configure_change();
1483 window->update_note_selection();
1492 SynthCanvas::SynthCanvas(Synth *synth, SynthWindow *window,
1493 int x, int y, int w, int h)
1494 : BC_SubWindow(x, y, w, h, BLACK)
1496 this->synth = synth;
1497 this->window = window;
1500 SynthCanvas::~SynthCanvas()
1504 int SynthCanvas::update()
1508 clear_box(0, 0, get_w(), get_h());
1511 draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1515 double normalize_constant = (double)1 / synth->get_total_power();
1516 y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1518 for(int i = 1; i < get_w(); i++)
1520 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1521 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1529 // ======================= level calculations
1530 SynthLevelZero::SynthLevelZero(Synth *synth)
1531 : BC_MenuItem(_("Zero"))
1533 this->synth = synth;
1536 SynthLevelZero::~SynthLevelZero()
1540 int SynthLevelZero::handle_event()
1542 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1544 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1547 ((SynthWindow*)synth->thread->window)->update_gui();
1548 synth->send_configure_change();
1552 SynthLevelMax::SynthLevelMax(Synth *synth)
1553 : BC_MenuItem(_("Maximum"))
1555 this->synth = synth;
1558 SynthLevelMax::~SynthLevelMax()
1562 int SynthLevelMax::handle_event()
1564 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1566 synth->config.oscillator_config.values[i]->level = 0;
1568 ((SynthWindow*)synth->thread->window)->update_gui();
1569 synth->send_configure_change();
1573 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1574 : BC_MenuItem(_("Normalize"))
1576 this->synth = synth;
1579 SynthLevelNormalize::~SynthLevelNormalize()
1583 int SynthLevelNormalize::handle_event()
1588 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1590 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1593 float scale = 1 / total;
1596 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1598 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1600 new_value = synth->db.todb(new_value);
1602 synth->config.oscillator_config.values[i]->level = new_value;
1605 ((SynthWindow*)synth->thread->window)->update_gui();
1606 synth->send_configure_change();
1610 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1611 : BC_MenuItem(_("Slope"))
1613 this->synth = synth;
1616 SynthLevelSlope::~SynthLevelSlope()
1620 int SynthLevelSlope::handle_event()
1622 float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1624 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1626 synth->config.oscillator_config.values[i]->level = i * slope;
1629 ((SynthWindow*)synth->thread->window)->update_gui();
1630 synth->send_configure_change();
1634 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1635 : BC_MenuItem(_("Random"))
1637 this->synth = synth;
1639 SynthLevelRandom::~SynthLevelRandom()
1643 int SynthLevelRandom::handle_event()
1646 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1648 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1651 ((SynthWindow*)synth->thread->window)->update_gui();
1652 synth->send_configure_change();
1656 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1657 : BC_MenuItem(_("Invert"))
1659 this->synth = synth;
1661 SynthLevelInvert::~SynthLevelInvert()
1665 int SynthLevelInvert::handle_event()
1667 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1669 synth->config.oscillator_config.values[i]->level =
1670 INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1673 ((SynthWindow*)synth->thread->window)->update_gui();
1674 synth->send_configure_change();
1678 SynthLevelSine::SynthLevelSine(Synth *synth)
1679 : BC_MenuItem(_("Sine"))
1681 this->synth = synth;
1683 SynthLevelSine::~SynthLevelSine()
1687 int SynthLevelSine::handle_event()
1691 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1693 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1694 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1695 synth->config.oscillator_config.values[i]->level = new_value;
1698 ((SynthWindow*)synth->thread->window)->update_gui();
1699 synth->send_configure_change();
1703 // ============================ phase calculations
1705 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1706 : BC_MenuItem(_("Invert"))
1708 this->synth = synth;
1710 SynthPhaseInvert::~SynthPhaseInvert()
1714 int SynthPhaseInvert::handle_event()
1716 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1718 synth->config.oscillator_config.values[i]->phase =
1719 1 - synth->config.oscillator_config.values[i]->phase;
1722 ((SynthWindow*)synth->thread->window)->update_gui();
1723 synth->send_configure_change();
1727 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1728 : BC_MenuItem(_("Zero"))
1730 this->synth = synth;
1732 SynthPhaseZero::~SynthPhaseZero()
1736 int SynthPhaseZero::handle_event()
1738 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1740 synth->config.oscillator_config.values[i]->phase = 0;
1743 ((SynthWindow*)synth->thread->window)->update_gui();
1744 synth->send_configure_change();
1748 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1749 : BC_MenuItem(_("Sine"))
1751 this->synth = synth;
1753 SynthPhaseSine::~SynthPhaseSine()
1757 int SynthPhaseSine::handle_event()
1760 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1762 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1763 new_value = sin(new_value) / 2 + .5;
1764 synth->config.oscillator_config.values[i]->phase = new_value;
1767 ((SynthWindow*)synth->thread->window)->update_gui();
1768 synth->send_configure_change();
1772 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1773 : BC_MenuItem(_("Random"))
1775 this->synth = synth;
1777 SynthPhaseRandom::~SynthPhaseRandom()
1781 int SynthPhaseRandom::handle_event()
1784 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1786 synth->config.oscillator_config.values[i]->phase =
1787 (float)(rand() % 360) / 360;
1790 ((SynthWindow*)synth->thread->window)->update_gui();
1791 synth->send_configure_change();
1796 // ============================ freq calculations
1798 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1799 : BC_MenuItem(_("Random"))
1801 this->synth = synth;
1803 SynthFreqRandom::~SynthFreqRandom()
1807 int SynthFreqRandom::handle_event()
1810 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1812 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1815 ((SynthWindow*)synth->thread->window)->update_gui();
1816 synth->send_configure_change();
1820 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1821 : BC_MenuItem(_("Enumerate"))
1823 this->synth = synth;
1825 SynthFreqEnum::~SynthFreqEnum()
1829 int SynthFreqEnum::handle_event()
1831 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1833 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1836 ((SynthWindow*)synth->thread->window)->update_gui();
1837 synth->send_configure_change();
1841 SynthFreqEven::SynthFreqEven(Synth *synth)
1842 : BC_MenuItem(_("Even"))
1844 this->synth = synth;
1846 SynthFreqEven::~SynthFreqEven()
1850 int SynthFreqEven::handle_event()
1852 if(synth->config.oscillator_config.total)
1853 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1855 for(int i = 1; i < synth->config.oscillator_config.total; i++)
1857 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1860 ((SynthWindow*)synth->thread->window)->update_gui();
1861 synth->send_configure_change();
1865 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1866 : BC_MenuItem(_("Odd"))
1867 { this->synth = synth; }
1868 SynthFreqOdd::~SynthFreqOdd()
1872 int SynthFreqOdd::handle_event()
1874 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1876 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1879 ((SynthWindow*)synth->thread->window)->update_gui();
1880 synth->send_configure_change();
1884 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
1885 : BC_MenuItem(_("Fibonnacci"))
1887 this->synth = synth;
1889 SynthFreqFibonacci::~SynthFreqFibonacci()
1893 int SynthFreqFibonacci::handle_event()
1895 float last_value1 = 0, last_value2 = 1;
1896 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1898 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1899 if(synth->config.oscillator_config.values[i]->freq_factor > 100)
1900 synth->config.oscillator_config.values[i]->freq_factor = 100;
1901 last_value1 = last_value2;
1902 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1905 ((SynthWindow*)synth->thread->window)->update_gui();
1906 synth->send_configure_change();
1910 SynthFreqPrime::SynthFreqPrime(Synth *synth)
1911 : BC_MenuItem(_("Prime"))
1913 this->synth = synth;
1915 SynthFreqPrime::~SynthFreqPrime()
1919 int SynthFreqPrime::handle_event()
1922 for(int i = 0; i < synth->config.oscillator_config.total; i++)
1924 synth->config.oscillator_config.values[i]->freq_factor = number;
1925 number = get_next_prime(number);
1928 ((SynthWindow*)synth->thread->window)->update_gui();
1929 synth->send_configure_change();
1933 float SynthFreqPrime::get_next_prime(float number)
1942 for(float i = number - 1; i > 1 && !result; i--)
1944 if((number / i) - (int)(number / i) == 0) result = 1;
1958 SynthOscillatorConfig::SynthOscillatorConfig(int number)
1961 this->number = number;
1964 SynthOscillatorConfig::~SynthOscillatorConfig()
1968 void SynthOscillatorConfig::reset()
1976 void SynthOscillatorConfig::read_data(FileXML *file)
1978 level = file->tag.get_property("LEVEL", (float)level);
1979 phase = file->tag.get_property("PHASE", (float)phase);
1980 freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
1983 void SynthOscillatorConfig::save_data(FileXML *file)
1985 file->tag.set_title("OSCILLATOR");
1986 file->tag.set_property("LEVEL", (float)level);
1987 file->tag.set_property("PHASE", (float)phase);
1988 file->tag.set_property("FREQFACTOR", (float)freq_factor);
1990 file->tag.set_title("/OSCILLATOR");
1992 file->append_newline();
1995 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
1997 if(EQUIV(level, that.level) &&
1998 EQUIV(phase, that.phase) &&
1999 EQUIV(freq_factor, that.freq_factor))
2005 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
2009 freq_factor = that.freq_factor;
2013 SynthConfig::SynthConfig()
2018 SynthConfig::~SynthConfig()
2020 oscillator_config.remove_all_objects();
2023 void SynthConfig::reset()
2027 for(int i = 1; i < MAX_FREQS; i++)
2029 wavefunction = SINE;
2030 for(int i = 0; i < oscillator_config.total; i++)
2032 oscillator_config.values[i]->reset();
2035 momentary_notes = 0;
2038 int SynthConfig::equivalent(SynthConfig &that)
2040 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
2041 for(int i = 0; i < MAX_FREQS; i++)
2042 if(base_freq[i] != that.base_freq[i]) return 0;
2044 if(wavefunction != that.wavefunction ||
2045 oscillator_config.total != that.oscillator_config.total ||
2046 momentary_notes != that.momentary_notes) return 0;
2048 for(int i = 0; i < oscillator_config.total; i++)
2050 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
2057 void SynthConfig::copy_from(SynthConfig& that)
2059 wetness = that.wetness;
2060 for(int i = 0; i < MAX_FREQS; i++)
2061 base_freq[i] = that.base_freq[i];
2062 wavefunction = that.wavefunction;
2063 momentary_notes = that.momentary_notes;
2067 i < oscillator_config.total && i < that.oscillator_config.total;
2070 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2074 i < that.oscillator_config.total;
2077 oscillator_config.append(new SynthOscillatorConfig(i));
2078 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2082 i < oscillator_config.total;
2085 oscillator_config.remove_object();
2090 void SynthConfig::interpolate(SynthConfig &prev,
2094 int64_t current_frame)
2096 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
2097 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
2100 wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
2101 // base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);
2103 momentary_notes = prev.momentary_notes;