From 766e4f7a2bc04820745507166750dcb0b45b8d7f Mon Sep 17 00:00:00 2001 From: Gordon JC Pearce Date: Tue, 3 Sep 2024 12:42:16 +0100 Subject: [PATCH] voice assignment --- plugin/chassis.cpp | 138 +++++++++++++-------------------------------- plugin/chassis.hpp | 24 ++++---- plugin/voice.cpp | 17 ++++++ plugin/voice.hpp | 36 ++++++++++++ 4 files changed, 102 insertions(+), 113 deletions(-) create mode 100644 plugin/voice.cpp create mode 100644 plugin/voice.hpp diff --git a/plugin/chassis.cpp b/plugin/chassis.cpp index 779a71b..d87d2d5 100644 --- a/plugin/chassis.cpp +++ b/plugin/chassis.cpp @@ -1,5 +1,5 @@ /* - Chassis reverb plugin + Chassis softsynth framework Copyright 2024 Gordon JC Pearce @@ -18,80 +18,14 @@ #include "chassis.hpp" -SVF::SVF(float cutoff = 0, float q = 0, float samplerate = 0) { - z1 = z2 = 0; - setFreq(cutoff, q, samplerate); -} - -void SVF::setFreq(float cutoff, float q, float samplerate) { - z1 = z2 = 0; - - printf("called with %f %f %f\n", cutoff, q, samplerate); - w = 2 * tan(3.14159 * (cutoff / samplerate)); - a = w / q; - b = w * w; - - // corrected SVF params, per Fons Adriaensen - c1 = (a + b) / (1 + a / 2 + b / 4); - c2 = b / (a + b); - - d0 = c1 * c2 / 4; - - printf("c1 %f c2 %f d0 %f\n", c1, c2, d0); -} - -inline float SVF::lpStep(float in) { - x = in - z1 - z2; - z2 += c2 * z1; - z1 += c1 * x; - return d0 * x + z2; -} - START_NAMESPACE_DISTRHO Chassis::Chassis() : Plugin(kParameterCount, 0, 0) { // one parameter, no programs, no states - // lowpass = new float[getBufferSize()]; - // ram = new int16_t[16384]; - - // bzero(lowpass, sizeof(float) * getBufferSize()); - // bzero(ram, sizeof(int16_t) * 16384); - - // f1.setFreq(5916, .6572, getSampleRate()); - // f2.setFreq(9458, 2.536, getSampleRate()); } // Initialisation functions void Chassis::initParameter(uint32_t index, Parameter ¶meter) { - if (index == p_saw) { - parameter.hints = kParameterIsAutomatable | kParameterIsInteger; - parameter.name = "Saw"; - parameter.symbol = "saw"; - parameter.ranges.max = 1.0f; - } - if (index == p_sqr) { - parameter.hints = kParameterIsAutomatable | kParameterIsInteger; - parameter.name = "Square"; - parameter.symbol = "sqr"; - parameter.ranges.max = 4.0f; - } - - if (index == p_sublev) { - parameter.hints = kParameterIsAutomatable; - parameter.name = "Sub"; - parameter.symbol = "sub"; - parameter.ranges.def = 20.0f; - parameter.ranges.min = 1.0f; - parameter.ranges.max = 64.0f; - } - if (index == paramProgram) { - parameter.hints = kParameterIsAutomatable; - parameter.name = "prog"; - parameter.symbol = "prog"; - parameter.ranges.def = 1.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 1.0f; - } } void Chassis::setParameterValue(uint32_t index, float value) { @@ -123,67 +57,71 @@ void Chassis::loadProgram(uint32_t index) { void Chassis::activate() { // calculate filter coefficients printf("called activate()\n"); - for (uint32_t i = 0; i< NUM_VOICES; i++ ) { - assign[i] = 0x80 | i; - - } } void Chassis::deactivate() { // zero out the outputs, maybe printf("called deactivate()\n"); - printf("%02x", assign[1]); + // printf("%02x", assign[1]); } void Chassis::noteOn(uint8_t note) { - for (uint32_t i = 0; i < NUM_VOICES; i++) { - printf("note on, finding free voice in %02x for %d\n", assign[i], note); - if (assign[i] & 0x80) { // top bit is voice free flag - assign[i] &= 0x7f; // enable - printf("voice %d would be set to note %d\n", assign[i], note); + uint32_t i; + for (i = 0; i < NUM_VOICES; i++) { + // printf("note on, finding free voice in %02x for %d\n", assign[i], note); + if (voice[i].state == V_OFF) { // top bit is voice free flag + voice[i].state = V_ON; // enable + voice[i].note = note; + printf("voice %d set to note %d\n", i, note); break; } - - if (i == NUM_VOICES) { // didn't find a free voice - uint32_t v = assign[0]; - memmove(assign, assign + 1, NUM_VOICES - 1); // shunt all voices down by one - assign[NUM_VOICES - 1] = v; // oldest voice goes at the top of the queue - printf("no free voices, reused %d for note %d\n", v, note); - } } - printf("note table is now "); - for (uint32_t i=0; i < NUM_VOICES; i++ ) { - printf("%02x = ", assign[i]); + if (i == NUM_VOICES) { // didn't find a free voice + // Voice v = voice[0]; + memmove(voice, voice + 1, sizeof(Voice) * (NUM_VOICES - 1)); // shunt all voices down by one + // lessvoice[NUM_VOICES - 1] = v; // oldest voice goes at the top of the queue + voice[NUM_VOICES - 1].note = note; // set note, assume state is still set + printf("no free voices, reused %d for note %d\n", 0, note); + } + + printf("note table is now\n"); + for (i = 0; i < NUM_VOICES; i++) { + printf("%2d = %3d %01x\n", i, voice[i].note, voice[i].state); } printf("----------------------------\n"); - } -/* void Chassis::noteOff(uint8_t note) { - uint32_t v; printf("note off called for %3d\n", note); + printf("trying voice "); for (uint32_t i = 0; i < NUM_VOICES; i++) { - v = assign[i]; - printf("trying voice %02x\n", v); - if (v < 0x80) { - printf("note %02x is playing\n", v); - + printf("%02x ", i); + + if (voice[i].note == note && voice[i].state != V_OFF) { + printf("note off for %d playing %02x\n", i, note); + //memmove(voice + i, voice + i + 1, sizeof(Voice) * (NUM_VOICES - i)); + voice[i].state = V_OFF; + break; } - } - + printf("\n note table is now\n"); + for (uint32_t i = 0; i < NUM_VOICES; i++) { + printf("%2d = %3d %01x\n", i, voice[i].note, voice[i].state); + } } -*/ + void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *MidiEvents, uint32_t midiEventCount) { - if (midiEventCount > 0) printf("\n--------------------\n"); + // if (midiEventCount > 0) printf("\n--------------------\n"); for (uint32_t i = 0; i < midiEventCount; i++) { - printf("%4d %02x %02x\n", MidiEvents[i].frame, MidiEvents[i].data[0], MidiEvents[i].data[1]); + // printf("%4d %02x %02x\n", MidiEvents[i].frame, MidiEvents[i].data[0], MidiEvents[i].data[1]); if (MidiEvents[i].data[0] == 0x90) { noteOn(MidiEvents[i].data[1]); } + if (MidiEvents[i].data[0] == 0x80) { + noteOff(MidiEvents[i].data[1]); + } } } diff --git a/plugin/chassis.hpp b/plugin/chassis.hpp index e2a2adf..67528dd 100644 --- a/plugin/chassis.hpp +++ b/plugin/chassis.hpp @@ -1,5 +1,5 @@ /* - Chassis reverb plugin + Chassis softsynth framework Copyright 2024 Gordon JC Pearce @@ -16,12 +16,13 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef BARRVERB_HPP -#define BARRVERB_HPP +#ifndef _CHASSIS_HPP +#define _CHASSIS_HPP #define NUM_VOICES 8 #include "DistrhoPlugin.hpp" +#include "voice.hpp" class SVF { public: @@ -40,8 +41,6 @@ START_NAMESPACE_DISTRHO class Chassis : public Plugin { public: enum Parameters { - p_saw, p_sqr, p_sublev, - paramProgram, kParameterCount }; @@ -64,25 +63,24 @@ class Chassis : public Plugin { void setParameterValue(uint32_t index, float value) override; float getParameterValue(uint32_t index) const override; - // void initProgramName(uint32_t index, String &programName) override; - // void loadProgram(uint32_t index) override; + // void initProgramName(uint32_t index, String &programName) override; + // void loadProgram(uint32_t index) override; // Processing void activate() override; void deactivate() override; void run(const float **, float **outputs, uint32_t frames, const MidiEvent *MidiEvents, uint32_t midiEventCount) override; - -void noteOn(uint8_t note); + void noteOn(uint8_t note); + void noteOff(uint8_t note); private: - uint8_t assign[NUM_VOICES]; // assigner table - - + Voice voice[NUM_VOICES]; + //uint32_t DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Chassis); }; END_NAMESPACE_DISTRHO -#endif // BARRVERB_HPP +#endif // _CHASSIS_HPP diff --git a/plugin/voice.cpp b/plugin/voice.cpp new file mode 100644 index 0000000..b574b87 --- /dev/null +++ b/plugin/voice.cpp @@ -0,0 +1,17 @@ +/* + Chassis softsynth framework + + Copyright 2024 Gordon JC Pearce + + 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. +*/ diff --git a/plugin/voice.hpp b/plugin/voice.hpp new file mode 100644 index 0000000..1462678 --- /dev/null +++ b/plugin/voice.hpp @@ -0,0 +1,36 @@ +/* + Chassis softsynth framework + + Copyright 2024 Gordon JC Pearce + + 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 _VOICE_HPP +#define _VOICE_HPP + +#include + + enum VoiceState { + V_OFF, + V_ON + }; + +class Voice { + public: + uint8_t note; + VoiceState state = V_OFF; +}; + +#endif // _VOICE_HPP \ No newline at end of file