Piano roll with totally Customizable UI

Lid's icon

Hi there, I’ve been searching the forums here trying to find a way to do this, but the closest external that might have worked no longer works on the latest Max version [Max8].

Basic piano roll functions I’m looking for
- can record and playback MIDI events
- each note stores pitch and duration info (velocity would be a plus)

UI Customizabilty
- flip the UI timeline vertically
- I’d like to be able to place two or more timelines on top of each other with opacity control
- size and colour of notes

Does anyone have any experience regarding objects that might fit the bill and will work with the latest version of Max?

- Brett

Roman Thilenius's icon


detonate & custom jitterbased ui

Lid's icon

great thank you, I’ll check it out

Lid's icon

Hi Roman, in reflection I have missed listing a function that I would like to have- in the UI I'd also like to be able to enter MIDI events with a mouse click. Would your method of using detonate with a custom jitter-based UI still be applicable? Using jitter as a UI is new to me... I've been looking at- https://cycling74.com/forums/gui-inside-jit·window - so the idea is to create the piano roll basic "editor" with a jitter UI?

Lid's icon

I'm finding it difficult to search the forum... the relevant searches are from a long time ago, probably outdated... and when using the "newest first" I get a ton of irrelevant posts. Tried searching via tags and that might be a little better but... still nothing too accurate. The older relevant posts are pointing towards using javascript for the UI... unless Jitter has some newer tools relevant to creating UI's?

Roman Thilenius's icon


you should be aware that creating a fully functional piano roll editor with the max board tools is probably more work than creating fully functional piano roll editor with swift or objective C type of tools, and that you are going to create a patch which is "bigger" than what many people do with max.

but if you actually start(!) to makea very basic version you will also be suprised how simple some things are. for example one of the things a piano roll editor does is that it draws a rectangle by mouseclick.

have you built something which does that already?

i straight on recommended jitter because of the "vertical mode" thing you want.

doing these things using video matrixes and the pwindow object jitter has a few useful "features" such as simple rotate and scale, and a comprehensive mouse&modifier keys output is already coming with pwindows for free.

inside such a video diplay you can combine lcd, GL, pictures or even draw single pixels and process them afterwards if required, so you remain flexible, which is not the case with all other solutions.

Lid's icon

Thanks for all the info Roman, it's very helpful. I have previously built some basic editor/UI stuff with the multislider and jit.cellblock objects, but I'm coming from the audio world... almost all my experience has been with Max/MSP, so Jitter is fairly foreign. I didn't realize how powerful the Jitter pwindow object is... just messing around with the examples it very well could be what I'm looking for. I'll try this all out and report back here.

testcase's icon

the pianoroll object doesn't meet all those requirements but it might be a place to start.

Lid's icon

thanks for the suggestion @TESTCASE, but I was actually checking that object out today and true, doesn‘t quite fit the bill. I won't budge on the vertical alignment idea as I have a pretty strong vision of how I want this to work. The idea is to have some functions of a basic piano roll editor but the main purpose is as a writing tool... for analyzing tonality/scales.

Xaver Römer's icon

Hi,
I wrote a typical pianoroll for pd some time ago. It seemes to be what you are looking for, I guess.
I had no needs to adapt it for max, so it's still pd only.
Greetings Xaver

https://github.com/XRoemer/sequencer-and-editor

Lid's icon

Thanks for the info and link Xaver, I had no idea pd could be used with a GUI like this... cool! I have no actual experience with pd, so I'm probably going to try and work this through Max and Jitter (I'm slowly breaking ground here), but I'll also keep pd in mind.

Iain Duncan's icon

Xaver, that looks amazing. I'm on the verge of releasing (properly) Scheme for Pd, and look forward to hooking that up to the Scheme interpreter! Thanks for sharing.

Iain Duncan's icon

I would agree with Roman that this may be something where the scales tip over to being easier in C/C++. I would also say that you are perhaps looking at two questions that may be better analyzed separately: the piano roll is a representation of sequence data, but is not really the sequencer. I have it on my bucket list to implement such a thing myself with Scheme for Max, this kind of work is actually why I made S4M. You may well want to even have the two sides running in different Max threads. The piano roll part can be done in the UI thread, but your sequencer should obviously be running in the main thread. My personal approach to this (so far prototyped with a drum grid style interface) is to have a low-priority s4m object running all my UI interactions, with a data store that is cloned into the sequencer engine. Not sure if those rambling's help. It's a big task!

Roman Thilenius's icon


an [idetonate] which supports controllers (and any float! parameters, and symbols! for that matter), and of course with custom colors and opacity layers like mentioned from the TE. it is on my to do list also. and it will remain there for a long, long time.

Xaver Römer's icon

Hi Iain,
I wrote the code 4 years ago, so I don't remember exactly how it works anymore.
But gui and sequencer are separated and they communicate via tcp, so its asynchronous.
And I have chosen nw.js for the gui, because:
1) To write some kind of code (js and html), which I found much easier to handle than doing it inside pd (I tried that first).
2) I wanted to be able to open more than one gui window
3) and a browser has lots of advantages for handling mouse events, scaling, drawing etc. and is quite fast.

