4 * Copyright (C) 1997-2011 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
23 // Originally from the following:
27 LADSPA Unique ID: 1441
30 Added support for changing bands in real time 2003-12-09
33 Adapted to LADSPA by Josh Green <jgreen@users.sourceforge.net>
34 15.6.2001 (for the LinuxTag 2001!)
36 Original program can be found at:
37 http://www.sirlab.de/linux/
38 Author: Achim Settelmeier <settel-linux@sirlab.de>
43 #include "bcdisplayinfo.h"
44 #include "bcsignals.h"
66 REGISTER_PLUGIN(Vocoder)
71 //#define USE_BANDWIDTH
73 const double decay_table[] =
76 1/100.0, 1/100.0, 1/100.0,
77 1/125.0, 1/125.0, 1/125.0,
78 1/166.0, 1/166.0, 1/166.0,
79 1/200.0, 1/200.0, 1/200.0,
80 1/250.0, 1/250.0, 1/250.0
84 VocoderBand::VocoderBand()
89 void VocoderBand::reset()
100 void VocoderBand::copy_from(VocoderBand *src)
117 VocoderOut::VocoderOut()
122 void VocoderOut::reset()
126 level = 0; /* 0.0 - 1.0 level of this output band */
130 VocoderConfig::VocoderConfig()
132 wetness = INFINITYGAIN;
139 int VocoderConfig::equivalent(VocoderConfig &that)
141 if(!EQUIV(wetness, that.wetness) ||
142 !EQUIV(level, that.level) ||
143 carrier_track != that.carrier_track ||
144 bands != that.bands) return 0;
148 void VocoderConfig::copy_from(VocoderConfig &that)
150 wetness = that.wetness;
151 carrier_track = that.carrier_track;
154 CLAMP(bands, 1, MAX_BANDS);
157 void VocoderConfig::interpolate(VocoderConfig &prev,
161 int64_t current_frame)
163 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
164 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
165 wetness = prev.wetness * prev_scale + next.wetness * next_scale;
166 level = prev.level * prev_scale + next.level * next_scale;
167 carrier_track = prev.carrier_track;
169 CLAMP(bands, 1, MAX_BANDS);
183 VocoderWetness::VocoderWetness(Vocoder *plugin, int x, int y)
184 : BC_FPot(x, y, plugin->config.wetness, INFINITYGAIN, 0)
186 this->plugin = plugin;
189 int VocoderWetness::handle_event()
191 plugin->config.wetness = get_value();
192 plugin->send_configure_change();
200 VocoderLevel::VocoderLevel(Vocoder *plugin, int x, int y)
201 : BC_FPot(x, y, plugin->config.level, INFINITYGAIN, 40)
203 this->plugin = plugin;
206 int VocoderLevel::handle_event()
208 plugin->config.level = get_value();
209 plugin->send_configure_change();
221 VocoderCarrier::VocoderCarrier(Vocoder *plugin,
222 VocoderWindow *window,
225 : BC_TumbleTextBox(window,
226 plugin->config.carrier_track,
233 this->plugin = plugin;
236 int VocoderCarrier::handle_event()
238 plugin->config.carrier_track = atoi(get_text());
239 plugin->send_configure_change();
245 VocoderBands::VocoderBands(Vocoder *plugin,
246 VocoderWindow *window,
249 : BC_TumbleTextBox(window,
250 plugin->config.bands,
257 this->plugin = plugin;
260 int VocoderBands::handle_event()
262 plugin->config.bands = atoi(get_text());
263 plugin->send_configure_change();
271 VocoderWindow::VocoderWindow(Vocoder *plugin)
272 : PluginClientWindow(plugin,
279 this->plugin = plugin;
282 VocoderWindow::~VocoderWindow()
286 void VocoderWindow::create_objects()
288 int x = plugin->get_theme()->widget_border;
289 int y = plugin->get_theme()->widget_border;
294 add_subwindow(title = new BC_Title(x, y, _("Wetness:")));
295 int x2 = x + title->get_w() + plugin->get_theme()->widget_border;
296 y += BC_Pot::calculate_h() + plugin->get_theme()->widget_border;
297 add_subwindow(title = new BC_Title(x, y, _("Level:")));
298 x2 = MAX(x2, x + title->get_w() + plugin->get_theme()->widget_border);
302 add_subwindow(wetness = new VocoderWetness(plugin, x, y));
303 y += wetness->get_h() + plugin->get_theme()->widget_border;
304 add_subwindow(level = new VocoderLevel(plugin, x, y));
305 y += level->get_h() + plugin->get_theme()->widget_border;
308 add_subwindow(title = new BC_Title(x, y, _("Carrier Track:")));
309 output = new VocoderCarrier(plugin,
311 x + title->get_w() + plugin->get_theme()->widget_border,
313 output->create_objects();
314 y += output->get_h() + plugin->get_theme()->widget_border;
316 add_subwindow(title = new BC_Title(x, y, _("Bands:")));
317 bands = new VocoderBands(plugin,
319 x + title->get_w() + plugin->get_theme()->widget_border,
321 bands->create_objects();
322 y += bands->get_h() + plugin->get_theme()->widget_border;
329 void VocoderWindow::update_gui()
331 wetness->update(plugin->config.wetness);
332 level->update(plugin->config.level);
333 output->update((int64_t)plugin->config.carrier_track);
334 bands->update((int64_t)plugin->config.bands);
347 Vocoder::Vocoder(PluginServer *server)
348 : PluginAClient(server)
350 need_reconfigure = 1;
358 NEW_WINDOW_MACRO(Vocoder, VocoderWindow)
360 LOAD_CONFIGURATION_MACRO(Vocoder, VocoderConfig)
363 const char* Vocoder::plugin_title() { return N_("Vocoder"); }
364 int Vocoder::is_realtime() { return 1; }
365 int Vocoder::is_multichannel() { return 1; }
367 void Vocoder::read_data(KeyFrame *keyframe)
370 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
375 result = input.read_tag();
379 if(input.tag.title_is("VOCODER"))
381 config.wetness = input.tag.get_property("WETNESS", config.wetness);
382 config.level = input.tag.get_property("LEVEL", config.level);
383 config.carrier_track = input.tag.get_property("OUTPUT", config.carrier_track);
384 config.bands = input.tag.get_property("BANDS", config.bands);
390 void Vocoder::save_data(KeyFrame *keyframe)
393 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
395 output.tag.set_title("VOCODER");
396 output.tag.set_property("WETNESS", config.wetness);
397 output.tag.set_property("LEVEL", config.level);
398 output.tag.set_property("OUTPUT", config.carrier_track);
399 output.tag.set_property("BANDS", config.bands);
401 output.tag.set_title("/VOCODER");
403 output.append_newline();
404 output.terminate_string();
407 void Vocoder::reconfigure()
409 need_reconfigure = 0;
411 if(current_bands != config.bands)
413 current_bands = config.bands;
414 for(int i = 0; i < config.bands; i++)
416 formant_bands[i].reset();
417 double a = 16.0 * i / (double)current_bands;
420 formant_bands[i].freq = 150 + 420 * a / 4.0;
422 formant_bands[i].freq = 600 * pow (1.23, a - 4.0);
424 double c = formant_bands[i].freq * 2 * M_PI / get_samplerate();
425 formant_bands[i].c = c * c;
427 formant_bands[i].f = 0.4 / c;
428 formant_bands[i].att =
429 1 / (6.0 + ((exp (formant_bands[i].freq
430 / get_samplerate()) - 1) * 10));
432 carrier_bands[i].copy_from(&formant_bands[i]);
434 output_bands[i].decay = decay_table[(int)a];
439 void Vocoder::do_bandpasses(VocoderBand *bands, double sample)
441 for(int i = 0; i < current_bands; i++)
443 bands[i].high1 = sample - bands[i].f * bands[i].mid1 - bands[i].low1;
444 bands[i].mid1 += bands[i].high1 * bands[i].c;
445 bands[i].low1 += bands[i].mid1;
447 bands[i].high2 = bands[i].low1 - bands[i].f * bands[i].mid2 -
449 bands[i].mid2 += bands[i].high2 * bands[i].c;
450 bands[i].low2 += bands[i].mid2;
451 bands[i].y = bands[i].high2 * bands[i].att;
456 int Vocoder::process_buffer(int64_t size,
458 int64_t start_position,
461 need_reconfigure |= load_configuration();
462 if(need_reconfigure) reconfigure();
464 // Process all except output channel
465 int carrier_track = config.carrier_track;
466 CLAMP(carrier_track, 0, PluginClient::get_total_buffers() - 1);
467 int formant_track = 0;
468 if(carrier_track == 0) formant_track = 1;
469 CLAMP(formant_track, 0, PluginClient::get_total_buffers() - 1);
472 // Copy level controls to band levels
473 for(int i = 0; i < current_bands; i++)
475 output_bands[i].level = 1.0;
479 for(int i = 0; i < get_total_buffers(); i++)
481 read_samples(buffer[i],
488 double *carrier_samples = buffer[carrier_track]->get_data();
489 double *formant_samples = buffer[formant_track]->get_data();
490 double *output = buffer[0]->get_data();
491 double wetness = DB::fromdb(config.wetness);
492 double level = DB::fromdb(config.level);
493 for(int i = 0; i < size; i++)
495 do_bandpasses(carrier_bands, carrier_samples[i]);
496 do_bandpasses(formant_bands, formant_samples[i]);
498 output[i] *= wetness;
500 for(int j = 0; j < current_bands; j++)
502 output_bands[j].oldval = output_bands[j].oldval +
503 (fabs (formant_bands[j].y) -
504 output_bands[j].oldval) *
505 output_bands[j].decay;
506 double x = carrier_bands[j].y * output_bands[j].oldval;
507 accum += x * output_bands[j].level;
527 void Vocoder::reset()
529 need_reconfigure = 1;
533 void Vocoder::update_gui()
537 if(load_configuration())
539 ((VocoderWindow*)thread->window)->lock_window("Vocoder::update_gui");
540 ((VocoderWindow*)thread->window)->update_gui();
541 ((VocoderWindow*)thread->window)->unlock_window();