eb60c71dff2617ebe371031fe35b231bc297eb9c
[goodguy/history.git] / cinelerra-5.1 / plugins / reverb / reverb.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2017 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 #include "clip.h"
23 #include "confirmsave.h"
24 #include "bchash.h"
25 #include "bcsignals.h"
26 #include "errorbox.h"
27 #include "filexml.h"
28 #include "language.h"
29 #include "reverb.h"
30 #include "reverbwindow.h"
31 #include "samples.h"
32 #include "units.h"
33
34 #include "vframe.h"
35
36 #include <math.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40
41
42
43 PluginClient* new_plugin(PluginServer *server)
44 {
45         return new Reverb(server);
46 }
47
48
49
50 Reverb::Reverb(PluginServer *server)
51  : PluginAClient(server)
52 {
53         srand(time(0));
54         redo_buffers = 1;       // set to redo buffers before the first render
55         dsp_in_length = 0;
56         ref_channels = 0;
57         ref_offsets = 0;
58         ref_levels = 0;
59         ref_lowpass = 0;
60         dsp_in = 0;
61         lowpass_in1 = 0;
62         lowpass_in2 = 0;
63         initialized = 0;
64
65 }
66
67 Reverb::~Reverb()
68 {
69
70
71         if(initialized)
72         {
73                 for(int i = 0; i < total_in_buffers; i++)
74                 {
75                         delete [] dsp_in[i];
76                         delete [] ref_channels[i];
77                         delete [] ref_offsets[i];
78                         delete [] ref_levels[i];
79                         delete [] ref_lowpass[i];
80                         delete [] lowpass_in1[i];
81                         delete [] lowpass_in2[i];
82                 }
83
84                 delete [] dsp_in;
85                 delete [] ref_channels;
86                 delete [] ref_offsets;
87                 delete [] ref_levels;
88                 delete [] ref_lowpass;
89                 delete [] lowpass_in1;
90                 delete [] lowpass_in2;
91
92                 for(int i = 0; i < (smp + 1); i++)
93                 {
94                         delete engine[i];
95                 }
96                 delete [] engine;
97                 initialized = 0;
98         }
99 }
100
101 const char* Reverb::plugin_title() { return _("Reverb"); }
102 int Reverb::is_realtime() { return 1; }
103 int Reverb::is_multichannel() { return 1; }
104 int Reverb::is_synthesis() { return 1; }
105
106 int Reverb::process_realtime(int64_t size,
107         Samples **input_ptr,
108         Samples **output_ptr)
109 {
110         int64_t new_dsp_length, i, j;
111         main_in = new double*[total_in_buffers];
112         main_out = new double*[total_in_buffers];
113
114         for(i = 0; i < total_in_buffers; i++)
115         {
116                 main_in[i] = input_ptr[i]->get_data();
117                 main_out[i] = output_ptr[i]->get_data();
118         }
119
120 //printf("Reverb::process_realtime 1\n");
121         redo_buffers |= load_configuration();
122
123 //printf("Reverb::process_realtime 1\n");
124         if(!config.ref_total)
125         {
126                 delete [] main_in;
127                 delete [] main_out;
128                 return 0;
129         }
130
131
132         if(!initialized)
133         {
134                 dsp_in = new double*[total_in_buffers];
135                 ref_channels = new int64_t*[total_in_buffers];
136                 ref_offsets = new int64_t*[total_in_buffers];
137                 ref_levels = new double*[total_in_buffers];
138                 ref_lowpass = new int64_t*[total_in_buffers];
139                 lowpass_in1 = new double*[total_in_buffers];
140                 lowpass_in2 = new double*[total_in_buffers];
141
142
143
144                 for(i = 0; i < total_in_buffers; i++)
145                 {
146                         dsp_in[i] = new double[1];
147                         ref_channels[i] = new int64_t[1];
148                         ref_offsets[i] = new int64_t[1];
149                         ref_levels[i] = new double[1];
150                         ref_lowpass[i] = new int64_t[1];
151                         lowpass_in1[i] = new double[1];
152                         lowpass_in2[i] = new double[1];
153                 }
154
155                 engine = new ReverbEngine*[(smp + 1)];
156                 for(i = 0; i < (smp + 1); i++)
157                 {
158                         engine[i] = new ReverbEngine(this);
159 //printf("Reverb::start_realtime %d\n", Thread::calculate_realtime());
160 // Realtime priority moved to sound driver
161 //              engine[i]->set_realtime(realtime_priority);
162                         engine[i]->start();
163                 }
164                 initialized = 1;
165                 redo_buffers = 1;
166         }
167
168         new_dsp_length = size +
169                 ((int64_t)config.delay_init + config.ref_length) * project_sample_rate / 1000 + 1;
170
171         if(redo_buffers || new_dsp_length != dsp_in_length)
172         {
173                 for(i = 0; i < total_in_buffers; i++)
174                 {
175                         double *old_dsp = dsp_in[i];
176                         double *new_dsp = new double[new_dsp_length];
177                         for(j = 0; j < dsp_in_length && j < new_dsp_length; j++)
178                                 new_dsp[j] = old_dsp[j];
179
180
181                         for( ; j < new_dsp_length; j++) new_dsp[j] = 0;
182                         delete [] old_dsp;
183                         dsp_in[i] = new_dsp;
184                 }
185
186                 dsp_in_length = new_dsp_length;
187                 redo_buffers = 1;
188         }
189 //printf("Reverb::process_realtime 1\n");
190
191         if(redo_buffers)
192         {
193                 for(i = 0; i < total_in_buffers; i++)
194                 {
195                         delete [] ref_channels[i];
196                         delete [] ref_offsets[i];
197                         delete [] ref_lowpass[i];
198                         delete [] ref_levels[i];
199                         delete [] lowpass_in1[i];
200                         delete [] lowpass_in2[i];
201
202                         ref_channels[i] = new int64_t[config.ref_total + 1];
203                         ref_offsets[i] = new int64_t[config.ref_total + 1];
204                         ref_lowpass[i] = new int64_t[config.ref_total + 1];
205                         ref_levels[i] = new double[config.ref_total + 1];
206                         lowpass_in1[i] = new double[config.ref_total + 1];
207                         lowpass_in2[i] = new double[config.ref_total + 1];
208
209 // set channels
210                         ref_channels[i][0] = i;         // primary noise
211                         ref_channels[i][1] = i;         // first reflection
212 // set offsets
213                         ref_offsets[i][0] = 0;
214                         ref_offsets[i][1] = config.delay_init * project_sample_rate / 1000;
215 // set levels
216                         ref_levels[i][0] = db.fromdb(config.level_init);
217                         ref_levels[i][1] = db.fromdb(config.ref_level1);
218 // set lowpass
219                         ref_lowpass[i][0] = -1;     // ignore first noise
220                         ref_lowpass[i][1] = config.lowpass1;
221                         lowpass_in1[i][0] = 0;
222                         lowpass_in2[i][0] = 0;
223                         lowpass_in1[i][1] = 0;
224                         lowpass_in2[i][1] = 0;
225
226                         int64_t ref_division = config.ref_length * project_sample_rate / 1000 / (config.ref_total + 1);
227                         for(j = 2; j < config.ref_total + 1; j++)
228                         {
229 // set random channels for remaining reflections
230                                 ref_channels[i][j] = rand() % total_in_buffers;
231
232 // set random offsets after first reflection
233                                 ref_offsets[i][j] = ref_offsets[i][1];
234                                 if( ref_division > 0 )
235                                         ref_offsets[i][j] += ref_division * j - (rand() % ref_division) / 2;
236
237 // set changing levels
238                                 ref_levels[i][j] = db.fromdb(config.ref_level1 + (config.ref_level2 - config.ref_level1) / (config.ref_total - 1) * (j - 2));
239                                 //ref_levels[i][j] /= 100;
240
241 // set changing lowpass as linear
242                                 ref_lowpass[i][j] = (int64_t)(config.lowpass1 + (double)(config.lowpass2 - config.lowpass1) / (config.ref_total - 1) * (j - 2));
243                                 lowpass_in1[i][j] = 0;
244                                 lowpass_in2[i][j] = 0;
245                         }
246                 }
247
248                 redo_buffers = 0;
249         }
250 //printf("Reverb::process_realtime 1\n");
251
252         for(i = 0; i < total_in_buffers; )
253         {
254                 for(j = 0; j < (smp + 1) && (i + j) < total_in_buffers; j++)
255                 {
256                         engine[j]->process_overlays(i + j, size);
257                 }
258
259                 for(j = 0; j < (smp + 1) && i < total_in_buffers; j++, i++)
260                 {
261                         engine[j]->wait_process_overlays();
262                 }
263         }
264 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
265
266         for(i = 0; i < total_in_buffers; i++)
267         {
268                 double *current_out = main_out[i];
269                 double *current_in = dsp_in[i];
270
271                 for(j = 0; j < size; j++) current_out[j] = current_in[j];
272
273                 int64_t k;
274                 for(k = 0; j < dsp_in_length; j++, k++) current_in[k] = current_in[j];
275
276                 for(; k < dsp_in_length; k++) current_in[k] = 0;
277         }
278 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
279
280
281         delete [] main_in;
282         delete [] main_out;
283         return 0;
284 }
285
286
287 NEW_WINDOW_MACRO(Reverb, ReverbWindow)
288
289
290 LOAD_CONFIGURATION_MACRO(Reverb, ReverbConfig)
291
292
293 void Reverb::save_data(KeyFrame *keyframe)
294 {
295 //printf("Reverb::save_data 1\n");
296         FileXML output;
297 //printf("Reverb::save_data 1\n");
298
299 // cause xml file to store data directly in text
300         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
301 //printf("Reverb::save_data 1\n");
302
303         output.tag.set_title("REVERB");
304         output.tag.set_property("LEVELINIT", config.level_init);
305         output.tag.set_property("DELAY_INIT", config.delay_init);
306         output.tag.set_property("REF_LEVEL1", config.ref_level1);
307         output.tag.set_property("REF_LEVEL2", config.ref_level2);
308         output.tag.set_property("REF_TOTAL", config.ref_total);
309 //printf("Reverb::save_data 1\n");
310         output.tag.set_property("REF_LENGTH", config.ref_length);
311         output.tag.set_property("LOWPASS1", config.lowpass1);
312         output.tag.set_property("LOWPASS2", config.lowpass2);
313 //printf("Reverb::save_data config.ref_level2 %f\n", config.ref_level2);
314         output.append_tag();
315         output.tag.set_title("/REVERB");
316         output.append_tag();
317         output.append_newline();
318         output.terminate_string();
319 //printf("Reverb::save_data 2\n");
320 }
321
322 void Reverb::read_data(KeyFrame *keyframe)
323 {
324         FileXML input;
325 // cause xml file to read directly from text
326         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
327         int result = 0;
328
329         result = input.read_tag();
330
331         if(!result)
332         {
333                 if(input.tag.title_is("REVERB"))
334                 {
335                         config.level_init = input.tag.get_property("LEVELINIT", config.level_init);
336                         config.delay_init = input.tag.get_property("DELAY_INIT", config.delay_init);
337                         config.ref_level1 = input.tag.get_property("REF_LEVEL1", config.ref_level1);
338                         config.ref_level2 = input.tag.get_property("REF_LEVEL2", config.ref_level2);
339                         config.ref_total = input.tag.get_property("REF_TOTAL", config.ref_total);
340                         config.ref_length = input.tag.get_property("REF_LENGTH", config.ref_length);
341                         config.lowpass1 = input.tag.get_property("LOWPASS1", config.lowpass1);
342                         config.lowpass2 = input.tag.get_property("LOWPASS2", config.lowpass2);
343                 }
344         }
345
346         config.boundaries();
347 }
348
349 void Reverb::update_gui()
350 {
351         if(thread)
352         {
353                 if(load_configuration())
354                 {
355 //printf("Reverb::update_gui %d %d\n", __LINE__, config.ref_length);
356                         thread->window->lock_window("Reverb::update_gui");
357                         ((ReverbWindow*)thread->window)->level_init->update(config.level_init);
358                         ((ReverbWindow*)thread->window)->delay_init->update(config.delay_init);
359                         ((ReverbWindow*)thread->window)->ref_level1->update(config.ref_level1);
360                         ((ReverbWindow*)thread->window)->ref_level2->update(config.ref_level2);
361                         ((ReverbWindow*)thread->window)->ref_total->update(config.ref_total);
362                         ((ReverbWindow*)thread->window)->ref_length->update(config.ref_length);
363                         ((ReverbWindow*)thread->window)->lowpass1->update(config.lowpass1);
364                         ((ReverbWindow*)thread->window)->lowpass2->update(config.lowpass2);
365                         thread->window->unlock_window();
366                 }
367         }
368 }
369
370
371
372
373 // int Reverb::load_from_file(char *path)
374 // {
375 //      FILE *in;
376 //      int result = 0;
377 //      int length;
378 //      char string[1024];
379 //      
380 //      if(in = fopen(path, "rb"))
381 //      {
382 //              fseek(in, 0, SEEK_END);
383 //              length = ftell(in);
384 //              fseek(in, 0, SEEK_SET);
385 //              int temp = fread(string, length, 1, in);
386 //              fclose(in);
387 // //           read_data(string);
388 //      }
389 //      else
390 //      {
391 //              perror("fopen:");
392 // // failed
393 //              ErrorBox errorbox("");
394 //              char string[1024];
395 //              sprintf(string, _("Couldn't open %s."), path);
396 //              errorbox.create_objects(string);
397 //              errorbox.run_window();
398 //              result = 1;
399 //      }
400 //      
401 //      return result;
402 // }
403 // 
404 // int Reverb::save_to_file(char *path)
405 // {
406 //      FILE *out;
407 //      int result = 0;
408 //      char string[1024];
409 //      
410 //      {
411 // //           ConfirmSave confirm;
412 // //           result = confirm.test_file("", path);
413 //      }
414 //      
415 //      if(!result)
416 //      {
417 //              if(out = fopen(path, "wb"))
418 //              {
419 // //                   save_data(string);
420 //                      fwrite(string, strlen(string), 1, out);
421 //                      fclose(out);
422 //              }
423 //              else
424 //              {
425 //                      result = 1;
426 // // failed
427 //                      ErrorBox errorbox("");
428 //                      char string[1024];
429 //                      sprintf(string, _("Couldn't save %s."), path);
430 //                      errorbox.create_objects(string);
431 //                      errorbox.run_window();
432 //                      result = 1;
433 //              }
434 //      }
435 //      
436 //      return result;
437 // }
438
439 ReverbEngine::ReverbEngine(Reverb *plugin)
440  : Thread(1, 0, 0)
441 {
442         this->plugin = plugin;
443         completed = 0;
444         input_lock.lock();
445         output_lock.lock();
446 }
447
448 ReverbEngine::~ReverbEngine()
449 {
450         completed = 1;
451         input_lock.unlock();
452         join();
453 }
454
455 int ReverbEngine::process_overlays(int output_buffer, int64_t size)
456 {
457         this->output_buffer = output_buffer;
458         this->size = size;
459         input_lock.unlock();
460         return 0;
461 }
462
463 int ReverbEngine::wait_process_overlays()
464 {
465         output_lock.lock();
466         return 0;
467 }
468
469 int ReverbEngine::process_overlay(double *in, double *out, double &out1, double &out2, double level, int64_t lowpass, int64_t samplerate, int64_t size)
470 {
471 // Modern niquist frequency is 44khz but pot limit is 20khz so can't use
472 // niquist
473         if(lowpass == -1 || lowpass >= 20000)
474         {
475 // no lowpass filter
476                 for(int i = 0; i < size; i++) out[i] += in[i] * level;
477         }
478         else
479         {
480                 double coef = 0.25 * 2.0 * M_PI * (double)lowpass / (double)plugin->project_sample_rate;
481                 double a = coef * 0.25;
482                 double b = coef * 0.50;
483
484                 for(int i = 0; i < size; i++)
485                 {
486                         out2 += a * (3 * out1 + in[i] - out2);
487                         out2 += b * (out1 + in[i] - out2);
488                         out2 += a * (out1 + 3 * in[i] - out2);
489                         out2 += coef * (in[i] - out2);
490                         out1 = in[i];
491                         out[i] += out2 * level;
492                 }
493         }
494         return 0;
495 }
496
497 void ReverbEngine::run()
498 {
499         int j, i;
500 //printf("ReverbEngine::run 1 %d\n", calculate_realtime());
501         while(1)
502         {
503                 input_lock.lock();
504                 if(completed) return;
505
506 // Process reverb
507                 for(i = 0; i < plugin->total_in_buffers; i++)
508                 {
509                         for(j = 0; j < plugin->config.ref_total + 1; j++)
510                         {
511                                 if(plugin->ref_channels[i][j] == output_buffer)
512                                         process_overlay(plugin->main_in[i],
513                                                                 &(plugin->dsp_in[plugin->ref_channels[i][j]][plugin->ref_offsets[i][j]]),
514                                                                 plugin->lowpass_in1[i][j],
515                                                                 plugin->lowpass_in2[i][j],
516                                                                 plugin->ref_levels[i][j],
517                                                                 plugin->ref_lowpass[i][j],
518                                                                 plugin->project_sample_rate,
519                                                                 size);
520                         }
521                 }
522
523                 output_lock.unlock();
524         }
525 }
526
527
528
529
530
531
532
533 ReverbConfig::ReverbConfig()
534 {
535         level_init = 0;
536         delay_init = 0;
537         ref_level1 = -20;
538         ref_level2 = INFINITYGAIN;
539         ref_total = 100;
540         ref_length = 600;
541         lowpass1 = Freq::tofreq(TOTALFREQS);
542         lowpass2 = Freq::tofreq(TOTALFREQS);
543
544 }
545
546 int ReverbConfig::equivalent(ReverbConfig &that)
547 {
548         return (EQUIV(level_init, that.level_init) &&
549                 delay_init == that.delay_init &&
550                 EQUIV(ref_level1, that.ref_level1) &&
551                 EQUIV(ref_level2, that.ref_level2) &&
552                 ref_total == that.ref_total &&
553                 ref_length == that.ref_length &&
554                 lowpass1 == that.lowpass1 &&
555                 lowpass2 == that.lowpass2);
556 }
557
558 void ReverbConfig::copy_from(ReverbConfig &that)
559 {
560         level_init = that.level_init;
561         delay_init = that.delay_init;
562         ref_level1 = that.ref_level1;
563         ref_level2 = that.ref_level2;
564         ref_total = that.ref_total;
565         ref_length = that.ref_length;
566         lowpass1 = that.lowpass1;
567         lowpass2 = that.lowpass2;
568 }
569
570 void ReverbConfig::interpolate(ReverbConfig &prev,
571         ReverbConfig &next,
572         int64_t prev_frame,
573         int64_t next_frame,
574         int64_t current_frame)
575 {
576         level_init = prev.level_init;
577         delay_init = prev.delay_init;
578         ref_level1 = prev.ref_level1;
579         ref_level2 = prev.ref_level2;
580         ref_total = prev.ref_total;
581         ref_length = prev.ref_length;
582         lowpass1 = prev.lowpass1;
583         lowpass2 = prev.lowpass2;
584 }
585
586 void ReverbConfig::boundaries()
587 {
588
589         CLAMP(level_init, INFINITYGAIN, 0);
590         CLAMP(delay_init, 0, MAX_DELAY_INIT);
591         CLAMP(ref_level1, INFINITYGAIN, 0);
592         CLAMP(ref_level2, INFINITYGAIN, 0);
593         CLAMP(ref_total, MIN_REFLECTIONS, MAX_REFLECTIONS);
594         CLAMP(ref_length, 0, MAX_REFLENGTH);
595         CLAMP(lowpass1, 0, Freq::tofreq(TOTALFREQS));
596         CLAMP(lowpass2, 0, Freq::tofreq(TOTALFREQS));
597 }
598
599 void ReverbConfig::dump()
600 {
601         printf("ReverbConfig::dump %f %jd %f %f %jd %jd %jd %jd\n",
602                 level_init, delay_init, ref_level1, ref_level2,
603                 ref_total, ref_length, lowpass1, lowpass2);
604 }
605
606