aboutsummaryrefslogtreecommitdiffstats
path: root/src/dahdsr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dahdsr.c')
-rw-r--r--src/dahdsr.c450
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*