no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / reverb / reverb.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2017-2019 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "clip.h"
21 #include "confirmsave.h"
22 #include "bchash.h"
23 #include "bcsignals.h"
24 #include "errorbox.h"
25 #include "filexml.h"
26 #include "language.h"
27 #include "reverb.h"
28 #include "reverbwindow.h"
29 #include "samples.h"
30 #include "transportque.inc"
31 #include "units.h"
32
33 #include "vframe.h"
34
35 #include <math.h>
36 #include <string.h>
37 #include <time.h>
38 #include <unistd.h>
39
40
41 PluginClient* new_plugin(PluginServer *server)
42 {
43         return new Reverb(server);
44 }
45
46 Reverb::Reverb(PluginServer *server)
47  : PluginAClient(server)
48 {
49         srand(time(0));
50         ref_channels = 0;
51         ref_offsets = 0;
52         ref_levels = 0;
53         dsp_in = 0;
54         dsp_in_length = 0;
55         dsp_in_allocated = 0;
56         need_reconfigure = 1;
57         envelope = 0;
58         last_position = 0;
59         start_pos = 0;
60         dir = 0;
61         fft = 0;
62 }
63
64 Reverb::~Reverb()
65 {
66         if( fft ) {
67                 for( int i = 0; i < total_in_buffers; i++ ) {
68                         delete [] dsp_in[i];
69                         delete [] ref_channels[i];
70                         delete [] ref_offsets[i];
71                         delete [] ref_levels[i];
72                         delete fft[i];
73                 }
74
75                 delete [] fft;
76                 delete [] dsp_in;
77                 delete [] ref_channels;
78                 delete [] ref_offsets;
79                 delete [] ref_levels;
80                 delete engine;
81         }
82         delete [] envelope;
83 }
84
85 const char* Reverb::plugin_title() { return N_("Reverb"); }
86 int Reverb::is_realtime() { return 1; }
87 int Reverb::is_multichannel() { return 1; }
88 int Reverb::is_synthesis() { return 1; }
89
90
91 void Reverb::reset()
92 {
93         dsp_in_length = 0;
94         if( fft ) {
95                 for( int i = 0; i < PluginClient::total_in_buffers; i++ )
96                         if( fft[i] ) fft[i]->delete_fft();
97         }
98         if( dsp_in ) {
99                 for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
100                         if( !dsp_in[i] ) continue;
101                         bzero(dsp_in[i], sizeof(double) * dsp_in_allocated);
102                 }
103         }
104         need_reconfigure = 1;
105 }
106
107 void Reverb::render_stop()
108 {
109         reset();
110 }
111
112
113 int Reverb::process_buffer(int64_t size, Samples **buffer,
114                 int64_t start_position, int sample_rate)
115 {
116         start_pos = (double)start_position / sample_rate;
117         dir = get_direction() == PLAY_REVERSE ? -1 : 1;
118         need_reconfigure |= load_configuration();
119
120         if( need_reconfigure ) {
121                 need_reconfigure = 0;
122
123                 calculate_envelope();
124
125                 if( fft && fft[0]->window_size != config.window_size ) {
126                         for( int i = 0; i < PluginClient::total_in_buffers; i++ )
127                                 delete fft[i];
128                         delete [] fft;  fft = 0;
129                 }
130
131                 if( !fft ) {
132                         fft = new ReverbFFT*[PluginClient::total_in_buffers];
133                         for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
134                                 fft[i] = new ReverbFFT(this, i);
135                                 fft[i]->initialize(config.window_size);
136                         }
137                 }
138
139 // allocate the stuff
140                 if( !dsp_in ) {
141                         dsp_in = new double*[PluginClient::total_in_buffers];
142                         ref_channels = new int*[PluginClient::total_in_buffers];
143                         ref_offsets = new int*[PluginClient::total_in_buffers];
144                         ref_levels = new double*[PluginClient::total_in_buffers];
145                         for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
146                                 dsp_in[i] = 0;
147                                 ref_channels[i] = 0;
148                                 ref_offsets[i] = 0;
149                                 ref_levels[i] = 0;
150                         }
151                         engine = new ReverbEngine(this);
152                 }
153
154
155                 for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
156                         delete [] ref_channels[i];  ref_channels[i] = new int[config.ref_total];
157                         delete [] ref_offsets[i];   ref_offsets[i] = new int[config.ref_total];
158                         delete [] ref_levels[i];    ref_levels[i] = new double[config.ref_total];
159
160 // 1st reflection is fixed by the user
161                         ref_channels[i][0] = i;
162                         ref_offsets[i][0] = config.delay_init * project_sample_rate / 1000;
163                         ref_levels[i][0] = db.fromdb(config.ref_level1);
164
165                         int64_t ref_division = config.ref_length *
166                                 project_sample_rate / 1000 / (config.ref_total + 1);
167                         for( int j = 1; j < config.ref_total; j++ ) {
168 // set random channels for remaining reflections
169                                 ref_channels[i][j] = rand() % total_in_buffers;
170
171 // set random offsets after first reflection
172                                 ref_offsets[i][j] = ref_offsets[i][0];
173                                 ref_offsets[i][j] += ref_division * j - (rand() % ref_division) / 2;
174 // set changing levels
175                                 double level_db = config.ref_level1 +
176                                         (config.ref_level2 - config.ref_level1) *
177                                         (j - 1) / (config.ref_total - 1);
178                                 ref_levels[i][j] = DB::fromdb(level_db);
179                         }
180                 }
181         }
182
183 // guess DSP allocation from the reflection time & requested samples
184         int new_dsp_allocated = size +
185                 ((int64_t)config.delay_init + config.ref_length) *
186                 project_sample_rate / 1000 + 1;
187         reallocate_dsp(new_dsp_allocated);
188
189 // Always read in the new samples & process the bandpass, even if there is no
190 // bandpass.  This way the user can tweek the bandpass without causing glitches.
191         for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
192                 new_dsp_length = dsp_in_length;
193                 new_spectrogram_frames = 0;
194                 fft[i]->process_buffer(start_position, size,
195                         buffer[i],   // temporary storage for the bandpassed output
196                         get_direction());
197         }
198
199 // update the length with what the FFT reads appended
200         dsp_in_length = new_dsp_length;
201
202 // now paint the reflections
203         engine->process_packages();
204
205 // copy the DSP buffer to the output
206         for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
207                 memcpy(buffer[i]->get_data(), dsp_in[i], size * sizeof(double));
208         }
209
210 // shift the DSP buffer forward
211         int remain = dsp_in_allocated - size;
212         for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
213                 memcpy(dsp_in[i], dsp_in[i] + size, remain * sizeof(double));
214                 bzero(dsp_in[i] + remain, size * sizeof(double));
215         }
216
217         dsp_in_length -= size;
218         last_position = start_position + dir * size;
219         return 0;
220 }
221
222
223 void Reverb::reallocate_dsp(int new_dsp_allocated)
224 {
225         if( new_dsp_allocated > dsp_in_allocated ) {
226 // copy samples already read into the new buffers
227                 for( int i = 0; i < PluginClient::total_in_buffers; i++ ) {
228                         double *old_dsp = dsp_in[i];
229                         double *new_dsp = new double[new_dsp_allocated];
230
231                         if( old_dsp ) {
232                                 memcpy(new_dsp, old_dsp, sizeof(double) * dsp_in_length);
233                                 delete [] old_dsp;
234                         }
235                         bzero(new_dsp + dsp_in_allocated,
236                                 sizeof(double) * (new_dsp_allocated - dsp_in_allocated));
237                         dsp_in[i] = new_dsp;
238                 }
239                 dsp_in_allocated = new_dsp_allocated;
240         }
241
242 }
243
244
245 double Reverb::gauss(double sigma, double center, double x)
246 {
247         if( EQUIV(sigma, 0) ) sigma = 0.01;
248
249         double result = 1.0 / sqrt(2 * M_PI * sigma * sigma) *
250                 exp(-(x - center) * (x - center) / (2 * sigma * sigma));
251         return result;
252 }
253
254 void Reverb::calculate_envelope()
255 {
256 // assume the window size changed
257         delete [] envelope;
258         int window_size2 = config.window_size/2;
259         envelope = new double[window_size2];
260
261         int max_freq = Freq::tofreq_f(TOTALFREQS-1);
262         int nyquist = PluginAClient::project_sample_rate/2;
263         int low = config.low;
264         int high = config.high;
265
266 // limit the frequencies
267         if( high >= max_freq ) high = nyquist;
268         if( low > high ) low = high;
269
270 // frequency slots of the edge
271         double edge = (1.0 - config.q) * TOTALFREQS/2;
272         double low_slot = Freq::fromfreq_f(low);
273         double high_slot = Freq::fromfreq_f(high);
274         for( int i = 0; i < window_size2; i++ ) {
275                 double freq = i * nyquist / window_size2;
276                 double slot = Freq::fromfreq_f(freq);
277
278 // printf("Reverb::calculate_envelope %d i=%d freq=%f slot=%f slot1=%f\n",
279 // __LINE__, i, freq, slot, low_slot - edge);
280                 if( slot < low_slot - edge ) {
281                         envelope[i] = 0.0;
282                 }
283                 else if( slot < low_slot ) {
284 #ifndef LOG_CROSSOVER
285                         envelope[i] = 1.0 - (low_slot - slot) / edge;
286 #else
287                         envelope[i] = DB::fromdb((low_slot - slot) * INFINITYGAIN / edge);
288 #endif
289                 }
290                 else if( slot < high_slot ) {
291                         envelope[i] = 1.0;
292                 }
293                 else if( slot < high_slot + edge ) {
294 #ifndef LOG_CROSSOVER
295                         envelope[i] = 1.0 - (slot - high_slot) / edge;
296 #else
297                         envelope[i] = DB::fromdb((slot - high_slot) * INFINITYGAIN / edge);
298 #endif
299                 }
300                 else {
301                         envelope[i] = 0.0;
302                 }
303         }
304 }
305
306
307 NEW_WINDOW_MACRO(Reverb, ReverbWindow)
308
309
310 LOAD_CONFIGURATION_MACRO(Reverb, ReverbConfig)
311
312
313 void Reverb::save_data(KeyFrame *keyframe)
314 {
315         FileXML output;
316         output.set_shared_output(keyframe->xbuf);
317         output.tag.set_title("REVERB");
318         output.tag.set_property("LEVELINIT", config.level_init);
319         output.tag.set_property("DELAY_INIT", config.delay_init);
320         output.tag.set_property("REF_LEVEL1", config.ref_level1);
321         output.tag.set_property("REF_LEVEL2", config.ref_level2);
322         output.tag.set_property("REF_TOTAL", config.ref_total);
323         output.tag.set_property("REF_LENGTH", config.ref_length);
324         output.tag.set_property("HIGH", config.high);
325         output.tag.set_property("LOW", config.low);
326         output.tag.set_property("Q", config.q);
327         output.tag.set_property("WINDOW_SIZE", config.window_size);
328         output.append_tag();
329         output.append_newline();
330         output.terminate_string();
331 }
332
333 void Reverb::read_data(KeyFrame *keyframe)
334 {
335         FileXML input;
336         input.set_shared_input(keyframe->xbuf);
337         int result = 0;
338         while( !(result = input.read_tag()) ) {
339                 if( input.tag.title_is("REVERB") ) {
340                         config.level_init = input.tag.get_property("LEVELINIT", config.level_init);
341                         config.delay_init = input.tag.get_property("DELAY_INIT", config.delay_init);
342                         config.ref_level1 = input.tag.get_property("REF_LEVEL1", config.ref_level1);
343                         config.ref_level2 = input.tag.get_property("REF_LEVEL2", config.ref_level2);
344                         config.ref_total = input.tag.get_property("REF_TOTAL", config.ref_total);
345                         config.ref_length = input.tag.get_property("REF_LENGTH", config.ref_length);
346                         config.high = input.tag.get_property("HIGH", config.high);
347                         config.low = input.tag.get_property("LOW", config.low);
348                         config.q = input.tag.get_property("Q", config.q);
349                         config.window_size = input.tag.get_property("WINDOW_SIZE", config.window_size);
350                 }
351         }
352
353         config.boundaries();
354 }
355
356 void Reverb::update_gui()
357 {
358         if( !thread ) return;
359         ReverbWindow *window = (ReverbWindow *)thread->window;
360         if( !window ) return;
361         int reconfigured = load_configuration();
362         int pending = pending_gui_frame();
363         if( !reconfigured && !pending ) return;
364         window->lock_window("Reverb::update_gui 1");
365         if( reconfigured )
366                 window->update();
367         if( pending )
368                 window->update_canvas();
369         window->unlock_window();
370 }
371
372 ReverbClientFrame::ReverbClientFrame(int size)
373  : CompressorFreqFrame()
374 {
375         data = new double[size];
376         bzero(data, sizeof(double) * size);
377         data_size = size;
378 }
379
380 ReverbClientFrame::~ReverbClientFrame()
381 {
382         delete [] data;  data = 0;
383 }
384
385 ReverbFFT::ReverbFFT(Reverb *plugin, int channel)
386 {
387         this->plugin = plugin;
388         this->channel = channel;
389 }
390
391 ReverbFFT::~ReverbFFT()
392 {
393 }
394
395 int ReverbFFT::signal_process()
396 {
397 // Create new spectrogram for updating the GUI
398         frame = new ReverbClientFrame(window_size/2);
399         frame->nyquist = plugin->PluginAClient::project_sample_rate/2;
400         frame->position = plugin->start_pos + plugin->dir *
401                 (double)plugin->new_spectrogram_frames * frame->data_size /
402                 plugin->get_samplerate();
403         plugin->add_gui_frame(frame);
404
405         for( int i=0; i<frame->data_size; i++ ) {
406                 double env = plugin->envelope[i];
407                 double fr = freq_real[i], fi = freq_imag[i];
408 // scale complex signal by envelope
409                 freq_real[i] = fr * env;
410                 freq_imag[i] = fi * env;
411                 double mag = sqrt(fr*fr + fi*fi);
412                 double out = mag * env;
413 // update the spectrogram with the output
414                 if( frame->data[i] < out )
415                         frame->data[i] = out;
416 // get the maximum output in the frequency domain
417                 if( frame->freq_max < out )
418                         frame->freq_max = out;
419         }
420
421         symmetry(window_size, freq_real, freq_imag);
422         return 0;
423 }
424
425 int ReverbFFT::post_process()
426 {
427 // get the maximum output in the time domain
428         double time_max = 0;
429         for( int i=0; i<window_size; ++i ) {
430                 if( fabs(output_real[i]) > time_max )
431                         time_max = fabs(output_real[i]);
432         }
433         if( time_max > frame->time_max )
434                 frame->time_max = time_max;
435
436         ++plugin->new_spectrogram_frames;
437         return 0;
438 }
439
440
441 int ReverbFFT::read_samples(int64_t output_sample, int samples, Samples *buffer)
442 {
443         int result = plugin->read_samples(buffer,
444                 channel, plugin->get_samplerate(), output_sample, samples);
445
446 // append original samples to the DSP buffer as the initial reflection
447         int new_dsp_allocation = plugin->new_dsp_length + samples;
448         plugin->reallocate_dsp(new_dsp_allocation);
449         double *dst = plugin->dsp_in[channel] + plugin->new_dsp_length;
450         double *src = buffer->get_data();
451         double level = DB::fromdb(plugin->config.level_init);
452         if( plugin->config.level_init <= INFINITYGAIN ) {
453                 level = 0;
454         }
455
456         for( int i = 0; i < samples; i++ ) {
457                 *dst++ += *src++ * level;
458         }
459
460         plugin->new_dsp_length += samples;
461         return result;
462 }
463
464
465 ReverbPackage::ReverbPackage()
466  : LoadPackage()
467 {
468 }
469
470
471 ReverbUnit::ReverbUnit(ReverbEngine *engine, Reverb *plugin)
472  : LoadClient(engine)
473 {
474         this->plugin = plugin;
475 }
476
477 ReverbUnit::~ReverbUnit()
478 {
479 }
480
481 void ReverbUnit::process_package(LoadPackage *package)
482 {
483         ReverbPackage *pkg = (ReverbPackage*)package;
484         int channel = pkg->channel;
485
486         for( int i = 0; i < plugin->config.ref_total; i++ ) {
487                 int src_channel = plugin->ref_channels[channel][i];
488                 int dst_offset = plugin->ref_offsets[channel][i];
489                 double level = plugin->ref_levels[channel][i];
490                 double *dst = plugin->dsp_in[channel] + dst_offset;
491                 double *src = plugin->get_output(src_channel)->get_data();
492                 int size = plugin->get_buffer_size();
493
494                 if( size + dst_offset > plugin->dsp_in_allocated ) {
495                         printf("ReverbUnit::process_package %d size=%d dst_offset=%d needed=%d allocated=%d\n",
496                         __LINE__, size, dst_offset, size + dst_offset, plugin->dsp_in_allocated);
497                 }
498
499                 for( int j = 0; j < size; j++ )
500                         *dst++ += *src++ * level;
501         }
502 }
503
504
505
506 ReverbEngine::ReverbEngine(Reverb *plugin)
507  : LoadServer(plugin->PluginClient::smp + 1, plugin->total_in_buffers)
508 {
509         this->plugin = plugin;
510 }
511
512 ReverbEngine::~ReverbEngine()
513 {
514 }
515
516
517 void ReverbEngine::init_packages()
518 {
519         for( int i = 0; i < LoadServer::get_total_packages(); i++ ) {
520                 ReverbPackage *package = (ReverbPackage*)LoadServer::get_package(i);
521                 package->channel = i;
522         }
523 }
524
525 LoadClient* ReverbEngine::new_client()
526 {
527         return new ReverbUnit(this, plugin);
528 }
529
530 LoadPackage* ReverbEngine::new_package()
531 {
532         return new ReverbPackage;
533 }
534
535
536 ReverbConfig::ReverbConfig()
537 {
538         level_init = 0;
539         delay_init = 0;
540         ref_level1 = -20;
541         ref_level2 = INFINITYGAIN;
542         ref_total = 128;
543         ref_length = 600;
544         high = Freq::tofreq(TOTALFREQS);
545         low = Freq::tofreq(0);
546         q = 1.0;
547         window_size = 4096;
548 }
549
550 int ReverbConfig::equivalent(ReverbConfig &that)
551 {
552         return (EQUIV(level_init, that.level_init) &&
553                 delay_init == that.delay_init &&
554                 EQUIV(ref_level1, that.ref_level1) &&
555                 EQUIV(ref_level2, that.ref_level2) &&
556                 ref_total == that.ref_total &&
557                 ref_length == that.ref_length &&
558                 high == that.high &&
559                 low == that.low &&
560                 EQUIV(q, that.q) &&
561                 window_size == that.window_size);
562 }
563
564 void ReverbConfig::copy_from(ReverbConfig &that)
565 {
566         level_init = that.level_init;
567         delay_init = that.delay_init;
568         ref_level1 = that.ref_level1;
569         ref_level2 = that.ref_level2;
570         ref_total = that.ref_total;
571         ref_length = that.ref_length;
572         high = that.high;
573         low = that.low;
574         q = that.q;
575         window_size = that.window_size;
576 }
577
578 void ReverbConfig::interpolate(ReverbConfig &prev, ReverbConfig &next,
579         int64_t prev_frame, int64_t next_frame, int64_t current_frame)
580 {
581         level_init = prev.level_init;
582         delay_init = prev.delay_init;
583         ref_level1 = prev.ref_level1;
584         ref_level2 = prev.ref_level2;
585         ref_total = prev.ref_total;
586         ref_length = prev.ref_length;
587         high = prev.high;
588         low = prev.low;
589         q = prev.q;
590         window_size = prev.window_size;
591 }
592
593 void ReverbConfig::boundaries()
594 {
595         CLAMP(level_init, INFINITYGAIN, 0);
596         CLAMP(delay_init, 0, MAX_DELAY_INIT);
597         CLAMP(ref_level1, INFINITYGAIN, 0);
598         CLAMP(ref_level2, INFINITYGAIN, 0);
599         CLAMP(ref_total, MIN_REFLECTIONS, MAX_REFLECTIONS);
600         CLAMP(ref_length, MIN_REFLENGTH, MAX_REFLENGTH);
601         CLAMP(high, 0, Freq::tofreq(TOTALFREQS));
602         CLAMP(low, 0, Freq::tofreq(TOTALFREQS));
603         CLAMP(q, 0.0, 1.0);
604 }
605
606 void ReverbConfig::dump()
607 {
608         printf("ReverbConfig::dump %d level_init=%f delay_init=%d ref_level1=%f"
609                 " ref_level2=%f ref_total=%d ref_length=%d high=%d low=%d q=%f\n",
610                 __LINE__, level_init, (int)delay_init, ref_level1, ref_level2,
611                 (int)ref_total, (int)ref_length, (int)high, (int)low, q);
612 }
613