add BC_SCALE env var for hi def monitors, cleanup theme data
[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 *
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         xS(400),
535         yS(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 xs10 = xS(10), xs20 = xS(20), xs50 = xS(50), xs70 = xS(70), xs75 = xS(75), xs240 = xS(240), xs265 = xS(265);
594         int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40), ys220 = yS(220);
595         int x = xs10, y = ys30;
596
597         add_subwindow(new BC_Title(x, y, _("Waveform")));
598         x += xs240;
599         add_subwindow(new BC_Title(x, y, _("Wave Function")));
600         y += ys20;
601         x = xs10;
602         add_subwindow(canvas = new SynthCanvas(synth, this, x, y, xS(230), yS(160)));
603         canvas->update();
604
605         x += xs240;
606         char string[BCTEXTLEN];
607         waveform_to_text(string, synth->config.wavefunction);
608
609         add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
610         waveform->create_objects();
611         y += ys30;
612         int x1 = x + waveform->get_w() + xs10;
613
614
615         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
616         y += ys30;
617         add_subwindow(base_freq = new SynthBaseFreq(synth, this, x, y));
618         base_freq->update((float)synth->config.base_freq[0]);
619         x += base_freq->get_w() + synth->get_theme()->widget_border;
620         add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - ys10));
621         base_freq->freq_pot = freqpot;
622         freqpot->freq_text = base_freq;
623         x -= base_freq->get_w() + synth->get_theme()->widget_border;
624         y += ys40;
625         add_subwindow(new BC_Title(x, y, _("Wetness:")));
626         add_subwindow(wetness = new SynthWetness(synth, x + xs70, y - ys10));
627
628         y += ys40;
629         add_subwindow(new SynthClear(synth, x, y));
630
631
632         x = xs50;
633         y = ys220;
634         add_subwindow(new BC_Title(x, y, _("Level")));
635         x += xs75;
636         add_subwindow(new BC_Title(x, y, _("Phase")));
637         x += xs75;
638         add_subwindow(new BC_Title(x, y, _("Harmonic")));
639
640
641
642         y += ys20; x = xs10;
643         add_subwindow(osc_subwindow = new BC_SubWindow(x, y, xs265, get_h() - y));
644         x += xs265;
645         add_subwindow(osc_scroll = new OscScroll(synth, this, x, y, get_h() - y));
646
647
648         x += xs20;
649         add_subwindow(new SynthAddOsc(synth, this, x, y));
650         y += ys30;
651         add_subwindow(new SynthDelOsc(synth, this, x, y));
652
653 // Create keyboard
654         y = ys30;
655
656 #include "white_up_png.h"
657 #include "white_hi_png.h"
658 #include "white_dn_png.h"
659 #include "white_checked_png.h"
660 #include "white_checkedhi_png.h"
661 #include "black_up_png.h"
662 #include "black_hi_png.h"
663 #include "black_dn_png.h"
664 #include "black_checked_png.h"
665 #include "black_checkedhi_png.h"
666         white_key[0] = new VFramePng(white_up_png);
667         white_key[1] = new VFramePng(white_hi_png);
668         white_key[2] = new VFramePng(white_checked_png);
669         white_key[3] = new VFramePng(white_dn_png);
670         white_key[4] = new VFramePng(white_checkedhi_png);
671         black_key[0] = new VFramePng(black_up_png);
672         black_key[1] = new VFramePng(black_hi_png);
673         black_key[2] = new VFramePng(black_checked_png);
674         black_key[3] = new VFramePng(black_dn_png);
675         black_key[4] = new VFramePng(black_checkedhi_png);
676
677
678         add_subwindow(note_subwindow = new BC_SubWindow(x1,
679                 y,
680                 get_w() - x1,
681                 white_key[0]->get_h() + MARGIN +
682                 get_text_height(MEDIUMFONT) + MARGIN +
683                 get_text_height(MEDIUMFONT) + MARGIN));
684         add_subwindow(note_scroll = new NoteScroll(synth,
685                 this,
686                 x1,
687                 note_subwindow->get_y() + note_subwindow->get_h(),
688                 note_subwindow->get_w()));
689
690         add_subwindow(momentary = new SynthMomentary(this,
691                 x1,
692                 note_scroll->get_y() + note_scroll->get_h() + MARGIN,
693                 _("Momentary notes")));
694
695
696         add_subwindow(note_instructions = new BC_Title(
697                 x1,
698                 momentary->get_y() + momentary->get_h() + MARGIN,
699                 _("Ctrl or Shift to select multiple notes.")));
700
701         update_scrollbar();
702         update_oscillators();
703         update_notes();
704
705         show_window();
706 }
707
708 int SynthWindow::keypress_event()
709 {
710         if(ctrl_down() && get_keypress() == 'w')
711         {
712                 set_done(1);
713                 return 1;
714         }
715         return 0;
716 }
717
718 int SynthWindow::resize_event(int w, int h)
719 {
720         clear_box(0, 0, w, h);
721         osc_subwindow->reposition_window(osc_subwindow->get_x(),
722                 osc_subwindow->get_y(),
723                 osc_subwindow->get_w(),
724                 h - osc_subwindow->get_y());
725         osc_subwindow->clear_box(0, 0, osc_subwindow->get_w(), osc_subwindow->get_h());
726         osc_scroll->reposition_window(osc_scroll->get_x(),
727                 osc_scroll->get_y(),
728                 h - osc_scroll->get_y());
729         note_subwindow->reposition_window(note_subwindow->get_x(),
730                 note_subwindow->get_y(),
731                 w - note_subwindow->get_x(),
732                 note_subwindow->get_h());
733         note_scroll->reposition_window(note_scroll->get_x(),
734                 note_scroll->get_y(),
735                 w - note_scroll->get_x());
736         note_scroll->update_length(white_key[0]->get_w() * TOTALNOTES * 7 / 12 +
737                         white_key[0]->get_w(),
738                 note_scroll->get_position(),
739                 note_subwindow->get_w(),
740                 0);
741
742         update_scrollbar();
743         update_notes();
744         update_oscillators();
745         synth->window_w = w;
746         synth->window_h = h;
747         return 1;
748 }
749
750 void SynthWindow::update_gui()
751 {
752         char string[BCTEXTLEN];
753         freqpot->update((int)synth->config.base_freq[0]);
754         base_freq->update((float)synth->config.base_freq[0]);
755         wetness->update(synth->config.wetness);
756         waveform_to_text(string, synth->config.wavefunction);
757         waveform->set_text(string);
758         momentary->update(synth->config.momentary_notes);
759
760         update_scrollbar();
761         update_oscillators();
762         canvas->update();
763         update_note_selection();
764         show_window();
765 }
766
767 void SynthWindow::update_scrollbar()
768 {
769         osc_scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
770                 osc_scroll->get_position(),
771                 osc_subwindow->get_h(),
772                 0);
773 }
774
775
776 void SynthWindow::update_whitekey(int number,
777         int *current_title,
778         int x,
779         int y)
780 {
781         if(!notes[number])
782         {
783                 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
784                         white_key, number, x, y));
785                 if(number >= FIRST_TITLE && number < LAST_TITLE)
786                         note_subwindow->add_subwindow(
787                                 note_titles[(*current_title)++] = new BC_Title(
788                                         x + text_white_margin,
789                                         y2,
790                                         keyboard_map[number - FIRST_TITLE]));
791 //printf("SynthWindow::update_whitekey %d\n", __LINE__);
792         }
793         else
794         {
795                 notes[number]->reposition_window(x, y);
796                 if(number >= FIRST_TITLE && number < LAST_TITLE)
797                         note_titles[(*current_title)++]->reposition_window(x + text_white_margin,
798                                         y2);
799         }
800 }
801
802
803 void SynthWindow::update_blackkey(int number,
804         int *current_title,
805         int x,
806         int y)
807 {
808         if(!notes[number])
809         {
810                 note_subwindow->add_subwindow(notes[number] = new SynthNote(this,
811                         black_key, number, x, y));
812                 if(number >= FIRST_TITLE && number < LAST_TITLE)
813                         note_subwindow->add_subwindow(
814                                 note_titles[(*current_title)++] = new BC_Title(x + text_black_margin,
815                                         y1,
816                                         keyboard_map[number - FIRST_TITLE]));
817         }
818         else
819         {
820                 notes[number]->reposition_window(x, y);
821                 if(number >= FIRST_TITLE && number < LAST_TITLE)
822                         note_titles[(*current_title)++]->reposition_window(x + text_black_margin,
823                                         y1);
824         }
825 }
826
827 void SynthWindow::update_notes()
828 {
829         //int octave_w = white_key[0]->get_w() * 7;
830         int white_w = white_key[0]->get_w();
831         int black_w = black_key[0]->get_w();
832         int white_w1 = white_w - black_w / 2 - 2;
833         int white_w2 = white_w / 2;
834         int white_w3 = white_w * 2 / 3;
835         int y = 0;
836         int x = 0;
837         y1 = y + white_key[0]->get_h() + 10;
838         y2 = y1 + get_text_height(MEDIUMFONT) + 10;
839         y3 = y2 + get_text_height(MEDIUMFONT) + 10;
840         text_black_margin = black_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
841         text_white_margin = white_w / 2 - get_text_width(MEDIUMFONT, "O") / 2;
842
843
844 //printf("SynthWindow::update_notes %d\n", __LINE__);
845         note_subwindow->clear_box(0, 0, get_w(), get_h());
846
847         note_subwindow->set_color(get_resources()->default_text_color);
848
849 // Add new notes
850 // To get the stacking order:
851 // pass 0 is white keys
852 // pass 1 is black keys
853         int current_title = 0;
854         for(int pass = 0; pass < 2; pass++)
855         {
856                 x = -note_scroll->get_position();
857
858                 for(int i = 0; i < TOTALNOTES; i++)
859                 {
860                         int octave_note = i % 12;
861                         if(!pass)
862                         {
863 // White keys
864                                 switch(octave_note)
865                                 {
866                                         case 0:
867                                                 update_whitekey(i, &current_title, x, y);
868                                                 break;
869                                         case 1:
870                                                 x += white_w;
871                                                 break;
872                                         case 2:
873                                                 update_whitekey(i, &current_title, x, y);
874                                                 break;
875                                         case 3:
876                                                 x += white_w;
877                                                 break;
878                                         case 4:
879                                                 update_whitekey(i, &current_title, x, y);
880                                                 x += white_w;
881                                                 break;
882                                         case 5:
883                                                 update_whitekey(i, &current_title, x, y);
884                                                 break;
885                                         case 6:
886                                                 x += white_w;
887                                                 break;
888                                         case 7:
889                                                 update_whitekey(i, &current_title, x, y);
890                                                 break;
891                                         case 8:
892                                                 x += white_w;
893                                                 break;
894                                         case 9:
895                                                 update_whitekey(i, &current_title, x, y);
896                                                 break;
897                                         case 10:
898                                                 x += white_w;
899                                                 break;
900                                         case 11:
901                                                 update_whitekey(i, &current_title, x, y);
902                                                 x += white_w;
903                                                 break;
904                                 }
905                         }
906                         else
907                         {
908 // Black keys
909                                 switch(octave_note)
910                                 {
911                                         case 1:
912                                                 update_blackkey(i, &current_title, x + white_w2, y);
913                                                 x += white_w;
914                                                 break;
915                                         case 3:
916                                                 update_blackkey(i, &current_title, x + white_w3, y);
917                                                 x += white_w;
918                                                 break;
919                                         case 4:
920                                                 x += white_w;
921                                                 break;
922                                         case 6:
923                                                 update_blackkey(i, &current_title, x + white_w2, y);
924                                                 x += white_w;
925                                                 break;
926                                         case 8:
927                                                 update_blackkey(i, &current_title, x + white_w1, y);
928                                                 x += white_w;
929                                                 break;
930                                         case 10:
931                                                 update_blackkey(i, &current_title, x + white_w3, y);
932                                                 x += white_w;
933                                                 break;
934                                         case 11:
935                                                 x += white_w;
936                                                 break;
937                                 }
938                         }
939                 }
940         }
941 }
942
943 void SynthWindow::update_note_selection()
944 {
945         for(int i = 0; i < TOTALNOTES; i++)
946         {
947                 int got_it = 0;
948                 for(int j = 0; j < MAX_FREQS; j++)
949                 {
950                         if(synth->freq_exists(keyboard_freqs[notes[i]->number]))
951                         {
952                                 got_it = 1;
953                                 break;
954                         }
955                 }
956
957                 if(got_it)
958                 {
959                         notes[i]->set_value(1);
960                 }
961                 else
962                         notes[i]->set_value(0);
963         }
964 }
965
966
967 void SynthWindow::update_oscillators()
968 {
969         int i, y = -osc_scroll->get_position();
970
971
972
973 // Add new oscillators
974         for(i = 0;
975                 i < synth->config.oscillator_config.total;
976                 i++)
977         {
978                 SynthOscGUI *gui;
979                 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
980
981                 if(oscillators.total <= i)
982                 {
983                         oscillators.append(gui = new SynthOscGUI(this, i));
984                         gui->create_objects(y);
985                 }
986                 else
987                 {
988                         gui = oscillators.values[i];
989
990                         gui->title->reposition_window(gui->title->get_x(), y + 15);
991
992                         gui->level->reposition_window(gui->level->get_x(), y);
993                         gui->level->update(config->level);
994
995                         gui->phase->reposition_window(gui->phase->get_x(), y);
996                         gui->phase->update((int64_t)(config->phase * 360));
997
998                         gui->freq->reposition_window(gui->freq->get_x(), y);
999                         gui->freq->update((int64_t)(config->freq_factor));
1000                 }
1001                 y += OSCILLATORHEIGHT;
1002         }
1003
1004 // Delete old oscillators
1005         for( ;
1006                 i < oscillators.total;
1007                 i++)
1008                 oscillators.remove_object();
1009 }
1010
1011
1012 int SynthWindow::waveform_to_text(char *text, int waveform)
1013 {
1014         switch(waveform)
1015         {
1016                 case DC:              sprintf(text, _("DC"));           break;
1017                 case SINE:            sprintf(text, _("Sine"));           break;
1018                 case SAWTOOTH:        sprintf(text, _("Sawtooth"));       break;
1019                 case SQUARE:          sprintf(text, _("Square"));         break;
1020                 case TRIANGLE:        sprintf(text, _("Triangle"));       break;
1021                 case PULSE:           sprintf(text, _("Pulse"));       break;
1022                 case NOISE:           sprintf(text, _("Noise"));       break;
1023         }
1024         return 0;
1025 }
1026
1027
1028 SynthMomentary::SynthMomentary(SynthWindow *window, int x, int y, char *text)
1029  : BC_CheckBox(x,
1030         y,
1031         window->synth->config.momentary_notes,
1032         text)
1033 {
1034         this->window = window;
1035 }
1036
1037 int SynthMomentary::handle_event()
1038 {
1039         window->synth->config.momentary_notes = get_value();
1040         window->synth->send_configure_change();
1041         return 1;
1042 }
1043
1044
1045
1046
1047 SynthNote::SynthNote(SynthWindow *window,
1048         VFrame **images,
1049         int number,
1050         int x,
1051         int y)
1052  : BC_Toggle(x,
1053         y,
1054         images,
1055         window->synth->freq_exists(keyboard_freqs[number]))
1056 {
1057         this->window = window;
1058         this->number = number;
1059         note_on = 0;
1060         set_select_drag(1);
1061         set_radial(1);
1062 }
1063
1064 void SynthNote::start_note()
1065 {
1066         if(window->synth->config.momentary_notes) note_on = 1;
1067
1068 //printf("SynthNote::start_note %d %d\n", __LINE__, ctrl_down());
1069         if(window->synth->config.momentary_notes || (!ctrl_down() && !shift_down()))
1070         {
1071 // Kill all frequencies
1072                 window->synth->delete_freqs();
1073         }
1074
1075         window->synth->new_freq(keyboard_freqs[number]);
1076         window->base_freq->update((float)window->synth->config.base_freq[0]);
1077 //printf("SynthNote::start_note %d %f\n", __LINE__, window->synth->config.base_freq[0]);
1078         window->freqpot->update(window->synth->config.base_freq[0]);
1079         window->synth->send_configure_change();
1080         window->update_note_selection();
1081 }
1082
1083 void SynthNote::stop_note()
1084 {
1085         note_on = 0;
1086         window->synth->delete_freq(keyboard_freqs[number]);
1087         window->base_freq->update((float)window->synth->config.base_freq[0]);
1088         window->freqpot->update(window->synth->config.base_freq[0]);
1089         window->synth->send_configure_change();
1090         window->update_note_selection();
1091 }
1092
1093 int SynthNote::keypress_event()
1094 {
1095         if(number >= FIRST_TITLE && number < LAST_TITLE)
1096         {
1097                 if(get_keypress() == keyboard_map[number - FIRST_TITLE][0])
1098                 {
1099                         if((ctrl_down() || shift_down()) &&
1100                                 window->synth->freq_exists(keyboard_freqs[number]))
1101                         {
1102                                 stop_note();
1103                         }
1104                         else
1105                         {
1106                                 start_note();
1107                                 set_value(1);
1108                         }
1109
1110 // Key releases are repeated, so momentary notes may not work
1111                         return 1;
1112                 }
1113         }
1114         return 0;
1115 }
1116
1117 int SynthNote::keyrelease_event()
1118 {
1119         if(note_on && window->synth->config.momentary_notes)
1120         {
1121                 stop_note();
1122                 set_value(0);
1123                 return 1;
1124         }
1125         return 0;
1126 }
1127
1128 int SynthNote::cursor_motion_event()
1129 {
1130         int result = 0;
1131         if(window->current_note > -1)
1132         {
1133                 int cursor_x = get_relative_cursor_x();
1134                 int cursor_y = get_relative_cursor_y();
1135                 if(cursor_x >= 0 && cursor_x < get_w() &&
1136                         cursor_y >= 0 && cursor_y < get_h())
1137                 {
1138                         if(window->starting_notes)
1139                         {
1140                                 start_note();
1141                         }
1142                         else
1143                         {
1144                                 stop_note();
1145                         }
1146
1147                         window->current_note = number;
1148                         result = 1;
1149                 }
1150         }
1151         return result;
1152 }
1153
1154 int SynthNote::button_press_event()
1155 {
1156         if(BC_Toggle::button_press_event())
1157         {
1158 // printf("SynthNote::button_press_event %d %d %d\n",
1159 // __LINE__,
1160 // ctrl_down(),
1161 // window->synth->freq_exists(keyboard_freqs[number]));
1162                 window->starting_notes = 1;
1163                 if((ctrl_down() || shift_down()) &&
1164                         window->synth->freq_exists(keyboard_freqs[number]))
1165                 {
1166 //printf("SynthNote::button_press_event %d\n", __LINE__);
1167                         stop_note();
1168                         window->starting_notes = 0;
1169                 }
1170                 else
1171                 {
1172 //printf("SynthNote::button_press_event %d\n", __LINE__);
1173                         start_note();
1174                         window->starting_notes = 1;
1175                 }
1176                 window->current_note = number;
1177                 return 1;
1178         }
1179         return 0;
1180 }
1181
1182 int SynthNote::button_release_event()
1183 {
1184 // Change frequency permanently
1185         if(window->current_note == number)
1186         {
1187                 if(window->synth->config.momentary_notes)
1188                 {
1189 // Mute on button release
1190                         stop_note();
1191                         set_value(0);
1192                 }
1193                 window->current_note = -1;
1194         }
1195
1196         return BC_Toggle::button_release_event();
1197 }
1198
1199 int SynthNote::draw_face(int flash, int flush)
1200 {
1201         BC_Toggle::draw_face(0, 0);
1202         static const char *titles[] =
1203         {
1204                 "C",
1205                 "C#",
1206                 "D",
1207                 "D#",
1208                 "E",
1209                 "F",
1210                 "F#",
1211                 "G",
1212                 "G#",
1213                 "A",
1214                 "A#",
1215                 "B"
1216         };
1217
1218
1219         const char *text = titles[number % (sizeof(titles) / sizeof(char*))];
1220         char string[BCTEXTLEN];
1221         sprintf(string, "%s%d", text, number / 12);
1222 //printf("SynthNote::draw_face %d %d %d %d %s\n", __LINE__, number, get_w(), get_h(), text);
1223         if(text[1] == '#')
1224         {
1225         }
1226         else
1227         {
1228                 set_color(BLACK);
1229                 draw_text(get_w() / 2 - get_text_width(MEDIUMFONT, string) / 2,
1230                         get_h() - get_text_height(MEDIUMFONT, string) - window->synth->get_theme()->widget_border,
1231                         string);
1232         }
1233
1234         if(flash) this->flash(0);
1235         if(flush) this->flush();
1236         return 0;
1237 }
1238
1239
1240
1241
1242
1243
1244
1245 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
1246 {
1247         this->window = window;
1248         this->number = number;
1249 }
1250
1251 SynthOscGUI::~SynthOscGUI()
1252 {
1253         delete title;
1254         delete level;
1255         delete phase;
1256         delete freq;
1257 }
1258
1259 void SynthOscGUI::create_objects(int y)
1260 {
1261         char text[BCTEXTLEN];
1262         sprintf(text, "%d:", number + 1);
1263         window->osc_subwindow->add_subwindow(title = new BC_Title(10, y + 15, text));
1264
1265         window->osc_subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
1266         window->osc_subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
1267         window->osc_subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
1268 }
1269
1270
1271
1272
1273 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
1274  : BC_FPot(50,
1275         y,
1276         synth->config.oscillator_config.values[gui->number]->level,
1277         INFINITYGAIN,
1278         0)
1279 {
1280         this->synth = synth;
1281         this->gui = gui;
1282 }
1283
1284 SynthOscGUILevel::~SynthOscGUILevel()
1285 {
1286 }
1287
1288 int SynthOscGUILevel::handle_event()
1289 {
1290         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1291         config->level = get_value();
1292         gui->window->canvas->update();
1293         synth->send_configure_change();
1294         return 1;
1295 }
1296
1297
1298
1299 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
1300  : BC_IPot(125,
1301         y,
1302         (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360),
1303         0,
1304         360)
1305 {
1306         this->synth = synth;
1307         this->gui = gui;
1308 }
1309
1310 SynthOscGUIPhase::~SynthOscGUIPhase()
1311 {
1312 }
1313
1314 int SynthOscGUIPhase::handle_event()
1315 {
1316         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1317         config->phase = (float)get_value() / 360;
1318         gui->window->canvas->update();
1319         synth->send_configure_change();
1320         return 1;
1321 }
1322
1323
1324
1325 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
1326  : BC_IPot(200,
1327         y,
1328         (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor),
1329         1,
1330         100)
1331 {
1332         this->synth = synth;
1333         this->gui = gui;
1334 }
1335
1336 SynthOscGUIFreq::~SynthOscGUIFreq()
1337 {
1338 }
1339
1340 int SynthOscGUIFreq::handle_event()
1341 {
1342         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
1343         config->freq_factor = get_value();
1344         gui->window->canvas->update();
1345         synth->send_configure_change();
1346         return 1;
1347 }
1348
1349
1350
1351
1352
1353
1354
1355 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
1356  : BC_GenericButton(x, y, _("Add"))
1357 {
1358         this->synth = synth;
1359         this->window = window;
1360 }
1361
1362 SynthAddOsc::~SynthAddOsc()
1363 {
1364 }
1365
1366 int SynthAddOsc::handle_event()
1367 {
1368         synth->add_oscillator();
1369         synth->send_configure_change();
1370         window->update_gui();
1371         return 1;
1372 }
1373
1374
1375
1376 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
1377  : BC_GenericButton(x, y, _("Delete"))
1378 {
1379         this->synth = synth;
1380         this->window = window;
1381 }
1382
1383 SynthDelOsc::~SynthDelOsc()
1384 {
1385 }
1386
1387 int SynthDelOsc::handle_event()
1388 {
1389         synth->delete_oscillator();
1390         synth->send_configure_change();
1391         window->update_gui();
1392         return 1;
1393 }
1394
1395
1396 OscScroll::OscScroll(Synth *synth,
1397         SynthWindow *window,
1398         int x,
1399         int y,
1400         int h)
1401  : BC_ScrollBar(x,
1402         y,
1403         SCROLL_VERT,
1404         h,
1405         synth->config.oscillator_config.total * OSCILLATORHEIGHT,
1406         0,
1407         window->osc_subwindow->get_h())
1408 {
1409         this->synth = synth;
1410         this->window = window;
1411 }
1412
1413 OscScroll::~OscScroll()
1414 {
1415 }
1416
1417 int OscScroll::handle_event()
1418 {
1419         window->update_oscillators();
1420         return 1;
1421 }
1422
1423
1424
1425 NoteScroll::NoteScroll(Synth *synth,
1426         SynthWindow *window,
1427         int x,
1428         int y,
1429         int w)
1430  : BC_ScrollBar(x,
1431         y,
1432         SCROLL_HORIZ,
1433         w,
1434         window->white_key[0]->get_w() * TOTALNOTES * 7 / 12 + window->white_key[0]->get_w(),
1435         0,
1436         window->note_subwindow->get_w())
1437 {
1438         this->synth = synth;
1439         this->window = window;
1440 }
1441
1442 NoteScroll::~NoteScroll()
1443 {
1444 }
1445
1446 int NoteScroll::handle_event()
1447 {
1448         window->update_notes();
1449         return 1;
1450 }
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465 SynthClear::SynthClear(Synth *synth, int x, int y)
1466  : BC_GenericButton(x, y, _("Clear"))
1467 {
1468         this->synth = synth;
1469 }
1470 SynthClear::~SynthClear()
1471 {
1472 }
1473 int SynthClear::handle_event()
1474 {
1475         synth->config.reset();
1476         synth->send_configure_change();
1477         synth->update_gui();
1478         return 1;
1479 }
1480
1481
1482
1483
1484
1485
1486 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
1487  : BC_PopupMenu(x, y, xS(120), text)
1488 {
1489         this->synth = synth;
1490 }
1491
1492 SynthWaveForm::~SynthWaveForm()
1493 {
1494 }
1495
1496 void SynthWaveForm::create_objects()
1497 {
1498 //      add_item(new SynthWaveFormItem(synth, _("DC"), DC));
1499         add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
1500         add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
1501         add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
1502         add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
1503         add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
1504         add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
1505 }
1506
1507 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1508  : BC_MenuItem(text)
1509 {
1510         this->synth = synth;
1511         this->value = value;
1512 }
1513
1514 SynthWaveFormItem::~SynthWaveFormItem()
1515 {
1516 }
1517
1518 int SynthWaveFormItem::handle_event()
1519 {
1520         synth->config.wavefunction = value;
1521         ((SynthWindow*)synth->thread->window)->canvas->update();
1522         get_popup_menu()->set_text(get_text());
1523         synth->send_configure_change();
1524         return 1;
1525 }
1526
1527
1528 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1529  : BC_FPot(x,
1530                 y,
1531                 synth->config.wetness,
1532                 INFINITYGAIN,
1533                 0)
1534 {
1535         this->synth = synth;
1536 }
1537
1538 int SynthWetness::handle_event()
1539 {
1540         synth->config.wetness = get_value();
1541         synth->send_configure_change();
1542         return 1;
1543 }
1544
1545
1546
1547 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1548  : BC_QPot(x, y, synth->config.base_freq[0])
1549 {
1550         this->synth = synth;
1551         this->window = window;
1552 }
1553 SynthFreqPot::~SynthFreqPot()
1554 {
1555 }
1556 int SynthFreqPot::handle_event()
1557 {
1558         if(get_value() > 0 && get_value() < 30000)
1559         {
1560                 synth->config.base_freq[0] = get_value();
1561                 freq_text->update(get_value());
1562                 synth->send_configure_change();
1563                 window->update_note_selection();
1564         }
1565         return 1;
1566 }
1567
1568
1569
1570 SynthBaseFreq::SynthBaseFreq(Synth *synth, SynthWindow *window, int x, int y)
1571  : BC_TextBox(x, y, xS(100), 1, (float)0)
1572 {
1573         this->synth = synth;
1574         this->window = window;
1575         set_precision(2);
1576 }
1577 SynthBaseFreq::~SynthBaseFreq()
1578 {
1579 }
1580 int SynthBaseFreq::handle_event()
1581 {
1582         double new_value = atof(get_text());
1583 // 0 is mute
1584         if(new_value < 30000)
1585         {
1586                 synth->config.base_freq[0] = new_value;
1587                 freq_pot->update(synth->config.base_freq[0]);
1588                 synth->send_configure_change();
1589                 window->update_note_selection();
1590         }
1591         return 1;
1592 }
1593
1594
1595
1596
1597
1598 SynthCanvas::SynthCanvas(Synth *synth,
1599         SynthWindow *window,
1600         int x,
1601         int y,
1602         int w,
1603         int h)
1604  : BC_SubWindow(x,
1605         y,
1606         w,
1607         h,
1608         BLACK)
1609 {
1610         this->synth = synth;
1611         this->window = window;
1612 }
1613
1614 SynthCanvas::~SynthCanvas()
1615 {
1616 }
1617
1618 int SynthCanvas::update()
1619 {
1620         int y1, y2, y = 0;
1621
1622         clear_box(0, 0, get_w(), get_h());
1623         set_color(RED);
1624
1625         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1626
1627         set_color(GREEN);
1628
1629         double normalize_constant = (double)1 / synth->get_total_power();
1630         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1631
1632         for(int i = 1; i < get_w(); i++)
1633         {
1634                 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1635                 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1636                 y1 = y2;
1637         }
1638         flash();
1639         return 0;
1640 }
1641
1642
1643
1644
1645
1646
1647
1648
1649 // ======================= level calculations
1650 SynthLevelZero::SynthLevelZero(Synth *synth)
1651  : BC_MenuItem(_("Zero"))
1652 {
1653         this->synth = synth;
1654 }
1655
1656 SynthLevelZero::~SynthLevelZero()
1657 {
1658 }
1659
1660 int SynthLevelZero::handle_event()
1661 {
1662         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1663         {
1664                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1665         }
1666
1667         ((SynthWindow*)synth->thread->window)->update_gui();
1668         synth->send_configure_change();
1669         return 1;
1670 }
1671
1672 SynthLevelMax::SynthLevelMax(Synth *synth)
1673  : BC_MenuItem(_("Maximum"))
1674 {
1675         this->synth = synth;
1676 }
1677
1678 SynthLevelMax::~SynthLevelMax()
1679 {
1680 }
1681
1682 int SynthLevelMax::handle_event()
1683 {
1684         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1685         {
1686                 synth->config.oscillator_config.values[i]->level = 0;
1687         }
1688         ((SynthWindow*)synth->thread->window)->update_gui();
1689         synth->send_configure_change();
1690         return 1;
1691 }
1692
1693 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1694  : BC_MenuItem(_("Normalize"))
1695 {
1696         this->synth = synth;
1697 }
1698
1699 SynthLevelNormalize::~SynthLevelNormalize()
1700 {
1701 }
1702
1703 int SynthLevelNormalize::handle_event()
1704 {
1705 // get total power
1706         float total = 0;
1707
1708         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1709         {
1710                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1711         }
1712
1713         float scale = 1 / total;
1714         float new_value;
1715
1716         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1717         {
1718                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1719                 new_value *= scale;
1720                 new_value = synth->db.todb(new_value);
1721
1722                 synth->config.oscillator_config.values[i]->level = new_value;
1723         }
1724
1725         ((SynthWindow*)synth->thread->window)->update_gui();
1726         synth->send_configure_change();
1727         return 1;
1728 }
1729
1730 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1731  : BC_MenuItem(_("Slope"))
1732 {
1733         this->synth = synth;
1734 }
1735
1736 SynthLevelSlope::~SynthLevelSlope()
1737 {
1738 }
1739
1740 int SynthLevelSlope::handle_event()
1741 {
1742         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1743
1744         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1745         {
1746                 synth->config.oscillator_config.values[i]->level = i * slope;
1747         }
1748
1749         ((SynthWindow*)synth->thread->window)->update_gui();
1750         synth->send_configure_change();
1751         return 1;
1752 }
1753
1754 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1755  : BC_MenuItem(_("Random"))
1756 {
1757         this->synth = synth;
1758 }
1759 SynthLevelRandom::~SynthLevelRandom()
1760 {
1761 }
1762
1763 int SynthLevelRandom::handle_event()
1764 {
1765         srand(time(0));
1766         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1767         {
1768                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1769         }
1770
1771         ((SynthWindow*)synth->thread->window)->update_gui();
1772         synth->send_configure_change();
1773         return 1;
1774 }
1775
1776 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1777  : BC_MenuItem(_("Invert"))
1778 {
1779         this->synth = synth;
1780 }
1781 SynthLevelInvert::~SynthLevelInvert()
1782 {
1783 }
1784
1785 int SynthLevelInvert::handle_event()
1786 {
1787         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1788         {
1789                 synth->config.oscillator_config.values[i]->level =
1790                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1791         }
1792
1793         ((SynthWindow*)synth->thread->window)->update_gui();
1794         synth->send_configure_change();
1795         return 1;
1796 }
1797
1798 SynthLevelSine::SynthLevelSine(Synth *synth)
1799  : BC_MenuItem(_("Sine"))
1800 {
1801         this->synth = synth;
1802 }
1803 SynthLevelSine::~SynthLevelSine()
1804 {
1805 }
1806
1807 int SynthLevelSine::handle_event()
1808 {
1809         float new_value;
1810
1811         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1812         {
1813                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1814                 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1815                 synth->config.oscillator_config.values[i]->level = new_value;
1816         }
1817
1818         ((SynthWindow*)synth->thread->window)->update_gui();
1819         synth->send_configure_change();
1820         return 1;
1821 }
1822
1823 // ============================ phase calculations
1824
1825 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1826  : BC_MenuItem(_("Invert"))
1827 {
1828         this->synth = synth;
1829 }
1830 SynthPhaseInvert::~SynthPhaseInvert()
1831 {
1832 }
1833
1834 int SynthPhaseInvert::handle_event()
1835 {
1836         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1837         {
1838                 synth->config.oscillator_config.values[i]->phase =
1839                         1 - synth->config.oscillator_config.values[i]->phase;
1840         }
1841
1842         ((SynthWindow*)synth->thread->window)->update_gui();
1843         synth->send_configure_change();
1844         return 1;
1845 }
1846
1847 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1848  : BC_MenuItem(_("Zero"))
1849 {
1850         this->synth = synth;
1851 }
1852 SynthPhaseZero::~SynthPhaseZero()
1853 {
1854 }
1855
1856 int SynthPhaseZero::handle_event()
1857 {
1858         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1859         {
1860                 synth->config.oscillator_config.values[i]->phase = 0;
1861         }
1862
1863         ((SynthWindow*)synth->thread->window)->update_gui();
1864         synth->send_configure_change();
1865         return 1;
1866 }
1867
1868 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1869  : BC_MenuItem(_("Sine"))
1870 {
1871         this->synth = synth;
1872 }
1873 SynthPhaseSine::~SynthPhaseSine()
1874 {
1875 }
1876
1877 int SynthPhaseSine::handle_event()
1878 {
1879         float new_value;
1880         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1881         {
1882                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1883                 new_value = sin(new_value) / 2 + .5;
1884                 synth->config.oscillator_config.values[i]->phase = new_value;
1885         }
1886
1887         ((SynthWindow*)synth->thread->window)->update_gui();
1888         synth->send_configure_change();
1889         return 1;
1890 }
1891
1892 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1893  : BC_MenuItem(_("Random"))
1894 {
1895         this->synth = synth;
1896 }
1897 SynthPhaseRandom::~SynthPhaseRandom()
1898 {
1899 }
1900
1901 int SynthPhaseRandom::handle_event()
1902 {
1903         srand(time(0));
1904         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1905         {
1906                 synth->config.oscillator_config.values[i]->phase =
1907                         (float)(rand() % 360) / 360;
1908         }
1909
1910         ((SynthWindow*)synth->thread->window)->update_gui();
1911         synth->send_configure_change();
1912         return 1;
1913 }
1914
1915
1916 // ============================ freq calculations
1917
1918 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1919  : BC_MenuItem(_("Random"))
1920 {
1921         this->synth = synth;
1922 }
1923 SynthFreqRandom::~SynthFreqRandom()
1924 {
1925 }
1926
1927 int SynthFreqRandom::handle_event()
1928 {
1929         srand(time(0));
1930         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1931         {
1932                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1933         }
1934
1935         ((SynthWindow*)synth->thread->window)->update_gui();
1936         synth->send_configure_change();
1937         return 1;
1938 }
1939
1940 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1941  : BC_MenuItem(_("Enumerate"))
1942 {
1943         this->synth = synth;
1944 }
1945 SynthFreqEnum::~SynthFreqEnum()
1946 {
1947 }
1948
1949 int SynthFreqEnum::handle_event()
1950 {
1951         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1952         {
1953                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1954         }
1955
1956         ((SynthWindow*)synth->thread->window)->update_gui();
1957         synth->send_configure_change();
1958         return 1;
1959 }
1960
1961 SynthFreqEven::SynthFreqEven(Synth *synth)
1962  : BC_MenuItem(_("Even"))
1963 {
1964         this->synth = synth;
1965 }
1966 SynthFreqEven::~SynthFreqEven()
1967 {
1968 }
1969
1970 int SynthFreqEven::handle_event()
1971 {
1972         if(synth->config.oscillator_config.total)
1973                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1974
1975         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1976         {
1977                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1978         }
1979
1980         ((SynthWindow*)synth->thread->window)->update_gui();
1981         synth->send_configure_change();
1982         return 1;
1983 }
1984
1985 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1986  : BC_MenuItem(_("Odd"))
1987 { this->synth = synth; }
1988 SynthFreqOdd::~SynthFreqOdd()
1989 {
1990 }
1991
1992 int SynthFreqOdd::handle_event()
1993 {
1994         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1995         {
1996                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1997         }
1998
1999         ((SynthWindow*)synth->thread->window)->update_gui();
2000         synth->send_configure_change();
2001         return 1;
2002 }
2003
2004 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
2005  : BC_MenuItem(_("Fibonnacci"))
2006 {
2007         this->synth = synth;
2008 }
2009 SynthFreqFibonacci::~SynthFreqFibonacci()
2010 {
2011 }
2012
2013 int SynthFreqFibonacci::handle_event()
2014 {
2015         float last_value1 = 0, last_value2 = 1;
2016         for(int i = 0; i < synth->config.oscillator_config.total; i++)
2017         {
2018                 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
2019                 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
2020                 last_value1 = last_value2;
2021                 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
2022         }
2023
2024         ((SynthWindow*)synth->thread->window)->update_gui();
2025         synth->send_configure_change();
2026         return 1;
2027 }
2028
2029 SynthFreqPrime::SynthFreqPrime(Synth *synth)
2030  : BC_MenuItem(_("Prime"))
2031 {
2032         this->synth = synth;
2033 }
2034 SynthFreqPrime::~SynthFreqPrime()
2035 {
2036 }
2037
2038 int SynthFreqPrime::handle_event()
2039 {
2040         float number = 1;
2041         for(int i = 0; i < synth->config.oscillator_config.total; i++)
2042         {
2043                 synth->config.oscillator_config.values[i]->freq_factor = number;
2044                 number = get_next_prime(number);
2045         }
2046
2047         ((SynthWindow*)synth->thread->window)->update_gui();
2048         synth->send_configure_change();
2049         return 1;
2050 }
2051
2052 float SynthFreqPrime::get_next_prime(float number)
2053 {
2054         int result = 1;
2055
2056         while(result)
2057         {
2058                 result = 0;
2059                 number++;
2060
2061                 for(float i = number - 1; i > 1 && !result; i--)
2062                 {
2063                         if((number / i) - (int)(number / i) == 0) result = 1;
2064                 }
2065         }
2066
2067         return number;
2068 }
2069
2070
2071
2072
2073
2074
2075
2076
2077 SynthOscillatorConfig::SynthOscillatorConfig(int number)
2078 {
2079         reset();
2080         this->number = number;
2081 }
2082
2083 SynthOscillatorConfig::~SynthOscillatorConfig()
2084 {
2085 }
2086
2087 void SynthOscillatorConfig::reset()
2088 {
2089         level = 0;
2090         phase = 0;
2091         freq_factor = 1;
2092 }
2093
2094
2095 void SynthOscillatorConfig::read_data(FileXML *file)
2096 {
2097         level = file->tag.get_property("LEVEL", (float)level);
2098         phase = file->tag.get_property("PHASE", (float)phase);
2099         freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
2100 }
2101
2102 void SynthOscillatorConfig::save_data(FileXML *file)
2103 {
2104         file->tag.set_title("OSCILLATOR");
2105         file->tag.set_property("LEVEL", (float)level);
2106         file->tag.set_property("PHASE", (float)phase);
2107         file->tag.set_property("FREQFACTOR", (float)freq_factor);
2108         file->append_tag();
2109         file->tag.set_title("/OSCILLATOR");
2110         file->append_tag();
2111         file->append_newline();
2112 }
2113
2114 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
2115 {
2116         if(EQUIV(level, that.level) &&
2117                 EQUIV(phase, that.phase) &&
2118                 EQUIV(freq_factor, that.freq_factor))
2119                 return 1;
2120         else
2121                 return 0;
2122 }
2123
2124 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
2125 {
2126         level = that.level;
2127         phase = that.phase;
2128         freq_factor = that.freq_factor;
2129 }
2130
2131
2132 SynthConfig::SynthConfig()
2133 {
2134         reset();
2135 }
2136
2137 SynthConfig::~SynthConfig()
2138 {
2139         oscillator_config.remove_all_objects();
2140 }
2141
2142 void SynthConfig::reset()
2143 {
2144         wetness = 0;
2145         base_freq[0] = 440;
2146         for(int i = 1; i < MAX_FREQS; i++)
2147                 base_freq[i] = 0;
2148         wavefunction = SINE;
2149         for(int i = 0; i < oscillator_config.total; i++)
2150         {
2151                 oscillator_config.values[i]->reset();
2152         }
2153
2154         momentary_notes = 0;
2155 }
2156
2157 int SynthConfig::equivalent(SynthConfig &that)
2158 {
2159 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
2160         for(int i = 0; i < MAX_FREQS; i++)
2161                 if(base_freq[i] != that.base_freq[i]) return 0;
2162
2163         if(wavefunction != that.wavefunction ||
2164                 oscillator_config.total != that.oscillator_config.total ||
2165                 momentary_notes != that.momentary_notes) return 0;
2166
2167         for(int i = 0; i < oscillator_config.total; i++)
2168         {
2169                 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
2170                         return 0;
2171         }
2172
2173         return 1;
2174 }
2175
2176 void SynthConfig::copy_from(SynthConfig& that)
2177 {
2178         wetness = that.wetness;
2179         for(int i = 0; i < MAX_FREQS; i++)
2180                 base_freq[i] = that.base_freq[i];
2181         wavefunction = that.wavefunction;
2182         momentary_notes = that.momentary_notes;
2183
2184         int i;
2185         for(i = 0;
2186                 i < oscillator_config.total && i < that.oscillator_config.total;
2187                 i++)
2188         {
2189                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2190         }
2191
2192         for( ;
2193                 i < that.oscillator_config.total;
2194                 i++)
2195         {
2196                 oscillator_config.append(new SynthOscillatorConfig(i));
2197                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
2198         }
2199
2200         for( ;
2201                 i < oscillator_config.total;
2202                 i++)
2203         {
2204                 oscillator_config.remove_object();
2205         }
2206
2207 }
2208
2209 void SynthConfig::interpolate(SynthConfig &prev,
2210         SynthConfig &next,
2211         int64_t prev_frame,
2212         int64_t next_frame,
2213         int64_t current_frame)
2214 {
2215         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
2216         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
2217
2218         copy_from(prev);
2219         wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
2220 //      base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);
2221
2222         momentary_notes = prev.momentary_notes;
2223 }
2224