From e550736dbb862d8333a4d7f2ede9804a3d48326c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 3 Oct 2011 05:22:14 +0000 Subject: Add 'blip', an LV2 port of the LADSPA 'blop' collection. git-svn-id: http://svn.drobilla.net/lad/trunk/plugins/blip.lv2@3525 a436a847-0d15-0410-975c-d299462d15a1 --- src/sequencer.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/sequencer.c (limited to 'src/sequencer.c') diff --git a/src/sequencer.c b/src/sequencer.c new file mode 100644 index 0000000..7b39a50 --- /dev/null +++ b/src/sequencer.c @@ -0,0 +1,193 @@ +/* + An LV2 plugin to simulate an analogue style step sequencer. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 3 of the License, or + (at your option) any later version. + + This software 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 software. If not, see . +*/ + +#include +#include +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "common.h" + +#define SEQUENCER_GATE 0 +#define SEQUENCER_TRIGGER 1 +#define SEQUENCER_LOOP_POINT 2 +#define SEQUENCER_RESET 3 +#define SEQUENCER_VALUE_GATE_CLOSED 4 +#define SEQUENCER_VALUE_START 5 +#define SEQUENCER_OUTPUT (SEQUENCER_MAX_INPUTS + 5) + +typedef struct { + float* gate; + float* trigger; + float* loop_steps; + float* reset; + float* value_gate_closed; + float* values[SEQUENCER_MAX_INPUTS]; + float* output; + float srate; + float inv_srate; + float last_gate; + float last_trigger; + float last_value; + unsigned int step_index; +} Sequencer; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Sequencer* plugin = (Sequencer*)instance; + + switch (port) { + case SEQUENCER_GATE: + plugin->gate = data; + break; + case SEQUENCER_TRIGGER: + plugin->trigger = data; + break; + case SEQUENCER_LOOP_POINT: + plugin->loop_steps = data; + break; + case SEQUENCER_OUTPUT: + plugin->output = data; + break; + case SEQUENCER_RESET: + plugin->reset = data; + break; + case SEQUENCER_VALUE_GATE_CLOSED: + plugin->value_gate_closed = data; + break; + default: + if (port >= SEQUENCER_VALUE_START && port < SEQUENCER_OUTPUT) { + plugin->values[port - SEQUENCER_VALUE_START] = data; + } + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Sequencer* plugin = (Sequencer*)malloc(sizeof(Sequencer)); + + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Sequencer* plugin = (Sequencer*)instance; + + plugin->last_gate = 0.0f; + plugin->last_trigger = 0.0f; + plugin->last_value = 0.0f; + plugin->step_index = 0; +} + +static void +runSequencer(LV2_Handle instance, + uint32_t sample_count) +{ + Sequencer* plugin = (Sequencer*)instance; + + /* Gate */ + float* gate = plugin->gate; + + /* Step Trigger */ + float* trigger = plugin->trigger; + + /* Loop Steps */ + float loop_steps = *(plugin->loop_steps); + + /* Reset to Value on Gate Close */ + float reset = *(plugin->reset); + + /* Value used when gate closed */ + float value_gate_closed = *(plugin->value_gate_closed); + + /* Step Values */ + float values[SEQUENCER_MAX_INPUTS]; + + /* Output */ + float* output = plugin->output; + + float last_gate = plugin->last_gate; + float last_trigger = plugin->last_trigger; + float last_value = plugin->last_value; + + unsigned int step_index = plugin->step_index; + unsigned int loop_index = LRINTF(loop_steps); + int rst = LRINTF(reset); + int i; + + loop_index = loop_index == 0 ? 1 : loop_index; + loop_index = (loop_index > SEQUENCER_MAX_INPUTS) + ? SEQUENCER_MAX_INPUTS + : loop_index; + + for (i = 0; i < SEQUENCER_MAX_INPUTS; i++) { + values[i] = *(plugin->values[i]); + } + + for (uint32_t s = 0; s < sample_count; ++s) { + if (gate[s] > 0.0f) { + if (trigger[s] > 0.0f && !(last_trigger > 0.0f)) { + if (last_gate > 0.0f) { + step_index++; + if (step_index >= loop_index) { + step_index = 0; + } + } else { + step_index = 0; + } + } + + output[s] = values[step_index]; + + last_value = values[step_index]; + } else { + if (rst) { + output[s] = value_gate_closed; + } else { + output[s] = last_value; + } + + step_index = 0; + } + last_gate = gate[s]; + last_trigger = trigger[s]; + } + + plugin->last_gate = last_gate; + plugin->last_trigger = last_trigger; + plugin->last_value = last_value; + plugin->step_index = step_index; +} -- cgit v1.2.1