OB-6 control via M4L

Working on this since a couple of days as interlude to my grand project (the one that doesn’t exist) just to relax and see different things than C++ and C. While patching and coding this Dave Smith Oberheim 6 Control many discoveries what works with M4L, what not even if documented. NRPN is still a troublesome object in Max for Live, in example it can mess up your unit by false sorting of the command structure, so ended up like many implementing my own transmitter that takes care for it.

Not in particular a YT fan, but to upload it here it is simply to large… so you might want to click over to gööglë to watch and hear. Ok the sound is not particular amazing yet as i am just testing and forcing the controller to do its boundary stuff that can fail… no other chance to find the culprits and eradicating all before publishing a final.

I am curious how you control your OB-6, do you use NRPN at all for it?

Well the same controller would likely work with pure CC’s as well but some functionality and values are not reachable via CC, in example forcing to record incoming notes into the sequencer.

ps: catching a coffee at my favourite spaeti and watching people Move down the road to Ableton HQ. lol

4 Likes

That’s a nice UI !
I made my own stripped down controller for my OB-6, but honestly never bothered using NRPNs…

1 Like

So i should at least go thru all controls and mark which are not available in CC-mode. Maybe i can even make it work in one and the same M4L Patch… being able to switch between NRPN & CC.

telling a bit about the journey of last week:

speed

Figured, it might be worth to develop an entire dedicated NRPN or even CC buffer emitter that simultaneous keeps track of last states. The M4L ‘zl’ object is certainly good for that but cpu intense compared to my other trials making an special ARP that punches 7’voice chords notoon&off out in 128t, which is fast i guess…

stalling midi buffer overflows

the main problem on midi output in ableton seems to be that M4L allows to directly send into the midi buffer of the ports without any regard to possible overflow of already buffered data on the same midi ports. Which most likely in many other M4L patches is the cause for defer(low prio thread function calls) latency and hickups or even completely stalling until that very overflow can be resolved by stopping. But stopping the playback means also stopping metronomes, and stopped metronomes cant drive render loops nor uzi objects that shall cause buffers to spit out data partially one after each other to make a signal serial output. In most cases developers might wonder and try to output one big chunk of data like coughing into the buffers (which is the case with while datasets of nrpn usually). So my thought: if i create my very own m4l extension in C that can send timely regardless the metronome, then i can also speed up below the 1ms or 1tick boundary… midi is math after all.

Button design

live.tab & live.text are very useful compared to buttons and knobs. But do not scale nice, i mean they do scale but some pixels get always chopped of cause of floating point errors. Kinda expected but was a surprise to me, because can be avoided if some dev would think about… It can certainly be prevented with jweb elements or even jsui. Where jsui is extreme more code for little output, so jweb like html5 development makes it very easy.

jweb vs jsui vs default ui

To this UI, which is a half jweb, half standard max4live elements. And to make the font for the Ob6-LED was fun too in the morning. But fonts cant be loaded in max unless they are part of an extension and then no guarantee it would work on windows, but in jweb you can of course load a font with css and voilá… So tshirts comming next - awkward smiling.

again: preventing overflows

there exist an object named qlim which prevents just that but it also prevents events from output at all, events that come below the treshold (timing given) are simply skipped, so its more some sort of qchop, kidding. Better not using that unless you really want to stop stuff from output to much…

speedlim

is your friend in general, but beware you must set a speed limit for data that is slower than that for the UI elements given, otherwise it does nothing good…

apropos keeping large datasets of properties

the pattr & pattrstorage objects are really cool, they can hold that much data and scale between each value (live), also store an recall as you like… so much so that you must keep an eye on limiting what it outputs, otherwise you are in caption 1 like written above again…

and because you will likely use the pattrstorage object, as soon you want to have a second state kept in your structure in example like i did to control what pattrstorage can even output, you need another object to handle those states, in example the coll object… which ultimately leeds to extra parsing and again using zl objects to output results correctly (in nrpn sorting matters very much)

idea of the UI

Well the idea was to keep as much look and feel as possible so to avoid double think what is what, i have an OB6-Desk.

next

One goal for the next days was to figure out if i can bundle max extensions properly with a maxpatch and this way ship special capabilities that are not available in the default m4L/max libary.

fun in coding hell

is it possible to subclass live.dial objects? Subclassing means just to keep an API as is and add new features… think think

1 Like

ok the journey goes on.

can i extend live.ui objects ?

yes, i can extend the attributes offered, they get also stored with the patch, so i can rely on their extra data given by user safely.

can i connect to pattrstorage automatically and orderly?

yes, i can find the object in the patcher and do the needed messages without extra cable salad

can i limit certain UI elements (controls) to be allowed to ‘autopattr’ and others not?

yes, it is a common problem in M4L and MAX in general when using pattrstorage linking the pattr’ed objects will be linked to pattrstorage as soon autopattr is used. This will likely mess up your preset data and become unreliable in some cases. Problem solved, i do the lookup by a name scheme used in varname (alias scriptingname) automatically. The whole patch is searched for such elements and automatically subscribe’d to the pattrstorage. Parallel i build up a lockup mechanism that allows to midi map either NRPN numbers and+or CC numbers. Which means no cables are needed to each UI element anymore. The communication to and from them is even shortened and centralised, which in turn allows for more complex tasks, like mapping automatically midi range values to NRPN range values and wise versa.

Can i find the patchername from within the patcher

… without javascript (slow)? A functionality not meant to exist until now, max just doesnt have any object that can tell you the tree of your patchers. So i wrote one explicit extension object to do just that, worked like charm. But that needed to be placed in subpatchers so it climbs up, but i try also to get rid of not needed cable salad and fasten up stuff. Well - until I figured out I can just do the same when searching the entire patch for “_varname” objects, find the according tree name and automatically subscribe to pattrstorage, read the NRPN and CC mapping given to each of those UI controls and build up the faster access lockup table…

centralsed midi NRPN & CC feeding

As now i have an lockup table that finds UI elements by CC number or NRPN number, i can just receive the data and fastforward the messaging with a direct call to the setter of the INT values.

No cables? but how do you get the integer values of the Controls out?

no big deal, same as i’d do with slower javascript, i simply let Max do what it does best, which is finding function pointers, object names and automatically notify… So i let my grand brainy extension be notified when the controls change, just like pattrstorage does as well, and from there implemented the midi CC mapping to NRPN or from NRPN to CC or even as is and punch that out as list’s feeding the midi out with data…

…and voilá

i have a fast, scalable, reliable, easy to program, visually clear maxpatch environment that can serve any NRPN/CC machinery with scaled presets recalled from pattrstorage.

Where to go from here?
I’d like to implement somethig that is similar to speedlim but for a whole buffer of midi command’s, kinda like a state-machine, so it knows if a midi byte has to be given out directly or came so fast in that i can simply replace it on the stream before is overloads the midi stream.


(photo, see no cables for controls, autopattr and pattrstorage present, and live.dial and the other 4 UI classes have the extended attribute)

wondering why this is/was not default part of Max4Live or MaxMSP… scratching my head
ps: for those who come along and might ask, but but there is fixed mapping of midi on live controls, this should mess everything up in ableton… well - nop, this extension is only at work when pattrstorage is involved, autopattr present and ‘my’ “find” (want likely to open source that) object placed in a patch. Should even work on push3

so, now it could be discussed how that brainy thingy i called “find” for now could be named… maybe ccpattr or subscriber or… any ideas ?