@impression I think it's not possible to avoid the central problem, which is associating a note-off message with the prior matching note-on message. Unfortunately, this problem takes some careful thinking. It's tempting to avoid doing this careful thinking at the incoming-message stage and try to push the problem off to another part of the patch. But, I think everything is going to be easier if the note parsing is done correctly in the first place.
I think you will need one [text] just to parse the messages into chords, and then another [text] as a chord repository.
The basic flow I'm thinking of is:
-
Use [poly] to assign an index to incoming note numbers. (Why? Because, when a note-off message comes in, you have to find the matching note-on record and look up the time. Then you can use that time to calculate the duration. There is no way to do this without matching note-on and note-off, and [poly] does this for you.)
-
Note on: Some jiggery-pokery to rearrange the note-on data into the format "poly-index timer-value note-num velocity" and then write this list into a [text] at the row number where that index lives.
-
Note off: Find the [text] entry matching index, unpack it, subtract the current time from the message's time (to get duration), pack into the desired format "note-num vel duration' and add to the current chord.
I had to make a decision about how to know when the current chord is finished. In this patch, it's when all notes have been released -- [pd notecount] gives a bang when a note-off decrements the active note count down to 0. That may or may not be right for your use case, but that part can probably be adjusted without requiring too much surgery on the rest.
In any case, in the end I get messages such as the following:
chord: 69 101 394.739 62 101 394.739 60 101 394.739 64 101 394.739 67 101 394.739 71 101 394.739
chord: 65 101 394.739 72 101 417.959 67 101 394.739 69 101 394.739
chord: 71 101 394.739 65 101 394.739 60 101 394.739 62 101 394.739 64 101 394.739 72 101 394.739
chord: 65 101 394.739 64 101 394.739 67 101 417.959 72 101 394.738 71 101 394.739
... which could be read out in groups of three for playback. (The durations and velocities are all the same because I was testing with MIDI notes from SuperCollider -- I had specified a duration of 400 ms for each note and Pd is pretty close to that. So I think that confirms the approach.)
(Note that it's a good idea to reset the [timer] at the beginning of a run -- I set up MIDI controller 37 as a trigger for that but you could do it any other way you want.)
hjh

midi-parsing.pd