aboutsummaryrefslogtreecommitdiffstats
path: root/src/sequencer.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-10-03 05:22:14 +0000
committerDavid Robillard <d@drobilla.net>2011-10-03 05:22:14 +0000
commite550736dbb862d8333a4d7f2ede9804a3d48326c (patch)
tree185b6f0483cbfe2fae87bb61b0e123fb2353b5d5 /src/sequencer.c
downloadblop.lv2-e550736dbb862d8333a4d7f2ede9804a3d48326c.tar.gz
blop.lv2-e550736dbb862d8333a4d7f2ede9804a3d48326c.tar.bz2
blop.lv2-e550736dbb862d8333a4d7f2ede9804a3d48326c.zip
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
Diffstat (limited to 'src/sequencer.c')
-rw-r--r--src/sequencer.c193
1 files changed, 193 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}