[Sharing] 3D piano roll visualizer
![](https://cycling74-web-uploads.s3.amazonaws.com/5891df4152004cf45a9f27d2/2023-11-22T16:47:57Z/Sans titre.png)
Hi,
Answering this post, I found fun to try to create a 3D piano roll visualization of incoming MIDI notes.
How it works basically:
- The geomtry is based on a simple [jit.gl.gridshape @shape cube] attached to a [jit.gl.multiple]
- A [jit.matrix 3 float32 1000 1 @name notes] is made to store the note history. A history of 1000 works very well, it can go higher without issue.
- Using a [counter 0 999] to address each new note to the next matrix cell
- Using a [poly~] to keep track of held notes and editing the note and velocity value.
- Using jit.gen and a couple buffer matrices, each cube is scaled through the y axis as long as the corresponding note is held, and everything is translated through time.
- I struggled with the reset system due to the feedbacks. Had to create some kind of global gate that would send 0s everywere at once.
Have fun!
Hey TFL,
This is amazing and just what I needed many thanks for this!!
I basically understand what you did, this approach is a good way to go with this, but very specific to Max.
@cycling:
To be honest sometimes I wish Max could me more like Processing in this respect. It would be cool to have like a straight forward poly possibility for jitter e.g.: You put a jit.gl object including features inside a sort of jit.gl.poly and instanciate it for a particle system for example. Here you did instances with a matrix inside poly, this is surely possible but you really need a deep understanding to go this way.
cheers Falk
To be honest sometimes I wish Max could me more like Processing in this respect. It would be cool to have like a straight forward poly possibility for jitter e.g.: You put a jit.gl object including features inside a sort of jit.gl.poly and instanciate it for a particle system for example
I think you are mixing up various concepts.
- For a particle system, just use a jit.matrix to store your particles (one cell = one particle) and use it to feed a [jit.g.mesh @draw_mode points] to draw each vertice as a point. You can also use [jit.gl.buffer] and [jit.gl.tf] to efficiently perform transform feedbacks on your particle system.
I feel like the jit.gl.poly you are describing is actually what [jit.gl.multiple] does: dynamically creating multiple instances of a [jit.gl.mesh] or [jit.gl.gridshape]. I am using it in the patch as each note is basically drawn from the same cube geometry, but scaled and positionned differently. The thing is, you also need a way to "record" every incoming note and modify the notes matrix accordingly. Given that you could receive a held note while simultaneously receiving shorter notes (because polyphony), it's not that trivial to keep track of which data to change and where. And for that purpose [poly~] is very helpful. I could have done it differently but that would have consisted of basically recreating my own poly~.
You could also not use [jit.gl.multiple] at all but only [poly~], and put the [jit.gl.gridshape @shape cube] inside of the [poly~] patcher. Each voice would be attributed to a unique note, and once you reach the poly~ limitation of 1023 voices, you start over from first voice. This solution might be less convoluted than mine, but you're limited to an history of a total of 1023 notes, and I have some reserve about its efficiency, as I assume having 1023 instances of a [jit.gl.gridshape] is more costly than using only one with a [jit.g.multiple].
Very nice. I‘d love to use this for setup with my dual manual Hammond which outputs 61 notes from the upper manual on midi channel 1 and 61 notes from the lower manual on midi ch 2.
any suggestions ? 🤔