summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-07-12 16:42:29 +0200
committerRobin Gareus <robin@gareus.org>2016-07-12 16:43:10 +0200
commit43f8d2503c88041feacd1c718a6a95ba091249f4 (patch)
treee7cf45e3b2684ba01b1a72cb2a687c618ca7c3de
parent4866106bcc488a1e85a78220652c486d37bb74d7 (diff)
a-reverb prototype (based on setBfree b_reverb)
-rw-r--r--libs/plugins/a-comp.lv2/a-comp.ttl.in2
-rw-r--r--libs/plugins/a-reverb.lv2/a-reverb.c323
-rw-r--r--libs/plugins/a-reverb.lv2/a-reverb.ttl.in61
-rw-r--r--libs/plugins/a-reverb.lv2/manifest.ttl.in7
-rw-r--r--libs/plugins/a-reverb.lv2/wscript51
-rw-r--r--wscript1
6 files changed, 444 insertions, 1 deletions
diff --git a/libs/plugins/a-comp.lv2/a-comp.ttl.in b/libs/plugins/a-comp.lv2/a-comp.ttl.in
index f89c60e29e..312d0b222f 100644
--- a/libs/plugins/a-comp.lv2/a-comp.ttl.in
+++ b/libs/plugins/a-comp.lv2/a-comp.ttl.in
@@ -137,7 +137,7 @@ A powerful mono compressor.
""" ;
doap:name "a-Compressor" ;
- doap:license "GPL v2+" ;
+ doap:license <http://usefulinc.com/doap/licenses/gpl> ;
doap:maintainer <http://ardour.org/credits.html>
# ui:ui <urn:ardour:a-comp#ui>;
diff --git a/libs/plugins/a-reverb.lv2/a-reverb.c b/libs/plugins/a-reverb.lv2/a-reverb.c
new file mode 100644
index 0000000000..ed3b80fb66
--- /dev/null
+++ b/libs/plugins/a-reverb.lv2/a-reverb.c
@@ -0,0 +1,323 @@
+/* a-reverb -- based on b_reverb (setBfree)
+ *
+ * Copyright (C) 2003-2004 Fredrik Kilander <fk@dsv.su.se>
+ * Copyright (C) 2008-2016 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2012 Will Panther <pantherb@setbfree.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include <string.h>
+
+#define RV_NZ 7
+#define DENORMAL_PROTECT (1e-14)
+
+typedef struct {
+ float* delays[RV_NZ]; /**< delay line buffer */
+
+ float* idx0[RV_NZ]; /**< Reset pointer ref delays[]*/
+ float* idxp[RV_NZ]; /**< Index pointer ref delays[]*/
+ float* endp[RV_NZ]; /**< End pointer ref delays[]*/
+
+ float gain[RV_NZ]; /**< feedback gains */
+ float yy1; /**< Previous output sample */
+ float y_1; /**< Feedback sample */
+
+ int end[RV_NZ];
+
+ float inputGain; /**< Input gain value */
+ float fbk; /**< Feedback gain */
+ float wet; /**< Output dry gain */
+ float dry; /**< Output wet gain */
+} b_reverb;
+
+static int
+setReverbPointers (b_reverb *r, int i, const double rate)
+{
+ int e = (r->end[i] * rate / 25000.0);
+ e = e | 1;
+ r->delays[i] = (float*)realloc ((void*)r->delays[i], (e + 2) * sizeof (float));
+ if (!r->delays[i]) {
+ return -1;
+ } else {
+ memset (r->delays[i], 0 , (e + 2) * sizeof (float));
+ }
+ r->endp[i] = r->delays[i] + e + 1;
+ r->idx0[i] = r->idxp[i] = &(r->delays[i][0]);
+
+ return 0;
+}
+
+static int
+initReverb (b_reverb *r, const double rate)
+{
+ int err = 0;
+ r->inputGain = 0.1; /* Input gain value */
+ r->fbk = -0.015; /* Feedback gain */
+ r->wet = 0.1; /* Output dry gain */
+ r->dry = 0.9; /* Output wet gain */
+
+ /* feedback combfilter */
+ r->gain[0] = 0.773;
+ r->gain[1] = 0.802;
+ r->gain[2] = 0.753;
+ r->gain[3] = 0.733;
+
+ /* all-pass filter */
+ r->gain[4] = sqrtf (0.5);
+ r->gain[5] = sqrtf (0.5);
+ r->gain[6] = sqrtf (0.5);
+
+ /* delay lines */
+ r->end[0] = 1687;
+ r->end[1] = 1601;
+ r->end[2] = 2053;
+ r->end[3] = 2251;
+
+ /* all pass filters */
+ r->end[4] = 347;
+ r->end[5] = 113;
+ r->end[6] = 37;
+
+ for (int i = 0; i < RV_NZ; ++i) {
+ r->delays[i]= NULL;
+ }
+
+ r->yy1 = 0.0;
+ r->y_1 = 0.0;
+
+ for (int i = 0; i < RV_NZ; i++) {
+ err |= setReverbPointers (r, i, rate);
+ }
+ return err;
+}
+
+static void
+reverb (b_reverb* r,
+ const float* inbuf,
+ float* outbuf,
+ size_t n_samples)
+{
+ float** const idxp = r->idxp;
+ float* const* const endp = r->endp;
+ float* const* const idx0 = r->idx0;
+ const float* const gain = r->gain;
+ const float inputGain = r->inputGain;
+ const float fbk = r->fbk;
+ const float wet = r->wet;
+ const float dry = r->dry;
+
+ const float* xp = inbuf;
+ float* yp = outbuf;
+
+ float y_1 = r->y_1;
+ float yy1 = r->yy1;
+
+ for (size_t i = 0; i < n_samples; ++i) {
+ int j;
+ float y;
+ const float xo = *xp++;
+ const float x = y_1 + (inputGain * xo);
+ float xa = 0.0;
+ /* First we do four feedback comb filters (ie parallel delay lines,
+ * each with a single tap at the end that feeds back at the start) */
+
+ for (j = 0; j < 4; ++j) {
+ y = *idxp[j];
+ *idxp[j] = x + (gain[j] * y);
+ if (endp[j] <= ++(idxp[j])) {
+ idxp[j] = idx0[j];
+ }
+ xa += y;
+ }
+
+ for (; j < 7; ++j) {
+ y = *idxp[j];
+ *idxp[j] = gain[j] * (xa + y);
+ if (endp[j] <= ++(idxp[j])) {
+ idxp[j] = idx0[j];
+ }
+ xa = y - xa;
+ }
+
+ y = 0.5f * (xa + yy1);
+ yy1 = y;
+ y_1 = fbk * xa;
+
+ *yp++ = ((wet * y) + (dry * xo));
+ }
+
+ r->y_1 = y_1 + DENORMAL_PROTECT;
+ r->yy1 = yy1 + DENORMAL_PROTECT;
+}
+
+/******************************************************************************
+ * LV2 wrapper
+ */
+
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+typedef enum {
+ AR_INPUT = 0,
+ AR_OUTPUT = 1,
+ AR_MIX = 2,
+ AR_GAIN_IN = 3,
+ AR_GAIN_OUT = 4,
+} PortIndex;
+
+typedef struct {
+ float* input;
+ float* output;
+
+ float* mix;
+ float* gain_in;
+ float* gain_out; // unused
+
+ float v_mix;
+ float v_gain_in;
+
+ b_reverb r;
+} AReverb;
+
+static LV2_Handle
+instantiate (const LV2_Descriptor* descriptor,
+ double rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ AReverb* self = (AReverb*)calloc (1, sizeof (AReverb));
+ if (!self) {
+ return NULL;
+ }
+ if (initReverb (&self->r, rate)) {
+ return NULL;
+ }
+
+ // these are set in initReverb()
+ self->v_gain_in = -40; // [dB]
+ self->v_mix = 0.1;
+
+ return (LV2_Handle)self;
+}
+
+static void
+connect_port (LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ AReverb* self = (AReverb*)instance;
+
+ switch ((PortIndex)port) {
+ case AR_INPUT:
+ self->input = (float*)data;
+ break;
+ case AR_OUTPUT:
+ self->output = (float*)data;
+ break;
+ case AR_MIX:
+ self->mix = (float*)data;
+ break;
+ case AR_GAIN_IN:
+ self->gain_in = (float*)data;
+ break;
+ case AR_GAIN_OUT:
+ self->gain_out = (float*)data;
+ break;
+ }
+}
+
+static void
+run (LV2_Handle instance, uint32_t n_samples)
+{
+ AReverb* self = (AReverb*)instance;
+
+ const float* const input = self->input;
+ float* const output = self->output;
+
+ // TODO interpolate
+ if (*self->mix != self->v_mix) {
+ self->v_mix = *self->mix;
+ const float u = self->r.wet + self->r.dry;
+ self->r.wet = self->v_mix * u;
+ self->r.dry = u - (self->v_mix * u);
+ }
+ if (*self->gain_in != self->v_gain_in) {
+ self->v_gain_in = *self->gain_in;
+ self->r.inputGain = powf (10.0, .05 * self->v_gain_in);
+ }
+ if (self->gain_out) { // unused
+ const float g = *self->gain_out;
+ const float u = self->r.wet + self->r.dry;
+ self->r.wet = g * (self->r.wet / u);
+ self->r.dry = g * (self->r.dry / u);
+ }
+
+ reverb (&self->r, input, output, n_samples);
+}
+
+static void
+activate (LV2_Handle instance)
+{
+ AReverb* self = (AReverb*)instance;
+ self->r.y_1 = 0;
+ self->r.yy1 = 0;
+}
+
+static void
+deactivate (LV2_Handle instance)
+{
+}
+
+static void
+cleanup (LV2_Handle instance)
+{
+ AReverb* self = (AReverb*)instance;
+ for (int i = 0; i < RV_NZ; ++i) {
+ free (self->r.delays[i]);
+ }
+ free (instance);
+}
+
+static const void*
+extension_data (const char* uri)
+{
+ return NULL;
+}
+
+static const LV2_Descriptor descriptor = {
+ "urn:ardour:a-reverb",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ deactivate,
+ cleanup,
+ extension_data
+};
+
+LV2_SYMBOL_EXPORT
+const LV2_Descriptor*
+lv2_descriptor (uint32_t index)
+{
+ switch (index) {
+ case 0:
+ return &descriptor;
+ default:
+ return NULL;
+ }
+}
diff --git a/libs/plugins/a-reverb.lv2/a-reverb.ttl.in b/libs/plugins/a-reverb.lv2/a-reverb.ttl.in
new file mode 100644
index 0000000000..9ff6801d15
--- /dev/null
+++ b/libs/plugins/a-reverb.lv2/a-reverb.ttl.in
@@ -0,0 +1,61 @@
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix mod: <http://moddevices.com/ns/mod#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://ardour.org/credits.html>
+ a foaf:Person ;
+ foaf:name "Ardour Team" ;
+ foaf:homepage <http://ardour.org/> .
+
+<urn:ardour:a-reverb>
+ a doap:Project, lv2:Plugin, lv2:SpatialPlugin ;
+
+ doap:name "A-Reverb";
+ rdfs:comment "A Schroeder Reverberator"
+
+ doap:maintainer <http://ardour.org/credits.html>
+ doap:license <http://usefulinc.com/doap/licenses/gpl> ;
+
+ lv2:microVersion 0 ; lv2:minorVersion 1 ;
+ lv2:optionalFeature lv2:hardRTCapable ;
+
+ lv2:port
+ [
+ a lv2:AudioPort ,
+ lv2:InputPort ;
+ lv2:index 0 ;
+ lv2:symbol "in" ;
+ lv2:name "In"
+ ],
+ [
+ a lv2:AudioPort ,
+ lv2:OutputPort ;
+ lv2:index 1 ;
+ lv2:symbol "out" ;
+ lv2:name "Out"
+ ],
+ [
+ a lv2:InputPort ,
+ lv2:ControlPort ;
+ lv2:index 3 ;
+ lv2:symbol "gain_in" ;
+ lv2:name "Input Gain";
+ lv2:default -30;
+ lv2:minimum -80;
+ lv2:maximum -3;
+ unit:unit unit:db ;
+ ],
+ [
+ a lv2:InputPort ,
+ lv2:ControlPort ;
+ lv2:index 2 ;
+ lv2:symbol "mix" ;
+ lv2:name "Dry/Wet";
+ lv2:default 0.3;
+ lv2:minimum 0.0 ;
+ lv2:maximum 1.0 ;
+ ] ;
+ .
diff --git a/libs/plugins/a-reverb.lv2/manifest.ttl.in b/libs/plugins/a-reverb.lv2/manifest.ttl.in
new file mode 100644
index 0000000000..c685139932
--- /dev/null
+++ b/libs/plugins/a-reverb.lv2/manifest.ttl.in
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<urn:ardour:a-reverb>
+ a lv2:Plugin ;
+ lv2:binary <a-reverb@LIB_EXT@> ;
+ rdfs:seeAlso <a-reverb.ttl> .
diff --git a/libs/plugins/a-reverb.lv2/wscript b/libs/plugins/a-reverb.lv2/wscript
new file mode 100644
index 0000000000..35601f2179
--- /dev/null
+++ b/libs/plugins/a-reverb.lv2/wscript
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+import os
+import re
+import shutil
+import waflib.extras.autowaf as autowaf
+import waflib.Options as Options, waflib.Utils as Utils
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+def options(opt):
+ autowaf.set_options(opt)
+
+def configure(conf):
+ conf.load('compiler_c')
+ autowaf.configure(conf)
+ if Options.options.lv2:
+ autowaf.check_pkg(conf, 'lv2', atleast_version='1.0.0',
+ uselib_store='LV2_1_0_0')
+
+def build(bld):
+ bundle = 'a-reverb.lv2'
+ module_pat = re.sub('^lib', '', bld.env.cshlib_PATTERN)
+ module_ext = module_pat[module_pat.rfind('.'):]
+
+ if bld.is_defined ('HAVE_LV2'):
+ # Build RDF files
+ for i in ['manifest.ttl', 'a-reverb.ttl']:
+ bld(features = 'subst',
+ source = i + '.in',
+ target = '../../LV2/%s/%s' % (bundle, i),
+ install_path = '${LV2DIR}/%s' % bundle,
+ chmod = Utils.O644,
+ LIB_EXT = module_ext)
+
+ # Build plugin library
+ obj = bld(features = 'c cshlib',
+ source = 'a-reverb.c',
+ name = 'a-reverb',
+ cflags = [ '-fPIC', bld.env['compiler_flags_dict']['c99'] ],
+ includes = [ '../../ardour' ],
+ target = '../../LV2/%s/a-reverb' % bundle,
+ install_path = '${LV2DIR}/%s' % bundle,
+ uselib = 'CAIRO',
+ use = 'LV2_1_0_0'
+ )
+ obj.env.cshlib_PATTERN = module_pat
+ obj.env.cxxshlib_PATTERN = module_pat
+
+# vi:set ts=4 sw=4 et:
diff --git a/wscript b/wscript
index 5678609811..fce1359b04 100644
--- a/wscript
+++ b/wscript
@@ -222,6 +222,7 @@ children = [
'libs/plugins/a-comp.lv2',
'libs/plugins/a-delay.lv2',
'libs/plugins/a-eq.lv2',
+ 'libs/plugins/a-reverb.lv2',
'gtk2_ardour',
'export',
'midi_maps',