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