initial commit
[goodguy/history.git] / cinelerra-5.0 / plugins / piano / piano.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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 "piano.h"
28 #include "vframe.h"
29
30 #include <string.h>
31
32
33
34 REGISTER_PLUGIN(Piano)
35
36
37
38
39
40 Piano::Piano(PluginServer *server)
41  : PluginAClient(server)
42 {
43         reset();
44 }
45
46
47
48 Piano::~Piano()
49 {
50         if(dsp_buffer) delete [] dsp_buffer;
51 }
52
53
54 char* Piano::plugin_title() { return N_("Pianoesizer"); }
55 int Piano::is_realtime() { return 1; }
56 int Piano::is_synthesis() { return 1; }
57
58
59 void Piano::reset()
60 {
61         thread = 0;
62         need_reconfigure = 1;
63         dsp_buffer = 0;
64 }
65
66
67
68
69 LOAD_CONFIGURATION_MACRO(Piano, PianoConfig)
70
71
72
73
74
75 void Piano::read_data(KeyFrame *keyframe)
76 {
77         FileXML input;
78 // cause htal file to read directly from text
79         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
80
81 //printf("Piano::read_data %s\n", keyframe->get_data());
82         int result = 0, current_osc = 0, total_oscillators = 0;
83         while(!result)
84         {
85                 result = input.read_tag();
86
87                 if(!result)
88                 {
89                         if(input.tag.title_is("SYNTH"))
90                         {
91                                 config.wetness = input.tag.get_property("WETNESS", config.wetness);
92                                 config.base_freq = input.tag.get_property("BASEFREQ", config.base_freq);
93                                 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
94                                 total_oscillators = input.tag.get_property("OSCILLATORS", 0);
95                         }
96                         else
97                         if(input.tag.title_is("OSCILLATOR"))
98                         {
99                                 if(current_osc >= config.oscillator_config.total)
100                                         config.oscillator_config.append(new PianoOscillatorConfig(current_osc));
101
102                                 config.oscillator_config.values[current_osc]->read_data(&input);
103                                 current_osc++;
104                         }
105                 }
106         }
107
108         while(config.oscillator_config.total > current_osc)
109                 config.oscillator_config.remove_object();
110 }
111
112 void Piano::save_data(KeyFrame *keyframe)
113 {
114         FileXML output;
115 // cause htal file to store data directly in text
116         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
117
118         output.tag.set_title("SYNTH");
119         output.tag.set_property("WETNESS", config.wetness);
120         output.tag.set_property("BASEFREQ", config.base_freq);
121         output.tag.set_property("WAVEFUNCTION", config.wavefunction);
122         output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
123         output.append_tag();
124         output.append_newline();
125
126         for(int i = 0; i < config.oscillator_config.total; i++)
127         {
128                 config.oscillator_config.values[i]->save_data(&output);
129         }
130
131         output.terminate_string();
132 // data is now in *text
133 }
134
135 int Piano::show_gui()
136 {
137         load_configuration();
138         
139         thread = new PianoThread(this);
140         thread->start();
141         return 0;
142 }
143
144 int Piano::set_string()
145 {
146         if(thread) thread->window->set_title(gui_string);
147         return 0;
148 }
149
150 void Piano::raise_window()
151 {
152         if(thread)
153         {
154                 thread->window->raise_window();
155                 thread->window->flush();
156         }
157 }
158
159 void Piano::update_gui()
160 {
161         if(thread)
162         {
163                 load_configuration();
164                 thread->window->lock_window();
165                 thread->window->update_gui();
166                 thread->window->unlock_window();
167         }
168 }
169
170
171 void Piano::add_oscillator()
172 {
173         if(config.oscillator_config.total > 20) return;
174
175         config.oscillator_config.append(new PianoOscillatorConfig(config.oscillator_config.total - 1));
176 }
177
178 void Piano::delete_oscillator()
179 {
180         if(config.oscillator_config.total)
181         {
182                 config.oscillator_config.remove_object();
183         }
184 }
185
186
187 double Piano::get_total_power()
188 {
189         double result = 0;
190
191         if(config.wavefunction == DC) return 1.0;
192
193         for(int i = 0; i < config.oscillator_config.total; i++)
194         {
195                 result += db.fromdb(config.oscillator_config.values[i]->level);
196         }
197
198         if(result == 0) result = 1;  // prevent division by 0
199         return result;
200 }
201
202
203 double Piano::solve_eqn(double *output, 
204         double x1, 
205         double x2, 
206         double normalize_constant,
207         int oscillator)
208 {
209         PianoOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
210         if(config->level <= INFINITYGAIN) return 0;
211
212         double result;
213         register double x;
214         double power = this->db.fromdb(config->level) * normalize_constant;
215         double phase_offset = config->phase * this->period;
216         double x3 = x1 + phase_offset;
217         double x4 = x2 + phase_offset;
218         double period = this->period / config->freq_factor;
219         int sample;
220
221         switch(this->config.wavefunction)
222         {
223                 case DC:
224                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
225                         {
226                                 output[sample] += power;
227                         }
228                         break;
229                 case SINE:
230                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
231                         {
232                                 output[sample] += sin(x / period * 2 * M_PI) * power;
233                         }
234                         break;
235                 case SAWTOOTH:
236                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
237                         {
238                                 output[sample] += function_sawtooth(x / period) * power;
239                         }
240                         break;
241                 case SQUARE:
242                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
243                         {
244                                 output[sample] += function_square(x / period) * power;
245                         }
246                         break;
247                 case TRIANGLE:
248                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
249                         {
250                                 output[sample] += function_triangle(x / period) * power;
251                         }
252                         break;
253                 case PULSE:
254                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
255                         {
256                                 output[sample] += function_pulse(x / period) * power;
257                         }
258                         break;
259                 case NOISE:
260                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
261                         {
262                                 output[sample] += function_noise() * power;
263                         }
264                         break;
265         }
266 }
267
268 double Piano::get_point(float x, double normalize_constant)
269 {
270         double result = 0;
271         for(int i = 0; i < config.oscillator_config.total; i++)
272                 result += get_oscillator_point(x, normalize_constant, i);
273
274         return result;
275 }
276
277 double Piano::get_oscillator_point(float x, 
278                 double normalize_constant, 
279                 int oscillator)
280 {
281         PianoOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
282         double power = db.fromdb(config->level) * normalize_constant;
283         switch(this->config.wavefunction)
284         {
285                 case DC:
286                         return power;
287                         break;
288                 case SINE:
289                         return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
290                         break;
291                 case SAWTOOTH:
292                         return function_sawtooth((x + config->phase) * config->freq_factor) * power;
293                         break;
294                 case SQUARE:
295                         return function_square((x + config->phase) * config->freq_factor) * power;
296                         break;
297                 case TRIANGLE:
298                         return function_triangle((x + config->phase) * config->freq_factor) * power;
299                         break;
300                 case PULSE:
301                         return function_pulse((x + config->phase) * config->freq_factor) * power;
302                         break;
303                 case NOISE:
304                         return function_noise() * power;
305                         break;
306         }
307 }
308
309 double Piano::function_square(double x)
310 {
311         x -= (int)x; // only fraction counts
312         return (x < .5) ? -1 : 1;
313 }
314
315 double Piano::function_pulse(double x)
316 {
317         x -= (int)x; // only fraction counts
318         return (x < .5) ? 0 : 1;
319 }
320
321 double Piano::function_noise()
322 {
323         return (double)(rand() % 65536 - 32768) / 32768;
324 }
325
326 double Piano::function_sawtooth(double x)
327 {
328         x -= (int)x;
329         return 1 - x * 2;
330 }
331
332 double Piano::function_triangle(double x)
333 {
334         x -= (int)x;
335         return (x < .5) ? 1 - x * 4 : -3 + x * 4;
336 }
337
338 int Piano::process_realtime(int64_t size, double *input_ptr, double *output_ptr)
339 {
340
341
342         need_reconfigure |= load_configuration();
343         if(need_reconfigure) reconfigure();
344
345         double wetness = DB::fromdb(config.wetness);
346         if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
347
348         for(int j = 0; j < size; j++)
349                 output_ptr[j] = input_ptr[j] * wetness;
350
351         int64_t fragment_len;
352         for(int64_t i = 0; i < size; i += fragment_len)
353         {
354                 fragment_len = size;
355                 if(i + fragment_len > size) fragment_len = size - i;
356
357 //printf("Piano::process_realtime 1 %d %d %d\n", i, fragment_len, size);
358                 fragment_len = overlay_synth(i, fragment_len, input_ptr, output_ptr);
359 //printf("Piano::process_realtime 2\n");
360         }
361         
362         
363         return 0;
364 }
365
366 int Piano::overlay_synth(int64_t start, int64_t length, double *input, double *output)
367 {
368         if(waveform_sample + length > waveform_length) 
369                 length = waveform_length - waveform_sample;
370
371 //printf("Piano::overlay_synth 1 %d %d\n", length, waveform_length);
372
373 // calculate some more data
374 // only calculate what's needed to speed it up
375         if(waveform_sample + length > samples_rendered)
376         {
377                 int64_t start = waveform_sample, end = waveform_sample + length;
378                 for(int i = start; i < end; i++) dsp_buffer[i] = 0;
379                 
380                 double normalize_constant = 1 / get_total_power();
381                 for(int i = 0; i < config.oscillator_config.total; i++)
382                         solve_eqn(dsp_buffer, 
383                                 start, 
384                                 end, 
385                                 normalize_constant,
386                                 i);
387
388                 
389                 samples_rendered = end;
390         }
391 //printf("Piano::overlay_synth 2\n");
392
393
394         double *buffer_in = &input[start];
395         double *buffer_out = &output[start];
396
397         for(int i = 0; i < length; i++)
398         {
399                 buffer_out[i] += dsp_buffer[waveform_sample++];
400         }
401 //printf("Piano::overlay_synth 3\n");
402
403         if(waveform_sample >= waveform_length) waveform_sample = 0;
404
405         return length;
406 }
407
408 void Piano::reconfigure()
409 {
410         need_reconfigure = 0;
411
412         if(dsp_buffer)
413         {
414                 delete [] dsp_buffer;
415         }
416
417 //printf("Piano::reconfigure 1 %d\n", PluginAClient::project_sample_rate);
418         waveform_length = PluginAClient::project_sample_rate;
419         period = (float)PluginAClient::project_sample_rate / config.base_freq;
420         dsp_buffer = new double[waveform_length + 1];
421
422         samples_rendered = 0;     // do some calculations on the next process_realtime
423         waveform_sample = 0;
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 PianoThread::PianoThread(Piano *synth)
447  : Thread()
448 {
449         this->synth = synth;
450         set_synchronous(0);
451         completion.lock();
452 }
453
454 PianoThread::~PianoThread()
455 {
456         delete window;
457 }
458
459 void PianoThread::run()
460 {
461         BC_DisplayInfo info;
462         window = new PianoWindow(synth, 
463                 info.get_abs_cursor_x() - 125, 
464                 info.get_abs_cursor_y() - 115);
465         window->create_objects();
466         int result = window->run_window();
467         completion.unlock();
468 // Last command executed in thread
469         if(result) synth->client_side_close();
470 }
471
472
473
474
475
476
477
478
479
480
481
482 PianoWindow::PianoWindow(Piano *synth, int x, int y)
483  : BC_Window(synth->gui_string, 
484         x, 
485         y, 
486         380, 
487         synth->h, 
488         380, 
489         10, 
490         1, 
491         0,
492         1)
493 {
494         this->synth = synth; 
495 }
496
497 PianoWindow::~PianoWindow()
498 {
499 }
500
501 int PianoWindow::create_objects()
502 {
503         BC_MenuBar *menu;
504         add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
505
506         BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
507         menu->add_menu(levelmenu = new BC_Menu(_("Level")));
508         menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
509         menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
510
511         levelmenu->add_item(new PianoLevelInvert(synth));
512         levelmenu->add_item(new PianoLevelMax(synth));
513         levelmenu->add_item(new PianoLevelRandom(synth));
514         levelmenu->add_item(new PianoLevelSine(synth));
515         levelmenu->add_item(new PianoLevelSlope(synth));
516         levelmenu->add_item(new PianoLevelZero(synth));
517
518         phasemenu->add_item(new PianoPhaseInvert(synth));
519         phasemenu->add_item(new PianoPhaseRandom(synth));
520         phasemenu->add_item(new PianoPhaseSine(synth));
521         phasemenu->add_item(new PianoPhaseZero(synth));
522
523         harmonicmenu->add_item(new PianoFreqEnum(synth));
524         harmonicmenu->add_item(new PianoFreqEven(synth));
525         harmonicmenu->add_item(new PianoFreqFibonacci(synth));
526         harmonicmenu->add_item(new PianoFreqOdd(synth));
527         harmonicmenu->add_item(new PianoFreqPrime(synth));
528
529         int x = 10, y = 30, i;
530         add_subwindow(new BC_Title(x, y, _("Waveform")));
531         x += 240;
532         add_subwindow(new BC_Title(x, y, _("Wave Function")));
533         y += 20;
534         x = 10;
535         add_subwindow(canvas = new PianoCanvas(synth, this, x, y, 230, 160));
536         canvas->update();
537
538         x += 240;
539         char string[BCTEXTLEN];
540         waveform_to_text(string, synth->config.wavefunction);
541
542         add_subwindow(waveform = new PianoWaveForm(synth, x, y, string));
543         waveform->create_objects();
544         y += 30;
545
546
547         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
548         y += 30;
549         add_subwindow(base_freq = new PianoBaseFreq(synth, x, y));
550         x += 80;
551         add_subwindow(freqpot = new PianoFreqPot(synth, this, x, y - 10));
552         base_freq->freq_pot = freqpot;
553         freqpot->freq_text = base_freq;
554         x -= 80;
555         y += 40;
556         add_subwindow(new BC_Title(x, y, _("Wetness:")));
557         add_subwindow(wetness = new PianoWetness(synth, x + 70, y - 10));
558
559         y += 40;
560         add_subwindow(new PianoClear(synth, x, y));
561
562
563         x = 50;  
564         y = 220;
565         add_subwindow(new BC_Title(x, y, _("Level"))); 
566         x += 75;
567         add_subwindow(new BC_Title(x, y, _("Phase"))); 
568         x += 75;
569         add_subwindow(new BC_Title(x, y, _("Harmonic")));
570
571
572
573         y += 20; x = 10;
574         add_subwindow(subwindow = new PianoSubWindow(synth, x, y, 265, get_h() - y));
575         x += 265;
576         add_subwindow(scroll = new PianoScroll(synth, this, x, y, get_h() - y));
577
578
579         x += 20;
580         add_subwindow(new PianoAddOsc(synth, this, x, y));
581         y += 30;
582         add_subwindow(new PianoDelOsc(synth, this, x, y));
583
584         update_scrollbar();
585         update_oscillators();
586
587         show_window();
588         flush();
589         return 0;
590 }
591
592 int PianoWindow::close_event()
593 {
594 // Set result to 1 to indicate a client side close
595         set_done(1);
596         return 1;
597 }
598
599 int PianoWindow::resize_event(int w, int h)
600 {
601         clear_box(0, 0, w, h);
602         subwindow->reposition_window(subwindow->get_x(), 
603                 subwindow->get_y(), 
604                 subwindow->get_w(), 
605                 h - subwindow->get_y());
606         subwindow->clear_box(0, 0, subwindow->get_w(), subwindow->get_h());
607         scroll->reposition_window(scroll->get_x(), 
608                 scroll->get_y(), 
609                 h - scroll->get_y());
610         update_scrollbar();
611         update_oscillators();
612         synth->w = w;
613         synth->h = h;
614         return 1;
615 }
616
617 void PianoWindow::update_gui()
618 {
619         char string[BCTEXTLEN];
620         freqpot->update(synth->config.base_freq);
621         base_freq->update((int64_t)synth->config.base_freq);
622         wetness->update(synth->config.wetness);
623         waveform_to_text(string, synth->config.wavefunction);
624         waveform->set_text(string);
625         
626         update_scrollbar();
627         update_oscillators();
628         canvas->update();
629 }
630
631 void PianoWindow::update_scrollbar()
632 {
633         scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
634                 scroll->get_position(), 
635                 subwindow->get_h());
636 }
637
638 void PianoWindow::update_oscillators()
639 {
640         int i, y = -scroll->get_position();
641
642
643
644 // Add new oscillators
645         for(i = 0; 
646                 i < synth->config.oscillator_config.total; 
647                 i++)
648         {
649                 PianoOscGUI *gui;
650                 PianoOscillatorConfig *config = synth->config.oscillator_config.values[i];
651
652                 if(oscillators.total <= i)
653                 {
654                         oscillators.append(gui = new PianoOscGUI(this, i));
655                         gui->create_objects(y);
656                 }
657                 else
658                 {
659                         gui = oscillators.values[i];
660
661                         gui->title->reposition_window(gui->title->get_x(), y + 15);
662
663                         gui->level->reposition_window(gui->level->get_x(), y);
664                         gui->level->update(config->level);
665
666                         gui->phase->reposition_window(gui->phase->get_x(), y);
667                         gui->phase->update((int64_t)(config->phase * 360));
668
669                         gui->freq->reposition_window(gui->freq->get_x(), y);
670                         gui->freq->update((int64_t)(config->freq_factor));
671                 }
672                 y += OSCILLATORHEIGHT;
673         }
674
675 // Delete old oscillators
676         for( ; 
677                 i < oscillators.total;
678                 i++)
679                 oscillators.remove_object();
680 }
681
682
683 int PianoWindow::waveform_to_text(char *text, int waveform)
684 {
685         switch(waveform)
686         {
687                 case DC:              sprintf(text, _("DC"));           break;
688                 case SINE:            sprintf(text, _("Sine"));           break;
689                 case SAWTOOTH:        sprintf(text, _("Sawtooth"));       break;
690                 case SQUARE:          sprintf(text, _("Square"));         break;
691                 case TRIANGLE:        sprintf(text, _("Triangle"));       break;
692                 case PULSE:           sprintf(text, _("Pulse"));       break;
693                 case NOISE:           sprintf(text, _("Noise"));       break;
694         }
695         return 0;
696 }
697
698
699
700
701
702
703
704 PianoOscGUI::PianoOscGUI(PianoWindow *window, int number)
705 {
706         this->window = window;
707         this->number = number;
708 }
709
710 PianoOscGUI::~PianoOscGUI()
711 {
712         delete title;
713         delete level;
714         delete phase;
715         delete freq;
716 }
717
718 int PianoOscGUI::create_objects(int y)
719 {
720         char text[BCTEXTLEN];
721         sprintf(text, "%d:", number + 1);
722         window->subwindow->add_subwindow(title = new BC_Title(10, y + 15, text));
723
724         window->subwindow->add_subwindow(level = new PianoOscGUILevel(window->synth, this, y));
725         window->subwindow->add_subwindow(phase = new PianoOscGUIPhase(window->synth, this, y));
726         window->subwindow->add_subwindow(freq = new PianoOscGUIFreq(window->synth, this, y));
727         return 1;
728 }
729
730
731
732
733 PianoOscGUILevel::PianoOscGUILevel(Piano *synth, PianoOscGUI *gui, int y)
734  : BC_FPot(50, 
735         y, 
736         synth->config.oscillator_config.values[gui->number]->level, 
737         INFINITYGAIN, 
738         0)
739 {
740         this->synth = synth;
741         this->gui = gui;
742 }
743
744 PianoOscGUILevel::~PianoOscGUILevel()
745 {
746 }
747
748 int PianoOscGUILevel::handle_event()
749 {
750         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
751         config->level = get_value();
752         gui->window->canvas->update();
753         synth->send_configure_change();
754         return 1;
755 }
756
757
758
759 PianoOscGUIPhase::PianoOscGUIPhase(Piano *synth, PianoOscGUI *gui, int y)
760  : BC_IPot(125, 
761         y, 
762         (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360), 
763         0, 
764         360)
765 {
766         this->synth = synth;
767         this->gui = gui;
768 }
769
770 PianoOscGUIPhase::~PianoOscGUIPhase()
771 {
772 }
773
774 int PianoOscGUIPhase::handle_event()
775 {
776         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
777         config->phase = (float)get_value() / 360;
778         gui->window->canvas->update();
779         synth->send_configure_change();
780         return 1;
781 }
782
783
784
785 PianoOscGUIFreq::PianoOscGUIFreq(Piano *synth, PianoOscGUI *gui, int y)
786  : BC_IPot(200, 
787         y, 
788         (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor), 
789         1, 
790         100)
791 {
792         this->synth = synth;
793         this->gui = gui;
794 }
795
796 PianoOscGUIFreq::~PianoOscGUIFreq()
797 {
798 }
799
800 int PianoOscGUIFreq::handle_event()
801 {
802         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
803         config->freq_factor = get_value();
804         gui->window->canvas->update();
805         synth->send_configure_change();
806         return 1;
807 }
808
809
810
811
812
813
814
815 PianoAddOsc::PianoAddOsc(Piano *synth, PianoWindow *window, int x, int y)
816  : BC_GenericButton(x, y, _("Add"))
817 {
818         this->synth = synth;
819         this->window = window;
820 }
821
822 PianoAddOsc::~PianoAddOsc()
823 {
824 }
825
826 int PianoAddOsc::handle_event()
827 {
828         synth->add_oscillator();
829         synth->send_configure_change();
830         window->update_gui();
831         return 1;
832 }
833
834
835
836 PianoDelOsc::PianoDelOsc(Piano *synth, PianoWindow *window, int x, int y)
837  : BC_GenericButton(x, y, _("Delete"))
838 {
839         this->synth = synth;
840         this->window = window;
841 }
842
843 PianoDelOsc::~PianoDelOsc()
844 {
845 }
846
847 int PianoDelOsc::handle_event()
848 {
849         synth->delete_oscillator();
850         synth->send_configure_change();
851         window->update_gui();
852         return 1;
853 }
854
855
856 PianoScroll::PianoScroll(Piano *synth, 
857         PianoWindow *window, 
858         int x, 
859         int y, 
860         int h)
861  : BC_ScrollBar(x, 
862         y, 
863         SCROLL_VERT,
864         h, 
865         synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
866         0, 
867         window->subwindow->get_h())
868 {
869         this->synth = synth;
870         this->window = window;
871 }
872
873 PianoScroll::~PianoScroll()
874 {
875 }
876
877 int PianoScroll::handle_event()
878 {
879         window->update_gui();
880         return 1;
881 }
882
883
884
885
886
887
888
889
890 PianoSubWindow::PianoSubWindow(Piano *synth, int x, int y, int w, int h)
891  : BC_SubWindow(x, y, w, h)
892 {
893         this->synth = synth;
894 }
895 PianoSubWindow::~PianoSubWindow()
896 {
897 }
898
899
900
901
902
903
904
905
906
907 PianoClear::PianoClear(Piano *synth, int x, int y)
908  : BC_GenericButton(x, y, _("Clear"))
909 {
910         this->synth = synth;
911 }
912 PianoClear::~PianoClear()
913 {
914 }
915 int PianoClear::handle_event()
916 {
917         synth->config.reset();
918         synth->send_configure_change();
919         synth->update_gui();
920         return 1;
921 }
922
923
924
925
926
927
928 PianoWaveForm::PianoWaveForm(Piano *synth, int x, int y, char *text)
929  : BC_PopupMenu(x, y, 120, text)
930 {
931         this->synth = synth;
932 }
933
934 PianoWaveForm::~PianoWaveForm()
935 {
936 }
937
938 int PianoWaveForm::create_objects()
939 {
940 //      add_item(new PianoWaveFormItem(synth, _("DC"), DC));
941         add_item(new PianoWaveFormItem(synth, _("Sine"), SINE));
942         add_item(new PianoWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
943         add_item(new PianoWaveFormItem(synth, _("Square"), SQUARE));
944         add_item(new PianoWaveFormItem(synth, _("Triangle"), TRIANGLE));
945         add_item(new PianoWaveFormItem(synth, _("Pulse"), PULSE));
946         add_item(new PianoWaveFormItem(synth, _("Noise"), NOISE));
947         return 0;
948 }
949
950 PianoWaveFormItem::PianoWaveFormItem(Piano *synth, char *text, int value)
951  : BC_MenuItem(text)
952 {
953         this->synth = synth;
954         this->value = value;
955 }
956
957 PianoWaveFormItem::~PianoWaveFormItem()
958 {
959 }
960
961 int PianoWaveFormItem::handle_event()
962 {
963         synth->config.wavefunction = value;
964         synth->thread->window->canvas->update();
965         synth->send_configure_change();
966         return 1;
967 }
968
969
970 PianoWetness::PianoWetness(Piano *synth, int x, int y)
971  : BC_FPot(x, 
972                 y, 
973                 synth->config.wetness, 
974                 INFINITYGAIN, 
975                 0)
976 {
977         this->synth = synth;
978 }
979
980 int PianoWetness::handle_event()
981 {
982         synth->config.wetness = get_value();
983         synth->send_configure_change();
984         return 1;
985 }
986
987
988
989 PianoFreqPot::PianoFreqPot(Piano *synth, PianoWindow *window, int x, int y)
990  : BC_QPot(x, y, synth->config.base_freq)
991 {
992         this->synth = synth;
993 }
994 PianoFreqPot::~PianoFreqPot()
995 {
996 }
997 int PianoFreqPot::handle_event()
998 {
999         if(get_value() > 0 && get_value() < 30000)
1000         {
1001                 synth->config.base_freq = get_value();
1002                 freq_text->update(get_value());
1003                 synth->send_configure_change();
1004         }
1005         return 1;
1006 }
1007
1008
1009
1010 PianoBaseFreq::PianoBaseFreq(Piano *synth, int x, int y)
1011  : BC_TextBox(x, y, 70, 1, (int)synth->config.base_freq)
1012 {
1013         this->synth = synth;
1014 }
1015 PianoBaseFreq::~PianoBaseFreq()
1016 {
1017 }
1018 int PianoBaseFreq::handle_event()
1019 {
1020         int new_value = atol(get_text());
1021         
1022         if(new_value > 0 && new_value < 30000)
1023         {
1024                 synth->config.base_freq = new_value;
1025                 freq_pot->update(synth->config.base_freq);
1026                 synth->send_configure_change();
1027         }
1028         return 1;
1029 }
1030
1031
1032
1033
1034
1035 PianoCanvas::PianoCanvas(Piano *synth, 
1036         PianoWindow *window, 
1037         int x, 
1038         int y, 
1039         int w, 
1040         int h)
1041  : BC_SubWindow(x, 
1042         y, 
1043         w, 
1044         h, 
1045         BLACK)
1046 {
1047         this->synth = synth;
1048         this->window = window;
1049 }
1050
1051 PianoCanvas::~PianoCanvas()
1052 {
1053 }
1054
1055 int PianoCanvas::update()
1056 {
1057         int y1, y2, y = 0;
1058         
1059         clear_box(0, 0, get_w(), get_h());
1060         set_color(RED);
1061
1062         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1063
1064         set_color(GREEN);
1065
1066         double normalize_constant = (double)1 / synth->get_total_power();
1067         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1068         
1069         for(int i = 1; i < get_w(); i++)
1070         {
1071                 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1072                 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1073                 y1 = y2;
1074         }
1075         flash();
1076         return 0;
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086 // ======================= level calculations
1087 PianoLevelZero::PianoLevelZero(Piano *synth)
1088  : BC_MenuItem(_("Zero"))
1089
1090         this->synth = synth; 
1091 }
1092
1093 PianoLevelZero::~PianoLevelZero() 
1094 {
1095 }
1096
1097 int PianoLevelZero::handle_event()
1098 {
1099         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1100         {
1101                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1102         }
1103
1104         synth->thread->window->update_gui();
1105         synth->send_configure_change();
1106 }
1107
1108 PianoLevelMax::PianoLevelMax(Piano *synth)
1109  : BC_MenuItem(_("Maximum"))
1110
1111         this->synth = synth; 
1112 }
1113
1114 PianoLevelMax::~PianoLevelMax()
1115 {
1116 }
1117
1118 int PianoLevelMax::handle_event()
1119 {
1120         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1121         {
1122                 synth->config.oscillator_config.values[i]->level = 0;
1123         }
1124         synth->thread->window->update_gui();
1125         synth->send_configure_change();
1126 }
1127
1128 PianoLevelNormalize::PianoLevelNormalize(Piano *synth)
1129  : BC_MenuItem(_("Normalize"))
1130 {
1131         this->synth = synth;
1132 }
1133
1134 PianoLevelNormalize::~PianoLevelNormalize()
1135 {
1136 }
1137
1138 int PianoLevelNormalize::handle_event()
1139 {
1140 // get total power
1141         float total = 0;
1142
1143         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1144         {
1145                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1146         }
1147
1148         float scale = 1 / total;
1149         float new_value;
1150
1151         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1152         {
1153                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1154                 new_value *= scale;
1155                 new_value = synth->db.todb(new_value);
1156                 
1157                 synth->config.oscillator_config.values[i]->level = new_value;
1158         }
1159
1160         synth->thread->window->update_gui();
1161         synth->send_configure_change();
1162 }
1163
1164 PianoLevelSlope::PianoLevelSlope(Piano *synth)
1165  : BC_MenuItem(_("Slope"))
1166 {
1167         this->synth = synth;
1168 }
1169
1170 PianoLevelSlope::~PianoLevelSlope()
1171 {
1172 }
1173
1174 int PianoLevelSlope::handle_event()
1175 {
1176         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1177         
1178         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1179         {
1180                 synth->config.oscillator_config.values[i]->level = i * slope;
1181         }
1182
1183         synth->thread->window->update_gui();
1184         synth->send_configure_change();
1185 }
1186
1187 PianoLevelRandom::PianoLevelRandom(Piano *synth)
1188  : BC_MenuItem(_("Random"))
1189
1190         this->synth = synth; 
1191 }
1192 PianoLevelRandom::~PianoLevelRandom()
1193 {
1194 }
1195
1196 int PianoLevelRandom::handle_event()
1197 {
1198         srand(time(0));
1199         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1200         {
1201                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1202         }
1203
1204         synth->thread->window->update_gui();
1205         synth->send_configure_change();
1206 }
1207
1208 PianoLevelInvert::PianoLevelInvert(Piano *synth)
1209  : BC_MenuItem(_("Invert"))
1210 {
1211         this->synth = synth;
1212 }
1213 PianoLevelInvert::~PianoLevelInvert()
1214 {
1215 }
1216
1217 int PianoLevelInvert::handle_event()
1218 {
1219         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1220         {
1221                 synth->config.oscillator_config.values[i]->level = 
1222                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1223         }
1224
1225         synth->thread->window->update_gui();
1226         synth->send_configure_change();
1227 }
1228
1229 PianoLevelSine::PianoLevelSine(Piano *synth)
1230  : BC_MenuItem(_("Sine"))
1231 {
1232         this->synth = synth;
1233 }
1234 PianoLevelSine::~PianoLevelSine()
1235 {
1236 }
1237
1238 int PianoLevelSine::handle_event()
1239 {
1240         float new_value;
1241
1242         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1243         {
1244                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1245                 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1246                 synth->config.oscillator_config.values[i]->level = new_value;
1247         }
1248
1249         synth->thread->window->update_gui();
1250         synth->send_configure_change();
1251 }
1252
1253 // ============================ phase calculations
1254
1255 PianoPhaseInvert::PianoPhaseInvert(Piano *synth)
1256  : BC_MenuItem(_("Invert"))
1257 {
1258         this->synth = synth;
1259 }
1260 PianoPhaseInvert::~PianoPhaseInvert()
1261 {
1262 }
1263
1264 int PianoPhaseInvert::handle_event()
1265 {
1266         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1267         {
1268                 synth->config.oscillator_config.values[i]->phase = 
1269                         1 - synth->config.oscillator_config.values[i]->phase;
1270         }
1271
1272         synth->thread->window->update_gui();
1273         synth->send_configure_change();
1274 }
1275
1276 PianoPhaseZero::PianoPhaseZero(Piano *synth)
1277  : BC_MenuItem(_("Zero"))
1278 {
1279         this->synth = synth;
1280 }
1281 PianoPhaseZero::~PianoPhaseZero()
1282 {
1283 }
1284
1285 int PianoPhaseZero::handle_event()
1286 {
1287         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1288         {
1289                 synth->config.oscillator_config.values[i]->phase = 0;
1290         }
1291
1292         synth->thread->window->update_gui();
1293         synth->send_configure_change();
1294 }
1295
1296 PianoPhaseSine::PianoPhaseSine(Piano *synth)
1297  : BC_MenuItem(_("Sine"))
1298 {
1299         this->synth = synth;
1300 }
1301 PianoPhaseSine::~PianoPhaseSine()
1302 {
1303 }
1304
1305 int PianoPhaseSine::handle_event()
1306 {
1307         float new_value;
1308         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1309         {
1310                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1311                 new_value = sin(new_value) / 2 + .5;
1312                 synth->config.oscillator_config.values[i]->phase = new_value;
1313         }
1314
1315         synth->thread->window->update_gui();
1316         synth->send_configure_change();
1317 }
1318
1319 PianoPhaseRandom::PianoPhaseRandom(Piano *synth)
1320  : BC_MenuItem(_("Random"))
1321 {
1322         this->synth = synth;
1323 }
1324 PianoPhaseRandom::~PianoPhaseRandom()
1325 {
1326 }
1327
1328 int PianoPhaseRandom::handle_event()
1329 {
1330         srand(time(0));
1331         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1332         {
1333                 synth->config.oscillator_config.values[i]->phase = 
1334                         (float)(rand() % 360) / 360;
1335         }
1336
1337         synth->thread->window->update_gui();
1338         synth->send_configure_change();
1339 }
1340
1341
1342 // ============================ freq calculations
1343
1344 PianoFreqRandom::PianoFreqRandom(Piano *synth)
1345  : BC_MenuItem(_("Random"))
1346 {
1347         this->synth = synth;
1348 }
1349 PianoFreqRandom::~PianoFreqRandom()
1350 {
1351 }
1352
1353 int PianoFreqRandom::handle_event()
1354 {
1355         srand(time(0));
1356         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1357         {
1358                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1359         }
1360
1361         synth->thread->window->update_gui();
1362         synth->send_configure_change();
1363 }
1364
1365 PianoFreqEnum::PianoFreqEnum(Piano *synth)
1366  : BC_MenuItem(_("Enumerate"))
1367 {
1368         this->synth = synth;
1369 }
1370 PianoFreqEnum::~PianoFreqEnum()
1371 {
1372 }
1373
1374 int PianoFreqEnum::handle_event()
1375 {
1376         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1377         {
1378                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1379         }
1380
1381         synth->thread->window->update_gui();
1382         synth->send_configure_change();
1383 }
1384
1385 PianoFreqEven::PianoFreqEven(Piano *synth)
1386  : BC_MenuItem(_("Even"))
1387 {
1388         this->synth = synth;
1389 }
1390 PianoFreqEven::~PianoFreqEven()
1391 {
1392 }
1393
1394 int PianoFreqEven::handle_event()
1395 {
1396         if(synth->config.oscillator_config.total)
1397                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1398
1399         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1400         {
1401                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1402         }
1403
1404         synth->thread->window->update_gui();
1405         synth->send_configure_change();
1406 }
1407
1408 PianoFreqOdd::PianoFreqOdd(Piano *synth)
1409  : BC_MenuItem(_("Odd"))
1410 { this->synth = synth; }
1411 PianoFreqOdd::~PianoFreqOdd()
1412 {
1413 }
1414
1415 int PianoFreqOdd::handle_event()
1416 {
1417         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1418         {
1419                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1420         }
1421
1422         synth->thread->window->update_gui();
1423         synth->send_configure_change();
1424 }
1425
1426 PianoFreqFibonacci::PianoFreqFibonacci(Piano *synth)
1427  : BC_MenuItem(_("Fibonnacci"))
1428
1429         this->synth = synth; 
1430 }
1431 PianoFreqFibonacci::~PianoFreqFibonacci()
1432 {
1433 }
1434
1435 int PianoFreqFibonacci::handle_event()
1436 {
1437         float last_value1 = 0, last_value2 = 1;
1438         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1439         {
1440                 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1441                 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
1442                 last_value1 = last_value2;
1443                 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1444         }
1445
1446         synth->thread->window->update_gui();
1447         synth->send_configure_change();
1448 }
1449
1450 PianoFreqPrime::PianoFreqPrime(Piano *synth)
1451  : BC_MenuItem(_("Prime"))
1452
1453         this->synth = synth; 
1454 }
1455 PianoFreqPrime::~PianoFreqPrime()
1456 {
1457 }
1458
1459 int PianoFreqPrime::handle_event()
1460 {
1461         float number = 1;
1462         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1463         {
1464                 synth->config.oscillator_config.values[i]->freq_factor = number;
1465                 number = get_next_prime(number);
1466         }
1467
1468         synth->thread->window->update_gui();
1469         synth->send_configure_change();
1470 }
1471
1472 float PianoFreqPrime::get_next_prime(float number)
1473 {
1474         int result = 1;
1475         
1476         while(result)
1477         {
1478                 result = 0;
1479                 number++;
1480                 
1481                 for(float i = number - 1; i > 1 && !result; i--)
1482                 {
1483                         if((number / i) - (int)(number / i) == 0) result = 1;
1484                 }
1485         }
1486         
1487         return number;
1488 }
1489
1490
1491
1492
1493
1494
1495
1496
1497 PianoOscillatorConfig::PianoOscillatorConfig(int number)
1498 {
1499         reset();
1500         this->number = number;
1501 }
1502
1503 PianoOscillatorConfig::~PianoOscillatorConfig()
1504 {
1505 }
1506
1507 void PianoOscillatorConfig::reset()
1508 {
1509         level = 0;
1510         phase = 0;
1511         freq_factor = 1;
1512 }
1513
1514 void PianoOscillatorConfig::read_data(FileXML *file)
1515 {
1516         level = file->tag.get_property("LEVEL", (float)level);
1517         phase = file->tag.get_property("PHASE", (float)phase);
1518         freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
1519 }
1520
1521 void PianoOscillatorConfig::save_data(FileXML *file)
1522 {
1523         file->tag.set_title("OSCILLATOR");
1524         file->tag.set_property("LEVEL", (float)level);
1525         file->tag.set_property("PHASE", (float)phase);
1526         file->tag.set_property("FREQFACTOR", (float)freq_factor);
1527         file->append_tag();
1528         file->append_newline();
1529 }
1530
1531 int PianoOscillatorConfig::equivalent(PianoOscillatorConfig &that)
1532 {
1533         if(EQUIV(level, that.level) && 
1534                 EQUIV(phase, that.phase) &&
1535                 EQUIV(freq_factor, that.freq_factor))
1536                 return 1;
1537         else
1538                 return 0;
1539 }
1540
1541 void PianoOscillatorConfig::copy_from(PianoOscillatorConfig& that)
1542 {
1543         level = that.level;
1544         phase = that.phase;
1545         freq_factor = that.freq_factor;
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 PianoConfig::PianoConfig()
1560 {
1561         reset();
1562 }
1563
1564 PianoConfig::~PianoConfig()
1565 {
1566         oscillator_config.remove_all_objects();
1567 }
1568
1569 void PianoConfig::reset()
1570 {
1571         wetness = 0;
1572         base_freq = 440;
1573         wavefunction = SINE;
1574         for(int i = 0; i < oscillator_config.total; i++)
1575         {
1576                 oscillator_config.values[i]->reset();
1577         }
1578 }
1579
1580 int PianoConfig::equivalent(PianoConfig &that)
1581 {
1582 //printf("PianoConfig::equivalent %d %d\n", base_freq, that.base_freq);
1583         if(base_freq != that.base_freq ||
1584                 wavefunction != that.wavefunction ||
1585                 oscillator_config.total != that.oscillator_config.total) return 0;
1586
1587         for(int i = 0; i < oscillator_config.total; i++)
1588         {
1589                 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
1590                         return 0;
1591         }
1592
1593         return 1;
1594 }
1595
1596 void PianoConfig::copy_from(PianoConfig& that)
1597 {
1598         wetness = that.wetness;
1599         base_freq = that.base_freq;
1600         wavefunction = that.wavefunction;
1601
1602         int i;
1603         for(i = 0; 
1604                 i < oscillator_config.total && i < that.oscillator_config.total;
1605                 i++)
1606         {
1607                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1608         }
1609
1610         for( ;
1611                 i < that.oscillator_config.total;
1612                 i++)
1613         {
1614                 oscillator_config.append(new PianoOscillatorConfig(i));
1615                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1616         }
1617
1618         for( ;
1619                 i < oscillator_config.total;
1620                 i++)
1621         {
1622                 oscillator_config.remove_object();
1623         }
1624 }
1625
1626 void PianoConfig::interpolate(PianoConfig &prev, 
1627         PianoConfig &next, 
1628         int64_t prev_frame, 
1629         int64_t next_frame, 
1630         int64_t current_frame)
1631 {
1632         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
1633         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
1634
1635         copy_from(prev);
1636         wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
1637         base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);
1638 }
1639
1640
1641
1642
1643