1 #include "bcdisplayinfo.h"
7 #include "pluginaclient.h"
8 #include "revmodel.hpp"
16 #define _(String) gettext(String)
17 #define gettext_noop(String) String
18 #define N_(String) gettext_noop (String)
33 int equivalent(FreeverbConfig &that);
34 void copy_from(FreeverbConfig &that);
35 void interpolate(FreeverbConfig &prev,
39 int64_t current_frame);
52 class FreeverbGain : public BC_FPot
55 FreeverbGain(FreeverbEffect *plugin, int x, int y);
57 FreeverbEffect *plugin;
60 class FreeverbRoomsize : public BC_FPot
63 FreeverbRoomsize(FreeverbEffect *plugin, int x, int y);
65 FreeverbEffect *plugin;
68 class FreeverbDamp : public BC_FPot
71 FreeverbDamp(FreeverbEffect *plugin, int x, int y);
73 FreeverbEffect *plugin;
76 class FreeverbWet : public BC_FPot
79 FreeverbWet(FreeverbEffect *plugin, int x, int y);
81 FreeverbEffect *plugin;
84 class FreeverbDry : public BC_FPot
87 FreeverbDry(FreeverbEffect *plugin, int x, int y);
89 FreeverbEffect *plugin;
92 class FreeverbWidth : public BC_FPot
95 FreeverbWidth(FreeverbEffect *plugin, int x, int y);
97 FreeverbEffect *plugin;
100 class FreeverbMode : public BC_CheckBox
103 FreeverbMode(FreeverbEffect *plugin, int x, int y);
105 FreeverbEffect *plugin;
110 class FreeverbWindow : public BC_Window
113 FreeverbWindow(FreeverbEffect *plugin, int x, int y);
114 void create_objects();
117 FreeverbEffect *plugin;
120 FreeverbRoomsize *roomsize;
124 FreeverbWidth *width;
128 PLUGIN_THREAD_HEADER(FreeverbEffect, FreeverbThread, FreeverbWindow)
132 class FreeverbEffect : public PluginAClient
135 FreeverbEffect(PluginServer *server);
139 char* plugin_title();
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);
154 int load_configuration();
159 FreeverbThread *thread;
160 FreeverbConfig config;
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;
188 int FreeverbGain::handle_event()
190 plugin->config.gain = get_value();
191 plugin->send_configure_change();
195 FreeverbRoomsize::FreeverbRoomsize(FreeverbEffect *plugin, int x, int y)
196 : BC_FPot(x, y, plugin->config.roomsize, INFINITYGAIN, 0)
198 this->plugin = plugin;
202 int FreeverbRoomsize::handle_event()
204 plugin->config.roomsize = get_value();
205 plugin->send_configure_change();
209 FreeverbDamp::FreeverbDamp(FreeverbEffect *plugin, int x, int y)
210 : BC_FPot(x, y, plugin->config.damp, INFINITYGAIN, 0)
212 this->plugin = plugin;
216 int FreeverbDamp::handle_event()
218 plugin->config.damp = get_value();
219 plugin->send_configure_change();
223 FreeverbWet::FreeverbWet(FreeverbEffect *plugin, int x, int y)
224 : BC_FPot(x, y, plugin->config.wet, INFINITYGAIN, 0)
226 this->plugin = plugin;
230 int FreeverbWet::handle_event()
232 plugin->config.wet = get_value();
233 plugin->send_configure_change();
237 FreeverbDry::FreeverbDry(FreeverbEffect *plugin, int x, int y)
238 : BC_FPot(x, y, plugin->config.dry, INFINITYGAIN, 0)
240 this->plugin = plugin;
244 int FreeverbDry::handle_event()
246 plugin->config.dry = get_value();
247 plugin->send_configure_change();
251 FreeverbWidth::FreeverbWidth(FreeverbEffect *plugin, int x, int y)
252 : BC_FPot(x, y, plugin->config.width, INFINITYGAIN, 0)
254 this->plugin = plugin;
258 int FreeverbWidth::handle_event()
260 plugin->config.width = get_value();
261 plugin->send_configure_change();
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();
288 FreeverbWindow::FreeverbWindow(FreeverbEffect *plugin, int x, int y)
289 : BC_Window(plugin->gui_string,
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));
311 add_subwindow(new BC_Title(x1, y2, _("Roomsize:")));
312 add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
315 add_subwindow(new BC_Title(x1, y2, _("Damp:")));
316 add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
319 add_subwindow(new BC_Title(x1, y2, _("Wet:")));
320 add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
323 add_subwindow(new BC_Title(x1, y2, _("Dry:")));
324 add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
327 add_subwindow(new BC_Title(x1, y2, _("Width:")));
328 add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
331 add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
336 int FreeverbWindow::close_event()
338 // Set result to 1 to indicate a client side close
354 FreeverbConfig::FreeverbConfig()
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)
380 roomsize = that.roomsize;
387 void FreeverbConfig::interpolate(FreeverbConfig &prev,
388 FreeverbConfig &next,
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;
428 PLUGIN_THREAD_OBJECT(FreeverbEffect, FreeverbThread, FreeverbWindow)
434 FreeverbEffect::FreeverbEffect(PluginServer *server)
435 : PluginAClient(server)
441 PLUGIN_CONSTRUCTOR_MACRO
444 FreeverbEffect::~FreeverbEffect()
446 if(engine) delete engine;
449 for(int i = 0; i < total_in_buffers; i++)
452 delete [] temp_out[i];
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)
480 input.set_shared_string(keyframe->data, strlen(keyframe->data));
485 result = input.read_tag();
489 if(input.tag.title_is("FREEVERB"))
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);
503 void FreeverbEffect::save_data(KeyFrame *keyframe)
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);
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);
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);
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);
556 void FreeverbEffect::update_gui()
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();
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)
591 for(int i = 0; i < total_in_buffers; i++)
594 delete [] temp_out[i];
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++)
609 temp[i] = new float[temp_allocated];
610 temp_out[i] = new float[temp_allocated];
614 for(int i = 0; i < 2 && i < total_in_buffers; i++)
616 float *out = temp[i];
617 double *in = input_ptr[i];
618 for(int j = 0; j < size; j++)
624 if(total_in_buffers < 2)
626 engine->processreplace(temp[0],
635 engine->processreplace(temp[0],
643 for(int i = 0; i < 2 && i < total_in_buffers; i++)
645 double *out = output_ptr[i];
646 float *in = temp_out[i];
647 for(int j = 0; j < size; j++)
649 out[j] = gain_f * in[j];