From 98ab957fafbfdc28f30f90156d2539492ff103fa Mon Sep 17 00:00:00 2001 From: Gordon JC Pearce Date: Wed, 4 Sep 2024 21:08:27 +0100 Subject: [PATCH] works for frames > updateFrames --- plugin/chassis.cpp | 56 ++++++++++++++++++++++++++++++++++++++-------- plugin/chassis.hpp | 2 ++ plugin/voice.cpp | 29 ++++++++++++++++++++---- plugin/voice.hpp | 21 +++++++++-------- 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/plugin/chassis.cpp b/plugin/chassis.cpp index b83f45e..637396f 100644 --- a/plugin/chassis.cpp +++ b/plugin/chassis.cpp @@ -20,14 +20,14 @@ START_NAMESPACE_DISTRHO -Chassis::Chassis() : Plugin(kParameterCount, 0, 0) { // one parameter, no programs, no states +Chassis::Chassis() : Plugin(kParameterCount, 0, 0), sampleRate(getSampleRate()) { // one parameter, no programs, no states } // Initialisation functions void Chassis::initParameter(uint32_t index, Parameter ¶meter) { switch (index) { - case k_saw: + case k_saw: parameter.hints = kParameterIsAutomatable | kParameterIsBoolean; parameter.name = "Saw"; parameter.symbol = "saw"; @@ -36,7 +36,7 @@ void Chassis::initParameter(uint32_t index, Parameter ¶meter) { parameter.ranges.def = 0.0f; break; - case k_sqr: + case k_sqr: parameter.hints = kParameterIsAutomatable | kParameterIsBoolean; parameter.name = "Square"; parameter.symbol = "sqr"; @@ -44,8 +44,16 @@ void Chassis::initParameter(uint32_t index, Parameter ¶meter) { parameter.ranges.max = 127.0f; parameter.ranges.def = 0.0f; break; + + case k_sub: + parameter.hints = kParameterIsAutomatable | kParameterIsBoolean; + parameter.name = "Sub Osc"; + parameter.symbol = "sub"; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 127.0f; + parameter.ranges.def = 0.0f; + break; } - } void Chassis::setParameterValue(uint32_t index, float value) { @@ -53,11 +61,12 @@ void Chassis::setParameterValue(uint32_t index, float value) { case k_saw: s.p.saw = value / 127.0f; break; - case k_sqr: + case k_sqr: s.p.sqr = value / 127.0f; break; - - + case k_sub: + s.p.sub = value / 127.0f; + break; } } @@ -86,8 +95,11 @@ void Chassis::loadProgram(uint32_t index) { // Processing functions void Chassis::activate() { - // calculate filter coefficients + // calculate filter coefficients and stuff printf("called activate()\n"); + s.updateLength = sampleRate / 238; // update rate in Hz; + printf("update length is %d for %dHz sample rate\n", s.updateLength, (int)sampleRate); + //s.samplesLeft = s.updateLength; } void Chassis::deactivate() { @@ -107,6 +119,7 @@ void Chassis::noteOn(uint8_t note) { break; } } + if (i == NUM_VOICES) { // didn't find a free voice vPtr++; if (vPtr == NUM_VOICES) vPtr = 0; @@ -125,8 +138,32 @@ void Chassis::noteOff(uint8_t note) { void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *MidiEvents, uint32_t midiEventCount) { // if (midiEventCount > 0) printf("\n--------------------\n"); + + //uint32_t framesDone = 0; +/* + if (s.samplesLeft == 0) { + printf("resetting s.samplesLeft to %d\n", frames); + s.samplesLeft = frames; + }*/ + + + printf("in run(%d), samplesLeft = %d\n", frames, s.samplesLeft); + s.samplesLeft = frames; + + do { + printf("doing %d frames %d\n", s.updateLength, s.samplesLeft); + s.samplesLeft -= s.updateLength; + + } while (s.samplesLeft > s.updateLength); + printf("doing %d frames %d\n", s.samplesLeft, s.samplesLeft); + s.samplesLeft = s.updateLength - s.samplesLeft; + + + + printf("done with all that, %d\n", s.samplesLeft); + + for (uint32_t i = 0; i < midiEventCount; i++) { - // 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]); } @@ -140,6 +177,7 @@ void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEv for (uint8_t i = 0; i < NUM_VOICES; i++) { s.voice[i].run(s, outputs[0], frames); } + s.lastpw = s.lfo; // copy left to right memmove(outputs[1], outputs[0], sizeof(float) * frames); } diff --git a/plugin/chassis.hpp b/plugin/chassis.hpp index 0280a8e..961430c 100644 --- a/plugin/chassis.hpp +++ b/plugin/chassis.hpp @@ -31,6 +31,7 @@ class Chassis : public Plugin { enum Parameters { k_saw, k_sqr, + k_sub, kParameterCount }; @@ -65,6 +66,7 @@ class Chassis : public Plugin { void noteOff(uint8_t note); private: + double sampleRate; // Voice voice[NUM_VOICES]; uint8_t vPtr; diff --git a/plugin/voice.cpp b/plugin/voice.cpp index e811c1a..eced6bb 100644 --- a/plugin/voice.cpp +++ b/plugin/voice.cpp @@ -55,14 +55,35 @@ void Voice::off() { } void Voice::run(Synth &s, float *buffer, uint32_t samples) { - float y; + float y, offset, pw = 0; env = ((target - env) * 0.01) + env; + pw = 0.5 - s.lfo * 0.4; + + // s.p.sqr=1; + for (uint32_t i = 0; i < samples; i++) { + + // sawtooth + y = 1 - (2 * phase); + y += blep(phase, omega); + + // need this if either saw or square is on; + y *= (s.p.saw + s.p.sqr); + + // bodged for 16ms 48000Hz + pw_rc = ((pw - pw_rc) * 0.000625) + pw_rc; + + // phase shifted saw + offset = phase + pw_rc; + if (offset > 1) offset -= 1; + + y -= (1 - (2 * offset)) * s.p.sqr; + y -= blep(offset, omega + (pw_rc - s.lastpw)) * s.p.sqr; + //s.lastpw = pw_rc; + + buffer[i] += (0.125 * y * env); phase += omega; if (phase > 1) phase -= 1; - y = (2 * phase) - 1; - y -= blep(phase, omega); - buffer[i] += (0.25 * y * env) * s.p.saw; } } diff --git a/plugin/voice.hpp b/plugin/voice.hpp index 92ade0b..a1d70a3 100644 --- a/plugin/voice.hpp +++ b/plugin/voice.hpp @@ -23,9 +23,8 @@ class Synth; class Patch { - public: - float saw,sqr; - + public: + float saw, sqr, sub; }; class Voice { @@ -48,14 +47,18 @@ class Voice { enum { K_OFF, K_ON, K_SUSTAIN } keyState = K_OFF; - float phase, omega; + float phase = 0, omega = 260 / 48000.0; float env, target; - float out, delay; - + + float pw_rc = 0; }; class Synth { - public: - Patch p; - Voice voice[8]; + public: + Patch p; + Voice voice[8]; + float lfo = 0, lfosw = 0.01; + float lastpw = 0; + uint32_t updateLength; + uint32_t samplesLeft = 0; };