r134: Heroine Virtual's release 1.1.8
[cinelerra_cv/mob.git] / hvirtual / plugins / freeverb / freeverb.C
blob4a522585fb0b2ffc34a3df0d129207c1f2840625
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.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>
20 class FreeverbEffect;
22 class FreeverbConfig
24 public:
25         FreeverbConfig();
28         int equivalent(FreeverbConfig &that);
29         void copy_from(FreeverbConfig &that);
30         void interpolate(FreeverbConfig &prev, 
31                 FreeverbConfig &next, 
32                 int64_t prev_frame, 
33                 int64_t next_frame, 
34                 int64_t current_frame);
37         float gain;
38         float roomsize;
39         float damp;
40         float wet;
41         float dry;
42         float width;
43         float mode;
47 class FreeverbGain : public BC_FPot
49 public:
50         FreeverbGain(FreeverbEffect *plugin, int x, int y);
51         int handle_event();
52         FreeverbEffect *plugin;
55 class FreeverbRoomsize : public BC_FPot
57 public:
58         FreeverbRoomsize(FreeverbEffect *plugin, int x, int y);
59         int handle_event();
60         FreeverbEffect *plugin;
63 class FreeverbDamp : public BC_FPot
65 public:
66         FreeverbDamp(FreeverbEffect *plugin, int x, int y);
67         int handle_event();
68         FreeverbEffect *plugin;
71 class FreeverbWet : public BC_FPot
73 public:
74         FreeverbWet(FreeverbEffect *plugin, int x, int y);
75         int handle_event();
76         FreeverbEffect *plugin;
79 class FreeverbDry : public BC_FPot
81 public:
82         FreeverbDry(FreeverbEffect *plugin, int x, int y);
83         int handle_event();
84         FreeverbEffect *plugin;
87 class FreeverbWidth : public BC_FPot
89 public:
90         FreeverbWidth(FreeverbEffect *plugin, int x, int y);
91         int handle_event();
92         FreeverbEffect *plugin;
95 class FreeverbMode : public BC_CheckBox
97 public:
98         FreeverbMode(FreeverbEffect *plugin, int x, int y);
99         int handle_event();
100         FreeverbEffect *plugin;
105 class FreeverbWindow : public BC_Window
107 public:
108         FreeverbWindow(FreeverbEffect *plugin, int x, int y);
109         void create_objects();
110         int close_event();
112         FreeverbEffect *plugin;
113         
114         FreeverbGain *gain;
115         FreeverbRoomsize *roomsize;
116         FreeverbDamp *damp;
117         FreeverbWet *wet;
118         FreeverbDry *dry;
119         FreeverbWidth *width;
120         FreeverbMode *mode;
123 PLUGIN_THREAD_HEADER(FreeverbEffect, FreeverbThread, FreeverbWindow)
127 class FreeverbEffect : public PluginAClient
129 public:
130         FreeverbEffect(PluginServer *server);
131         ~FreeverbEffect();
133         VFrame* new_picon();
134         char* plugin_title();
135         int show_gui();
136         void raise_window();
137         int set_string();
138         int is_realtime();
139         int is_multichannel();
140         void read_data(KeyFrame *keyframe);
141         void save_data(KeyFrame *keyframe);
142         int process_realtime(int64_t size, double **input_ptr, double **output_ptr);
147         int load_defaults();
148         int save_defaults();
149         int load_configuration();
150         void update_gui();
153         Defaults *defaults;
154         FreeverbThread *thread;
155         FreeverbConfig config;
156         revmodel *engine;
157         float **temp;
158         float **temp_out;
159         int temp_allocated;
165 REGISTER_PLUGIN(FreeverbEffect)
176 FreeverbGain::FreeverbGain(FreeverbEffect *plugin, int x, int y)
177  : BC_FPot(x, y, plugin->config.gain, INFINITYGAIN, 6)
179         this->plugin = plugin;
180         set_precision(.1);
183 int FreeverbGain::handle_event()
185         plugin->config.gain = get_value();
186         plugin->send_configure_change();
187         return 1;
190 FreeverbRoomsize::FreeverbRoomsize(FreeverbEffect *plugin, int x, int y)
191  : BC_FPot(x, y, plugin->config.roomsize, INFINITYGAIN, 0)
193         this->plugin = plugin;
194         set_precision(.01);
197 int FreeverbRoomsize::handle_event()
199         plugin->config.roomsize = get_value();
200         plugin->send_configure_change();
201         return 1;
204 FreeverbDamp::FreeverbDamp(FreeverbEffect *plugin, int x, int y)
205  : BC_FPot(x, y, plugin->config.damp, INFINITYGAIN, 0)
207         this->plugin = plugin;
208         set_precision(.01);
211 int FreeverbDamp::handle_event()
213         plugin->config.damp = get_value();
214         plugin->send_configure_change();
215         return 1;
218 FreeverbWet::FreeverbWet(FreeverbEffect *plugin, int x, int y)
219  : BC_FPot(x, y, plugin->config.wet, INFINITYGAIN, 0)
221         this->plugin = plugin;
222         set_precision(.01);
225 int FreeverbWet::handle_event()
227         plugin->config.wet = get_value();
228         plugin->send_configure_change();
229         return 1;
232 FreeverbDry::FreeverbDry(FreeverbEffect *plugin, int x, int y)
233  : BC_FPot(x, y, plugin->config.dry, INFINITYGAIN, 0)
235         this->plugin = plugin;
236         set_precision(.01);
239 int FreeverbDry::handle_event()
241         plugin->config.dry = get_value();
242         plugin->send_configure_change();
243         return 1;
246 FreeverbWidth::FreeverbWidth(FreeverbEffect *plugin, int x, int y)
247  : BC_FPot(x, y, plugin->config.width, INFINITYGAIN, 0)
249         this->plugin = plugin;
250         set_precision(.01);
253 int FreeverbWidth::handle_event()
255         plugin->config.width = get_value();
256         plugin->send_configure_change();
257         return 1;
260 FreeverbMode::FreeverbMode(FreeverbEffect *plugin, int x, int y)
261  : BC_CheckBox(x, y, (int)plugin->config.mode, "Freeze")
263         this->plugin = plugin;
266 int FreeverbMode::handle_event()
268         plugin->config.mode = get_value();
269         plugin->send_configure_change();
270         return 1;
283 FreeverbWindow::FreeverbWindow(FreeverbEffect *plugin, int x, int y)
284  : BC_Window(plugin->gui_string, 
285         x, 
286         y, 
287         180, 
288         250, 
289         180, 
290         250,
291         0, 
292         0,
293         1)
295         this->plugin = plugin;
298 void FreeverbWindow::create_objects()
300         int x1 = 10, x2 = 100, x3 = 135, y1 = 10, y2 = 20, margin = 30;
302         add_subwindow(new BC_Title(x1, y2, "Gain:"));
303         add_subwindow(gain = new FreeverbGain(plugin, x3, y1));
304         y1 += margin;
305         y2 += margin;
306         add_subwindow(new BC_Title(x1, y2, "Roomsize:"));
307         add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
308         y1 += margin;
309         y2 += margin;
310         add_subwindow(new BC_Title(x1, y2, "Damp:"));
311         add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
312         y1 += margin;
313         y2 += margin;
314         add_subwindow(new BC_Title(x1, y2, "Wet:"));
315         add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
316         y1 += margin;
317         y2 += margin;
318         add_subwindow(new BC_Title(x1, y2, "Dry:"));
319         add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
320         y1 += margin;
321         y2 += margin;
322         add_subwindow(new BC_Title(x1, y2, "Width:"));
323         add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
324         y1 += margin;
325         y2 += margin;
326         add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
327         show_window();
328         flush();
331 int FreeverbWindow::close_event()
333 // Set result to 1 to indicate a client side close
334         set_done(1);
335         return 1;
349 FreeverbConfig::FreeverbConfig()
351         gain = -6.0;
352         wet = -6.0;
353         dry = 0;
354         roomsize = -6.0;
355         damp = 0;
356         width = 0;
357         mode = 0;
360 int FreeverbConfig::equivalent(FreeverbConfig &that)
362         return EQUIV(gain, that.gain) &&
363                 EQUIV(wet, that.wet) &&
364                 EQUIV(roomsize, that.roomsize) &&
365                 EQUIV(dry, that.dry) &&
366                 EQUIV(damp, that.damp) &&
367                 EQUIV(width, that.width) &&
368                 EQUIV(mode, that.mode);
371 void FreeverbConfig::copy_from(FreeverbConfig &that)
373         gain = that.gain;
374         wet = that.wet;
375         roomsize = that.roomsize;
376         dry = that.dry;
377         damp = that.damp;
378         width = that.width;
379         mode = that.mode;
382 void FreeverbConfig::interpolate(FreeverbConfig &prev, 
383         FreeverbConfig &next, 
384         int64_t prev_frame, 
385         int64_t next_frame, 
386         int64_t current_frame)
388         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
389         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
391         gain = prev.gain * prev_scale + next.gain * next_scale;
392         wet = prev.wet * prev_scale + next.wet * next_scale;
393         roomsize = prev.roomsize * prev_scale + next.roomsize * next_scale;
394         dry = prev.dry * prev_scale + next.dry * next_scale;
395         damp = prev.damp * prev_scale + next.damp * next_scale;
396         width = prev.width * prev_scale + next.width * next_scale;
397         mode = prev.mode;
423 PLUGIN_THREAD_OBJECT(FreeverbEffect, FreeverbThread, FreeverbWindow)
429 FreeverbEffect::FreeverbEffect(PluginServer *server)
430  : PluginAClient(server)
432         engine = 0;
433         temp = 0;
434         temp_out = 0;
435         temp_allocated = 0;
436         PLUGIN_CONSTRUCTOR_MACRO
439 FreeverbEffect::~FreeverbEffect()
441         if(engine) delete engine;
442         if(temp)
443         {
444                 for(int i = 0; i < total_in_buffers; i++)
445                 {
446                         delete [] temp[i];
447                         delete [] temp_out[i];
448                 }
449                 delete [] temp;
450                 delete [] temp_out;
451         }
452         PLUGIN_DESTRUCTOR_MACRO
455 NEW_PICON_MACRO(FreeverbEffect)
457 LOAD_CONFIGURATION_MACRO(FreeverbEffect, FreeverbConfig)
459 SHOW_GUI_MACRO(FreeverbEffect, FreeverbThread)
461 RAISE_WINDOW_MACRO(FreeverbEffect)
463 SET_STRING_MACRO(FreeverbEffect)
466 char* FreeverbEffect::plugin_title()
468         return "Freeverb";
472 int FreeverbEffect::is_realtime()
474         return 1;
477 int FreeverbEffect::is_multichannel()
479         return 1;
484 void FreeverbEffect::read_data(KeyFrame *keyframe)
486         FileXML input;
487         input.set_shared_string(keyframe->data, strlen(keyframe->data));
489         int result = 0;
490         while(!result)
491         {
492                 result = input.read_tag();
494                 if(!result)
495                 {
496                         if(input.tag.title_is("FREEVERB"))
497                         {
498                                 config.gain = input.tag.get_property("GAIN", config.gain);
499                                 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
500                                 config.damp = input.tag.get_property("DAMP", config.damp);
501                                 config.wet = input.tag.get_property("WET", config.wet);
502                                 config.dry = input.tag.get_property("DRY", config.dry);
503                                 config.width = input.tag.get_property("WIDTH", config.width);
504                                 config.mode = input.tag.get_property("MODE", config.mode);
505                         }
506                 }
507         }
510 void FreeverbEffect::save_data(KeyFrame *keyframe)
512         FileXML output;
513         output.set_shared_string(keyframe->data, MESSAGESIZE);
515         output.tag.set_title("FREEVERB");
516         output.tag.set_property("GAIN", config.gain);
517         output.tag.set_property("ROOMSIZE", config.roomsize);
518         output.tag.set_property("DAMP", config.damp);
519         output.tag.set_property("WET", config.wet);
520         output.tag.set_property("DRY", config.dry);
521         output.tag.set_property("WIDTH", config.width);
522         output.tag.set_property("MODE", config.mode);
523         output.append_tag();
524         output.append_newline();
526         output.terminate_string();
529 int FreeverbEffect::load_defaults()
531         char directory[BCTEXTLEN], string[BCTEXTLEN];
532         sprintf(directory, "%sfreeverb.rc", BCASTDIR);
533         defaults = new Defaults(directory);
534         defaults->load();
536         config.gain = defaults->get("GAIN", config.gain);
537         config.roomsize = defaults->get("ROOMSIZE", config.roomsize);
538         config.damp = defaults->get("DAMP", config.damp);
539         config.wet = defaults->get("WET", config.wet);
540         config.dry = defaults->get("DRY", config.dry);
541         config.width = defaults->get("WIDTH", config.width);
542         config.mode = defaults->get("MODE", config.mode);
543         return 0;
546 int FreeverbEffect::save_defaults()
548         char string[BCTEXTLEN];
550         defaults->update("GAIN", config.gain);
551         defaults->update("ROOMSIZE", config.roomsize);
552         defaults->update("DAMP", config.damp);
553         defaults->update("WET", config.wet);
554         defaults->update("DRY", config.dry);
555         defaults->update("WIDTH", config.width);
556         defaults->update("MODE", config.mode);
557         defaults->save();
559         return 0;
563 void FreeverbEffect::update_gui()
565         if(thread)
566         {
567                 load_configuration();
568                 thread->window->lock_window();
569                 thread->window->gain->update(config.gain);
570                 thread->window->roomsize->update(config.roomsize);
571                 thread->window->damp->update(config.damp);
572                 thread->window->wet->update(config.wet);
573                 thread->window->dry->update(config.dry);
574                 thread->window->width->update(config.width);
575                 thread->window->mode->update((int)config.mode);
576                 thread->window->unlock_window();
577         }
580 int FreeverbEffect::process_realtime(int64_t size, double **input_ptr, double **output_ptr)
582         load_configuration();
583         if(!engine) engine = new revmodel;
585         engine->setroomsize(DB::fromdb(config.roomsize));
586         engine->setdamp(DB::fromdb(config.damp));
587         engine->setwet(DB::fromdb(config.wet));
588         engine->setdry(DB::fromdb(config.dry));
589         engine->setwidth(DB::fromdb(config.width));
590         engine->setmode(config.mode);
592         float gain_f = DB::fromdb(config.gain);
594         if(size > temp_allocated)
595         {
596                 if(temp)
597                 {
598                         for(int i = 0; i < total_in_buffers; i++)
599                         {
600                                 delete [] temp[i];
601                                 delete [] temp_out[i];
602                         }
603                         delete [] temp;
604                         delete [] temp_out;
605                 }
606                 temp = 0;
607                 temp_out = 0;
608         }
609         if(!temp)
610         {
611                 temp_allocated = size * 2;
612                 temp = new float*[total_in_buffers];
613                 temp_out = new float*[total_in_buffers];
614                 for(int i = 0; i < total_in_buffers; i++)
615                 {
616                         temp[i] = new float[temp_allocated];
617                         temp_out[i] = new float[temp_allocated];
618                 }
619         }
621         for(int i = 0; i < 2 && i < total_in_buffers; i++)
622         {
623                 float *out = temp[i];
624                 double *in = input_ptr[i];
625                 for(int j = 0; j < size; j++)
626                 {
627                         out[j] = in[j];
628                 }
629         }
631         if(total_in_buffers < 2)
632         {
633                 engine->processreplace(temp[0], 
634                         temp[0], 
635                         temp_out[0], 
636                         temp_out[0], 
637                         size, 
638                         1);
639         }
640         else
641         {
642                 engine->processreplace(temp[0], 
643                         temp[1], 
644                         temp_out[0], 
645                         temp_out[1], 
646                         size, 
647                         1);
648         }
650         for(int i = 0; i < 2 && i < total_in_buffers; i++)
651         {
652                 double *out = output_ptr[i];
653                 float *in = temp_out[i];
654                 for(int j = 0; j < size; j++)
655                 {
656                         out[j] = gain_f * in[j];
657                 }
658         }
660         return 0;