From 7b20413c84b14d2c2bc1037bb08134dcdf152ddb Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 31 May 2012 06:23:57 +0000 Subject: Umm... commit pretty much all the work of the past few days. Again. git-svn-id: http://svn.drobilla.net/lad/trunk/plugins/blop.lv2@4488 a436a847-0d15-0410-975c-d299462d15a1 --- src/adsr.c | 11 +- src/adsr_gt.c | 14 +- src/amp.c | 77 +++++--- src/branch.c | 2 +- src/dahdsr.c | 450 +++++++++---------------------------------- src/difference.c | 169 +++++++++------- src/fmod.c | 164 ++++++++-------- src/include/common.h | 6 +- src/include/interpolate.h | 8 +- src/include/lp4pole_filter.h | 6 +- src/include/math_func.h | 2 +- src/include/wavedata.h | 14 +- src/include/wdatutil.h | 6 +- src/interpolator.c | 11 +- src/lp4pole.c | 97 ++++++---- src/product.c | 126 +++++++----- src/pulse.c | 208 +++++++------------- src/quantiser.c | 66 +++---- src/random.c | 253 +++++++----------------- src/ratio.c | 150 ++++++++------- src/sawtooth.c | 81 ++++---- src/sequencer.c | 29 ++- src/square.c | 79 ++++---- src/sum.c | 121 ++++++++---- src/sync_pulse.c | 118 ++++++------ src/sync_square.c | 111 ++++++----- src/tracker.c | 158 +++++++-------- src/triangle.c | 234 +++++++--------------- src/wavedata.c | 4 +- src/wdatutil.c | 14 +- 30 files changed, 1192 insertions(+), 1597 deletions(-) diff --git a/src/adsr.c b/src/adsr.c index 227dca7..c50951d 100644 --- a/src/adsr.c +++ b/src/adsr.c @@ -98,6 +98,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Adsr* plugin = (Adsr*)malloc(sizeof(Adsr)); + if (!plugin) { + return NULL; + } plugin->srate = (float)sample_rate; plugin->inv_srate = 1.0f / plugin->srate; @@ -117,8 +120,8 @@ activate(LV2_Handle instance) } static void -runAdsr(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Adsr* plugin = (Adsr*)instance; @@ -236,11 +239,11 @@ runAdsr(LV2_Handle instance, } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/adsr", + "http://drobilla.net/plugins/blop/adsr", instantiate, connect_port, activate, - runAdsr, + run, NULL, cleanup, NULL, diff --git a/src/adsr_gt.c b/src/adsr_gt.c index 77bec65..de0b0e7 100644 --- a/src/adsr_gt.c +++ b/src/adsr_gt.c @@ -100,8 +100,10 @@ instantiate(const LV2_Descriptor* descriptor, { Adsr* plugin = (Adsr*)malloc(sizeof(Adsr)); - plugin->srate = (float)sample_rate; - plugin->inv_srate = 1.0f / plugin->srate; + if (plugin) { + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + } return (LV2_Handle)plugin; } @@ -119,8 +121,8 @@ activate(LV2_Handle instance) } static void -runAdsr(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Adsr* plugin = (Adsr*)instance; @@ -244,11 +246,11 @@ runAdsr(LV2_Handle instance, } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/adsr_gt", + "http://drobilla.net/plugins/blop/adsr_gt", instantiate, connect_port, activate, - runAdsr, + run, NULL, cleanup, NULL, diff --git a/src/amp.c b/src/amp.c index edb9291..dac6bb0 100644 --- a/src/amp.c +++ b/src/amp.c @@ -18,8 +18,10 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "math_func.h" +#include "uris.h" #define AMP_GAIN 0 #define AMP_INPUT 1 @@ -29,6 +31,8 @@ typedef struct { const float* gain; const float* input; float* output; + URIs uris; + uint32_t gain_is_cv; } Amp; static void @@ -57,6 +61,28 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Amp* plugin = (Amp*)instance; + switch (port) { + case AMP_GAIN: + if (type == plugin->uris.lv2_ControlPort) { + plugin->gain_is_cv = 0; + } else if (type == plugin->uris.lv2_CVPort) { + plugin->gain_is_cv = 1; + } else { + return LV2_MORPH_ERR_BAD_TYPE; + } + return LV2_MORPH_SUCCESS; + default: + return LV2_MORPH_ERR_BAD_PORT; + } +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -64,13 +90,19 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Amp* plugin = (Amp*)malloc(sizeof(Amp)); + if (!plugin) { + return NULL; + } + + plugin->gain_is_cv = 0; + map_uris(&plugin->uris, features); return (LV2_Handle)plugin; } static void -runAmp_gaia_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Amp* plugin = (Amp*)instance; @@ -83,50 +115,33 @@ runAmp_gaia_oa(LV2_Handle instance, /* Output */ float* output = plugin->output; - float gn; - float in; - float scale; - for (uint32_t s = 0; s < sample_count; ++s) { - gn = gain[s]; - in = input[s]; + const float gn = gain[s * plugin->gain_is_cv]; + const float scale = (float)EXPF(M_LN10 * gn * 0.05f); - scale = (float)EXPF(M_LN10 * gn * 0.05f); - - output[s] = scale * in; + output[s] = scale * input[s]; } } -static void -runAmp_gcia_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Amp* plugin = (Amp*)instance; - - /* Gain (dB) */ - const float gain = *(plugin->gain); - - /* Input */ - const float* input = plugin->input; - - /* Output */ - float* output = plugin->output; - - const float scale = (float)EXPF(M_LN10 * gain * 0.05f); - for (uint32_t s = 0; s < sample_count; s++) { - output[s] = scale * input[s]; + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/amp", + "http://drobilla.net/plugins/blop/amp", instantiate, connect_port, NULL, - runAmp_gcia_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/branch.c b/src/branch.c index 4625e5c..f4c92a0 100644 --- a/src/branch.c +++ b/src/branch.c @@ -113,7 +113,7 @@ runBranch_ic_ococ(LV2_Handle instance, } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/branch", + "http://drobilla.net/plugins/blop/branch", instantiate, connect_port, NULL, diff --git a/src/dahdsr.c b/src/dahdsr.c index cfddb6b..97cd373 100644 --- a/src/dahdsr.c +++ b/src/dahdsr.c @@ -18,8 +18,10 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "common.h" +#include "uris.h" #define DAHDSR_GATE 0 #define DAHDSR_TRIGGER 1 @@ -57,8 +59,15 @@ typedef struct { float last_trigger; float from_level; float level; + uint32_t delay_is_cv; + uint32_t attack_is_cv; + uint32_t hold_is_cv; + uint32_t decay_is_cv; + uint32_t sustain_is_cv; + uint32_t release_is_cv; DAHDSRState state; uint32_t samples; + URIs uris; } Dahdsr; static void @@ -105,6 +114,45 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Dahdsr* plugin = (Dahdsr*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case DAHDSR_DELAY: + plugin->delay_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_ATTACK: + plugin->attack_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_HOLD: + plugin->hold_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_DECAY: + plugin->decay_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_SUSTAIN: + plugin->sustain_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_RELEASE: + plugin->release_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -112,10 +160,22 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Dahdsr* plugin = (Dahdsr*)malloc(sizeof(Dahdsr)); + if (!plugin) { + return NULL; + } plugin->srate = (float)sample_rate; plugin->inv_srate = 1.0f / plugin->srate; + plugin->delay_is_cv = 0; + plugin->attack_is_cv = 0; + plugin->hold_is_cv = 0; + plugin->decay_is_cv = 0; + plugin->sustain_is_cv = 0; + plugin->release_is_cv = 0; + + map_uris(&plugin->uris, features); + return (LV2_Handle)plugin; } @@ -133,8 +193,8 @@ activate(LV2_Handle instance) } static void -runDahdsr_Audio(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Dahdsr* plugin = (Dahdsr*)instance; @@ -175,20 +235,26 @@ runDahdsr_Audio(LV2_Handle instance, DAHDSRState state = plugin->state; uint32_t samples = plugin->samples; - float gat, trg, del, att, hld, dec, sus, rel; float elapsed; for (uint32_t s = 0; s < sample_count; ++s) { + const float dl = delay[s * plugin->delay_is_cv]; + const float at = attack[s * plugin->attack_is_cv]; + const float hl = hold[s * plugin->hold_is_cv]; + const float dc = decay[s * plugin->decay_is_cv]; + const float st = sustain[s * plugin->sustain_is_cv]; + const float rl = release[s * plugin->release_is_cv]; + /* Convert times into rates */ - del = delay[s] > 0.0f ? inv_srate / delay[s] : srate; - att = attack[s] > 0.0f ? inv_srate / attack[s] : srate; - hld = hold[s] > 0.0f ? inv_srate / hold[s] : srate; - dec = decay[s] > 0.0f ? inv_srate / decay[s] : srate; - rel = release[s] > 0.0f ? inv_srate / release[s] : srate; + const float del = dl > 0.0f ? inv_srate / dl : srate; + const float att = at > 0.0f ? inv_srate / at : srate; + const float hld = hl > 0.0f ? inv_srate / hl : srate; + const float dec = dc > 0.0f ? inv_srate / dc : srate; + const float rel = rl > 0.0f ? inv_srate / rl : srate; - gat = gate[s]; - trg = trigger[s]; - sus = f_clip(sustain[s], 0.0f, 1.0f); + const float gat = gate[s]; + const float trg = trigger[s]; + const float sus = f_clip(st, 0.0f, 1.0f); /* Initialise delay phase if gate is opened and was closed, or we received a trigger */ @@ -310,369 +376,25 @@ runDahdsr_Audio(LV2_Handle instance, plugin->samples = samples; } -static void -runDahdsr_Control(LV2_Handle instance, - uint32_t sample_count) -{ - Dahdsr* plugin = (Dahdsr*)instance; - - /* Gate */ - const float* gate = plugin->gate; - - /* Trigger */ - const float* trigger = plugin->trigger; - - /* Delay Time (s) */ - const float delay = *(plugin->delay); - - /* Attack Time (s) */ - const float attack = *(plugin->attack); - - /* Hold Time (s) */ - const float hold = *(plugin->hold); - - /* Decay Time (s) */ - const float decay = *(plugin->decay); - - /* Sustain Level */ - const float sustain = *(plugin->sustain); - - /* Release Time (s) */ - const 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; - uint32_t samples = plugin->samples; - - float gat, trg, del, att, hld, dec, sus, rel; - float elapsed; - - /* 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 = f_clip(sustain, 0.0f, 1.0f); - - for (uint32_t 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 = from_level + elapsed * (sus - from_level); - } - 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 = from_level - elapsed * from_level; - } - 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 void -runDahdsr_CGT_Control(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Dahdsr* plugin = (Dahdsr*)instance; - - /* Gate */ - const float gate = *(plugin->gate); - - /* Trigger */ - const float trigger = *(plugin->trigger); - - /* Delay Time (s) */ - const float delay = *(plugin->delay); - - /* Attack Time (s) */ - const float attack = *(plugin->attack); - - /* Hold Time (s) */ - const float hold = *(plugin->hold); - - /* Decay Time (s) */ - const float decay = *(plugin->decay); - - /* Sustain Level */ - const float sustain = *(plugin->sustain); - - /* Release Time (s) */ - const 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; - uint32_t samples = plugin->samples; - - float gat, trg, del, att, hld, dec, sus, rel; - float elapsed; - - /* 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; - - gat = gate; - trg = trigger; - sus = f_clip(sustain, 0.0f, 1.0f); - - /* 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; - } - - for (uint32_t s = 0; s < sample_count; ++s) { - 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 = from_level + elapsed * (sus - from_level); - } - 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 = from_level - elapsed * from_level; - } - break; - default: - /* Should never happen */ - level = 0.0f; - } - - output[s] = level; + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - - plugin->last_gate = gat; - plugin->last_trigger = trg; - plugin->from_level = from_level; - plugin->level = level; - plugin->state = state; - plugin->samples = samples; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/dahdsr", + "http://drobilla.net/plugins/blop/dahdsr", instantiate, connect_port, activate, - runDahdsr_Control, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/difference.c b/src/difference.c index bee9552..92e9a26 100644 --- a/src/difference.c +++ b/src/difference.c @@ -18,16 +18,22 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" -#define DIFFERENCE_INPUT 0 -#define DIFFERENCE_MINUS 1 -#define DIFFERENCE_OUTPUT 2 +#define DIFFERENCE_MINUEND 0 +#define DIFFERENCE_SUBTRAHEND 1 +#define DIFFERENCE_DIFFERENCE 2 typedef struct { - float* input; - float* minus; - float* output; + float* minuend; + float* subtrahend; + float* difference; + uint32_t minuend_is_cv; + uint32_t subtrahend_is_cv; + uint32_t difference_is_cv; + URIs uris; } Difference; static void @@ -44,116 +50,131 @@ connect_port(LV2_Handle instance, Difference* plugin = (Difference*)instance; switch (port) { - case DIFFERENCE_INPUT: - plugin->input = data; + case DIFFERENCE_MINUEND: + plugin->minuend = data; break; - case DIFFERENCE_MINUS: - plugin->minus = data; + case DIFFERENCE_SUBTRAHEND: + plugin->subtrahend = data; break; - case DIFFERENCE_OUTPUT: - plugin->output = data; + case DIFFERENCE_DIFFERENCE: + plugin->difference = data; break; } } -static LV2_Handle -instantiate(const LV2_Descriptor* descriptor, - double sample_rate, - const char* bundle_path, - const LV2_Feature* const* features) -{ - Difference* plugin = (Difference*)malloc(sizeof(Difference)); - - return (LV2_Handle)plugin; -} - -static void -runDifference_iama_oa(LV2_Handle instance, - uint32_t sample_count) +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) { Difference* plugin = (Difference*)instance; - /* Input (array of floats of length sample_count) */ - const float* input = plugin->input; + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } - /* Input to Subtract (array of floats of length sample_count) */ - const float* minus = plugin->minus; + switch (port) { + case DIFFERENCE_MINUEND: + plugin->minuend_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case DIFFERENCE_SUBTRAHEND: + plugin->subtrahend_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; + plugin->difference_is_cv = (plugin->minuend_is_cv || + plugin->subtrahend_is_cv); - for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input[s] - minus[s]; - } + return LV2_MORPH_SUCCESS; } -static void -runDifference_iamc_oa(LV2_Handle instance, - uint32_t sample_count) +static LV2_URID +port_type(LV2_Handle instance, + uint32_t port, + LV2_Morph_Property*const* properties) { Difference* plugin = (Difference*)instance; - /* Input (array of floats of length sample_count) */ - const float* input = plugin->input; + switch (port) { + case DIFFERENCE_DIFFERENCE: + return (plugin->difference_is_cv + ? plugin->uris.lv2_CVPort + : plugin->uris.lv2_ControlPort); + default: + return 0; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Difference* plugin = (Difference*)malloc(sizeof(Difference)); + if (!plugin) { + return NULL; + } - /* Input to Subtract (float value) */ - const float minus = *(plugin->minus); + plugin->minuend_is_cv = 0; + plugin->subtrahend_is_cv = 0; + plugin->difference_is_cv = 0; - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; + map_uris(&plugin->uris, features); - for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input[s] - minus; - } + return (LV2_Handle)plugin; } static void -runDifference_icma_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Difference* plugin = (Difference*)instance; - /* Input (float value) */ - const float input = *(plugin->input); + /* Minuend (array of floats of length 1 or sample_count) */ + const float* minuend = plugin->minuend; - /* Input to Subtract (array of floats of length sample_count) */ - const float* minus = plugin->minus; + /* Subtrahend (array of floats of length 1 or sample_count) */ + const float* subtrahend = plugin->subtrahend; - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; + /* Difference (array of floats of length 1 or sample_count) */ + float* difference = plugin->difference; + + if (!plugin->difference_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; + } for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input - minus[s]; + const float min = minuend[s * plugin->minuend_is_cv]; + const float sub = subtrahend[s * plugin->subtrahend_is_cv]; + + difference[s] = min - sub; } } -static void -runDifference_icmc_oc(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Difference* plugin = (Difference*)instance; - - /* Input (float value) */ - const float input = *(plugin->input); - - /* Input to Subtract (float value) */ - const float minus = *(plugin->minus); - - /* Output Frequency (pointer to float value) */ - float* output = plugin->output; - - output[0] = input - minus; + static const LV2_Morph_Interface morph = { morph_port, port_type }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; + } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/difference", + "http://drobilla.net/plugins/blop/difference", instantiate, connect_port, NULL, - runDifference_icmc_oc, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/fmod.c b/src/fmod.c index ee14a87..d566418 100644 --- a/src/fmod.c +++ b/src/fmod.c @@ -18,17 +18,23 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "math_func.h" +#include "uris.h" #define FMOD_FREQUENCY 0 #define FMOD_MODULATOR 1 #define FMOD_OUTPUT 2 typedef struct { - float* frequency; - float* modulator; - float* output; + float* frequency; + float* modulator; + float* output; + uint32_t frequency_is_cv; + uint32_t modulator_is_cv; + uint32_t output_is_cv; + URIs uris; } Fmod; static void @@ -57,129 +63,113 @@ connect_port(LV2_Handle instance, } } -static LV2_Handle -instantiate(const LV2_Descriptor* descriptor, - double sample_rate, - const char* bundle_path, - const LV2_Feature* const* features) -{ - Fmod* plugin = (Fmod*)malloc(sizeof(Fmod)); - - return (LV2_Handle)plugin; -} - -static void -runFmod_fama_oa(LV2_Handle instance, - uint32_t sample_count) +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) { Fmod* plugin = (Fmod*)instance; - /* Frequency to Modulate (array of floats of length sample_count) */ - const float* frequency = plugin->frequency; - - /* LFO Input (array of floats of length sample_count) */ - const float* modulator = plugin->modulator; - - /* Output Frequency (array of floats of length sample_count) */ - float* output = plugin->output; - - float freq; - float mod; - float scale; - - for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; - mod = modulator[s]; - - scale = (float)EXPF(M_LN2 * mod); + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } - output[s] = scale * freq; + switch (port) { + case FMOD_FREQUENCY: + plugin->frequency_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case FMOD_MODULATOR: + plugin->modulator_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; } + + return LV2_MORPH_SUCCESS; } -static void -runFmod_famc_oa(LV2_Handle instance, - uint32_t sample_count) +static LV2_URID +port_type(LV2_Handle instance, + uint32_t port, + LV2_Morph_Property*const* properties) { Fmod* plugin = (Fmod*)instance; - /* Frequency to Modulate (array of floats of length sample_count) */ - const float* frequency = plugin->frequency; - - /* Shift (Octaves) (float value) */ - const float modulator = *(plugin->modulator); - - /* Output Frequency (array of floats of length sample_count) */ - float* output = plugin->output; - - float freq; - float scale = (float)EXPF(M_LN2 * modulator); + switch (port) { + case FMOD_FREQUENCY: + return (plugin->output_is_cv + ? plugin->uris.lv2_CVPort + : plugin->uris.lv2_ControlPort); + default: + return 0; + } +} - for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Fmod* plugin = (Fmod*)malloc(sizeof(Fmod)); - output[s] = scale * freq; + if (plugin) { + plugin->frequency_is_cv = 0; + plugin->modulator_is_cv = 0; } + + return (LV2_Handle)plugin; } static void -runFmod_fcma_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Fmod* plugin = (Fmod*)instance; - /* Frequency to Modulate (float value) */ - const float frequency = *(plugin->frequency); + /* Frequency to Modulate (array of floats of length 1 or sample_count) */ + const float* frequency = plugin->frequency; - /* LFO Input (array of floats of length sample_count) */ + /* LFO Input (array of floats of length 1 or sample_count) */ const float* modulator = plugin->modulator; - /* Output Frequency (array of floats of length sample_count) */ + /* Output Frequency (array of floats of length 1 or sample_count) */ float* output = plugin->output; - float mod; - float scale; + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; + } for (uint32_t s = 0; s < sample_count; ++s) { - mod = modulator[s]; - - scale = (float)EXPF(M_LN2 * mod); + const float freq = frequency[s * plugin->frequency_is_cv]; + const float mod = modulator[s * plugin->modulator_is_cv]; + const float scale = (float)EXPF(M_LN2 * mod); - output[s] = scale * frequency; + output[s] = scale * freq; } } -static void -runFmod_fcmc_oc(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Fmod* plugin = (Fmod*)instance; - - /* Frequency to Modulate (float value) */ - const float frequency = *(plugin->frequency); - - /* Shift (Octaves) (float value) */ - const float modulator = *(plugin->modulator); - - /* Output Frequency (pointer to float value) */ - float* output = plugin->output; - - float scale; - - scale = (float)EXPF(M_LN2 * modulator); - - output[0] = scale * frequency; + static const LV2_Morph_Interface morph = { morph_port, port_type }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; + } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/fmod", + "http://drobilla.net/plugins/blop/fmod", instantiate, connect_port, NULL, - runFmod_fcmc_oc, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/include/common.h b/src/include/common.h index 0f30aa1..26a405a 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -17,8 +17,8 @@ along with this software. If not, see . */ -#ifndef blip_common_h -#define blip_common_h +#ifndef blop_common_h +#define blop_common_h #include "math_func.h" @@ -51,4 +51,4 @@ f_clip (float x, float a, float b) return 0.5f * (FABSF (x - a) + a + b - FABSF (x - b)); } -#endif /* blip_common_h */ +#endif /* blop_common_h */ diff --git a/src/include/interpolate.h b/src/include/interpolate.h index 5fba16a..304a817 100644 --- a/src/include/interpolate.h +++ b/src/include/interpolate.h @@ -1,8 +1,8 @@ -#ifndef blip_interpolate_h -#define blip_interpolate_h +#ifndef blop_interpolate_h +#define blop_interpolate_h #include "lv2/lv2plug.in/ns/lv2core/lv2.h" -#include "blip_config.h" +#include "blop_config.h" #include "math_func.h" /** @@ -72,4 +72,4 @@ f_lerp (float value, return value; } -#endif /* blip_interpolate_h */ +#endif /* blop_interpolate_h */ diff --git a/src/include/lp4pole_filter.h b/src/include/lp4pole_filter.h index adc5cba..a6b27f1 100644 --- a/src/include/lp4pole_filter.h +++ b/src/include/lp4pole_filter.h @@ -30,8 +30,8 @@ along with this software. If not, see . */ -#ifndef blip_lp4pole_filter_h -#define blip_lp4pole_filter_h +#ifndef blop_lp4pole_filter_h +#define blop_lp4pole_filter_h #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "common.h" @@ -134,4 +134,4 @@ lp4pole_run(LP4PoleFilter* lpf, return lpf->out4; } -#endif /* blip_lp4pole_filter_h */ +#endif /* blop_lp4pole_filter_h */ diff --git a/src/include/math_func.h b/src/include/math_func.h index 2e4b6e4..60f7ce0 100644 --- a/src/include/math_func.h +++ b/src/include/math_func.h @@ -7,7 +7,7 @@ #define math_func_h #include -#include "blip_config.h" +#include "blop_config.h" #ifndef M_PI # define M_PI 3.14159265358979323846 /* pi */ diff --git a/src/include/wavedata.h b/src/include/wavedata.h index 9bd313c..9d24823 100644 --- a/src/include/wavedata.h +++ b/src/include/wavedata.h @@ -17,19 +17,19 @@ along with this software. If not, see . */ -#ifndef blip_wavedata_h -#define blip_wavedata_h +#ifndef blop_wavedata_h +#define blop_wavedata_h #include "lv2/lv2plug.in/ns/lv2core/lv2.h" -#include "blip_config.h" +#include "blop_config.h" #include "math_func.h" #include "interpolate.h" #include "common.h" /* Functions identifying wavedata dlls */ -#define BLOP_DLSYM_SAWTOOTH "blip_get_sawtooth" -#define BLOP_DLSYM_SQUARE "blip_get_square" -#define BLOP_DLSYM_PARABOLA "blip_get_parabola" +#define BLOP_DLSYM_SAWTOOTH "blop_get_sawtooth" +#define BLOP_DLSYM_SQUARE "blop_get_square" +#define BLOP_DLSYM_PARABOLA "blop_get_parabola" /* * Structure holding a single segment of sample data @@ -191,4 +191,4 @@ wavedata_get_table(Wavedata* w, } /* extern "C" { */ #endif -#endif /* blip_wavedata_h */ +#endif /* blop_wavedata_h */ diff --git a/src/include/wdatutil.h b/src/include/wdatutil.h index 931a7f3..a084c7a 100644 --- a/src/include/wdatutil.h +++ b/src/include/wdatutil.h @@ -17,8 +17,8 @@ along with this software. If not, see . */ -#ifndef blip_wdatutil_h -#define blip_wdatutil_h +#ifndef blop_wdatutil_h +#define blop_wdatutil_h #include #include "lv2/lv2plug.in/ns/lv2core/lv2.h" @@ -138,4 +138,4 @@ int wavedata_write(Wavedata* w, } /* extern "C" { */ #endif -#endif /* blip_wdatutil_h */ +#endif /* blop_wdatutil_h */ diff --git a/src/interpolator.c b/src/interpolator.c index 52a6c37..24fa927 100644 --- a/src/interpolator.c +++ b/src/interpolator.c @@ -79,6 +79,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Interpolator* plugin = (Interpolator*)malloc(sizeof(Interpolator)); + if (!plugin) { + return NULL; + } return (LV2_Handle)plugin; } @@ -93,8 +96,8 @@ activate(LV2_Handle instance) } static void -runInterpolator(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Interpolator* plugin = (Interpolator*)instance; @@ -121,11 +124,11 @@ runInterpolator(LV2_Handle instance, } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/interpolator", + "http://drobilla.net/plugins/blop/interpolator", instantiate, connect_port, activate, - runInterpolator, + run, NULL, cleanup, NULL, diff --git a/src/lp4pole.c b/src/lp4pole.c index a00ca5b..1997ae3 100644 --- a/src/lp4pole.c +++ b/src/lp4pole.c @@ -18,9 +18,11 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "lp4pole_filter.h" #include "common.h" +#include "uris.h" #define LP4POLE_CUTOFF 0 #define LP4POLE_RESONANCE 1 @@ -33,6 +35,9 @@ typedef struct { float* input; float* output; LP4PoleFilter* lpf; + uint32_t cutoff_is_cv; + uint32_t resonance_is_cv; + URIs uris; } Lp4pole; static void @@ -68,6 +73,33 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Lp4pole* plugin = (Lp4pole*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case LP4POLE_CUTOFF: + plugin->cutoff_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case LP4POLE_RESONANCE: + plugin->resonance_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -80,9 +112,12 @@ instantiate(const LV2_Descriptor* descriptor, plugin->lpf = lp4pole_new(sample_rate); if (!plugin->lpf) { free(plugin); - plugin = 0; + return NULL; } + plugin->cutoff_is_cv = 0; + plugin->resonance_is_cv = 0; } + return (LV2_Handle)plugin; } @@ -95,15 +130,15 @@ activate(LV2_Handle instance) } static void -runLp4pole_faraia_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Lp4pole* plugin = (Lp4pole*)instance; - /* Cutoff Frequency (array of floats of length sample_count) */ + /* Cutoff Frequency (array of floats of length 1 or sample_count) */ const float* cutoff = plugin->cutoff; - /* Resonance (array of floats of length sample_count) */ + /* Resonance (array of floats of length 1 or sample_count) */ const float* resonance = plugin->resonance; /* Input (array of floats of length sample_count) */ @@ -115,61 +150,39 @@ runLp4pole_faraia_oa(LV2_Handle instance, /* Instance data */ LP4PoleFilter* lpf = plugin->lpf; - float in; - float co; - float res; - for (uint32_t s = 0; s < sample_count; ++s) { - co = cutoff[s]; - res = resonance[s]; - in = input[s]; + const float co = cutoff[s * plugin->cutoff_is_cv]; + const float res = resonance[s * plugin->resonance_is_cv]; + const float in = input[s]; + /* TODO: There is no branching in this function. + Would it actually be faster to check if co or res has changed? + */ lp4pole_set_params(lpf, co, res); output[s] = lp4pole_run(lpf, in); } } -static void -runLp4pole_fcrcia_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Lp4pole* plugin = (Lp4pole*)instance; - - /* Cutoff Frequency (float value) */ - const float cutoff = *(plugin->cutoff); - - /* Resonance (float value) */ - const float resonance = *(plugin->resonance); - - /* Input (array of floats of length sample_count) */ - const float* input = plugin->input; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - LP4PoleFilter* lpf = plugin->lpf; - - float in; - - lp4pole_set_params(lpf, cutoff, resonance); - - for (uint32_t s = 0; s < sample_count; ++s) { - in = input[s]; - output[s] = lp4pole_run(lpf, in); + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/lp4pole", + "http://drobilla.net/plugins/blop/lp4pole", instantiate, connect_port, activate, - runLp4pole_fcrcia_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/product.c b/src/product.c index 0b892a1..3f83af9 100644 --- a/src/product.c +++ b/src/product.c @@ -18,16 +18,22 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #define PRODUCT_MULTIPLICAND 0 #define PRODUCT_MULTIPLIER 1 #define PRODUCT_PRODUCT 2 typedef struct { - float* input1; - float* input2; - float* output; + float* input1; + float* input2; + float* output; + uint32_t input1_is_cv; + uint32_t input2_is_cv; + uint32_t output_is_cv; + URIs uris; } Product; static void @@ -56,6 +62,51 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Product* plugin = (Product*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case PRODUCT_MULTIPLICAND: + plugin->input1_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case PRODUCT_MULTIPLIER: + plugin->input2_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + plugin->output_is_cv = plugin->input1_is_cv || plugin->input2_is_cv; + return LV2_MORPH_SUCCESS; +} + +static LV2_URID +port_type(LV2_Handle instance, + uint32_t port, + LV2_Morph_Property*const* properties) +{ + Product* plugin = (Product*)instance; + + switch (port) { + case PRODUCT_PRODUCT: + return (plugin->output_is_cv + ? plugin->uris.lv2_CVPort + : plugin->uris.lv2_ControlPort); + default: + return 0; + } +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -63,77 +114,64 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Product* plugin = (Product*)malloc(sizeof(Product)); + if (!plugin) { + return NULL; + } + + plugin->input1_is_cv = 0; + plugin->input2_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); return (LV2_Handle)plugin; } static void -runProduct_iaia_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Product* plugin = (Product*)instance; - /* First Input (array of floats of length sample_count) */ + /* First Input (array of floats of length 1 or sample_count) */ const float* input1 = plugin->input1; - /* Second Input (array of floats of length sample_count) */ + /* Second Input (array of floats of length 1 or sample_count) */ const float* input2 = plugin->input2; /* Output (array of floats of length sample_count) */ float* output = plugin->output; - for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input1[s] * input2[s]; + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; } -} - -static void -runProduct_iaic_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Product* plugin = (Product*)instance; - - /* First Input (array of floats of length sample_count) */ - const float* input1 = plugin->input1; - - /* Second Input (float value) */ - const float input2 = *(plugin->input2); - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input1[s] * input2; + const float in1 = input1[s * plugin->input1_is_cv]; + const float in2 = input2[s * plugin->input2_is_cv]; + output[s] = in1 * in2; } } -static void -runProduct_icic_oc(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Product* plugin = (Product*)instance; - - /* First Input (float value) */ - const float input1 = *(plugin->input1); - - /* Second Input (float value) */ - const float input2 = *(plugin->input2); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - output[0] = input1 * input2; + static const LV2_Morph_Interface morph = { morph_port, port_type }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; + } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/product", + "http://drobilla.net/plugins/blop/product", instantiate, connect_port, NULL, - runProduct_iaia_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/pulse.c b/src/pulse.c index 8890fbd..c4d857b 100644 --- a/src/pulse.c +++ b/src/pulse.c @@ -18,7 +18,9 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #include "wavedata.h" #define PULSE_FREQUENCY 0 @@ -30,7 +32,10 @@ typedef struct { float* pulsewidth; float* output; float phase; + uint32_t frequency_is_cv; + uint32_t pulsewidth_is_cv; Wavedata wdat; + URIs uris; } Pulse; static void @@ -53,6 +58,33 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Pulse* plugin = (Pulse*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case PULSE_FREQUENCY: + plugin->frequency_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case PULSE_PULSEWIDTH: + plugin->pulsewidth_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -60,6 +92,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Pulse* plugin = (Pulse*)malloc(sizeof(Pulse)); + if (!plugin) { + return NULL; + } if (wavedata_load(&plugin->wdat, bundle_path, "sawtooth_data", BLOP_DLSYM_SAWTOOTH, sample_rate)) { @@ -67,6 +102,11 @@ instantiate(const LV2_Descriptor* descriptor, return 0; } + plugin->frequency_is_cv = 0; + plugin->pulsewidth_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + return (LV2_Handle)plugin; } @@ -88,8 +128,8 @@ activate(LV2_Handle instance) } static void -runPulse_fapa_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Pulse* plugin = (Pulse*)instance; @@ -106,114 +146,32 @@ runPulse_fapa_oa(LV2_Handle instance, Wavedata* wdat = &plugin->wdat; float phase = plugin->phase; - float freq; - float pwidth; - float phase_shift; + float last_pwidth = pulsewidth[0]; + float pwidth = f_clip(last_pwidth, 0.0f, 1.0f); + float dc_shift = 1.0 - (2.0 * pwidth); + float phase_shift = pwidth * wdat->sample_rate; for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; - pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f); - phase_shift = pwidth * wdat->sample_rate; - - /* Lookup which table to use from frequency */ - wavedata_get_table(wdat, freq); - - /* Get samples from sawtooth and phase shifted inverted sawtooth, - with approriate DC offset */ - output[s] = wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift) - + 1.0f - (2.0f * pwidth); - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); } - } - plugin->phase = phase; -} - -static void -runPulse_fapc_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Pulse* plugin = (Pulse*)instance; - - /* Frequency (array of float of length sample_count) */ - const float* frequency = plugin->frequency; - - /* Pulse Width (float value) */ - const float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f); - - /* Output (pointer to float value) */ - float* output = plugin->output; - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - - float freq; - float dc_shift = 1.0 - (2.0 * pulsewidth); - float phase_shift = pulsewidth * wdat->sample_rate; - - for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; - - /* Lookup which table to use from frequency */ - wavedata_get_table(wdat, freq); - - /* Get samples from sawtooth and phase shifted inverted sawtooth, - with approriate DC offset */ - output[s] = wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift) - + dc_shift; - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; + const float this_pwidth = pulsewidth[s * plugin->pulsewidth_is_cv]; + if (this_pwidth != last_pwidth) { + /* Pulsewidth changed, recalculate */ + last_pwidth = this_pwidth; + pwidth = f_clip(this_pwidth, 0.0f, 1.0f); + dc_shift = 1.0f - (2.0f * pwidth); + phase_shift = pwidth * wdat->sample_rate; } - } - plugin->phase = phase; -} - -static void -runPulse_fcpa_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Pulse* plugin = (Pulse*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Pulse Width (array of float of length sample_count) */ - const float* pulsewidth = plugin->pulsewidth; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - - float pwidth; - float phase_shift; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; ++s) { - pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f); - phase_shift = pwidth * wdat->sample_rate; /* Get samples from sawtooth and phase shifted inverted sawtooth, with approriate DC offset */ output[s] = wavedata_get_sample(wdat, phase) - wavedata_get_sample(wdat, phase + phase_shift) - + 1.0f - (2.0f * pwidth); + + dc_shift; /* Update phase, wrapping if necessary */ phase += wdat->frequency; @@ -226,57 +184,25 @@ runPulse_fcpa_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runPulse_fcpc_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Pulse* plugin = (Pulse*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Pulse Width (float value) */ - const float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - - float dc_shift = 1.0f - (2.0f * pulsewidth); - float phase_shift = pulsewidth * wdat->sample_rate; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; ++s) { - /* Get samples from sawtooth and phase shifted inverted sawtooth, - with approriate DC offset */ - output[s] = wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift) - + dc_shift; - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/pulse", + "http://drobilla.net/plugins/blop/pulse", instantiate, connect_port, activate, - runPulse_fcpc_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/quantiser.c b/src/quantiser.c index 793da32..419467f 100644 --- a/src/quantiser.c +++ b/src/quantiser.c @@ -205,54 +205,16 @@ instantiate(const LV2_Descriptor* descriptor, } static void -runQuantiser_audio(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Quantiser* plugin = (Quantiser*)instance; /* Range Min (float value) */ - const float min = *(plugin->min); + float min = *(plugin->min); /* Range Max (float value) */ - const float max = *(plugin->max); - - /* Match Range (float value) */ - const float match_range = *(plugin->match_range); - - /* Mode (float value) */ - const float mode = *(plugin->mode); - - /* Count (float value) */ - const float count = *(plugin->count); - - /* Input (array of float of length sample_count) */ - const float* input = plugin->input; - - /* Values */ - float* values[QUANTISER_MAX_INPUTS]; - - /* Output (array of float of length sample_count) */ - float* output = plugin->output; - - /* Output Changed (array of float of length sample_count) */ - float* output_changed = plugin->output_changed; - - for (uint32_t s = 0; s < sample_count; s++) { - output[s] = input[s]; - } -} - -static void -runQuantiser_control(LV2_Handle instance, - uint32_t sample_count) -{ - Quantiser* plugin = (Quantiser*)instance; - - /* Range Min (float value) */ - const float min = *(plugin->min); - - /* Range Max (float value) */ - const float max = *(plugin->max); + float max = *(plugin->max); /* Match Range (float value) */ const float match_range = FABSF(*(plugin->match_range)); @@ -469,3 +431,23 @@ runQuantiser_control(LV2_Handle instance, } plugin->last_found = last_found; } + +static const LV2_Descriptor descriptor = { + QUANTISER_URI, + 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/random.c b/src/random.c index 4a6f5b8..1671854 100644 --- a/src/random.c +++ b/src/random.c @@ -18,24 +18,29 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include #include "math_func.h" #include "common.h" +#include "uris.h" #define RANDOM_FREQUENCY 0 #define RANDOM_SMOOTH 1 #define RANDOM_OUTPUT 2 typedef struct { - float* frequency; - float* smooth; - float* output; - float nyquist; - float inv_nyquist; - float phase; - float value1; - float value2; + float* frequency; + float* smooth; + float* output; + float nyquist; + float inv_nyquist; + float phase; + float value1; + float value2; + uint32_t frequency_is_cv; + uint32_t smooth_is_cv; + URIs uris; } Random; float inv_rand_max; @@ -66,6 +71,33 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Random* plugin = (Random*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case RANDOM_FREQUENCY: + plugin->frequency_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case RANDOM_SMOOTH: + plugin->smooth_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -73,6 +105,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Random* plugin = (Random*)malloc(sizeof(Random)); + if (!plugin) { + return NULL; + } srand((int)time((time_t*)0)); @@ -84,6 +119,9 @@ instantiate(const LV2_Descriptor* descriptor, plugin->value1 = rand() * inv_rand_max - 1.0f; plugin->value2 = rand() * inv_rand_max - 1.0f; + plugin->frequency_is_cv = 0; + plugin->smooth_is_cv = 0; + return (LV2_Handle)plugin; } @@ -96,15 +134,15 @@ activate(LV2_Handle instance) } static void -runRandom_fasa_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Random* plugin = (Random*)instance; - /* Frequency (Hz) (array of floats of length sample_count) */ + /* Frequency (Hz) (array of floats of length 1 or sample_count) */ const float* frequency = plugin->frequency; - /* Wave smoothness (array of floats of length sample_count) */ + /* Wave smoothness (array of floats of length 1 or sample_count) */ const float* smooth = plugin->smooth; /* Output (array of floats of length sample_count) */ @@ -117,132 +155,16 @@ runRandom_fasa_oa(LV2_Handle instance, float value1 = plugin->value1; float value2 = plugin->value2; - float freq; - float smth; - float interval; float result; for (uint32_t s = 0; s < sample_count; ++s) { - freq = f_clip(frequency[s], 0.0f, nyquist); - - smth = f_clip(smooth[s], 0.0f, 1.0f); - interval = (1.0f - smth) * 0.5f; - - if (phase < interval) { - result = 1.0f; - } else if (phase > (1.0f - interval)) { - result = -1.0f; - } else if (interval > 0.0f) { - result = COSF((phase - interval) / smth * M_PI); - } else { - result = COSF(phase * M_PI); - } - - result *= (value2 - value1) * 0.5f; - result -= (value2 + value1) * 0.5f; - - output[s] = result; - - phase += freq * inv_nyquist; - if (phase > 1.0f) { - phase -= 1.0f; - value1 = value2; - value2 = (float)rand() * inv_rand_max - 1.0f; - } - } - - plugin->phase = phase; - plugin->value1 = value1; - plugin->value2 = value2; -} - -static void -runRandom_fasc_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Random* plugin = (Random*)instance; - - /* Frequency (Hz) (array of floats of length sample_count) */ - const float* frequency = plugin->frequency; - - /* Wave smoothness (float value) */ - const float smooth = f_clip(*(plugin->smooth), 0.0f, 1.0f); - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; - - /* Instance data */ - float nyquist = plugin->nyquist; - float inv_nyquist = plugin->inv_nyquist; - float phase = plugin->phase; - float value1 = plugin->value1; - float value2 = plugin->value2; - - float freq; - float interval = (1.0f - smooth) * 0.5f; - float result; - - for (uint32_t s = 0; s < sample_count; ++s) { - freq = f_clip(frequency[s], 0.0f, nyquist); - - if (phase < interval) { - result = 1.0f; - } else if (phase > (1.0f - interval)) { - result = -1.0f; - } else if (interval > 0.0f) { - result = COSF((phase - interval) / smooth * M_PI); - } else { - result = COSF(phase * M_PI); - } - - result *= (value2 - value1) * 0.5f; - result -= (value2 + value1) * 0.5f; - - output[s] = result; - - phase += freq * inv_nyquist; - if (phase > 1.0f) { - phase -= 1.0f; - value1 = value2; - value2 = (float)rand() * inv_rand_max - 1.0f; - } - } - - plugin->phase = phase; - plugin->value1 = value1; - plugin->value2 = value2; -} + const float freq = f_clip(frequency[s * plugin->frequency_is_cv], + 0.0f, nyquist); -static void -runRandom_fcsa_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Random* plugin = (Random*)instance; + const float smth = f_clip(smooth[s * plugin->smooth_is_cv], + 0.0f, 1.0f); - /* Frequency (Hz) (float value) */ - const float frequency = *(plugin->frequency); - - /* Wave smoothness (array of floats of length sample_count) */ - const float* smooth = plugin->smooth; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - float nyquist = plugin->nyquist; - float inv_nyquist = plugin->inv_nyquist; - float phase = plugin->phase; - float value1 = plugin->value1; - float value2 = plugin->value2; - - float phase_scale = f_clip(frequency, 0.0f, nyquist) * inv_nyquist; - float smth; - float interval; - float result; - - for (uint32_t s = 0; s < sample_count; ++s) { - smth = f_clip(smooth[s], 0.0f, 1.0f); - interval = (1.0f - smth) * 0.5f; + const float interval = (1.0f - smth) * 0.5f; if (phase < interval) { result = 1.0f; @@ -259,7 +181,7 @@ runRandom_fcsa_oa(LV2_Handle instance, output[s] = result; - phase += phase_scale; + phase += freq * inv_nyquist; if (phase > 1.0f) { phase -= 1.0f; value1 = value2; @@ -272,70 +194,25 @@ runRandom_fcsa_oa(LV2_Handle instance, plugin->value2 = value2; } -static void -runRandom_fcsc_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Random* plugin = (Random*)instance; - - /* Frequency (Hz) (float value) */ - const float frequency = *(plugin->frequency); - - /* Wave smoothness (float value) */ - const float smooth = f_clip(*(plugin->smooth), 0.0f, 1.0f); - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; - - /* Instance data */ - float nyquist = plugin->nyquist; - float inv_nyquist = plugin->inv_nyquist; - float phase = plugin->phase; - float value1 = plugin->value1; - float value2 = plugin->value2; - - float phase_scale = f_clip(frequency, 0.0f, nyquist) * inv_nyquist; - float interval = (1.0f - smooth) * 0.5f; - float result; - - for (uint32_t s = 0; s < sample_count; ++s) { - if (phase < interval) { - result = 1.0f; - } else if (phase > (1.0f - interval)) { - result = -1.0f; - } else if (interval > 0.0f) { - result = COSF((phase - interval) / smooth * M_PI); - } else { - result = COSF(phase * M_PI); - } - - result *= (value2 - value1) * 0.5f; - result -= (value2 + value1) * 0.5f; - - output[s] = result; - - phase += phase_scale; - if (phase > 1.0f) { - phase -= 1.0f; - value1 = value2; - value2 = (float)rand() * inv_rand_max - 1.0f; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - - plugin->phase = phase; - plugin->value1 = value1; - plugin->value2 = value2; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/random", + "http://drobilla.net/plugins/blop/random", instantiate, connect_port, activate, - runRandom_fcsc_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/ratio.c b/src/ratio.c index 4659f4f..0bb3f1f 100644 --- a/src/ratio.c +++ b/src/ratio.c @@ -18,18 +18,24 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "math_func.h" #include "common.h" +#include "uris.h" #define RATIO_NUMERATOR 0 #define RATIO_DENOMINATOR 1 #define RATIO_OUTPUT 2 typedef struct { - float* numerator; - float* denominator; - float* output; + float* numerator; + float* denominator; + float* output; + uint32_t numerator_is_cv; + uint32_t denominator_is_cv; + uint32_t output_is_cv; + URIs uris; } Ratio; static void @@ -58,6 +64,51 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Ratio* plugin = (Ratio*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case RATIO_NUMERATOR: + plugin->numerator_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case RATIO_DENOMINATOR: + plugin->denominator_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + plugin->output_is_cv = plugin->numerator_is_cv || plugin->denominator_is_cv; + return LV2_MORPH_SUCCESS; +} + +static LV2_URID +port_type(LV2_Handle instance, + uint32_t port, + LV2_Morph_Property*const* properties) +{ + Ratio* plugin = (Ratio*)instance; + + switch (port) { + case RATIO_OUTPUT: + return (plugin->output_is_cv + ? plugin->uris.lv2_CVPort + : plugin->uris.lv2_ControlPort); + default: + return 0; + } +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -66,12 +117,20 @@ instantiate(const LV2_Descriptor* descriptor, { Ratio* plugin = (Ratio*)malloc(sizeof(Ratio)); + if (plugin) { + plugin->numerator_is_cv = 0; + plugin->denominator_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); + } + return (LV2_Handle)plugin; } static void -runRatio_nada_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Ratio* plugin = (Ratio*)instance; @@ -84,90 +143,39 @@ runRatio_nada_oa(LV2_Handle instance, /* Output (array of floats of length sample_count) */ float* output = plugin->output; - for (uint32_t s = 0; s < sample_count; ++s) { - const float n = numerator[s]; - float d = denominator[s]; - - d = COPYSIGNF(f_max(FABSF(d), 1e-16f), d); - - output[s] = n / d; + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; } -} - -static void -runRatio_nadc_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Ratio* plugin = (Ratio*)instance; - - /* Numerator (array of floats of length sample_count) */ - const float* numerator = plugin->numerator; - - /* Denominator (float value) */ - float denominator = *(plugin->denominator); - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; - - denominator = COPYSIGNF(f_max(FABSF(denominator), 1e-16f), denominator); for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = numerator[s] / denominator; - } -} - -static void -runRatio_ncda_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Ratio* plugin = (Ratio*)instance; + const float n = numerator[s * plugin->numerator_is_cv]; + float d = denominator[s * plugin->denominator_is_cv]; - /* Numerator (float value) */ - const float numerator = *(plugin->numerator); - - /* Denominator (array of floats of length sample_count) */ - const float* denominator = plugin->denominator; - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; - - for (uint32_t s = 0; s < sample_count; ++s) { - float d = denominator[s]; d = COPYSIGNF(f_max(FABSF(d), 1e-16f), d); - output[s] = numerator / d; + output[s] = n / d; } } -static void -runRatio_ncdc_oc(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Ratio* plugin = (Ratio*)instance; - - /* Numerator (float value) */ - const float numerator = *(plugin->numerator); - - /* Denominator (float value) */ - float denominator = *(plugin->denominator); - - /* Output Frequency (pointer to float value) */ - float* output = plugin->output; - - denominator = COPYSIGNF(f_max(FABSF(denominator), 1e-16f), denominator); - - output[0] = numerator / denominator; + static const LV2_Morph_Interface morph = { morph_port, port_type }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; + } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/ratio", + "http://drobilla.net/plugins/blop/ratio", instantiate, connect_port, NULL, - runRatio_nada_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/sawtooth.c b/src/sawtooth.c index 3c242e1..35db21f 100644 --- a/src/sawtooth.c +++ b/src/sawtooth.c @@ -18,7 +18,9 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #include "wavedata.h" #define SAWTOOTH_FREQUENCY 0 @@ -28,7 +30,9 @@ typedef struct { float* frequency; float* output; float phase; + uint32_t frequency_is_cv; Wavedata wdat; + URIs uris; } Sawtooth; static void @@ -48,6 +52,23 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Sawtooth* plugin = (Sawtooth*)instance; + if (type == plugin->uris.lv2_ControlPort) { + plugin->frequency_is_cv = 0; + } else if (type == plugin->uris.lv2_CVPort) { + plugin->frequency_is_cv = 1; + } else { + return LV2_MORPH_ERR_BAD_TYPE; + } + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -55,6 +76,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Sawtooth* plugin = (Sawtooth*)malloc(sizeof(Sawtooth)); + if (!plugin) { + return NULL; + } if (wavedata_load(&plugin->wdat, bundle_path, "sawtooth_data", BLOP_DLSYM_SAWTOOTH, sample_rate)) { @@ -62,6 +86,10 @@ instantiate(const LV2_Descriptor* descriptor, return 0; } + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + return (LV2_Handle)plugin; } @@ -83,12 +111,12 @@ activate(LV2_Handle instance) } static void -runSawtooth_fa_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Sawtooth* plugin = (Sawtooth*)instance; - /* Frequency (array of float of length sample_count) */ + /* Frequency (array of float of length 1 or sample_count) */ const float* frequency = plugin->frequency; /* Output (pointer to float value) */ @@ -99,8 +127,11 @@ runSawtooth_fa_oa(LV2_Handle instance, float phase = plugin->phase; for (uint32_t s = 0; s < sample_count; s++) { - /* Lookup table to play */ - wavedata_get_table(wdat, frequency[s]); + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } output[s] = wavedata_get_sample(wdat, phase); @@ -115,47 +146,25 @@ runSawtooth_fa_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runSawtooth_fc_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Sawtooth* plugin = (Sawtooth*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; s++) { - output[s] = wavedata_get_sample(wdat, phase); - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/sawtooth", + "http://drobilla.net/plugins/blop/sawtooth", instantiate, connect_port, activate, - runSawtooth_fc_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/sequencer.c b/src/sequencer.c index ef22a8a..e5c97c7 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -94,6 +94,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Sequencer* plugin = (Sequencer*)malloc(sizeof(Sequencer)); + if (!plugin) { + return NULL; + } plugin->srate = (float)sample_rate; plugin->inv_srate = 1.0f / plugin->srate; @@ -113,8 +116,8 @@ activate(LV2_Handle instance) } static void -runSequencer(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Sequencer* plugin = (Sequencer*)instance; @@ -145,7 +148,7 @@ runSequencer(LV2_Handle instance, unsigned int step_index = plugin->step_index; unsigned int loop_index = LRINTF(loop_steps); - int rst = LRINTF(reset); + int rst = reset > 0.0f; int i; loop_index = loop_index == 0 ? 1 : loop_index; @@ -191,3 +194,23 @@ runSequencer(LV2_Handle instance, plugin->last_value = last_value; plugin->step_index = step_index; } + +static const LV2_Descriptor descriptor = { + SEQUENCER_URI, + 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/square.c b/src/square.c index fb78859..59dd22f 100644 --- a/src/square.c +++ b/src/square.c @@ -18,7 +18,9 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #include "wavedata.h" #define SQUARE_FREQUENCY 0 @@ -28,7 +30,9 @@ typedef struct { float* frequency; float* output; float phase; + uint32_t frequency_is_cv; Wavedata wdat; + URIs uris; } Square; static void @@ -48,6 +52,23 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Square* plugin = (Square*)instance; + if (type == plugin->uris.lv2_ControlPort) { + plugin->frequency_is_cv = 0; + } else if (type == plugin->uris.lv2_CVPort) { + plugin->frequency_is_cv = 1; + } else { + return LV2_MORPH_ERR_BAD_TYPE; + } + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -55,6 +76,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Square* plugin = (Square*)malloc(sizeof(Square)); + if (!plugin) { + return NULL; + } if (wavedata_load(&plugin->wdat, bundle_path, "square_data", BLOP_DLSYM_SQUARE, sample_rate)) { @@ -62,6 +86,10 @@ instantiate(const LV2_Descriptor* descriptor, return NULL; } + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + return (LV2_Handle)plugin; } @@ -83,8 +111,8 @@ activate(LV2_Handle instance) } static void -runSquare_fa_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Square* plugin = (Square*)instance; @@ -99,8 +127,11 @@ runSquare_fa_oa(LV2_Handle instance, float phase = plugin->phase; for (uint32_t s = 0; s < sample_count; ++s) { - /* Get table to play */ - wavedata_get_table(wdat, frequency[s]); + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } /* Get interpolated sample */ output[s] = wavedata_get_sample(wdat, phase); @@ -116,47 +147,25 @@ runSquare_fa_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runSquare_fc_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Square* plugin = (Square*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = wavedata_get_sample(wdat, phase); - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/square", + "http://drobilla.net/plugins/blop/square", instantiate, connect_port, activate, - runSquare_fc_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/sum.c b/src/sum.c index 2384d73..4eb9182 100644 --- a/src/sum.c +++ b/src/sum.c @@ -18,16 +18,22 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #define SUM_INPUT1 0 #define SUM_INPUT2 1 #define SUM_OUTPUT 2 typedef struct { - float* input1; - float* input2; - float* output; + float* input1; + float* input2; + float* output; + uint32_t input1_is_cv; + uint32_t input2_is_cv; + uint32_t output_is_cv; + URIs uris; } Sum; static void @@ -56,6 +62,51 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Sum* plugin = (Sum*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case SUM_INPUT1: + plugin->input1_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case SUM_INPUT2: + plugin->input2_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + plugin->output_is_cv = plugin->input1_is_cv || plugin->input2_is_cv; + return LV2_MORPH_SUCCESS; +} + +static LV2_URID +port_type(LV2_Handle instance, + uint32_t port, + LV2_Morph_Property*const* properties) +{ + Sum* plugin = (Sum*)instance; + + switch (port) { + case SUM_OUTPUT: + return (plugin->output_is_cv + ? plugin->uris.lv2_CVPort + : plugin->uris.lv2_ControlPort); + default: + return 0; + } +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -64,12 +115,20 @@ instantiate(const LV2_Descriptor* descriptor, { Sum* plugin = (Sum*)malloc(sizeof(Sum)); + if (plugin) { + plugin->input1_is_cv = 0; + plugin->input2_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); + } + return (LV2_Handle)plugin; } static void -runSum_iaia_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Sum* plugin = (Sum*)instance; @@ -82,58 +141,36 @@ runSum_iaia_oa(LV2_Handle instance, /* Output (array of floats of length sample_count) */ float* output = plugin->output; - for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input1[s] + input2[s]; + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; } -} - -static void -runSum_iaic_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Sum* plugin = (Sum*)instance; - - /* First Input (array of floats of length sample_count) */ - const float* input1 = plugin->input1; - - /* Second Input (float value) */ - const float input2 = *(plugin->input2); - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; for (uint32_t s = 0; s < sample_count; ++s) { - output[s] = input1[s] + input2; + const float in1 = input1[s * plugin->input1_is_cv]; + const float in2 = input2[s * plugin->input2_is_cv]; + output[s] = in1 + in2; } } -static void -runSum_icic_oc(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Sum* plugin = (Sum*)instance; - - /* First Input (float value) */ - const float input1 = *(plugin->input1); - - /* Second Input (float value) */ - const float input2 = *(plugin->input2); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - output[0] = input1 + input2; + static const LV2_Morph_Interface morph = { morph_port, port_type }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; + } + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/sum", + "http://drobilla.net/plugins/blop/sum", instantiate, connect_port, NULL, - runSum_iaia_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/sync_pulse.c b/src/sync_pulse.c index 96f90c7..732faa9 100644 --- a/src/sync_pulse.c +++ b/src/sync_pulse.c @@ -19,7 +19,9 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #include "common.h" #define SYNCPULSE_FREQUENCY 0 @@ -28,12 +30,15 @@ #define SYNCPULSE_OUTPUT 3 typedef struct { - float* frequency; - float* pulsewidth; - float* gate; - float* output; - float srate; - float phase; + float* frequency; + float* pulsewidth; + float* gate; + float* output; + float srate; + float phase; + uint32_t frequency_is_cv; + uint32_t pulsewidth_is_cv; + URIs uris; } SyncPulse; static void @@ -65,6 +70,33 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + SyncPulse* plugin = (SyncPulse*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case SYNCPULSE_FREQUENCY: + plugin->frequency_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case SYNCPULSE_PULSEWIDTH: + plugin->pulsewidth_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -73,7 +105,12 @@ instantiate(const LV2_Descriptor* descriptor, { SyncPulse* plugin = (SyncPulse*)malloc(sizeof(SyncPulse)); - plugin->srate = (float)sample_rate; + if (plugin) { + plugin->srate = (float)sample_rate; + plugin->frequency_is_cv = 0; + plugin->pulsewidth_is_cv = 0; + map_uris(&plugin->uris, features); + } return (LV2_Handle)plugin; } @@ -87,8 +124,8 @@ activate(LV2_Handle instance) } static void -runSyncPulse_fapaga_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { SyncPulse* plugin = (SyncPulse*)instance; @@ -108,13 +145,11 @@ runSyncPulse_fapaga_oa(LV2_Handle instance, float phase = plugin->phase; float srate = plugin->srate; - float freq; - float pwidth; - for (uint32_t s = 0; s < sample_count; ++s) { if (gate[s] > 0.0f) { - freq = frequency[s]; - pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f) * srate; + const float freq = frequency[s * plugin->frequency_is_cv]; + const float pw = pulsewidth[s * plugin->pulsewidth_is_cv]; + const float pwidth = f_clip(pw, 0.0f, 1.0f) * srate; if (phase < pwidth) { output[s] = 1.0f; @@ -137,62 +172,25 @@ runSyncPulse_fapaga_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runSyncPulse_fcpcga_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - SyncPulse* plugin = (SyncPulse*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Pulse Width (float value) */ - float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f); - - /* Gate (array of float of length sample_count) */ - const float* gate = plugin->gate; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance Data */ - float phase = plugin->phase; - float srate = plugin->srate; - - pulsewidth *= srate; - - for (uint32_t s = 0; s < sample_count; ++s) { - if (gate[s] > 0.0f) { - if (phase < pulsewidth) { - output[s] = 1.0f; - } else { - output[s] = -1.0f; - } - - phase += frequency; - if (phase < 0.0f) { - phase += srate; - } else if (phase > srate) { - phase -= srate; - } - } else { - output[s] = 0.0f; - phase = 0.0f; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/sync_pulse", + "http://drobilla.net/plugins/blop/sync_pulse", instantiate, connect_port, activate, - runSyncPulse_fcpcga_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/sync_square.c b/src/sync_square.c index 51ceac5..19fbcc1 100644 --- a/src/sync_square.c +++ b/src/sync_square.c @@ -19,19 +19,23 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #define SYNCSQUARE_FREQUENCY 0 #define SYNCSQUARE_GATE 1 #define SYNCSQUARE_OUTPUT 2 typedef struct { - float* frequency; - float* gate; - float* output; - float srate; - float nyquist; - float phase; + float* frequency; + float* gate; + float* output; + float srate; + float nyquist; + float phase; + uint32_t frequency_is_cv; + URIs uris; } SyncSquare; static void @@ -60,6 +64,31 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + SyncSquare* plugin = (SyncSquare*)instance; + + switch (port) { + case SYNCSQUARE_FREQUENCY: + if (type == plugin->uris.lv2_ControlPort) { + plugin->frequency_is_cv = 0; + } else if (type == plugin->uris.lv2_CVPort) { + plugin->frequency_is_cv = 1; + } else { + return LV2_MORPH_ERR_BAD_TYPE; + } + return LV2_MORPH_SUCCESS; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -67,9 +96,14 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { SyncSquare* plugin = (SyncSquare*)malloc(sizeof(SyncSquare)); + if (!plugin) { + return NULL; + } - plugin->srate = (float)sample_rate; - plugin->nyquist = (float)(sample_rate / 2); + plugin->srate = (float)sample_rate; + plugin->nyquist = (float)(sample_rate / 2.0f); + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); return (LV2_Handle)plugin; } @@ -83,12 +117,12 @@ activate(LV2_Handle instance) } static void -runSyncSquare_faga_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { SyncSquare* plugin = (SyncSquare*)instance; - /* Frequency (array of float of length sample_count) */ + /* Frequency (array of float of length 1 or sample_count) */ const float* frequency = plugin->frequency; /* Gate (array of float of length sample_count) */ @@ -102,11 +136,9 @@ runSyncSquare_faga_oa(LV2_Handle instance, float srate = plugin->srate; float nyquist = plugin->nyquist; - float freq; - for (uint32_t s = 0; s < sample_count; ++s) { if (gate[s] > 0.0f) { - freq = frequency[s]; + const float freq = frequency[s * plugin->frequency_is_cv]; if (phase < nyquist) { output[s] = 1.0f; @@ -129,58 +161,25 @@ runSyncSquare_faga_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runSyncSquare_fcga_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - SyncSquare* plugin = (SyncSquare*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Gate (array of float of length sample_count) */ - const float* gate = plugin->gate; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance Data */ - float phase = plugin->phase; - float srate = plugin->srate; - float nyquist = plugin->nyquist; - - for (uint32_t s = 0; s < sample_count; ++s) { - if (gate[s] > 0.0f) { - if (phase < nyquist) { - output[s] = 1.0f; - } else { - output[s] = -1.0f; - } - - phase += frequency; - if (phase < 0.0f) { - phase += srate; - } else if (phase > srate) { - phase -= srate; - } - } else { - output[s] = 0.0f; - phase = 0.0f; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/sync_square", + "http://drobilla.net/plugins/blop/sync_square", instantiate, connect_port, activate, - runSyncSquare_fcga_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/tracker.c b/src/tracker.c index cb93bf8..0df74df 100644 --- a/src/tracker.c +++ b/src/tracker.c @@ -18,8 +18,10 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "common.h" +#include "uris.h" #define TRACKER_GATE 0 #define TRACKER_HATTACK 1 @@ -30,15 +32,20 @@ #define TRACKER_OUTPUT 6 typedef struct { - float* gate; - float* hattack; - float* hdecay; - float* lattack; - float* ldecay; - float* input; - float* output; - float coeff; - float last_value; + float* gate; + float* hattack; + float* hdecay; + float* lattack; + float* ldecay; + float* input; + float* output; + float coeff; + float last_value; + uint32_t hattack_is_cv; + uint32_t hdecay_is_cv; + uint32_t lattack_is_cv; + uint32_t ldecay_is_cv; + URIs uris; } Tracker; static void @@ -79,6 +86,39 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Tracker* plugin = (Tracker*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case TRACKER_HATTACK: + plugin->hattack_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case TRACKER_HDECAY: + plugin->hdecay_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case TRACKER_LATTACK: + plugin->lattack_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case TRACKER_LDECAY: + plugin->ldecay_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -86,9 +126,19 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Tracker* plugin = (Tracker*)malloc(sizeof(Tracker)); + if (!plugin) { + return NULL; + } plugin->coeff = 2.0f * M_PI / (float)sample_rate; + plugin->hattack_is_cv = 0; + plugin->hdecay_is_cv = 0; + plugin->lattack_is_cv = 0; + plugin->ldecay_is_cv = 0; + + map_uris(&plugin->uris, features); + return (LV2_Handle)plugin; } @@ -101,24 +151,24 @@ activate(LV2_Handle instance) } static void -runTracker_gaaadaia_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Tracker* plugin = (Tracker*)instance; /* Gate (array of floats of length sample_count) */ const float* gate = plugin->gate; - /* Gate High Attack Rate (array of floats of length sample_count) */ + /* Gate High Attack Rate (array of floats of length 1 or sample_count) */ const float* hattack = plugin->hattack; - /* Gate High Decay Rate (array of floats of length sample_count) */ + /* Gate High Decay Rate (array of floats of length 1 or sample_count) */ const float* hdecay = plugin->hdecay; - /* Gate Low Attack Rate (array of floats of length sample_count) */ + /* Gate Low Attack Rate (array of floats of length 1 or sample_count) */ const float* lattack = plugin->lattack; - /* Gate Low Decay Rate (array of floats of length sample_count) */ + /* Gate Low Decay Rate (array of floats of length 1 or sample_count) */ const float* ldecay = plugin->ldecay; /* Input (array of floats of length sample_count) */ @@ -131,16 +181,18 @@ runTracker_gaaadaia_oa(LV2_Handle instance, float coeff = plugin->coeff; float last_value = plugin->last_value; - float rate; - float in; - for (uint32_t s = 0; s < sample_count; ++s) { - in = input[s]; + const float in = input[s]; + const float ha = hattack[s * plugin->hattack_is_cv]; + const float hd = hdecay[s * plugin->hdecay_is_cv]; + const float la = lattack[s * plugin->lattack_is_cv]; + const float ld = ldecay[s * plugin->ldecay_is_cv]; + float rate; if (gate[s] > 0.0f) { - rate = in > last_value ? hattack[s] : hdecay[s]; + rate = in > last_value ? ha : hd; } else { - rate = in > last_value ? lattack[s] : ldecay[s]; + rate = in > last_value ? la : ld; } rate = f_min(1.0f, rate * coeff); @@ -152,71 +204,25 @@ runTracker_gaaadaia_oa(LV2_Handle instance, plugin->last_value = last_value; } -static void -runTracker_gaacdcia_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Tracker* plugin = (Tracker*)instance; - - /* Gate (array of floats of length sample_count) */ - const float* gate = plugin->gate; - - /* Gate High Attack Rate (float value) */ - float hattack = *(plugin->hattack); - - /* Gate High Decay Rate (float value) */ - float hdecay = *(plugin->hdecay); - - /* Gate Low Attack Rate (float value) */ - float lattack = *(plugin->lattack); - - /* Gate Low Decay Rate (float value) */ - float ldecay = *(plugin->ldecay); - - /* Input (array of floats of length sample_count) */ - const float* input = plugin->input; - - /* Output (array of floats of length sample_count) */ - float* output = plugin->output; - - /* Instance Data */ - float coeff = plugin->coeff; - float last_value = plugin->last_value; - - float in; - float rate; - - hattack = f_min(1.0f, hattack * coeff); - hdecay = f_min(1.0f, hdecay * coeff); - lattack = f_min(1.0f, lattack * coeff); - ldecay = f_min(1.0f, ldecay * coeff); - - for (uint32_t s = 0; s < sample_count; ++s) { - in = input[s]; - - if (gate[s] > 0.0f) { - rate = in > last_value ? hattack : hdecay; - } else { - rate = in > last_value ? lattack : ldecay; - } - - last_value = last_value * (1.0f - rate) + in * rate; - - output[s] = last_value; + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - - plugin->last_value = last_value; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/tracker", + "http://drobilla.net/plugins/blop/tracker", instantiate, connect_port, activate, - runTracker_gaacdcia_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/triangle.c b/src/triangle.c index 0a06f6c..f42e84c 100644 --- a/src/triangle.c +++ b/src/triangle.c @@ -18,7 +18,9 @@ */ #include +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" #include "wavedata.h" #define TRIANGLE_FREQUENCY 0 @@ -32,7 +34,10 @@ typedef struct { float phase; float min_slope; float max_slope; + uint32_t frequency_is_cv; + uint32_t slope_is_cv; Wavedata wdat; + URIs uris; } Triangle; static void @@ -55,6 +60,33 @@ connect_port(LV2_Handle instance, } } +static LV2_Morph_Status +morph_port(LV2_Handle instance, + uint32_t port, + LV2_URID type, + const LV2_Morph_Property*const* properties) +{ + Triangle* plugin = (Triangle*)instance; + + if (type != plugin->uris.lv2_ControlPort && + type != plugin->uris.lv2_CVPort) { + return LV2_MORPH_ERR_BAD_TYPE; + } + + switch (port) { + case TRIANGLE_FREQUENCY: + plugin->frequency_is_cv = (type == plugin->uris.lv2_CVPort); + break; + case TRIANGLE_SLOPE: + plugin->slope_is_cv = (type == plugin->uris.lv2_CVPort); + break; + default: + return LV2_MORPH_ERR_BAD_PORT; + } + + return LV2_MORPH_SUCCESS; +} + static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double sample_rate, @@ -62,6 +94,9 @@ instantiate(const LV2_Descriptor* descriptor, const LV2_Feature* const* features) { Triangle* plugin = (Triangle*)malloc(sizeof(Triangle)); + if (!plugin) { + return NULL; + } if (wavedata_load(&plugin->wdat, bundle_path, "parabola_data", BLOP_DLSYM_PARABOLA, sample_rate)) { @@ -72,6 +107,12 @@ instantiate(const LV2_Descriptor* descriptor, plugin->min_slope = 2.0f / plugin->wdat.sample_rate; plugin->max_slope = 1.0f - plugin->min_slope; + plugin->frequency_is_cv = 0; + plugin->slope_is_cv = 0; + + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + return (LV2_Handle)plugin; } @@ -93,141 +134,51 @@ activate(LV2_Handle instance) } static void -runTriangle_fasa_oa(LV2_Handle instance, - uint32_t sample_count) +run(LV2_Handle instance, + uint32_t sample_count) { Triangle* plugin = (Triangle*)instance; - /* Frequency (array of float of length sample_count) */ + /* Frequency (array of float of length 1 or sample_count) */ const float* frequency = plugin->frequency; - /* Slope (array of float of length sample_count) */ + /* Slope (array of float of length 1 or sample_count) */ const float* slope = plugin->slope; /* Output (pointer to float value) */ float* output = plugin->output; /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - float min_slope = plugin->min_slope; - float max_slope = plugin->max_slope; + Wavedata* wdat = &plugin->wdat; + float phase = plugin->phase; + const float min_slope = plugin->min_slope; + const float max_slope = plugin->max_slope; - float freq; - float slp; - float phase_shift; + float last_slope = slope[0]; + float slp = f_clip(last_slope, min_slope, max_slope); + float phase_shift = slp * wdat->sample_rate; + float scale = 1.0f / (8.0f * (slp - (slp * slp))); for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; - slp = f_clip(slope[s], min_slope, max_slope); - phase_shift = slp * wdat->sample_rate; - - /* Lookup which table to use from frequency */ - wavedata_get_table(wdat, freq); - - /* Get samples from parabola and phase shifted inverted parabola, - and scale to compensate */ - output[s] = (wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift)) - / (8.0f * (slp - (slp * slp))); - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); } - } - plugin->phase = phase; -} - -static void -runTriangle_fasc_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Triangle* plugin = (Triangle*)instance; - - /* Frequency (array of float of length sample_count) */ - const float* frequency = plugin->frequency; - - /* Slope (float value) */ - float slope = *(plugin->slope); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - float min_slope = plugin->min_slope; - float max_slope = plugin->max_slope; - - float freq; - float phase_shift; - float scale; - - slope = f_clip(slope, min_slope, max_slope); - scale = 1.0f / (8.0f * (slope - (slope * slope))); - phase_shift = slope * wdat->sample_rate; - - for (uint32_t s = 0; s < sample_count; ++s) { - freq = frequency[s]; - - /* Lookup which table to use from frequency */ - wavedata_get_table(wdat, freq); - - /* Get samples from parabola and phase shifted inverted parabola, - and scale to compensate */ - output[s] = (wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift)) * scale; - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; + const float this_slope = slope[s * plugin->slope_is_cv]; + if (this_slope != last_slope) { + /* Slope changed, recalculate */ + last_slope = this_slope; + slp = f_clip(this_slope, min_slope, max_slope); + phase_shift = slp * wdat->sample_rate; + scale = 1.0f / (8.0f * (slp - (slp * slp))); } - } - plugin->phase = phase; -} - -static void -runTriangle_fcsa_oa(LV2_Handle instance, - uint32_t sample_count) -{ - Triangle* plugin = (Triangle*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Slope (array of float of length sample_count) */ - const float* slope = plugin->slope; - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - float min_slope = plugin->min_slope; - float max_slope = plugin->max_slope; - - float slp; - float phase_shift; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; ++s) { - slp = f_clip(slope[s], min_slope, max_slope); - phase_shift = slp * wdat->sample_rate; /* Get samples from parabola and phase shifted inverted parabola, and scale to compensate */ output[s] = (wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift)) - / (8.0f * (slp - (slp * slp))); + - wavedata_get_sample(wdat, phase + phase_shift)) * scale; /* Update phase, wrapping if necessary */ phase += wdat->frequency; @@ -240,62 +191,25 @@ runTriangle_fcsa_oa(LV2_Handle instance, plugin->phase = phase; } -static void -runTriangle_fcsc_oa(LV2_Handle instance, - uint32_t sample_count) +static const void* +extension_data(const char* uri) { - Triangle* plugin = (Triangle*)instance; - - /* Frequency (float value) */ - const float frequency = *(plugin->frequency); - - /* Slope (float value) */ - float slope = *(plugin->slope); - - /* Output (pointer to float value) */ - float* output = plugin->output; - - /* Instance data */ - Wavedata* wdat = &plugin->wdat; - float phase = plugin->phase; - float min_slope = plugin->min_slope; - float max_slope = plugin->max_slope; - - float scale; - float phase_shift; - - slope = f_clip(slope, min_slope, max_slope); - scale = 1.0f / (8.0f * (slope - (slope * slope))); - phase_shift = slope * wdat->sample_rate; - - wavedata_get_table(wdat, frequency); - - for (uint32_t s = 0; s < sample_count; ++s) { - /* Get samples from parabola and phase shifted inverted parabola, - and scale to compensate */ - output[s] = (wavedata_get_sample(wdat, phase) - - wavedata_get_sample(wdat, phase + phase_shift)) * scale; - - /* Update phase, wrapping if necessary */ - phase += wdat->frequency; - if (phase < 0.0f) { - phase += wdat->sample_rate; - } else if (phase > wdat->sample_rate) { - phase -= wdat->sample_rate; - } + static const LV2_Morph_Interface morph = { morph_port, NULL }; + if (!strcmp(uri, LV2_MORPH__interface)) { + return &morph; } - plugin->phase = phase; + return NULL; } static const LV2_Descriptor descriptor = { - "http://drobilla.net/plugins/blip/triangle", + "http://drobilla.net/plugins/blop/triangle", instantiate, connect_port, activate, - runTriangle_fcsc_oa, + run, NULL, cleanup, - NULL, + extension_data, }; LV2_SYMBOL_EXPORT const LV2_Descriptor* diff --git a/src/wavedata.c b/src/wavedata.c index ff955a1..e76047e 100644 --- a/src/wavedata.c +++ b/src/wavedata.c @@ -25,7 +25,7 @@ #include #include #include "lv2/lv2plug.in/ns/lv2core/lv2.h" -#include "blip_config.h" +#include "blop_config.h" #include "wavedata.h" int @@ -46,6 +46,7 @@ wavedata_load(Wavedata* w, bundle_path, lib_name, BLIP_SHLIB_EXT); void* handle = dlopen(lib_path, RTLD_NOW); + free(lib_path); if (handle) { int (*desc_func)(Wavedata*, unsigned long); @@ -57,7 +58,6 @@ wavedata_load(Wavedata* w, } } - free(lib_path); return retval; } diff --git a/src/wdatutil.c b/src/wdatutil.c index f7a277d..636981b 100644 --- a/src/wdatutil.c +++ b/src/wdatutil.c @@ -328,7 +328,7 @@ wavedata_write(Wavedata* w, fprintf(wdat_fp, "int\n"); fprintf( wdat_fp, - "blip_get_%s (Wavedata * w, double sample_rate, const char* bundle_path, const LV2_Feature* const* features)\n", + "blop_get_%s (Wavedata * w, double sample_rate, const char* bundle_path, const LV2_Feature* const* features)\n", data_name); fprintf(wdat_fp, "{\n"); fprintf(wdat_fp, "\tWavetable * t;\n"); @@ -611,18 +611,18 @@ generate_parabola(float* samples, float scale = 2.0f / (M_PI * M_PI); unsigned long i; unsigned long h; - double mhf; + //double mhf; double hf; - double k; - double m; + //double k; + //double m; double phase; double partial; double sign; if (gibbs_comp > 0.0f) { /* Degree of Gibbs Effect compensation */ - mhf = (double)harmonics; - k = M_PI * (double)gibbs_comp / mhf; + //mhf = (double)harmonics; + //k = M_PI * (double)gibbs_comp / mhf; for (i = 0; i < sample_count; i++) { samples[i] = 0.0f; @@ -635,7 +635,7 @@ generate_parabola(float* samples, /* Gibbs Effect compensation - Hamming window */ /* Modified slightly for smoother fade at highest frequencies */ - m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k); + //m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k); for (i = 0; i < sample_count; i++) { phase = (double)i * phase_scale; -- cgit v1.2.1