Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segregate monophonic midi from polyphonic midi signals #8

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 25 additions & 41 deletions include/sst/voicemanager/managers/polymanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

namespace sst::voicemanager::managers
{
template <typename Cfg, typename Responder> struct PolyManager
template <typename Cfg, typename VoiceResponder, typename MonoResponder> struct PolyManager
{
int64_t mostRecentNoteCounter{1};

Expand Down Expand Up @@ -52,8 +52,9 @@ template <typename Cfg, typename Responder> struct PolyManager
std::array<VoiceInfo, Cfg::maxVoiceCount> voiceInfo;
std::array<typename Cfg::voice_t *, Cfg::maxVoiceCount> 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);
}
Expand Down Expand Up @@ -122,6 +123,21 @@ template <typename Cfg, typename Responder> 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)
Expand All @@ -144,21 +160,6 @@ template <typename Cfg, typename Responder> 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)
{
Expand Down Expand Up @@ -226,19 +227,13 @@ template <typename Cfg, typename Responder> struct PolyManager
}
}

std::array<uint16_t, 16> lastPBByChannel{};
void routeMIDIPitchBend(int16_t port, int16_t channel, uint16_t pb14bit)
std::array<int16_t, 16> 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)
Expand Down Expand Up @@ -309,14 +304,9 @@ template <typename Cfg, typename Responder> 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)
Expand All @@ -330,13 +320,7 @@ template <typename Cfg, typename Responder> 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
Expand Down
7 changes: 4 additions & 3 deletions include/sst/voicemanager/voicemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

namespace sst::voicemanager
{
template <typename Cfg, typename Responder> struct VoiceManager
template <typename Cfg, typename Responder, typename MonoResponder> struct VoiceManager
{
enum VoiceMode
{
Expand All @@ -39,7 +39,8 @@ template <typename Cfg, typename Responder> 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();
}
Expand Down Expand Up @@ -192,7 +193,7 @@ template <typename Cfg, typename Responder> struct VoiceManager

static float midiToFloatVelocity(uint8_t vel) { return 1.f * vel / 127.f; }

using polymanager_t = sst::voicemanager::managers::PolyManager<Cfg, Responder>;
using polymanager_t = sst::voicemanager::managers::PolyManager<Cfg, Responder, MonoResponder>;
polymanager_t polyManager;
};
} // namespace sst::voicemanager
Expand Down
15 changes: 10 additions & 5 deletions tests/basic_poly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -126,16 +123,24 @@ struct ConcreteResp
} innards;
};

using voicemanager_t = sst::voicemanager::VoiceManager<Config, ConcreteResp>;
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<Config, ConcreteResp, ConcreteMonoResp>;

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};
Expand Down
Loading