diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/adenv.c | 250 | ||||
-rw-r--r-- | src/adenv_lvl.c | 299 | ||||
-rw-r--r-- | src/comparison.c | 135 | ||||
-rw-r--r-- | src/dahdsr_fexp.c | 342 | ||||
-rw-r--r-- | src/dahdsr_hexp.c | 344 | ||||
-rw-r--r-- | src/fast_crossfade.c | 139 | ||||
-rw-r--r-- | src/formant_filter.c | 213 | ||||
-rw-r--r-- | src/hz_voct.c | 117 | ||||
-rw-r--r-- | src/masher.c | 244 | ||||
-rw-r--r-- | src/multiplexer.c | 120 | ||||
-rw-r--r-- | src/prob_switch.c | 130 | ||||
-rw-r--r-- | src/range_trans.c | 131 | ||||
-rw-r--r-- | src/sample_and_hold.c | 150 | ||||
-rw-r--r-- | src/signal_abs.c | 124 | ||||
-rw-r--r-- | src/slew_limiter.c | 149 | ||||
-rw-r--r-- | src/slide.c | 170 | ||||
-rw-r--r-- | src/waveguide_mesh.c | 274 |
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; + } +} |