00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "guicast.h"
00005 #include "filexml.h"
00006 #include "picon_png.h"
00007 #include "pluginaclient.h"
00008 #include "revmodel.hpp"
00009 #include "units.h"
00010 #include "vframe.h"
00011
00012 #include <math.h>
00013 #include <string.h>
00014
00015 #include <libintl.h>
00016 #define _(String) gettext(String)
00017 #define gettext_noop(String) String
00018 #define N_(String) gettext_noop (String)
00019
00020
00021
00022
00023
00024
00025 class FreeverbEffect;
00026
00027 class FreeverbConfig
00028 {
00029 public:
00030 FreeverbConfig();
00031
00032
00033 int equivalent(FreeverbConfig &that);
00034 void copy_from(FreeverbConfig &that);
00035 void interpolate(FreeverbConfig &prev,
00036 FreeverbConfig &next,
00037 int64_t prev_frame,
00038 int64_t next_frame,
00039 int64_t current_frame);
00040
00041
00042 float gain;
00043 float roomsize;
00044 float damp;
00045 float wet;
00046 float dry;
00047 float width;
00048 float mode;
00049 };
00050
00051
00052 class FreeverbGain : public BC_FPot
00053 {
00054 public:
00055 FreeverbGain(FreeverbEffect *plugin, int x, int y);
00056 int handle_event();
00057 FreeverbEffect *plugin;
00058 };
00059
00060 class FreeverbRoomsize : public BC_FPot
00061 {
00062 public:
00063 FreeverbRoomsize(FreeverbEffect *plugin, int x, int y);
00064 int handle_event();
00065 FreeverbEffect *plugin;
00066 };
00067
00068 class FreeverbDamp : public BC_FPot
00069 {
00070 public:
00071 FreeverbDamp(FreeverbEffect *plugin, int x, int y);
00072 int handle_event();
00073 FreeverbEffect *plugin;
00074 };
00075
00076 class FreeverbWet : public BC_FPot
00077 {
00078 public:
00079 FreeverbWet(FreeverbEffect *plugin, int x, int y);
00080 int handle_event();
00081 FreeverbEffect *plugin;
00082 };
00083
00084 class FreeverbDry : public BC_FPot
00085 {
00086 public:
00087 FreeverbDry(FreeverbEffect *plugin, int x, int y);
00088 int handle_event();
00089 FreeverbEffect *plugin;
00090 };
00091
00092 class FreeverbWidth : public BC_FPot
00093 {
00094 public:
00095 FreeverbWidth(FreeverbEffect *plugin, int x, int y);
00096 int handle_event();
00097 FreeverbEffect *plugin;
00098 };
00099
00100 class FreeverbMode : public BC_CheckBox
00101 {
00102 public:
00103 FreeverbMode(FreeverbEffect *plugin, int x, int y);
00104 int handle_event();
00105 FreeverbEffect *plugin;
00106 };
00107
00108
00109
00110 class FreeverbWindow : public BC_Window
00111 {
00112 public:
00113 FreeverbWindow(FreeverbEffect *plugin, int x, int y);
00114 void create_objects();
00115 int close_event();
00116
00117 FreeverbEffect *plugin;
00118
00119 FreeverbGain *gain;
00120 FreeverbRoomsize *roomsize;
00121 FreeverbDamp *damp;
00122 FreeverbWet *wet;
00123 FreeverbDry *dry;
00124 FreeverbWidth *width;
00125 FreeverbMode *mode;
00126 };
00127
00128 PLUGIN_THREAD_HEADER(FreeverbEffect, FreeverbThread, FreeverbWindow)
00129
00130
00131
00132 class FreeverbEffect : public PluginAClient
00133 {
00134 public:
00135 FreeverbEffect(PluginServer *server);
00136 ~FreeverbEffect();
00137
00138 VFrame* new_picon();
00139 char* plugin_title();
00140 int show_gui();
00141 void raise_window();
00142 int set_string();
00143 int is_realtime();
00144 int is_multichannel();
00145 void read_data(KeyFrame *keyframe);
00146 void save_data(KeyFrame *keyframe);
00147 int process_realtime(int64_t size, double **input_ptr, double **output_ptr);
00148
00149
00150
00151
00152 int load_defaults();
00153 int save_defaults();
00154 int load_configuration();
00155 void update_gui();
00156
00157
00158 BC_Hash *defaults;
00159 FreeverbThread *thread;
00160 FreeverbConfig config;
00161 revmodel *engine;
00162 float **temp;
00163 float **temp_out;
00164 int temp_allocated;
00165 };
00166
00167
00168
00169
00170 REGISTER_PLUGIN(FreeverbEffect)
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 FreeverbGain::FreeverbGain(FreeverbEffect *plugin, int x, int y)
00182 : BC_FPot(x, y, plugin->config.gain, INFINITYGAIN, 6)
00183 {
00184 this->plugin = plugin;
00185 set_precision(.1);
00186 }
00187
00188 int FreeverbGain::handle_event()
00189 {
00190 plugin->config.gain = get_value();
00191 plugin->send_configure_change();
00192 return 1;
00193 }
00194
00195 FreeverbRoomsize::FreeverbRoomsize(FreeverbEffect *plugin, int x, int y)
00196 : BC_FPot(x, y, plugin->config.roomsize, INFINITYGAIN, 0)
00197 {
00198 this->plugin = plugin;
00199 set_precision(.01);
00200 }
00201
00202 int FreeverbRoomsize::handle_event()
00203 {
00204 plugin->config.roomsize = get_value();
00205 plugin->send_configure_change();
00206 return 1;
00207 }
00208
00209 FreeverbDamp::FreeverbDamp(FreeverbEffect *plugin, int x, int y)
00210 : BC_FPot(x, y, plugin->config.damp, INFINITYGAIN, 0)
00211 {
00212 this->plugin = plugin;
00213 set_precision(.01);
00214 }
00215
00216 int FreeverbDamp::handle_event()
00217 {
00218 plugin->config.damp = get_value();
00219 plugin->send_configure_change();
00220 return 1;
00221 }
00222
00223 FreeverbWet::FreeverbWet(FreeverbEffect *plugin, int x, int y)
00224 : BC_FPot(x, y, plugin->config.wet, INFINITYGAIN, 0)
00225 {
00226 this->plugin = plugin;
00227 set_precision(.01);
00228 }
00229
00230 int FreeverbWet::handle_event()
00231 {
00232 plugin->config.wet = get_value();
00233 plugin->send_configure_change();
00234 return 1;
00235 }
00236
00237 FreeverbDry::FreeverbDry(FreeverbEffect *plugin, int x, int y)
00238 : BC_FPot(x, y, plugin->config.dry, INFINITYGAIN, 0)
00239 {
00240 this->plugin = plugin;
00241 set_precision(.01);
00242 }
00243
00244 int FreeverbDry::handle_event()
00245 {
00246 plugin->config.dry = get_value();
00247 plugin->send_configure_change();
00248 return 1;
00249 }
00250
00251 FreeverbWidth::FreeverbWidth(FreeverbEffect *plugin, int x, int y)
00252 : BC_FPot(x, y, plugin->config.width, INFINITYGAIN, 0)
00253 {
00254 this->plugin = plugin;
00255 set_precision(.01);
00256 }
00257
00258 int FreeverbWidth::handle_event()
00259 {
00260 plugin->config.width = get_value();
00261 plugin->send_configure_change();
00262 return 1;
00263 }
00264
00265 FreeverbMode::FreeverbMode(FreeverbEffect *plugin, int x, int y)
00266 : BC_CheckBox(x, y, (int)plugin->config.mode, _("Freeze"))
00267 {
00268 this->plugin = plugin;
00269 }
00270
00271 int FreeverbMode::handle_event()
00272 {
00273 plugin->config.mode = get_value();
00274 plugin->send_configure_change();
00275 return 1;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 FreeverbWindow::FreeverbWindow(FreeverbEffect *plugin, int x, int y)
00289 : BC_Window(plugin->gui_string,
00290 x,
00291 y,
00292 180,
00293 250,
00294 180,
00295 250,
00296 0,
00297 0,
00298 1)
00299 {
00300 this->plugin = plugin;
00301 }
00302
00303 void FreeverbWindow::create_objects()
00304 {
00305 int x1 = 10, x2 = 100, x3 = 135, y1 = 10, y2 = 20, margin = 30;
00306
00307 add_subwindow(new BC_Title(x1, y2, _("Gain:")));
00308 add_subwindow(gain = new FreeverbGain(plugin, x3, y1));
00309 y1 += margin;
00310 y2 += margin;
00311 add_subwindow(new BC_Title(x1, y2, _("Roomsize:")));
00312 add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
00313 y1 += margin;
00314 y2 += margin;
00315 add_subwindow(new BC_Title(x1, y2, _("Damp:")));
00316 add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
00317 y1 += margin;
00318 y2 += margin;
00319 add_subwindow(new BC_Title(x1, y2, _("Wet:")));
00320 add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
00321 y1 += margin;
00322 y2 += margin;
00323 add_subwindow(new BC_Title(x1, y2, _("Dry:")));
00324 add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
00325 y1 += margin;
00326 y2 += margin;
00327 add_subwindow(new BC_Title(x1, y2, _("Width:")));
00328 add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
00329 y1 += margin;
00330 y2 += margin;
00331 add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
00332 show_window();
00333 flush();
00334 }
00335
00336 int FreeverbWindow::close_event()
00337 {
00338
00339 set_done(1);
00340 return 1;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 FreeverbConfig::FreeverbConfig()
00355 {
00356 gain = -6.0;
00357 wet = -6.0;
00358 dry = 0;
00359 roomsize = -6.0;
00360 damp = 0;
00361 width = 0;
00362 mode = 0;
00363 }
00364
00365 int FreeverbConfig::equivalent(FreeverbConfig &that)
00366 {
00367 return EQUIV(gain, that.gain) &&
00368 EQUIV(wet, that.wet) &&
00369 EQUIV(roomsize, that.roomsize) &&
00370 EQUIV(dry, that.dry) &&
00371 EQUIV(damp, that.damp) &&
00372 EQUIV(width, that.width) &&
00373 EQUIV(mode, that.mode);
00374 }
00375
00376 void FreeverbConfig::copy_from(FreeverbConfig &that)
00377 {
00378 gain = that.gain;
00379 wet = that.wet;
00380 roomsize = that.roomsize;
00381 dry = that.dry;
00382 damp = that.damp;
00383 width = that.width;
00384 mode = that.mode;
00385 }
00386
00387 void FreeverbConfig::interpolate(FreeverbConfig &prev,
00388 FreeverbConfig &next,
00389 int64_t prev_frame,
00390 int64_t next_frame,
00391 int64_t current_frame)
00392 {
00393 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00394 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00395
00396 gain = prev.gain * prev_scale + next.gain * next_scale;
00397 wet = prev.wet * prev_scale + next.wet * next_scale;
00398 roomsize = prev.roomsize * prev_scale + next.roomsize * next_scale;
00399 dry = prev.dry * prev_scale + next.dry * next_scale;
00400 damp = prev.damp * prev_scale + next.damp * next_scale;
00401 width = prev.width * prev_scale + next.width * next_scale;
00402 mode = prev.mode;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 PLUGIN_THREAD_OBJECT(FreeverbEffect, FreeverbThread, FreeverbWindow)
00429
00430
00431
00432
00433
00434 FreeverbEffect::FreeverbEffect(PluginServer *server)
00435 : PluginAClient(server)
00436 {
00437 engine = 0;
00438 temp = 0;
00439 temp_out = 0;
00440 temp_allocated = 0;
00441 PLUGIN_CONSTRUCTOR_MACRO
00442 }
00443
00444 FreeverbEffect::~FreeverbEffect()
00445 {
00446 if(engine) delete engine;
00447 if(temp)
00448 {
00449 for(int i = 0; i < total_in_buffers; i++)
00450 {
00451 delete [] temp[i];
00452 delete [] temp_out[i];
00453 }
00454 delete [] temp;
00455 delete [] temp_out;
00456 }
00457 PLUGIN_DESTRUCTOR_MACRO
00458 }
00459
00460 NEW_PICON_MACRO(FreeverbEffect)
00461
00462 LOAD_CONFIGURATION_MACRO(FreeverbEffect, FreeverbConfig)
00463
00464 SHOW_GUI_MACRO(FreeverbEffect, FreeverbThread)
00465
00466 RAISE_WINDOW_MACRO(FreeverbEffect)
00467
00468 SET_STRING_MACRO(FreeverbEffect)
00469
00470
00471 char* FreeverbEffect::plugin_title() { return N_("Freeverb"); }
00472 int FreeverbEffect::is_realtime() { return 1; }
00473 int FreeverbEffect::is_multichannel() { return 1; }
00474
00475
00476
00477 void FreeverbEffect::read_data(KeyFrame *keyframe)
00478 {
00479 FileXML input;
00480 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00481
00482 int result = 0;
00483 while(!result)
00484 {
00485 result = input.read_tag();
00486
00487 if(!result)
00488 {
00489 if(input.tag.title_is("FREEVERB"))
00490 {
00491 config.gain = input.tag.get_property("GAIN", config.gain);
00492 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
00493 config.damp = input.tag.get_property("DAMP", config.damp);
00494 config.wet = input.tag.get_property("WET", config.wet);
00495 config.dry = input.tag.get_property("DRY", config.dry);
00496 config.width = input.tag.get_property("WIDTH", config.width);
00497 config.mode = input.tag.get_property("MODE", config.mode);
00498 }
00499 }
00500 }
00501 }
00502
00503 void FreeverbEffect::save_data(KeyFrame *keyframe)
00504 {
00505 FileXML output;
00506 output.set_shared_string(keyframe->data, MESSAGESIZE);
00507
00508 output.tag.set_title("FREEVERB");
00509 output.tag.set_property("GAIN", config.gain);
00510 output.tag.set_property("ROOMSIZE", config.roomsize);
00511 output.tag.set_property("DAMP", config.damp);
00512 output.tag.set_property("WET", config.wet);
00513 output.tag.set_property("DRY", config.dry);
00514 output.tag.set_property("WIDTH", config.width);
00515 output.tag.set_property("MODE", config.mode);
00516 output.append_tag();
00517 output.tag.set_title("/FREEVERB");
00518 output.append_tag();
00519 output.append_newline();
00520
00521 output.terminate_string();
00522 }
00523
00524 int FreeverbEffect::load_defaults()
00525 {
00526 char directory[BCTEXTLEN], string[BCTEXTLEN];
00527 sprintf(directory, "%sfreeverb.rc", BCASTDIR);
00528 defaults = new BC_Hash(directory);
00529 defaults->load();
00530
00531 config.gain = defaults->get("GAIN", config.gain);
00532 config.roomsize = defaults->get("ROOMSIZE", config.roomsize);
00533 config.damp = defaults->get("DAMP", config.damp);
00534 config.wet = defaults->get("WET", config.wet);
00535 config.dry = defaults->get("DRY", config.dry);
00536 config.width = defaults->get("WIDTH", config.width);
00537 config.mode = defaults->get("MODE", config.mode);
00538 return 0;
00539 }
00540
00541 int FreeverbEffect::save_defaults()
00542 {
00543 char string[BCTEXTLEN];
00544
00545 defaults->update("GAIN", config.gain);
00546 defaults->update("ROOMSIZE", config.roomsize);
00547 defaults->update("DAMP", config.damp);
00548 defaults->update("WET", config.wet);
00549 defaults->update("DRY", config.dry);
00550 defaults->update("WIDTH", config.width);
00551 defaults->update("MODE", config.mode);
00552 defaults->save();
00553
00554 return 0;
00555 }
00556
00557
00558 void FreeverbEffect::update_gui()
00559 {
00560 if(thread)
00561 {
00562 load_configuration();
00563 thread->window->lock_window();
00564 thread->window->gain->update(config.gain);
00565 thread->window->roomsize->update(config.roomsize);
00566 thread->window->damp->update(config.damp);
00567 thread->window->wet->update(config.wet);
00568 thread->window->dry->update(config.dry);
00569 thread->window->width->update(config.width);
00570 thread->window->mode->update((int)config.mode);
00571 thread->window->unlock_window();
00572 }
00573 }
00574
00575 int FreeverbEffect::process_realtime(int64_t size, double **input_ptr, double **output_ptr)
00576 {
00577 load_configuration();
00578 if(!engine) engine = new revmodel;
00579
00580 engine->setroomsize(DB::fromdb(config.roomsize));
00581 engine->setdamp(DB::fromdb(config.damp));
00582 engine->setwet(DB::fromdb(config.wet));
00583 engine->setdry(DB::fromdb(config.dry));
00584 engine->setwidth(DB::fromdb(config.width));
00585 engine->setmode(config.mode);
00586
00587 float gain_f = DB::fromdb(config.gain);
00588
00589 if(size > temp_allocated)
00590 {
00591 if(temp)
00592 {
00593 for(int i = 0; i < total_in_buffers; i++)
00594 {
00595 delete [] temp[i];
00596 delete [] temp_out[i];
00597 }
00598 delete [] temp;
00599 delete [] temp_out;
00600 }
00601 temp = 0;
00602 temp_out = 0;
00603 }
00604 if(!temp)
00605 {
00606 temp_allocated = size * 2;
00607 temp = new float*[total_in_buffers];
00608 temp_out = new float*[total_in_buffers];
00609 for(int i = 0; i < total_in_buffers; i++)
00610 {
00611 temp[i] = new float[temp_allocated];
00612 temp_out[i] = new float[temp_allocated];
00613 }
00614 }
00615
00616 for(int i = 0; i < 2 && i < total_in_buffers; i++)
00617 {
00618 float *out = temp[i];
00619 double *in = input_ptr[i];
00620 for(int j = 0; j < size; j++)
00621 {
00622 out[j] = in[j];
00623 }
00624 }
00625
00626 if(total_in_buffers < 2)
00627 {
00628 engine->processreplace(temp[0],
00629 temp[0],
00630 temp_out[0],
00631 temp_out[0],
00632 size,
00633 1);
00634 }
00635 else
00636 {
00637 engine->processreplace(temp[0],
00638 temp[1],
00639 temp_out[0],
00640 temp_out[1],
00641 size,
00642 1);
00643 }
00644
00645 for(int i = 0; i < 2 && i < total_in_buffers; i++)
00646 {
00647 double *out = output_ptr[i];
00648 float *in = temp_out[i];
00649 for(int j = 0; j < size; j++)
00650 {
00651 out[j] = gain_f * in[j];
00652 }
00653 }
00654
00655 return 0;
00656 }
00657
00658