From ef93561963437e17d991ae54efed8a8d237e04c6 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 2 Oct 2024 11:56:09 -0400 Subject: [PATCH] Segregate monophonic midi from polyphonic midi signals MIDIcc for instance should route to an overarching handler not to each voice. So introduce a MonoVoiceResponder also. I'm sure I will tweak this futher. Still not quite stable API here. --- .../sst/voicemanager/managers/polymanager.h | 66 +++++++------------ include/sst/voicemanager/voicemanager.h | 7 +- tests/basic_poly.cpp | 15 +++-- 3 files changed, 39 insertions(+), 49 deletions(-) diff --git a/include/sst/voicemanager/managers/polymanager.h b/include/sst/voicemanager/managers/polymanager.h index be5572b..a918430 100644 --- a/include/sst/voicemanager/managers/polymanager.h +++ b/include/sst/voicemanager/managers/polymanager.h @@ -23,7 +23,7 @@ namespace sst::voicemanager::managers { -template struct PolyManager +template struct PolyManager { int64_t mostRecentNoteCounter{1}; @@ -52,8 +52,9 @@ template struct PolyManager std::array voiceInfo; std::array voiceInitWorkingBuffer; - Responder &responder; - PolyManager(Responder &r) : responder(r) + VoiceResponder &responder; + MonoResponder &monoResponder; + PolyManager(VoiceResponder &r, MonoResponder &m) : responder(r), monoResponder(m) { std::fill(lastPBByChannel.begin(), lastPBByChannel.end(), 0); } @@ -122,6 +123,21 @@ template struct PolyManager } */ + if (lastPBByChannel[channel] != 0) + { + monoResponder.setMIDIPitchBend(channel, lastPBByChannel[channel] + 8192); + } + + int cid{0}; + for (auto &mcc : midiCCCache[channel]) + { + if (mcc != 0) + { + monoResponder.setMIDI1CC(channel, cid, mcc); + } + cid++; + } + auto voicesLaunched = responder.initializeMultipleVoices( voiceInitWorkingBuffer, port, channel, key, noteid, velocity, retune); if (voicesLaunched != voicesToBeLaunched) @@ -144,21 +160,6 @@ template struct PolyManager vi.gatedDueToSustain = false; vi.activeVoiceCookie = voiceInitWorkingBuffer[voicesLeft - 1]; - if (lastPBByChannel[channel] != 0) - { - responder.setVoiceMIDIPitchBend(vi.activeVoiceCookie, - lastPBByChannel[channel] + 8192); - } - - int cid{0}; - for (auto &mcc : midiCCCache[channel]) - { - if (mcc != 0) - { - responder.setMIDI1CC(vi.activeVoiceCookie, cid, mcc); - } - cid++; - } voicesLeft--; if (voicesLeft == 0) { @@ -226,19 +227,13 @@ template struct PolyManager } } - std::array lastPBByChannel{}; - void routeMIDIPitchBend(int16_t port, int16_t channel, uint16_t pb14bit) + std::array lastPBByChannel{}; + void routeMIDIPitchBend(int16_t port, int16_t channel, int16_t pb14bit) { if (channel >= 0 && channel < lastPBByChannel.size()) lastPBByChannel[channel] = pb14bit - 8192; - for (auto &vi : voiceInfo) - { - if (vi.matches(port, channel, -1, -1)) // all keys and notes on a channel for midi PB - { - responder.setVoiceMIDIPitchBend(vi.activeVoiceCookie, pb14bit); - } - } + monoResponder.setMIDIPitchBend(channel, pb14bit); } void routeMIDIMPEChannelPitchBend(int16_t port, int16_t channel, uint16_t pb14bit) @@ -309,14 +304,9 @@ template struct PolyManager void routeMIDI1CC(int16_t port, int16_t channel, int8_t cc, int8_t val) { midiCCCache[channel][cc] = val; - for (auto &vi : voiceInfo) - { - if (vi.matches(port, channel, -1, -1)) // all keys and notes on a channel for midi PB - { - responder.setMIDI1CC(vi.activeVoiceCookie, cc, val); - } - } + monoResponder.setMIDI1CC(channel, cc, val); } + void routePolyphonicAftertouch(int16_t port, int16_t channel, int16_t key, int8_t pat) { for (auto &vi : voiceInfo) @@ -330,13 +320,7 @@ template struct PolyManager void routeChannelPressure(int16_t port, int16_t channel, int8_t pat) { - for (auto &vi : voiceInfo) - { - if (vi.matches(port, channel, -1, -1)) // all keys and notes on a channel for midi PB - { - responder.setChannelPressure(vi.activeVoiceCookie, pat); - } - } + monoResponder.setMIDIChannelPressure(channel, pat); } }; } // namespace sst::voicemanager::managers diff --git a/include/sst/voicemanager/voicemanager.h b/include/sst/voicemanager/voicemanager.h index 842d13b..445144e 100644 --- a/include/sst/voicemanager/voicemanager.h +++ b/include/sst/voicemanager/voicemanager.h @@ -23,7 +23,7 @@ namespace sst::voicemanager { -template struct VoiceManager +template struct VoiceManager { enum VoiceMode { @@ -39,7 +39,8 @@ template struct VoiceManager int8_t mpeGlobalChannel{0}; Responder &responder; - VoiceManager(Responder &r) : responder(r), polyManager(r) + MonoResponder &monoResponder; + VoiceManager(Responder &r, MonoResponder &m) : responder(r), monoResponder(m), polyManager(r, m) { polyManager.registerVoiceEndCallback(); } @@ -192,7 +193,7 @@ template struct VoiceManager static float midiToFloatVelocity(uint8_t vel) { return 1.f * vel / 127.f; } - using polymanager_t = sst::voicemanager::managers::PolyManager; + using polymanager_t = sst::voicemanager::managers::PolyManager; polymanager_t polyManager; }; } // namespace sst::voicemanager diff --git a/tests/basic_poly.cpp b/tests/basic_poly.cpp index eca469c..5552be2 100644 --- a/tests/basic_poly.cpp +++ b/tests/basic_poly.cpp @@ -55,12 +55,9 @@ struct ConcreteResp return 1; } - void setMIDI1CC(void *v, int32_t cc, int32_t val) {} - void releaseVoice(void *v, float velocity) { innards.release(v, velocity); } void retriggerVoiceWithNewNoteID(void *v, int32_t noteid, float velocity) {} - void setVoiceMIDIPitchBend(void *v, uint16_t) {} int beginVoiceCreationTransaction(uint16_t port, uint16_t channel, uint16_t key, int32_t noteid, float velocity) { @@ -126,16 +123,24 @@ struct ConcreteResp } innards; }; -using voicemanager_t = sst::voicemanager::VoiceManager; +struct ConcreteMonoResp +{ + void setMIDIPitchBend(int16_t channel, int16_t pb14bit) {} + void setMIDI1CC(int16_t channel, int16_t cc, int16_t val) {} + void setMIDIChannelPressure(int16_t channel, int16_t pres) {} +}; + +using voicemanager_t = sst::voicemanager::VoiceManager; TEST_CASE("Basic Poly Note On Note Off") { ConcreteResp concreteResp; + ConcreteMonoResp concreteMonoResp; SECTION("OnOff") { // voice manager: consumes config - voicemanager_t vm(concreteResp); + voicemanager_t vm(concreteResp, concreteMonoResp); // Send a midi message note on, see voice and gated voice tick up uint16_t port{0}, channel{0}, key{60}, velocity{90};