17a1de090c80e108617b45be8046b34b3bf34e1c
[goodguy/history.git] / cinelerra-5.1 / plugins / vocoder / vocoder.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22
23 // Originally from the following:
24 /* vocoder.c
25    Version 0.3
26
27    LADSPA Unique ID: 1441
28
29    Version 0.3
30    Added support for changing bands in real time 2003-12-09
31
32    Version 0.2
33    Adapted to LADSPA by Josh Green <jgreen@users.sourceforge.net>
34    15.6.2001 (for the LinuxTag 2001!)
35
36    Original program can be found at:
37    http://www.sirlab.de/linux/
38    Author: Achim Settelmeier <settel-linux@sirlab.de>
39 */
40
41
42
43 #include "bcdisplayinfo.h"
44 #include "bcsignals.h"
45 #include "clip.h"
46 #include "bchash.h"
47 #include "filexml.h"
48 #include "language.h"
49 #include "samples.h"
50 #include "theme.h"
51 #include "units.h"
52 #include "vframe.h"
53 #include "vocoder.h"
54
55 #include <math.h>
56 #include <string.h>
57
58
59
60
61
62
63
64
65
66 REGISTER_PLUGIN(Vocoder)
67
68
69
70
71 //#define USE_BANDWIDTH
72
73 const double decay_table[] =
74 {
75   1/100.0,
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
81 };
82
83
84 VocoderBand::VocoderBand()
85 {
86         reset();
87 }
88
89 void VocoderBand::reset()
90 {
91         c = f = att = 0;
92
93         freq = 0;
94         low1 = low2 = 0;
95         mid1 = mid2 = 0;
96         high1 = high2 = 0;
97         y = 0;
98 }
99
100 void VocoderBand::copy_from(VocoderBand *src)
101 {
102         c = src->c;
103         f = src->f;
104         att = src->att;
105
106         freq = src->freq;
107         low1 = src->low1;
108         low2 = src->low2;
109         mid1 = src->mid1;
110         mid2 = src->mid2;
111         high1 = src->high1;
112         high2 = src->high2;
113         y = src->y;
114 }
115
116
117 VocoderOut::VocoderOut()
118 {
119         reset();
120 }
121
122 void VocoderOut::reset()
123 {
124         decay = 0;
125         oldval = 0;
126         level = 0;       /* 0.0 - 1.0 level of this output band */
127 }
128
129
130 VocoderConfig::VocoderConfig()
131 {
132         wetness = INFINITYGAIN;
133         carrier_track = 0;
134         bands = MAX_BANDS;
135         level = 0.0;
136 }
137
138
139 int VocoderConfig::equivalent(VocoderConfig &that)
140 {
141         if(!EQUIV(wetness, that.wetness) ||
142                 !EQUIV(level, that.level) ||
143                 carrier_track != that.carrier_track ||
144                 bands != that.bands) return 0;
145         return 1;
146 }
147
148 void VocoderConfig::copy_from(VocoderConfig &that)
149 {
150         wetness = that.wetness;
151         carrier_track = that.carrier_track;
152         bands = that.bands;
153         level = that.level;
154         CLAMP(bands, 1, MAX_BANDS);
155 }
156
157 void VocoderConfig::interpolate(VocoderConfig &prev,
158                 VocoderConfig &next,
159                 int64_t prev_frame,
160                 int64_t next_frame,
161                 int64_t current_frame)
162 {
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;
168         bands = prev.bands;
169         CLAMP(bands, 1, MAX_BANDS);
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183 VocoderWetness::VocoderWetness(Vocoder *plugin, int x, int y)
184  : BC_FPot(x, y, plugin->config.wetness, INFINITYGAIN, 0)
185 {
186         this->plugin = plugin;
187 }
188
189 int VocoderWetness::handle_event()
190 {
191         plugin->config.wetness = get_value();
192         plugin->send_configure_change();
193         return 1;
194 }
195
196
197
198
199
200 VocoderLevel::VocoderLevel(Vocoder *plugin, int x, int y)
201  : BC_FPot(x, y, plugin->config.level, INFINITYGAIN, 40)
202 {
203         this->plugin = plugin;
204 }
205
206 int VocoderLevel::handle_event()
207 {
208         plugin->config.level = get_value();
209         plugin->send_configure_change();
210         return 1;
211 }
212
213
214
215
216
217
218
219
220
221 VocoderCarrier::VocoderCarrier(Vocoder *plugin,
222         VocoderWindow *window,
223         int x,
224         int y)
225  : BC_TumbleTextBox(window,
226         plugin->config.carrier_track,
227         0,
228         256,
229         x,
230         y,
231         100)
232 {
233         this->plugin = plugin;
234 }
235
236 int VocoderCarrier::handle_event()
237 {
238         plugin->config.carrier_track = atoi(get_text());
239         plugin->send_configure_change();
240         return 1;
241 }
242
243
244
245 VocoderBands::VocoderBands(Vocoder *plugin,
246         VocoderWindow *window,
247         int x,
248         int y)
249  : BC_TumbleTextBox(window,
250         plugin->config.bands,
251         1,
252         MAX_BANDS,
253         x,
254         y,
255         100)
256 {
257         this->plugin = plugin;
258 }
259
260 int VocoderBands::handle_event()
261 {
262         plugin->config.bands = atoi(get_text());
263         plugin->send_configure_change();
264         return 1;
265 }
266
267
268
269
270
271 VocoderWindow::VocoderWindow(Vocoder *plugin)
272  : PluginClientWindow(plugin,
273         320,
274         150,
275         320,
276         150,
277         0)
278 {
279         this->plugin = plugin;
280 }
281
282 VocoderWindow::~VocoderWindow()
283 {
284 }
285
286 void VocoderWindow::create_objects()
287 {
288         int x = plugin->get_theme()->widget_border;
289         int y = plugin->get_theme()->widget_border;
290         BC_Title *title = 0;
291
292         int x1 = x;
293         int y1 = y;
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);
299
300         x = x2;
301         y = y1;
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;
306
307         x = x1;
308         add_subwindow(title = new BC_Title(x, y, _("Carrier Track:")));
309         output = new VocoderCarrier(plugin,
310                 this,
311                 x + title->get_w() + plugin->get_theme()->widget_border,
312                 y);
313         output->create_objects();
314         y += output->get_h() + plugin->get_theme()->widget_border;
315
316         add_subwindow(title = new BC_Title(x, y, _("Bands:")));
317         bands = new VocoderBands(plugin,
318                 this,
319                 x + title->get_w() + plugin->get_theme()->widget_border,
320                 y);
321         bands->create_objects();
322         y += bands->get_h() + plugin->get_theme()->widget_border;
323
324         show_window();
325 }
326
327
328
329 void VocoderWindow::update_gui()
330 {
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);
335 }
336
337
338
339
340
341
342
343
344
345
346
347 Vocoder::Vocoder(PluginServer *server)
348  : PluginAClient(server)
349 {
350         need_reconfigure = 1;
351         current_bands = 0;
352 }
353
354 Vocoder::~Vocoder()
355 {
356 }
357
358 NEW_WINDOW_MACRO(Vocoder, VocoderWindow)
359
360 LOAD_CONFIGURATION_MACRO(Vocoder, VocoderConfig)
361
362
363 const char* Vocoder::plugin_title() { return _("Vocoder"); }
364 int Vocoder::is_realtime() { return 1; }
365 int Vocoder::is_multichannel() { return 1; }
366
367 void Vocoder::read_data(KeyFrame *keyframe)
368 {
369         FileXML input;
370         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
371
372         int result = 0;
373         while(!result)
374         {
375                 result = input.read_tag();
376
377                 if(!result)
378                 {
379                         if(input.tag.title_is("VOCODER"))
380                         {
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);
385                         }
386                 }
387         }
388 }
389
390 void Vocoder::save_data(KeyFrame *keyframe)
391 {
392         FileXML output;
393         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
394
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);
400         output.append_tag();
401         output.tag.set_title("/VOCODER");
402         output.append_tag();
403         output.append_newline();
404         output.terminate_string();
405 }
406
407 void Vocoder::reconfigure()
408 {
409         need_reconfigure = 0;
410
411         if(current_bands != config.bands)
412         {
413                 current_bands = config.bands;
414                 for(int i = 0; i < config.bands; i++)
415                 {
416                         formant_bands[i].reset();
417                         double a = 16.0 * i / (double)current_bands;
418
419                         if(a < 4.0)
420                                 formant_bands[i].freq = 150 + 420 * a / 4.0;
421                         else
422                                 formant_bands[i].freq = 600 * pow (1.23, a - 4.0);
423
424                         double c = formant_bands[i].freq * 2 * M_PI / get_samplerate();
425                         formant_bands[i].c = c * c;
426
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));
431
432                   carrier_bands[i].copy_from(&formant_bands[i]);
433
434                   output_bands[i].decay = decay_table[(int)a];
435                 }
436         }
437 }
438
439 void Vocoder::do_bandpasses(VocoderBand *bands, double sample)
440 {
441         for(int i = 0; i < current_bands; i++)
442     {
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;
446
447         bands[i].high2 = bands[i].low1 - bands[i].f * bands[i].mid2 -
448                         bands[i].low2;
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;
452     }
453 }
454
455
456 int Vocoder::process_buffer(int64_t size,
457         Samples **buffer,
458         int64_t start_position,
459         int sample_rate)
460 {
461         need_reconfigure |= load_configuration();
462         if(need_reconfigure) reconfigure();
463
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);
470
471
472 // Copy level controls to band levels
473         for(int i = 0; i < current_bands; i++)
474         {
475                 output_bands[i].level = 1.0;
476         }
477
478
479         for(int i = 0; i < get_total_buffers(); i++)
480         {
481                 read_samples(buffer[i],
482                         i,
483                         get_samplerate(),
484                         start_position,
485                         size);
486         }
487
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++)
494         {
495                 do_bandpasses(carrier_bands, carrier_samples[i]);
496                 do_bandpasses(formant_bands, formant_samples[i]);
497
498                 output[i] *= wetness;
499                 double accum = 0;
500                 for(int j = 0; j < current_bands; j++)
501                 {
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;
508                 }
509
510                 accum *= level;
511
512                 output[i] += accum;
513         }
514
515         return 0;
516 }
517
518
519
520
521
522
523
524
525
526
527 void Vocoder::reset()
528 {
529         need_reconfigure = 1;
530         thread = 0;
531 }
532
533 void Vocoder::update_gui()
534 {
535         if(thread)
536         {
537                 if(load_configuration())
538                 {
539                         ((VocoderWindow*)thread->window)->lock_window("Vocoder::update_gui");
540                         ((VocoderWindow*)thread->window)->update_gui();
541                         ((VocoderWindow*)thread->window)->unlock_window();
542                 }
543         }
544 }
545
546
547