From f0efe3c6aaa0dbdc7dd6693131fa97581598b244 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Fri, 27 Dec 2024 17:10:31 -0500 Subject: [PATCH 1/5] Fix a missing keybed update in legato mode In legato mode when no voice was created the keybed was mis-recorded, leading to inconsistent triggering when legatoing across an ungated phase, and in some cases, inconsistent retriggering --- include/sst/voicemanager/voicemanager_impl.h | 51 +++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/include/sst/voicemanager/voicemanager_impl.h b/include/sst/voicemanager/voicemanager_impl.h index 44ac62d..cab4ecf 100644 --- a/include/sst/voicemanager/voicemanager_impl.h +++ b/include/sst/voicemanager/voicemanager_impl.h @@ -496,7 +496,7 @@ struct VoiceManager::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) { @@ -504,17 +504,18 @@ struct VoiceManager::Details { 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"); } } }; @@ -670,7 +671,8 @@ bool VoiceManager::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); @@ -743,21 +745,30 @@ bool VoiceManager::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) @@ -828,19 +839,38 @@ void VoiceManager::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) { @@ -854,6 +884,7 @@ void VoiceManager::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 @@ -880,6 +911,7 @@ void VoiceManager::processNoteOffEvent(int16_t po << vi.activeVoiceCookie); responder.releaseVoice(vi.activeVoiceCookie, velocity); } + VML("- Gated to False ***"); vi.gated = false; } } @@ -896,6 +928,7 @@ void VoiceManager::processNoteOffEvent(int16_t po if (vi.gated) { responder.releaseVoice(vi.activeVoiceCookie, velocity); + VML("- Gated to False ***"); vi.gated = false; } } @@ -958,6 +991,7 @@ void VoiceManager::updateSustainPedal(int16_t por details.keyStateByPort[vi.port][vi.channel][vi.key] = {}; + VML("- Gated to False ***"); vi.gated = false; vi.gatedDueToSustain = false; } @@ -1137,6 +1171,7 @@ void VoiceManager::allNotesOff() if (v.activeVoiceCookie) { responder.releaseVoice(v.activeVoiceCookie, 0); + VML("- Gated to False ***"); v.gated = false; } } From 6c293151362a443981b3c6b17ef751206e12bcfd Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Fri, 27 Dec 2024 17:15:30 -0500 Subject: [PATCH 2/5] wthgcc --- tests/test_player.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_player.h b/tests/test_player.h index 510ddeb..174a68e 100644 --- a/tests/test_player.h +++ b/tests/test_player.h @@ -290,14 +290,17 @@ template struct TestPlayer MonoResponder(TestPlayer &p) : testPlayer(p) {} void setMIDIPitchBend(int16_t channel, int16_t pb14bit) { + assert(channel >=0 && channel < 16); testPlayer.pitchBend[channel] = pb14bit; } void setMIDI1CC(int16_t channel, int16_t cc, int8_t val) { + assert(channel >=0 && channel < 16); testPlayer.midi1CC[channel][cc] = val; } void setMIDIChannelPressure(int16_t channel, int16_t pres) { + assert(channel >=0 && channel < 16); testPlayer.channelPressure[channel] = pres; } } monoResponder; From 3b0d452f963e3764742e8d50356043ba169d002d Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Fri, 27 Dec 2024 17:16:19 -0500 Subject: [PATCH 3/5] fff --- tests/test_player.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_player.h b/tests/test_player.h index 174a68e..2f955b3 100644 --- a/tests/test_player.h +++ b/tests/test_player.h @@ -290,17 +290,17 @@ template struct TestPlayer MonoResponder(TestPlayer &p) : testPlayer(p) {} void setMIDIPitchBend(int16_t channel, int16_t pb14bit) { - assert(channel >=0 && channel < 16); + assert(channel >= 0 && channel < 16); testPlayer.pitchBend[channel] = pb14bit; } void setMIDI1CC(int16_t channel, int16_t cc, int8_t val) { - assert(channel >=0 && channel < 16); + assert(channel >= 0 && channel < 16); testPlayer.midi1CC[channel][cc] = val; } void setMIDIChannelPressure(int16_t channel, int16_t pres) { - assert(channel >=0 && channel < 16); + assert(channel >= 0 && channel < 16); testPlayer.channelPressure[channel] = pres; } } monoResponder; From 309399c7398a57b82d473d578d71e5bf3756fec6 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Fri, 27 Dec 2024 17:17:30 -0500 Subject: [PATCH 4/5] ggrrrn --- .github/workflows/build-pr.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 3ec4eec..2bfdeed 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -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 From 801f648e52b12c9c55a8145673e1aa8144dfda04 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Fri, 27 Dec 2024 17:22:25 -0500 Subject: [PATCH 5/5] ffff --- tests/test_player.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_player.h b/tests/test_player.h index 2f955b3..42872a6 100644 --- a/tests/test_player.h +++ b/tests/test_player.h @@ -28,6 +28,7 @@ #include #include "sst/voicemanager/voicemanager.h" +#include #define TPT(...) \ if constexpr (doLog) \ @@ -290,18 +291,17 @@ template struct TestPlayer MonoResponder(TestPlayer &p) : testPlayer(p) {} void setMIDIPitchBend(int16_t channel, int16_t pb14bit) { - assert(channel >= 0 && channel < 16); - 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) { assert(channel >= 0 && channel < 16); - testPlayer.midi1CC[channel][cc] = val; + testPlayer.midi1CC[std::clamp(channel, (int16_t)0, (int16_t)15)][cc] = val; } void setMIDIChannelPressure(int16_t channel, int16_t pres) { assert(channel >= 0 && channel < 16); - testPlayer.channelPressure[channel] = pres; + testPlayer.channelPressure[std::clamp(channel, (int16_t)0, (int16_t)15)] = pres; } } monoResponder;