r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / synthesizer / synthesizer.C
blob59845173eca13fad83f59a187e35a7f14ca15304
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()
60         return _("Synthesizer");
64 void Synth::reset()
66         thread = 0;
67         need_reconfigure = 1;
68         dsp_buffer = 0;
71 int Synth::is_realtime()
73         return 1;
76 int Synth::is_synthesis()
78         return 1;
83 LOAD_CONFIGURATION_MACRO(Synth, SynthConfig)
88 int Synth::load_defaults()
90         char directory[BCTEXTLEN], string[BCTEXTLEN];
92         sprintf(directory, "%ssynthesizer.rc", BCASTDIR);
93         defaults = new Defaults(directory);
94         defaults->load();
95         w = defaults->get("WIDTH", 380);
96         h = defaults->get("HEIGHT", 400);
98         config.wetness = defaults->get("WETNESS", 0);
99         config.base_freq = defaults->get("BASEFREQ", 440);
100         config.wavefunction = defaults->get("WAVEFUNCTION", 0);
102         int total_oscillators = defaults->get("OSCILLATORS", TOTALOSCILLATORS);
103         config.oscillator_config.remove_all_objects();
104         for(int i = 0; i < total_oscillators; i++)
105         {
106                 config.oscillator_config.append(new SynthOscillatorConfig(i));
107                 config.oscillator_config.values[i]->load_defaults(defaults);
108         }
110         return 0;
114 void Synth::read_data(KeyFrame *keyframe)
116         FileXML input;
117 // cause htal file to read directly from text
118         input.set_shared_string(keyframe->data, strlen(keyframe->data));
120 //printf("Synth::read_data %s\n", keyframe->data);
121         int result = 0, current_osc = 0, total_oscillators = 0;
122         while(!result)
123         {
124                 result = input.read_tag();
126                 if(!result)
127                 {
128                         if(input.tag.title_is("SYNTH"))
129                         {
130                                 config.wetness = input.tag.get_property("WETNESS", config.wetness);
131                                 config.base_freq = input.tag.get_property("BASEFREQ", config.base_freq);
132                                 config.wavefunction = input.tag.get_property("WAVEFUNCTION", config.wavefunction);
133                                 total_oscillators = input.tag.get_property("OSCILLATORS", 0);
134                         }
135                         else
136                         if(input.tag.title_is("OSCILLATOR"))
137                         {
138                                 if(current_osc >= config.oscillator_config.total)
139                                         config.oscillator_config.append(new SynthOscillatorConfig(current_osc));
141                                 config.oscillator_config.values[current_osc]->read_data(&input);
142                                 current_osc++;
143                         }
144                 }
145         }
147         while(config.oscillator_config.total > current_osc)
148                 config.oscillator_config.remove_object();
151 void Synth::save_data(KeyFrame *keyframe)
153         FileXML output;
154 // cause htal file to store data directly in text
155         output.set_shared_string(keyframe->data, MESSAGESIZE);
157         output.tag.set_title("SYNTH");
158         output.tag.set_property("WETNESS", config.wetness);
159         output.tag.set_property("BASEFREQ", config.base_freq);
160         output.tag.set_property("WAVEFUNCTION", config.wavefunction);
161         output.tag.set_property("OSCILLATORS", config.oscillator_config.total);
162         output.append_tag();
163         output.append_newline();
165         for(int i = 0; i < config.oscillator_config.total; i++)
166         {
167                 config.oscillator_config.values[i]->save_data(&output);
168         }
170         output.terminate_string();
171 // data is now in *text
174 int Synth::save_defaults()
176         char string[BCTEXTLEN];
178         defaults->update("WIDTH", w);
179         defaults->update("HEIGHT", h);
180         defaults->update("WETNESS", config.wetness);
181         defaults->update("BASEFREQ", config.base_freq);
182         defaults->update("WAVEFUNCTION", config.wavefunction);
183         defaults->update("OSCILLATORS", config.oscillator_config.total);
185         for(int i = 0; i < config.oscillator_config.total; i++)
186         {
187                 config.oscillator_config.values[i]->save_defaults(defaults);
188         }
189         defaults->save();
191         return 0;
194 int Synth::show_gui()
196         load_configuration();
197         
198         thread = new SynthThread(this);
199         thread->start();
200         return 0;
203 int Synth::set_string()
205         if(thread) thread->window->set_title(gui_string);
206         return 0;
209 void Synth::raise_window()
211         if(thread)
212         {
213                 thread->window->raise_window();
214                 thread->window->flush();
215         }
218 void Synth::update_gui()
220         if(thread)
221         {
222                 load_configuration();
223                 thread->window->lock_window();
224                 thread->window->update_gui();
225                 thread->window->unlock_window();
226         }
230 void Synth::add_oscillator()
232         if(config.oscillator_config.total > 20) return;
234         config.oscillator_config.append(new SynthOscillatorConfig(config.oscillator_config.total - 1));
237 void Synth::delete_oscillator()
239         if(config.oscillator_config.total)
240         {
241                 config.oscillator_config.remove_object();
242         }
246 double Synth::get_total_power()
248         double result = 0;
250         if(config.wavefunction == DC) return 1.0;
252         for(int i = 0; i < config.oscillator_config.total; i++)
253         {
254                 result += db.fromdb(config.oscillator_config.values[i]->level);
255         }
257         if(result == 0) result = 1;  // prevent division by 0
258         return result;
262 double Synth::solve_eqn(double *output, 
263         double x1, 
264         double x2, 
265         double normalize_constant,
266         int oscillator)
268         SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
269         if(config->level <= INFINITYGAIN) return 0;
271         double result;
272         register double x;
273         double power = this->db.fromdb(config->level) * normalize_constant;
274         double phase_offset = config->phase * this->period;
275         double x3 = x1 + phase_offset;
276         double x4 = x2 + phase_offset;
277         double period = this->period / config->freq_factor;
278         int sample;
280         switch(this->config.wavefunction)
281         {
282                 case DC:
283                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
284                         {
285                                 output[sample] += power;
286                         }
287                         break;
288                 case SINE:
289                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
290                         {
291                                 output[sample] += sin(x / period * 2 * M_PI) * power;
292                         }
293                         break;
294                 case SAWTOOTH:
295                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
296                         {
297                                 output[sample] += function_sawtooth(x / period) * power;
298                         }
299                         break;
300                 case SQUARE:
301                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
302                         {
303                                 output[sample] += function_square(x / period) * power;
304                         }
305                         break;
306                 case TRIANGLE:
307                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
308                         {
309                                 output[sample] += function_triangle(x / period) * power;
310                         }
311                         break;
312                 case PULSE:
313                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
314                         {
315                                 output[sample] += function_pulse(x / period) * power;
316                         }
317                         break;
318                 case NOISE:
319                         for(sample = (int)x1, x = x3; x < x4; x++, sample++)
320                         {
321                                 output[sample] += function_noise() * power;
322                         }
323                         break;
324         }
327 double Synth::get_point(float x, double normalize_constant)
329         double result = 0;
330         for(int i = 0; i < config.oscillator_config.total; i++)
331                 result += get_oscillator_point(x, normalize_constant, i);
333         return result;
336 double Synth::get_oscillator_point(float x, 
337                 double normalize_constant, 
338                 int oscillator)
340         SynthOscillatorConfig *config = this->config.oscillator_config.values[oscillator];
341         double power = db.fromdb(config->level) * normalize_constant;
342         switch(this->config.wavefunction)
343         {
344                 case DC:
345                         return power;
346                         break;
347                 case SINE:
348                         return sin((x + config->phase) * config->freq_factor * 2 * M_PI) * power;
349                         break;
350                 case SAWTOOTH:
351                         return function_sawtooth((x + config->phase) * config->freq_factor) * power;
352                         break;
353                 case SQUARE:
354                         return function_square((x + config->phase) * config->freq_factor) * power;
355                         break;
356                 case TRIANGLE:
357                         return function_triangle((x + config->phase) * config->freq_factor) * power;
358                         break;
359                 case PULSE:
360                         return function_pulse((x + config->phase) * config->freq_factor) * power;
361                         break;
362                 case NOISE:
363                         return function_noise() * power;
364                         break;
365         }
368 double Synth::function_square(double x)
370         x -= (int)x; // only fraction counts
371         return (x < .5) ? -1 : 1;
374 double Synth::function_pulse(double x)
376         x -= (int)x; // only fraction counts
377         return (x < .5) ? 0 : 1;
380 double Synth::function_noise()
382         return (double)(rand() % 65536 - 32768) / 32768;
385 double Synth::function_sawtooth(double x)
387         x -= (int)x;
388         return 1 - x * 2;
391 double Synth::function_triangle(double x)
393         x -= (int)x;
394         return (x < .5) ? 1 - x * 4 : -3 + x * 4;
397 int Synth::process_realtime(int64_t size, double *input_ptr, double *output_ptr)
401         need_reconfigure |= load_configuration();
402         if(need_reconfigure) reconfigure();
404         double wetness = DB::fromdb(config.wetness);
405         if(EQUIV(config.wetness, INFINITYGAIN)) wetness = 0;
407         for(int j = 0; j < size; j++)
408                 output_ptr[j] = input_ptr[j] * wetness;
410         int64_t fragment_len;
411         for(int64_t i = 0; i < size; i += fragment_len)
412         {
413                 fragment_len = size;
414                 if(i + fragment_len > size) fragment_len = size - i;
416 //printf("Synth::process_realtime 1 %d %d %d\n", i, fragment_len, size);
417                 fragment_len = overlay_synth(i, fragment_len, input_ptr, output_ptr);
418 //printf("Synth::process_realtime 2\n");
419         }
420         
421         
422         return 0;
425 int Synth::overlay_synth(int64_t start, int64_t length, double *input, double *output)
427         if(waveform_sample + length > waveform_length) 
428                 length = waveform_length - waveform_sample;
430 //printf("Synth::overlay_synth 1 %d %d\n", length, waveform_length);
432 // calculate some more data
433 // only calculate what's needed to speed it up
434         if(waveform_sample + length > samples_rendered)
435         {
436                 int64_t start = waveform_sample, end = waveform_sample + length;
437                 for(int i = start; i < end; i++) dsp_buffer[i] = 0;
438                 
439                 double normalize_constant = 1 / get_total_power();
440                 for(int i = 0; i < config.oscillator_config.total; i++)
441                         solve_eqn(dsp_buffer, 
442                                 start, 
443                                 end, 
444                                 normalize_constant,
445                                 i);
447                 
448                 samples_rendered = end;
449         }
450 //printf("Synth::overlay_synth 2\n");
453         double *buffer_in = &input[start];
454         double *buffer_out = &output[start];
456         for(int i = 0; i < length; i++)
457         {
458                 buffer_out[i] += dsp_buffer[waveform_sample++];
459         }
460 //printf("Synth::overlay_synth 3\n");
462         if(waveform_sample >= waveform_length) waveform_sample = 0;
464         return length;
467 void Synth::reconfigure()
469         need_reconfigure = 0;
471         if(dsp_buffer)
472         {
473                 delete [] dsp_buffer;
474         }
476 //printf("Synth::reconfigure 1 %d\n", PluginAClient::project_sample_rate);
477         waveform_length = PluginAClient::project_sample_rate;
478         period = (float)PluginAClient::project_sample_rate / config.base_freq;
479         dsp_buffer = new double[waveform_length + 1];
481         samples_rendered = 0;     // do some calculations on the next process_realtime
482         waveform_sample = 0;
505 SynthThread::SynthThread(Synth *synth)
506  : Thread()
508         this->synth = synth;
509         set_synchronous(0);
510         completion.lock();
513 SynthThread::~SynthThread()
515         delete window;
518 void SynthThread::run()
520         BC_DisplayInfo info;
521         window = new SynthWindow(synth, 
522                 info.get_abs_cursor_x() - 125, 
523                 info.get_abs_cursor_y() - 115);
524         window->create_objects();
525         int result = window->run_window();
526         completion.unlock();
527 // Last command executed in thread
528         if(result) synth->client_side_close();
541 SynthWindow::SynthWindow(Synth *synth, int x, int y)
542  : BC_Window(synth->gui_string, 
543         x, 
544         y, 
545         380, 
546         synth->h, 
547         380, 
548         10, 
549         1, 
550         0,
551         1)
553         this->synth = synth; 
556 SynthWindow::~SynthWindow()
560 int SynthWindow::create_objects()
562         BC_MenuBar *menu;
563         add_subwindow(menu = new BC_MenuBar(0, 0, get_w()));
565         BC_Menu *levelmenu, *phasemenu, *harmonicmenu;
566         menu->add_menu(levelmenu = new BC_Menu(_("Level")));
567         menu->add_menu(phasemenu = new BC_Menu(_("Phase")));
568         menu->add_menu(harmonicmenu = new BC_Menu(_("Harmonic")));
570         levelmenu->add_item(new SynthLevelInvert(synth));
571         levelmenu->add_item(new SynthLevelMax(synth));
572         levelmenu->add_item(new SynthLevelRandom(synth));
573         levelmenu->add_item(new SynthLevelSine(synth));
574         levelmenu->add_item(new SynthLevelSlope(synth));
575         levelmenu->add_item(new SynthLevelZero(synth));
577         phasemenu->add_item(new SynthPhaseInvert(synth));
578         phasemenu->add_item(new SynthPhaseRandom(synth));
579         phasemenu->add_item(new SynthPhaseSine(synth));
580         phasemenu->add_item(new SynthPhaseZero(synth));
582         harmonicmenu->add_item(new SynthFreqEnum(synth));
583         harmonicmenu->add_item(new SynthFreqEven(synth));
584         harmonicmenu->add_item(new SynthFreqFibonacci(synth));
585         harmonicmenu->add_item(new SynthFreqOdd(synth));
586         harmonicmenu->add_item(new SynthFreqPrime(synth));
588         int x = 10, y = 30, i;
589         add_subwindow(new BC_Title(x, y, _("Waveform")));
590         x += 240;
591         add_subwindow(new BC_Title(x, y, _("Wave Function")));
592         y += 20;
593         x = 10;
594         add_subwindow(canvas = new SynthCanvas(synth, this, x, y, 230, 160));
595         canvas->update();
597         x += 240;
598         char string[BCTEXTLEN];
599         waveform_to_text(string, synth->config.wavefunction);
601         add_subwindow(waveform = new SynthWaveForm(synth, x, y, string));
602         waveform->create_objects();
603         y += 30;
606         add_subwindow(new BC_Title(x, y, _("Base Frequency:")));
607         y += 30;
608         add_subwindow(base_freq = new SynthBaseFreq(synth, x, y));
609         x += 80;
610         add_subwindow(freqpot = new SynthFreqPot(synth, this, x, y - 10));
611         base_freq->freq_pot = freqpot;
612         freqpot->freq_text = base_freq;
613         x -= 80;
614         y += 40;
615         add_subwindow(new BC_Title(x, y, _("Wetness:")));
616         add_subwindow(wetness = new SynthWetness(synth, x + 70, y - 10));
618         y += 40;
619         add_subwindow(new SynthClear(synth, x, y));
622         x = 50;  
623         y = 220;
624         add_subwindow(new BC_Title(x, y, _("Level"))); 
625         x += 75;
626         add_subwindow(new BC_Title(x, y, _("Phase"))); 
627         x += 75;
628         add_subwindow(new BC_Title(x, y, _("Harmonic")));
632         y += 20; x = 10;
633         add_subwindow(subwindow = new SynthSubWindow(synth, x, y, 265, get_h() - y));
634         x += 265;
635         add_subwindow(scroll = new SynthScroll(synth, this, x, y, get_h() - y));
638         x += 20;
639         add_subwindow(new SynthAddOsc(synth, this, x, y));
640         y += 30;
641         add_subwindow(new SynthDelOsc(synth, this, x, y));
643         update_scrollbar();
644         update_oscillators();
646         show_window();
647         flush();
648         return 0;
651 int SynthWindow::close_event()
653 // Set result to 1 to indicate a client side close
654         set_done(1);
655         return 1;
658 int SynthWindow::resize_event(int w, int h)
660         clear_box(0, 0, w, h);
661         subwindow->reposition_window(subwindow->get_x(), 
662                 subwindow->get_y(), 
663                 subwindow->get_w(), 
664                 h - subwindow->get_y());
665         subwindow->clear_box(0, 0, subwindow->get_w(), subwindow->get_h());
666         scroll->reposition_window(scroll->get_x(), 
667                 scroll->get_y(), 
668                 h - scroll->get_y());
669         update_scrollbar();
670         update_oscillators();
671         synth->w = w;
672         synth->h = h;
673         return 1;
676 void SynthWindow::update_gui()
678         char string[BCTEXTLEN];
679         freqpot->update(synth->config.base_freq);
680         base_freq->update((int64_t)synth->config.base_freq);
681         wetness->update(synth->config.wetness);
682         waveform_to_text(string, synth->config.wavefunction);
683         waveform->set_text(string);
684         
685         update_scrollbar();
686         update_oscillators();
687         canvas->update();
690 void SynthWindow::update_scrollbar()
692         scroll->update_length(synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
693                 scroll->get_position(), 
694                 subwindow->get_h());
697 void SynthWindow::update_oscillators()
699         int i, y = -scroll->get_position();
703 // Add new oscillators
704         for(i = 0; 
705                 i < synth->config.oscillator_config.total; 
706                 i++)
707         {
708                 SynthOscGUI *gui;
709                 SynthOscillatorConfig *config = synth->config.oscillator_config.values[i];
711                 if(oscillators.total <= i)
712                 {
713                         oscillators.append(gui = new SynthOscGUI(this, i));
714                         gui->create_objects(y);
715                 }
716                 else
717                 {
718                         gui = oscillators.values[i];
720                         gui->title->reposition_window(gui->title->get_x(), y + 15);
722                         gui->level->reposition_window(gui->level->get_x(), y);
723                         gui->level->update(config->level);
725                         gui->phase->reposition_window(gui->phase->get_x(), y);
726                         gui->phase->update((int64_t)(config->phase * 360));
728                         gui->freq->reposition_window(gui->freq->get_x(), y);
729                         gui->freq->update((int64_t)(config->freq_factor));
730                 }
731                 y += OSCILLATORHEIGHT;
732         }
734 // Delete old oscillators
735         for( ; 
736                 i < oscillators.total;
737                 i++)
738                 oscillators.remove_object();
742 int SynthWindow::waveform_to_text(char *text, int waveform)
744         switch(waveform)
745         {
746                 case DC:              sprintf(text, _("DC"));           break;
747                 case SINE:            sprintf(text, _("Sine"));           break;
748                 case SAWTOOTH:        sprintf(text, _("Sawtooth"));       break;
749                 case SQUARE:          sprintf(text, _("Square"));         break;
750                 case TRIANGLE:        sprintf(text, _("Triangle"));       break;
751                 case PULSE:           sprintf(text, _("Pulse"));       break;
752                 case NOISE:           sprintf(text, _("Noise"));       break;
753         }
754         return 0;
763 SynthOscGUI::SynthOscGUI(SynthWindow *window, int number)
765         this->window = window;
766         this->number = number;
769 SynthOscGUI::~SynthOscGUI()
771         delete title;
772         delete level;
773         delete phase;
774         delete freq;
777 int SynthOscGUI::create_objects(int y)
779         char text[BCTEXTLEN];
780         sprintf(text, "%d:", number + 1);
781         window->subwindow->add_subwindow(title = new BC_Title(10, y + 15, text));
783         window->subwindow->add_subwindow(level = new SynthOscGUILevel(window->synth, this, y));
784         window->subwindow->add_subwindow(phase = new SynthOscGUIPhase(window->synth, this, y));
785         window->subwindow->add_subwindow(freq = new SynthOscGUIFreq(window->synth, this, y));
786         return 1;
792 SynthOscGUILevel::SynthOscGUILevel(Synth *synth, SynthOscGUI *gui, int y)
793  : BC_FPot(50, 
794         y, 
795         synth->config.oscillator_config.values[gui->number]->level, 
796         INFINITYGAIN, 
797         0)
799         this->synth = synth;
800         this->gui = gui;
803 SynthOscGUILevel::~SynthOscGUILevel()
807 int SynthOscGUILevel::handle_event()
809         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
810         config->level = get_value();
811         gui->window->canvas->update();
812         synth->send_configure_change();
813         return 1;
818 SynthOscGUIPhase::SynthOscGUIPhase(Synth *synth, SynthOscGUI *gui, int y)
819  : BC_IPot(125, 
820         y, 
821         (int64_t)(synth->config.oscillator_config.values[gui->number]->phase * 360), 
822         0, 
823         360)
825         this->synth = synth;
826         this->gui = gui;
829 SynthOscGUIPhase::~SynthOscGUIPhase()
833 int SynthOscGUIPhase::handle_event()
835         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
836         config->phase = (float)get_value() / 360;
837         gui->window->canvas->update();
838         synth->send_configure_change();
839         return 1;
844 SynthOscGUIFreq::SynthOscGUIFreq(Synth *synth, SynthOscGUI *gui, int y)
845  : BC_IPot(200, 
846         y, 
847         (int64_t)(synth->config.oscillator_config.values[gui->number]->freq_factor), 
848         1, 
849         100)
851         this->synth = synth;
852         this->gui = gui;
855 SynthOscGUIFreq::~SynthOscGUIFreq()
859 int SynthOscGUIFreq::handle_event()
861         SynthOscillatorConfig *config = synth->config.oscillator_config.values[gui->number];
862         config->freq_factor = get_value();
863         gui->window->canvas->update();
864         synth->send_configure_change();
865         return 1;
874 SynthAddOsc::SynthAddOsc(Synth *synth, SynthWindow *window, int x, int y)
875  : BC_GenericButton(x, y, _("Add"))
877         this->synth = synth;
878         this->window = window;
881 SynthAddOsc::~SynthAddOsc()
885 int SynthAddOsc::handle_event()
887         synth->add_oscillator();
888         synth->send_configure_change();
889         window->update_gui();
890         return 1;
895 SynthDelOsc::SynthDelOsc(Synth *synth, SynthWindow *window, int x, int y)
896  : BC_GenericButton(x, y, _("Delete"))
898         this->synth = synth;
899         this->window = window;
902 SynthDelOsc::~SynthDelOsc()
906 int SynthDelOsc::handle_event()
908         synth->delete_oscillator();
909         synth->send_configure_change();
910         window->update_gui();
911         return 1;
915 SynthScroll::SynthScroll(Synth *synth, 
916         SynthWindow *window, 
917         int x, 
918         int y, 
919         int h)
920  : BC_ScrollBar(x, 
921         y, 
922         SCROLL_VERT,
923         h, 
924         synth->config.oscillator_config.total * OSCILLATORHEIGHT, 
925         0, 
926         window->subwindow->get_h())
928         this->synth = synth;
929         this->window = window;
932 SynthScroll::~SynthScroll()
936 int SynthScroll::handle_event()
938         window->update_gui();
939         return 1;
949 SynthSubWindow::SynthSubWindow(Synth *synth, int x, int y, int w, int h)
950  : BC_SubWindow(x, y, w, h)
952         this->synth = synth;
954 SynthSubWindow::~SynthSubWindow()
966 SynthClear::SynthClear(Synth *synth, int x, int y)
967  : BC_GenericButton(x, y, _("Clear"))
969         this->synth = synth;
971 SynthClear::~SynthClear()
974 int SynthClear::handle_event()
976         synth->config.reset();
977         synth->send_configure_change();
978         synth->update_gui();
979         return 1;
987 SynthWaveForm::SynthWaveForm(Synth *synth, int x, int y, char *text)
988  : BC_PopupMenu(x, y, 120, text)
990         this->synth = synth;
993 SynthWaveForm::~SynthWaveForm()
997 int SynthWaveForm::create_objects()
999 //      add_item(new SynthWaveFormItem(synth, _("DC"), DC));
1000         add_item(new SynthWaveFormItem(synth, _("Sine"), SINE));
1001         add_item(new SynthWaveFormItem(synth, _("Sawtooth"), SAWTOOTH));
1002         add_item(new SynthWaveFormItem(synth, _("Square"), SQUARE));
1003         add_item(new SynthWaveFormItem(synth, _("Triangle"), TRIANGLE));
1004         add_item(new SynthWaveFormItem(synth, _("Pulse"), PULSE));
1005         add_item(new SynthWaveFormItem(synth, _("Noise"), NOISE));
1006         return 0;
1009 SynthWaveFormItem::SynthWaveFormItem(Synth *synth, char *text, int value)
1010  : BC_MenuItem(text)
1012         this->synth = synth;
1013         this->value = value;
1016 SynthWaveFormItem::~SynthWaveFormItem()
1020 int SynthWaveFormItem::handle_event()
1022         synth->config.wavefunction = value;
1023         synth->thread->window->canvas->update();
1024         synth->send_configure_change();
1025         return 1;
1029 SynthWetness::SynthWetness(Synth *synth, int x, int y)
1030  : BC_FPot(x, 
1031                 y, 
1032                 synth->config.wetness, 
1033                 INFINITYGAIN, 
1034                 0)
1036         this->synth = synth;
1039 int SynthWetness::handle_event()
1041         synth->config.wetness = get_value();
1042         synth->send_configure_change();
1043         return 1;
1048 SynthFreqPot::SynthFreqPot(Synth *synth, SynthWindow *window, int x, int y)
1049  : BC_QPot(x, y, synth->config.base_freq)
1051         this->synth = synth;
1053 SynthFreqPot::~SynthFreqPot()
1056 int SynthFreqPot::handle_event()
1058         if(get_value() > 0 && get_value() < 30000)
1059         {
1060                 synth->config.base_freq = get_value();
1061                 freq_text->update(get_value());
1062                 synth->send_configure_change();
1063         }
1064         return 1;
1069 SynthBaseFreq::SynthBaseFreq(Synth *synth, int x, int y)
1070  : BC_TextBox(x, y, 70, 1, (int)synth->config.base_freq)
1072         this->synth = synth;
1074 SynthBaseFreq::~SynthBaseFreq()
1077 int SynthBaseFreq::handle_event()
1079         int new_value = atol(get_text());
1080         
1081         if(new_value > 0 && new_value < 30000)
1082         {
1083                 synth->config.base_freq = new_value;
1084                 freq_pot->update(synth->config.base_freq);
1085                 synth->send_configure_change();
1086         }
1087         return 1;
1094 SynthCanvas::SynthCanvas(Synth *synth, 
1095         SynthWindow *window, 
1096         int x, 
1097         int y, 
1098         int w, 
1099         int h)
1100  : BC_SubWindow(x, 
1101         y, 
1102         w, 
1103         h, 
1104         BLACK)
1106         this->synth = synth;
1107         this->window = window;
1110 SynthCanvas::~SynthCanvas()
1114 int SynthCanvas::update()
1116         int y1, y2, y = 0;
1117         
1118         clear_box(0, 0, get_w(), get_h());
1119         set_color(RED);
1121         draw_line(0, get_h() / 2 + y, get_w(), get_h() / 2 + y);
1123         set_color(GREEN);
1125         double normalize_constant = (double)1 / synth->get_total_power();
1126         y1 = (int)(synth->get_point((float)0, normalize_constant) * get_h() / 2);
1127         
1128         for(int i = 1; i < get_w(); i++)
1129         {
1130                 y2 = (int)(synth->get_point((float)i / get_w(), normalize_constant) * get_h() / 2);
1131                 draw_line(i - 1, get_h() / 2 - y1, i, get_h() / 2 - y2);
1132                 y1 = y2;
1133         }
1134         flash();
1135         return 0;
1145 // ======================= level calculations
1146 SynthLevelZero::SynthLevelZero(Synth *synth)
1147  : BC_MenuItem(_("Zero"))
1149         this->synth = synth; 
1152 SynthLevelZero::~SynthLevelZero() 
1156 int SynthLevelZero::handle_event()
1158         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1159         {
1160                 synth->config.oscillator_config.values[i]->level = INFINITYGAIN;
1161         }
1163         synth->thread->window->update_gui();
1164         synth->send_configure_change();
1167 SynthLevelMax::SynthLevelMax(Synth *synth)
1168  : BC_MenuItem(_("Maximum"))
1170         this->synth = synth; 
1173 SynthLevelMax::~SynthLevelMax()
1177 int SynthLevelMax::handle_event()
1179         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1180         {
1181                 synth->config.oscillator_config.values[i]->level = 0;
1182         }
1183         synth->thread->window->update_gui();
1184         synth->send_configure_change();
1187 SynthLevelNormalize::SynthLevelNormalize(Synth *synth)
1188  : BC_MenuItem(_("Normalize"))
1190         this->synth = synth;
1193 SynthLevelNormalize::~SynthLevelNormalize()
1197 int SynthLevelNormalize::handle_event()
1199 // get total power
1200         float total = 0;
1202         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1203         {
1204                 total += synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1205         }
1207         float scale = 1 / total;
1208         float new_value;
1210         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1211         {
1212                 new_value = synth->db.fromdb(synth->config.oscillator_config.values[i]->level);
1213                 new_value *= scale;
1214                 new_value = synth->db.todb(new_value);
1215                 
1216                 synth->config.oscillator_config.values[i]->level = new_value;
1217         }
1219         synth->thread->window->update_gui();
1220         synth->send_configure_change();
1223 SynthLevelSlope::SynthLevelSlope(Synth *synth)
1224  : BC_MenuItem(_("Slope"))
1226         this->synth = synth;
1229 SynthLevelSlope::~SynthLevelSlope()
1233 int SynthLevelSlope::handle_event()
1235         float slope = (float)INFINITYGAIN / synth->config.oscillator_config.total;
1236         
1237         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1238         {
1239                 synth->config.oscillator_config.values[i]->level = i * slope;
1240         }
1242         synth->thread->window->update_gui();
1243         synth->send_configure_change();
1246 SynthLevelRandom::SynthLevelRandom(Synth *synth)
1247  : BC_MenuItem(_("Random"))
1249         this->synth = synth; 
1251 SynthLevelRandom::~SynthLevelRandom()
1255 int SynthLevelRandom::handle_event()
1257         srand(time(0));
1258         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1259         {
1260                 synth->config.oscillator_config.values[i]->level = -(rand() % -INFINITYGAIN);
1261         }
1263         synth->thread->window->update_gui();
1264         synth->send_configure_change();
1267 SynthLevelInvert::SynthLevelInvert(Synth *synth)
1268  : BC_MenuItem(_("Invert"))
1270         this->synth = synth;
1272 SynthLevelInvert::~SynthLevelInvert()
1276 int SynthLevelInvert::handle_event()
1278         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1279         {
1280                 synth->config.oscillator_config.values[i]->level = 
1281                         INFINITYGAIN - synth->config.oscillator_config.values[i]->level;
1282         }
1284         synth->thread->window->update_gui();
1285         synth->send_configure_change();
1288 SynthLevelSine::SynthLevelSine(Synth *synth)
1289  : BC_MenuItem(_("Sine"))
1291         this->synth = synth;
1293 SynthLevelSine::~SynthLevelSine()
1297 int SynthLevelSine::handle_event()
1299         float new_value;
1301         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1302         {
1303                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1304                 new_value = sin(new_value) * INFINITYGAIN / 2 + INFINITYGAIN / 2;
1305                 synth->config.oscillator_config.values[i]->level = new_value;
1306         }
1308         synth->thread->window->update_gui();
1309         synth->send_configure_change();
1312 // ============================ phase calculations
1314 SynthPhaseInvert::SynthPhaseInvert(Synth *synth)
1315  : BC_MenuItem(_("Invert"))
1317         this->synth = synth;
1319 SynthPhaseInvert::~SynthPhaseInvert()
1323 int SynthPhaseInvert::handle_event()
1325         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1326         {
1327                 synth->config.oscillator_config.values[i]->phase = 
1328                         1 - synth->config.oscillator_config.values[i]->phase;
1329         }
1331         synth->thread->window->update_gui();
1332         synth->send_configure_change();
1335 SynthPhaseZero::SynthPhaseZero(Synth *synth)
1336  : BC_MenuItem(_("Zero"))
1338         this->synth = synth;
1340 SynthPhaseZero::~SynthPhaseZero()
1344 int SynthPhaseZero::handle_event()
1346         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1347         {
1348                 synth->config.oscillator_config.values[i]->phase = 0;
1349         }
1351         synth->thread->window->update_gui();
1352         synth->send_configure_change();
1355 SynthPhaseSine::SynthPhaseSine(Synth *synth)
1356  : BC_MenuItem(_("Sine"))
1358         this->synth = synth;
1360 SynthPhaseSine::~SynthPhaseSine()
1364 int SynthPhaseSine::handle_event()
1366         float new_value;
1367         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1368         {
1369                 new_value = (float)i / synth->config.oscillator_config.total * 2 * M_PI;
1370                 new_value = sin(new_value) / 2 + .5;
1371                 synth->config.oscillator_config.values[i]->phase = new_value;
1372         }
1374         synth->thread->window->update_gui();
1375         synth->send_configure_change();
1378 SynthPhaseRandom::SynthPhaseRandom(Synth *synth)
1379  : BC_MenuItem(_("Random"))
1381         this->synth = synth;
1383 SynthPhaseRandom::~SynthPhaseRandom()
1387 int SynthPhaseRandom::handle_event()
1389         srand(time(0));
1390         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1391         {
1392                 synth->config.oscillator_config.values[i]->phase = 
1393                         (float)(rand() % 360) / 360;
1394         }
1396         synth->thread->window->update_gui();
1397         synth->send_configure_change();
1401 // ============================ freq calculations
1403 SynthFreqRandom::SynthFreqRandom(Synth *synth)
1404  : BC_MenuItem(_("Random"))
1406         this->synth = synth;
1408 SynthFreqRandom::~SynthFreqRandom()
1412 int SynthFreqRandom::handle_event()
1414         srand(time(0));
1415         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1416         {
1417                 synth->config.oscillator_config.values[i]->freq_factor = rand() % 100;
1418         }
1420         synth->thread->window->update_gui();
1421         synth->send_configure_change();
1424 SynthFreqEnum::SynthFreqEnum(Synth *synth)
1425  : BC_MenuItem(_("Enumerate"))
1427         this->synth = synth;
1429 SynthFreqEnum::~SynthFreqEnum()
1433 int SynthFreqEnum::handle_event()
1435         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1436         {
1437                 synth->config.oscillator_config.values[i]->freq_factor = (float)i + 1;
1438         }
1440         synth->thread->window->update_gui();
1441         synth->send_configure_change();
1444 SynthFreqEven::SynthFreqEven(Synth *synth)
1445  : BC_MenuItem(_("Even"))
1447         this->synth = synth;
1449 SynthFreqEven::~SynthFreqEven()
1453 int SynthFreqEven::handle_event()
1455         if(synth->config.oscillator_config.total)
1456                 synth->config.oscillator_config.values[0]->freq_factor = (float)1;
1458         for(int i = 1; i < synth->config.oscillator_config.total; i++)
1459         {
1460                 synth->config.oscillator_config.values[i]->freq_factor = (float)i * 2;
1461         }
1463         synth->thread->window->update_gui();
1464         synth->send_configure_change();
1467 SynthFreqOdd::SynthFreqOdd(Synth *synth)
1468  : BC_MenuItem(_("Odd"))
1469 { this->synth = synth; }
1470 SynthFreqOdd::~SynthFreqOdd()
1474 int SynthFreqOdd::handle_event()
1476         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1477         {
1478                 synth->config.oscillator_config.values[i]->freq_factor = (float)1 + i * 2;
1479         }
1481         synth->thread->window->update_gui();
1482         synth->send_configure_change();
1485 SynthFreqFibonacci::SynthFreqFibonacci(Synth *synth)
1486  : BC_MenuItem(_("Fibonnacci"))
1488         this->synth = synth; 
1490 SynthFreqFibonacci::~SynthFreqFibonacci()
1494 int SynthFreqFibonacci::handle_event()
1496         float last_value1 = 0, last_value2 = 1;
1497         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1498         {
1499                 synth->config.oscillator_config.values[i]->freq_factor = last_value1 + last_value2;
1500                 if(synth->config.oscillator_config.values[i]->freq_factor > 100) synth->config.oscillator_config.values[i]->freq_factor = 100;
1501                 last_value1 = last_value2;
1502                 last_value2 = synth->config.oscillator_config.values[i]->freq_factor;
1503         }
1505         synth->thread->window->update_gui();
1506         synth->send_configure_change();
1509 SynthFreqPrime::SynthFreqPrime(Synth *synth)
1510  : BC_MenuItem(_("Prime"))
1512         this->synth = synth; 
1514 SynthFreqPrime::~SynthFreqPrime()
1518 int SynthFreqPrime::handle_event()
1520         float number = 1;
1521         for(int i = 0; i < synth->config.oscillator_config.total; i++)
1522         {
1523                 synth->config.oscillator_config.values[i]->freq_factor = number;
1524                 number = get_next_prime(number);
1525         }
1527         synth->thread->window->update_gui();
1528         synth->send_configure_change();
1531 float SynthFreqPrime::get_next_prime(float number)
1533         int result = 1;
1534         
1535         while(result)
1536         {
1537                 result = 0;
1538                 number++;
1539                 
1540                 for(float i = number - 1; i > 1 && !result; i--)
1541                 {
1542                         if((number / i) - (int)(number / i) == 0) result = 1;
1543                 }
1544         }
1545         
1546         return number;
1556 SynthOscillatorConfig::SynthOscillatorConfig(int number)
1558         reset();
1559         this->number = number;
1562 SynthOscillatorConfig::~SynthOscillatorConfig()
1566 void SynthOscillatorConfig::reset()
1568         level = 0;
1569         phase = 0;
1570         freq_factor = 1;
1573 void SynthOscillatorConfig::load_defaults(Defaults *defaults)
1575         char string[BCTEXTLEN];
1577         sprintf(string, "LEVEL%d", number);
1578         level = defaults->get(string, (float)0);
1579         sprintf(string, "PHASE%d", number);
1580         phase = defaults->get(string, (float)0);
1581         sprintf(string, "FREQFACTOR%d", number);
1582         freq_factor = defaults->get(string, (float)1);
1585 void SynthOscillatorConfig::save_defaults(Defaults *defaults)
1587         char string[BCTEXTLEN];
1589         sprintf(string, "LEVEL%d", number);
1590         defaults->update(string, (float)level);
1591         sprintf(string, "PHASE%d", number);
1592         defaults->update(string, (float)phase);
1593         sprintf(string, "FREQFACTOR%d", number);
1594         defaults->update(string, (float)freq_factor);
1597 void SynthOscillatorConfig::read_data(FileXML *file)
1599         level = file->tag.get_property("LEVEL", (float)level);
1600         phase = file->tag.get_property("PHASE", (float)phase);
1601         freq_factor = file->tag.get_property("FREQFACTOR", (float)freq_factor);
1604 void SynthOscillatorConfig::save_data(FileXML *file)
1606         file->tag.set_title("OSCILLATOR");
1607         file->tag.set_property("LEVEL", (float)level);
1608         file->tag.set_property("PHASE", (float)phase);
1609         file->tag.set_property("FREQFACTOR", (float)freq_factor);
1610         file->append_tag();
1611         file->append_newline();
1614 int SynthOscillatorConfig::equivalent(SynthOscillatorConfig &that)
1616         if(EQUIV(level, that.level) && 
1617                 EQUIV(phase, that.phase) &&
1618                 EQUIV(freq_factor, that.freq_factor))
1619                 return 1;
1620         else
1621                 return 0;
1624 void SynthOscillatorConfig::copy_from(SynthOscillatorConfig& that)
1626         level = that.level;
1627         phase = that.phase;
1628         freq_factor = that.freq_factor;
1642 SynthConfig::SynthConfig()
1644         reset();
1647 SynthConfig::~SynthConfig()
1649         oscillator_config.remove_all_objects();
1652 void SynthConfig::reset()
1654         wetness = 0;
1655         base_freq = 440;
1656         wavefunction = SINE;
1657         for(int i = 0; i < oscillator_config.total; i++)
1658         {
1659                 oscillator_config.values[i]->reset();
1660         }
1663 int SynthConfig::equivalent(SynthConfig &that)
1665 //printf("SynthConfig::equivalent %d %d\n", base_freq, that.base_freq);
1666         if(base_freq != that.base_freq ||
1667                 wavefunction != that.wavefunction ||
1668                 oscillator_config.total != that.oscillator_config.total) return 0;
1670         for(int i = 0; i < oscillator_config.total; i++)
1671         {
1672                 if(!oscillator_config.values[i]->equivalent(*that.oscillator_config.values[i]))
1673                         return 0;
1674         }
1676         return 1;
1679 void SynthConfig::copy_from(SynthConfig& that)
1681         wetness = that.wetness;
1682         base_freq = that.base_freq;
1683         wavefunction = that.wavefunction;
1685         int i;
1686         for(i = 0; 
1687                 i < oscillator_config.total && i < that.oscillator_config.total;
1688                 i++)
1689         {
1690                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1691         }
1693         for( ;
1694                 i < that.oscillator_config.total;
1695                 i++)
1696         {
1697                 oscillator_config.append(new SynthOscillatorConfig(i));
1698                 oscillator_config.values[i]->copy_from(*that.oscillator_config.values[i]);
1699         }
1701         for( ;
1702                 i < oscillator_config.total;
1703                 i++)
1704         {
1705                 oscillator_config.remove_object();
1706         }
1709 void SynthConfig::interpolate(SynthConfig &prev, 
1710         SynthConfig &next, 
1711         int64_t prev_frame, 
1712         int64_t next_frame, 
1713         int64_t current_frame)
1715         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
1716         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
1718         copy_from(prev);
1719         wetness = (int)(prev.wetness * prev_scale + next.wetness * next_scale);
1720         base_freq = (int)(prev.base_freq * prev_scale + next.base_freq * next_scale);