r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / plugins / synthesizer / synthesizer.C
blobdac2878b7549a76d3be0d6e98142863179ba8020
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "picon_png.h"
6 #include "synthesizer.h"
7 #include "vframe.h"
9 #include <string.h>
12 #include <libintl.h>
13 #define _(String) gettext(String)
14 #define gettext_noop(String) String
15 #define N_(String) gettext_noop (String)
19 PluginClient* new_plugin(PluginServer *server)
21         return new Synth(server);
28 Synth::Synth(PluginServer *server)
29  : PluginAClient(server)
31         reset();
32         load_defaults();
37 Synth::~Synth()
39         if(thread)
40         {
41                 thread->window->set_done(0);
42                 thread->completion.lock();
43                 delete thread;
44         }
46         save_defaults();
47         delete defaults;
48         
49         if(dsp_buffer) delete [] dsp_buffer;
52 VFrame* Synth::new_picon()
54         return new VFrame(picon_png);
58 char* Synth::plugin_title() { return N_("Synthesizer"); }
59 int Synth::is_realtime() { return 1; }
60 int Synth::is_synthesis() { return 1; }
63 void Synth::reset()
65         thread = 0;
66         need_reconfigure = 1;
67         dsp_buffer = 0;
73 LOAD_CONFIGURATION_MACRO(Synth, SynthConfig)
78 int Synth::load_defaults()
80         char directory[BCTEXTLEN], string[BCTEXTLEN];
82         sprintf(directory, "%ssynthesizer.rc", BCASTDIR);
83         defaults = new Defaults(directory);
84         defaults->load();
85         w = defaults->get("WIDTH", 380);
86         h = defaults->get("HEIGHT", 400);
88         config.wetness = defaults->get("WETNESS", 0);
89         config.base_freq = defaults->get("BASEFREQ", 440);
90         config.wavefunction = defaults->get("WAVEFUNCTION", 0);
92         int total_oscillators = defaults->get("OSCILLATORS", TOTALOSCILLATORS);
93         config.oscillator_config.remove_all_objects();
94         for(int i = 0; i < total_oscillators; i++)
95         {
96                 config.oscillator_config.append(new SynthOscillatorConfig(i));
97                 config.oscillator_config.values[i]->load_defaults(defaults);
98         }
100         return 0;
104 void Synth::read_data(KeyFrame *keyframe)
106         FileXML input;
107 // cause htal file to read directly from text
108         input.set_shared_string(keyframe->data, strlen(keyframe->data));
110 //printf("Synth::read_data %s\n", keyframe->data);
111         int result = 0, current_osc = 0, total_oscillators = 0;
112         while(!result)
113         {
114                 result = input.read_tag();
116                 if(!result)
117                 {
118                         if(input.tag.title_is("SYNTH"))
119                         {
120                                 config.wetness = input.tag.get_property("WETNESS", config.wetness);
121                                 config.base_freq = input.tag.get_property("BASEFREQ", config.base_freq);
122                                 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
123                                 total_oscillators = input.tag.get_property("OSCILLATORS", 0);
124                         }
125                         else
126                         if(input.tag.title_is("OSCILLATOR"))
127                         {
128                                 if(current_osc >= config.oscillator_config.total)
129                                         config.oscillator_config.append(new SynthOscillatorConfig(current_osc));
131                                 config.oscillator_config.values[current_osc]->read_data(&input);
132                                 current_osc++;
133                         }
134                 }
135         }
137         while(config.oscillator_config.total > current_osc)
138                 config.oscillator_config.remove_object();
141 void Synth::save_data(KeyFrame *keyframe)
143         FileXML output;
144 // cause htal file to store data directly in text
145         output.set_shared_string(keyframe->data, MESSAGESIZE);
147         output.tag.set_title("SYNTH");
148         output.tag.set_property("WETNESS", config.wetness);
149         output.tag.set_property("BASEFREQ", config.base_freq);
150         output.tag.set_property("WAVEFUNCTION", config.wavefunction);
151         output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
152         output.append_tag();
153         output.append_newline();
155         for(int i = 0; i < config.oscillator_config.total; i++)
156         {
157                 config.oscillator_config.values[i]->save_data(&output);
158         }
160         output.terminate_string();
161 // data is now in *text
164 int Synth::save_defaults()
166         char string[BCTEXTLEN];
168         defaults->update("WIDTH", w);
169         defaults->update("HEIGHT", h);
170         defaults->update("WETNESS", config.wetness);
171         defaults->update("BASEFREQ", config.base_freq);
172         defaults->update("WAVEFUNCTION", config.wavefunction);
173         defaults->update("OSCILLATORS", config.oscillator_config.total);
175         for(int i = 0; i < config.oscillator_config.total; i++)
176         {
177                 config.oscillator_config.values[i]->save_defaults(defaults);
178         }
179         defaults->save();
181         return 0;
184 int Synth::show_gui()
186         load_configuration();
187         
188         thread = new SynthThread(this);
189         thread->start();
190         return 0;
193 int Synth::set_string()
195         if(thread) thread->window->set_title(gui_string);
196         return 0;
199 void Synth::raise_window()
201         if(thread)
202         {
203                 thread->window->raise_window();
204                 thread->window->flush();
205         }
208 void Synth::update_gui()
210         if(thread)
211         {
212                 load_configuration();
213                 thread->window->lock_window();
214                 thread->window->update_gui();
215                 thread->window->unlock_window();
216         }
220 void Synth::add_oscillator()
222         if(config.oscillator_config.total > 20) return;
224         config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
227 void Synth::delete_oscillator()
229         if(config.oscillator_config.total)
230         {
231                 config.oscillator_config.remove_object();
232         }
236 double Synth::get_total_power()
238         double result = 0;
240         if(config.wavefunction == DC) return 1.0;
242         for(int i = 0; i < config.oscillator_config.total; i++)
243         {
244                 result += db.fromdb(config.oscillator_config.values[i]->level);
245         }
247         if(result == 0) result = 1;  // prevent division by 0
248         return result;
252 double Synth::solve_eqn(double *output, 
253         double x1, 
254         double x2, 
255         double normalize_constant,
256         int oscillator)
258         SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
259         if(config->level <= INFINITYGAIN) return 0;
261         double result;
262         register double x;
263         double power = this->db.fromdb(config->level) * normalize_constant;
264         double phase_offset = config->phase * this->period;
265         double x3 = x1 + phase_offset;
266         double x4 = x2 + phase_offset;
267         double period = this->period / config->freq_factor;
268         int sample;
270         switch(this->config.wavefunction)
271         {
272                 case DC:
273                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
274                         {
275                                 output[sample] += power;
276                         }
277                         break;
278                 case SINE:
279                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
280                         {
281                                 output[sample] += sin(x / period * 2 * M_PI) * power;
282                         }
283                         break;
284                 case SAWTOOTH:
285                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
286                         {
287                                 output[sample] += function_sawtooth(x / period) * power;
288                         }
289                         break;
290                 case SQUARE:
291                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
292                         {
293                                 output[sample] += function_square(x / period) * power;
294                         }
295                         break;
296                 case TRIANGLE:
297                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
298                         {
299                                 output[sample] += function_triangle(x / period) * power;
300                         }
301                         break;
302                 case PULSE:
303                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
304                         {
305                                 output[sample] += function_pulse(x / period) * power;
306                         }
307                         break;
308                 case NOISE:
309                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
310                         {
311                                 output[sample] += function_noise() * power;
312                         }
313                         break;
314         }
317 double Synth::get_point(float x, double normalize_constant)
319         double result = 0;
320         for(int i = 0; i < config.oscillator_config.total; i++)
321                 result += get_oscillator_point(x, normalize_constant, i);
323         return result;
326 double Synth::get_oscillator_point(float x, 
327                 double normalize_constant, 
328                 int oscillator)
330         SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
331         double power = db.fromdb(config->level) * normalize_constant;
332         switch(this->config.wavefunction)
333         {
334                 case DC:
335                         return power;
336                         break;
337                 case SINE:
338                         return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
339                         break;
340                 case SAWTOOTH:
341                         return function_sawtooth((x + config->phase) * config->freq_factor) * power;
342                         break;
343                 case SQUARE:
344                         return function_square((x + config->phase) * config->freq_factor) * power;
345                         break;
346                 case TRIANGLE:
347                         return function_triangle((x + config->phase) * config->freq_factor) * power;
348                         break;
349                 case PULSE:
350                         return function_pulse((x + config->phase) * config->freq_factor) * power;
351                         break;
352                 case NOISE:
353                         return function_noise() * power;
354                         break;
355         }
358 double Synth::function_square(double x)
360         x -= (int)x; // only fraction counts
361         return (x < .5) ? -1 : 1;
364 double Synth::function_pulse(double x)
366         x -= (int)x; // only fraction counts
367         return (x < .5) ? 0 : 1;
370 double Synth::function_noise()
372         return (double)(rand() % 65536 - 32768) / 32768;
375 double Synth::function_sawtooth(double x)
377         x -= (int)x;
378         return 1 - x * 2;
381 double Synth::function_triangle(double x)
383         x -= (int)x;
384         return (x < .5) ? 1 - x * 4 : -3 + x * 4;
387 int Synth::process_realtime(int64_t size, double *input_ptr, double *output_ptr)
391         need_reconfigure |= load_configuration();
392         if(need_reconfigure) reconfigure();
394         double wetness = DB::fromdb(config.wetness);
395         if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
397         for(int j = 0; j < size; j++)
398                 output_ptr[j] = input_ptr[j] * wetness;
400         int64_t fragment_len;
401         for(int64_t i = 0; i < size; i += fragment_len)
402         {
403                 fragment_len = size;
404                 if(i + fragment_len > size) fragment_len = size - i;
406 //printf("Synth::process_realtime 1 %d %d %d\n", i, fragment_len, size);
407                 fragment_len = overlay_synth(i, fragment_len, input_ptr, output_ptr);
408 //printf("Synth::process_realtime 2\n");
409         }
410         
411         
412         return 0;
415 int Synth::overlay_synth(int64_t start, int64_t length, double *input, double *output)
417         if(waveform_sample + length > waveform_length) 
418                 length = waveform_length - waveform_sample;
420 //printf("Synth::overlay_synth 1 %d %d\n", length, waveform_length);
422 // calculate some more data
423 // only calculate what's needed to speed it up
424         if(waveform_sample + length > samples_rendered)
425         {
426                 int64_t start = waveform_sample, end = waveform_sample + length;
427                 for(int i = start; i < end; i++) dsp_buffer[i] = 0;
428                 
429                 double normalize_constant = 1 / get_total_power();
430                 for(int i = 0; i < config.oscillator_config.total; i++)
431                         solve_eqn(dsp_buffer, 
432                                 start, 
433                                 end, 
434                                 normalize_constant,
435                                 i);
437                 
438                 samples_rendered = end;
439         }
440 //printf("Synth::overlay_synth 2\n");
443         double *buffer_in = &input[start];
444         double *buffer_out = &output[start];
446         for(int i = 0; i < length; i++)
447         {
448                 buffer_out[i] += dsp_buffer[waveform_sample++];
449         }
450 //printf("Synth::overlay_synth 3\n");
452         if(waveform_sample >= waveform_length) waveform_sample = 0;
454         return length;
457 void Synth::reconfigure()
459         need_reconfigure = 0;
461         if(dsp_buffer)
462         {
463                 delete [] dsp_buffer;
464         }
466 //printf("Synth::reconfigure 1 %d\n", PluginAClient::project_sample_rate);
467         waveform_length = PluginAClient::project_sample_rate;
468         period = (float)PluginAClient::project_sample_rate / config.base_freq;
469         dsp_buffer = new double[waveform_length + 1];
471         samples_rendered = 0;     // do some calculations on the next process_realtime
472         waveform_sample = 0;
495 SynthThread::SynthThread(Synth *synth)
496  : Thread()
498         this->synth = synth;
499         set_synchronous(0);
500         completion.lock();
503 SynthThread::~SynthThread()
505         delete window;
508 void SynthThread::run()
510         BC_DisplayInfo info;
511         window = new SynthWindow(synth, 
512                 info.get_abs_cursor_x() - 125, 
513                 info.get_abs_cursor_y() - 115);
514         window->create_objects();
515         int result = window->run_window();
516         completion.unlock();
517 // Last command executed in thread
518         if(result) synth->client_side_close();
531 SynthWindow::SynthWindow(Synth *synth, int x, int y)
532  : BC_Window(synth->gui_string, 
533         x, 
534         y, 
535         380, 
536         synth->h, 
537         380, 
538         10, 
539         1, 
540         0,
541         1)
543         this->synth = synth; 
546 SynthWindow::~SynthWindow()
550 int SynthWindow::create_objects()
552         BC_MenuBar *menu;
553         add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
555         BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
556         menu->add_menu(levelmenu = new BC_Menu(_("Level")));
557         menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
558         menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
560         levelmenu->add_item(new SynthLevelInvert(synth));
561         levelmenu->add_item(new SynthLevelMax(synth));
562         levelmenu->add_item(new SynthLevelRandom(synth));
563         levelmenu->add_item(new SynthLevelSine(synth));
564         levelmenu->add_item(new SynthLevelSlope(synth));
565         levelmenu->add_item(new SynthLevelZero(synth));
567         phasemenu->add_item(new SynthPhaseInvert(synth));
568         phasemenu->add_item(new SynthPhaseRandom(synth));
569         phasemenu->add_item(new SynthPhaseSine(synth));
570         phasemenu->add_item(new SynthPhaseZero(synth));
572         harmonicmenu->add_item(new SynthFreqEnum(synth));
573         harmonicmenu->add_item(new SynthFreqEven(synth));
574         harmonicmenu->add_item(new SynthFreqFibonacci(synth));
575         harmonicmenu->add_item(new SynthFreqOdd(synth));
576         harmonicmenu->add_item(new SynthFreqPrime(synth));
578         int x = 10, y = 30, i;
579         add_subwindow(new BC_Title(x, y, _("Waveform")));
580         x += 240;
581         add_subwindow(new BC_Title(x, y, _("Wave Function")));
582         y += 20;
583         x = 10;
584         add_subwindow(canvas = new SynthCanvas(synth, this, x, y, 230, 160));
585         canvas->update();
587         x += 240;
588         char string[BCTEXTLEN];
589         waveform_to_text(string, synth->config.wavefunction);
591         add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
592         waveform->create_objects();
593         y += 30;
596         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
597         y += 30;
598         add_subwindow(base_freq = new SynthBaseFreq(synth, x, y));
599         x += 80;
600         add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - 10));
601         base_freq->freq_pot = freqpot;
602         freqpot->freq_text = base_freq;
603         x -= 80;
604         y += 40;
605         add_subwindow(new BC_Title(x, y, _("Wetness:")));
606         add_subwindow(wetness = new SynthWetness(synth, x + 70, y - 10));
608         y += 40;
609         add_subwindow(new SynthClear(synth, x, y));
612         x = 50;  
613         y = 220;
614         add_subwindow(new BC_Title(x, y, _("Level"))); 
615         x += 75;
616         add_subwindow(new BC_Title(x, y, _("Phase"))); 
617         x += 75;
618         add_subwindow(new BC_Title(x, y, _("Harmonic")));
622         y += 20; x = 10;
623         add_subwindow(subwindow = new SynthSubWindow(synth, x, y, 265, get_h() - y));
624         x += 265;
625         add_subwindow(scroll = new SynthScroll(synth, this, x, y, get_h() - y));
628         x += 20;
629         add_subwindow(new SynthAddOsc(synth, this, x, y));
630         y += 30;
631         add_subwindow(new SynthDelOsc(synth, this, x, y));
633         update_scrollbar();
634         update_oscillators();
636         show_window();
637         flush();
638         return 0;
641 int SynthWindow::close_event()
643 // Set result to 1 to indicate a client side close
644         set_done(1);
645         return 1;
648 int SynthWindow::resize_event(int w, int h)
650         clear_box(0, 0, w, h);
651         subwindow->reposition_window(subwindow->get_x(), 
652                 subwindow->get_y(), 
653                 subwindow->get_w(), 
654                 h - subwindow->get_y());
655         subwindow->clear_box(0, 0, subwindow->get_w(), subwindow->get_h());
656         scroll->reposition_window(scroll->get_x(), 
657                 scroll->get_y(), 
658                 h - scroll->get_y());
659         update_scrollbar();
660         update_oscillators();
661         synth->w = w;
662         synth->h = h;
663         return 1;
666 void SynthWindow::update_gui()
668         char string[BCTEXTLEN];
669         freqpot->update(synth->config.base_freq);
670         base_freq->update((int64_t)synth->config.base_freq);
671         wetness->update(synth->config.wetness);
672         waveform_to_text(string, synth->config.wavefunction);
673         waveform->set_text(string);
674         
675         update_scrollbar();
676         update_oscillators();
677         canvas->update();
680 void SynthWindow::update_scrollbar()
682         scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
683                 scroll->get_position(), 
684                 subwindow->get_h());
687 void SynthWindow::update_oscillators()
689         int i, y = -scroll->get_position();
693 // Add new oscillators
694         for(i = 0; 
695                 i < synth->config.oscillator_config.total; 
696                 i++)
697         {
698                 SynthOscGUI *gui;
699                 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
701                 if(oscillators.total <= i)
702                 {
703                         oscillators.append(gui = new SynthOscGUI(this, i));
704                         gui->create_objects(y);
705                 }
706                 else
707                 {
708                         gui = oscillators.values[i];
710                         gui->title->reposition_window(gui->title->get_x(), y + 15);
712                         gui->level->reposition_window(gui->level->get_x(), y);
713                         gui->level->update(config->level);
715                         gui->phase->reposition_window(gui->phase->get_x(), y);
716                         gui->phase->update((int64_t)(config->phase * 360));
718                         gui->freq->reposition_window(gui->freq->get_x(), y);
719                         gui->freq->update((int64_t)(config->freq_factor));
720                 }
721                 y += OSCILLATORHEIGHT;
722         }
724 // Delete old oscillators
725         for( ; 
726                 i < oscillators.total;
727                 i++)
728                 oscillators.remove_object();
732 int SynthWindow::waveform_to_text(char *text, int waveform)
734         switch(waveform)
735         {
736                 case DC:              sprintf(text, _("DC"));           break;
737                 case SINE:            sprintf(text, _("Sine"));           break;
738                 case SAWTOOTH:        sprintf(text, _("Sawtooth"));       break;
739                 case SQUARE:          sprintf(text, _("Square"));         break;
740                 case TRIANGLE:        sprintf(text, _("Triangle"));       break;
741                 case PULSE:           sprintf(text, _("Pulse"));       break;
742                 case NOISE:           sprintf(text, _("Noise"));       break;
743         }
744         return 0;
753 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
755         this->window = window;
756         this->number = number;
759 SynthOscGUI::~SynthOscGUI()
761         delete title;
762         delete level;
763         delete phase;
764         delete freq;
767 int SynthOscGUI::create_objects(int y)
769         char text[BCTEXTLEN];
770         sprintf(text, "%d:", number + 1);
771         window->subwindow->add_subwindow(title = new BC_Title(10, y + 15, text));
773         window->subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
774         window->subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
775         window->subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
776         return 1;
782 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
783  : BC_FPot(50, 
784         y, 
785         synth->config.oscillator_config.values[gui->number]->level, 
786         INFINITYGAIN, 
787         0)
789         this->synth = synth;
790         this->gui = gui;
793 SynthOscGUILevel::~SynthOscGUILevel()
797 int SynthOscGUILevel::handle_event()
799         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
800         config->level = get_value();
801         gui->window->canvas->update();
802         synth->send_configure_change();
803         return 1;
808 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
809  : BC_IPot(125, 
810         y, 
811         (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360), 
812         0, 
813         360)
815         this->synth = synth;
816         this->gui = gui;
819 SynthOscGUIPhase::~SynthOscGUIPhase()
823 int SynthOscGUIPhase::handle_event()
825         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
826         config->phase = (float)get_value() / 360;
827         gui->window->canvas->update();
828         synth->send_configure_change();
829         return 1;
834 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
835  : BC_IPot(200, 
836         y, 
837         (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor), 
838         1, 
839         100)
841         this->synth = synth;
842         this->gui = gui;
845 SynthOscGUIFreq::~SynthOscGUIFreq()
849 int SynthOscGUIFreq::handle_event()
851         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
852         config->freq_factor = get_value();
853         gui->window->canvas->update();
854         synth->send_configure_change();
855         return 1;
864 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
865  : BC_GenericButton(x, y, _("Add"))
867         this->synth = synth;
868         this->window = window;
871 SynthAddOsc::~SynthAddOsc()
875 int SynthAddOsc::handle_event()
877         synth->add_oscillator();
878         synth->send_configure_change();
879         window->update_gui();
880         return 1;
885 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
886  : BC_GenericButton(x, y, _("Delete"))
888         this->synth = synth;
889         this->window = window;
892 SynthDelOsc::~SynthDelOsc()
896 int SynthDelOsc::handle_event()
898         synth->delete_oscillator();
899         synth->send_configure_change();
900         window->update_gui();
901         return 1;
905 SynthScroll::SynthScroll(Synth *synth, 
906         SynthWindow *window, 
907         int x, 
908         int y, 
909         int h)
910  : BC_ScrollBar(x, 
911         y, 
912         SCROLL_VERT,
913         h, 
914         synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
915         0, 
916         window->subwindow->get_h())
918         this->synth = synth;
919         this->window = window;
922 SynthScroll::~SynthScroll()
926 int SynthScroll::handle_event()
928         window->update_gui();
929         return 1;
939 SynthSubWindow::SynthSubWindow(Synth *synth, int x, int y, int w, int h)
940  : BC_SubWindow(x, y, w, h)
942         this->synth = synth;
944 SynthSubWindow::~SynthSubWindow()
956 SynthClear::SynthClear(Synth *synth, int x, int y)
957  : BC_GenericButton(x, y, _("Clear"))
959         this->synth = synth;
961 SynthClear::~SynthClear()
964 int SynthClear::handle_event()
966         synth->config.reset();
967         synth->send_configure_change();
968         synth->update_gui();
969         return 1;
977 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
978  : BC_PopupMenu(x, y, 120, text)
980         this->synth = synth;
983 SynthWaveForm::~SynthWaveForm()
987 int SynthWaveForm::create_objects()
989 //      add_item(new SynthWaveFormItem(synth, _("DC"), DC));
990         add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
991         add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
992         add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
993         add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
994         add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
995         add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
996         return 0;
999 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1000  : BC_MenuItem(text)
1002         this->synth = synth;
1003         this->value = value;
1006 SynthWaveFormItem::~SynthWaveFormItem()
1010 int SynthWaveFormItem::handle_event()
1012         synth->config.wavefunction = value;
1013         synth->thread->window->canvas->update();
1014         synth->send_configure_change();
1015         return 1;
1019 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1020  : BC_FPot(x, 
1021                 y, 
1022                 synth->config.wetness, 
1023                 INFINITYGAIN, 
1024                 0)
1026         this->synth = synth;
1029 int SynthWetness::handle_event()
1031         synth->config.wetness = get_value();
1032         synth->send_configure_change();
1033         return 1;
1038 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1039  : BC_QPot(x, y, synth->config.base_freq)
1041         this->synth = synth;
1043 SynthFreqPot::~SynthFreqPot()
1046 int SynthFreqPot::handle_event()
1048         if(get_value() > 0 && get_value() < 30000)
1049         {
1050                 synth->config.base_freq = get_value();
1051                 freq_text->update(get_value());
1052                 synth->send_configure_change();
1053         }
1054         return 1;
1059 SynthBaseFreq::SynthBaseFreq(Synth *synth, int x, int y)
1060  : BC_TextBox(x, y, 70, 1, (int)synth->config.base_freq)
1062         this->synth = synth;
1064 SynthBaseFreq::~SynthBaseFreq()
1067 int SynthBaseFreq::handle_event()
1069         int new_value = atol(get_text());
1070         
1071         if(new_value > 0 && new_value < 30000)
1072         {
1073                 synth->config.base_freq = new_value;
1074                 freq_pot->update(synth->config.base_freq);
1075                 synth->send_configure_change();
1076         }
1077         return 1;
1084 SynthCanvas::SynthCanvas(Synth *synth, 
1085         SynthWindow *window, 
1086         int x, 
1087         int y, 
1088         int w, 
1089         int h)
1090  : BC_SubWindow(x, 
1091         y, 
1092         w, 
1093         h, 
1094         BLACK)
1096         this->synth = synth;
1097         this->window = window;
1100 SynthCanvas::~SynthCanvas()
1104 int SynthCanvas::update()
1106         int y1, y2, y = 0;
1107         
1108         clear_box(0, 0, get_w(), get_h());
1109         set_color(RED);
1111         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1113         set_color(GREEN);
1115         double normalize_constant = (double)1 / synth->get_total_power();
1116         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1117         
1118         for(int i = 1; i < get_w(); i++)
1119         {
1120                 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1121                 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1122                 y1 = y2;
1123         }
1124         flash();
1125         return 0;
1135 // ======================= level calculations
1136 SynthLevelZero::SynthLevelZero(Synth *synth)
1137  : BC_MenuItem(_("Zero"))
1139         this->synth = synth; 
1142 SynthLevelZero::~SynthLevelZero() 
1146 int SynthLevelZero::handle_event()
1148         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1149         {
1150                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1151         }
1153         synth->thread->window->update_gui();
1154         synth->send_configure_change();
1157 SynthLevelMax::SynthLevelMax(Synth *synth)
1158  : BC_MenuItem(_("Maximum"))
1160         this->synth = synth; 
1163 SynthLevelMax::~SynthLevelMax()
1167 int SynthLevelMax::handle_event()
1169         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1170         {
1171                 synth->config.oscillator_config.values[i]->level = 0;
1172         }
1173         synth->thread->window->update_gui();
1174         synth->send_configure_change();
1177 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1178  : BC_MenuItem(_("Normalize"))
1180         this->synth = synth;
1183 SynthLevelNormalize::~SynthLevelNormalize()
1187 int SynthLevelNormalize::handle_event()
1189 // get total power
1190         float total = 0;
1192         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1193         {
1194                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1195         }
1197         float scale = 1 / total;
1198         float new_value;
1200         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1201         {
1202                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1203                 new_value *= scale;
1204                 new_value = synth->db.todb(new_value);
1205                 
1206                 synth->config.oscillator_config.values[i]->level = new_value;
1207         }
1209         synth->thread->window->update_gui();
1210         synth->send_configure_change();
1213 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1214  : BC_MenuItem(_("Slope"))
1216         this->synth = synth;
1219 SynthLevelSlope::~SynthLevelSlope()
1223 int SynthLevelSlope::handle_event()
1225         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1226         
1227         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1228         {
1229                 synth->config.oscillator_config.values[i]->level = i * slope;
1230         }
1232         synth->thread->window->update_gui();
1233         synth->send_configure_change();
1236 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1237  : BC_MenuItem(_("Random"))
1239         this->synth = synth; 
1241 SynthLevelRandom::~SynthLevelRandom()
1245 int SynthLevelRandom::handle_event()
1247         srand(time(0));
1248         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1249         {
1250                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1251         }
1253         synth->thread->window->update_gui();
1254         synth->send_configure_change();
1257 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1258  : BC_MenuItem(_("Invert"))
1260         this->synth = synth;
1262 SynthLevelInvert::~SynthLevelInvert()
1266 int SynthLevelInvert::handle_event()
1268         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1269         {
1270                 synth->config.oscillator_config.values[i]->level = 
1271                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1272         }
1274         synth->thread->window->update_gui();
1275         synth->send_configure_change();
1278 SynthLevelSine::SynthLevelSine(Synth *synth)
1279  : BC_MenuItem(_("Sine"))
1281         this->synth = synth;
1283 SynthLevelSine::~SynthLevelSine()
1287 int SynthLevelSine::handle_event()
1289         float new_value;
1291         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1292         {
1293                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1294                 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1295                 synth->config.oscillator_config.values[i]->level = new_value;
1296         }
1298         synth->thread->window->update_gui();
1299         synth->send_configure_change();
1302 // ============================ phase calculations
1304 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1305  : BC_MenuItem(_("Invert"))
1307         this->synth = synth;
1309 SynthPhaseInvert::~SynthPhaseInvert()
1313 int SynthPhaseInvert::handle_event()
1315         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1316         {
1317                 synth->config.oscillator_config.values[i]->phase = 
1318                         1 - synth->config.oscillator_config.values[i]->phase;
1319         }
1321         synth->thread->window->update_gui();
1322         synth->send_configure_change();
1325 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1326  : BC_MenuItem(_("Zero"))
1328         this->synth = synth;
1330 SynthPhaseZero::~SynthPhaseZero()
1334 int SynthPhaseZero::handle_event()
1336         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1337         {
1338                 synth->config.oscillator_config.values[i]->phase = 0;
1339         }
1341         synth->thread->window->update_gui();
1342         synth->send_configure_change();
1345 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1346  : BC_MenuItem(_("Sine"))
1348         this->synth = synth;
1350 SynthPhaseSine::~SynthPhaseSine()
1354 int SynthPhaseSine::handle_event()
1356         float new_value;
1357         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1358         {
1359                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1360                 new_value = sin(new_value) / 2 + .5;
1361                 synth->config.oscillator_config.values[i]->phase = new_value;
1362         }
1364         synth->thread->window->update_gui();
1365         synth->send_configure_change();
1368 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1369  : BC_MenuItem(_("Random"))
1371         this->synth = synth;
1373 SynthPhaseRandom::~SynthPhaseRandom()
1377 int SynthPhaseRandom::handle_event()
1379         srand(time(0));
1380         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1381         {
1382                 synth->config.oscillator_config.values[i]->phase = 
1383                         (float)(rand() % 360) / 360;
1384         }
1386         synth->thread->window->update_gui();
1387         synth->send_configure_change();
1391 // ============================ freq calculations
1393 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1394  : BC_MenuItem(_("Random"))
1396         this->synth = synth;
1398 SynthFreqRandom::~SynthFreqRandom()
1402 int SynthFreqRandom::handle_event()
1404         srand(time(0));
1405         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1406         {
1407                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1408         }
1410         synth->thread->window->update_gui();
1411         synth->send_configure_change();
1414 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1415  : BC_MenuItem(_("Enumerate"))
1417         this->synth = synth;
1419 SynthFreqEnum::~SynthFreqEnum()
1423 int SynthFreqEnum::handle_event()
1425         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1426         {
1427                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1428         }
1430         synth->thread->window->update_gui();
1431         synth->send_configure_change();
1434 SynthFreqEven::SynthFreqEven(Synth *synth)
1435  : BC_MenuItem(_("Even"))
1437         this->synth = synth;
1439 SynthFreqEven::~SynthFreqEven()
1443 int SynthFreqEven::handle_event()
1445         if(synth->config.oscillator_config.total)
1446                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1448         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1449         {
1450                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1451         }
1453         synth->thread->window->update_gui();
1454         synth->send_configure_change();
1457 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1458  : BC_MenuItem(_("Odd"))
1459 { this->synth = synth; }
1460 SynthFreqOdd::~SynthFreqOdd()
1464 int SynthFreqOdd::handle_event()
1466         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1467         {
1468                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1469         }
1471         synth->thread->window->update_gui();
1472         synth->send_configure_change();
1475 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
1476  : BC_MenuItem(_("Fibonnacci"))
1478         this->synth = synth; 
1480 SynthFreqFibonacci::~SynthFreqFibonacci()
1484 int SynthFreqFibonacci::handle_event()
1486         float last_value1 = 0, last_value2 = 1;
1487         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1488         {
1489                 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1490                 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
1491                 last_value1 = last_value2;
1492                 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1493         }
1495         synth->thread->window->update_gui();
1496         synth->send_configure_change();
1499 SynthFreqPrime::SynthFreqPrime(Synth *synth)
1500  : BC_MenuItem(_("Prime"))
1502         this->synth = synth; 
1504 SynthFreqPrime::~SynthFreqPrime()
1508 int SynthFreqPrime::handle_event()
1510         float number = 1;
1511         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1512         {
1513                 synth->config.oscillator_config.values[i]->freq_factor = number;
1514                 number = get_next_prime(number);
1515         }
1517         synth->thread->window->update_gui();
1518         synth->send_configure_change();
1521 float SynthFreqPrime::get_next_prime(float number)
1523         int result = 1;
1524         
1525         while(result)
1526         {
1527                 result = 0;
1528                 number++;
1529                 
1530                 for(float i = number - 1; i > 1 && !result; i--)
1531                 {
1532                         if((number / i) - (int)(number / i) == 0) result = 1;
1533                 }
1534         }
1535         
1536         return number;
1546 SynthOscillatorConfig::SynthOscillatorConfig(int number)
1548         reset();
1549         this->number = number;
1552 SynthOscillatorConfig::~SynthOscillatorConfig()
1556 void SynthOscillatorConfig::reset()
1558         level = 0;
1559         phase = 0;
1560         freq_factor = 1;
1563 void SynthOscillatorConfig::load_defaults(Defaults *defaults)
1565         char string[BCTEXTLEN];
1567         sprintf(string, "LEVEL%d", number);
1568         level = defaults->get(string, (float)0);
1569         sprintf(string, "PHASE%d", number);
1570         phase = defaults->get(string, (float)0);
1571         sprintf(string, "FREQFACTOR%d", number);
1572         freq_factor = defaults->get(string, (float)1);
1575 void SynthOscillatorConfig::save_defaults(Defaults *defaults)
1577         char string[BCTEXTLEN];
1579         sprintf(string, "LEVEL%d", number);
1580         defaults->update(string, (float)level);
1581         sprintf(string, "PHASE%d", number);
1582         defaults->update(string, (float)phase);
1583         sprintf(string, "FREQFACTOR%d", number);
1584         defaults->update(string, (float)freq_factor);
1587 void SynthOscillatorConfig::read_data(FileXML *file)
1589         level = file->tag.get_property("LEVEL", (float)level);
1590         phase = file->tag.get_property("PHASE", (float)phase);
1591         freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
1594 void SynthOscillatorConfig::save_data(FileXML *file)
1596         file->tag.set_title("OSCILLATOR");
1597         file->tag.set_property("LEVEL", (float)level);
1598         file->tag.set_property("PHASE", (float)phase);
1599         file->tag.set_property("FREQFACTOR", (float)freq_factor);
1600         file->append_tag();
1601         file->append_newline();
1604 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
1606         if(EQUIV(level, that.level) && 
1607                 EQUIV(phase, that.phase) &&
1608                 EQUIV(freq_factor, that.freq_factor))
1609                 return 1;
1610         else
1611                 return 0;
1614 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
1616         level = that.level;
1617         phase = that.phase;
1618         freq_factor = that.freq_factor;
1632 SynthConfig::SynthConfig()
1634         reset();
1637 SynthConfig::~SynthConfig()
1639         oscillator_config.remove_all_objects();
1642 void SynthConfig::reset()
1644         wetness = 0;
1645         base_freq = 440;
1646         wavefunction = SINE;
1647         for(int i = 0; i < oscillator_config.total; i++)
1648         {
1649                 oscillator_config.values[i]->reset();
1650         }
1653 int SynthConfig::equivalent(SynthConfig &that)
1655 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
1656         if(base_freq != that.base_freq ||
1657                 wavefunction != that.wavefunction ||
1658                 oscillator_config.total != that.oscillator_config.total) return 0;
1660         for(int i = 0; i < oscillator_config.total; i++)
1661         {
1662                 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
1663                         return 0;
1664         }
1666         return 1;
1669 void SynthConfig::copy_from(SynthConfig& that)
1671         wetness = that.wetness;
1672         base_freq = that.base_freq;
1673         wavefunction = that.wavefunction;
1675         int i;
1676         for(i = 0; 
1677                 i < oscillator_config.total && i < that.oscillator_config.total;
1678                 i++)
1679         {
1680                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1681         }
1683         for( ;
1684                 i < that.oscillator_config.total;
1685                 i++)
1686         {
1687                 oscillator_config.append(new SynthOscillatorConfig(i));
1688                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1689         }
1691         for( ;
1692                 i < oscillator_config.total;
1693                 i++)
1694         {
1695                 oscillator_config.remove_object();
1696         }
1699 void SynthConfig::interpolate(SynthConfig &prev, 
1700         SynthConfig &next, 
1701         int64_t prev_frame, 
1702         int64_t next_frame, 
1703         int64_t current_frame)
1705         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
1706         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
1708         copy_from(prev);
1709         wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
1710         base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);