MidiChannel issue

Hi,
Hi I noticed that there is a problem here :

std::unique_ptr<tracktion::graph::Node> createNodeForMidiClip (MidiClip& clip, const TrackMuteState& trackMuteState, const CreateNodeParams& params)
{
    CRASH_TRACER
    const bool generateMPE = clip.getMPEMode();
    const auto timeBase = clip.canUseProxy() ? MidiList::TimeBase::seconds
                                             : MidiList::TimeBase::beatsRaw;

    const auto channels = generateMPE ? juce::Range<int> (2, 15)
                                      : juce::Range<int>::withStartAndLength (clip.getMidiChannel().getChannelNumber(), 1);

    if (timeBase == MidiList::TimeBase::beatsRaw)
    {
        std::vector<juce::MidiMessageSequence> sequences;
        sequences.emplace_back (clip.getSequence().exportToPlaybackMidiSequence (clip, timeBase, generateMPE));

        return graph::makeNode<LoopingMidiNode> (std::move (sequences),
                                                 channels,
                                                 generateMPE,
                                                 BeatRange (clip.getStartBeat(), clip.getEndBeat()),
                                                 BeatRange (clip.getLoopStartBeats(), clip.getLoopLengthBeats()),
                                                 clip.getOffsetInBeats(),
                                                 clip.getLiveClipLevel(),
                                                 params.processState,
                                                 clip.itemID,
                                                 clip.getQuantisation(),
                                                 clip.edit.engine.getGrooveTemplateManager().getTemplateByName (clip.getGrooveTemplate()),
                                                 clip.getGrooveStrength(),
                                                 [&trackMuteState]
                                                 {
                                                      if (! trackMuteState.shouldTrackBeAudible())
                                                         return ! trackMuteState.shouldTrackMidiBeProcessed();

                                                     return false;
                                                 });
    }

    // Use looped sequence in seconds time base
    const auto clipTimeRange = clip.getEditTimeRange();
    const juce::Range<double> editTimeRange { clipTimeRange.getStart().inSeconds(), clipTimeRange.getEnd().inSeconds() };

    std::vector<juce::MidiMessageSequence> sequences;
    sequences.emplace_back (clip.getSequenceLooped().exportToPlaybackMidiSequence (clip, timeBase, generateMPE));

    return graph::makeNode<MidiNode> (std::move (sequences),
                                      timeBase,
                                      channels,
                                      generateMPE,
                                      editTimeRange,
                                      clip.getLiveClipLevel(),
                                      params.processState,
                                      clip.itemID,
                                      [&trackMuteState]
                                      {
                                          if (! trackMuteState.shouldTrackBeAudible())
                                              return ! trackMuteState.shouldTrackMidiBeProcessed();

                                          return false;
                                      });
}

When at a midi clip I set the channel to 16 , in single channel mode

const auto channels = generateMPE ? juce::Range<int> (2, 15)
                                      : juce::Range<int>::withStartAndLength (clip.getMidiChannel().getChannelNumber(), 1);

The value of channels would be [16,17] .

So when a MidiNode is created an assert is reached :

MidiNode::MidiNode (std::vector<juce::MidiMessageSequence> sequences,
                    MidiList::TimeBase tb,
                    juce::Range<int> midiChannelNumbers,
                    bool useMPE,
                    juce::Range<double> editTimeRange,
                    LiveClipLevel liveClipLevel,
                    ProcessState& processStateToUse,
                    EditItemID editItemIDToUse,
                    std::function<bool()> shouldBeMuted)
    : TracktionEngineNode (processStateToUse),
      ms (std::move (sequences)),
      timeBase (tb),
      channelNumbers (midiChannelNumbers),
      useMPEChannelMode (useMPE),
      editRange (editTimeRange),
      clipLevel (liveClipLevel),
      editItemID (editItemIDToUse),
      shouldBeMutedDelegate (std::move (shouldBeMuted)),
      wasMute (liveClipLevel.isMute())
{
    jassert (channelNumbers.getStart() > 0 && channelNumbers.getEnd() <= 16);
    ... 
    ...
}

How can i set the midi channel to 16 avoiding reaching this issue ?

MIDI channel is 0 based in juce so should be 0-15. Where MIDI channel 16 would be 15.

Tks for the reply.
When i wanna set the midi channel of a midi clip i think i should call this method :
void setMidiChannel (MidiChannel newChannel) { getSequence().setMidiChannel (newChannel); }

where

 // Takes a number 1-16
 explicit MidiChannel (int channelNumber1to16) noexcept  : channel ((uint8_t) channelNumber1to16)
 {
     jassert (channelNumber1to16 > 0 && channelNumber1to16 <= 16);
 }

So i should pass a value range from 1-16 and not 0-15.

@dave96 Hi,
I just see this old post : Assertion playing edit with midi clip set to midi channel 16

Where RolandMR says to just ignore the assert… can i still accept this answer as the right one or there are other issues ?

Ok, sorry I read and replied to this whilst I wasn’t at my computer so couldn’t see all of the code.

What branch are you on? On develop (the default) the assertion should be gone as it looks like this:

Yes i’m on develop branch.

There is another assert :

bool MidiMessage::isForChannel (const int channel) const noexcept
{

    jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16


    auto data = getRawData();

    return ((data[0] & 0xf) == channel - 1)
             && ((data[0] & 0xf0) != 0xf0);

}

What should i do here ?

What’s the call stack for triggering that assert?
I can’t seem to replicate what you’re seeing as I think the channel number should be correct at that point?
Ideally I’d like a few lines of code that I could write as a unit test.