Skip to content

Conversation

@eakwarren
Copy link
Contributor

@eakwarren eakwarren commented Jan 14, 2026

This PR enables full MIDI note support in the VST Sequencer. It doesn't touch fluidsynth or MuseSampler, but similar noteIndex and noteTuning methods in fluidsequencer.cpp and musesamplersequencer.cpp could be ported in subsequent PRs.

While ideally this should be fixed in pitchutils.h as described in #16657, this small PR unlocks full VST instrument and keyswitch support for the short term and incurs little tech debt as only two methods are changed.

  • Allow raw MIDI 0..127 through the VST sequencer; remove the old C0..C8 clamp.
  • Introduce MIDI_MIN_NOTE=0 and MIDI_MAX_NOTE=127; delete MAX_SUPPORTED_PITCH_LEVEL.
  • noteIndex():
    • Primary: compute idx relative to C0 (MIDI 12) and std::clamp to 0..127.
    • Fallback: for wrapped “below C0” pitch levels, map to keyswitch zone 0..11 using a modulo phase fix ((stepsRounded + 5) % 12) to eliminate 11→6 offset.
  • noteTuning():
    • Derive tuning versus the effective MIDI idx returned by noteIndex().
    • Zero tuning for keyswitch notes (idx < 12) to avoid large wrapped cent values.

Tested with Vital Synth, Kontakt 8, Sine Player, Synchron Player, Spitfire Player, MuseSounds, MS Basic.

Resolves: #16657

  • I signed the CLA
  • The title of the PR describes the problem it addresses
  • Each commit's message describes its purpose and effects, and references the issue it resolves
  • If changes are extensive, there is a sequence of easily reviewable commits
  • The code in the PR follows the coding rules
  • There are no unnecessary changes
  • The code compiles and runs on my machine, preferably after each commit individually
  • I created a unit test or vtest to verify the changes I made (if applicable)

- Allow raw MIDI 0..127 through the VST sequencer; remove the old C0..C8 clamp.
- Introduce MIDI_MIN_NOTE=0 and MIDI_MAX_NOTE=127; delete MAX_SUPPORTED_PITCH_LEVEL.
- noteIndex():
  * Primary: compute idx relative to C0 (MIDI 12) and std::clamp to 0..127.
  * Fallback: for wrapped “below C0” pitch levels, map to keyswitch zone 0..11
     using a modulo phase fix ((stepsRounded + 5) % 12) to eliminate 11→6 offset.
- noteTuning():
  * Derive tuning versus the effective MIDI idx returned by noteIndex().
  * Zero tuning for keyswitch notes (idx < 12) to avoid large wrapped cent values.
@eakwarren
Copy link
Contributor Author

@cbjeukendrup @avvvvve What do you think? There may not be much value in porting to fluidsynth or MuseSampler if their instruments don't use the full 0-127 midi note range. But for consistency, I'm happy to do so.

@avvvvve
Copy link

avvvvve commented Jan 15, 2026

I'll let @cbjeukendrup answer the technical bits, but it sounds like we will certainly need a fix like this if we want to get keyswitches working with automation down the line!

@cbjeukendrup
Copy link
Member

cbjeukendrup commented Jan 18, 2026

I'm afraid I don't understand why this fallback logic is necessary. I would expect that MIDI note 0 is represented as -12 * mpe::PITCH_LEVEL_STEP in pitch_level_t, and if that's the case, everything should just work. But apparently, that's not the case and I've yet to find out why. (pitch_level_t is signed, so that's also not the source of trouble)

@cbjeukendrup
Copy link
Member

UPDATE: I think I've found the problem. pitch_level_t is indeed a signed type. But octave_t not. Fixing that seems to fix all trouble.

@eakwarren
Copy link
Contributor Author

Sweet! Looking forward to testing it in nightly. @cbjeukendrup want me to close this PR?

@cbjeukendrup
Copy link
Member

You could test my PR: #31809 and if that works, you could indeed close this one.

@eakwarren eakwarren deleted the MIDI_Full_Note_Range branch January 20, 2026 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Playback does not support notes below C0 (MIDI note 12) or above C8 (MIDI note 108)

3 participants