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