assigner
This commit is contained in:
parent
8661286e79
commit
5bfe06f721
|
@ -32,9 +32,5 @@
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_IS_SYNTH 1
|
#define DISTRHO_PLUGIN_IS_SYNTH 1
|
||||||
|
|
||||||
enum Parameters {
|
#define NUM_VOICES 8
|
||||||
bass,
|
|
||||||
kParameterCount
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
NAME = sonnenlicht
|
NAME = sonnenlicht
|
||||||
|
|
||||||
FILES_DSP = sonnenlicht.cpp
|
FILES_DSP = assigner.cpp sonnenlicht.cpp
|
||||||
include ../dpf/Makefile.plugins.mk
|
include ../dpf/Makefile.plugins.mk
|
||||||
|
|
||||||
TARGETS += vst2 vst3 jack lv2_dsp
|
TARGETS += vst2 vst3 jack lv2_dsp
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
sonnenlicht poly ensemble
|
||||||
|
|
||||||
|
Copyright 2025 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assigner.hpp"
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
|
void Assigner::dumpTables() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("table state is:\n");
|
||||||
|
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
||||||
|
uint8_t e = voiceTbl[i];
|
||||||
|
uint8_t a = noteTbl[e];
|
||||||
|
printf("%2d=%3d%c ", e, a & 0x7f, (a & 0x80) ? '^' : 'v');
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Assigner::Assigner() {
|
||||||
|
d_debug("assigner constructor");
|
||||||
|
|
||||||
|
// set up the assigner tables
|
||||||
|
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
||||||
|
voiceTbl[i] = i;
|
||||||
|
noteTbl[i] = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assigner::handleMidi(MidiEvent *ev) {
|
||||||
|
uint8_t status = ev->data[0];
|
||||||
|
switch (status & 0xf0) {
|
||||||
|
case 0x80:
|
||||||
|
noteOff(ev->data[1]);
|
||||||
|
dumpTables();
|
||||||
|
break;
|
||||||
|
case 0x90:
|
||||||
|
// dumpTables();
|
||||||
|
noteOn(ev->data[1]);
|
||||||
|
dumpTables();
|
||||||
|
break;
|
||||||
|
case 0xb0:
|
||||||
|
switch (ev->data[1]) {
|
||||||
|
// handle the following
|
||||||
|
// CC 1 - modwheel
|
||||||
|
// CC 64 - sustain
|
||||||
|
// possibly JU-06 CC values
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break; // nothing to do here except in special cases where we don't expect the host to pass on controls
|
||||||
|
case 0xc0: // program change
|
||||||
|
break;
|
||||||
|
case 0xe0: // pitch bend;
|
||||||
|
break;
|
||||||
|
case 0xf0: // sysex
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
d_debug("unhandled MIDI event, status %02x value %02x\n", ev->data[0], ev->data[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Assigner::noteOff(uint8_t note) {
|
||||||
|
d_debug("note off %3d", note);
|
||||||
|
|
||||||
|
uint8_t i, v;
|
||||||
|
// scan for note in table
|
||||||
|
for (i = 0; i < NUM_VOICES; i++) {
|
||||||
|
if ((noteTbl[voiceTbl[i]] & 0x7f) == note) break;
|
||||||
|
}
|
||||||
|
if (i == NUM_VOICES) return; // got note off for note that isn't in the table
|
||||||
|
|
||||||
|
// get the voice at this slot
|
||||||
|
// then move the rest down and place this at the end
|
||||||
|
// and mark the note for this voice as "off" by setting bit 7
|
||||||
|
v = voiceTbl[i];
|
||||||
|
memmove(voiceTbl + i, voiceTbl + i + 1, NUM_VOICES - i - 1);
|
||||||
|
voiceTbl[NUM_VOICES - 1] = v;
|
||||||
|
noteTbl[v] |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assigner::noteOn(uint8_t note) {
|
||||||
|
d_debug("note on %3d", note);
|
||||||
|
|
||||||
|
int8_t i, a, v;
|
||||||
|
|
||||||
|
// don't even attempt to steal voices
|
||||||
|
// by overwriting the last voice in the table
|
||||||
|
// we could actually do voice stealing
|
||||||
|
if ((noteTbl[voiceTbl[NUM_VOICES - 1]] & 0x80) == 0x00) {
|
||||||
|
d_debug("note table full");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop around the voices
|
||||||
|
for (i = NUM_VOICES - 1; i >= 0; i--) {
|
||||||
|
v = voiceTbl[i];
|
||||||
|
a = noteTbl[v];
|
||||||
|
|
||||||
|
// if this note is playing we've gone too far
|
||||||
|
// we need to back up a slot and consider it for use
|
||||||
|
if ((a & 0x80) == 0) {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// shunt them all up to the end
|
||||||
|
v = voiceTbl[i];
|
||||||
|
memmove(voiceTbl + 1, voiceTbl, i);
|
||||||
|
voiceTbl[0] = v;
|
||||||
|
break; // note is already playing in table
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((a & 0x7f) == note) {
|
||||||
|
memmove(voiceTbl + 1, voiceTbl, i);
|
||||||
|
voiceTbl[0] = v;
|
||||||
|
a &= 0x7f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// printf("at end, l=%d e=%d\n", l,e);
|
||||||
|
noteTbl[v] = note;
|
||||||
|
|
||||||
|
d_debug("send voice on %3d to voice %d", note, v);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
sonnenlicht poly ensemble
|
||||||
|
|
||||||
|
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASSIGNER_HPP
|
||||||
|
#define _ASSIGNER_HPP
|
||||||
|
|
||||||
|
#include "DistrhoPlugin.hpp"
|
||||||
|
|
||||||
|
class Assigner {
|
||||||
|
public:
|
||||||
|
Assigner();
|
||||||
|
void handleMidi(MidiEvent *ev);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void noteOn(uint8_t note); // incoming note on (or off, if velocity = 0)
|
||||||
|
void noteOff(uint8_t note); // incoming note off
|
||||||
|
uint8_t voiceTbl[NUM_VOICES]; // voices in order of use
|
||||||
|
uint8_t noteTbl[NUM_VOICES]; // note played by voice
|
||||||
|
|
||||||
|
void dumpTables();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,34 +18,48 @@
|
||||||
|
|
||||||
#include "sonnenlicht.hpp"
|
#include "sonnenlicht.hpp"
|
||||||
|
|
||||||
|
#include "assigner.hpp"
|
||||||
|
|
||||||
START_NAMESPACE_DISTRHO
|
START_NAMESPACE_DISTRHO
|
||||||
|
|
||||||
Sonnenlicht::Sonnenlicht() : Plugin(kParameterCount, 0, 0), fSampleRate(getSampleRate()) {
|
Sonnenlicht::Sonnenlicht() : Plugin(kParameterCount, 0, 0), fSampleRate(getSampleRate()) {
|
||||||
printf("initialiser called\n");
|
printf("initialiser called\n");
|
||||||
w = 440.0 / fSampleRate;
|
w = 440.0 / fSampleRate;
|
||||||
phase = 0;
|
phase = 0;
|
||||||
|
assigner = new Assigner;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sonnenlicht::~Sonnenlicht() {
|
||||||
|
delete assigner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonnenlicht::setParameterValue(uint32_t index, float value) {
|
||||||
|
printf("got parameter %d, %f\n", index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonnenlicht::initAudioPort(bool input, uint32_t index, AudioPort& port) {
|
||||||
|
port.groupId = kPortGroupStereo;
|
||||||
|
Plugin::initAudioPort(input, index, port);
|
||||||
|
|
||||||
|
if (!input && index == 0) port.symbol = "Left";
|
||||||
|
if (!input && index == 1) port.symbol = "Right";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonnenlicht::activate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonnenlicht::deactivate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sonnenlicht::initParameter(uint32_t index, Parameter& parameter) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sonnenlicht::run(const float**, float** outputs, uint32_t frames,
|
void Sonnenlicht::run(const float**, float** outputs, uint32_t frames,
|
||||||
const MidiEvent* midiEvents, uint32_t midiEventCount) {
|
const MidiEvent* ev, uint32_t evCount) {
|
||||||
|
for (uint32_t i = 0; i < evCount; i++) {
|
||||||
if (midiEventCount > 0) {
|
//printf("%3d: %02x %02x\n", i, midiEvents[i].data[0], midiEvents[i].data[1]);
|
||||||
for (uint32_t i=0; i < midiEventCount; i++ ) {
|
assigner->handleMidi((MidiEvent *)&ev[i]);
|
||||||
const uint8_t *data = midiEvents[i].data;
|
|
||||||
const uint8_t status = data[0] & 0xf0;
|
|
||||||
|
|
||||||
|
|
||||||
if (status == 0x90) {
|
|
||||||
w = (261.6 * (powf(2, (data[1]-60)/12.0f)))/fSampleRate;
|
|
||||||
printf("set w to %f\n", w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < frames; i++) {
|
|
||||||
phase += w;
|
|
||||||
if (phase > 1) phase -= 1;
|
|
||||||
outputs[0][i] = phase - 0.5;
|
|
||||||
outputs[1][i] = phase - 0.5;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Sonnenlicht reverb plugin
|
sonnenlicht poly ensemble
|
||||||
|
|
||||||
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||||
|
|
||||||
|
@ -20,17 +20,18 @@
|
||||||
#define SONNENLICHT_HPP
|
#define SONNENLICHT_HPP
|
||||||
|
|
||||||
#include "DistrhoPlugin.hpp"
|
#include "DistrhoPlugin.hpp"
|
||||||
|
#include "assigner.hpp"
|
||||||
|
|
||||||
START_NAMESPACE_DISTRHO
|
START_NAMESPACE_DISTRHO
|
||||||
|
|
||||||
class Sonnenlicht : public Plugin {
|
class Sonnenlicht : public Plugin {
|
||||||
public:
|
public:
|
||||||
enum Parameters {
|
enum Parameters {
|
||||||
bass,
|
|
||||||
kParameterCount
|
kParameterCount
|
||||||
};
|
};
|
||||||
|
|
||||||
Sonnenlicht();
|
Sonnenlicht();
|
||||||
|
~Sonnenlicht();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char *getLabel() const override { return "sonnenlicht"; }
|
const char *getLabel() const override { return "sonnenlicht"; }
|
||||||
|
@ -42,17 +43,21 @@ class Sonnenlicht : public Plugin {
|
||||||
uint32_t getVersion() const override { return d_version(1, 0, 0); }
|
uint32_t getVersion() const override { return d_version(1, 0, 0); }
|
||||||
int64_t getUniqueId() const override { return d_cconst('S', 'L', 'C', 'T'); }
|
int64_t getUniqueId() const override { return d_cconst('S', 'L', 'C', 'T'); }
|
||||||
|
|
||||||
|
void initParameter(uint32_t index, Parameter ¶meter) override;
|
||||||
|
void setParameterValue(uint32_t index, float value) override;
|
||||||
|
|
||||||
// Initialisation
|
// Initialisation
|
||||||
// void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
|
void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
|
||||||
|
|
||||||
// Processing
|
// Processing
|
||||||
// void activate() override;
|
void activate() override;
|
||||||
// void deactivate() override;
|
void deactivate() override;
|
||||||
|
|
||||||
void run(const float **, float **outputs, uint32_t frames,
|
void run(const float **, float **outputs, uint32_t frames,
|
||||||
const MidiEvent *midiEvents, uint32_t midiEventCount) override;
|
const MidiEvent *midiEvents, uint32_t midiEventCount) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Assigner *assigner;
|
||||||
double fSampleRate;
|
double fSampleRate;
|
||||||
float phase;
|
float phase;
|
||||||
float w;
|
float w;
|
||||||
|
|
Loading…
Reference in New Issue