How to route incoming MIDI messages by MIDI channel?
I'm working with external MIDI devices that send data on multiple channels, and I want to route each channel to a separate vst~ object. I have an attempt at this using midiparse and midi select. This works fine when only one channel is sending but when more than one is sending, the data from different channels gets garbled somehow. I suspect I have a timing race between the midiparse and the midi select but can't quite see it.
I have the midiparse sending all incoming midi events to both destinations, and my intent is to use the channel output of the midiselect to send the message to one or the other vst~. But when midi is coming in on both channels simultaneously the messages interfere with each other. I'm kind of wishing that midiparse took an @ch attribute like midi select does.
Can someone tell me what's the correct way to do this in Max?

For example:

Hmm, very strange. When I do that, I miss all the note off events. But if I connect the last midiparse outlet directly to the vst~, then the note off events get through okay. Also, if I print the output of the route, it says the note off events are being sent to the vst~ in both cases.
Okay, I found the problem. I needed to put 'buddy' between midiparse and join. It seems that the timing was otherwise inconsistent. Seems to be working properly now, thank you for the help.
I have to admit that I did not test the patch with sound.
You are right. Looks like a bug in midiparse.
I don't think it's a problem with midiparse - it's more to do with how you are using it and/or expecting it to work. midiparse sends out the channel number first, then any decoded messages, and the remaining midievent message comes out of the rightmost outlet last. It means that the channel number is coming out before the midievent message. This will cause your join object to trigger output before the midievent comes forth. buddy will "fix" this in a way but I would suggest using a gate 16 instead of route as it will work without the extra clutter:

In this example (ignore the top two lines as they are just there to generate a test message in the same format as midiin), the channel number emerges first and selects which gate output is opened ready for the midievent to pass through to the respective outlet. You can then connect these outlets straight into your respective vst~ objects.
I see, yes. So a gate works well.
But isn't it a bug, that the rightmost output isn't the first one to output data? This speciality is not mentioned in reference or help.
Thanks, yes the gate is a better solution. Using it that way now.
Well, I'd say that it's more of a failure to put the detail in the documentation really.
When I first started using Max, I found the general rule of things being processed right to left, bottom to top rather counter-intuitive but as I've got more used to its idiosyncrasies, I've realised that things usually work the way they do to make linked processes work in the correct order. In this situation, the fact that the channel comes out first makes it logical to run it into a gate where the gate inputs are the same way round (no crossed connectors).
That aside, I confirmed the order of events by stepping through the process with the debugger, something that has proved invaluable as my projects have become increasingly complicated.
The other thing I have learnt is that using objects like delay, pipe, buddy, bondo and swap can usually be avoided by using trigger with multiple arguments in a specific order (operated right to left of course!) to force operations to take place in the desired manner when Max doesn't quite follow the rules!
Max uses a "stack based" system for processing objects and process threads and using the debugger in step mode can really help in understanding the impact that has on patch layout.
with 3 objects:

with 2 objects:

Hi @Roman! I’m afraid that you’ve got your gate wired up wrong! The midi channel outlet, that is the last but one of midiparse, needs to go to the gate control (left inlet) and the last outlet of midiparse, which gives the correctly formatted messages for plugging in to the vst~ objects he’s using (midievent, note/channel command, note number, velocity) needs to go through the gate (right inlet). The first outlet of midiparse only gives the note values (note number and velocity) but the vst~ expects a fully formatted midievent. Using notein won’t work as again it only gives the note number and velocity separately from its two outlets.
Roman, your 2 object version doesn't handle CC, or program change, or aftertouch, or pitch bend...
Yes, of course, I was focussing on note messages as an example but the midievent message from the rightmost outlet of midiparse will include all midi messages of any type. (Except sysex of course!)
Andy, could you give me an idea of how this would be solved with trigger? I will be using the version with gate, but I would like to have a better understanding of how to use trigger. Initially I intended to use trigger for this, but couldn't quite understand how it would work. I was confused by the fact that the midievent message would not always be the same length.
You don’t need trigger in this situation as the midiparse-gate method does exactly what you need
When I mentioned trigger, it was more about those unusual circumstances where you need to have specific control over the order of events. For example, you talked about using buddy to overcome the fact that join was being triggered by the channel message before the midi message arrived.
As I was learning, I resorted to all sorts of hacks using bangs, delays, pipes, buddies and bondos because I wasn’t fully aware of how Max schedules things. Trigger has lots of advantages in many situations when you need to control the flow and order of events. Unlike the other solutions, trigger responds to any input and you can use the arguments to output pretty much anything too. And you can guarantee that the outputs will be in order from right to left.
I should be asleep now (!) but in the morning I’ll post an example of what I mean.
Roman's gate is perfectly allright, all you need is to understand that there were max versions
older that what one uses now, which had no midievent outlet.
Logic itself should have been enough to find that out.
And it will route all midi output from midiparse to correct outlet.
All one needs is to use as many gates for data type.
It would be also possible to use route/routepass
on that last midievent outlet.
All you need is to play with channels - raw midi data.
@SourceAudio, late to the party again!
Look at Neil's original post and I think you'll see that he's using a "recent" version of Max where midiparse has the rightmost outlet generating midievents and vst~ that requires them:

