diff --git a/plugin/chassis.cpp b/plugin/chassis.cpp index d87d2d5..9354fa2 100644 --- a/plugin/chassis.cpp +++ b/plugin/chassis.cpp @@ -69,10 +69,9 @@ void Chassis::noteOn(uint8_t 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); + if (voice[i].isFree()) { // top bit is voice free flag + voice[i].voiceOn(note); + //printf("voice %d set to note %d\n", i, note); break; } } @@ -80,36 +79,38 @@ void Chassis::noteOn(uint8_t note) { // 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); + voice[NUM_VOICES - 1].voiceOn(note); // FIXME distinguish between restarting reused note and stolen note + //printf("no free voices, 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("%2d = %3d %s\n", i, voice[i].note, voice[i].isFree()?"off":"on "); } printf("----------------------------\n"); + */ } void Chassis::noteOff(uint8_t note) { uint32_t v; - printf("note off called for %3d\n", note); + //printf("note off called for %3d\n", note); - printf("trying voice "); + //printf("trying voice "); for (uint32_t i = 0; i < NUM_VOICES; i++) { - printf("%02x ", i); + //printf("%02x ", i); - if (voice[i].note == note && voice[i].state != V_OFF) { - printf("note off for %d playing %02x\n", i, note); + if (voice[i].note == note && !voice[i].isFree()) { + // printf("note off for %d playing %3d\n", i, note); //memmove(voice + i, voice + i + 1, sizeof(Voice) * (NUM_VOICES - i)); - voice[i].state = V_OFF; + voice[i].voiceOff(); 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); - } + printf("%2d = %3d %s\n", i, voice[i].note, voice[i].isFree()?"off":"on "); + }*/ } void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *MidiEvents, uint32_t midiEventCount) { @@ -123,6 +124,14 @@ void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEv noteOff(MidiEvents[i].data[1]); } } + + // run each synth voice + bzero(outputs[0], sizeof(float)*frames); + for (uint8_t i = 0; i < NUM_VOICES; i++) { + voice[i].run(outputs[0], frames); + } + // copy left to right + memmove(outputs[1], outputs[0], sizeof(float)*frames); } // create the plugin diff --git a/plugin/chassis.hpp b/plugin/chassis.hpp index b586f80..8e7c2c4 100644 --- a/plugin/chassis.hpp +++ b/plugin/chassis.hpp @@ -19,12 +19,11 @@ #ifndef _CHASSIS_HPP #define _CHASSIS_HPP -#define NUM_VOICES 8 +#define NUM_VOICES 4 #include "DistrhoPlugin.hpp" #include "voice.hpp" - START_NAMESPACE_DISTRHO class Chassis : public Plugin { @@ -65,7 +64,7 @@ class Chassis : public Plugin { private: Voice voice[NUM_VOICES]; - //uint32_t + // uint32_t DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Chassis); }; diff --git a/plugin/voice.hpp b/plugin/voice.hpp index 1462678..85566c0 100644 --- a/plugin/voice.hpp +++ b/plugin/voice.hpp @@ -16,21 +16,53 @@ 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; + + void voiceOn(uint32_t key) { + keyState = K_ON; + envState = ATTACK; + note = key; + omega = (261.63 * powf(2, (note - 60)/12.0f))/48000.0f; + target = 1; + } + + void voiceOff() { + keyState = K_OFF; + envState = RELEASE; + target = 0; + } + + inline bool isFree() { + return keyState == K_OFF; + } + + void run(float *buffer, uint32_t samples) { + + env = ((target - env)*0.01) + env; + for (uint32_t i = 0; i < samples; i++) { + phase += omega; + if (phase > 1) phase -= 1; + buffer[i] += (0.5-phase) * env; + } + } + + private: + enum { ATTACK, + DECAY, + SUSTAIN, + RELEASE } envState = RELEASE; + enum { K_OFF, + K_ON, + K_SUSTAIN } keyState = K_OFF; + float phase, omega; + float env, target; }; -#endif // _VOICE_HPP \ No newline at end of file +#endif // _VOICE_HPP \ No newline at end of file