diff --git a/plugin/assigner.cpp b/plugin/assigner.cpp index 70e9789..65ac907 100644 --- a/plugin/assigner.cpp +++ b/plugin/assigner.cpp @@ -17,8 +17,9 @@ */ #include "assigner.hpp" + #include "generator.hpp" -//#define DEBUG +// #define DEBUG void Assigner::dumpTables() { #ifdef DEBUG @@ -57,10 +58,9 @@ void Assigner::handleMidi(MidiEvent *ev) { break; case 0xb0: switch (ev->data[1]) { - // handle the following + // maybe handle the following // CC 1 - modwheel // CC 64 - sustain - // possibly JU-06 CC values default: break; } @@ -95,8 +95,6 @@ void Assigner::noteOff(uint8_t note) { voiceTbl[NUM_VOICES - 1] = v; noteTbl[v] |= 0x80; voices[v].stopNote(); - - } void Assigner::noteOn(uint8_t note) { @@ -139,7 +137,7 @@ void Assigner::noteOn(uint8_t note) { // printf("at end, l=%d e=%d\n", l,e); noteTbl[v] = note; - voices[v].startNote(note, 48000); + voices[v].startNote(note); d_debug("send voice on %3d to voice %d", note, v); } diff --git a/plugin/assigner.hpp b/plugin/assigner.hpp index b5f1f54..84e2799 100644 --- a/plugin/assigner.hpp +++ b/plugin/assigner.hpp @@ -27,12 +27,12 @@ class Assigner { public: Assigner(Voice *v); void handleMidi(MidiEvent *ev); - uint8_t noteTbl[NUM_VOICES]; // note played by voice 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 Voice *voices; diff --git a/plugin/generator.cpp b/plugin/generator.cpp index 516800a..18956cd 100644 --- a/plugin/generator.cpp +++ b/plugin/generator.cpp @@ -24,9 +24,17 @@ #include "DistrhoPluginInfo.h" -Generator::Generator(uint32_t bufferSize, float sampleRate) { +// some unit-local globals + +float sampleRate = 0; + +float envTc[2]; + + +Generator::Generator(uint32_t bufferSize, double xSampleRate) { + sampleRate = xSampleRate; output = new float[bufferSize]; - // create the phase increments for each semitone + // create the phase increments for each semitone for (uint8_t i = 0; i < 12; i++) { phase[i] = 0; uint32_t f; @@ -39,7 +47,7 @@ Generator::~Generator() { delete output; } -void Generator::runBlock(uint8_t *noteTable, uint32_t frames) { +void Generator::runBlock(uint32_t frames) { Voice *v; uint32_t i; uint8_t k, p, key, n1, n2, d; @@ -53,11 +61,9 @@ void Generator::runBlock(uint8_t *noteTable, uint32_t frames) { } for (k = 0; k < NUM_VOICES; k++) { - key = noteTable[k] & 0x7f; - n1 = key % 12, n2 = (key / 12 - 3); v = &voices[k]; - d = (phase[n1] & (0x40000000 >> n2)) != 0; + d = (phase[v->semi] & (0x40000000 >> v->oct)) != 0; n = d ? 0.25 : -0.25; v->vc34 = ((n - v->vc34) * v->c34) + v->vc34; n -= v->vc34; @@ -65,7 +71,7 @@ void Generator::runBlock(uint8_t *noteTable, uint32_t frames) { v->vc78 = ((n - v->vc78) * v->c78) + v->vc78; v->vc107 = ((v->vc78 - v->vc107) * v->c107) + v->vc107; - d = (phase[n1] & (0x80000000 >> n2)) != 0; + d = (phase[v->semi] & (0x80000000 >> v->oct)) != 0; n = d ? 0.25 : -0.25; v->vc33 = ((n - v->vc33) * v->c33) + v->vc33; n -= v->vc33; @@ -73,17 +79,17 @@ void Generator::runBlock(uint8_t *noteTable, uint32_t frames) { v->vc22 = ((n - v->vc22) * v->c22) + v->vc22; v->vc31 = ((v->vc22 - v->vc31) * v->c31) + v->vc31; - v->vca = ((v->gate - v->vca) * v->vcatc) + v->vca; + v->vca = ((v->gate - v->vca) * envTc[v->vcatc]) + v->vca; float v4 = (v->vc78 - v->vc107); float v8 = (v->vc22 - v->vc31); - output[i] += 0.25* (v4 + v8) * v->vca; //((noteTable[k]&0x80)?0:1); + output[i] += 0.25 * (v4 + v8) * v->vca; } } } -void Voice::startNote(uint8_t key, double sampleRate) { +void Voice::startNote(uint8_t key) { // start a new note // violin and viola filter params float fc = 88.4 * powf(2, 0.083334 * (key - 24)); @@ -101,10 +107,16 @@ void Voice::startNote(uint8_t key, double sampleRate) { c31 = 1 - exp(-6.283 * 150.0 / sampleRate); gate = 1; - vcatc = 0.0001; + vcatc = 0; + semi = key % 12, oct = (key / 12 - 3); } void Voice::stopNote() { gate = 0; - vcatc = 0.000033; + vcatc = 1; +} + +void Generator::setEnvelope(float attack, float sustain) { + envTc[0] = ((96* powf(100, -attack))/sampleRate); + envTc[1] = ((48* powf(100, -sustain))/sampleRate); } diff --git a/plugin/generator.hpp b/plugin/generator.hpp index 37ce2d8..563e105 100644 --- a/plugin/generator.hpp +++ b/plugin/generator.hpp @@ -29,7 +29,7 @@ class Voice { friend Generator; public: - void startNote(uint8_t key, double sampleRate); + void startNote(uint8_t key); void stopNote(); private: @@ -40,14 +40,16 @@ class Voice { float c33 = 0, vc33 = 0; float c78 = 0, vc78 = 0; float c107 = 0, vc107 = 0; - float vca = 0, vcatc = 0, gate = 0; + float vca = 0, gate = 0; + uint8_t vcatc; }; class Generator { public: - Generator(uint32_t bufferSize, float sampleRate); + Generator(uint32_t bufferSize, double xSampleRate); ~Generator(); - void runBlock(uint8_t *noteTable, uint32_t frames); + void setEnvelope(float attack, float sustain); + void runBlock(uint32_t frames); Voice voices[NUM_VOICES]; float *output; diff --git a/plugin/parameters.cpp b/plugin/parameters.cpp index 57bc2a2..6687b5a 100644 --- a/plugin/parameters.cpp +++ b/plugin/parameters.cpp @@ -99,13 +99,32 @@ void Sonnenlicht::initParameter(uint32_t index, Parameter& parameter) { void Sonnenlicht::setParameterValue(uint32_t index, float value) { switch (index) { case pViola: - viola = value; + prog.viola = value; break; + case pViolin: - violin = value; + prog.violin = value; break; + case pBassVolume: - bassVolume = value; + prog.bassVolume = value; + break; + + case pAttack: + prog.attack = value; + genny->setEnvelope(prog.attack, prog.sustain); + break; + + case pSustain: + prog.sustain = value; + genny->setEnvelope(prog.attack, prog.sustain); + //printf("pSustain: value=%f p.a %f p.s %f\n", value, prog.attack, prog.sustain); + break; + + case pChorale: + prog.enableChorus = (bool)value; + break; + default: break; } @@ -117,14 +136,26 @@ void Sonnenlicht::setParameterValue(uint32_t index, float value) { float Sonnenlicht::getParameterValue(uint32_t index) const { switch (index) { case pViola: - return viola; + return prog.viola; + + case pViolin: + return prog.violin; + + case pAttack: + return prog.attack; + + case pSustain: + return prog.sustain; case pBassVolume: - return bassVolume; + return prog.bassVolume; + + case pChorale: + return (float)prog.enableChorus; default: return 0; } // if we fall all the way through... - return 2; + return 0; } diff --git a/plugin/sonnenlicht.cpp b/plugin/sonnenlicht.cpp index 33453de..137b32f 100644 --- a/plugin/sonnenlicht.cpp +++ b/plugin/sonnenlicht.cpp @@ -54,9 +54,15 @@ void Sonnenlicht::run(const float**, float** outputs, uint32_t frames, assigner->handleMidi((MidiEvent*)&ev[i]); } - genny->runBlock(assigner->noteTbl, frames); + genny->runBlock(frames); + + if (prog.enableChorus) { chorus->run(genny->output, outputs, frames); + } else { + memcpy(outputs[0], genny->output, frames * sizeof(float)); + memcpy(outputs[1], genny->output, frames * sizeof(float)); + } } Plugin* createPlugin() { return new Sonnenlicht(); } diff --git a/plugin/sonnenlicht.hpp b/plugin/sonnenlicht.hpp index 8b6f3a9..0c9a167 100644 --- a/plugin/sonnenlicht.hpp +++ b/plugin/sonnenlicht.hpp @@ -26,6 +26,13 @@ START_NAMESPACE_DISTRHO +class Program { + public: + float viola = 0, violin = 0, bassVolume = 0; + float attack, sustain; + bool enableChorus; +}; + class Sonnenlicht : public Plugin { public: enum Parameters { @@ -70,8 +77,9 @@ class Sonnenlicht : public Plugin { const MidiEvent *midiEvents, uint32_t midiEventCount) override; private: - float viola = 0, violin = 0, bassVolume = 0; double fSampleRate; + + Program prog; Assigner *assigner; Generator *genny; Chorus *chorus;