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