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()
473 return _("Freeverb");
477 int FreeverbEffect::is_realtime()
482 int FreeverbEffect::is_multichannel()
489 void FreeverbEffect::read_data(KeyFrame *keyframe)
492 input.set_shared_string(keyframe->data, strlen(keyframe->data));
497 result = input.read_tag();
501 if(input.tag.title_is("FREEVERB"))
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);
515 void FreeverbEffect::save_data(KeyFrame *keyframe)
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);
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);
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);
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);
568 void FreeverbEffect::update_gui()
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();
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)
603 for(int i = 0; i < total_in_buffers; i++)
606 delete [] temp_out[i];
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++)
621 temp[i] = new float[temp_allocated];
622 temp_out[i] = new float[temp_allocated];
626 for(int i = 0; i < 2 && i < total_in_buffers; i++)
628 float *out = temp[i];
629 double *in = input_ptr[i];
630 for(int j = 0; j < size; j++)
636 if(total_in_buffers < 2)
638 engine->processreplace(temp[0],
647 engine->processreplace(temp[0],
655 for(int i = 0; i < 2 && i < total_in_buffers; i++)
657 double *out = output_ptr[i];
658 float *in = temp_out[i];
659 for(int j = 0; j < size; j++)
661 out[j] = gain_f * in[j];