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 x1 = 10, x2 = 100, x3 = 135, y1 = 10, y2 = 20, margin = 30;
310 add_subwindow(new BC_Title(x1, y2, _("Gain:")));
311 add_subwindow(gain = new FreeverbGain(plugin, x3, y1));
314 add_subwindow(new BC_Title(x1, y2, _("Roomsize:")));
315 add_subwindow(roomsize = new FreeverbRoomsize(plugin, x2, y1));
318 add_subwindow(new BC_Title(x1, y2, _("Damp:")));
319 add_subwindow(damp = new FreeverbDamp(plugin, x3, y1));
322 add_subwindow(new BC_Title(x1, y2, _("Wet:")));
323 add_subwindow(wet = new FreeverbWet(plugin, x2, y1));
326 add_subwindow(new BC_Title(x1, y2, _("Dry:")));
327 add_subwindow(dry = new FreeverbDry(plugin, x3, y1));
330 add_subwindow(new BC_Title(x1, y2, _("Width:")));
331 add_subwindow(width = new FreeverbWidth(plugin, x2, y1));
334 add_subwindow(mode = new FreeverbMode(plugin, x1, y2));
351 FreeverbConfig::FreeverbConfig()
362 int FreeverbConfig::equivalent(FreeverbConfig &that)
364 return EQUIV(gain, that.gain) &&
365 EQUIV(wet, that.wet) &&
366 EQUIV(roomsize, that.roomsize) &&
367 EQUIV(dry, that.dry) &&
368 EQUIV(damp, that.damp) &&
369 EQUIV(width, that.width) &&
370 EQUIV(mode, that.mode);
373 void FreeverbConfig::copy_from(FreeverbConfig &that)
377 roomsize = that.roomsize;
384 void FreeverbConfig::interpolate(FreeverbConfig &prev,
385 FreeverbConfig &next,
388 int64_t current_frame)
390 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
391 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
393 gain = prev.gain * prev_scale + next.gain * next_scale;
394 wet = prev.wet * prev_scale + next.wet * next_scale;
395 roomsize = prev.roomsize * prev_scale + next.roomsize * next_scale;
396 dry = prev.dry * prev_scale + next.dry * next_scale;
397 damp = prev.damp * prev_scale + next.damp * next_scale;
398 width = prev.width * prev_scale + next.width * next_scale;
430 FreeverbEffect::FreeverbEffect(PluginServer *server)
431 : PluginAClient(server)
440 FreeverbEffect::~FreeverbEffect()
442 if(engine) delete engine;
445 for(int i = 0; i < total_in_buffers; i++)
448 delete [] temp_out[i];
456 NEW_WINDOW_MACRO(FreeverbEffect, FreeverbWindow)
459 const char* FreeverbEffect::plugin_title() { return N_("Freeverb"); }
460 int FreeverbEffect::is_realtime() { return 1; }
461 int FreeverbEffect::is_multichannel() { return 1; }
465 void FreeverbEffect::read_data(KeyFrame *keyframe)
468 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
473 result = input.read_tag();
477 if(input.tag.title_is("FREEVERB"))
479 config.gain = input.tag.get_property("GAIN", config.gain);
480 config.roomsize = input.tag.get_property("ROOMSIZE", config.roomsize);
481 config.damp = input.tag.get_property("DAMP", config.damp);
482 config.wet = input.tag.get_property("WET", config.wet);
483 config.dry = input.tag.get_property("DRY", config.dry);
484 config.width = input.tag.get_property("WIDTH", config.width);
485 config.mode = input.tag.get_property("MODE", config.mode);
491 void FreeverbEffect::save_data(KeyFrame *keyframe)
494 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
496 output.tag.set_title("FREEVERB");
497 output.tag.set_property("GAIN", config.gain);
498 output.tag.set_property("ROOMSIZE", config.roomsize);
499 output.tag.set_property("DAMP", config.damp);
500 output.tag.set_property("WET", config.wet);
501 output.tag.set_property("DRY", config.dry);
502 output.tag.set_property("WIDTH", config.width);
503 output.tag.set_property("MODE", config.mode);
505 output.tag.set_title("/FREEVERB");
507 output.append_newline();
508 output.terminate_string();
512 LOAD_CONFIGURATION_MACRO(FreeverbEffect, FreeverbConfig)
514 void FreeverbEffect::update_gui()
518 load_configuration();
519 thread->window->lock_window();
520 ((FreeverbWindow*)thread->window)->gain->update(config.gain);
521 ((FreeverbWindow*)thread->window)->roomsize->update(config.roomsize);
522 ((FreeverbWindow*)thread->window)->damp->update(config.damp);
523 ((FreeverbWindow*)thread->window)->wet->update(config.wet);
524 ((FreeverbWindow*)thread->window)->dry->update(config.dry);
525 ((FreeverbWindow*)thread->window)->width->update(config.width);
526 ((FreeverbWindow*)thread->window)->mode->update((int)config.mode);
527 thread->window->unlock_window();
531 int FreeverbEffect::process_realtime(int64_t size,
533 Samples **output_ptr)
535 load_configuration();
536 if(!engine) engine = new revmodel;
538 engine->setroomsize(DB::fromdb(config.roomsize));
539 engine->setdamp(DB::fromdb(config.damp));
540 engine->setwet(DB::fromdb(config.wet));
541 engine->setdry(DB::fromdb(config.dry));
542 engine->setwidth(DB::fromdb(config.width));
543 engine->setmode(config.mode);
545 // printf("FreeverbEffect::process_realtime %d %f %f %f %f %f %d\n",
547 // DB::fromdb(config.roomsize),
548 // DB::fromdb(config.damp),
549 // DB::fromdb(config.wet),
550 // DB::fromdb(config.dry),
551 // DB::fromdb(config.width),
552 // (int)config.mode);
554 float gain_f = DB::fromdb(config.gain);
556 if(size > temp_allocated)
560 for(int i = 0; i < total_in_buffers; i++)
563 delete [] temp_out[i];
574 temp_allocated = size * 2;
575 temp = new float*[total_in_buffers];
576 temp_out = new float*[total_in_buffers];
577 for(int i = 0; i < total_in_buffers; i++)
579 temp[i] = new float[temp_allocated];
580 temp_out[i] = new float[temp_allocated];
584 for(int i = 0; i < 2 && i < total_in_buffers; i++)
586 float *out = temp[i];
587 double *in = input_ptr[i]->get_data();
588 for(int j = 0; j < size; j++)
594 if(total_in_buffers < 2)
596 engine->processreplace(temp[0],
606 engine->processreplace(temp[0],
614 for(int i = 0; i < 2 && i < total_in_buffers; i++)
616 double *out = output_ptr[i]->get_data();
617 float *in = temp_out[i];
618 for(int j = 0; j < size; j++)
620 out[j] = gain_f * in[j];