MPEInstrument in Bitwig: Zone-Pitch-Range 14-bit MIDI bug and assertion

JUCE 8.0.11 / reproduced in Bitwig 5.3.1 and 5.3.13 (actual)

We have an MPE plugin, and when we load it in Bitwig, it hits the following assertion:

void MPEZoneLayout::checkAndLimitZoneParameters (int minValue, int maxValue,
                                                 int& valueToCheckAndLimit) noexcept
{
    if (valueToCheckAndLimit < minValue || valueToCheckAndLimit > maxValue)
    {
        // if you hit this, one of the parameters you supplied for this zone
        // was not within the allowed range!
        // we fit this back into the allowed range here to maintain a valid
        // state for the zone, but probably the resulting zone is not what you
        // wanted it to be!
        jassertfalse;

        valueToCheckAndLimit = jlimit (minValue, maxValue, valueToCheckAndLimit);
    }
}

This is because Bitwig also sends the zone range as 14-bit value, and JUCE directly uses this to set the zones, which leads to an invalid pitch range. For 48 semitones, it is 6144 semitones:

Some calculation is required for 14-bit values to get the semitones range. I think this is a bug in the JUCE code.

It should be easy to reproduce this when duplicating a track that contains the loaded MPE plugin. Or when loading a session that contains an MPE plugin. In this cases Bitwig sends these MPE MIDI messages.

Any help welcome!

Something like this would be a temporary fix. Probably we should also consider floating point values for the pitch ranges, otherwise the 14 bit value makes no sense.

void MPEZoneLayout::processPitchbendRangeRpnMessage (MidiRPNMessage rpn)
{
    int value = rpn.is14BitValue ? (int)std::floor(rpn.value / 128.0f + 0.5f) : rpn.value;

    if (rpn.channel == 1)
    {
        updateMasterPitchbend (lowerZone, value);
    }
    else if (rpn.channel == 16)
    {
        updateMasterPitchbend (upperZone, value);
    }
    else
    {
        if (lowerZone.isUsingChannelAsMemberChannel (rpn.channel))
            updatePerNotePitchbendRange (lowerZone, value);
        else if (upperZone.isUsingChannelAsMemberChannel (rpn.channel))
            updatePerNotePitchbendRange (upperZone, value);
    }
}

Has anyone reproduced this with JUCE 8.0.11 and juce::MPEInstrument in Bitwig (VST3)?

It looks to me like a regression introduced with the new MIDI features.

I don’t think this is a regression - the recent MIDI rewrite only touched MidiInput and MidiOutput and their implementations, so MPEInstrument and the plugin wrappers should not have been affected.

In any case, we’ve pushed a change that should fix the issue you’re seeing:

Thanks a lot for the fix. This was important for us.