Note Order of "flush" Upon Receiving bang

Nick Suda's icon

Hi all,

I'm building a simple little MIDI virtual keyboard Swiss Army utility for test automation purposes at my job.

Just a floating widget to be opened in standalone when I don't have a keyboard or any other MIDI device handy to send things some note on and note off messages.

Currently, the 128-note wide kslider in my proper patch is "dumb" to the responsiveness of mouse clicks; when you click a note it just sends information to makenote at a fixed duration of 100 ms.

I'm trying make kslider behave more like your average "onscreen keyboard" that you would see in someone like NI's plug-ins (or, more importantly, my company's :O ). As in, the onscreen widget is monophonic, but it highlights whatever key is being pressed down and you can drag all around the keyboard and trigger a cascade of note offs - until you hold your mouse down on one note - and then that one will hold in duration until you release.

So I snapped off makenote for noteout and got some cheap-o mousestate polling action going to make kslider pretend like it isn't so old - a mousebutton release bangs a flush in the stream of note-ons, and sets the kslider to note 129 - off the range of MIDI notes.

Max Patch
Copy patch and select New From Clipboard in Max.

This chunk of patcher is a sliced of and semi-prepared bit to help with asking my question.

You wanna pay attention to the note pitch / velocity combo message that I put a green circle around.

Please click on a higher note on the kslider and drag your mouse down to a lower note and then release, paying attention to the last note off the the mousestated bang to flush sent.

Note that this "higher notes first" behavior is inapplicable to starting on a lower note and dragging up and releasing on a higher note.

Is there some way that either flush can be swapped out for some cockamamie subpatcher madness that doesn't follow this internal logic, or some configuration of arguments or something that would make flush just kill whatever the LAST note was LAST, regardless of low or high?

Thank you,

Nick

Christopher Dobrian's icon

I'm tempted to ask why it matters, but I won't.

Max Patch
Copy patch and select New From Clipboard in Max.

Here's a off-the-top-of-my-head solution, which appears to work but is probably not the most elegant way possible.

Nick Suda's icon

Christopher,

Thanks for the help. I wasn't raised with good zl ethics, so I always forget to think about how a good mode of zl could help me out. ;)

Unfortunately, this block isn't still quite running the behavior I'd like, because it's not queueing redundant instances of notes, only stacking first instances in bag.

"Unidirectionality" has been corrected with your configuration, but "unconditional direction" has not.

For example, if you start with a low note, drag up to a high note, and then go back down to a low note, you will find that it still plays the release segment of the "highest note crossed" first.

It "matters" (so to speak) because it needs to be reflective of the user's interaction with the notes via mouse. Releasing a mouse click and hearing the release segment of the highest note that the mouse dragged up to is not an expected behavior. Ideally, the "note killing allocation" (since it is modularized into two separate processes, vs. something like makenote) would line up consistently with the aural behavior as well, since it could start getting sticky when the device supports multiple MIDI channel outputs in simultaneity, etc.

I can get "redundant stacking" via unpacking the end of the chain and sending the note and velocity outputs to noteout, but then this weird behavior sets in where the first recieved note isn't played, in addition to still having the "highest note release" behavior.

Christopher Dobrian's icon

>> "Unfortunately, this block isn't still quite running the behavior I'd like, because it's not queueing redundant instances of notes, only stacking first instances in bag."

Understood. You're right about that.

The flush object will never give you what you want because it sends everything out in low-to-high order regardless of the order in which it was received, so all original ordering information is lost.

I'm still not convinced about the "why it matters" part. The difference in when the note-off messages will occur is a matter of milliseconds (one millisecond per MIDI note message), so it's unlikely that anyone will hear the difference and care about it. It sounds like your concern is more hypothetical than empirical at this point, but if you have a patch that demonstrates it being audibly bothersome, I could of course be swayed. :)

In any event, if you're determined to preserve the original order, you'll need to avoid flush and roll your own, with borax and coll for instance, or with zl queue.

Christopher Dobrian's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Something like this...

Nick Suda's icon

Christopher,

I've been sending my "from Max 1" output to a channel strip in Ableton Live 8.3 - just running any old patch in Absynth 5 for demoing. Release order may not seem like it's doing anything going to the 001 Grand Piano of AU DLS Synth or the Windows MME GM engine, for instance, but in some Absynth 5 patches and in other VSTi/AU instrument/etc. guinea pigs I've been playing with, the patch will terminate with a decay portion of the highest-played note, despite having been passed-over in the MIDI performance ages ago.

Perhaps I can find a nice free, cross-platform instrument that will demonstrate this behavior, and verify that the issue is independent of the host and OS - in which case I'll point you to that configuration, so that we can use the same model test case.

(This is assuming you don't have Absynth 5/anything applicable from a Komplete distro, Max 6, OS X 10.7.4 "Lion," and Ableton Live 8.3, in which case, lemme just find something that works, haha!)

I thank you for sticking with me through this, though. I don't have a chance to try it out at this moment, but I will play with it when I have the time at home this week; it's saved into a maxpat from my clipboard, ready to play with.