How to force MIDI chord notes to NOT be sent simultaneosly?

Sonoran Music Devices's icon

My understanding is nothing in the Max scheduler happens truly simultaneously. However, when I send a MIDI chord from midiin into a pipe, the pipe delays all the notes by the same amount. When I print before and after adding the pipe, all the notes are spit out together - delayed by the same amount set in the pipe. It is like the pipe is trying to intelligently keep the notes together or something. I need the notes sent out separately.

I have tried flushing the pipe after each note, but no dice.

I have tried routing my chord notes to separate pipes and delaying each one by one sample more than the other. E.g., pipe 1 delays by 1 sample; pipe 2 delays by 2 samples, etc. It seems to work, but it seems clunky. Plus, I want to eventually add messages from Live parameters (e.g. live.dial) to the mix, and I need to make sure Max does not try to send those at the same time with the chord notes like it is doing with the chord notes. Ultimately, all this MIDI is going to get blasted through a single live.remote~, but I need to send the events separately.

Any ideas are most appreciated.

Why am I doing this? I am trying a technique to use one live.remote~ for many parameters as discussed here.

TFL's icon

I understand that you want to add time between each notes of a chord you receive from [midiin]. This is not what [pipe] does. What it does is to delay all incoming events, but the elapsed time between each event remain the same. They just happen later, but at the same speed. You can see that very clearly in the [pipe] helper patch when you change the number by hand. No matter how fast you go, the output will be as fast, just later.

It seems what you want to build is called a FIFO, "first in, first out" list acting as a memory buffer, storing any incoming data, allowing you to output them however you want, at any given speed, one at a time or in bulks, in the same order as they arrived. But you have to understand that if you output your data too slowly, or if there is too much coming too quickly, you will end up with huge delay between a latter event arrives in the list and the time it gets out of it. You can find examples of FIFO lists in the forum.

But now that I re-read your post more carefully, forget about what I just said, it seems that you just want to be able to get your notes separately, and this is what happens already. It seems you just miss how to observe that. The fact that these notes are printed each in their own line in the console means that they arrive one after the other.

I need to make sure Max does not try to send those at the same time with the chord notes like it is doing with the chord notes

It is not what Max does. Each note, each CC control arrives one after the other, period. In fact there are even Max objects to do exactly the opposite: regroup notes into chords, because they always arrive as separate notes. Check [thresh] and [quickthresh]. What makes you decide if a succession of notes should be treated as a single chord or as a very fast arpeggio is the delay between them and your opinion on that. But in essence, they always arrive one by one, one after the other.

About what you're trying to achieve with live.remote~, I struggle to see the link with the current question. But using a single live.dial + live.remote~ to control 128 different parameters each using a different range of the live.dial also means that you divide the number of events (ie the sample rate) by the number of parameters changing simultaneously. Given that each sample (each change in your live.dial) can be used for only one parameter, if you update the value of all 128 parameters at the same time, you will use 128 samples for that. And if your 128 parameters keep changing simultaneously, they will get updated every 128 samples only, skipping values in the way. It might be fine for some parameters, but much more of a problem for parameters requiring audio-rate control.

Roman Thilenius's icon

before dealing with data input from outside build the same thing using data from within max to understand what the objects actually do.

even successive messages in the scheduler thread will always be delayed as ordered.

i bet you tried to send a list into pipe. :)

Sonoran Music Devices's icon

@TFL

Each note, each CC control arrives one after the other, period.

That’s what I thought. Given further testing, it seems the rate of data is simply too fast. Speedlim is not a solution since it apparently can lose data. This solution posted by @BROC offers the most elegant way I have seen for slowing data down non-destructively. I tried it, and it seems to work. Delaying my MIDI messages by 1 sample seems to provide enough separation for the target live.remote~ to handle it. I have no problem latency compensating that delay. Hopefully that holds up during further testing.

Given that each sample (each change in your live.dial) can be used for only one parameter, if you update the value of all 128 parameters at the same time, you will use 128 samples for that.

A live.dial - with a float data type - can handle at least many thousands of different values. In theory, I have plenty of values to work with, and there will be no audio rate modulation. Your explanation about the sample rate was elucidating though.

About what you're trying to achieve with live.remote~, I struggle to see the link with the current question.

The link is this: I use notes AND and live.dials for control messages, and I am trying to get away with using one live.remote~ for controlling many parameters as I mentioned in the OP. I can explain why I want to do that if you are interested.

Your explanation of pipe is what I was seeing when I print, but that really helped explain what I was seeing.

I am grateful for your reply, and if you have any other insight, then I am all ears.

Thanks again.

@Roman Thilenius

i bet you tried to send a list into pipe. :)

No, I am simply sending MIDI events (specifically, right now in my testing, only the note on pitch values, which are ints). @TFL's reply helped me understand what I was seeing when I was testing and printing. Thank you for the reply though.