diff options
Diffstat (limited to 'src/dahdsr.c')
-rw-r--r-- | src/dahdsr.c | 450 |
1 files changed, 86 insertions, 364 deletions
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 <stdlib.h> +#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* |