@Neil, back to triggers! This is an example where I'm sending lots of sysex messages to my control desks that need to go in precise orders and timings to work. As you can see, I've used trigger in several different ways with different parameters to pass data and to control the order of events:

@ andy much talk less facts as usuall ...
I find nothing wrong with helping someone understand that that simple gate
solution works.
@SourceAudio - try reading the whole thread! Using gate was my very first suggestion (along with an explanation of why he was struggling with his method)! And Neil was perfectly happy. End of story!
At the risk of being rude, you keep coming in late on established threads with suggestions that are clearly based on your undoubtedly considerable (historical) experience but in a manner that is condescending to those who have already made perfectly reasonable suggestions. (e.g. " Logic itself should have been enough to find that out.") You could have contributed right at beginning, suggested gate then and solved Neil's problem. So there, I've said it now. Report me!
Thanks everyone for your contributions. I've only been using Max for a few weeks, and began with the latest version. Previously I've used a little PD, as well as Reaktor and Bidule. So I'm still in the phase of translating my existing knowledge into Max.
Andy, thanks for posting your patch. Could you say what control desk this is for? It's interesting that you post a sysex example right now, as that's exactly what I will be tackling next. I will be sending sysex to my hardware sequencer.
It's a pretty major project! I have 4 X-Touch mixer control desks (one X-Touch and three extenders) physically bolted together to create a 32 channel mixing desk. It either drives my X32 Rack mixer through an application called Mixing-Station or it drives CuBase Pro. My Max project sits in between the desk and the applications, allowing seamless "live" switching between the two modes and adding quite a bit of functionality in the process. My app has to maintain a dynamic memory for the inactive application as well so that when I switch, the desk instantly shows all the correct settings.
The X-Touch uses normal MIDI data for most things but the little LCD scribble strip panels for each track need sysex to drive them. There's also a bit of OSC thrown in for good measure for direct access to certain parameters on the X32 that Mixing-Station doesn't currently support, such as displaying the current Scene name on the X-Touch numerical display.
Oh, and the numeric display also runs a clock/alarm/timer when it's got nothing better to do!

There's about 25 patches all hidden behind this rather simple looking front end!
Regarding the timing issue with [midiparse] outputs :
I've reported that to Cycling'74 and if I interpret their answer right, they are already tracking this one.
"Roman, your 2 object version doesn't handle CC, or program change, or aftertouch, or pitch bend..."
what works for [notein] also works for [cntlin]. (i am not so sure now if it works the same way for xbendin´n stuff.)
but indeed, it doesn work with [midiin], which only allows a "port" argument.
"Roman's gate is perfectly allright, all you need is to understand that there "
it could as well have been what andy thought what was wrong... i often mix up the inlets of [gate] because i mostly use something very special called [110.gate] which has the inlets in the correct order.
haha.
Which package does 110.gate come from Roman?
the famous 110.package, of course.
Yes, but where does one find this famous 110.package?
110.shelter/110.datacenter/192.168.100.101 - 192.168.100.114 /MacOS9/Max4/patches/
Oh dear - Mac only! I’m a Windows delinquent!
Hey! Is there anyone here who can help me with this similar problem? I would appreciate any tips/pointers if you would spare some of your time.
https://cycling74.com/forums/how-to-distribute-incoming-individual-midi-notes-to-different-midi-channels-by-order-they-are-triggered
I tried out the [gate]-solution that worked for Neil, but if I understand correctly the MIDI event message is made to speak with [vst~], and I need aftertouch/pitch/etc. on seperate outputs. I am making a MIDI channel translator in a way. More details in the post on the link. Thank you so much to anyone who could try and help.:)
Can you be a little more specific about your aims? Do you simply want to send each successive midi message to the next midi channel in a cycle, do you want to send each message type to a separate channel, or do you want to send all messages that arrive between one note and the next to go the same channel as the leading note? Or something else?