minor changes; mostly for new Context Help feature
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / synthesizer / synthesizer.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "bchash.h"
25 #include "filexml.h"
26 #include "language.h"
27 #include "samples.h"
28 #include "synthesizer.h"
29 #include "theme.h"
30 #include "transportque.inc"
31 #include "vframe.h"
32
33 #include <string.h>
34
35
36
37
38 REGISTER_PLUGIN(Synth)
39
40
41
42
43 Synth::Synth(PluginServer *server)
44  : PluginAClient(server)
45 {
46         reset();
47         window_w = xS(640);
48         window_h = yS(480);
49 }
50
51
52
53 Synth::~Synth()
54 {
55
56 }
57
58 NEW_WINDOW_MACRO(Synth, SynthWindow);
59
60 const char* Synth::plugin_title() { return N_("Synthesizer"); }
61 int Synth::is_realtime() { return 1; }
62 int Synth::is_synthesis() { return 1; }
63
64
65 void Synth::reset()
66 {
67         need_reconfigure = 1;
68 }
69
70
71
72
73 LOAD_CONFIGURATION_MACRO(Synth, SynthConfig)
74
75
76
77
78
79
80 void Synth::read_data(KeyFrame *keyframe)
81 {
82         FileXML input;
83         char string[BCTEXTLEN];
84 // cause htal file to read directly from text
85         input.set_shared_input(keyframe->xbuf);
86
87 //printf("Synth::read_data %s\n", keyframe->get_data());
88         int result = 0, current_osc = 0;
89         while(!result)
90         {
91                 result = input.read_tag();
92
93                 if(!result)
94                 {
95                         if(input.tag.title_is("SYNTH"))
96                         {
97                                 config.wetness = input.tag.get_property("WETNESS", config.wetness);
98
99                                 if(is_defaults())
100                                 {
101                                         window_w = input.tag.get_property("WINDOW_W", window_w);
102                                         window_h = input.tag.get_property("WINDOW_H", window_h);
103                                 }
104                                 config.momentary_notes = input.tag.get_property("MOMENTARY_NOTES", config.momentary_notes);
105
106 //printf("Synth::read_data %d %d %d\n", __LINE__, window_w, window_h);
107                                 for(int i = 0; i < MAX_FREQS; i++)
108                                 {
109                                         sprintf(string, "BASEFREQ_%d", i);
110                                         config.base_freq[i] = input.tag.get_property(string, (double)0);
111                                 }
112
113                                 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
114                                 // int total_oscillators = input.tag.get_property("OSCILLATORS", 0);
115                         }
116                         else
117                         if(input.tag.title_is("OSCILLATOR"))
118                         {
119                                 if(current_osc >= config.oscillator_config.total)
120                                         config.oscillator_config.append(new SynthOscillatorConfig(current_osc));
121
122                                 config.oscillator_config.values[current_osc]->read_data(&input);
123                                 current_osc++;
124                         }
125                 }
126         }
127
128         while(config.oscillator_config.total > current_osc)
129                 config.oscillator_config.remove_object();
130 }
131
132 void Synth::save_data(KeyFrame *keyframe)
133 {
134         FileXML output;
135         char string[BCTEXTLEN];
136
137 // cause htal file to store data directly in text
138         output.set_shared_output(keyframe->xbuf);
139
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);
145
146         for(int i = 0; i < MAX_FREQS; i++)
147         {
148 //              if(!EQUIV(config.base_freq[i], 0))
149                 {
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);
153                 }
154         }
155
156         output.tag.set_property("WAVEFUNCTION", config.wavefunction);
157         output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
158         output.append_tag();
159         output.append_newline();
160
161         for(int i = 0; i < config.oscillator_config.total; i++)
162         {
163                 config.oscillator_config.values[i]->save_data(&output);
164         }
165
166         output.terminate_string();
167 //printf("Synth::save_data %d %s\n", __LINE__, output.string);
168 // data is now in *text
169 }
170
171
172
173 void Synth::update_gui()
174 {
175         if(thread)
176         {
177                 if(load_configuration())
178                 {
179                         thread->window->lock_window();
180                         ((SynthWindow*)thread->window)->update_gui();
181                         thread->window->unlock_window();
182                 }
183         }
184 }
185
186
187 void Synth::add_oscillator()
188 {
189         if(config.oscillator_config.total > MAX_OSCILLATORS) return;
190
191         config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
192 }
193
194 void Synth::delete_oscillator()
195 {
196         if(config.oscillator_config.total)
197         {
198                 config.oscillator_config.remove_object();
199         }
200 }
201
202
203 double Synth::get_total_power()
204 {
205         double result = 0;
206
207         if(config.wavefunction == DC) return 1.0;
208
209         for(int i = 0; i < config.oscillator_config.total; i++)
210         {
211                 result += db.fromdb(config.oscillator_config.values[i]->level);
212         }
213
214         if(result == 0) result = 1;  // prevent division by 0
215         return result;
216 }
217
218
219 double Synth::solve_eqn(double *output,
220         int length,
221         double freq,
222         double normalize_constant,
223         int oscillator)
224 {
225         SynthOscillatorConfig *config =
226                 this->config.oscillator_config.values[oscillator];
227         if(config->level <= INFINITYGAIN) return 0;
228
229         double power = this->db.fromdb(config->level) * normalize_constant;
230 // Period of fundamental frequency in samples
231         double orig_period = (double)get_samplerate() /
232                 freq;
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;
239         int sample;
240         double step = 1;
241         if(get_direction() == PLAY_REVERSE) step = -1;
242
243         switch(this->config.wavefunction)
244         {
245                 case DC:
246                         for(sample = 0; sample < length; sample++)
247                         {
248                                 output[sample] += power;
249                         }
250                         break;
251
252                 case SINE:
253                         for(sample = 0; sample < length; sample++)
254                         {
255                                 output[sample] += sin((x + phase_offset) /
256                                         period * 2 * M_PI) * power;
257                                 x += step;
258                         }
259                         break;
260
261                 case SAWTOOTH:
262                         for(sample = 0; sample < length; sample++)
263                         {
264                                 output[sample] += function_sawtooth((x + phase_offset) /
265                                         period) * power;
266                                 x += step;
267                         }
268                         break;
269
270                 case SQUARE:
271                         for(sample = 0; sample < length; sample++)
272                         {
273                                 output[sample] += function_square((x + phase_offset) /
274                                         period) * power;
275                                 x += step;
276                         }
277                         break;
278
279                 case TRIANGLE:
280                         for(sample = 0; sample < length; sample++)
281                         {
282                                 output[sample] += function_triangle((x + phase_offset) /
283                                         period) * power;
284                                 x += step;
285                         }
286                         break;
287
288                 case PULSE:
289                         for(sample = 0; sample < length; sample++)
290                         {
291                                 output[sample] += function_pulse((x + phase_offset) /
292                                         period) * power;
293                                 x += step;
294                         }
295                         break;
296
297                 case NOISE:
298                         for(sample = 0; sample < length; sample++)
299                         {
300                                 output[sample] += function_noise() * power;
301                         }
302                         break;
303         }
304         return 0;
305 }
306
307 double Synth::get_point(float x, double normalize_constant)
308 {
309         double result = 0;
310         for(int i = 0; i < config.oscillator_config.total; i++)
311                 result += get_oscillator_point(x, normalize_constant, i);
312
313         return result;
314 }
315
316 double Synth::get_oscillator_point(float x,
317                 double normalize_constant,
318                 int oscillator)
319 {
320         SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
321         double power = db.fromdb(config->level) * normalize_constant;
322         switch(this->config.wavefunction)
323         {
324                 case DC:
325                         return power;
326                         break;
327                 case SINE:
328                         return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
329                         break;
330                 case SAWTOOTH:
331                         return function_sawtooth((x + config->phase) * config->freq_factor) * power;
332                         break;
333                 case SQUARE:
334                         return function_square((x + config->phase) * config->freq_factor) * power;
335                         break;
336                 case TRIANGLE:
337                         return function_triangle((x + config->phase) * config->freq_factor) * power;
338                         break;
339                 case PULSE:
340                         return function_pulse((x + config->phase) * config->freq_factor) * power;
341                         break;
342                 case NOISE:
343                         return function_noise() * power;
344                         break;
345         }
346         return 0;
347 }
348
349 double Synth::function_square(double x)
350 {
351         x -= (int)x; // only fraction counts
352         return (x < .5) ? -1 : 1;
353 }
354
355 double Synth::function_pulse(double x)
356 {
357         x -= (int)x; // only fraction counts
358         return (x < .5) ? 0 : 1;
359 }
360
361 double Synth::function_noise()
362 {
363         return (double)(rand() % 65536 - 32768) / 32768;
364 }
365
366 double Synth::function_sawtooth(double x)
367 {
368         x -= (int)x;
369         return 1 - x * 2;
370 }
371
372 double Synth::function_triangle(double x)
373 {
374         x -= (int)x;
375         return (x < .5) ? 1 - x * 4 : -3 + x * 4;
376 }
377
378 int Synth::process_realtime(int64_t size,
379         Samples *input_ptr,
380         Samples *output_ptr)
381 {
382 // sample relative to start of plugin
383         waveform_sample = get_source_position();
384
385         need_reconfigure |= load_configuration();
386         if(need_reconfigure) reconfigure();
387
388         double wetness = DB::fromdb(config.wetness);
389         if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
390
391 // Apply wetness
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;
396
397 // Overlay each frequency
398         for(int j = 0; j < MAX_FREQS; j++)
399         {
400                 if(!EQUIV(config.base_freq[j], 0))
401                 {
402
403 // Compute fragment
404                         overlay_synth(
405                                 config.base_freq[j],
406                                 size,
407                                 input_ptr->get_data(),
408                                 output_ptr->get_data());
409         //printf("Synth::process_realtime 2\n");
410                 }
411         }
412
413 //      waveform_sample += size;
414         return 0;
415 }
416
417 int Synth::overlay_synth(double freq,
418         int64_t length,
419         double *input,
420         double *output)
421 {
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);
425         return length;
426 }
427
428 void Synth::reconfigure()
429 {
430         need_reconfigure = 0;
431 //      waveform_sample = 0;
432 }
433
434 int Synth::freq_exists(double freq)
435 {
436         for(int i = 0; i < MAX_FREQS; i++)
437         {
438
439 // printf("Synth::freq_exists %d %d %f %f\n",
440 // __LINE__,
441 // i,
442 // freq,
443 // config.base_freq[i]);
444                 if(fabs(freq - config.base_freq[i]) < 1.0)
445                         return 1;
446         }
447
448         return 0;
449 }
450
451 void Synth::new_freq(double freq)
452 {
453 // Check for dupes
454         for(int i = 0; i < MAX_FREQS; i++)
455         {
456                 if(EQUIV(config.base_freq[i], freq)) return;
457         }
458
459         for(int i = 0; i < MAX_FREQS; i++)
460         {
461                 if(EQUIV(config.base_freq[i], 0))
462                 {
463                         config.base_freq[i] = freq;
464 //printf("Synth::new_freq %d\n", __LINE__);
465                         break;
466                 }
467         }
468 }
469
470 void Synth::delete_freq(double freq)
471 {
472         for(int i = 0; i < MAX_FREQS; i++)
473         {
474                 if(EQUIV(config.base_freq[i], freq))
475                 {
476 //printf("Synth::delete_freq %d\n", __LINE__);
477 // Shift frequencies back
478                         for(int j = i; j < MAX_FREQS - 1; j++)
479                         {
480                                 config.base_freq[j] = config.base_freq[j + 1];
481                         }
482                         config.base_freq[MAX_FREQS - 1] = 0;
483
484                         i--;
485                 }
486         }
487 }
488
489 void Synth::delete_freqs()
490 {
491         for(int i = 0; i < MAX_FREQS; i++)
492                 config.base_freq[i] = 0;
493 }
494
495
496 SynthWindow::SynthWindow(Synth *synth)
497  : PluginClientWindow(synth, synth->window_w, synth->window_h,
498                 xS(400), yS(350), 1)
499 {
500         this->synth = synth;
501         white_key[0] = 0;
502         white_key[1] = 0;
503         white_key[2] = 0;
504         black_key[0] = 0;
505         black_key[1] = 0;
506         black_key[2] = 0;
507         bzero(notes, sizeof(SynthNote*) * TOTALNOTES);
508         current_note = -1;
509 }
510
511 SynthWindow::~SynthWindow()
512 {
513         delete white_key[0];
514         delete white_key[1];
515         delete white_key[2];
516         delete black_key[0];
517         delete black_key[1];
518         delete black_key[2];
519 }
520
521 static const char *keyboard_map[] =
522 {
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"
525 };
526
527 void SynthWindow::create_objects()
528 {
529         int margin = client->get_theme()->widget_border;
530
531         BC_MenuBar *menu;
532         add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
533
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")));
538
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));
545
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));
550
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));
557
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;
561
562         add_subwindow(new BC_Title(x, y, _("Waveform")));
563         x += xs240;
564         add_subwindow(new BC_Title(x, y, _("Wave Function")));
565         y += ys20;
566         x = xs10;
567         add_subwindow(canvas = new SynthCanvas(synth, this, x, y, xS(230), yS(160)));
568         canvas->update();
569
570         x += xs240;
571         char string[BCTEXTLEN];
572         waveform_to_text(string, synth->config.wavefunction);
573
574         add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
575         waveform->create_objects();
576         y += ys30;
577         int x1 = x + waveform->get_w() + xs50;
578
579
580         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
581         y += ys30;
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;
589         y += ys40;
590         add_subwindow(new BC_Title(x, y, _("Wetness:")));
591         add_subwindow(wetness = new SynthWetness(synth, x + xs70, y - ys10));
592
593         y += ys40;
594         add_subwindow(new SynthClear(synth, x, y));
595
596
597         x = xs50;
598         y = ys220;
599         add_subwindow(new BC_Title(x, y, _("Level")));
600         x += xs75;
601         add_subwindow(new BC_Title(x, y, _("Phase")));
602         x += xs75;
603         add_subwindow(new BC_Title(x, y, _("Harmonic")));
604
605
606
607         y += ys20; x = xs10;
608         add_subwindow(osc_subwindow = new BC_SubWindow(x, y, xs265, get_h() - y));
609         x += xs265;
610         add_subwindow(osc_scroll = new OscScroll(synth, this, x, y, get_h() - y));
611
612
613         x += xs20;
614         add_subwindow(new SynthAddOsc(synth, this, x, y));
615         y += ys30;
616         add_subwindow(new SynthDelOsc(synth, this, x, y));
617
618 // Create keyboard
619         y = ys30;
620
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);
641
642
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()));
651
652         add_subwindow(momentary = new SynthMomentary(this, x1,
653                 note_scroll->get_y() + note_scroll->get_h() + margin,
654                 _("Momentary notes")));
655
656
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.")));
660
661         update_scrollbar();
662         update_oscillators();
663         update_notes();
664
665         show_window();
666 }
667
668 int SynthWindow::keypress_event()
669 {
670         if(ctrl_down() && get_keypress() == 'w')
671         {
672                 set_done(1);
673                 return 1;
674         }
675         return context_help_check_and_show();
676 }
677
678 int SynthWindow::resize_event(int w, int h)
679 {
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(),
687                 osc_scroll->get_y(),
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(),
700                 0);
701
702         update_scrollbar();
703         update_notes();
704         update_oscillators();
705         synth->window_w = w;
706         synth->window_h = h;
707         return 1;
708 }
709
710 void SynthWindow::update_gui()
711 {
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);
719
720         update_scrollbar();
721         update_oscillators();
722         canvas->update();
723         update_note_selection();
724         show_window();
725 }
726
727 void SynthWindow::update_scrollbar()
728 {
729         osc_scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
730                 osc_scroll->get_position(),
731                 osc_subwindow->get_h(),
732                 0);
733 }
734
735
736 void SynthWindow::update_whitekey(int number,
737         int *current_title,
738         int x,
739         int y)
740 {
741         if(!notes[number])
742         {
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__);
751         }
752         else
753         {
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,
757                                         y2);
758         }
759 }
760
761
762 void SynthWindow::update_blackkey(int number,
763         int *current_title,
764         int x,
765         int y)
766 {
767         if(!notes[number])
768         {
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]));
775         }
776         else
777         {
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);
781         }
782 }
783
784 void SynthWindow::update_notes()
785 {
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;
798
799
800 //printf("SynthWindow::update_notes %d\n", __LINE__);
801         note_subwindow->clear_box(0, 0, get_w(), get_h());
802
803         note_subwindow->set_color(get_resources()->default_text_color);
804
805 // Add new notes
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++)
811         {
812                 x = -note_scroll->get_position();
813
814                 for(int i = 0; i < TOTALNOTES; i++)
815                 {
816                         int octave_note = i % 12;
817                         if(!pass)
818                         {
819 // White keys
820                                 switch(octave_note)
821                                 {
822                                         case 0:
823                                                 update_whitekey(i, &current_title, x, y);
824                                                 break;
825                                         case 1:
826                                                 x += white_w;
827                                                 break;
828                                         case 2:
829                                                 update_whitekey(i, &current_title, x, y);
830                                                 break;
831                                         case 3:
832                                                 x += white_w;
833                                                 break;
834                                         case 4:
835                                                 update_whitekey(i, &current_title, x, y);
836                                                 x += white_w;
837                                                 break;
838                                         case 5:
839                                                 update_whitekey(i, &current_title, x, y);
840                                                 break;
841                                         case 6:
842                                                 x += white_w;
843                                                 break;
844                                         case 7:
845                                                 update_whitekey(i, &current_title, x, y);
846                                                 break;
847                                         case 8:
848                                                 x += white_w;
849                                                 break;
850                                         case 9:
851                                                 update_whitekey(i, &current_title, x, y);
852                                                 break;
853                                         case 10:
854                                                 x += white_w;
855                                                 break;
856                                         case 11:
857                                                 update_whitekey(i, &current_title, x, y);
858                                                 x += white_w;
859                                                 break;
860                                 }
861                         }
862                         else
863                         {
864 // Black keys
865                                 switch(octave_note)
866                                 {
867                                         case 1:
868                                                 update_blackkey(i, &current_title, x + white_w2, y);
869                                                 x += white_w;
870                                                 break;
871                                         case 3:
872                                                 update_blackkey(i, &current_title, x + white_w3, y);
873                                                 x += white_w;
874                                                 break;
875                                         case 4:
876                                                 x += white_w;
877                                                 break;
878                                         case 6:
879                                                 update_blackkey(i, &current_title, x + white_w2, y);
880                                                 x += white_w;
881                                                 break;
882                                         case 8:
883                                                 update_blackkey(i, &current_title, x + white_w1, y);
884                                                 x += white_w;
885                                                 break;
886                                         case 10:
887                                                 update_blackkey(i, &current_title, x + white_w3, y);
888                                                 x += white_w;
889                                                 break;
890                                         case 11:
891                                                 x += white_w;
892                                                 break;
893                                 }
894                         }
895                 }
896         }
897 }
898
899 void SynthWindow::update_note_selection()
900 {
901         for(int i = 0; i < TOTALNOTES; i++)
902         {
903                 int got_it = 0;
904                 for(int j = 0; j < MAX_FREQS; j++)
905                 {
906                         if(synth->freq_exists(keyboard_freqs[notes[i]->number]))
907                         {
908                                 got_it = 1;
909                                 break;
910                         }
911                 }
912
913                 if(got_it)
914                 {
915                         notes[i]->set_value(1);
916                 }
917                 else
918                         notes[i]->set_value(0);
919         }
920 }
921
922
923 void SynthWindow::update_oscillators()
924 {
925         int i, y = -osc_scroll->get_position();
926
927
928
929 // Add new oscillators
930         for(i = 0;
931                 i < synth->config.oscillator_config.total;
932                 i++)
933         {
934                 SynthOscGUI *gui;
935                 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
936
937                 if(oscillators.total <= i)
938                 {
939                         oscillators.append(gui = new SynthOscGUI(this, i));
940                         gui->create_objects(y);
941                 }
942                 else
943                 {
944                         gui = oscillators.values[i];
945
946                         gui->title->reposition_window(gui->title->get_x(), y + yS(15));
947
948                         gui->level->reposition_window(gui->level->get_x(), y);
949                         gui->level->update(config->level);
950
951                         gui->phase->reposition_window(gui->phase->get_x(), y);
952                         gui->phase->update((int64_t)(config->phase * 360));
953
954                         gui->freq->reposition_window(gui->freq->get_x(), y);
955                         gui->freq->update(config->freq_factor);
956                 }
957                 y += OSCILLATORHEIGHT;
958         }
959
960 // Delete old oscillators
961         for( ;
962                 i < oscillators.total;
963                 i++)
964                 oscillators.remove_object();
965 }
966
967
968 int SynthWindow::waveform_to_text(char *text, int waveform)
969 {
970         switch(waveform)
971         {
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;
979         }
980         return 0;
981 }
982
983
984 SynthMomentary::SynthMomentary(SynthWindow *window, int x, int y, char *text)
985  : BC_CheckBox(x, y, window->synth->config.momentary_notes, text)
986 {
987         this->window = window;
988 }
989
990 int SynthMomentary::handle_event()
991 {
992         window->synth->config.momentary_notes = get_value();
993         window->synth->send_configure_change();
994         return 1;
995 }
996
997
998
999
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]))
1002 {
1003         this->window = window;
1004         this->number = number;
1005         note_on = 0;
1006         set_select_drag(1);
1007         set_radial(1);
1008 }
1009
1010 void SynthNote::start_note()
1011 {
1012         if(window->synth->config.momentary_notes) note_on = 1;
1013
1014 //printf("SynthNote::start_note %d %d\n", __LINE__, ctrl_down());
1015         if(window->synth->config.momentary_notes || (!ctrl_down() && !shift_down()))
1016         {
1017 // Kill all frequencies
1018                 window->synth->delete_freqs();
1019         }
1020
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();
1027 }
1028
1029 void SynthNote::stop_note()
1030 {
1031         note_on = 0;
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();
1037 }
1038
1039 int SynthNote::keypress_event()
1040 {
1041 // Evtl catch Alt/H
1042         if (get_keypress() == 'h' && alt_down())
1043         {
1044                 context_help_show();
1045                 return 1;
1046         }
1047
1048         if(number >= FIRST_TITLE && number < LAST_TITLE)
1049         {
1050                 if(get_keypress() == keyboard_map[number - FIRST_TITLE][0])
1051                 {
1052                         if((ctrl_down() || shift_down()) &&
1053                                 window->synth->freq_exists(keyboard_freqs[number]))
1054                         {
1055                                 stop_note();
1056                         }
1057                         else
1058                         {
1059                                 start_note();
1060                                 set_value(1);
1061                         }
1062
1063 // Key releases are repeated, so momentary notes may not work
1064                         return 1;
1065                 }
1066         }
1067         return 0;
1068 }
1069
1070 int SynthNote::keyrelease_event()
1071 {
1072         if(note_on && window->synth->config.momentary_notes)
1073         {
1074                 stop_note();
1075                 set_value(0);
1076                 return 1;
1077         }
1078         return 0;
1079 }
1080
1081 int SynthNote::cursor_motion_event()
1082 {
1083         int result = 0;
1084         if(window->current_note > -1)
1085         {
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())
1090                 {
1091                         if(window->starting_notes)
1092                         {
1093                                 start_note();
1094                         }
1095                         else
1096                         {
1097                                 stop_note();
1098                         }
1099
1100                         window->current_note = number;
1101                         result = 1;
1102                 }
1103         }
1104         return result;
1105 }
1106
1107 int SynthNote::button_press_event()
1108 {
1109         if(BC_Toggle::button_press_event())
1110         {
1111 // printf("SynthNote::button_press_event %d %d %d\n",
1112 // __LINE__,
1113 // ctrl_down(),
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]))
1118                 {
1119 //printf("SynthNote::button_press_event %d\n", __LINE__);
1120                         stop_note();
1121                         window->starting_notes = 0;
1122                 }
1123                 else
1124                 {
1125 //printf("SynthNote::button_press_event %d\n", __LINE__);
1126                         start_note();
1127                         window->starting_notes = 1;
1128                 }
1129                 window->current_note = number;
1130                 return 1;
1131         }
1132         return 0;
1133 }
1134
1135 int SynthNote::button_release_event()
1136 {
1137 // Change frequency permanently
1138         if(window->current_note == number)
1139         {
1140                 if(window->synth->config.momentary_notes)
1141                 {
1142 // Mute on button release
1143                         stop_note();
1144                         set_value(0);
1145                 }
1146                 window->current_note = -1;
1147         }
1148
1149         return BC_Toggle::button_release_event();
1150 }
1151
1152 int SynthNote::draw_face(int flash, int flush)
1153 {
1154         BC_Toggle::draw_face(0, 0);
1155         static const char *titles[] =
1156         {
1157                 "C",
1158                 "C#",
1159                 "D",
1160                 "D#",
1161                 "E",
1162                 "F",
1163                 "F#",
1164                 "G",
1165                 "G#",
1166                 "A",
1167                 "A#",
1168                 "B"
1169         };
1170
1171
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);
1176         if(text[1] == '#')
1177         {
1178         }
1179         else
1180         {
1181                 set_color(BLACK);
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,
1184                         string);
1185         }
1186
1187         if(flash) this->flash(0);
1188         if(flush) this->flush();
1189         return 0;
1190 }
1191
1192
1193
1194
1195
1196
1197
1198 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
1199 {
1200         this->window = window;
1201         this->number = number;
1202 }
1203
1204 SynthOscGUI::~SynthOscGUI()
1205 {
1206         delete title;
1207         delete level;
1208         delete phase;
1209         delete freq;
1210 }
1211
1212 void SynthOscGUI::create_objects(int y)
1213 {
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));
1217
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));
1221 }
1222
1223
1224
1225
1226 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
1227  : BC_FPot(xS(50), y,
1228         synth->config.oscillator_config.values[gui->number]->level,
1229         INFINITYGAIN, 0)
1230 {
1231         this->synth = synth;
1232         this->gui = gui;
1233 }
1234
1235 SynthOscGUILevel::~SynthOscGUILevel()
1236 {
1237 }
1238
1239 int SynthOscGUILevel::handle_event()
1240 {
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();
1245         return 1;
1246 }
1247
1248
1249
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),
1253         0, 360)
1254 {
1255         this->synth = synth;
1256         this->gui = gui;
1257 }
1258
1259 SynthOscGUIPhase::~SynthOscGUIPhase()
1260 {
1261 }
1262
1263 int SynthOscGUIPhase::handle_event()
1264 {
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();
1269         return 1;
1270 }
1271
1272
1273
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),
1277         1, 100)
1278 {
1279         this->synth = synth;
1280         this->gui = gui;
1281 }
1282
1283 SynthOscGUIFreq::~SynthOscGUIFreq()
1284 {
1285 }
1286
1287 int SynthOscGUIFreq::handle_event()
1288 {
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();
1293         return 1;
1294 }
1295
1296
1297 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
1298  : BC_GenericButton(x, y, _("Add"))
1299 {
1300         this->synth = synth;
1301         this->window = window;
1302 }
1303
1304 SynthAddOsc::~SynthAddOsc()
1305 {
1306 }
1307
1308 int SynthAddOsc::handle_event()
1309 {
1310         synth->add_oscillator();
1311         synth->send_configure_change();
1312         window->update_gui();
1313         return 1;
1314 }
1315
1316
1317 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
1318  : BC_GenericButton(x, y, _("Delete"))
1319 {
1320         this->synth = synth;
1321         this->window = window;
1322 }
1323
1324 SynthDelOsc::~SynthDelOsc()
1325 {
1326 }
1327
1328 int SynthDelOsc::handle_event()
1329 {
1330         synth->delete_oscillator();
1331         synth->send_configure_change();
1332         window->update_gui();
1333         return 1;
1334 }
1335
1336
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())
1342 {
1343         this->synth = synth;
1344         this->window = window;
1345 }
1346
1347 OscScroll::~OscScroll()
1348 {
1349 }
1350
1351 int OscScroll::handle_event()
1352 {
1353         window->update_oscillators();
1354         return 1;
1355 }
1356
1357
1358
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())
1364 {
1365         this->synth = synth;
1366         this->window = window;
1367 }
1368
1369 NoteScroll::~NoteScroll()
1370 {
1371 }
1372
1373 int NoteScroll::handle_event()
1374 {
1375         window->update_notes();
1376         return 1;
1377 }
1378
1379
1380 SynthClear::SynthClear(Synth *synth, int x, int y)
1381  : BC_GenericButton(x, y, _("Clear"))
1382 {
1383         this->synth = synth;
1384 }
1385 SynthClear::~SynthClear()
1386 {
1387 }
1388 int SynthClear::handle_event()
1389 {
1390         synth->config.reset();
1391         synth->send_configure_change();
1392         synth->update_gui();
1393         return 1;
1394 }
1395
1396
1397
1398
1399
1400
1401 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
1402  : BC_PopupMenu(x, y, xS(120), text)
1403 {
1404         this->synth = synth;
1405 }
1406
1407 SynthWaveForm::~SynthWaveForm()
1408 {
1409 }
1410
1411 void SynthWaveForm::create_objects()
1412 {
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));
1420 }
1421
1422 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1423  : BC_MenuItem(text)
1424 {
1425         this->synth = synth;
1426         this->value = value;
1427 }
1428
1429 SynthWaveFormItem::~SynthWaveFormItem()
1430 {
1431 }
1432
1433 int SynthWaveFormItem::handle_event()
1434 {
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();
1439         return 1;
1440 }
1441
1442
1443 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1444  : BC_FPot(x, y, synth->config.wetness, INFINITYGAIN, 0)
1445 {
1446         this->synth = synth;
1447 }
1448
1449 int SynthWetness::handle_event()
1450 {
1451         synth->config.wetness = get_value();
1452         synth->send_configure_change();
1453         return 1;
1454 }
1455
1456
1457
1458 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1459  : BC_QPot(x, y, synth->config.base_freq[0])
1460 {
1461         this->synth = synth;
1462         this->window = window;
1463 }
1464 SynthFreqPot::~SynthFreqPot()
1465 {
1466 }
1467 int SynthFreqPot::handle_event()
1468 {
1469         if(get_value() > 0 && get_value() < 30000)
1470         {
1471                 synth->config.base_freq[0] = get_value();
1472                 freq_text->update(get_value());
1473                 synth->send_configure_change();
1474                 window->update_note_selection();
1475         }
1476         return 1;
1477 }
1478
1479
1480
1481 SynthBaseFreq::SynthBaseFreq(Synth *synth, SynthWindow *window, int x, int y)
1482  : BC_TextBox(x, y, xS(100), 1, (float)0)
1483 {
1484         this->synth = synth;
1485         this->window = window;
1486         set_precision(2);
1487 }
1488 SynthBaseFreq::~SynthBaseFreq()
1489 {
1490 }
1491 int SynthBaseFreq::handle_event()
1492 {
1493         double new_value = atof(get_text());
1494 // 0 is mute
1495         if(new_value < 30000)
1496         {
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();
1501         }
1502         return 1;
1503 }
1504
1505
1506
1507
1508
1509 SynthCanvas::SynthCanvas(Synth *synth, SynthWindow *window,
1510                 int x, int y, int w, int h)
1511  : BC_SubWindow(x, y, w, h, BLACK)
1512 {
1513         this->synth = synth;
1514         this->window = window;
1515 }
1516
1517 SynthCanvas::~SynthCanvas()
1518 {
1519 }
1520
1521 int SynthCanvas::update()
1522 {
1523         int y1, y2, y = 0;
1524
1525         clear_box(0, 0, get_w(), get_h());
1526         set_color(RED);
1527
1528         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1529
1530         set_color(GREEN);
1531
1532         double normalize_constant = (double)1 / synth->get_total_power();
1533         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1534
1535         for(int i = 1; i < get_w(); i++)
1536         {
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);
1539                 y1 = y2;
1540         }
1541         flash();
1542         return 0;
1543 }
1544
1545
1546 // ======================= level calculations
1547 SynthLevelZero::SynthLevelZero(Synth *synth)
1548  : BC_MenuItem(_("Zero"))
1549 {
1550         this->synth = synth;
1551 }
1552
1553 SynthLevelZero::~SynthLevelZero()
1554 {
1555 }
1556
1557 int SynthLevelZero::handle_event()
1558 {
1559         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1560         {
1561                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1562         }
1563
1564         ((SynthWindow*)synth->thread->window)->update_gui();
1565         synth->send_configure_change();
1566         return 1;
1567 }
1568
1569 SynthLevelMax::SynthLevelMax(Synth *synth)
1570  : BC_MenuItem(_("Maximum"))
1571 {
1572         this->synth = synth;
1573 }
1574
1575 SynthLevelMax::~SynthLevelMax()
1576 {
1577 }
1578
1579 int SynthLevelMax::handle_event()
1580 {
1581         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1582         {
1583                 synth->config.oscillator_config.values[i]->level = 0;
1584         }
1585         ((SynthWindow*)synth->thread->window)->update_gui();
1586         synth->send_configure_change();
1587         return 1;
1588 }
1589
1590 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1591  : BC_MenuItem(_("Normalize"))
1592 {
1593         this->synth = synth;
1594 }
1595
1596 SynthLevelNormalize::~SynthLevelNormalize()
1597 {
1598 }
1599
1600 int SynthLevelNormalize::handle_event()
1601 {
1602 // get total power
1603         float total = 0;
1604
1605         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1606         {
1607                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1608         }
1609
1610         float scale = 1 / total;
1611         float new_value;
1612
1613         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1614         {
1615                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1616                 new_value *= scale;
1617                 new_value = synth->db.todb(new_value);
1618
1619                 synth->config.oscillator_config.values[i]->level = new_value;
1620         }
1621
1622         ((SynthWindow*)synth->thread->window)->update_gui();
1623         synth->send_configure_change();
1624         return 1;
1625 }
1626
1627 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1628  : BC_MenuItem(_("Slope"))
1629 {
1630         this->synth = synth;
1631 }
1632
1633 SynthLevelSlope::~SynthLevelSlope()
1634 {
1635 }
1636
1637 int SynthLevelSlope::handle_event()
1638 {
1639         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1640
1641         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1642         {
1643                 synth->config.oscillator_config.values[i]->level = i * slope;
1644         }
1645
1646         ((SynthWindow*)synth->thread->window)->update_gui();
1647         synth->send_configure_change();
1648         return 1;
1649 }
1650
1651 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1652  : BC_MenuItem(_("Random"))
1653 {
1654         this->synth = synth;
1655 }
1656 SynthLevelRandom::~SynthLevelRandom()
1657 {
1658 }
1659
1660 int SynthLevelRandom::handle_event()
1661 {
1662         srand(time(0));
1663         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1664         {
1665                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1666         }
1667
1668         ((SynthWindow*)synth->thread->window)->update_gui();
1669         synth->send_configure_change();
1670         return 1;
1671 }
1672
1673 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1674  : BC_MenuItem(_("Invert"))
1675 {
1676         this->synth = synth;
1677 }
1678 SynthLevelInvert::~SynthLevelInvert()
1679 {
1680 }
1681
1682 int SynthLevelInvert::handle_event()
1683 {
1684         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1685         {
1686                 synth->config.oscillator_config.values[i]->level =
1687                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1688         }
1689
1690         ((SynthWindow*)synth->thread->window)->update_gui();
1691         synth->send_configure_change();
1692         return 1;
1693 }
1694
1695 SynthLevelSine::SynthLevelSine(Synth *synth)
1696  : BC_MenuItem(_("Sine"))
1697 {
1698         this->synth = synth;
1699 }
1700 SynthLevelSine::~SynthLevelSine()
1701 {
1702 }
1703
1704 int SynthLevelSine::handle_event()
1705 {
1706         float new_value;
1707
1708         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1709         {
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;
1713         }
1714
1715         ((SynthWindow*)synth->thread->window)->update_gui();
1716         synth->send_configure_change();
1717         return 1;
1718 }
1719
1720 // ============================ phase calculations
1721
1722 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1723  : BC_MenuItem(_("Invert"))
1724 {
1725         this->synth = synth;
1726 }
1727 SynthPhaseInvert::~SynthPhaseInvert()
1728 {
1729 }
1730
1731 int SynthPhaseInvert::handle_event()
1732 {
1733         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1734         {
1735                 synth->config.oscillator_config.values[i]->phase =
1736                         1 - synth->config.oscillator_config.values[i]->phase;
1737         }
1738
1739         ((SynthWindow*)synth->thread->window)->update_gui();
1740         synth->send_configure_change();
1741         return 1;
1742 }
1743
1744 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1745  : BC_MenuItem(_("Zero"))
1746 {
1747         this->synth = synth;
1748 }
1749 SynthPhaseZero::~SynthPhaseZero()
1750 {
1751 }
1752
1753 int SynthPhaseZero::handle_event()
1754 {
1755         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1756         {
1757                 synth->config.oscillator_config.values[i]->phase = 0;
1758         }
1759
1760         ((SynthWindow*)synth->thread->window)->update_gui();
1761         synth->send_configure_change();
1762         return 1;
1763 }
1764
1765 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1766  : BC_MenuItem(_("Sine"))
1767 {
1768         this->synth = synth;
1769 }
1770 SynthPhaseSine::~SynthPhaseSine()
1771 {
1772 }
1773
1774 int SynthPhaseSine::handle_event()
1775 {
1776         float new_value;
1777         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1778         {
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;
1782         }
1783
1784         ((SynthWindow*)synth->thread->window)->update_gui();
1785         synth->send_configure_change();
1786         return 1;
1787 }
1788
1789 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1790  : BC_MenuItem(_("Random"))
1791 {
1792         this->synth = synth;
1793 }
1794 SynthPhaseRandom::~SynthPhaseRandom()
1795 {
1796 }
1797
1798 int SynthPhaseRandom::handle_event()
1799 {
1800         srand(time(0));
1801         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1802         {
1803                 synth->config.oscillator_config.values[i]->phase =
1804                         (float)(rand() % 360) / 360;
1805         }
1806
1807         ((SynthWindow*)synth->thread->window)->update_gui();
1808         synth->send_configure_change();
1809         return 1;
1810 }
1811
1812
1813 // ============================ freq calculations
1814
1815 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1816  : BC_MenuItem(_("Random"))
1817 {
1818         this->synth = synth;
1819 }
1820 SynthFreqRandom::~SynthFreqRandom()
1821 {
1822 }
1823
1824 int SynthFreqRandom::handle_event()
1825 {
1826         srand(time(0));
1827         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1828         {
1829                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1830         }
1831
1832         ((SynthWindow*)synth->thread->window)->update_gui();
1833         synth->send_configure_change();
1834         return 1;
1835 }
1836
1837 SynthFreqPow1::SynthFreqPow1(Synth *synth)
1838  : BC_MenuItem(_("Powers of 1.4"))
1839 {
1840         this->synth = synth;
1841 }
1842 SynthFreqPow1::~SynthFreqPow1()
1843 {
1844 }
1845
1846 int SynthFreqPow1::handle_event()
1847 {
1848         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1849         {
1850                 synth->config.oscillator_config.values[i]->freq_factor = pow(sqrt(2), i);
1851         }
1852
1853         ((SynthWindow*)synth->thread->window)->update_gui();
1854         synth->send_configure_change();
1855         return 1;
1856 }
1857
1858
1859 SynthFreqPow2::SynthFreqPow2(Synth *synth)
1860  : BC_MenuItem(_("Powers of 2"))
1861 {
1862         this->synth = synth;
1863 }
1864 SynthFreqPow2::~SynthFreqPow2()
1865 {
1866 }
1867
1868 int SynthFreqPow2::handle_event()
1869 {
1870         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1871         {
1872                 synth->config.oscillator_config.values[i]->freq_factor = pow(2, i);
1873         }
1874
1875         ((SynthWindow*)synth->thread->window)->update_gui();
1876         synth->send_configure_change();
1877         return 1;
1878 }
1879
1880
1881
1882
1883 SynthFreqMin::SynthFreqMin(Synth *synth)
1884  : BC_MenuItem(_("Minimum"))
1885 {
1886         this->synth = synth;
1887 }
1888 SynthFreqMin::~SynthFreqMin()
1889 {
1890 }
1891
1892 int SynthFreqMin::handle_event()
1893 {
1894         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1895         {
1896                 synth->config.oscillator_config.values[i]->freq_factor = 1;
1897         }
1898
1899         ((SynthWindow*)synth->thread->window)->update_gui();
1900         synth->send_configure_change();
1901         return 1;
1902 }
1903
1904
1905 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1906  : BC_MenuItem(_("Enumerate"))
1907 {
1908         this->synth = synth;
1909 }
1910 SynthFreqEnum::~SynthFreqEnum()
1911 {
1912 }
1913
1914 int SynthFreqEnum::handle_event()
1915 {
1916         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1917         {
1918                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1919         }
1920
1921         ((SynthWindow*)synth->thread->window)->update_gui();
1922         synth->send_configure_change();
1923         return 1;
1924 }
1925
1926 SynthFreqEven::SynthFreqEven(Synth *synth)
1927  : BC_MenuItem(_("Even"))
1928 {
1929         this->synth = synth;
1930 }
1931 SynthFreqEven::~SynthFreqEven()
1932 {
1933 }
1934
1935 int SynthFreqEven::handle_event()
1936 {
1937         if(synth->config.oscillator_config.total)
1938                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1939
1940         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1941         {
1942                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1943         }
1944
1945         ((SynthWindow*)synth->thread->window)->update_gui();
1946         synth->send_configure_change();
1947         return 1;
1948 }
1949
1950 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1951  : BC_MenuItem(_("Odd"))
1952 { this->synth = synth; }
1953 SynthFreqOdd::~SynthFreqOdd()
1954 {
1955 }
1956
1957 int SynthFreqOdd::handle_event()
1958 {
1959         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1960         {
1961                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1962         }
1963
1964         ((SynthWindow*)synth->thread->window)->update_gui();
1965         synth->send_configure_change();
1966         return 1;
1967 }
1968
1969 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
1970  : BC_MenuItem(_("Fibonnacci"))
1971 {
1972         this->synth = synth;
1973 }
1974 SynthFreqFibonacci::~SynthFreqFibonacci()
1975 {
1976 }
1977
1978 int SynthFreqFibonacci::handle_event()
1979 {
1980         float last_value1 = 0, last_value2 = 1;
1981         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1982         {
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;
1988         }
1989
1990         ((SynthWindow*)synth->thread->window)->update_gui();
1991         synth->send_configure_change();
1992         return 1;
1993 }
1994
1995 SynthFreqPrime::SynthFreqPrime(Synth *synth)
1996  : BC_MenuItem(_("Prime"))
1997 {
1998         this->synth = synth;
1999 }
2000 SynthFreqPrime::~SynthFreqPrime()
2001 {
2002 }
2003
2004 int SynthFreqPrime::handle_event()
2005 {
2006         float number = 1;
2007         for(int i = 0; i < synth->config.oscillator_config.total; i++)
2008         {
2009                 synth->config.oscillator_config.values[i]->freq_factor = number;
2010                 number = get_next_prime(number);
2011         }
2012
2013         ((SynthWindow*)synth->thread->window)->update_gui();
2014         synth->send_configure_change();
2015         return 1;
2016 }
2017
2018 float SynthFreqPrime::get_next_prime(float number)
2019 {
2020         int result = 1;
2021
2022         while(result)
2023         {
2024                 result = 0;
2025                 number++;
2026
2027                 for(float i = number - 1; i > 1 && !result; i--)
2028                 {
2029                         if((number / i) - (int)(number / i) == 0) result = 1;
2030                 }
2031         }
2032
2033         return number;
2034 }
2035
2036
2037
2038
2039
2040
2041
2042
2043 SynthOscillatorConfig::SynthOscillatorConfig(int number)
2044 {
2045         reset();
2046         this->number = number;
2047 }
2048
2049 SynthOscillatorConfig::~SynthOscillatorConfig()
2050 {
2051 }
2052
2053 void SynthOscillatorConfig::reset()
2054 {
2055         level = 0;
2056         phase = 0;
2057         freq_factor = 1;
2058 }
2059
2060
2061 void SynthOscillatorConfig::read_data(FileXML *file)
2062 {
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);
2066 }
2067
2068 void SynthOscillatorConfig::save_data(FileXML *file)
2069 {
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);
2074         file->append_tag();
2075         file->tag.set_title("/OSCILLATOR");
2076         file->append_tag();
2077         file->append_newline();
2078 }
2079
2080 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
2081 {
2082         if(EQUIV(level, that.level) &&
2083                 EQUIV(phase, that.phase) &&
2084                 EQUIV(freq_factor, that.freq_factor))
2085                 return 1;
2086         else
2087                 return 0;
2088 }
2089
2090 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
2091 {
2092         level = that.level;
2093         phase = that.phase;
2094         freq_factor = that.freq_factor;
2095 }
2096
2097
2098 SynthConfig::SynthConfig()
2099 {
2100         reset();
2101 }
2102
2103 SynthConfig::~SynthConfig()
2104 {
2105         oscillator_config.remove_all_objects();
2106 }
2107
2108 void SynthConfig::reset()
2109 {
2110         wetness = 0;
2111         base_freq[0] = 440;
2112         for(int i = 1; i < MAX_FREQS; i++)
2113                 base_freq[i] = 0;
2114         wavefunction = SINE;
2115         for(int i = 0; i < oscillator_config.total; i++)
2116         {
2117                 oscillator_config.values[i]->reset();
2118         }
2119
2120         momentary_notes = 0;
2121 }
2122
2123 int SynthConfig::equivalent(SynthConfig &that)
2124 {
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;
2128
2129         if(wavefunction != that.wavefunction ||
2130                 oscillator_config.total != that.oscillator_config.total ||
2131                 momentary_notes != that.momentary_notes) return 0;
2132
2133         for(int i = 0; i < oscillator_config.total; i++)
2134         {
2135                 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
2136                         return 0;
2137         }
2138
2139         return 1;
2140 }
2141
2142 void SynthConfig::copy_from(SynthConfig& that)
2143 {
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;
2149
2150         int i;
2151         for(i = 0;
2152                 i < oscillator_config.total && i < that.oscillator_config.total;
2153                 i++)
2154         {
2155                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2156         }
2157
2158         for( ;
2159                 i < that.oscillator_config.total;
2160                 i++)
2161         {
2162                 oscillator_config.append(new SynthOscillatorConfig(i));
2163                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2164         }
2165
2166         for( ;
2167                 i < oscillator_config.total;
2168                 i++)
2169         {
2170                 oscillator_config.remove_object();
2171         }
2172
2173 }
2174
2175 void SynthConfig::interpolate(SynthConfig &prev,
2176         SynthConfig &next,
2177         int64_t prev_frame,
2178         int64_t next_frame,
2179         int64_t current_frame)
2180 {
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);
2183
2184         copy_from(prev);
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);
2187
2188         momentary_notes = prev.momentary_notes;
2189 }
2190