4 * Copyright (C) 2017 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 #include "confirmsave.h"
25 #include "bcsignals.h"
30 #include "reverbwindow.h"
43 PluginClient* new_plugin(PluginServer *server)
45 return new Reverb(server);
50 Reverb::Reverb(PluginServer *server)
51 : PluginAClient(server)
54 redo_buffers = 1; // set to redo buffers before the first render
73 for(int i = 0; i < total_in_buffers; 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];
85 delete [] ref_channels;
86 delete [] ref_offsets;
88 delete [] ref_lowpass;
89 delete [] lowpass_in1;
90 delete [] lowpass_in2;
92 for(int i = 0; i < (smp + 1); i++)
101 const char* Reverb::plugin_title() { return N_("Reverb"); }
102 int Reverb::is_realtime() { return 1; }
103 int Reverb::is_multichannel() { return 1; }
104 int Reverb::is_synthesis() { return 1; }
106 int Reverb::process_realtime(int64_t size,
108 Samples **output_ptr)
110 int64_t new_dsp_length, i, j;
111 main_in = new double*[total_in_buffers];
112 main_out = new double*[total_in_buffers];
114 for(i = 0; i < total_in_buffers; i++)
116 main_in[i] = input_ptr[i]->get_data();
117 main_out[i] = output_ptr[i]->get_data();
120 //printf("Reverb::process_realtime 1\n");
121 redo_buffers |= load_configuration();
123 //printf("Reverb::process_realtime 1\n");
124 if(!config.ref_total)
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];
144 for(i = 0; i < total_in_buffers; i++)
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];
155 engine = new ReverbEngine*[(smp + 1)];
156 for(i = 0; i < (smp + 1); i++)
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);
168 new_dsp_length = size +
169 ((int64_t)config.delay_init + config.ref_length) * project_sample_rate / 1000 + 1;
171 if(redo_buffers || new_dsp_length != dsp_in_length)
173 for(i = 0; i < total_in_buffers; i++)
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];
181 for( ; j < new_dsp_length; j++) new_dsp[j] = 0;
186 dsp_in_length = new_dsp_length;
189 //printf("Reverb::process_realtime 1\n");
193 for(i = 0; i < total_in_buffers; i++)
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];
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];
210 ref_channels[i][0] = i; // primary noise
211 ref_channels[i][1] = i; // first reflection
213 ref_offsets[i][0] = 0;
214 ref_offsets[i][1] = config.delay_init * project_sample_rate / 1000;
216 ref_levels[i][0] = db.fromdb(config.level_init);
217 ref_levels[i][1] = db.fromdb(config.ref_level1);
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;
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++)
229 // set random channels for remaining reflections
230 ref_channels[i][j] = rand() % total_in_buffers;
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;
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;
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;
250 //printf("Reverb::process_realtime 1\n");
252 for(i = 0; i < total_in_buffers; )
254 for(j = 0; j < (smp + 1) && (i + j) < total_in_buffers; j++)
256 engine[j]->process_overlays(i + j, size);
259 for(j = 0; j < (smp + 1) && i < total_in_buffers; j++, i++)
261 engine[j]->wait_process_overlays();
264 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
266 for(i = 0; i < total_in_buffers; i++)
268 double *current_out = main_out[i];
269 double *current_in = dsp_in[i];
271 for(j = 0; j < size; j++) current_out[j] = current_in[j];
274 for(k = 0; j < dsp_in_length; j++, k++) current_in[k] = current_in[j];
276 for(; k < dsp_in_length; k++) current_in[k] = 0;
278 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
287 NEW_WINDOW_MACRO(Reverb, ReverbWindow)
290 LOAD_CONFIGURATION_MACRO(Reverb, ReverbConfig)
293 void Reverb::save_data(KeyFrame *keyframe)
295 //printf("Reverb::save_data 1\n");
297 //printf("Reverb::save_data 1\n");
299 // cause xml file to store data directly in text
300 output.set_shared_output(keyframe->xbuf);
301 //printf("Reverb::save_data 1\n");
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);
315 output.tag.set_title("/REVERB");
317 output.append_newline();
318 output.terminate_string();
319 //printf("Reverb::save_data 2\n");
322 void Reverb::read_data(KeyFrame *keyframe)
325 // cause xml file to read directly from text
326 input.set_shared_input(keyframe->xbuf);
329 result = input.read_tag();
333 if(input.tag.title_is("REVERB"))
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);
349 void Reverb::update_gui()
353 if(load_configuration())
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();
373 // int Reverb::load_from_file(char *path)
378 // char string[1024];
380 // if(in = fopen(path, "rb"))
382 // fseek(in, 0, SEEK_END);
383 // length = ftell(in);
384 // fseek(in, 0, SEEK_SET);
385 // int temp = fread(string, length, 1, in);
387 // // read_data(string);
393 // ErrorBox errorbox("");
394 // char string[1024];
395 // sprintf(string, _("Couldn't open %s."), path);
396 // errorbox.create_objects(string);
397 // errorbox.run_window();
404 // int Reverb::save_to_file(char *path)
408 // char string[1024];
411 // // ConfirmSave confirm;
412 // // result = confirm.test_file("", path);
417 // if(out = fopen(path, "wb"))
419 // // save_data(string);
420 // fwrite(string, strlen(string), 1, out);
427 // ErrorBox errorbox("");
428 // char string[1024];
429 // sprintf(string, _("Couldn't save %s."), path);
430 // errorbox.create_objects(string);
431 // errorbox.run_window();
439 ReverbEngine::ReverbEngine(Reverb *plugin)
442 this->plugin = plugin;
448 ReverbEngine::~ReverbEngine()
455 int ReverbEngine::process_overlays(int output_buffer, int64_t size)
457 this->output_buffer = output_buffer;
463 int ReverbEngine::wait_process_overlays()
469 int ReverbEngine::process_overlay(double *in, double *out, double &out1, double &out2, double level, int64_t lowpass, int64_t samplerate, int64_t size)
471 // Modern niquist frequency is 44khz but pot limit is 20khz so can't use
473 if(lowpass == -1 || lowpass >= 20000)
476 for(int i = 0; i < size; i++) out[i] += in[i] * level;
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;
484 for(int i = 0; i < size; i++)
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);
491 out[i] += out2 * level;
497 void ReverbEngine::run()
500 //printf("ReverbEngine::run 1 %d\n", calculate_realtime());
504 if(completed) return;
507 for(i = 0; i < plugin->total_in_buffers; i++)
509 for(j = 0; j < plugin->config.ref_total + 1; j++)
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,
523 output_lock.unlock();
533 ReverbConfig::ReverbConfig()
538 ref_level2 = INFINITYGAIN;
541 lowpass1 = Freq::tofreq(TOTALFREQS);
542 lowpass2 = Freq::tofreq(TOTALFREQS);
546 int ReverbConfig::equivalent(ReverbConfig &that)
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);
558 void ReverbConfig::copy_from(ReverbConfig &that)
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;
570 void ReverbConfig::interpolate(ReverbConfig &prev,
574 int64_t current_frame)
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;
586 void ReverbConfig::boundaries()
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));
599 void ReverbConfig::dump()
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);