I wrote a similar gui for the display of my Push2. And I did it with jit.mgraphics (my first time with jitter). But I've found it quite complicated. Layering and deleting objects in a browser for example can be easily done, and the browser takes care of drawing it correctly. In jitter I always had to redraw certain parts.
Also I had some issues to draw 1px lines in jitter. But maybe it's just because of my bad knowledge of jitter.

As far as I remember, I had an issue with the tcp connection on open/close/reopen windows. Maybe it's possible to use node in max instead of nw.js. I think I tried when I stepped over from pd to max, but it didn't work right out of the box.

Xaver Römer's icon

I created a version for max. It can be downloaded here:
https://github.com/XRoemer/XPianoRoll

Iain Duncan's icon

Fantastic, thanks for creating a Max version! I look forward to playing with this. :-)

Iain Duncan's icon

It might be a while, as I have a lot on my plate right now, but I would like to hook this up to my Scheme based sequencers, and when I do, I will let you know Xaver. Following on github!

Lid's icon

Thanks for all the resources and info Xaver and Iain. There’s lots of new information there. The idea about using a web browser for the UI is very interesting to me… because it’s universal… and common. Cool stuff!

Xaver Römer's icon

Iain, give me a feedback when you have tried it out.

Iain Duncan's icon

Xaver, I definitely will. It might be a month or two as I'm trying to get new releases of Scheme for Max and Pd done, but I'll get in touch. :-)

Lid's icon

Xaver, does your XPianoRoll support vertical scroll orientation? In the demo pics it's all horizontal, and in the description it makes no mention of this ability.

Xaver Römer's icon

Yes,
scroll x - scroll wheel left/right or scroll bar x, scroll y - scroll bar y
zoom x - scroll wheel, zoom y - ctrl scroll wheel
when y axis is zoomed in the scrolling by wheel gets inconsistant and it's better to use the scroll bars. needs some revise.

Lid's icon

I don't think I was clear enough in my wording. I actually mean the timeline being vertical instead of horizontal (that time scrolls "downward" as it moves on- or the cursor moves from top to bottom across the notes). This is one of my major requirements.

Xaver Römer's icon

Well, not really.
But you can set line 40 in index.html to:
<body style="margin:0; padding:0; font-family:verdana; transform: rotate(90deg)" onload='init()' >
than the whole document will be rotated.

Lid's icon

lol... check out how I received my last reply notification email from Cycling

Lid's icon

well... I'm guessing that rotating the whole document will not be quite what I'm going for... but I'll keep it in mind in case I get really stuck with what I'm doing, but so far... I'm working with mtr and jitter/openGL and making slow progress, and it's starting to make more sense. Definitely it's worked out that there's a clear divide in the processing regarding sequencer versus GUI.

Roman Thilenius's icon


¿ʅᴉɐɯǝ uoᴉʇɐɔᴉⅎᴉʇou ʇɐɥʇ ɥʇᴉʍ ƃuoɹʍ s´ʇɐɥʍ

Lid's icon

lol

Xaver Römer's icon

:)
If that's possible, what else would be possible?

LID, usually I would use another editor for editing midi, like Live or Reaper. I wrote the piano roll for pd, where I did not have that choice. But maybe it's handy for someone who wants to stay inside max. Or who doesn't want to start max from Live. - this process of starting Live, starting Max, starting a maxpatcher you work on, is timeconsuming and if you have to do that a couple of times... well, one reason to use purely max.

If you want a custom design of the editor, it might be a good a idea to write a program for a browser. There are games written for browsers so the abilities are great. Doing it over again I would use [node.script] as it comes with max.

Is it possible to use jitter asynchronous for splitting gui and dsp processing? I guess it is, but I don't know.

Iain Duncan's icon

Ah Xaver, sounds like are working very similarly to me, I also pop back and forth between all of those!

I started working a while back on one that I did as a Max external in C, using their Cairo-like low level drawing toolkit (though mine was more of a drum grid than piano roll). I got distracted by other things but mean to get back to it. It definitely runs fast within Max if done in C. I had been tossing around the idea of doing the next iteration in Juce and letting it run outside of the Max process with a shadow copy of the data, so I'm interested to see how you tackled it.

iain

Xaver Römer's icon

Iain, it's quite simple. I start nw.js via shell and set up a tcp connection. So nw.js is a separate process and runs on its own. Dsp has to be done in max. And max sends an information of the time position and the tempo only on start, stop and the beginning of a beat to keep the gui in sync. nw.js processes the time position while running and is updating the gui.

Iain Duncan's icon

Ah, so do you mean your sequence data is also stored outside of max? I'm currently exploring doing it by having the engine own the sequence data in the high priority Max thread, but publishing changes to a read only copy of the data in the UI thread. Essentially like a frame buffer but for sequence data. I was thinking of trying this out with the shadow copy completely outside of Max.

Xaver Römer's icon

Yes, the data is doubled. Maybe that's a disadvantage, but after loading the gui no calculations have to be processed while it is running (besides the transport bar). The browser gui gets just scrolled. And on editing only the changes are send back to max.

Iain Duncan's icon

I think that's a pretty common pattern for music apps, makes sense to me.

Roman Thilenius's icon


in theory, you can use a regular patcher window for that kind of stuff (what i mean is: scroll the whole window)

the only problem with this is that lcd or pwindow objects have size limits. ;)