add BC_SCALE env var for hi def monitors, cleanup theme data
[goodguy/cinelerra.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->xbuf);
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->xbuf);
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() - xS(125),
468                 info.get_abs_cursor_y() - yS(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, x, y, xS(380), synth->h,
488         xS(380), yS(10), 1, 0, 1)
489 {
490         this->synth = synth;
491 }
492
493 PianoWindow::~PianoWindow()
494 {
495 }
496
497 int PianoWindow::create_objects()
498 {
499         BC_MenuBar *menu;
500         add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
501
502         BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
503         menu->add_menu(levelmenu = new BC_Menu(_("Level")));
504         menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
505         menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
506
507         levelmenu->add_item(new PianoLevelInvert(synth));
508         levelmenu->add_item(new PianoLevelMax(synth));
509         levelmenu->add_item(new PianoLevelRandom(synth));
510         levelmenu->add_item(new PianoLevelSine(synth));
511         levelmenu->add_item(new PianoLevelSlope(synth));
512         levelmenu->add_item(new PianoLevelZero(synth));
513
514         phasemenu->add_item(new PianoPhaseInvert(synth));
515         phasemenu->add_item(new PianoPhaseRandom(synth));
516         phasemenu->add_item(new PianoPhaseSine(synth));
517         phasemenu->add_item(new PianoPhaseZero(synth));
518
519         harmonicmenu->add_item(new PianoFreqEnum(synth));
520         harmonicmenu->add_item(new PianoFreqEven(synth));
521         harmonicmenu->add_item(new PianoFreqFibonacci(synth));
522         harmonicmenu->add_item(new PianoFreqOdd(synth));
523         harmonicmenu->add_item(new PianoFreqPrime(synth));
524
525         int xs10 = xS(10), xs240 = xS(240);
526         int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys35 = yS(35);
527         int x = xs10, y = ys30, i;
528         add_subwindow(new BC_Title(x, y, _("Waveform")));
529         x += xs240;
530         add_subwindow(new BC_Title(x, y, _("Wave Function")));
531         y += ys20;
532         x = xs10;
533         add_subwindow(canvas = new PianoCanvas(synth, this, x, y, xS(230), yS(160)));
534         canvas->update();
535
536         x += xS(240);
537         char string[BCTEXTLEN];
538         waveform_to_text(string, synth->config.wavefunction);
539
540         add_subwindow(waveform = new PianoWaveForm(synth, x, y, string));
541         waveform->create_objects();
542         y += ys30;
543
544
545         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
546         y += ys30;
547         add_subwindow(base_freq = new PianoBaseFreq(synth, x, y));
548         x += xs80;
549         add_subwindow(freqpot = new PianoFreqPot(synth, this, x, y - ys10));
550         base_freq->freq_pot = freqpot;
551         freqpot->freq_text = base_freq;
552         x -= xs80;
553         y += ys40;
554         add_subwindow(new BC_Title(x, y, _("Wetness:")));
555         add_subwindow(wetness = new PianoWetness(synth, x + xs70, y - ys10));
556
557         y += ys40;
558         add_subwindow(new PianoClear(synth, x, y));
559
560
561         x = xs50;
562         y = yS(220);
563         add_subwindow(new BC_Title(x, y, _("Level")));
564         x += xs75;
565         add_subwindow(new BC_Title(x, y, _("Phase")));
566         x += xs75;
567         add_subwindow(new BC_Title(x, y, _("Harmonic")));
568
569
570
571         y += ys20; x = xs10;
572         add_subwindow(subwindow = new PianoSubWindow(synth, x, y, xS(265), get_h() - y));
573         x += xS(265);
574         add_subwindow(scroll = new PianoScroll(synth, this, x, y, get_h() - y));
575
576
577         x += xs20;
578         add_subwindow(new PianoAddOsc(synth, this, x, y));
579         y += ys30;
580         add_subwindow(new PianoDelOsc(synth, this, x, y));
581
582         update_scrollbar();
583         update_oscillators();
584
585         show_window();
586         flush();
587         return 0;
588 }
589
590 int PianoWindow::close_event()
591 {
592 // Set result to 1 to indicate a client side close
593         set_done(1);
594         return 1;
595 }
596
597 int PianoWindow::resize_event(int w, int h)
598 {
599         clear_box(0, 0, w, h);
600         subwindow->reposition_window(subwindow->get_x(),
601                 subwindow->get_y(),
602                 subwindow->get_w(),
603                 h - subwindow->get_y());
604         subwindow->clear_box(0, 0, subwindow->get_w(), subwindow->get_h());
605         scroll->reposition_window(scroll->get_x(),
606                 scroll->get_y(),
607                 h - scroll->get_y());
608         update_scrollbar();
609         update_oscillators();
610         synth->w = w;
611         synth->h = h;
612         return 1;
613 }
614
615 void PianoWindow::update_gui()
616 {
617         char string[BCTEXTLEN];
618         freqpot->update(synth->config.base_freq);
619         base_freq->update((int64_t)synth->config.base_freq);
620         wetness->update(synth->config.wetness);
621         waveform_to_text(string, synth->config.wavefunction);
622         waveform->set_text(string);
623
624         update_scrollbar();
625         update_oscillators();
626         canvas->update();
627 }
628
629 void PianoWindow::update_scrollbar()
630 {
631         scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT,
632                 scroll->get_position(),
633                 subwindow->get_h());
634 }
635
636 void PianoWindow::update_oscillators()
637 {
638         int i, y = -scroll->get_position();
639
640
641
642 // Add new oscillators
643         for(i = 0;
644                 i < synth->config.oscillator_config.total;
645                 i++)
646         {
647                 PianoOscGUI *gui;
648                 PianoOscillatorConfig *config = synth->config.oscillator_config.values[i];
649
650                 if(oscillators.total <= i)
651                 {
652                         oscillators.append(gui = new PianoOscGUI(this, i));
653                         gui->create_objects(y);
654                 }
655                 else
656                 {
657                         gui = oscillators.values[i];
658
659                         gui->title->reposition_window(gui->title->get_x(), y + yS(15));
660
661                         gui->level->reposition_window(gui->level->get_x(), y);
662                         gui->level->update(config->level);
663
664                         gui->phase->reposition_window(gui->phase->get_x(), y);
665                         gui->phase->update((int64_t)(config->phase * 360));
666
667                         gui->freq->reposition_window(gui->freq->get_x(), y);
668                         gui->freq->update((int64_t)(config->freq_factor));
669                 }
670                 y += OSCILLATORHEIGHT;
671         }
672
673 // Delete old oscillators
674         for( ;
675                 i < oscillators.total;
676                 i++)
677                 oscillators.remove_object();
678 }
679
680
681 int PianoWindow::waveform_to_text(char *text, int waveform)
682 {
683         switch(waveform)
684         {
685                 case DC:              sprintf(text, _("DC"));           break;
686                 case SINE:            sprintf(text, _("Sine"));           break;
687                 case SAWTOOTH:        sprintf(text, _("Sawtooth"));       break;
688                 case SQUARE:          sprintf(text, _("Square"));         break;
689                 case TRIANGLE:        sprintf(text, _("Triangle"));       break;
690                 case PULSE:           sprintf(text, _("Pulse"));       break;
691                 case NOISE:           sprintf(text, _("Noise"));       break;
692         }
693         return 0;
694 }
695
696
697
698
699
700
701
702 PianoOscGUI::PianoOscGUI(PianoWindow *window, int number)
703 {
704         this->window = window;
705         this->number = number;
706 }
707
708 PianoOscGUI::~PianoOscGUI()
709 {
710         delete title;
711         delete level;
712         delete phase;
713         delete freq;
714 }
715
716 int PianoOscGUI::create_objects(int y)
717 {
718         char text[BCTEXTLEN];
719         sprintf(text, "%d:", number + 1);
720         window->subwindow->add_subwindow(title = new BC_Title(xs10, y + ys15, text));
721
722         window->subwindow->add_subwindow(level = new PianoOscGUILevel(window->synth, this, y));
723         window->subwindow->add_subwindow(phase = new PianoOscGUIPhase(window->synth, this, y));
724         window->subwindow->add_subwindow(freq = new PianoOscGUIFreq(window->synth, this, y));
725         return 1;
726 }
727
728
729
730
731 PianoOscGUILevel::PianoOscGUILevel(Piano *synth, PianoOscGUI *gui, int y)
732  : BC_FPot(xS(50),
733         y,
734         synth->config.oscillator_config.values[gui->number]->level,
735         INFINITYGAIN,
736         0)
737 {
738         this->synth = synth;
739         this->gui = gui;
740 }
741
742 PianoOscGUILevel::~PianoOscGUILevel()
743 {
744 }
745
746 int PianoOscGUILevel::handle_event()
747 {
748         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
749         config->level = get_value();
750         gui->window->canvas->update();
751         synth->send_configure_change();
752         return 1;
753 }
754
755
756
757 PianoOscGUIPhase::PianoOscGUIPhase(Piano *synth, PianoOscGUI *gui, int y)
758  : BC_IPot(xS(125),
759         y,
760         (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360),
761         0,
762         xS(360))
763 {
764         this->synth = synth;
765         this->gui = gui;
766 }
767
768 PianoOscGUIPhase::~PianoOscGUIPhase()
769 {
770 }
771
772 int PianoOscGUIPhase::handle_event()
773 {
774         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
775         config->phase = (float)get_value() / 360;
776         gui->window->canvas->update();
777         synth->send_configure_change();
778         return 1;
779 }
780
781
782
783 PianoOscGUIFreq::PianoOscGUIFreq(Piano *synth, PianoOscGUI *gui, int y)
784  : BC_IPot(xS(200),
785         y,
786         (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor),
787         yS(1),
788         xS(100))
789 {
790         this->synth = synth;
791         this->gui = gui;
792 }
793
794 PianoOscGUIFreq::~PianoOscGUIFreq()
795 {
796 }
797
798 int PianoOscGUIFreq::handle_event()
799 {
800         PianoOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
801         config->freq_factor = get_value();
802         gui->window->canvas->update();
803         synth->send_configure_change();
804         return 1;
805 }
806
807
808
809
810
811
812
813 PianoAddOsc::PianoAddOsc(Piano *synth, PianoWindow *window, int x, int y)
814  : BC_GenericButton(x, y, _("Add"))
815 {
816         this->synth = synth;
817         this->window = window;
818 }
819
820 PianoAddOsc::~PianoAddOsc()
821 {
822 }
823
824 int PianoAddOsc::handle_event()
825 {
826         synth->add_oscillator();
827         synth->send_configure_change();
828         window->update_gui();
829         return 1;
830 }
831
832
833
834 PianoDelOsc::PianoDelOsc(Piano *synth, PianoWindow *window, int x, int y)
835  : BC_GenericButton(x, y, _("Delete"))
836 {
837         this->synth = synth;
838         this->window = window;
839 }
840
841 PianoDelOsc::~PianoDelOsc()
842 {
843 }
844
845 int PianoDelOsc::handle_event()
846 {
847         synth->delete_oscillator();
848         synth->send_configure_change();
849         window->update_gui();
850         return 1;
851 }
852
853
854 PianoScroll::PianoScroll(Piano *synth,
855         PianoWindow *window,
856         int x,
857         int y,
858         int h)
859  : BC_ScrollBar(x,
860         y,
861         SCROLL_VERT,
862         h,
863         synth->config.oscillator_config.total * OSCILLATORHEIGHT,
864         0,
865         window->subwindow->get_h())
866 {
867         this->synth = synth;
868         this->window = window;
869 }
870
871 PianoScroll::~PianoScroll()
872 {
873 }
874
875 int PianoScroll::handle_event()
876 {
877         window->update_gui();
878         return 1;
879 }
880
881
882
883
884
885
886
887
888 PianoSubWindow::PianoSubWindow(Piano *synth, int x, int y, int w, int h)
889  : BC_SubWindow(x, y, w, h)
890 {
891         this->synth = synth;
892 }
893 PianoSubWindow::~PianoSubWindow()
894 {
895 }
896
897
898
899
900
901
902
903
904
905 PianoClear::PianoClear(Piano *synth, int x, int y)
906  : BC_GenericButton(x, y, _("Clear"))
907 {
908         this->synth = synth;
909 }
910 PianoClear::~PianoClear()
911 {
912 }
913 int PianoClear::handle_event()
914 {
915         synth->config.reset();
916         synth->send_configure_change();
917         synth->update_gui();
918         return 1;
919 }
920
921
922
923
924
925
926 PianoWaveForm::PianoWaveForm(Piano *synth, int x, int y, char *text)
927  : BC_PopupMenu(x, y, xS(120), text)
928 {
929         this->synth = synth;
930 }
931
932 PianoWaveForm::~PianoWaveForm()
933 {
934 }
935
936 int PianoWaveForm::create_objects()
937 {
938 //      add_item(new PianoWaveFormItem(synth, _("DC"), DC));
939         add_item(new PianoWaveFormItem(synth, _("Sine"), SINE));
940         add_item(new PianoWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
941         add_item(new PianoWaveFormItem(synth, _("Square"), SQUARE));
942         add_item(new PianoWaveFormItem(synth, _("Triangle"), TRIANGLE));
943         add_item(new PianoWaveFormItem(synth, _("Pulse"), PULSE));
944         add_item(new PianoWaveFormItem(synth, _("Noise"), NOISE));
945         return 0;
946 }
947
948 PianoWaveFormItem::PianoWaveFormItem(Piano *synth, char *text, int value)
949  : BC_MenuItem(text)
950 {
951         this->synth = synth;
952         this->value = value;
953 }
954
955 PianoWaveFormItem::~PianoWaveFormItem()
956 {
957 }
958
959 int PianoWaveFormItem::handle_event()
960 {
961         synth->config.wavefunction = value;
962         synth->thread->window->canvas->update();
963         synth->send_configure_change();
964         return 1;
965 }
966
967
968 PianoWetness::PianoWetness(Piano *synth, int x, int y)
969  : BC_FPot(x,
970                 y,
971                 synth->config.wetness,
972                 INFINITYGAIN,
973                 0)
974 {
975         this->synth = synth;
976 }
977
978 int PianoWetness::handle_event()
979 {
980         synth->config.wetness = get_value();
981         synth->send_configure_change();
982         return 1;
983 }
984
985
986
987 PianoFreqPot::PianoFreqPot(Piano *synth, PianoWindow *window, int x, int y)
988  : BC_QPot(x, y, synth->config.base_freq)
989 {
990         this->synth = synth;
991 }
992 PianoFreqPot::~PianoFreqPot()
993 {
994 }
995 int PianoFreqPot::handle_event()
996 {
997         if(get_value() > 0 && get_value() < 30000)
998         {
999                 synth->config.base_freq = get_value();
1000                 freq_text->update(get_value());
1001                 synth->send_configure_change();
1002         }
1003         return 1;
1004 }
1005
1006
1007
1008 PianoBaseFreq::PianoBaseFreq(Piano *synth, int x, int y)
1009  : BC_TextBox(x, y, xS(70), 1, (int)synth->config.base_freq)
1010 {
1011         this->synth = synth;
1012 }
1013 PianoBaseFreq::~PianoBaseFreq()
1014 {
1015 }
1016 int PianoBaseFreq::handle_event()
1017 {
1018         int new_value = atol(get_text());
1019
1020         if(new_value > 0 && new_value < 30000)
1021         {
1022                 synth->config.base_freq = new_value;
1023                 freq_pot->update(synth->config.base_freq);
1024                 synth->send_configure_change();
1025         }
1026         return 1;
1027 }
1028
1029
1030
1031
1032
1033 PianoCanvas::PianoCanvas(Piano *synth,
1034         PianoWindow *window,
1035         int x,
1036         int y,
1037         int w,
1038         int h)
1039  : BC_SubWindow(x,
1040         y,
1041         w,
1042         h,
1043         BLACK)
1044 {
1045         this->synth = synth;
1046         this->window = window;
1047 }
1048
1049 PianoCanvas::~PianoCanvas()
1050 {
1051 }
1052
1053 int PianoCanvas::update()
1054 {
1055         int y1, y2, y = 0;
1056
1057         clear_box(0, 0, get_w(), get_h());
1058         set_color(RED);
1059
1060         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1061
1062         set_color(GREEN);
1063
1064         double normalize_constant = (double)1 / synth->get_total_power();
1065         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1066
1067         for(int i = 1; i < get_w(); i++)
1068         {
1069                 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1070                 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1071                 y1 = y2;
1072         }
1073         flash();
1074         return 0;
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084 // ======================= level calculations
1085 PianoLevelZero::PianoLevelZero(Piano *synth)
1086  : BC_MenuItem(_("Zero"))
1087 {
1088         this->synth = synth;
1089 }
1090
1091 PianoLevelZero::~PianoLevelZero()
1092 {
1093 }
1094
1095 int PianoLevelZero::handle_event()
1096 {
1097         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1098         {
1099                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1100         }
1101
1102         synth->thread->window->update_gui();
1103         synth->send_configure_change();
1104 }
1105
1106 PianoLevelMax::PianoLevelMax(Piano *synth)
1107  : BC_MenuItem(_("Maximum"))
1108 {
1109         this->synth = synth;
1110 }
1111
1112 PianoLevelMax::~PianoLevelMax()
1113 {
1114 }
1115
1116 int PianoLevelMax::handle_event()
1117 {
1118         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1119         {
1120                 synth->config.oscillator_config.values[i]->level = 0;
1121         }
1122         synth->thread->window->update_gui();
1123         synth->send_configure_change();
1124 }
1125
1126 PianoLevelNormalize::PianoLevelNormalize(Piano *synth)
1127  : BC_MenuItem(_("Normalize"))
1128 {
1129         this->synth = synth;
1130 }
1131
1132 PianoLevelNormalize::~PianoLevelNormalize()
1133 {
1134 }
1135
1136 int PianoLevelNormalize::handle_event()
1137 {
1138 // get total power
1139         float total = 0;
1140
1141         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1142         {
1143                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1144         }
1145
1146         float scale = 1 / total;
1147         float new_value;
1148
1149         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1150         {
1151                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1152                 new_value *= scale;
1153                 new_value = synth->db.todb(new_value);
1154
1155                 synth->config.oscillator_config.values[i]->level = new_value;
1156         }
1157
1158         synth->thread->window->update_gui();
1159         synth->send_configure_change();
1160 }
1161
1162 PianoLevelSlope::PianoLevelSlope(Piano *synth)
1163  : BC_MenuItem(_("Slope"))
1164 {
1165         this->synth = synth;
1166 }
1167
1168 PianoLevelSlope::~PianoLevelSlope()
1169 {
1170 }
1171
1172 int PianoLevelSlope::handle_event()
1173 {
1174         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1175
1176         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1177         {
1178                 synth->config.oscillator_config.values[i]->level = i * slope;
1179         }
1180
1181         synth->thread->window->update_gui();
1182         synth->send_configure_change();
1183 }
1184
1185 PianoLevelRandom::PianoLevelRandom(Piano *synth)
1186  : BC_MenuItem(_("Random"))
1187 {
1188         this->synth = synth;
1189 }
1190 PianoLevelRandom::~PianoLevelRandom()
1191 {
1192 }
1193
1194 int PianoLevelRandom::handle_event()
1195 {
1196         srand(time(0));
1197         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1198         {
1199                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1200         }
1201
1202         synth->thread->window->update_gui();
1203         synth->send_configure_change();
1204 }
1205
1206 PianoLevelInvert::PianoLevelInvert(Piano *synth)
1207  : BC_MenuItem(_("Invert"))
1208 {
1209         this->synth = synth;
1210 }
1211 PianoLevelInvert::~PianoLevelInvert()
1212 {
1213 }
1214
1215 int PianoLevelInvert::handle_event()
1216 {
1217         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1218         {
1219                 synth->config.oscillator_config.values[i]->level =
1220                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1221         }
1222
1223         synth->thread->window->update_gui();
1224         synth->send_configure_change();
1225 }
1226
1227 PianoLevelSine::PianoLevelSine(Piano *synth)
1228  : BC_MenuItem(_("Sine"))
1229 {
1230         this->synth = synth;
1231 }
1232 PianoLevelSine::~PianoLevelSine()
1233 {
1234 }
1235
1236 int PianoLevelSine::handle_event()
1237 {
1238         float new_value;
1239
1240         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1241         {
1242                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1243                 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1244                 synth->config.oscillator_config.values[i]->level = new_value;
1245         }
1246
1247         synth->thread->window->update_gui();
1248         synth->send_configure_change();
1249 }
1250
1251 // ============================ phase calculations
1252
1253 PianoPhaseInvert::PianoPhaseInvert(Piano *synth)
1254  : BC_MenuItem(_("Invert"))
1255 {
1256         this->synth = synth;
1257 }
1258 PianoPhaseInvert::~PianoPhaseInvert()
1259 {
1260 }
1261
1262 int PianoPhaseInvert::handle_event()
1263 {
1264         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1265         {
1266                 synth->config.oscillator_config.values[i]->phase =
1267                         1 - synth->config.oscillator_config.values[i]->phase;
1268         }
1269
1270         synth->thread->window->update_gui();
1271         synth->send_configure_change();
1272 }
1273
1274 PianoPhaseZero::PianoPhaseZero(Piano *synth)
1275  : BC_MenuItem(_("Zero"))
1276 {
1277         this->synth = synth;
1278 }
1279 PianoPhaseZero::~PianoPhaseZero()
1280 {
1281 }
1282
1283 int PianoPhaseZero::handle_event()
1284 {
1285         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1286         {
1287                 synth->config.oscillator_config.values[i]->phase = 0;
1288         }
1289
1290         synth->thread->window->update_gui();
1291         synth->send_configure_change();
1292 }
1293
1294 PianoPhaseSine::PianoPhaseSine(Piano *synth)
1295  : BC_MenuItem(_("Sine"))
1296 {
1297         this->synth = synth;
1298 }
1299 PianoPhaseSine::~PianoPhaseSine()
1300 {
1301 }
1302
1303 int PianoPhaseSine::handle_event()
1304 {
1305         float new_value;
1306         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1307         {
1308                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1309                 new_value = sin(new_value) / 2 + .5;
1310                 synth->config.oscillator_config.values[i]->phase = new_value;
1311         }
1312
1313         synth->thread->window->update_gui();
1314         synth->send_configure_change();
1315 }
1316
1317 PianoPhaseRandom::PianoPhaseRandom(Piano *synth)
1318  : BC_MenuItem(_("Random"))
1319 {
1320         this->synth = synth;
1321 }
1322 PianoPhaseRandom::~PianoPhaseRandom()
1323 {
1324 }
1325
1326 int PianoPhaseRandom::handle_event()
1327 {
1328         srand(time(0));
1329         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1330         {
1331                 synth->config.oscillator_config.values[i]->phase =
1332                         (float)(rand() % 360) / 360;
1333         }
1334
1335         synth->thread->window->update_gui();
1336         synth->send_configure_change();
1337 }
1338
1339
1340 // ============================ freq calculations
1341
1342 PianoFreqRandom::PianoFreqRandom(Piano *synth)
1343  : BC_MenuItem(_("Random"))
1344 {
1345         this->synth = synth;
1346 }
1347 PianoFreqRandom::~PianoFreqRandom()
1348 {
1349 }
1350
1351 int PianoFreqRandom::handle_event()
1352 {
1353         srand(time(0));
1354         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1355         {
1356                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1357         }
1358
1359         synth->thread->window->update_gui();
1360         synth->send_configure_change();
1361 }
1362
1363 PianoFreqEnum::PianoFreqEnum(Piano *synth)
1364  : BC_MenuItem(_("Enumerate"))
1365 {
1366         this->synth = synth;
1367 }
1368 PianoFreqEnum::~PianoFreqEnum()
1369 {
1370 }
1371
1372 int PianoFreqEnum::handle_event()
1373 {
1374         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1375         {
1376                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1377         }
1378
1379         synth->thread->window->update_gui();
1380         synth->send_configure_change();
1381 }
1382
1383 PianoFreqEven::PianoFreqEven(Piano *synth)
1384  : BC_MenuItem(_("Even"))
1385 {
1386         this->synth = synth;
1387 }
1388 PianoFreqEven::~PianoFreqEven()
1389 {
1390 }
1391
1392 int PianoFreqEven::handle_event()
1393 {
1394         if(synth->config.oscillator_config.total)
1395                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1396
1397         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1398         {
1399                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1400         }
1401
1402         synth->thread->window->update_gui();
1403         synth->send_configure_change();
1404 }
1405
1406 PianoFreqOdd::PianoFreqOdd(Piano *synth)
1407  : BC_MenuItem(_("Odd"))
1408 { this->synth = synth; }
1409 PianoFreqOdd::~PianoFreqOdd()
1410 {
1411 }
1412
1413 int PianoFreqOdd::handle_event()
1414 {
1415         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1416         {
1417                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1418         }
1419
1420         synth->thread->window->update_gui();
1421         synth->send_configure_change();
1422 }
1423
1424 PianoFreqFibonacci::PianoFreqFibonacci(Piano *synth)
1425  : BC_MenuItem(_("Fibonnacci"))
1426 {
1427         this->synth = synth;
1428 }
1429 PianoFreqFibonacci::~PianoFreqFibonacci()
1430 {
1431 }
1432
1433 int PianoFreqFibonacci::handle_event()
1434 {
1435         float last_value1 = 0, last_value2 = 1;
1436         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1437         {
1438                 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1439                 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
1440                 last_value1 = last_value2;
1441                 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1442         }
1443
1444         synth->thread->window->update_gui();
1445         synth->send_configure_change();
1446 }
1447
1448 PianoFreqPrime::PianoFreqPrime(Piano *synth)
1449  : BC_MenuItem(_("Prime"))
1450 {
1451         this->synth = synth;
1452 }
1453 PianoFreqPrime::~PianoFreqPrime()
1454 {
1455 }
1456
1457 int PianoFreqPrime::handle_event()
1458 {
1459         float number = 1;
1460         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1461         {
1462                 synth->config.oscillator_config.values[i]->freq_factor = number;
1463                 number = get_next_prime(number);
1464         }
1465
1466         synth->thread->window->update_gui();
1467         synth->send_configure_change();
1468 }
1469
1470 float PianoFreqPrime::get_next_prime(float number)
1471 {
1472         int result = 1;
1473
1474         while(result)
1475         {
1476                 result = 0;
1477                 number++;
1478
1479                 for(float i = number - 1; i > 1 && !result; i--)
1480                 {
1481                         if((number / i) - (int)(number / i) == 0) result = 1;
1482                 }
1483         }
1484
1485         return number;
1486 }
1487
1488
1489
1490
1491
1492
1493
1494
1495 PianoOscillatorConfig::PianoOscillatorConfig(int number)
1496 {
1497         reset();
1498         this->number = number;
1499 }
1500
1501 PianoOscillatorConfig::~PianoOscillatorConfig()
1502 {
1503 }
1504
1505 void PianoOscillatorConfig::reset()
1506 {
1507         level = 0;
1508         phase = 0;
1509         freq_factor = 1;
1510 }
1511
1512 void PianoOscillatorConfig::read_data(FileXML *file)
1513 {
1514         level = file->tag.get_property("LEVEL", (float)level);
1515         phase = file->tag.get_property("PHASE", (float)phase);
1516         freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
1517 }
1518
1519 void PianoOscillatorConfig::save_data(FileXML *file)
1520 {
1521         file->tag.set_title("OSCILLATOR");
1522         file->tag.set_property("LEVEL", (float)level);
1523         file->tag.set_property("PHASE", (float)phase);
1524         file->tag.set_property("FREQFACTOR", (float)freq_factor);
1525         file->append_tag();
1526         file->tag.set_title("/OSCILLATOR");
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