r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / freeverb / freeverb.C
blob9d0a90b9aeebf61805e039af832dfebb115e36ad
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>
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         Defaults *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()
473         return _("Freeverb");
477 int FreeverbEffect::is_realtime()
479         return 1;
482 int FreeverbEffect::is_multichannel()
484         return 1;
489 void FreeverbEffect::read_data(KeyFrame *keyframe)
491         FileXML input;
492         input.set_shared_string(keyframe->data, strlen(keyframe->data));
494         int result = 0;
495         while(!result)
496         {
497                 result = input.read_tag();
499                 if(!result)
500                 {
501                         if(input.tag.title_is("FREEVERB"))
502                         {
503                                 config.gain = input.tag.get_property("GAIN", config.gain);
504                                 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
505                                 config.damp = input.tag.get_property("DAMP", config.damp);
506                                 config.wet = input.tag.get_property("WET", config.wet);
507                                 config.dry = input.tag.get_property("DRY", config.dry);
508                                 config.width = input.tag.get_property("WIDTH", config.width);
509                                 config.mode = input.tag.get_property("MODE", config.mode);
510                         }
511                 }
512         }
515 void FreeverbEffect::save_data(KeyFrame *keyframe)
517         FileXML output;
518         output.set_shared_string(keyframe->data, MESSAGESIZE);
520         output.tag.set_title("FREEVERB");
521         output.tag.set_property("GAIN", config.gain);
522         output.tag.set_property("ROOMSIZE", config.roomsize);
523         output.tag.set_property("DAMP", config.damp);
524         output.tag.set_property("WET", config.wet);
525         output.tag.set_property("DRY", config.dry);
526         output.tag.set_property("WIDTH", config.width);
527         output.tag.set_property("MODE", config.mode);
528         output.append_tag();
529         output.append_newline();
531         output.terminate_string();
534 int FreeverbEffect::load_defaults()
536         char directory[BCTEXTLEN], string[BCTEXTLEN];
537         sprintf(directory, "%sfreeverb.rc", BCASTDIR);
538         defaults = new Defaults(directory);
539         defaults->load();
541         config.gain = defaults->get("GAIN", config.gain);
542         config.roomsize = defaults->get("ROOMSIZE", config.roomsize);
543         config.damp = defaults->get("DAMP", config.damp);
544         config.wet = defaults->get("WET", config.wet);
545         config.dry = defaults->get("DRY", config.dry);
546         config.width = defaults->get("WIDTH", config.width);
547         config.mode = defaults->get("MODE", config.mode);
548         return 0;
551 int FreeverbEffect::save_defaults()
553         char string[BCTEXTLEN];
555         defaults->update("GAIN", config.gain);
556         defaults->update("ROOMSIZE", config.roomsize);
557         defaults->update("DAMP", config.damp);
558         defaults->update("WET", config.wet);
559         defaults->update("DRY", config.dry);
560         defaults->update("WIDTH", config.width);
561         defaults->update("MODE", config.mode);
562         defaults->save();
564         return 0;
568 void FreeverbEffect::update_gui()
570         if(thread)
571         {
572                 load_configuration();
573                 thread->window->lock_window();
574                 thread->window->gain->update(config.gain);
575                 thread->window->roomsize->update(config.roomsize);
576                 thread->window->damp->update(config.damp);
577                 thread->window->wet->update(config.wet);
578                 thread->window->dry->update(config.dry);
579                 thread->window->width->update(config.width);
580                 thread->window->mode->update((int)config.mode);
581                 thread->window->unlock_window();
582         }
585 int FreeverbEffect::process_realtime(int64_t size, double **input_ptr, double **output_ptr)
587         load_configuration();
588         if(!engine) engine = new revmodel;
590         engine->setroomsize(DB::fromdb(config.roomsize));
591         engine->setdamp(DB::fromdb(config.damp));
592         engine->setwet(DB::fromdb(config.wet));
593         engine->setdry(DB::fromdb(config.dry));
594         engine->setwidth(DB::fromdb(config.width));
595         engine->setmode(config.mode);
597         float gain_f = DB::fromdb(config.gain);
599         if(size > temp_allocated)
600         {
601                 if(temp)
602                 {
603                         for(int i = 0; i < total_in_buffers; i++)
604                         {
605                                 delete [] temp[i];
606                                 delete [] temp_out[i];
607                         }
608                         delete [] temp;
609                         delete [] temp_out;
610                 }
611                 temp = 0;
612                 temp_out = 0;
613         }
614         if(!temp)
615         {
616                 temp_allocated = size * 2;
617                 temp = new float*[total_in_buffers];
618                 temp_out = new float*[total_in_buffers];
619                 for(int i = 0; i < total_in_buffers; i++)
620                 {
621                         temp[i] = new float[temp_allocated];
622                         temp_out[i] = new float[temp_allocated];
623                 }
624         }
626         for(int i = 0; i < 2 && i < total_in_buffers; i++)
627         {
628                 float *out = temp[i];
629                 double *in = input_ptr[i];
630                 for(int j = 0; j < size; j++)
631                 {
632                         out[j] = in[j];
633                 }
634         }
636         if(total_in_buffers < 2)
637         {
638                 engine->processreplace(temp[0], 
639                         temp[0], 
640                         temp_out[0], 
641                         temp_out[0], 
642                         size, 
643                         1);
644         }
645         else
646         {
647                 engine->processreplace(temp[0], 
648                         temp[1], 
649                         temp_out[0], 
650                         temp_out[1], 
651                         size, 
652                         1);
653         }
655         for(int i = 0; i < 2 && i < total_in_buffers; i++)
656         {
657                 double *out = output_ptr[i];
658                 float *in = temp_out[i];
659                 for(int j = 0; j < size; j++)
660                 {
661                         out[j] = gain_f * in[j];
662                 }
663         }
665         return 0;