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.
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);
}
}
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: