aboutsummaryrefslogtreecommitdiffstats
path: root/src/adenv_lvl.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-06-09 14:34:20 +0000
committerDavid Robillard <d@drobilla.net>2006-06-09 14:34:20 +0000
commit1ad3c632e91211ae84bc738eebd8d4a8318707c9 (patch)
treeb060300cf35069b227851f62f0957edb9006e989 /src/adenv_lvl.c
Added omins
git-svn-id: http://svn.drobilla.net/lad/omins@8 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/adenv_lvl.c')
-rw-r--r--src/adenv_lvl.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/src/adenv_lvl.c b/src/adenv_lvl.c
new file mode 100644
index 0000000..10c8378
--- /dev/null
+++ b/src/adenv_lvl.c
@@ -0,0 +1,461 @@
+/*
+ adenv.c - A LADSPA plugin to generate percussive (i.e no sustain time), linear AD envelopes.
+ This one takes in levels to make filter sweeps/etc easier.
+
+ Copyright (C) 2005 Loki Davison
+ based of DADSR by Mike Rawes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define _XOPEN_SOURCE 500 /* strdup */
+#include <stdlib.h>
+#include <ladspa.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifdef ENABLE_NLS
+# include <locale.h>
+# define G_(s) gettext(s)
+#else
+# define G_(s) (s)
+#endif
+#define G_NOP(s) s
+
+#define ADENVLVL_BASE_ID 2662
+#define ADENVLVL_VARIANT_COUNT 1
+
+#define ADENVLVL_GATE 0
+#define ADENVLVL_TRIGGER 1
+#define ADENVLVL_START_LEVEL 2
+#define ADENVLVL_ATTACK_LEVEL 3
+#define ADENVLVL_DECAY_LEVEL 4
+#define ADENVLVL_ATTACK 5
+#define ADENVLVL_DECAY 6
+#define ADENVLVL_OUTPUT 7
+#define ADENVLVL_RESET 8
+
+LADSPA_Descriptor **dahdsr_descriptors = 0;
+
+typedef enum {
+ IDLE,
+ ATTACK,
+ DECAY,
+} ADENVLVLState;
+
+typedef struct {
+ LADSPA_Data *gate;
+ LADSPA_Data *trigger;
+ LADSPA_Data *attack;
+ LADSPA_Data *reset;
+ LADSPA_Data *decay;
+ LADSPA_Data *start_level;
+ LADSPA_Data *attack_level;
+ LADSPA_Data *decay_level;
+ LADSPA_Data *output;
+ LADSPA_Data srate;
+ LADSPA_Data inv_srate;
+ LADSPA_Data last_gate;
+ LADSPA_Data last_trigger;
+ LADSPA_Data last_reset;
+ LADSPA_Data level;
+ ADENVLVLState state;
+ unsigned long samples;
+} Dahdsr;
+
+const LADSPA_Descriptor *
+ladspa_descriptor(unsigned long index)
+{
+ if (index < ADENVLVL_VARIANT_COUNT)
+ return dahdsr_descriptors[index];
+
+ return 0;
+}
+
+void
+cleanupDahdsr(LADSPA_Handle instance)
+{
+ free(instance);
+}
+
+void
+connectPortDahdsr(LADSPA_Handle instance,
+ unsigned long port, LADSPA_Data * data)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ switch (port) {
+ case ADENVLVL_GATE:
+ plugin->gate = data;
+ break;
+ case ADENVLVL_TRIGGER:
+ plugin->trigger = data;
+ break;
+ case ADENVLVL_START_LEVEL:
+ plugin->start_level = data;
+ break;
+ case ADENVLVL_ATTACK_LEVEL:
+ plugin->attack_level = data;
+ break;
+ case ADENVLVL_DECAY_LEVEL:
+ plugin->decay_level = data;
+ break;
+ case ADENVLVL_ATTACK:
+ plugin->attack = data;
+ break;
+ case ADENVLVL_DECAY:
+ plugin->decay = data;
+ break;
+ case ADENVLVL_RESET:
+ plugin->reset = data;
+ break;
+ case ADENVLVL_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+LADSPA_Handle
+instantiateDahdsr(const LADSPA_Descriptor * descriptor,
+ unsigned long sample_rate)
+{
+ Dahdsr *plugin = (Dahdsr *) malloc(sizeof(Dahdsr));
+
+ plugin->srate = (LADSPA_Data) sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LADSPA_Handle) plugin;
+}
+
+void
+activateDahdsr(LADSPA_Handle instance)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->last_reset = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+void
+runDahdsr_Control(LADSPA_Handle instance, unsigned long sample_count)
+{
+ Dahdsr *plugin = (Dahdsr *) instance;
+
+ /* Gate */
+ LADSPA_Data *gate = plugin->gate;
+
+ /* Trigger */
+ LADSPA_Data *trigger = plugin->trigger;
+
+ /* Reset */
+ LADSPA_Data *reset = plugin->reset;
+
+ /* Start Level */
+ LADSPA_Data start_level = *(plugin->start_level);
+
+ /* Attack Level */
+ LADSPA_Data attack_level = *(plugin->attack_level);
+
+ /* Decay Level */
+ LADSPA_Data decay_level = *(plugin->decay_level);
+
+ /* Attack Time (s) */
+ LADSPA_Data attack = *(plugin->attack);
+
+ /* Decay Time (s) */
+ LADSPA_Data decay = *(plugin->decay);
+
+ /* Envelope Out */
+ LADSPA_Data *output = plugin->output;
+
+ /* Instance Data */
+ LADSPA_Data srate = plugin->srate;
+ LADSPA_Data inv_srate = plugin->inv_srate;
+ LADSPA_Data last_gate = plugin->last_gate;
+ LADSPA_Data last_trigger = plugin->last_trigger;
+ LADSPA_Data last_reset = plugin->last_reset;
+ LADSPA_Data level = plugin->level;
+ ADENVLVLState state = plugin->state;
+ unsigned long samples = plugin->samples;
+
+ LADSPA_Data gat, trg, att, dec;
+ LADSPA_Data elapsed;
+ unsigned long s;
+
+ /* Convert times into rates */
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ /* cuse's formula ...
+ * ReleaseCoeff = (ln(EndLevel) - ln(StartLevel)) / (EnvelopeDuration * SampleRate)
+ *
+ * while (currentSample < endSample) Level += Level * ReleaseCoeff;
+ */
+ /* check params don't cause div by zero */
+ if (start_level == 0) {
+ start_level = 0.0000001;
+ }
+ if (attack_level == 0) {
+ attack_level = 0.0000001;
+ }
+ if (decay_level == 0) {
+ decay_level = 0.0000001;
+ }
+ LADSPA_Data ReleaseCoeff_att =
+ (log(attack_level) - log(start_level)) / (attack * srate);
+ LADSPA_Data ReleaseCoeff_dec =
+ (log(decay_level) - log(attack_level)) / (decay * srate);
+
+ for (s = 0; s < sample_count; s++) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f)) ||
+ (gat > 0.0f && !(last_gate > 0.0f))) {
+ //fprintf(stderr, "triggered in control \n");
+ if (att < srate) {
+ state = ATTACK;
+ }
+ samples = 0;
+ }
+ /* if we got a reset */
+
+ if (reset[s] > 0.0f && !(last_reset > 0.0f)) {
+ level = start_level;
+ /*fprintf(stderr, "got reset start level %f \n", start_level); */
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ /* might need to fix this... */
+ break;
+ case ATTACK:
+ /* fix level adding prob */
+ if (samples == 0) {
+ level = start_level;
+ }
+ samples++;
+ elapsed = (LADSPA_Data) samples *att;
+
+ if (elapsed > 1.0f) {
+ state = DECAY;
+ samples = 0;
+ //fprintf(stderr, "finished attack, RC %f, level %f attack_level %f start %f\n", ReleaseCoeff_att, level, attack_level, start_level);
+ } else {
+ level += level * ReleaseCoeff_att;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (LADSPA_Data) samples *dec;
+
+ if (elapsed > 1.0f) {
+ //fprintf(stderr, "finished decay, RC %f , level %f decay_level %f start %f\n", ReleaseCoeff_dec, level, decay_level, start_level);
+ state = IDLE;
+ samples = 0;
+ } else {
+ level += level * ReleaseCoeff_dec;
+ }
+ break;
+ default:
+ /* Should never happen */
+ fprintf(stderr, "bugger!!!");
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ last_gate = gat;
+ last_trigger = trg;
+ last_reset = reset[s];
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->last_reset = last_reset;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+void
+_init(void)
+{
+ static const unsigned long ids[] = { ADENVLVL_BASE_ID };
+ static const char *labels[] = { "adenv_lvl" };
+ static const char *names[] =
+ { G_NOP("Percussive AD Envelope with levels") };
+ char **port_names;
+ LADSPA_PortDescriptor *port_descriptors;
+ LADSPA_PortRangeHint *port_range_hints;
+ LADSPA_Descriptor *descriptor;
+
+ LADSPA_PortDescriptor gate_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO };
+ LADSPA_PortDescriptor trigger_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO };
+ LADSPA_PortDescriptor start_level_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL };
+ LADSPA_PortDescriptor attack_level_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL };
+ LADSPA_PortDescriptor decay_level_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL };
+ LADSPA_PortDescriptor attack_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL };
+ LADSPA_PortDescriptor decay_port_descriptors[] =
+ { LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL };
+ LADSPA_PortDescriptor output_port_descriptors[] =
+ { LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO };
+
+ void (*run_functions[]) (LADSPA_Handle, unsigned long) = {
+ runDahdsr_Control};
+
+#ifdef ENABLE_NLS
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+
+ dahdsr_descriptors =
+ (LADSPA_Descriptor **) calloc(ADENVLVL_VARIANT_COUNT,
+ sizeof(LADSPA_Descriptor));
+
+ if (dahdsr_descriptors) {
+ int i = 0;
+
+ dahdsr_descriptors[i] =
+ (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor));
+ descriptor = dahdsr_descriptors[i];
+ if (descriptor) {
+ descriptor->UniqueID = ids[i];
+ descriptor->Label = labels[i];
+ descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+ descriptor->Name = G_(names[i]);
+ descriptor->Maker =
+ "Loki Davison <ltdav1[at]student.monash.edu.au>";
+ descriptor->Copyright = "GPL";
+
+ descriptor->PortCount = 9;
+
+ port_descriptors =
+ (LADSPA_PortDescriptor *) calloc(9,
+ sizeof
+ (LADSPA_PortDescriptor));
+ descriptor->PortDescriptors =
+ (const LADSPA_PortDescriptor *)port_descriptors;
+
+ port_range_hints =
+ (LADSPA_PortRangeHint *) calloc(9,
+ sizeof(LADSPA_PortRangeHint));
+ descriptor->PortRangeHints =
+ (const LADSPA_PortRangeHint *)port_range_hints;
+
+ port_names = (char **)calloc(9, sizeof(char *));
+ descriptor->PortNames = (const char **)port_names;
+
+ /* Parameters for Gate */
+ port_descriptors[ADENVLVL_GATE] = gate_port_descriptors[i];
+ port_names[ADENVLVL_GATE] = G_("Gate");
+ port_range_hints[ADENVLVL_GATE].HintDescriptor =
+ LADSPA_HINT_TOGGLED;
+
+ /* Parameters for Trigger */
+ port_descriptors[ADENVLVL_TRIGGER] = trigger_port_descriptors[i];
+ port_names[ADENVLVL_TRIGGER] = G_("Trigger");
+ port_range_hints[ADENVLVL_TRIGGER].HintDescriptor =
+ LADSPA_HINT_TOGGLED;
+ /* Parameters for Reset */
+ port_descriptors[ADENVLVL_RESET] = trigger_port_descriptors[i];
+ port_names[ADENVLVL_RESET] = G_("Reset Level");
+ port_range_hints[ADENVLVL_RESET].HintDescriptor =
+ LADSPA_HINT_TOGGLED;
+
+ /* Parameters for Attack Time (s) */
+ port_descriptors[ADENVLVL_ATTACK] = attack_port_descriptors[i];
+ port_names[ADENVLVL_ATTACK] = G_("Attack Time (s)");
+ port_range_hints[ADENVLVL_ATTACK].HintDescriptor =
+ LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_DEFAULT_MINIMUM;
+ port_range_hints[ADENVLVL_ATTACK].LowerBound = 0.0f;
+
+ /* Parameters for Start Level */
+ port_descriptors[ADENVLVL_START_LEVEL] =
+ start_level_port_descriptors[i];
+ port_names[ADENVLVL_START_LEVEL] = G_("Initial Level");
+ port_range_hints[ADENVLVL_START_LEVEL].HintDescriptor =
+ LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_DEFAULT_MINIMUM;
+ port_range_hints[ADENVLVL_START_LEVEL].LowerBound = 0.0f;
+
+ /* Parameters for Attack to level (s) */
+ port_descriptors[ADENVLVL_ATTACK_LEVEL] =
+ attack_level_port_descriptors[i];
+ port_names[ADENVLVL_ATTACK_LEVEL] = G_("Attack to Level");
+ port_range_hints[ADENVLVL_ATTACK_LEVEL].HintDescriptor =
+ LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_DEFAULT_1;
+ port_range_hints[ADENVLVL_ATTACK_LEVEL].LowerBound = 0.0f;
+
+ /* Parameters for Decay to level (s) */
+ port_descriptors[ADENVLVL_DECAY_LEVEL] =
+ decay_level_port_descriptors[i];
+ port_names[ADENVLVL_DECAY_LEVEL] = G_("Decay to Level");
+ port_range_hints[ADENVLVL_DECAY_LEVEL].HintDescriptor =
+ LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_DEFAULT_MINIMUM;
+ port_range_hints[ADENVLVL_DECAY_LEVEL].LowerBound = 0.0f;
+
+ /* Parameters for Decay Time (s) */
+ port_descriptors[ADENVLVL_DECAY] = decay_port_descriptors[i];
+ port_names[ADENVLVL_DECAY] = G_("Decay Time (s)");
+ port_range_hints[ADENVLVL_DECAY].HintDescriptor =
+ LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_DEFAULT_MINIMUM;
+ port_range_hints[ADENVLVL_DECAY].LowerBound = 0.0f;
+
+ /* Parameters for Envelope Out */
+ port_descriptors[ADENVLVL_OUTPUT] = output_port_descriptors[i];
+ port_names[ADENVLVL_OUTPUT] = G_("Envelope Out");
+ port_range_hints[ADENVLVL_OUTPUT].HintDescriptor = 0;
+
+ descriptor->activate = activateDahdsr;
+ descriptor->cleanup = cleanupDahdsr;
+ descriptor->connect_port = connectPortDahdsr;
+ descriptor->deactivate = NULL;
+ descriptor->instantiate = instantiateDahdsr;
+ descriptor->run = run_functions[i];
+ descriptor->run_adding = NULL;
+ descriptor->set_run_adding_gain = NULL;
+ }
+ }
+
+}
+
+void
+_fini(void)
+{
+ LADSPA_Descriptor *descriptor;
+
+ if (dahdsr_descriptors) {
+ descriptor = dahdsr_descriptors[0];
+ if (descriptor) {
+ free((LADSPA_PortDescriptor *) descriptor->PortDescriptors);
+ free((char **)descriptor->PortNames);
+ free((LADSPA_PortRangeHint *) descriptor->PortRangeHints);
+ free(descriptor);
+ }
+ free(dahdsr_descriptors);
+ }
+}