r1009: Move the dependencies to newer package names
[cinelerra_cv/mob.git] / plugins / freeverb / freeverb.C
blob73f042896963629b4a451e85c51f32d750aabda5
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "bchash.h"
4 #include "guicast.h"
5 #include "filexml.h"
6 #include "picon_png.h"
7 #include "pluginaclient.h"
8 #include "revmodel.hpp"
9 #include "units.h"
10 #include "vframe.h"
12 #include <math.h>
13 #include <string.h>
15 #include <libintl.h>
16 #define _(String) gettext(String)
17 #define gettext_noop(String) String
18 #define N_(String) gettext_noop (String)
25 class FreeverbEffect;
27 class FreeverbConfig
29 public:
30         FreeverbConfig();
33         int equivalent(FreeverbConfig &that);
34         void copy_from(FreeverbConfig &that);
35         void interpolate(FreeverbConfig &prev, 
36                 FreeverbConfig &next, 
37                 int64_t prev_frame, 
38                 int64_t next_frame, 
39                 int64_t current_frame);
42         float gain;
43         float roomsize;
44         float damp;
45         float wet;
46         float dry;
47         float width;
48         float mode;
52 class FreeverbGain : public BC_FPot
54 public:
55         FreeverbGain(FreeverbEffect *plugin, int x, int y);
56         int handle_event();
57         FreeverbEffect *plugin;
60 class FreeverbRoomsize : public BC_FPot
62 public:
63         FreeverbRoomsize(FreeverbEffect *plugin, int x, int y);
64         int handle_event();
65         FreeverbEffect *plugin;
68 class FreeverbDamp : public BC_FPot
70 public:
71         FreeverbDamp(FreeverbEffect *plugin, int x, int y);
72         int handle_event();
73         FreeverbEffect *plugin;
76 class FreeverbWet : public BC_FPot
78 public:
79         FreeverbWet(FreeverbEffect *plugin, int x, int y);
80         int handle_event();
81         FreeverbEffect *plugin;
84 class FreeverbDry : public BC_FPot
86 public:
87         FreeverbDry(FreeverbEffect *plugin, int x, int y);
88         int handle_event();
89         FreeverbEffect *plugin;
92 class FreeverbWidth : public BC_FPot
94 public:
95         FreeverbWidth(FreeverbEffect *plugin, int x, int y);
96         int handle_event();
97         FreeverbEffect *plugin;
100 class FreeverbMode : public BC_CheckBox
102 public:
103         FreeverbMode(FreeverbEffect *plugin, int x, int y);
104         int handle_event();
105         FreeverbEffect *plugin;
110 class FreeverbWindow : public BC_Window
112 public:
113         FreeverbWindow(FreeverbEffect *plugin, int x, int y);
114         void create_objects();
115         int close_event();
117         FreeverbEffect *plugin;
118         
119         FreeverbGain *gain;
120         FreeverbRoomsize *roomsize;
121         FreeverbDamp *damp;
122         FreeverbWet *wet;
123         FreeverbDry *dry;
124         FreeverbWidth *width;
125         FreeverbMode *mode;
128 PLUGIN_THREAD_HEADER(FreeverbEffect, FreeverbThread, FreeverbWindow)
132 class FreeverbEffect : public PluginAClient
134 public:
135         FreeverbEffect(PluginServer *server);
136         ~FreeverbEffect();
138         VFrame* new_picon();
139         char* plugin_title();
140         int show_gui();
141         void raise_window();
142         int set_string();
143         int is_realtime();
144         int is_multichannel();
145         void read_data(KeyFrame *keyframe);
146         void save_data(KeyFrame *keyframe);
147         int process_realtime(int64_t size, double **input_ptr, double **output_ptr);
152         int load_defaults();
153         int save_defaults();
154         int load_configuration();
155         void update_gui();
158         BC_Hash *defaults;
159         FreeverbThread *thread;
160         FreeverbConfig config;
161         revmodel *engine;
162         float **temp;
163         float **temp_out;
164         int temp_allocated;
170 REGISTER_PLUGIN(FreeverbEffect)
181 FreeverbGain::FreeverbGain(FreeverbEffect *plugin, int x, int y)
182  : BC_FPot(x, y, plugin->config.gain, INFINITYGAIN, 6)
184         this->plugin = plugin;
185         set_precision(.1);
188 int FreeverbGain::handle_event()
190         plugin->config.gain = get_value();
191         plugin->send_configure_change();
192         return 1;
195 FreeverbRoomsize::FreeverbRoomsize(FreeverbEffect *plugin, int x, int y)
196  : BC_FPot(x, y, plugin->config.roomsize, INFINITYGAIN, 0)
198         this->plugin = plugin;
199         set_precision(.01);
202 int FreeverbRoomsize::handle_event()
204         plugin->config.roomsize = get_value();
205         plugin->send_configure_change();
206         return 1;
209 FreeverbDamp::FreeverbDamp(FreeverbEffect *plugin, int x, int y)
210  : BC_FPot(x, y, plugin->config.damp, INFINITYGAIN, 0)
212         this->plugin = plugin;
213         set_precision(.01);
216 int FreeverbDamp::handle_event()
218         plugin->config.damp = get_value();
219         plugin->send_configure_change();
220         return 1;
223 FreeverbWet::FreeverbWet(FreeverbEffect *plugin, int x, int y)
224  : BC_FPot(x, y, plugin->config.wet, INFINITYGAIN, 0)
226         this->plugin = plugin;
227         set_precision(.01);
230 int FreeverbWet::handle_event()
232         plugin->config.wet = get_value();
233         plugin->send_configure_change();
234         return 1;
237 FreeverbDry::FreeverbDry(FreeverbEffect *plugin, int x, int y)
238  : BC_FPot(x, y, plugin->config.dry, INFINITYGAIN, 0)
240         this->plugin = plugin;
241         set_precision(.01);
244 int FreeverbDry::handle_event()
246         plugin->config.dry = get_value();
247         plugin->send_configure_change();
248         return 1;
251 FreeverbWidth::FreeverbWidth(FreeverbEffect *plugin, int x, int y)
252  : BC_FPot(x, y, plugin->config.width, INFINITYGAIN, 0)
254         this->plugin = plugin;
255         set_precision(.01);
258 int FreeverbWidth::handle_event()
260         plugin->config.width = get_value();
261         plugin->send_configure_change();
262         return 1;
265 FreeverbMode::FreeverbMode(FreeverbEffect *plugin, int x, int y)
266  : BC_CheckBox(x, y, (int)plugin->config.mode, _("Freeze"))
268         this->plugin = plugin;
271 int FreeverbMode::handle_event()
273         plugin->config.mode = get_value();
274         plugin->send_configure_change();
275         return 1;
288 FreeverbWindow::FreeverbWindow(FreeverbEffect *plugin, int x, int y)
289  : BC_Window(plugin->gui_string, 
290         x, 
291         y, 
292         180, 
293         250, 
294         180, 
295         250,
296         0, 
297         0,
298         1)
300         this->plugin = plugin;
303 void FreeverbWindow::create_objects()
305         int x1 = 10, x2 = 100, x3 = 135, y1 = 10, y2 = 20, margin = 30;
307         add_subwindow(new BC_Title(x1, y2, _("Gain:")));
308         add_subwindow(gain = new FreeverbGain(plugin, x3, y1));
309         y1 += margin;
310         y2 += margin;
311         add_subwindow(new BC_Title(x1, y2, _("Roomsize:")));
312         add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
313         y1 += margin;
314         y2 += margin;
315         add_subwindow(new BC_Title(x1, y2, _("Damp:")));
316         add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
317         y1 += margin;
318         y2 += margin;
319         add_subwindow(new BC_Title(x1, y2, _("Wet:")));
320         add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
321         y1 += margin;
322         y2 += margin;
323         add_subwindow(new BC_Title(x1, y2, _("Dry:")));
324         add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
325         y1 += margin;
326         y2 += margin;
327         add_subwindow(new BC_Title(x1, y2, _("Width:")));
328         add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
329         y1 += margin;
330         y2 += margin;
331         add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
332         show_window();
333         flush();
336 int FreeverbWindow::close_event()
338 // Set result to 1 to indicate a client side close
339         set_done(1);
340         return 1;
354 FreeverbConfig::FreeverbConfig()
356         gain = -6.0;
357         wet = -6.0;
358         dry = 0;
359         roomsize = -6.0;
360         damp = 0;
361         width = 0;
362         mode = 0;
365 int FreeverbConfig::equivalent(FreeverbConfig &that)
367         return EQUIV(gain, that.gain) &&
368                 EQUIV(wet, that.wet) &&
369                 EQUIV(roomsize, that.roomsize) &&
370                 EQUIV(dry, that.dry) &&
371                 EQUIV(damp, that.damp) &&
372                 EQUIV(width, that.width) &&
373                 EQUIV(mode, that.mode);
376 void FreeverbConfig::copy_from(FreeverbConfig &that)
378         gain = that.gain;
379         wet = that.wet;
380         roomsize = that.roomsize;
381         dry = that.dry;
382         damp = that.damp;
383         width = that.width;
384         mode = that.mode;
387 void FreeverbConfig::interpolate(FreeverbConfig &prev, 
388         FreeverbConfig &next, 
389         int64_t prev_frame, 
390         int64_t next_frame, 
391         int64_t current_frame)
393         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
394         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
396         gain = prev.gain * prev_scale + next.gain * next_scale;
397         wet = prev.wet * prev_scale + next.wet * next_scale;
398         roomsize = prev.roomsize * prev_scale + next.roomsize * next_scale;
399         dry = prev.dry * prev_scale + next.dry * next_scale;
400         damp = prev.damp * prev_scale + next.damp * next_scale;
401         width = prev.width * prev_scale + next.width * next_scale;
402         mode = prev.mode;
428 PLUGIN_THREAD_OBJECT(FreeverbEffect, FreeverbThread, FreeverbWindow)
434 FreeverbEffect::FreeverbEffect(PluginServer *server)
435  : PluginAClient(server)
437         engine = 0;
438         temp = 0;
439         temp_out = 0;
440         temp_allocated = 0;
441         PLUGIN_CONSTRUCTOR_MACRO
444 FreeverbEffect::~FreeverbEffect()
446         if(engine) delete engine;
447         if(temp)
448         {
449                 for(int i = 0; i < total_in_buffers; i++)
450                 {
451                         delete [] temp[i];
452                         delete [] temp_out[i];
453                 }
454                 delete [] temp;
455                 delete [] temp_out;
456         }
457         PLUGIN_DESTRUCTOR_MACRO
460 NEW_PICON_MACRO(FreeverbEffect)
462 LOAD_CONFIGURATION_MACRO(FreeverbEffect, FreeverbConfig)
464 SHOW_GUI_MACRO(FreeverbEffect, FreeverbThread)
466 RAISE_WINDOW_MACRO(FreeverbEffect)
468 SET_STRING_MACRO(FreeverbEffect)
471 char* FreeverbEffect::plugin_title() { return N_("Freeverb"); }
472 int FreeverbEffect::is_realtime() { return 1; }
473 int FreeverbEffect::is_multichannel() { return 1; }
477 void FreeverbEffect::read_data(KeyFrame *keyframe)
479         FileXML input;
480         input.set_shared_string(keyframe->data, strlen(keyframe->data));
482         int result = 0;
483         while(!result)
484         {
485                 result = input.read_tag();
487                 if(!result)
488                 {
489                         if(input.tag.title_is("FREEVERB"))
490                         {
491                                 config.gain = input.tag.get_property("GAIN", config.gain);
492                                 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
493                                 config.damp = input.tag.get_property("DAMP", config.damp);
494                                 config.wet = input.tag.get_property("WET", config.wet);
495                                 config.dry = input.tag.get_property("DRY", config.dry);
496                                 config.width = input.tag.get_property("WIDTH", config.width);
497                                 config.mode = input.tag.get_property("MODE", config.mode);
498                         }
499                 }
500         }
503 void FreeverbEffect::save_data(KeyFrame *keyframe)
505         FileXML output;
506         output.set_shared_string(keyframe->data, MESSAGESIZE);
508         output.tag.set_title("FREEVERB");
509         output.tag.set_property("GAIN", config.gain);
510         output.tag.set_property("ROOMSIZE", config.roomsize);
511         output.tag.set_property("DAMP", config.damp);
512         output.tag.set_property("WET", config.wet);
513         output.tag.set_property("DRY", config.dry);
514         output.tag.set_property("WIDTH", config.width);
515         output.tag.set_property("MODE", config.mode);
516         output.append_tag();
517         output.append_newline();
519         output.terminate_string();
522 int FreeverbEffect::load_defaults()
524         char directory[BCTEXTLEN], string[BCTEXTLEN];
525         sprintf(directory, "%sfreeverb.rc", BCASTDIR);
526         defaults = new BC_Hash(directory);
527         defaults->load();
529         config.gain = defaults->get("GAIN", config.gain);
530         config.roomsize = defaults->get("ROOMSIZE", config.roomsize);
531         config.damp = defaults->get("DAMP", config.damp);
532         config.wet = defaults->get("WET", config.wet);
533         config.dry = defaults->get("DRY", config.dry);
534         config.width = defaults->get("WIDTH", config.width);
535         config.mode = defaults->get("MODE", config.mode);
536         return 0;
539 int FreeverbEffect::save_defaults()
541         char string[BCTEXTLEN];
543         defaults->update("GAIN", config.gain);
544         defaults->update("ROOMSIZE", config.roomsize);
545         defaults->update("DAMP", config.damp);
546         defaults->update("WET", config.wet);
547         defaults->update("DRY", config.dry);
548         defaults->update("WIDTH", config.width);
549         defaults->update("MODE", config.mode);
550         defaults->save();
552         return 0;
556 void FreeverbEffect::update_gui()
558         if(thread)
559         {
560                 load_configuration();
561                 thread->window->lock_window();
562                 thread->window->gain->update(config.gain);
563                 thread->window->roomsize->update(config.roomsize);
564                 thread->window->damp->update(config.damp);
565                 thread->window->wet->update(config.wet);
566                 thread->window->dry->update(config.dry);
567                 thread->window->width->update(config.width);
568                 thread->window->mode->update((int)config.mode);
569                 thread->window->unlock_window();
570         }
573 int FreeverbEffect::process_realtime(int64_t size, double **input_ptr, double **output_ptr)
575         load_configuration();
576         if(!engine) engine = new revmodel;
578         engine->setroomsize(DB::fromdb(config.roomsize));
579         engine->setdamp(DB::fromdb(config.damp));
580         engine->setwet(DB::fromdb(config.wet));
581         engine->setdry(DB::fromdb(config.dry));
582         engine->setwidth(DB::fromdb(config.width));
583         engine->setmode(config.mode);
585         float gain_f = DB::fromdb(config.gain);
587         if(size > temp_allocated)
588         {
589                 if(temp)
590                 {
591                         for(int i = 0; i < total_in_buffers; i++)
592                         {
593                                 delete [] temp[i];
594                                 delete [] temp_out[i];
595                         }
596                         delete [] temp;
597                         delete [] temp_out;
598                 }
599                 temp = 0;
600                 temp_out = 0;
601         }
602         if(!temp)
603         {
604                 temp_allocated = size * 2;
605                 temp = new float*[total_in_buffers];
606                 temp_out = new float*[total_in_buffers];
607                 for(int i = 0; i < total_in_buffers; i++)
608                 {
609                         temp[i] = new float[temp_allocated];
610                         temp_out[i] = new float[temp_allocated];
611                 }
612         }
614         for(int i = 0; i < 2 && i < total_in_buffers; i++)
615         {
616                 float *out = temp[i];
617                 double *in = input_ptr[i];
618                 for(int j = 0; j < size; j++)
619                 {
620                         out[j] = in[j];
621                 }
622         }
624         if(total_in_buffers < 2)
625         {
626                 engine->processreplace(temp[0], 
627                         temp[0], 
628                         temp_out[0], 
629                         temp_out[0], 
630                         size, 
631                         1);
632         }
633         else
634         {
635                 engine->processreplace(temp[0], 
636                         temp[1], 
637                         temp_out[0], 
638                         temp_out[1], 
639                         size, 
640                         1);
641         }
643         for(int i = 0; i < 2 && i < total_in_buffers; i++)
644         {
645                 double *out = output_ptr[i];
646                 float *in = temp_out[i];
647                 for(int j = 0; j < size; j++)
648                 {
649                         out[j] = gain_f * in[j];
650                 }
651         }
653         return 0;