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