2 #include "confirmsave.h"
8 #include "reverbwindow.h"
18 #define _(String) gettext(String)
19 #define gettext_noop(String) String
20 #define N_(String) gettext_noop (String)
24 PluginClient* new_plugin(PluginServer *server)
26 return new Reverb(server);
31 Reverb::Reverb(PluginServer *server)
32 : PluginAClient(server)
35 redo_buffers = 1; // set to redo buffers before the first render
45 PLUGIN_CONSTRUCTOR_MACRO
50 PLUGIN_DESTRUCTOR_MACRO
54 for(int i = 0; i < total_in_buffers; i++)
57 delete [] ref_channels[i];
58 delete [] ref_offsets[i];
59 delete [] ref_levels[i];
60 delete [] ref_lowpass[i];
61 delete [] lowpass_in1[i];
62 delete [] lowpass_in2[i];
66 delete [] ref_channels;
67 delete [] ref_offsets;
69 delete [] ref_lowpass;
70 delete [] lowpass_in1;
71 delete [] lowpass_in2;
73 for(int i = 0; i < (smp + 1); i++)
82 char* Reverb::plugin_title() { return _("Heroine College Concert Hall"); }
83 int Reverb::is_realtime() { return 1; }
84 int Reverb::is_multichannel() { return 1; }
86 int Reverb::process_realtime(int64_t size, double **input_ptr, double **output_ptr)
88 int64_t new_dsp_length, i, j;
90 main_out = output_ptr;
91 //printf("Reverb::process_realtime 1\n");
92 redo_buffers |= load_configuration();
94 //printf("Reverb::process_realtime 1\n");
95 if(!config.ref_total) return 0;
100 dsp_in = new double*[total_in_buffers];
101 ref_channels = new int64_t*[total_in_buffers];
102 ref_offsets = new int64_t*[total_in_buffers];
103 ref_levels = new double*[total_in_buffers];
104 ref_lowpass = new int64_t*[total_in_buffers];
105 lowpass_in1 = new double*[total_in_buffers];
106 lowpass_in2 = new double*[total_in_buffers];
108 for(i = 0; i < total_in_buffers; i++)
110 dsp_in[i] = new double[1];
111 ref_channels[i] = new int64_t[1];
112 ref_offsets[i] = new int64_t[1];
113 ref_levels[i] = new double[1];
114 ref_lowpass[i] = new int64_t[1];
115 lowpass_in1[i] = new double[1];
116 lowpass_in2[i] = new double[1];
119 engine = new ReverbEngine*[(smp + 1)];
120 for(i = 0; i < (smp + 1); i++)
122 engine[i] = new ReverbEngine(this);
123 //printf("Reverb::start_realtime %d\n", Thread::calculate_realtime());
124 // Realtime priority moved to sound driver
125 // engine[i]->set_realtime(realtime_priority);
132 new_dsp_length = size +
133 (config.delay_init + config.ref_length) * project_sample_rate / 1000 + 1;
134 //printf("Reverb::process_realtime 1 %d %d\n", in_buffer_size, size);
136 if(redo_buffers || new_dsp_length != dsp_in_length)
138 for(i = 0; i < total_in_buffers; i++)
140 double *old_dsp = dsp_in[i];
141 double *new_dsp = new double[new_dsp_length];
142 for(j = 0; j < dsp_in_length && j < new_dsp_length; j++)
143 new_dsp[j] = old_dsp[j];
144 for( ; j < new_dsp_length; j++) new_dsp[j] = 0;
149 dsp_in_length = new_dsp_length;
152 //printf("Reverb::process_realtime 1\n");
156 for(i = 0; i < total_in_buffers; i++)
158 delete [] ref_channels[i];
159 delete [] ref_offsets[i];
160 delete [] ref_lowpass[i];
161 delete [] ref_levels[i];
162 delete [] lowpass_in1[i];
163 delete [] lowpass_in2[i];
165 ref_channels[i] = new int64_t[config.ref_total + 1];
166 ref_offsets[i] = new int64_t[config.ref_total + 1];
167 ref_lowpass[i] = new int64_t[config.ref_total + 1];
168 ref_levels[i] = new double[config.ref_total + 1];
169 lowpass_in1[i] = new double[config.ref_total + 1];
170 lowpass_in2[i] = new double[config.ref_total + 1];
173 ref_channels[i][0] = i; // primary noise
174 ref_channels[i][1] = i; // first reflection
176 ref_offsets[i][0] = 0;
177 ref_offsets[i][1] = config.delay_init * project_sample_rate / 1000;
179 ref_levels[i][0] = db.fromdb(config.level_init);
180 ref_levels[i][1] = db.fromdb(config.ref_level1);
182 ref_lowpass[i][0] = -1; // ignore first noise
183 ref_lowpass[i][1] = config.lowpass1;
184 lowpass_in1[i][0] = 0;
185 lowpass_in2[i][0] = 0;
186 lowpass_in1[i][1] = 0;
187 lowpass_in2[i][1] = 0;
189 int64_t ref_division = config.ref_length * project_sample_rate / 1000 / (config.ref_total + 1);
190 for(j = 2; j < config.ref_total + 1; j++)
192 // set random channels for remaining reflections
193 ref_channels[i][j] = rand() % total_in_buffers;
195 // set random offsets after first reflection
196 ref_offsets[i][j] = ref_offsets[i][1];
197 ref_offsets[i][j] += ref_division * j - (rand() % ref_division) / 2;
199 // set changing levels
200 ref_levels[i][j] = db.fromdb(config.ref_level1 + (config.ref_level2 - config.ref_level1) / (config.ref_total - 1) * (j - 2));
201 //ref_levels[i][j] /= 100;
203 // set changing lowpass as linear
204 ref_lowpass[i][j] = (int64_t)(config.lowpass1 + (double)(config.lowpass2 - config.lowpass1) / (config.ref_total - 1) * (j - 2));
205 lowpass_in1[i][j] = 0;
206 lowpass_in2[i][j] = 0;
212 //printf("Reverb::process_realtime 1\n");
214 for(i = 0; i < total_in_buffers; )
216 for(j = 0; j < (smp + 1) && (i + j) < total_in_buffers; j++)
218 engine[j]->process_overlays(i + j, size);
221 for(j = 0; j < (smp + 1) && i < total_in_buffers; j++, i++)
223 engine[j]->wait_process_overlays();
226 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
228 for(i = 0; i < total_in_buffers; i++)
230 double *current_out = main_out[i];
231 double *current_in = dsp_in[i];
233 for(j = 0; j < size; j++) current_out[j] = current_in[j];
236 for(k = 0; j < dsp_in_length; j++, k++) current_in[k] = current_in[j];
238 for(; k < dsp_in_length; k++) current_in[k] = 0;
240 //printf("Reverb::process_realtime 2 %d %d\n", total_in_buffers, size);
244 NEW_PICON_MACRO(Reverb)
246 SHOW_GUI_MACRO(Reverb, ReverbThread)
248 SET_STRING_MACRO(Reverb)
250 RAISE_WINDOW_MACRO(Reverb)
252 int Reverb::load_defaults()
254 char directory[1024];
256 // set the default directory
257 sprintf(directory, "%sreverb.rc", get_defaultdir());
261 defaults = new Defaults(directory);
265 config.level_init = defaults->get("LEVEL_INIT", (double)0);
266 config.delay_init = defaults->get("DELAY_INIT", 100);
267 config.ref_level1 = defaults->get("REF_LEVEL1", (double)-6);
268 config.ref_level2 = defaults->get("REF_LEVEL2", (double)INFINITYGAIN);
269 config.ref_total = defaults->get("REF_TOTAL", 12);
270 config.ref_length = defaults->get("REF_LENGTH", 1000);
271 config.lowpass1 = defaults->get("LOWPASS1", 20000);
272 config.lowpass2 = defaults->get("LOWPASS2", 20000);
274 sprintf(config_directory, "~");
275 defaults->get("CONFIG_DIRECTORY", config_directory);
277 //printf("Reverb::load_defaults config.ref_level2 %f\n", config.ref_level2);
281 int Reverb::save_defaults()
283 defaults->update("LEVEL_INIT", config.level_init);
284 defaults->update("DELAY_INIT", config.delay_init);
285 defaults->update("REF_LEVEL1", config.ref_level1);
286 defaults->update("REF_LEVEL2", config.ref_level2);
287 defaults->update("REF_TOTAL", config.ref_total);
288 defaults->update("REF_LENGTH", config.ref_length);
289 defaults->update("LOWPASS1", config.lowpass1);
290 defaults->update("LOWPASS2", config.lowpass2);
291 defaults->update("CONFIG_DIRECTORY", config_directory);
296 LOAD_CONFIGURATION_MACRO(Reverb, ReverbConfig)
299 void Reverb::save_data(KeyFrame *keyframe)
301 //printf("Reverb::save_data 1\n");
303 //printf("Reverb::save_data 1\n");
305 // cause xml file to store data directly in text
306 output.set_shared_string(keyframe->data, MESSAGESIZE);
307 //printf("Reverb::save_data 1\n");
309 output.tag.set_title("REVERB");
310 output.tag.set_property("LEVELINIT", config.level_init);
311 output.tag.set_property("DELAY_INIT", config.delay_init);
312 output.tag.set_property("REF_LEVEL1", config.ref_level1);
313 output.tag.set_property("REF_LEVEL2", config.ref_level2);
314 output.tag.set_property("REF_TOTAL", config.ref_total);
315 //printf("Reverb::save_data 1\n");
316 output.tag.set_property("REF_LENGTH", config.ref_length);
317 output.tag.set_property("LOWPASS1", config.lowpass1);
318 output.tag.set_property("LOWPASS2", config.lowpass2);
319 //printf("Reverb::save_data config.ref_level2 %f\n", config.ref_level2);
321 output.append_newline();
322 //printf("Reverb::save_data 1\n");
326 output.terminate_string();
327 //printf("Reverb::save_data 2\n");
330 void Reverb::read_data(KeyFrame *keyframe)
333 // cause xml file to read directly from text
334 input.set_shared_string(keyframe->data, strlen(keyframe->data));
337 result = input.read_tag();
341 if(input.tag.title_is("REVERB"))
343 config.level_init = input.tag.get_property("LEVELINIT", config.level_init);
344 config.delay_init = input.tag.get_property("DELAY_INIT", config.delay_init);
345 config.ref_level1 = input.tag.get_property("REF_LEVEL1", config.ref_level1);
346 config.ref_level2 = input.tag.get_property("REF_LEVEL2", config.ref_level2);
347 config.ref_total = input.tag.get_property("REF_TOTAL", config.ref_total);
348 config.ref_length = input.tag.get_property("REF_LENGTH", config.ref_length);
349 config.lowpass1 = input.tag.get_property("LOWPASS1", config.lowpass1);
350 config.lowpass2 = input.tag.get_property("LOWPASS2", config.lowpass2);
355 void Reverb::update_gui()
359 thread->window->lock_window();
360 thread->window->level_init->update(config.level_init);
361 thread->window->delay_init->update(config.delay_init);
362 thread->window->ref_level1->update(config.ref_level1);
363 thread->window->ref_level2->update(config.ref_level2);
364 thread->window->ref_total->update(config.ref_total);
365 thread->window->ref_length->update(config.ref_length);
366 thread->window->lowpass1->update(config.lowpass1);
367 thread->window->lowpass2->update(config.lowpass2);
368 thread->window->unlock_window();
375 int Reverb::load_from_file(char *path)
382 if(in = fopen(path, "rb"))
384 fseek(in, 0, SEEK_END);
386 fseek(in, 0, SEEK_SET);
387 fread(string, length, 1, in);
389 // read_data(string);
395 ErrorBox errorbox("");
397 sprintf(string, _("Couldn't open %s."), path);
398 errorbox.create_objects(string);
399 errorbox.run_window();
406 int Reverb::save_to_file(char *path)
413 // ConfirmSave confirm;
414 // result = confirm.test_file("", path);
419 if(out = fopen(path, "wb"))
421 // save_data(string);
422 fwrite(string, strlen(string), 1, out);
429 ErrorBox errorbox("");
431 sprintf(string, _("Couldn't save %s."), path);
432 errorbox.create_objects(string);
433 errorbox.run_window();
441 ReverbEngine::ReverbEngine(Reverb *plugin)
444 this->plugin = plugin;
450 ReverbEngine::~ReverbEngine()
457 int ReverbEngine::process_overlays(int output_buffer, int64_t size)
459 this->output_buffer = output_buffer;
464 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;
496 void ReverbEngine::run()
502 if(completed) return;
505 for(i = 0; i < plugin->total_in_buffers; i++)
507 for(j = 0; j < plugin->config.ref_total + 1; j++)
509 if(plugin->ref_channels[i][j] == output_buffer)
510 process_overlay(plugin->main_in[i],
511 &(plugin->dsp_in[plugin->ref_channels[i][j]][plugin->ref_offsets[i][j]]),
512 plugin->lowpass_in1[i][j],
513 plugin->lowpass_in2[i][j],
514 plugin->ref_levels[i][j],
515 plugin->ref_lowpass[i][j],
516 plugin->project_sample_rate,
521 output_lock.unlock();
531 ReverbConfig::ReverbConfig()
535 int ReverbConfig::equivalent(ReverbConfig &that)
537 return (EQUIV(level_init, that.level_init) &&
538 delay_init == that.delay_init &&
539 EQUIV(ref_level1, that.ref_level1) &&
540 EQUIV(ref_level2, that.ref_level2) &&
541 ref_total == that.ref_total &&
542 ref_length == that.ref_length &&
543 lowpass1 == that.lowpass1 &&
544 lowpass2 == that.lowpass2);
547 void ReverbConfig::copy_from(ReverbConfig &that)
549 level_init = that.level_init;
550 delay_init = that.delay_init;
551 ref_level1 = that.ref_level1;
552 ref_level2 = that.ref_level2;
553 ref_total = that.ref_total;
554 ref_length = that.ref_length;
555 lowpass1 = that.lowpass1;
556 lowpass2 = that.lowpass2;
559 void ReverbConfig::interpolate(ReverbConfig &prev,
563 int64_t current_frame)
565 level_init = prev.level_init;
566 delay_init = prev.delay_init;
567 ref_level1 = prev.ref_level1;
568 ref_level2 = prev.ref_level2;
569 ref_total = prev.ref_total;
570 ref_length = prev.ref_length;
571 lowpass1 = prev.lowpass1;
572 lowpass2 = prev.lowpass2;
575 void ReverbConfig::dump()
577 printf("ReverbConfig::dump %f %d %f %f %d %d %d %d\n",