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

Fix a missing keybed update in legato mode #18

Merged
merged 5 commits into from
Dec 27, 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
6 changes: 6 additions & 0 deletions .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ jobs:
with:
submodules: recursive

- name: pick GCC12
if: runner.os == 'Linux'
run: |
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 12
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 12

- name: Build test
run: |
cmake -S . -B ./build -DCMAKE_BUILD_TYPE=Release -DSST_VOICEMANAGER_BUILD_TESTS=TRUE
Expand Down
51 changes: 43 additions & 8 deletions include/sst/voicemanager/voicemanager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,25 +496,26 @@ struct VoiceManager<Cfg, Responder, MonoResponder>::Details
{
if constexpr (vmLog)
{
VML(">>>> Dump Key State");
VML(">>>> Dump Key State " << port);
auto &ks = keyStateByPort.at(port);
for (int ch = 0; ch < 16; ++ch)
{
for (int k = 0; k < 128; ++k)
{
if (!ks[ch][k].empty())
{
VML("- State at " << ch << "/" << k);
VML(">>>> - State at " << ch << "/" << k);
auto &vmap = ks[ch][k];
for (const auto &[pg, it] : vmap)
{
VML(" - PG=" << pg);
VML(" " << it.transaction << "/" << it.inceptionVelocity << "/"
<< it.heldBySustain);
VML(">>>> - PG=" << pg);
VML(">>>> " << it.transaction << "/" << it.inceptionVelocity << "/"
<< it.heldBySustain);
}
}
}
}
VML("<<<< Dump Key State");
}
}
};
Expand Down Expand Up @@ -670,7 +671,8 @@ bool VoiceManager<Cfg, Responder, MonoResponder>::processNoteOnEvent(int16_t por
{
if (v.activeVoiceCookie && v.polyGroup == mpg)
{
VML(" - Moving existing voice " << v.activeVoiceCookie << " to " << key);
VML(" - Moving existing voice " << &v << " " << v.activeVoiceCookie << " to "
<< key << " (" << v.gated << ")");
if (v.gated)
{
responder.moveVoice(v.activeVoiceCookie, port, channel, key, velocity);
Expand Down Expand Up @@ -743,21 +745,30 @@ bool VoiceManager<Cfg, Responder, MonoResponder>::processNoteOnEvent(int16_t por
port, channel, key, noteid, velocity, retune);

VML("- Voices created " << voicesLaunched);
details.debugDumpKeyState(port);

if (voicesLaunched != voicesToBeLaunched)
{
// This is probably OK
}

++details.mostRecentTransactionID;
if (voicesLaunched == 0)
{
for (int i = 0; i < voicesToBeLaunched; ++i)
{
// bail but still record the key press
details.keyStateByPort[port][channel][key]
[details.voiceBeginWorkingBuffer[i].polyphonyGroup] = {
details.mostRecentTransactionID, velocity};
}

responder.endVoiceCreationTransaction(port, channel, key, noteid, velocity);

return false;
}

auto voicesLeft = voicesLaunched;
++details.mostRecentTransactionID;
VML("- VoicesToBeLaunced " << voicesToBeLaunched << " voices launched " << voicesLaunched);

auto placeVoiceFromIndex = [&](int index)
Expand Down Expand Up @@ -828,19 +839,38 @@ void VoiceManager<Cfg, Responder, MonoResponder>::processNoteOffEvent(int16_t po
{
if (vi.matches(port, channel, key, noteid))
{
VML("- Found matching release note at " << vi.polyGroup << " " << vi.key);
VML("- Found matching release note at " << vi.polyGroup << " " << vi.key << " "
<< vi.gated);
if (details.playMode[vi.polyGroup] == PlayMode::MONO_NOTES)
{
if (details.playModeFeatures[vi.polyGroup] &
(uint64_t)MonoPlayModeFeatures::MONO_LEGATO)
{
bool anyOtherOption = details.anyKeyHeldFor(port, vi.polyGroup, channel, key);
VML("- AnoyOther check for legato at " << vi.polyGroup << " " << (int)channel
<< " " << (int)key << " is "
<< anyOtherOption);
if (anyOtherOption)
{
retriggerGroups.insert(vi.polyGroup);
VML("- A key is down in same group. Initiating mono legato move");
continue;
}
else
{
auto &ks = details.keyStateByPort[port];
for (int ch = 0; ch < 16; ++ch)
{
for (int k = 0; k < 128; ++k)
{
for (const auto &[g, s] : ks[ch][k])
{
VML("=== Held Key " << g << " " << s.transaction
<< " at k=" << (int)k << " ch=" << (int)ch)
}
}
}
}
}
if (details.sustainOn)
{
Expand All @@ -854,6 +884,7 @@ void VoiceManager<Cfg, Responder, MonoResponder>::processNoteOffEvent(int16_t po
VML("- There's a gated key away so untrigger this");
retriggerGroups.insert(vi.polyGroup);
responder.terminateVoice(vi.activeVoiceCookie);
VML("- Gated to False ***");
vi.gated = false;
}
else
Expand All @@ -880,6 +911,7 @@ void VoiceManager<Cfg, Responder, MonoResponder>::processNoteOffEvent(int16_t po
<< vi.activeVoiceCookie);
responder.releaseVoice(vi.activeVoiceCookie, velocity);
}
VML("- Gated to False ***");
vi.gated = false;
}
}
Expand All @@ -896,6 +928,7 @@ void VoiceManager<Cfg, Responder, MonoResponder>::processNoteOffEvent(int16_t po
if (vi.gated)
{
responder.releaseVoice(vi.activeVoiceCookie, velocity);
VML("- Gated to False ***");
vi.gated = false;
}
}
Expand Down Expand Up @@ -958,6 +991,7 @@ void VoiceManager<Cfg, Responder, MonoResponder>::updateSustainPedal(int16_t por

details.keyStateByPort[vi.port][vi.channel][vi.key] = {};

VML("- Gated to False ***");
vi.gated = false;
vi.gatedDueToSustain = false;
}
Expand Down Expand Up @@ -1137,6 +1171,7 @@ void VoiceManager<Cfg, Responder, MonoResponder>::allNotesOff()
if (v.activeVoiceCookie)
{
responder.releaseVoice(v.activeVoiceCookie, 0);
VML("- Gated to False ***");
v.gated = false;
}
}
Expand Down
9 changes: 6 additions & 3 deletions tests/test_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <map>

#include "sst/voicemanager/voicemanager.h"
#include <algorithm>

#define TPT(...) \
if constexpr (doLog) \
Expand Down Expand Up @@ -290,15 +291,17 @@ template <size_t voiceCount, bool doLog = false> struct TestPlayer
MonoResponder(TestPlayer &p) : testPlayer(p) {}
void setMIDIPitchBend(int16_t channel, int16_t pb14bit)
{
testPlayer.pitchBend[channel] = pb14bit;
testPlayer.pitchBend[std::clamp(channel, (int16_t)0, (int16_t)15)] = pb14bit;
}
void setMIDI1CC(int16_t channel, int16_t cc, int8_t val)
{
testPlayer.midi1CC[channel][cc] = val;
assert(channel >= 0 && channel < 16);
testPlayer.midi1CC[std::clamp(channel, (int16_t)0, (int16_t)15)][cc] = val;
}
void setMIDIChannelPressure(int16_t channel, int16_t pres)
{
testPlayer.channelPressure[channel] = pres;
assert(channel >= 0 && channel < 16);
testPlayer.channelPressure[std::clamp(channel, (int16_t)0, (int16_t)15)] = pres;
}
} monoResponder;

Expand Down
Loading