aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/adenv.c250
-rw-r--r--src/adenv_lvl.c299
-rw-r--r--src/comparison.c135
-rw-r--r--src/dahdsr_fexp.c342
-rw-r--r--src/dahdsr_hexp.c344
-rw-r--r--src/fast_crossfade.c139
-rw-r--r--src/formant_filter.c213
-rw-r--r--src/hz_voct.c117
-rw-r--r--src/masher.c244
-rw-r--r--src/multiplexer.c120
-rw-r--r--src/prob_switch.c130
-rw-r--r--src/range_trans.c131
-rw-r--r--src/sample_and_hold.c150
-rw-r--r--src/signal_abs.c124
-rw-r--r--src/slew_limiter.c149
-rw-r--r--src/slide.c170
-rw-r--r--src/waveguide_mesh.c274
17 files changed, 3331 insertions, 0 deletions
diff --git a/src/adenv.c b/src/adenv.c
new file mode 100644
index 0000000..dabca16
--- /dev/null
+++ b/src/adenv.c
@@ -0,0 +1,250 @@
+/*
+ adenv.c - A LV2 plugin to generate percussive (i.e no sustain time), linear AD envelopes.
+
+ Copyright 2005 Loki Davison
+ based on ADENV by Mike Rawes
+
+ 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 of the License, 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <stdio.h>
+#include <math.h>
+
+#define ADENV_BASE_ID 2661
+
+#define ADENV_GATE 0
+#define ADENV_TRIGGER 1
+#define ADENV_ATTACK 2
+#define ADENV_DECAY 3
+#define ADENV_OUTPUT 4
+
+LV2_Descriptor **dahdsr_descriptors = 0;
+
+typedef enum {
+ IDLE,
+ ATTACK,
+ DECAY,
+} ADENVState;
+
+typedef struct {
+ float *gate;
+ float *trigger;
+ float *attack;
+ float *decay;
+ float *output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float from_level;
+ float level;
+ ADENVState state;
+ unsigned long samples;
+} Dahdsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ switch (port) {
+ case ADENV_GATE:
+ plugin->gate = (float*)data;
+ break;
+ case ADENV_TRIGGER:
+ plugin->trigger = (float*)data;
+ break;
+ case ADENV_ATTACK:
+ plugin->attack = (float*)data;
+ break;
+ case ADENV_DECAY:
+ plugin->decay = (float*)data;
+ break;
+ case ADENV_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Dahdsr *plugin = (Dahdsr *) malloc(sizeof(Dahdsr));
+
+ plugin->srate = (float) sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle) plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t sample_count)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ /* Gate */
+ float *gate = plugin->gate;
+
+ /* Trigger */
+ float *trigger = plugin->trigger;
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Envelope Out */
+ float *output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ ADENVState state = plugin->state;
+ unsigned long samples = plugin->samples;
+
+ float gat, trg, att, dec;
+ float elapsed;
+ unsigned long s;
+
+ /* Convert times into rates */
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ /* cuse's formula ...
+ * ReleaseCoeff = (ln(EndLevel) - ln(StartLevel)) / (EnvelopeDuration * SampleRate)
+ *
+ * while (currentSample < endSample) Level += Level * ReleaseCoeff;
+ */
+
+ float ReleaseCoeff = log(0.001) / (decay * srate);
+
+ for (s = 0; s < sample_count; s++) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f)) ||
+ (gat > 0.0f && !(last_gate > 0.0f))) {
+ //fprintf(stderr, "triggered in control \n");
+ if (att <= srate) {
+ state = ATTACK;
+ }
+ samples = 0;
+ }
+
+ if (samples == 0)
+ from_level = level;
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float) samples *att;
+
+ if (elapsed > 1.0f) {
+ state = DECAY;
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float) samples *dec;
+
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ //fprintf(stderr, "decay, dec %f elapsed %f from level %f level %f\n", dec, elapsed, from_level, level);
+ level += level * ReleaseCoeff;
+
+ }
+ break;
+ default:
+ /* Should never happen */
+ fprintf(stderr, "bugger!!!");
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ last_gate = gat;
+ last_trigger = trg;
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/adenv",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/adenv_lvl.c b/src/adenv_lvl.c
new file mode 100644
index 0000000..4fb6a9c
--- /dev/null
+++ b/src/adenv_lvl.c
@@ -0,0 +1,299 @@
+/*
+ adenv.c - A LV2 plugin to generate percussive (i.e no sustain time), linear AD envelopes.
+ This one takes in levels to make filter sweeps/etc easier.
+
+ Copyright 2005 Loki Davison
+ based of DADSR by Mike Rawes
+
+ 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 of the License, 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <stdio.h>
+#include <math.h>
+
+#define ADENVLVL_BASE_ID 2662
+#define ADENVLVL_VARIANT_COUNT 1
+
+#define ADENVLVL_GATE 0
+#define ADENVLVL_TRIGGER 1
+#define ADENVLVL_START_LEVEL 2
+#define ADENVLVL_ATTACK_LEVEL 3
+#define ADENVLVL_DECAY_LEVEL 4
+#define ADENVLVL_ATTACK 5
+#define ADENVLVL_DECAY 6
+#define ADENVLVL_OUTPUT 7
+#define ADENVLVL_RESET 8
+
+typedef enum {
+ IDLE,
+ ATTACK,
+ DECAY,
+} ADENVLVLState;
+
+typedef struct {
+ float *gate;
+ float *trigger;
+ float *attack;
+ float *reset;
+ float *decay;
+ float *start_level;
+ float *attack_level;
+ float *decay_level;
+ float *output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float last_reset;
+ float level;
+ ADENVLVLState state;
+ unsigned long samples;
+} Dahdsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port, void * data)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ switch (port) {
+ case ADENVLVL_GATE:
+ plugin->gate = (float*)data;
+ break;
+ case ADENVLVL_TRIGGER:
+ plugin->trigger = (float*)data;
+ break;
+ case ADENVLVL_START_LEVEL:
+ plugin->start_level = (float*)data;
+ break;
+ case ADENVLVL_ATTACK_LEVEL:
+ plugin->attack_level = (float*)data;
+ break;
+ case ADENVLVL_DECAY_LEVEL:
+ plugin->decay_level = (float*)data;
+ break;
+ case ADENVLVL_ATTACK:
+ plugin->attack = (float*)data;
+ break;
+ case ADENVLVL_DECAY:
+ plugin->decay = (float*)data;
+ break;
+ case ADENVLVL_RESET:
+ plugin->reset = (float*)data;
+ break;
+ case ADENVLVL_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Dahdsr *plugin = (Dahdsr *) malloc(sizeof(Dahdsr));
+
+ plugin->srate = (float) sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle) plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->last_reset = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t sample_count)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ /* Gate */
+ float *gate = plugin->gate;
+
+ /* Trigger */
+ float *trigger = plugin->trigger;
+
+ /* Reset */
+ float *reset = plugin->reset;
+
+ /* Start Level */
+ float start_level = *(plugin->start_level);
+
+ /* Attack Level */
+ float attack_level = *(plugin->attack_level);
+
+ /* Decay Level */
+ float decay_level = *(plugin->decay_level);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Envelope Out */
+ float *output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float last_reset = plugin->last_reset;
+ float level = plugin->level;
+ ADENVLVLState state = plugin->state;
+ unsigned long samples = plugin->samples;
+
+ float gat, trg, att, dec;
+ float elapsed;
+ unsigned long s;
+
+ /* Convert times into rates */
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ /* cuse's formula ...
+ * ReleaseCoeff = (ln(EndLevel) - ln(StartLevel)) / (EnvelopeDuration * SampleRate)
+ *
+ * while (currentSample < endSample) Level += Level * ReleaseCoeff;
+ */
+ /* check params don't cause div by zero */
+ if (start_level == 0) {
+ start_level = 0.0000001;
+ }
+ if (attack_level == 0) {
+ attack_level = 0.0000001;
+ }
+ if (decay_level == 0) {
+ decay_level = 0.0000001;
+ }
+ float ReleaseCoeff_att =
+ (log(attack_level) - log(start_level)) / (attack * srate);
+ float ReleaseCoeff_dec =
+ (log(decay_level) - log(attack_level)) / (decay * srate);
+
+ for (s = 0; s < sample_count; s++) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f)) ||
+ (gat > 0.0f && !(last_gate > 0.0f))) {
+ //fprintf(stderr, "triggered in control \n");
+ if (att < srate) {
+ state = ATTACK;
+ }
+ samples = 0;
+ }
+ /* if we got a reset */
+
+ if (reset[s] > 0.0f && !(last_reset > 0.0f)) {
+ level = start_level;
+ /*fprintf(stderr, "got reset start level %f \n", start_level); */
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ /* might need to fix this... */
+ break;
+ case ATTACK:
+ /* fix level adding prob */
+ if (samples == 0) {
+ level = start_level;
+ }
+ samples++;
+ elapsed = (float) samples *att;
+
+ if (elapsed > 1.0f) {
+ state = DECAY;
+ samples = 0;
+ //fprintf(stderr, "finished attack, RC %f, level %f attack_level %f start %f\n", ReleaseCoeff_att, level, attack_level, start_level);
+ } else {
+ level += level * ReleaseCoeff_att;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float) samples *dec;
+
+ if (elapsed > 1.0f) {
+ //fprintf(stderr, "finished decay, RC %f , level %f decay_level %f start %f\n", ReleaseCoeff_dec, level, decay_level, start_level);
+ state = IDLE;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_dec;
+ }
+ break;
+ default:
+ /* Should never happen */
+ fprintf(stderr, "bugger!!!");
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ last_gate = gat;
+ last_trigger = trg;
+ last_reset = reset[s];
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->last_reset = last_reset;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/adenv_lvl",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/comparison.c b/src/comparison.c
new file mode 100644
index 0000000..009989b
--- /dev/null
+++ b/src/comparison.c
@@ -0,0 +1,135 @@
+/* Comparison plugin.
+ * Copyright 2005 Thorsten Wilms.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#include "lv2.h"
+
+#define COMP_BASE_ID 4440
+
+#define COMP_NUM_PORTS 6
+
+/* Port Numbers */
+#define COMP_A 0
+#define COMP_B 1
+#define COMP_LARGER 2
+#define COMP_SMALLER 3
+#define COMP_A_LARGER 4
+#define COMP_EQUAL 5
+
+/* All state information for plugin */
+typedef struct {
+ /* Ports */
+ float *a_buffer;
+ float *b_buffer;
+ float *larger_buffer;
+ float *smaller_buffer;
+ float *a_larger_buffer;
+ float *equal_buffer;
+} Comp;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Comp* plugin = (Comp*)calloc(1, sizeof(Comp));
+
+ return (LV2_Handle)plugin;
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Comp* plugin = (Comp*)instance;
+ switch (port) {
+ case COMP_A:
+ plugin->a_buffer = (float*)data;
+ break;
+ case COMP_B:
+ plugin->b_buffer = (float*)data;
+ break;
+ case COMP_LARGER:
+ plugin->larger_buffer = (float*)data;
+ break;
+ case COMP_SMALLER:
+ plugin->smaller_buffer = (float*)data;
+ break;
+ case COMP_A_LARGER:
+ plugin->a_larger_buffer = (float*)data;
+ break;
+ case COMP_EQUAL:
+ plugin->equal_buffer = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ Comp* const plugin = (Comp*)instance;
+ const float* const a = plugin->a_buffer;
+ const float* const b = plugin->b_buffer;
+ float* const larger = plugin->larger_buffer;
+ float* const smaller = plugin->smaller_buffer;
+ float* const a_larger = plugin->a_larger_buffer;
+ float* const equal = plugin->equal_buffer;
+ unsigned long i;
+
+ for (i = 0; i < nframes; i++) {
+ equal[i] = (a[i] == b[i]) ? 1.0 : 0.0;
+ larger[i] = (a[i] > b[i]) ? a[i] : b[i];
+ smaller[i] = (a[i] < b[i]) ? a[i] : b[i];
+ a_larger[i] = (a[i] > b[i]) ? 1.0 : 0.0;
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/comparison",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/dahdsr_fexp.c b/src/dahdsr_fexp.c
new file mode 100644
index 0000000..7e92c09
--- /dev/null
+++ b/src/dahdsr_fexp.c
@@ -0,0 +1,342 @@
+/*
+ dahdsr_fexp.c - A LV2 plugin to generate DAHDSR envelopes
+ exponential attack, decay and release version.
+ Copyright 2005 Loki Davison, based on DAHDSR by Mike Rawes
+
+ 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 of the License, 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <math.h>
+
+#define DAHDSR_GATE 0
+#define DAHDSR_TRIGGER 1
+#define DAHDSR_DELAY 2
+#define DAHDSR_ATTACK 3
+#define DAHDSR_HOLD 4
+#define DAHDSR_DECAY 5
+#define DAHDSR_SUSTAIN 6
+#define DAHDSR_RELEASE 7
+#define DAHDSR_OUTPUT 8
+
+typedef enum {
+ IDLE,
+ DELAY,
+ ATTACK,
+ HOLD,
+ DECAY,
+ SUSTAIN,
+ RELEASE
+} DAHDSRState;
+
+typedef struct {
+ float *gate;
+ float *trigger;
+ float *delay;
+ float *attack;
+ float *hold;
+ float *decay;
+ float *sustain;
+ float *release;
+ float *output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float from_level;
+ float level;
+ DAHDSRState state;
+ unsigned long samples;
+} Dahdsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ switch (port) {
+ case DAHDSR_GATE:
+ plugin->gate = (float*)data;
+ break;
+ case DAHDSR_TRIGGER:
+ plugin->trigger = (float*)data;
+ break;
+ case DAHDSR_DELAY:
+ plugin->delay = (float*)data;
+ break;
+ case DAHDSR_ATTACK:
+ plugin->attack = (float*)data;
+ break;
+ case DAHDSR_HOLD:
+ plugin->hold = (float*)data;
+ break;
+ case DAHDSR_DECAY:
+ plugin->decay = (float*)data;
+ break;
+ case DAHDSR_SUSTAIN:
+ plugin->sustain = (float*)data;
+ break;
+ case DAHDSR_RELEASE:
+ plugin->release = (float*)data;
+ break;
+ case DAHDSR_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Dahdsr *plugin = (Dahdsr *) malloc(sizeof(Dahdsr));
+
+ plugin->srate = (float) sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle) plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t sample_count)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ /* Gate */
+ float *gate = plugin->gate;
+
+ /* Trigger */
+ float *trigger = plugin->trigger;
+
+ /* Delay Time (s) */
+ float delay = *(plugin->delay);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Hold Time (s) */
+ float hold = *(plugin->hold);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = *(plugin->sustain);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float *output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ DAHDSRState state = plugin->state;
+ unsigned long samples = plugin->samples;
+
+ float gat, trg, del, att, hld, dec, sus, rel;
+ float elapsed;
+ unsigned long s;
+
+ /* Convert times into rates */
+ del = delay > 0.0f ? inv_srate / delay : srate;
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ hld = hold > 0.0f ? inv_srate / hold : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ rel = release > 0.0f ? inv_srate / release : srate;
+ sus = sustain;
+
+ if (sus == 0.0f) {
+ sus = 0.001f;
+ }
+ if (sus > 1.0f) {
+ sus = 1.0f;
+ }
+
+ float ReleaseCoeff_att = (0 - log(0.001)) / (attack * srate);
+ float ReleaseCoeff_dec = (log(sus)) / (decay * srate);
+ float ReleaseCoeff_rel =
+ (log(0.001) - log(sus)) / (release * srate);
+
+ for (s = 0; s < sample_count; s++) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f)) ||
+ (gat > 0.0f && !(last_gate > 0.0f))) {
+ if (del < srate) {
+ state = DELAY;
+ } else if (att < srate) {
+ state = ATTACK;
+ } else {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE)));
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate was open and now closed */
+ if (state != IDLE && state != RELEASE &&
+ last_gate > 0.0f && !(gat > 0.0f)) {
+ state = rel < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ if (samples == 0)
+ from_level = level;
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case DELAY:
+ samples++;
+ elapsed = (float) samples *del;
+
+ if (elapsed > 1.0f) {
+ state = att < srate ? ATTACK
+ : (hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE))));
+ samples = 0;
+ }
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float) samples *att;
+
+ if (elapsed > 1.0f) {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE)));
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_att;
+ }
+ break;
+ case HOLD:
+ samples++;
+ elapsed = (float) samples *hld;
+
+ if (elapsed > 1.0f) {
+ state = dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN : (rel < srate ? RELEASE : IDLE));
+ samples = 0;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float) samples *dec;
+
+ if (elapsed > 1.0f) {
+ state = gat > 0.0f ? SUSTAIN : (rel < srate ? RELEASE : IDLE);
+ level = sus;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_dec;
+ }
+ break;
+ case SUSTAIN:
+ level = sus;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float) samples *rel;
+
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_rel;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+
+ last_gate = gat;
+ last_trigger = trg;
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/dahdsr_fexp",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/dahdsr_hexp.c b/src/dahdsr_hexp.c
new file mode 100644
index 0000000..8f45fc9
--- /dev/null
+++ b/src/dahdsr_hexp.c
@@ -0,0 +1,344 @@
+/*
+ dahdsr.so.c - A LV2 plugin to generate DAHDSR envelopes
+ linear attack, exponential decay and release version.
+ Copyright 2005 Loki Davison, based on DAHDSR by Mike Rawes
+
+ 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 of the License, 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <math.h>
+
+#define DAHDSR_GATE 0
+#define DAHDSR_TRIGGER 1
+#define DAHDSR_DELAY 2
+#define DAHDSR_ATTACK 3
+#define DAHDSR_HOLD 4
+#define DAHDSR_DECAY 5
+#define DAHDSR_SUSTAIN 6
+#define DAHDSR_RELEASE 7
+#define DAHDSR_OUTPUT 8
+
+LV2_Descriptor **dahdsr_descriptors = 0;
+
+typedef enum {
+ IDLE,
+ DELAY,
+ ATTACK,
+ HOLD,
+ DECAY,
+ SUSTAIN,
+ RELEASE
+} DAHDSRState;
+
+typedef struct {
+ float *gate;
+ float *trigger;
+ float *delay;
+ float *attack;
+ float *hold;
+ float *decay;
+ float *sustain;
+ float *release;
+ float *output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float from_level;
+ float level;
+ DAHDSRState state;
+ unsigned long samples;
+} Dahdsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ switch (port) {
+ case DAHDSR_GATE:
+ plugin->gate = (float*)data;
+ break;
+ case DAHDSR_TRIGGER:
+ plugin->trigger = (float*)data;
+ break;
+ case DAHDSR_DELAY:
+ plugin->delay = (float*)data;
+ break;
+ case DAHDSR_ATTACK:
+ plugin->attack = (float*)data;
+ break;
+ case DAHDSR_HOLD:
+ plugin->hold = (float*)data;
+ break;
+ case DAHDSR_DECAY:
+ plugin->decay = (float*)data;
+ break;
+ case DAHDSR_SUSTAIN:
+ plugin->sustain = (float*)data;
+ break;
+ case DAHDSR_RELEASE:
+ plugin->release = (float*)data;
+ break;
+ case DAHDSR_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Dahdsr *plugin = (Dahdsr *) malloc(sizeof(Dahdsr));
+
+ plugin->srate = (float) sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle) plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t sample_count)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ /* Gate */
+ float *gate = plugin->gate;
+
+ /* Trigger */
+ float *trigger = plugin->trigger;
+
+ /* Delay Time (s) */
+ float delay = *(plugin->delay);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Hold Time (s) */
+ float hold = *(plugin->hold);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = *(plugin->sustain);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float *output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ DAHDSRState state = plugin->state;
+ unsigned long samples = plugin->samples;
+
+ float gat, trg, del, att, hld, dec, sus, rel;
+ float elapsed;
+ unsigned long s;
+
+ /* Convert times into rates */
+ del = delay > 0.0f ? inv_srate / delay : srate;
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ hld = hold > 0.0f ? inv_srate / hold : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ rel = release > 0.0f ? inv_srate / release : srate;
+ sus = sustain;
+
+ if (sus == 0) {
+ sus = 0.001;
+ }
+ if (sus > 1.0f) {
+ sus = 1.0f;
+ }
+
+ //float ReleaseCoeff_att = (0 - log(0.001)) / (attack * srate);
+ float ReleaseCoeff_dec = (log(sus)) / (decay * srate);
+ float ReleaseCoeff_rel =
+ (log(0.001) - log(sus)) / (release * srate);
+
+ for (s = 0; s < sample_count; s++) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f)) ||
+ (gat > 0.0f && !(last_gate > 0.0f))) {
+ if (del < srate) {
+ state = DELAY;
+ } else if (att < srate) {
+ state = ATTACK;
+ } else {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE)));
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate was open and now closed */
+ if (state != IDLE && state != RELEASE &&
+ last_gate > 0.0f && !(gat > 0.0f)) {
+ state = rel < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ if (samples == 0)
+ from_level = level;
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case DELAY:
+ samples++;
+ elapsed = (float) samples *del;
+
+ if (elapsed > 1.0f) {
+ state = att < srate ? ATTACK
+ : (hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE))));
+ samples = 0;
+ }
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float) samples *att;
+
+ if (elapsed > 1.0f) {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE : IDLE)));
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case HOLD:
+ samples++;
+ elapsed = (float) samples *hld;
+
+ if (elapsed > 1.0f) {
+ state = dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN : (rel < srate ? RELEASE : IDLE));
+ samples = 0;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float) samples *dec;
+
+ if (elapsed > 1.0f) {
+ state = gat > 0.0f ? SUSTAIN : (rel < srate ? RELEASE : IDLE);
+ level = sus;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_dec;
+ }
+ break;
+ case SUSTAIN:
+ level = sus;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float) samples *rel;
+
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_rel;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+
+ last_gate = gat;
+ last_trigger = trg;
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/dahdsr_hexp",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/fast_crossfade.c b/src/fast_crossfade.c
new file mode 100644
index 0000000..0e4389b
--- /dev/null
+++ b/src/fast_crossfade.c
@@ -0,0 +1,139 @@
+/* Crossfade with AR Level plugin.
+ * Copyright 2005 Thorsten Wilms.
+ *
+ * Based on David Robillard's "Hz to AMS style V/Oct" plugin for the skeleton.
+ * Thanks to Florian Schmidt for explaining how to calculate the scale values
+ * before I could work it out myself! ;-)
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define XFADE_LEVEL_ID 4410
+
+#define XFADE_NUM_PORTS 4
+
+/* Port Numbers */
+#define XFADE_LEVEL 0
+#define XFADE_A 1
+#define XFADE_B 2
+#define XFADE_OUTPUT 3
+
+/* All state information for plugin */
+typedef struct {
+ /* Ports */
+ float *level_buffer;
+ float *a_buffer;
+ float *b_buffer;
+ float *output_buffer;
+} XFADE;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(XFADE));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ XFADE* plugin;
+
+ plugin = (XFADE*) instance;
+ switch (port) {
+ case XFADE_LEVEL:
+ plugin->level_buffer = (float*)data;
+ break;
+ case XFADE_A:
+ plugin->a_buffer = (float*)data;
+ break;
+ case XFADE_B:
+ plugin->b_buffer = (float*)data;
+ break;
+ case XFADE_OUTPUT:
+ plugin->output_buffer = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ float* level;
+ float* a;
+ float* b;
+ float* output;
+ XFADE* plugin;
+ unsigned long i;
+ float l;
+
+ plugin = (XFADE*)instance;
+
+ level = plugin->level_buffer;
+ a = plugin->a_buffer;
+ b = plugin->b_buffer;
+ output = plugin->output_buffer;
+
+ for (i = 0; i < nframes; i++) {
+ /* transfer multiplication value to 0 to 1 range */
+ if (level[i] < -1) {
+ l = 0;
+ } else if (level[i] > 1) {
+ l = 1;
+ } else {
+ l = (level[i] + 1) / 2;
+ }
+
+ output[i] = a[i] * l + b[i] * (1 - l);
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/fast_crossfade",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/formant_filter.c b/src/formant_filter.c
new file mode 100644
index 0000000..afbf4f7
--- /dev/null
+++ b/src/formant_filter.c
@@ -0,0 +1,213 @@
+/* Formant filter plugin. Copyright 2005-2011 David Robillard.
+ *
+ * Based on SSM formant filter,
+ * Copyright 2001 David Griffiths <dave@pawfal.org>
+ *
+ * Based on public domain code from alex@smartelectronix.com
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define FORMANT_BASE_ID 4300
+
+#define FORMANT_NUM_PORTS 3
+
+/* Port Numbers */
+#define FORMANT_VOWEL 0
+#define FORMANT_INPUT 1
+#define FORMANT_OUTPUT 2
+
+/* Vowel Coefficients */
+const double coeff[5][11] = {
+ { /* A */ 8.11044e-06,
+ 8.943665402, -36.83889529, 92.01697887, -154.337906, 181.6233289,
+ -151.8651235, 89.09614114, -35.10298511, 8.388101016, -0.923313471
+ },
+ { /* E */ 4.36215e-06,
+ 8.90438318, -36.55179099, 91.05750846, -152.422234, 179.1170248,
+ -149.6496211, 87.78352223, -34.60687431, 8.282228154, -0.914150747
+ },
+ { /* I */ 3.33819e-06,
+ 8.893102966, -36.49532826, 90.96543286, -152.4545478, 179.4835618,
+ -150.315433, 88.43409371, -34.98612086, 8.407803364, -0.932568035
+ },
+ { /* O */ 1.13572e-06,
+ 8.994734087, -37.2084849, 93.22900521, -156.6929844, 184.596544,
+ -154.3755513, 90.49663749, -35.58964535, 8.478996281, -0.929252233
+ },
+ { /* U */ 4.09431e-07,
+ 8.997322763, -37.20218544, 93.11385476, -156.2530937, 183.7080141,
+ -153.2631681, 89.59539726, -35.12454591, 8.338655623, -0.910251753
+ }
+};
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* vowel;
+ float* input;
+ float* output;
+
+ double memory[5][10];
+} Formant;
+
+/* Linear interpolation */
+inline static float
+linear(float bot, float top, float pos, float val1, float val2)
+{
+ float t = (pos - bot) / (top - bot);
+ return val1 * t + val2 * (1.0f - t);
+}
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(Formant));
+}
+
+/** Activate an instance */
+static void
+activate(LV2_Handle instance)
+{
+ Formant* plugin = (Formant*)instance;
+ int i, j;
+
+ for (i = 0; i < 5; ++i)
+ for (j = 0; j < 10; ++j)
+ plugin->memory[i][j] = 0.0;
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Formant* plugin = (Formant*)instance;
+ switch (port) {
+ case FORMANT_VOWEL:
+ plugin->vowel = (float*)data;
+ break;
+ case FORMANT_INPUT:
+ plugin->input = (float*)data;
+ break;
+ case FORMANT_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ Formant* plugin = (Formant*)instance;
+ float vowel;
+ float in;
+ float* out;
+ float res;
+ float o[5];
+ size_t n, v;
+
+ for (n=0; n < nframes; ++n) {
+ vowel = plugin->vowel[0];
+ in = plugin->input[n];
+ out = plugin->output;
+
+ for (v=0; v < 5; ++v) {
+ res = (float) (coeff[v][0] * (in * 0.1f) +
+ coeff[v][1] * plugin->memory[v][0] +
+ coeff[v][2] * plugin->memory[v][1] +
+ coeff[v][3] * plugin->memory[v][2] +
+ coeff[v][4] * plugin->memory[v][3] +
+ coeff[v][5] * plugin->memory[v][4] +
+ coeff[v][6] * plugin->memory[v][5] +
+ coeff[v][7] * plugin->memory[v][6] +
+ coeff[v][8] * plugin->memory[v][7] +
+ coeff[v][9] * plugin->memory[v][8] +
+ coeff[v][10] * plugin->memory[v][9] );
+
+ plugin->memory[v][9] = plugin->memory[v][8];
+ plugin->memory[v][8] = plugin->memory[v][7];
+ plugin->memory[v][7] = plugin->memory[v][6];
+ plugin->memory[v][6] = plugin->memory[v][5];
+ plugin->memory[v][5] = plugin->memory[v][4];
+ plugin->memory[v][4] = plugin->memory[v][3];
+ plugin->memory[v][3] = plugin->memory[v][2];
+ plugin->memory[v][2] = plugin->memory[v][1];
+ plugin->memory[v][1] = plugin->memory[v][0];
+ plugin->memory[v][0] = (double)res;
+
+ o[v] = res;
+ }
+
+ // Mix between formants
+ if (vowel <= 0)
+ out[n] = o[0];
+ else if (vowel > 0 && vowel < 1)
+ out[n] = linear(0.0f, 1.0f, vowel, o[1], o[0]);
+ else if (vowel == 1)
+ out[n] = o[1];
+ else if (vowel > 1 && vowel < 2)
+ out[n] = linear(0.0f, 1.0f, vowel - 1.0f, o[2], o[1]);
+ else if (vowel == 2)
+ out[n] = o[2];
+ else if (vowel > 2 && vowel < 3)
+ out[n] = linear(0.0f, 1.0f, vowel - 2.0f, o[3], o[2]);
+ else if (vowel == 3)
+ out[n] = o[3];
+ else if (vowel > 3 && vowel < 4)
+ out[n] = linear(0.0f, 1.0f, vowel - 3.0f, o[4], o[3]);
+ else //if (vowel >= 4)
+ out[n] = o[4];
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/formant_filter",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/hz_voct.c b/src/hz_voct.c
new file mode 100644
index 0000000..b272425
--- /dev/null
+++ b/src/hz_voct.c
@@ -0,0 +1,117 @@
+/* Hz to AMS style V/Oct plugin. Copyright 2005-2011 David Robillard.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define HZVOCT_BASE_ID 4200
+
+#define HZVOCT_NUM_PORTS 2
+
+/* Port Numbers */
+#define HZVOCT_INPUT 0
+#define HZVOCT_OUTPUT 1
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* input_buffer;
+ float* output_buffer;
+} HzVoct;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ HzVoct* plugin = (HzVoct*)calloc(1, sizeof(HzVoct));
+ return (LV2_Handle)plugin;
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ HzVoct* plugin;
+
+ plugin = (HzVoct*)instance;
+ switch (port) {
+ case HZVOCT_INPUT:
+ plugin->input_buffer = (float*)data;
+ break;
+ case HZVOCT_OUTPUT:
+ plugin->output_buffer = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ float* input;
+ float* output;
+ HzVoct* plugin;
+ unsigned long i;
+ float log2inv;
+ float eighth = 1.0f/8.0f;
+ const float offset = 5.0313842; // + octave, ... -1, 0, 1 ...
+
+ plugin = (HzVoct*)instance;
+ log2inv = 1.0f/logf(2.0);
+
+ input = plugin->input_buffer;
+ output = plugin->output_buffer;
+
+ // Inverse of the formula used in AMS's converter module (except the 1/8 part)
+ for (i = 0; i < nframes; i++)
+ *output++ = logf((*input++) * eighth) * log2inv - offset;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/hz_voct",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/masher.c b/src/masher.c
new file mode 100644
index 0000000..0a9eeda
--- /dev/null
+++ b/src/masher.c
@@ -0,0 +1,244 @@
+/* Masher
+ * Copyright 2001 David Griffiths <dave@pawfal.org>
+ * LV2fication 2005 David Robillard <drobilla@connect.carelton.ca>
+ *
+ * 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 of the License, 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* NOTE: This is a very dirty hack full of arbitrary limits and assumptions.
+ * It needs fixing/completion */
+
+#define _XOPEN_SOURCE 600 /* posix_memalign */
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define MASHER_BASE_ID 4310
+
+#define MASHER_NUM_PORTS 4
+
+/* Port Numbers */
+#define MASHER_INPUT 0
+#define MASHER_GRAINPITCH 1
+#define MASHER_DENSITY 2
+#define MASHER_OUTPUT 3
+
+#define GRAINSTORE_SIZE 1000
+#define OVERLAPS_SIZE 1000
+#define MAX_GRAIN_SIZE 2048
+
+typedef struct {
+ float* data;
+ size_t length;
+} Sample;
+
+typedef struct {
+ int pos;
+ int grain;
+} GrainDesc;
+
+/* All state information for plugin */
+typedef struct {
+ /* Ports */
+ float *input;
+ float *grain_pitch;
+ float *density;
+ float *output;
+
+ Sample grain_store[GRAINSTORE_SIZE];
+ GrainDesc overlaps[OVERLAPS_SIZE];
+ size_t overlaps_size;
+
+ size_t write_grain;
+} Masher;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(Masher));
+}
+
+/** Activate an instance */
+static void
+activate(LV2_Handle instance)
+{
+ Masher *plugin = (Masher*)instance;
+ int i = 0;
+
+ plugin->overlaps_size = 0;
+ plugin->write_grain = 0;
+
+ for (i=0; i < GRAINSTORE_SIZE; ++i) {
+#ifdef HAVE_POSIX_MEMALIGN
+ posix_memalign((void**)&plugin->grain_store[i].data, 16, MAX_GRAIN_SIZE * sizeof(float));
+#else
+ plugin->grain_store[i].data = (float*)calloc(MAX_GRAIN_SIZE, sizeof(float));
+#endif
+ plugin->grain_store[i].length = 0;
+ }
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void * data)
+{
+ Masher *plugin = (Masher *) instance;
+
+ switch (port) {
+ case MASHER_INPUT:
+ plugin->input = (float*)data;
+ break;
+ case MASHER_GRAINPITCH:
+ plugin->grain_pitch = (float*)data;
+ break;
+ case MASHER_DENSITY:
+ plugin->density = (float*)data;
+ break;
+ case MASHER_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static void
+mix_pitch(Sample* src, Sample* dst, size_t pos, float pitch)
+{
+ float n = 0;
+ size_t p = pos;
+
+ while (n < src->length && p < dst->length) {
+ dst->data[p] = dst->data[p] + src->data[(size_t)n];
+ n += pitch;
+ p++;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ Masher* plugin = (Masher*)instance;
+
+ static const int randomness = 1.0; // FIXME: make a control port
+ int read_grain = 0; // FIXME: what is this?
+ int grain_store_size = 100; // FIXME: what is this? (max 1000)
+
+ const float grain_pitch = *plugin->grain_pitch;
+ const float density = *plugin->density;
+
+ const float* const in = plugin->input;
+ float* const out = plugin->output;
+
+ Sample out_sample = { out, nframes };
+
+ size_t n = 0;
+ float s = in[0];
+ int last = 0;
+ bool first = true;
+ size_t grain_index = 0;
+ size_t next_grain = 0;
+
+ // Zero output buffer
+ for (n = 0; n < nframes; ++n)
+ out[n] = 0.0f;
+
+ // Paste any overlapping grains to the start of the buffer.
+ for (n = 0; n < plugin->overlaps_size; ++n) {
+ mix_pitch(&plugin->grain_store[plugin->overlaps[n].grain], &out_sample,
+ plugin->overlaps[n].pos - nframes, grain_pitch);
+ }
+ plugin->overlaps_size = 0;
+
+ // Chop up the buffer and put the grains in the grainstore
+ for (n = 0; n < nframes; n++) {
+ if ((s < 0 && in[n] > 0) || (s > 0 && in[n] < 0)) {
+ // Chop the bits between zero crossings
+ if (!first) {
+ if (n - last <= MAX_GRAIN_SIZE) {
+ grain_index = plugin->write_grain % grain_store_size;
+ memcpy(plugin->grain_store[grain_index].data, in, nframes);
+ plugin->grain_store[grain_index].length = n - last;
+ }
+ plugin->write_grain++; // FIXME: overflow?
+ } else {
+ first = false;
+ }
+
+ last = n;
+ s = in[n];
+ }
+ }
+
+ for (n = 0; n < nframes; n++) {
+ if (n >= next_grain || rand() % 1000 < density) {
+ size_t grain_num = read_grain % grain_store_size;
+ mix_pitch(&plugin->grain_store[grain_num], &out_sample, n, grain_pitch);
+ size_t grain_length = (plugin->grain_store[grain_num].length * grain_pitch);
+
+ next_grain = n + plugin->grain_store[grain_num].length;
+
+ // If this grain overlaps the buffer
+ if (n + grain_length > nframes) {
+ if (plugin->overlaps_size < OVERLAPS_SIZE) {
+ GrainDesc new_grain;
+
+ new_grain.pos = n;
+ new_grain.grain = grain_num;
+ plugin->overlaps[plugin->overlaps_size++] = new_grain;
+ }
+ }
+
+ if (randomness)
+ read_grain += 1 + rand() % randomness;
+ else
+ read_grain++;
+ }
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/masher",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/multiplexer.c b/src/multiplexer.c
new file mode 100644
index 0000000..151302d
--- /dev/null
+++ b/src/multiplexer.c
@@ -0,0 +1,120 @@
+/* Multiplxer plugin.
+ * Copyright 2005 Thorsten Wilms.
+ * Based on David Robillard's "Hz to AMS style V/Oct" plugin for the skeleton.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define MUX_GATE_ID 4420
+
+#define MUX_NUM_PORTS 4
+
+/* Port Numbers */
+#define MUX_GATE 0
+#define MUX_OFF 1
+#define MUX_ON 2
+#define MUX_OUTPUT 3
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* gate_buffer;
+ float* off_buffer;
+ float* on_buffer;
+ float* output_buffer;
+} MUX;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(MUX));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ MUX* plugin;
+
+ plugin = (MUX*)instance;
+ switch (port) {
+ case MUX_GATE:
+ plugin->gate_buffer = (float*)data;
+ break;
+ case MUX_OFF:
+ plugin->off_buffer = (float*)data;
+ break;
+ case MUX_ON:
+ plugin->on_buffer = (float*)data;
+ break;
+ case MUX_OUTPUT:
+ plugin->output_buffer = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ const MUX* const plugin = (MUX*)instance;
+ const float* const gate = plugin->gate_buffer;
+ const float* const off = plugin->off_buffer;
+ const float* const on = plugin->on_buffer;
+ float* const output = plugin->output_buffer;
+ unsigned long i;
+
+ for (i = 0; i < nframes; i++)
+ output[i] = (gate[i] <= 0) ? off[i] : on[i];
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/multiplexer",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/prob_switch.c b/src/prob_switch.c
new file mode 100644
index 0000000..ae5d508
--- /dev/null
+++ b/src/prob_switch.c
@@ -0,0 +1,130 @@
+/* This file is an audio plugin.
+ * Copyright 2005 Loki Davison.
+ *
+ * Probability parameter is the prob of input 1 being the output value.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define PROBSWITCH_BASE_ID 2667
+
+#define PROBSWITCH_NUM_PORTS 4
+
+/* Port Numbers */
+#define PROBSWITCH_INPUT1 0
+#define PROBSWITCH_INPUT2 1
+#define PROBSWITCH_PROB 2
+#define PROBSWITCH_OUTPUT 3
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* input2;
+ float* prob;
+ float* input1;
+ float* output;
+} ProbSwitch;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(ProbSwitch));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ ProbSwitch* plugin;
+
+ plugin = (ProbSwitch*)instance;
+ switch (port) {
+ case PROBSWITCH_INPUT2:
+ plugin->input2 = (float*)data;
+ break;
+ case PROBSWITCH_PROB:
+ plugin->prob = (float*)data;
+ break;
+ case PROBSWITCH_INPUT1:
+ plugin->input1 = (float*)data;
+ break;
+ case PROBSWITCH_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ ProbSwitch* plugin = (ProbSwitch*)instance;
+ float* input2 = plugin->input2;
+ float* prob = plugin->prob;
+ float* input1 = plugin->input1;
+ float* output = plugin->output;
+ size_t i;
+
+ for (i = 0; i < nframes; ++i)
+ {
+ if((rand()/RAND_MAX) <= prob[i])
+ {
+ output[i] = input1[i];
+ }
+ else
+ {
+ output[i] = input2[i];
+ }
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/prob_switch",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/range_trans.c b/src/range_trans.c
new file mode 100644
index 0000000..26b5272
--- /dev/null
+++ b/src/range_trans.c
@@ -0,0 +1,131 @@
+/* This file is an audio plugin. Copyright 2005-2011 David Robillard.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define RANGETRANS_BASE_ID 4210
+
+#define RANGETRANS_NUM_PORTS 6
+
+/* Port Numbers */
+#define RANGETRANS_IN_MIN 0
+#define RANGETRANS_IN_MAX 1
+#define RANGETRANS_OUT_MIN 2
+#define RANGETRANS_OUT_MAX 3
+#define RANGETRANS_INPUT 4
+#define RANGETRANS_OUTPUT 5
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* in_min;
+ float* in_max;
+ float* out_min;
+ float* out_max;
+ float* input;
+ float* output;
+} RangeTrans;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(RangeTrans));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ RangeTrans* plugin;
+
+ plugin = (RangeTrans*)instance;
+ switch (port) {
+ case RANGETRANS_IN_MIN:
+ plugin->in_min = (float*)data;
+ break;
+ case RANGETRANS_IN_MAX:
+ plugin->in_max = (float*)data;
+ break;
+ case RANGETRANS_OUT_MIN:
+ plugin->out_min = (float*)data;
+ break;
+ case RANGETRANS_OUT_MAX:
+ plugin->out_max = (float*)data;
+ break;
+ case RANGETRANS_INPUT:
+ plugin->input = (float*)data;
+ break;
+ case RANGETRANS_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ const RangeTrans* const plugin = (RangeTrans*)instance;
+ const float* const in_min = plugin->in_min;
+ const float* const in_max = plugin->in_max;
+ const float* const out_min = plugin->out_min;
+ const float* const out_max = plugin->out_max;
+ const float* const input = plugin->input;
+ float* const output = plugin->output;
+ unsigned long i;
+
+ for (i = 0; i < nframes; ++i)
+ output[i] = ((input[i] - in_min[i]) / (in_max[i] - in_min[i]))
+ * (out_max[i] - out_min[i]) + out_min[i];
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/range_trans",
+ instantiate,
+ connect_port,
+ NULL,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sample_and_hold.c b/src/sample_and_hold.c
new file mode 100644
index 0000000..6b0abeb
--- /dev/null
+++ b/src/sample_and_hold.c
@@ -0,0 +1,150 @@
+/* Sample and Hold.
+ * Copyright 2005 Thorsten Wilms.
+ * Based on David Robillard's "Hz to AMS style V/Oct" plugin for the skeleton.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define ID 4430
+
+#define NUM_PORTS 5
+
+/* Port Numbers */
+#define INPUT 0
+#define TRIGGER 1
+#define THRESHOLD 2
+#define CONTINUOUS 3
+#define OUTPUT 4
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* input_buffer;
+ float* trigger_buffer;
+ float* threshold_buffer;
+ float* continuous_buffer;
+ float* output_buffer;
+
+ float hold; /* the value sampled and held */
+ float last_trigger; /* trigger port value from the previous frame */
+} SH;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(SH));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ SH* plugin = (SH*)instance;
+
+ switch (port) {
+ case INPUT:
+ plugin->input_buffer = (float*)data;
+ break;
+ case TRIGGER:
+ plugin->trigger_buffer = (float*)data;
+ break;
+ case THRESHOLD:
+ plugin->threshold_buffer = (float*)data;
+ break;
+ case CONTINUOUS:
+ plugin->continuous_buffer = (float*)data;
+ break;
+ case OUTPUT:
+ plugin->output_buffer = (float*)data;
+ break;
+ }
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ SH* plugin = (SH*)instance;
+
+ plugin->hold = 0;
+ plugin->last_trigger = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ SH* const plugin = (SH*)instance;
+ const float* const input = plugin->input_buffer;
+ const float* const trigger = plugin->trigger_buffer;
+ const float* const threshold = plugin->threshold_buffer;
+ const float* const continuous = plugin->continuous_buffer;
+ float* const output = plugin->output_buffer;
+
+ unsigned long i;
+
+ for (i = 0; i < nframes; i++) {
+ if (continuous[0] != 0) {
+ /* Continuous triggering on (sample while trigger > threshold) */
+ if (trigger[i] >= threshold[i])
+ plugin->hold = input[i];
+ } else {
+ /* Continuous triggering off
+ * (only sample on first frame with trigger > threshold) */
+ if (plugin->last_trigger < threshold[i] && trigger[i] >= threshold[i])
+ plugin->hold = input[i];
+ }
+
+ plugin->last_trigger = trigger[i];
+ output[i] = plugin->hold;
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/sample_and_hold",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/signal_abs.c b/src/signal_abs.c
new file mode 100644
index 0000000..90ad59c
--- /dev/null
+++ b/src/signal_abs.c
@@ -0,0 +1,124 @@
+/* Absolute value audio plugin.
+ * Copyright 2005 Loki Davison.
+ *
+ * Sign parameter is the sign of the output, 0 being negative and >0 begin positive.
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define SIGNAL_ABS_BASE_ID 2669
+
+#define SIGNAL_ABS_NUM_PORTS 3
+
+/* Port Numbers */
+#define SIGNAL_ABS_INPUT1 0
+#define SIGNAL_ABS_SIGN 1
+#define SIGNAL_ABS_OUTPUT 2
+
+/* All state information for plugin */
+typedef struct
+{
+ /* Ports */
+ float* sign;
+ float* input1;
+ float* output;
+} SignalAbs;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ return (LV2_Handle)malloc(sizeof(SignalAbs));
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ SignalAbs* plugin;
+
+ plugin = (SignalAbs*)instance;
+ switch (port) {
+ case SIGNAL_ABS_SIGN:
+ plugin->sign = (float*)data;
+ break;
+ case SIGNAL_ABS_INPUT1:
+ plugin->input1 = (float*)data;
+ break;
+ case SIGNAL_ABS_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+static void
+run_ar(LV2_Handle instance, uint32_t nframes)
+{
+ SignalAbs* plugin = (SignalAbs*)instance;
+ float* sign = plugin->sign;
+ float* input1 = plugin->input1;
+ float* output = plugin->output;
+ size_t i;
+
+ for (i = 0; i < nframes; ++i)
+ {
+ if(sign[i] > 0.5)
+ {
+ output[i] = fabs(input1[i]);
+ }
+ else
+ {
+ output[i] = fabs(input1[i]) * -1;
+ }
+ }
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/signal_abs",
+ instantiate,
+ connect_port,
+ NULL,
+ run_ar,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/slew_limiter.c b/src/slew_limiter.c
new file mode 100644
index 0000000..7fe0ee5
--- /dev/null
+++ b/src/slew_limiter.c
@@ -0,0 +1,149 @@
+/* slew_limiter - A LV2 plugin that limits the rate of change of a
+ * signal. Increases and decreases in the signal can be
+ * limited separately.
+ *
+ * Copyright 2005 Lars Luthman
+ * LV2 skeleton code taken from dahdsr_fexp.c by Loki Davison
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <math.h>
+
+/* These are the port numbers */
+#define SLIM_INPUT 0
+#define SLIM_MAXRISE 1
+#define SLIM_MAXFALL 2
+#define SLIM_OUTPUT 3
+
+/* This is an array pointer to the descriptors of the different variants */
+LV2_Descriptor** slim_descriptors = 0;
+
+/* This is the data for a single instance of the plugin */
+typedef struct
+{
+ float* input;
+ float* maxrise;
+ float* maxfall;
+ float* reset;
+ float* output;
+ float srate;
+ float last_output;
+}
+SLim;
+
+/* Clean up after a plugin instance */
+static void cleanup (LV2_Handle instance)
+{
+ free(instance);
+}
+
+/* This is called when the hosts connects a port to a buffer */
+static void connect_port(LV2_Handle instance,
+ uint32_t port, void* data)
+{
+ SLim* plugin = (SLim *)instance;
+
+ switch (port) {
+ case SLIM_INPUT:
+ plugin->input = (float*)data;
+ break;
+ case SLIM_MAXRISE:
+ plugin->maxrise = (float*)data;
+ break;
+ case SLIM_MAXFALL:
+ plugin->maxfall = (float*)data;
+ break;
+ case SLIM_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+/* The host uses this function to create an instance of a plugin */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ SLim* plugin = (SLim*)calloc(1, sizeof(SLim));
+ plugin->srate = (float)sample_rate;
+ return (LV2_Handle)plugin;
+}
+
+/* This is called before the hosts starts to use the plugin instance */
+static void activate(LV2_Handle instance)
+{
+ SLim* plugin = (SLim*)instance;
+ plugin->last_output = 0;
+}
+
+/* The run function! */
+static void run(LV2_Handle instance, uint32_t sample_count)
+{
+ SLim* plugin = (SLim*)instance;
+
+ if (plugin->input && plugin->output) {
+ unsigned long i;
+ float maxrise, maxfall;
+ for (i = 0; i < sample_count; ++i) {
+
+ if (plugin->maxrise)
+ maxrise = plugin->maxrise[i];
+ else
+ maxrise = 0;
+
+ if (plugin->maxfall)
+ maxfall = plugin->maxfall[i];
+ else
+ maxfall = 0;
+
+ float maxinc = maxrise / plugin->srate;
+ float maxdec = maxfall / plugin->srate;
+ float increment = plugin->input[i] - plugin->last_output;
+ if (increment > maxinc)
+ increment = maxinc;
+ else if (increment < -maxdec)
+ increment = -maxdec;
+
+ plugin->output[i] = plugin->last_output + increment;
+ plugin->last_output = plugin->output[i];
+ }
+ }
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/slew_limiter",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/slide.c b/src/slide.c
new file mode 100644
index 0000000..fe026f7
--- /dev/null
+++ b/src/slide.c
@@ -0,0 +1,170 @@
+/* slide.c - A LV2 plugin that "slides" the output signal between
+ * the current and the previous input value, taking the given
+ * number of seconds to reach the current input value.
+ *
+ * Copyright 2005 Lars Luthman
+ * LV2 skeleton code taken from dahdsr_fexp.c by Loki Davison
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <math.h>
+
+/* These are the port numbers */
+#define SLIDE_INPUT 0
+#define SLIDE_RISETIME 1
+#define SLIDE_FALLTIME 2
+#define SLIDE_OUTPUT 3
+
+/* This is the data for a single instance of the plugin */
+typedef struct
+{
+ float* input;
+ float* risetime;
+ float* falltime;
+ float* output;
+ float srate;
+ float from;
+ float to;
+ float last_output;
+} Slide;
+
+/* Clean up after a plugin instance */
+static void cleanup (LV2_Handle instance)
+{
+ free(instance);
+}
+
+/* This is called when the hosts connects a port to a buffer */
+static void connect_port(LV2_Handle instance,
+ uint32_t port, void* data)
+{
+ Slide* plugin = (Slide *)instance;
+
+ switch (port) {
+ case SLIDE_INPUT:
+ plugin->input = (float*)data;
+ break;
+ case SLIDE_RISETIME:
+ plugin->risetime = (float*)data;
+ break;
+ case SLIDE_FALLTIME:
+ plugin->falltime = (float*)data;
+ break;
+ case SLIDE_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ }
+}
+
+/* The host uses this function to create an instance of a plugin */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Slide* plugin = (Slide*)calloc(1, sizeof(Slide));
+ plugin->srate = (float)sample_rate;
+ return (LV2_Handle)plugin;
+}
+
+/* This is called before the hosts starts to use the plugin instance */
+static void activate(LV2_Handle instance)
+{
+ Slide* plugin = (Slide*)instance;
+ plugin->last_output = 0;
+ plugin->from = 0;
+ plugin->to = 0;
+}
+
+/* The run function! */
+static void run(LV2_Handle instance, uint32_t sample_count)
+{
+ Slide* plugin = (Slide*)instance;
+
+ if (plugin->input && plugin->output) {
+ unsigned long i;
+ float risetime, falltime;
+ for (i = 0; i < sample_count; ++i) {
+
+ if (plugin->risetime)
+ risetime = plugin->risetime[i];
+ else
+ risetime = 0;
+
+ if (plugin->falltime)
+ falltime = plugin->falltime[i];
+ else
+ falltime = 0;
+
+ /* If the signal changed, start sliding to the new value */
+ if (plugin->input[i] != plugin->to) {
+ plugin->from = plugin->last_output;
+ plugin->to = plugin->input[i];
+ }
+
+ float time;
+ int rising;
+ if (plugin->to > plugin->from) {
+ time = risetime;
+ rising = 1;
+ } else {
+ time = falltime;
+ rising = 0;
+ }
+
+ /* If the rise/fall time is 0, just copy the input to the output */
+ if (time == 0)
+ plugin->output[i] = plugin->input[i];
+
+ /* Otherwise, do the portamento */
+ else {
+ float increment =
+ (plugin->to - plugin->from) / (time * plugin->srate);
+ plugin->output[i] = plugin->last_output + increment;
+ if ((plugin->output[i] > plugin->to && rising) ||
+ (plugin->output[i] < plugin->to && !rising)) {
+ plugin->output[i] = plugin->to;
+ }
+ }
+
+ plugin->last_output = plugin->output[i];
+ }
+ }
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/slide",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/waveguide_mesh.c b/src/waveguide_mesh.c
new file mode 100644
index 0000000..5232ff5
--- /dev/null
+++ b/src/waveguide_mesh.c
@@ -0,0 +1,274 @@
+/* This file is an audio plugin.
+ * Copyright 2005 Loki Davison.
+ *
+ * Based on code by Brook Eaton and a couple of papers...
+ *
+ * Implements a Waveguide Mesh drum. FIXME to be extended, to have rimguides, power normalisation and all
+ * manner of other goodies.
+ *
+ * Tension is well, drum tension
+ * power is how hard you hit it.
+ *
+ *
+ * This plugin 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This plugin 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _XOPEN_SOURCE 600 /* strdup */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+
+#define MESH_BASE_ID 2670
+
+#define MESH_NUM_PORTS 6
+
+/* Port Numbers */
+#define MESH_INPUT1 0
+#define MESH_OUTPUT 1
+#define MESH_TENSION 2
+#define MESH_POWER 3
+#define MESH_EX_X 4
+#define MESH_EX_Y 5
+
+#define LENGTH 8 // must be divisible by 4!!
+#define WIDTH 8
+#define SIZE LENGTH*WIDTH // Size of mesh
+#define INITIAL 0 // initial values stored at junctions
+#define LOSS 0.2 // loss in wave propagation
+#define INIT_DELTA 6 // initial values
+#define INIT_T 0.1 // for the impedances
+#define INIT_GAMMA 8 //
+#define PORTS 8 //for the initialization of junction velocities from excitation
+
+// 2D array of junctions.
+// The important function of the junction is to store
+// the velocities of travelling waves so that adjacent junction's
+// velocities can be calculated.
+typedef struct _junction
+{
+ float v_junction; // junction velocity
+ float n_junction; // velocity heading north into junction
+ float s_junction; // velocity heading south into junction
+ float e_junction; // velocity heading east into junction
+ float w_junction; // velocity heading west into junction
+ float c_junction; // velocity heading back into the junction (delayed)
+ float s_temp; // these two 'temp' values are used because calculation
+ float e_temp; // of the mesh updates s/e values before they are used
+} _junction; // to calculate north and south velocities!
+
+/* All state information for plugin */
+
+typedef struct
+{
+ /* Ports */
+ float* input1;
+ float* output;
+ float* tension;
+ float* power;
+ float* ex_x;
+ float* ex_y;
+
+ /* vars */
+ _junction mesh[LENGTH][WIDTH];
+ float last_trigger;
+
+} WgMesh;
+
+/* Construct a new plugin instance */
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ WgMesh * plugin = (WgMesh *) malloc (sizeof (WgMesh));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ WgMesh * plugin = (WgMesh *) instance;
+ for (int i=0; i<LENGTH; i++) {
+ for (int j=0; j<WIDTH; j++) {
+ plugin->mesh[i][j].v_junction = INITIAL;
+ plugin->mesh[i][j].n_junction = INITIAL;
+ plugin->mesh[i][j].s_junction = INITIAL;
+ plugin->mesh[i][j].e_junction = INITIAL;
+ plugin->mesh[i][j].w_junction = INITIAL;
+ plugin->mesh[i][j].c_junction = INITIAL;
+ plugin->mesh[i][j].s_temp = INITIAL;
+ plugin->mesh[i][j].e_temp = INITIAL;
+ }
+ }
+ plugin->last_trigger = 0.0;
+}
+
+/* Connect a port to a data location */
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ WgMesh* plugin;
+
+ plugin = (WgMesh*)instance;
+ switch (port) {
+ case MESH_INPUT1:
+ plugin->input1 = (float*)data;
+ break;
+ case MESH_OUTPUT:
+ plugin->output = (float*)data;
+ break;
+ case MESH_TENSION:
+ plugin->tension = (float*)data;
+ break;
+ case MESH_POWER:
+ plugin->power = (float*)data;
+ break;
+ case MESH_EX_X:
+ plugin->ex_x = (float*)data;
+ break;
+ case MESH_EX_Y:
+ plugin->ex_y = (float*)data;
+ break;
+ }
+}
+
+inline static void excite_mesh(WgMesh* plugin, float power, float ex_x, float ex_y)
+{
+ int i=ex_x,j=ex_y;
+ float temp;
+ float Yj;
+
+ Yj = 2*(INIT_DELTA*INIT_DELTA/((INIT_T*INIT_T)*(INIT_GAMMA*INIT_GAMMA))); // junction admittance
+ temp = power*2/(LENGTH+WIDTH);
+ plugin->mesh[i][j].v_junction = plugin->mesh[i][j].v_junction + temp;
+ plugin->mesh[i][j].n_junction = plugin->mesh[i][j].n_junction + Yj*temp/PORTS;
+ // All velocities leaving the junction are equal to
+ plugin->mesh[i][j].s_junction = plugin->mesh[i][j].s_junction + Yj*temp/PORTS;
+ // the total velocity in the junction * the admittance
+ plugin->mesh[i][j].e_junction = plugin->mesh[i][j].e_junction + Yj*temp/PORTS;
+ // divided by the number of outgoing ports.
+ plugin->mesh[i][j].w_junction = plugin->mesh[i][j].w_junction + Yj*temp/PORTS;
+ //mesh[i][j].c_junction = 0;
+}
+
+static void
+run(LV2_Handle instance, uint32_t nframes)
+{
+ WgMesh* plugin = (WgMesh*)instance;
+ float tension = *(plugin->tension);
+ float ex_x = *(plugin->ex_x);
+ float ex_y = *(plugin->ex_y);
+ float* input = plugin->input1;
+ float* out = plugin->output;
+ float* power = plugin->power;
+ float last_trigger = plugin->last_trigger;
+ size_t i,j,k;
+ float filt, trg, oldfilt;
+ float Yc,Yj,tempN,tempS,tempE,tempW;
+
+ // Set input variables //
+ oldfilt = plugin->mesh[LENGTH-LENGTH/4][WIDTH-WIDTH/4].v_junction;
+
+ for (k=0; k<nframes; k++) {
+ if (tension==0)
+ tension=0.0001;
+ trg = input[k];
+
+ if (trg > 0.0f && !(last_trigger > 0.0f))
+ {
+ //printf("got trigger, exciting mesh, %f \n", tension);
+ excite_mesh(plugin, power[k], ex_x, ex_y);
+ }
+
+ //junction admitance
+ Yj = 2*INIT_DELTA*INIT_DELTA/(( (tension)*((tension) )*(INIT_GAMMA*INIT_GAMMA)));
+ Yc = Yj-4; // junction admittance (left shift is for multiply by 2!)
+ //plugin->v_power = power[k];
+
+ for (i=1; i<LENGTH-1; i++) {
+ // INNER MESH //
+ for (j=1; j<WIDTH-1; j++) { // to multiply by 2 - simply shift to the left by 1!
+ plugin->mesh[i][j].v_junction = 2.0*(plugin->mesh[i][j].n_junction + plugin->mesh[i][j].s_junction
+ + plugin->mesh[i][j].e_junction + plugin->mesh[i][j].w_junction + Yc*plugin->mesh[i][j].c_junction)/Yj;
+
+ plugin->mesh[i][j+1].s_junction = plugin->mesh[i][j].v_junction - plugin->mesh[i][j].n_junction;
+ plugin->mesh[i][j-1].n_junction = plugin->mesh[i][j].v_junction - plugin->mesh[i][j].s_temp;
+
+ plugin->mesh[i+1][j].e_junction = plugin->mesh[i][j].v_junction - plugin->mesh[i][j].w_junction;
+ plugin->mesh[i-1][j].w_junction = plugin->mesh[i][j].v_junction - plugin->mesh[i][j].e_temp;
+
+ plugin->mesh[i][j].c_junction = plugin->mesh[i][j].v_junction - plugin->mesh[i][j].c_junction;
+
+ plugin->mesh[i][j].s_temp = plugin->mesh[i][j].s_junction; //
+ plugin->mesh[i][j].e_temp = plugin->mesh[i][j].e_junction; // update current values in the temp slots!
+ }
+ // BOUNDARY //
+ tempS = plugin->mesh[i][0].s_junction;
+ plugin->mesh[i][0].s_junction = -plugin->mesh[i][0].n_junction;
+ plugin->mesh[i][1].s_junction = plugin->mesh[i][1].s_temp = tempS;
+ tempN = plugin->mesh[i][WIDTH-1].n_junction;
+ plugin->mesh[i][WIDTH-1].n_junction = -plugin->mesh[i][WIDTH-1].s_junction;
+ plugin->mesh[i][WIDTH-2].n_junction = tempN;
+ // 'i's in the neplugint few lines are really 'j's!
+ tempE = plugin->mesh[0][i].e_junction;
+ plugin->mesh[0][i].e_junction = -plugin->mesh[0][i].w_junction;
+ plugin->mesh[1][i].e_junction = plugin->mesh[1][i].e_temp = tempE;
+ tempW = plugin->mesh[WIDTH-1][i].w_junction;
+ plugin->mesh[WIDTH-1][i].w_junction = -plugin->mesh[WIDTH-1][i].e_junction;
+ plugin->mesh[WIDTH-2][i].w_junction = tempW;
+ }
+
+ filt = LOSS*(plugin->mesh[LENGTH-LENGTH/4][WIDTH-WIDTH/4].v_junction + oldfilt);
+ oldfilt = plugin->mesh[LENGTH-LENGTH/4][WIDTH-WIDTH/4].v_junction;
+ plugin->mesh[LENGTH-LENGTH/4][WIDTH-WIDTH/4].v_junction = filt;
+
+ out[k] = plugin->mesh[WIDTH/4][WIDTH/4-1].v_junction;
+ last_trigger = trg;
+ }
+ plugin->last_trigger = last_trigger;
+
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/omins/waveguide_mesh",
+ instantiate,
+ connect_port,
+ activate,
+ run,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}