4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
28 #include "pluginaclient.h"
29 #include "revmodel.hpp"
51 int equivalent(FreeverbConfig &that);
52 void copy_from(FreeverbConfig &that);
53 void interpolate(FreeverbConfig &prev,
57 int64_t current_frame);
70 class FreeverbGain : public BC_FPot
73 FreeverbGain(FreeverbEffect *plugin, int x, int y);
75 FreeverbEffect *plugin;
78 class FreeverbRoomsize : public BC_FPot
81 FreeverbRoomsize(FreeverbEffect *plugin, int x, int y);
83 FreeverbEffect *plugin;
86 class FreeverbDamp : public BC_FPot
89 FreeverbDamp(FreeverbEffect *plugin, int x, int y);
91 FreeverbEffect *plugin;
94 class FreeverbWet : public BC_FPot
97 FreeverbWet(FreeverbEffect *plugin, int x, int y);
99 FreeverbEffect *plugin;
102 class FreeverbDry : public BC_FPot
105 FreeverbDry(FreeverbEffect *plugin, int x, int y);
107 FreeverbEffect *plugin;
110 class FreeverbWidth : public BC_FPot
113 FreeverbWidth(FreeverbEffect *plugin, int x, int y);
115 FreeverbEffect *plugin;
118 class FreeverbMode : public BC_CheckBox
121 FreeverbMode(FreeverbEffect *plugin, int x, int y);
123 FreeverbEffect *plugin;
128 class FreeverbWindow : public PluginClientWindow
131 FreeverbWindow(FreeverbEffect *plugin);
132 void create_objects();
134 FreeverbEffect *plugin;
137 FreeverbRoomsize *roomsize;
141 FreeverbWidth *width;
149 class FreeverbEffect : public PluginAClient
152 FreeverbEffect(PluginServer *server);
155 PLUGIN_CLASS_MEMBERS(FreeverbConfig)
157 int is_multichannel();
158 void read_data(KeyFrame *keyframe);
159 void save_data(KeyFrame *keyframe);
160 int process_realtime(int64_t size, Samples **input_ptr, Samples **output_ptr);
177 REGISTER_PLUGIN(FreeverbEffect)
188 FreeverbGain::FreeverbGain(FreeverbEffect *plugin, int x, int y)
189 : BC_FPot(x, y, plugin->config.gain, INFINITYGAIN, 6)
191 this->plugin = plugin;
195 int FreeverbGain::handle_event()
197 plugin->config.gain = get_value();
198 plugin->send_configure_change();
202 FreeverbRoomsize::FreeverbRoomsize(FreeverbEffect *plugin, int x, int y)
203 : BC_FPot(x, y, plugin->config.roomsize, INFINITYGAIN, 0)
205 this->plugin = plugin;
209 int FreeverbRoomsize::handle_event()
211 plugin->config.roomsize = get_value();
212 plugin->send_configure_change();
216 FreeverbDamp::FreeverbDamp(FreeverbEffect *plugin, int x, int y)
217 : BC_FPot(x, y, plugin->config.damp, INFINITYGAIN, 0)
219 this->plugin = plugin;
223 int FreeverbDamp::handle_event()
225 plugin->config.damp = get_value();
226 plugin->send_configure_change();
230 FreeverbWet::FreeverbWet(FreeverbEffect *plugin, int x, int y)
231 : BC_FPot(x, y, plugin->config.wet, INFINITYGAIN, 0)
233 this->plugin = plugin;
237 int FreeverbWet::handle_event()
239 plugin->config.wet = get_value();
240 plugin->send_configure_change();
244 FreeverbDry::FreeverbDry(FreeverbEffect *plugin, int x, int y)
245 : BC_FPot(x, y, plugin->config.dry, INFINITYGAIN, 0)
247 this->plugin = plugin;
251 int FreeverbDry::handle_event()
253 plugin->config.dry = get_value();
254 plugin->send_configure_change();
258 FreeverbWidth::FreeverbWidth(FreeverbEffect *plugin, int x, int y)
259 : BC_FPot(x, y, plugin->config.width, INFINITYGAIN, 0)
261 this->plugin = plugin;
265 int FreeverbWidth::handle_event()
267 plugin->config.width = get_value();
268 plugin->send_configure_change();
272 FreeverbMode::FreeverbMode(FreeverbEffect *plugin, int x, int y)
273 : BC_CheckBox(x, y, (int)plugin->config.mode, _("Freeze"))
275 this->plugin = plugin;
278 int FreeverbMode::handle_event()
280 plugin->config.mode = get_value();
281 plugin->send_configure_change();
295 FreeverbWindow::FreeverbWindow(FreeverbEffect *plugin)
296 : PluginClientWindow(plugin,
303 this->plugin = plugin;
306 void FreeverbWindow::create_objects()
308 int xs10 = xS(10), xs100 = xS(100), xs135 = xS(135);
309 int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30);
310 int x1 = xs10, x2 = xs100, x3 = xs135, y1 = ys10, y2 = ys20, margin = ys30;
312 add_subwindow(new BC_Title(x1, y2, _("Gain:")));
313 add_subwindow(gain = new FreeverbGain(plugin, x3, y1));
316 add_subwindow(new BC_Title(x1, y2, _("Roomsize:")));
317 add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
320 add_subwindow(new BC_Title(x1, y2, _("Damp:")));
321 add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
324 add_subwindow(new BC_Title(x1, y2, _("Wet:")));
325 add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
328 add_subwindow(new BC_Title(x1, y2, _("Dry:")));
329 add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
332 add_subwindow(new BC_Title(x1, y2, _("Width:")));
333 add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
336 add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
353 FreeverbConfig::FreeverbConfig()
364 int FreeverbConfig::equivalent(FreeverbConfig &that)
366 return EQUIV(gain, that.gain) &&
367 EQUIV(wet, that.wet) &&
368 EQUIV(roomsize, that.roomsize) &&
369 EQUIV(dry, that.dry) &&
370 EQUIV(damp, that.damp) &&
371 EQUIV(width, that.width) &&
372 EQUIV(mode, that.mode);
375 void FreeverbConfig::copy_from(FreeverbConfig &that)
379 roomsize = that.roomsize;
386 void FreeverbConfig::interpolate(FreeverbConfig &prev,
387 FreeverbConfig &next,
390 int64_t current_frame)
392 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
393 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
395 gain = prev.gain * prev_scale + next.gain * next_scale;
396 wet = prev.wet * prev_scale + next.wet * next_scale;
397 roomsize = prev.roomsize * prev_scale + next.roomsize * next_scale;
398 dry = prev.dry * prev_scale + next.dry * next_scale;
399 damp = prev.damp * prev_scale + next.damp * next_scale;
400 width = prev.width * prev_scale + next.width * next_scale;
432 FreeverbEffect::FreeverbEffect(PluginServer *server)
433 : PluginAClient(server)
442 FreeverbEffect::~FreeverbEffect()
444 if(engine) delete engine;
447 for(int i = 0; i < total_in_buffers; i++)
450 delete [] temp_out[i];
458 NEW_WINDOW_MACRO(FreeverbEffect, FreeverbWindow)
461 const char* FreeverbEffect::plugin_title() { return N_("Freeverb"); }
462 int FreeverbEffect::is_realtime() { return 1; }
463 int FreeverbEffect::is_multichannel() { return 1; }
467 void FreeverbEffect::read_data(KeyFrame *keyframe)
470 input.set_shared_input(keyframe->xbuf);
475 result = input.read_tag();
479 if(input.tag.title_is("FREEVERB"))
481 config.gain = input.tag.get_property("GAIN", config.gain);
482 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
483 config.damp = input.tag.get_property("DAMP", config.damp);
484 config.wet = input.tag.get_property("WET", config.wet);
485 config.dry = input.tag.get_property("DRY", config.dry);
486 config.width = input.tag.get_property("WIDTH", config.width);
487 config.mode = input.tag.get_property("MODE", config.mode);
493 void FreeverbEffect::save_data(KeyFrame *keyframe)
496 output.set_shared_output(keyframe->xbuf);
498 output.tag.set_title("FREEVERB");
499 output.tag.set_property("GAIN", config.gain);
500 output.tag.set_property("ROOMSIZE", config.roomsize);
501 output.tag.set_property("DAMP", config.damp);
502 output.tag.set_property("WET", config.wet);
503 output.tag.set_property("DRY", config.dry);
504 output.tag.set_property("WIDTH", config.width);
505 output.tag.set_property("MODE", config.mode);
507 output.tag.set_title("/FREEVERB");
509 output.append_newline();
510 output.terminate_string();
514 LOAD_CONFIGURATION_MACRO(FreeverbEffect, FreeverbConfig)
516 void FreeverbEffect::update_gui()
520 load_configuration();
521 thread->window->lock_window();
522 ((FreeverbWindow*)thread->window)->gain->update(config.gain);
523 ((FreeverbWindow*)thread->window)->roomsize->update(config.roomsize);
524 ((FreeverbWindow*)thread->window)->damp->update(config.damp);
525 ((FreeverbWindow*)thread->window)->wet->update(config.wet);
526 ((FreeverbWindow*)thread->window)->dry->update(config.dry);
527 ((FreeverbWindow*)thread->window)->width->update(config.width);
528 ((FreeverbWindow*)thread->window)->mode->update((int)config.mode);
529 thread->window->unlock_window();
533 int FreeverbEffect::process_realtime(int64_t size,
535 Samples **output_ptr)
537 load_configuration();
538 if(!engine) engine = new revmodel;
540 engine->setroomsize(DB::fromdb(config.roomsize));
541 engine->setdamp(DB::fromdb(config.damp));
542 engine->setwet(DB::fromdb(config.wet));
543 engine->setdry(DB::fromdb(config.dry));
544 engine->setwidth(DB::fromdb(config.width));
545 engine->setmode(config.mode);
547 // printf("FreeverbEffect::process_realtime %d %f %f %f %f %f %d\n",
549 // DB::fromdb(config.roomsize),
550 // DB::fromdb(config.damp),
551 // DB::fromdb(config.wet),
552 // DB::fromdb(config.dry),
553 // DB::fromdb(config.width),
554 // (int)config.mode);
556 float gain_f = DB::fromdb(config.gain);
558 if(size > temp_allocated)
562 for(int i = 0; i < total_in_buffers; i++)
565 delete [] temp_out[i];
576 temp_allocated = size * 2;
577 temp = new float*[total_in_buffers];
578 temp_out = new float*[total_in_buffers];
579 for(int i = 0; i < total_in_buffers; i++)
581 temp[i] = new float[temp_allocated];
582 temp_out[i] = new float[temp_allocated];
586 for(int i = 0; i < 2 && i < total_in_buffers; i++)
588 float *out = temp[i];
589 double *in = input_ptr[i]->get_data();
590 for(int j = 0; j < size; j++)
596 if(total_in_buffers < 2)
598 engine->processreplace(temp[0],
608 engine->processreplace(temp[0],
616 for(int i = 0; i < 2 && i < total_in_buffers; i++)
618 double *out = output_ptr[i]->get_data();
619 float *in = temp_out[i];
620 for(int j = 0; j < size; j++)
622 out[j] = gain_f * in[j];