1 /*
2 Copyright (C) 2011 Tom Szilagyi
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <inttypes.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <time.h>
25
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <sndfile.h>
29 #include <samplerate.h>
30 #include <zita-convolver.h>
31 #include <lv2.h>
32
33 #include "ir.h"
34 #include "ir_utils.h"
35
36 #define ZITA_CONVOLVER_VERSION 0
37 #if ZITA_CONVOLVER_MAJOR_VERSION == 3
38 #undef ZITA_CONVOLVER_VERSION
39 #define ZITA_CONVOLVER_VERSION 3
40 #elif ZITA_CONVOLVER_MAJOR_VERSION == 4
41 #undef ZITA_CONVOLVER_VERSION
42 #define ZITA_CONVOLVER_VERSION 4
43 #else
44 #error "This version of IR requires zita-convolver 3.x.x or 4.x.x"
45 #endif
46
47 /* You may need to change these to match your JACK server setup!
48 *
49 * Priority should match -P parameter passed to jackd.
50 * Sched.class: either SCHED_FIFO or SCHED_RR (I think Jack uses SCHED_FIFO).
51 *
52 * THREAD_SYNC_MODE must be true if you want to use the plugin in Jack
53 * freewheeling mode (eg. while exporting in Ardour). You may only use
54 * false if you *only* run the plugin realtime.
55 */
56 #define CONVPROC_SCHEDULER_PRIORITY 0
57 #define CONVPROC_SCHEDULER_CLASS SCHED_FIFO
58 #define THREAD_SYNC_MODE true
59
60
61 static LV2_Descriptor * IR_Descriptor = NULL;
62 static GKeyFile * keyfile = NULL;
63 static GtkListStore * store_bookmarks = NULL;
64 G_LOCK_DEFINE_STATIC(conv_configure_lock);
65
connectPortIR(LV2_Handle instance,uint32_t port,void * data)66 static void connectPortIR(LV2_Handle instance,
67 uint32_t port,
68 void * data) {
69
70 IR * ir = (IR *)instance;
71
72 switch (port) {
73 /* Audio I/O */
74 case IR_PORT_INPUT_L:
75 ir->in_L = (const float*)data;
76 break;
77 case IR_PORT_INPUT_R:
78 ir->in_R = (const float*)data;
79 break;
80 case IR_PORT_OUTPUT_L:
81 ir->out_L = (float*)data;
82 break;
83 case IR_PORT_OUTPUT_R:
84 ir->out_R = (float*)data;
85 break;
86
87 /* Control */
88 case IR_PORT_REVERSE:
89 ir->port_reverse = (float*)data;
90 break;
91 case IR_PORT_PREDELAY:
92 ir->port_predelay = (float*)data;
93 break;
94 case IR_PORT_ATTACK:
95 ir->port_attack = (float*)data;
96 break;
97 case IR_PORT_ATTACKTIME:
98 ir->port_attacktime = (float*)data;
99 break;
100 case IR_PORT_ENVELOPE:
101 ir->port_envelope = (float*)data;
102 break;
103 case IR_PORT_LENGTH:
104 ir->port_length = (float*)data;
105 break;
106 case IR_PORT_STRETCH:
107 ir->port_stretch = (float*)data;
108 break;
109 case IR_PORT_STEREO_IN:
110 ir->port_stereo_in = (float*)data;
111 break;
112 case IR_PORT_STEREO_IR:
113 ir->port_stereo_ir = (float*)data;
114 break;
115 case IR_PORT_AGC_SW:
116 ir->port_agc_sw = (float*)data;
117 break;
118 case IR_PORT_DRY_SW:
119 ir->port_dry_sw = (float*)data;
120 break;
121 case IR_PORT_DRY_GAIN:
122 ir->port_dry_gain = (float*)data;
123 break;
124 case IR_PORT_WET_SW:
125 ir->port_wet_sw = (float*)data;
126 break;
127 case IR_PORT_WET_GAIN:
128 ir->port_wet_gain = (float*)data;
129 break;
130
131 /* Save/Restore */
132 case IR_PORT_FHASH_0:
133 ir->port_fhash_0 = (float*)data;
134 break;
135 case IR_PORT_FHASH_1:
136 ir->port_fhash_1 = (float*)data;
137 break;
138 case IR_PORT_FHASH_2:
139 ir->port_fhash_2 = (float*)data;
140 break;
141
142 /* Meter ports */
143 case IR_PORT_METER_DRY_L:
144 ir->port_meter_dry_L = (float*)data;
145 break;
146 case IR_PORT_METER_DRY_R:
147 ir->port_meter_dry_R = (float*)data;
148 break;
149 case IR_PORT_METER_WET_L:
150 ir->port_meter_wet_L = (float*)data;
151 break;
152 case IR_PORT_METER_WET_R:
153 ir->port_meter_wet_R = (float*)data;
154 break;
155
156 /* Latency port */
157 case IR_PORT_LATENCY:
158 ir->port_latency = (float*)data;
159 break;
160 }
161 }
162
free_ir_samples(IR * ir)163 static void free_ir_samples(IR * ir) {
164 if (ir->ir_samples != 0) {
165 float **p = ir->ir_samples;
166 while (*p) {
167 free(*p++);
168 }
169 free(ir->ir_samples);
170 ir->ir_samples = 0;
171 }
172 }
173
free_conv_safely(Convproc * conv)174 static void free_conv_safely(Convproc * conv) {
175 unsigned int state;
176
177 if (!conv) {
178 return;
179 }
180 state = conv->state();
181 if (state != Convproc::ST_STOP) {
182 conv->stop_process();
183 }
184 conv->cleanup();
185 delete conv;
186 }
187
free_convproc(IR * ir)188 static void free_convproc(IR * ir) {
189 free_conv_safely(ir->conv_0);
190 ir->conv_0 = 0;
191 free_conv_safely(ir->conv_1);
192 ir->conv_1 = 0;
193 }
194
cleanupIR(LV2_Handle instance)195 static void cleanupIR(LV2_Handle instance) {
196 IR * ir = (IR*)instance;
197
198 if (!ir->first_conf_done) {
199 ir->conf_thread_exit = 1;
200 g_thread_join(ir->conf_thread);
201 }
202
203 free_convproc(ir);
204 if (ir->source_samples != NULL) {
205 free(ir->source_samples);
206 ir->source_samples = NULL;
207 }
208 if (ir->resampled_samples != NULL) {
209 free(ir->resampled_samples);
210 ir->resampled_samples = NULL;
211 }
212 free_ir_samples(ir);
213
214 if (ir->source_path && (strlen(ir->source_path) > 0)) {
215 save_path(keyfile, ir->source_path);
216 free(ir->source_path);
217 }
218
219 free(instance);
220 }
221
222 /* Read IR audio file
223 * input data: source_path
224 * output data: nchan, source_samples
225 * return value: 0 OK, < 0 error
226 */
load_sndfile(IR * ir)227 static int load_sndfile(IR * ir) {
228
229 int length = 0;
230 int offset = 0;
231 float * buff;
232
233 if (!(ir->source_path) || *ir->source_path != '/') {
234 fprintf(stderr, "IR: load_sndfile error: %s is not an absolute path\n",
235 ir->source_path);
236 return -1;
237 }
238
239 ir->Finp = sf_open(ir->source_path, SFM_READ, &ir->Sinp);
240 if (!ir->Finp) {
241 fprintf(stderr, "IR: unable to read IR input file '%s'\n",
242 ir->source_path);
243 return -1;
244 }
245
246 ir->source_samplerate = ir->Sinp.samplerate;
247 ir->nchan = ir->Sinp.channels;
248 ir->source_nfram = ir->Sinp.frames;
249
250 if ((ir->nchan != 1) && (ir->nchan != 2) && (ir->nchan != 4)) {
251 fprintf(stderr, "IR: channel count %d of '%s' not supported.\n",
252 ir->nchan, ir->source_path);
253 sf_close(ir->Finp);
254 return -1;
255 }
256
257 length = ir->source_nfram;
258 if (ir->source_samples != NULL) {
259 free(ir->source_samples);
260 }
261 ir->source_samples = (float*)malloc(ir->nchan * length * sizeof(float));
262 buff = new float[BSIZE * ir->nchan];
263
264 while (length) {
265 int n = (length > BSIZE) ? BSIZE : length;
266 n = sf_readf_float(ir->Finp, buff, n);
267 if (n < 0) {
268 fprintf(stderr, "IR: error reading file %s\n", ir->source_path);
269 sf_close(ir->Finp);
270 delete[] buff;
271 return -1;
272 }
273 if (n) {
274 for (int i = 0; i < n * ir->nchan; i++) {
275 ir->source_samples[offset + i] = buff[i];
276 }
277 offset += n * ir->nchan;
278 length -= n;
279 }
280 }
281
282 delete[] buff;
283 sf_close(ir->Finp);
284
285 return 0;
286 }
287
288 /* Resample the IR samples, taking stretch into account
289 * input: source_nfram, source_samples
290 * output: ir_nfram, resampled_samples
291 * This function sets up the resampling operation
292 * return: 0: OK, 1: OK, no SRC needed, -1: error
293 */
resample_init(IR * ir)294 static int resample_init(IR * ir) {
295
296 float stretch = *ir->port_stretch / 100.0;
297 float fs_out = ir->sample_rate * stretch;
298
299 if (!ir->source_samples || !ir->source_nfram || !ir->nchan) {
300 return -1;
301 }
302
303 if (ir->source_samplerate == (unsigned int)fs_out) {
304 ir->ir_nfram = ir->source_nfram;
305 if (ir->resampled_samples != NULL) {
306 free(ir->resampled_samples);
307 }
308 ir->resampled_samples =
309 (float*)calloc(ir->nchan * ir->ir_nfram, sizeof(float));
310 for (int i = 0; i < ir->nchan * ir->ir_nfram; i++) {
311 ir->resampled_samples[i] = ir->source_samples[i];
312 }
313 return 1;
314 }
315
316 ir->ir_nfram = ir->source_nfram * fs_out / ir->source_samplerate + 1;
317
318 //printf("IR Resampler: fs_in=%d fs_out=%f\n", ir->source_samplerate, fs_out);
319 //printf(" samples_in=%d samples_out=%d\n", ir->source_nfram, ir->ir_nfram);
320
321 if (ir->resampled_samples != NULL) {
322 free(ir->resampled_samples);
323 }
324 ir->resampled_samples = (float*)calloc(ir->nchan * ir->ir_nfram, sizeof(float));
325
326 int src_error;
327 ir->src_state = src_new(SRC_SINC_BEST_QUALITY, ir->nchan, &src_error);
328 if (ir->src_state == NULL) {
329 fprintf(stderr, "IR: src_new() error: %s\n", src_strerror(src_error));
330 return -1;
331 }
332 src_error = src_set_ratio(ir->src_state, fs_out / ir->source_samplerate);
333 if (src_error) {
334 fprintf(stderr, "IR: src_set_ratio() error: %s, new_ratio = %g\n",
335 src_strerror(src_error), fs_out / ir->source_samplerate);
336 src_delete(ir->src_state);
337 return -1;
338 }
339
340 ir->src_progress = 0.0;
341 ir->src_in_frames = ir->source_nfram;
342 ir->src_out_frames = 0;
343 ir->src_data.data_in = ir->source_samples;
344 ir->src_data.data_out = ir->resampled_samples;
345 ir->src_data.input_frames_used = 0;
346 ir->src_data.output_frames_gen = 0;
347 ir->src_data.src_ratio = fs_out / ir->source_samplerate; /* really needed? */
348 ir->src_data.end_of_input = 0;
349 return 0;
350 }
351
352 /* Do a chunk of resample processing
353 * return: 0: OK, not ready (call it again); 1: ready; -1: error
354 * ir->src_progress can be used to track progress of resampling
355 */
resample_do(IR * ir)356 static int resample_do(IR * ir) {
357 if (!ir->src_in_frames) {
358 return 1;
359 }
360
361 ir->src_data.input_frames = (ir->src_in_frames > BSIZE_SR) ? BSIZE_SR : ir->src_in_frames;
362 ir->src_data.output_frames = ir->ir_nfram - ir->src_out_frames;
363
364 //printf("src_progress %f\n", ir->src_progress);
365 int src_error = src_process(ir->src_state, &ir->src_data);
366 if (src_error != 0) {
367 fprintf(stderr, "IR: src_process() error: %s\n", src_strerror(src_error));
368 src_delete(ir->src_state);
369 return -1;
370 }
371
372 ir->src_data.data_in += ir->nchan * ir->src_data.input_frames_used;
373 ir->src_data.data_out += ir->nchan * ir->src_data.output_frames_gen;
374 ir->src_in_frames -= ir->src_data.input_frames_used;
375 ir->src_out_frames += ir->src_data.output_frames_gen;
376 ir->src_progress = (float)ir->src_out_frames / ir->ir_nfram;
377
378 return ir->src_in_frames ? 0 : 1;
379 }
380
381 /* Finish resampling; call this after resample_do returned 1 */
resample_cleanup(IR * ir)382 static void resample_cleanup(IR * ir) {
383 if (ir->src_out_frames < ir->ir_nfram) {
384 ir->ir_nfram = ir->src_out_frames;
385 }
386 ir->src_progress = 1.0;
387 src_delete(ir->src_state);
388 }
389
390 /* In place processing on ir_samples[] */
process_envelopes(IR * ir)391 static void process_envelopes(IR * ir) {
392
393 int attack_time_s = (int)*ir->port_attacktime * ir->sample_rate / 1000;
394 float attack_pc = *ir->port_attack;
395 float length_pc = *ir->port_length;
396 float env_pc = *ir->port_envelope;
397
398 compute_envelope(ir->ir_samples, ir->nchan, ir->ir_nfram,
399 attack_time_s, attack_pc,
400 env_pc, length_pc);
401 }
402
403 /* Mid-Side based Stereo width effect */
ms_stereo(float width,float * lp,float * rp,int length)404 static void ms_stereo(float width, float * lp, float * rp, int length) {
405
406 float w = width / 100.0f;
407 float x = (1.0 - w) / (1.0 + w); /* M-S coeff.; L_out = L + x*R; R_out = x*L + R */
408 float L, R;
409
410 for (int i = 0; i < length; i++) {
411 L = *lp;
412 R = *rp;
413 *lp++ = L + x * R;
414 *rp++ = R + x * L;
415 }
416 }
417
418 /* Prepare samples to be loaded into convolution engine
419 * input: ir_nfram, resampled_samples
420 * output: ir_samples
421 * parameters: all plugin parameters except stretch,
422 * stereo_in, dry_*, wet_*
423 */
prepare_convdata(IR * ir)424 static void prepare_convdata(IR * ir) {
425
426 if (!ir->resampled_samples || !ir->ir_nfram || !ir->nchan) {
427 return;
428 }
429
430 free_ir_samples(ir);
431 ir->ir_samples = (float**)malloc((1 + ir->nchan) * sizeof(float*));
432 for (int i = 0; i < ir->nchan; i++) {
433 ir->ir_samples[i] = (float*)malloc(ir->ir_nfram * sizeof(float));
434 }
435 ir->ir_samples[ir->nchan] = NULL;
436
437 /* de-interleave resampled_samples to ir_samples */
438 for (int ch = 0; ch < ir->nchan; ch++) {
439 float * p = ir->resampled_samples + ch;
440 float * q = ir->ir_samples[ch];
441 int nch = ir->nchan;
442 int nfram = ir->ir_nfram;
443 for (int i = 0; i < nfram; i++) {
444 q[i] = p[i * nch];
445 }
446 }
447
448 /* Autogain calculation */
449 float pow = 0;
450 for (int ch = 0; ch < ir->nchan; ch++) {
451 float * p = ir->ir_samples[ch];
452 for (int i = 0; i < ir->ir_nfram; i++) {
453 pow += p[i] * p[i];
454 }
455 }
456 pow /= ir->nchan;
457 ir->autogain_new = -10.0 * log10f(pow / 6.0);
458
459 /* IR stereo width */
460 if (ir->nchan == 2) {
461 ms_stereo(*ir->port_stereo_ir, ir->ir_samples[0], ir->ir_samples[1], ir->ir_nfram);
462 } else if (ir->nchan == 4) {
463 ms_stereo(*ir->port_stereo_ir, ir->ir_samples[0], ir->ir_samples[1], ir->ir_nfram);
464 ms_stereo(*ir->port_stereo_ir, ir->ir_samples[2], ir->ir_samples[3], ir->ir_nfram);
465 }
466 process_envelopes(ir);
467
468 /* reverse ir vector if needed */
469 int reverse = (*ir->port_reverse > 0.0f) ? 1 : 0;
470 if (reverse) {
471 float tmp;
472 int nfram = ir->ir_nfram;
473 for (int ch = 0; ch < ir->nchan; ch++) {
474 float * p = ir->ir_samples[ch];
475 for (int i = 0, j = nfram-1; i < nfram/2; i++, j--) {
476 tmp = p[i];
477 p[i] = p[j];
478 p[j] = tmp;
479 }
480 }
481 }
482 }
483
484 /* Initialise (the next) convolution engine to use */
init_conv(IR * ir)485 static void init_conv(IR * ir) {
486
487 Convproc * conv;
488 int req_to_use;
489
490 if (!ir->ir_samples || !ir->ir_nfram || !ir->nchan) {
491 return;
492 }
493
494 if (ir->conv_in_use != ir->conv_req_to_use) {
495 fprintf(stderr, "IR init_conv: error, engine still in use!\n");
496 return;
497 }
498
499 if (ir->conv_in_use == 1) { /* new one will be 0th */
500 free_conv_safely(ir->conv_0);
501 ir->conv_0 = new Convproc;
502 conv = ir->conv_0;
503 req_to_use = 0;
504 } else { /* new one will be 1st */
505 free_conv_safely(ir->conv_1);
506 ir->conv_1 = new Convproc;
507 conv = ir->conv_1;
508 req_to_use = 1;
509 }
510
511 uint32_t predelay_samples = (int)*ir->port_predelay * ir->sample_rate / 1000;
512 uint32_t length = ir->maxsize;
513 int nfram;
514
515 if (predelay_samples + ir->ir_nfram > length) {
516 fprintf(stderr, "IR: warning: truncated IR to %d samples\n", length);
517 nfram = length - predelay_samples;
518 } else {
519 nfram = ir->ir_nfram;
520 length = predelay_samples + ir->ir_nfram;
521 }
522
523 if (length < ir->block_length) {
524 length = ir->block_length;
525 }
526
527 G_LOCK(conv_configure_lock);
528 //printf("configure length=%d ir->block_length=%d\n", length, ir->block_length);
529 #if ZITA_CONVOLVER_VERSION == 3
530 if (ir->nchan == 4) {
531 conv->set_density(1);
532 }
533 int ret = conv->configure(2, // n_inputs
534 2, // n_outputs
535 length,
536 ir->block_length,
537 ir->block_length,
538 Convproc::MAXPART);
539 #elif ZITA_CONVOLVER_VERSION == 4
540 float density = 0.0f;
541 if (ir->nchan == 4) {
542 density = 1.0f;
543 }
544 int ret = conv->configure(2, // n_inputs
545 2, // n_outputs
546 length,
547 ir->block_length,
548 ir->block_length,
549 Convproc::MAXPART,
550 density);
551 #endif
552 G_UNLOCK(conv_configure_lock);
553 if (ret != 0) {
554 fprintf(stderr, "IR: can't initialise zita-convolver engine, Convproc::configure returned %d\n", ret);
555 free_conv_safely(conv);
556 if (req_to_use == 0) {
557 ir->conv_0 = NULL;
558 } else {
559 ir->conv_1 = NULL;
560 }
561 return;
562 }
563
564 switch (ir->nchan) {
565 case 1: /* both input channels are convolved with the same IR */
566 conv->impdata_create(0, 0, 1, ir->ir_samples[0],
567 predelay_samples, nfram + predelay_samples);
568 conv->impdata_copy(0, 0, 1, 1);
569 break;
570 case 2: /* left channel convolved with left IR channel yields left output
571 same for the right channel */
572 conv->impdata_create(0, 0, 1, ir->ir_samples[0],
573 predelay_samples, nfram + predelay_samples);
574 conv->impdata_create(1, 1, 1, ir->ir_samples[1],
575 predelay_samples, nfram + predelay_samples);
576 break;
577 case 4: /* IR is a full matrix: / in_L -> out_L in_L -> out_R \
578 \ in_R -> out_L in_R -> out_R / */
579 conv->impdata_create(0, 0, 1, ir->ir_samples[0],
580 predelay_samples, nfram + predelay_samples);
581 conv->impdata_create(0, 1, 1, ir->ir_samples[1],
582 predelay_samples, nfram + predelay_samples);
583 conv->impdata_create(1, 0, 1, ir->ir_samples[2],
584 predelay_samples, nfram + predelay_samples);
585 conv->impdata_create(1, 1, 1, ir->ir_samples[3],
586 predelay_samples, nfram + predelay_samples);
587 break;
588 default: printf("IR init_conv: error, impossible value: ir->nchan = %d\n",
589 ir->nchan);
590 }
591
592 conv->start_process(CONVPROC_SCHEDULER_PRIORITY, CONVPROC_SCHEDULER_CLASS);
593 ir->conv_req_to_use = req_to_use;
594 }
595
IR_configurator_thread(gpointer data)596 static gpointer IR_configurator_thread(gpointer data) {
597
598 IR * ir = (IR *)data;
599
600 struct timespec treq;
601 struct timespec trem;
602
603 while (!ir->conf_thread_exit) {
604 if ((ir->run > 0) && !ir->first_conf_done) {
605 uint64_t fhash = fhash_from_ports(ir->port_fhash_0,
606 ir->port_fhash_1,
607 ir->port_fhash_2);
608 //printf("IR confthread: fhash = %016" PRIx64 "\n", fhash);
609 if (fhash) {
610 char * filename = get_path_from_key(keyfile, fhash);
611 if (filename) {
612 //printf(" load filename=%s\n", filename);
613 ir->source_path = filename;
614 if (load_sndfile(ir) == 0) {
615 int r = resample_init(ir);
616 if (r == 0) {
617 while ((r == 0) && (!ir->conf_thread_exit)) {
618 r = resample_do(ir);
619 }
620 resample_cleanup(ir);
621 }
622 if (r >= 0) {
623 prepare_convdata(ir);
624 init_conv(ir);
625 }
626 } else {
627 free(ir->source_path);
628 ir->source_path = NULL;
629 }
630 } else {
631 fprintf(stderr, "IR: fhash=%016" PRIx64
632 " was not found in DB\n", fhash);
633 }
634 }
635 ir->first_conf_done = 1;
636 return NULL;
637 }
638
639 /* sleep 100 ms before checking again */
640 treq.tv_sec = 0;
641 treq.tv_nsec = 100000000;
642 nanosleep(&treq, &trem);
643 }
644 return NULL;
645 }
646
instantiateIR(const LV2_Descriptor * descriptor,double sample_rate,const char * path,const LV2_Feature * const * features)647 static LV2_Handle instantiateIR(const LV2_Descriptor *descriptor,
648 double sample_rate,
649 const char *path,
650 const LV2_Feature *const *features) {
651
652 IR * ir = (IR *)calloc(1, sizeof(IR));
653
654 ir->sample_rate = sample_rate;
655 ir->reinit_pending = 0;
656 ir->maxsize = MAXSIZE;
657 ir->block_length = IR_DEFAULT_JACK_BUFLEN;
658 ir->bufconv_pos = 0;
659 ir->run = -5; /* do nothing for the first 5 run() calls */
660
661 ir->load_sndfile = load_sndfile;
662 ir->resample_init = resample_init;
663 ir->resample_do = resample_do;
664 ir->resample_cleanup = resample_cleanup;
665 ir->prepare_convdata = prepare_convdata;
666 ir->init_conv = init_conv;
667
668 ir->keyfile = keyfile;
669 ir->store_bookmarks = store_bookmarks;
670
671 ir->conf_thread = g_thread_new("IR_configurator_thread",
672 IR_configurator_thread, (gpointer)ir);
673 return (LV2_Handle)ir;
674 }
675
676 #define ACC_MAX(m,v) (((fabs(v))>(m))?fabs(v):(m))
runIR(LV2_Handle instance,uint32_t n)677 static void runIR(LV2_Handle instance, uint32_t n) {
678
679 IR * ir = (IR *)instance;
680 Convproc * conv;
681
682 const float * const in_L = ir->in_L;
683 const float * const in_R = ir->in_R;
684 float * const out_L = ir->out_L;
685 float * const out_R = ir->out_R;
686
687 float dry_L_meter = 0.0;
688 float dry_R_meter = 0.0;
689 float wet_L_meter = 0.0;
690 float wet_R_meter = 0.0;
691
692 float width = ir->width;
693 float dry_gain = ir->dry_gain;
694 float wet_gain = ir->wet_gain;
695
696 if (ir->run < 0) { /* XXX safety measure: wait until buffer size stabilizes, bypass until then */
697 if ((in_L != out_L) || (in_R != out_R)) {
698 for (unsigned int j = 0; j < n; j++) {
699 out_L[j] = in_L[j];
700 out_R[j] = in_R[j];
701 }
702 }
703 ir->run++;
704 *ir->port_latency = ir->block_length;
705 return;
706 }
707
708 if (ir->conv_in_use != ir->conv_req_to_use) {
709 /* call stop_process() on the conv being switched away from
710 * so it can be deallocated next time it is needed */
711 Convproc * conv_from;
712 if (ir->conv_in_use == 0) {
713 conv_from = ir->conv_0;
714 } else {
715 conv_from = ir->conv_1;
716 }
717 if (conv_from) {
718 conv_from->stop_process();
719 }
720
721 ir->conv_in_use = ir->conv_req_to_use;
722 ir->autogain = ir->autogain_new;
723 //printf("IR engine switching to conv_%d autogain = %f\n", ir->conv_in_use, ir->autogain);
724
725 /* fade it up */
726 wet_gain = 0.0;
727 }
728 if (ir->conv_in_use == 0) {
729 conv = ir->conv_0;
730 } else {
731 conv = ir->conv_1;
732 }
733
734 if (n > ir->block_length) {
735 /* MUST range from IR_DEFAULT_JACK_BUFLEN<<1 to IR_MAXIMUM_JACK_BUFLEN */
736 if ((n == 2048) || (n == 4096) || (n = 8192) || (n = 16384)) {
737 /* block size seems to be a valid JACK buffer size */
738 ir->block_length = n;
739 ir->reinit_pending = 1;
740 ir->bufconv_pos = 0;
741 conv = 0;
742 //printf("IR block_length = %d\n", n);
743 }
744 }
745
746 if (n > IR_MAXIMUM_JACK_BUFLEN) {
747 fprintf(stderr, "IR: being run() with buffer length %d greater than largest supported length %d, bypassing...\n",
748 n, IR_MAXIMUM_JACK_BUFLEN);
749 if ((in_L != out_L) || (in_R != out_R)) {
750 for (unsigned int j = 0; j < n; j++) {
751 out_L[j] = in_L[j];
752 out_R[j] = in_R[j];
753 }
754 }
755 return;
756 }
757
758 float agc_gain_raw = (*ir->port_agc_sw > 0.0f) ? DB_CO(ir->autogain) : 1.0f;
759
760 float width_raw = *ir->port_stereo_in / 100.0f; /* stereo width */
761 float dry_sw = (*ir->port_dry_sw > 0.0f) ? 1.0f : 0.0f;
762 float wet_sw = (*ir->port_wet_sw > 0.0f) ? 1.0f : 0.0f;
763 float dry_gain_raw = DB_CO(*ir->port_dry_gain) * dry_sw;
764 float wet_gain_raw = DB_CO(*ir->port_wet_gain) * wet_sw * agc_gain_raw;
765
766 float * pi, * qi, * po, * qo, * dL, * dR;
767 float dry_L, dry_R, wet_L, wet_R;
768 unsigned int bcp = ir->bufconv_pos;
769
770 if (conv != 0) {
771 pi = conv->inpdata(0);
772 qi = conv->inpdata(1);
773 po = conv->outdata(0);
774 qo = conv->outdata(1);
775 dL = ir->drybuf_L;
776 dR = ir->drybuf_R;
777 float x;
778 for (unsigned int j = 0; j < n; j++) {
779 width = width * SMOOTH_CO_1 + width_raw * SMOOTH_CO_0;
780 x = (1.0 - width) / (1.0 + width); /* M-S coeff. */
781 pi[bcp] = in_L[j] + x * in_R[j];
782 qi[bcp] = in_R[j] + x * in_L[j];
783
784 dry_gain = SMOOTH_CO_1 * dry_gain + SMOOTH_CO_0 * dry_gain_raw;
785 wet_gain = SMOOTH_CO_1 * wet_gain + SMOOTH_CO_0 * wet_gain_raw;
786 dry_L = dL[bcp];
787 dry_R = dR[bcp];
788 dL[bcp] = in_L[j] * dry_gain;
789 dR[bcp] = in_R[j] * dry_gain;
790 wet_L = po[bcp] * wet_gain;
791 wet_R = qo[bcp] * wet_gain;
792 dry_L_meter = ACC_MAX(dry_L_meter, dry_L);
793 dry_R_meter = ACC_MAX(dry_R_meter, dry_R);
794 wet_L_meter = ACC_MAX(wet_L_meter, wet_L);
795 wet_R_meter = ACC_MAX(wet_R_meter, wet_R);
796 out_L[j] = dry_L + wet_L;
797 out_R[j] = dry_R + wet_R;
798
799 if (++bcp == ir->block_length) {
800 bcp = 0;
801 conv->process(THREAD_SYNC_MODE);
802 }
803 }
804 } else { /* convolution engine not available */
805 dL = ir->drybuf_L;
806 dR = ir->drybuf_R;
807 for (unsigned int j = 0; j < n; j++) {
808 dry_gain = SMOOTH_CO_1 * dry_gain + SMOOTH_CO_0 * dry_gain_raw;
809 dry_L = dL[bcp];
810 dry_R = dR[bcp];
811 dL[bcp] = in_L[j] * dry_gain;
812 dR[bcp] = in_R[j] * dry_gain;
813 dry_L_meter = ACC_MAX(dry_L_meter, dry_L);
814 dry_R_meter = ACC_MAX(dry_R_meter, dry_R);
815 out_L[j] = dry_L;
816 out_R[j] = dry_R;
817
818 if (++bcp == ir->block_length) {
819 bcp = 0;
820 }
821 }
822 }
823
824 ir->width = width;
825 ir->dry_gain = dry_gain;
826 ir->wet_gain = wet_gain;
827 ir->bufconv_pos = bcp;
828
829 *ir->port_meter_dry_L = dry_L_meter;
830 *ir->port_meter_dry_R = dry_R_meter;
831 *ir->port_meter_wet_L = wet_L_meter;
832 *ir->port_meter_wet_R = wet_R_meter;
833
834 *ir->port_latency = ir->block_length;
835 ir->run = 1;
836 }
837
extdata_IR(const char * uri)838 const void * extdata_IR(const char * uri) {
839 return NULL;
840 }
841
init()842 void __attribute__ ((constructor)) init() {
843
844 if (zita_convolver_major_version () != ZITA_CONVOLVER_MAJOR_VERSION) {
845 fprintf(stderr, "IR: compile-time & runtime library versions of zita-convolver do not match!\n");
846 IR_Descriptor = NULL;
847 return;
848 }
849
850 if (!g_thread_supported()) {
851 fprintf(stderr, "IR: This plugin requires a working GLib with GThread.\n");
852 IR_Descriptor = NULL;
853 return;
854 }
855
856 IR_Descriptor = (LV2_Descriptor *)malloc(sizeof(LV2_Descriptor));
857
858 IR_Descriptor->URI = IR_URI;
859 IR_Descriptor->instantiate = instantiateIR;
860 IR_Descriptor->cleanup = cleanupIR;
861 IR_Descriptor->activate = NULL;
862 IR_Descriptor->deactivate = NULL;
863 IR_Descriptor->connect_port = connectPortIR;
864 IR_Descriptor->run = runIR;
865 IR_Descriptor->extension_data = extdata_IR;
866
867 keyfile = load_keyfile();
868 store_bookmarks = gtk_list_store_new(2,
869 G_TYPE_STRING, /* visible name (key) */
870 G_TYPE_STRING); /* full pathname (value) */
871 load_bookmarks(keyfile, store_bookmarks);
872 }
873
fini()874 void __attribute__ ((destructor)) fini() {
875 save_keyfile(keyfile);
876 g_key_file_free(keyfile);
877 g_object_unref(store_bookmarks);
878 free(IR_Descriptor);
879 }
880
881 LV2_SYMBOL_EXPORT
lv2_descriptor(uint32_t index)882 const LV2_Descriptor * lv2_descriptor(uint32_t index) {
883
884 switch (index) {
885 case 0:
886 return IR_Descriptor;
887 default:
888 return NULL;
889 }
890 }
891