OSC Stream Processing in Max
I’m happy to see all the recent interest in OSC on the Max list! In light of some of the recent discussions, I thought I would mention a library of objects that have been in development for some time at CNMAT that operate on OSC data directly (as opposed to OSC-route which operates on OSC-style Max messages). You can find the objects here: http://cnmat.berkeley.edu/downloads/odot (they’ll move to the main downloads page in a few weeks once I’m done reorganizing it).
There are two papers from 2011 here:
Although the objects have changed (significantly, in some cases) since those papers were written, they still serve as a useful introduction to the basic concepts. We have a new paper that’s just been submitted for review that should make its way onto the website soon.
These objects are being used quite heavily in a number of projects and are stable and performing well. That said, if you run into bugs, have ideas about how they can be improved, or have any questions, feel free to email me directly while we set up an official issue tracking system.
Would you care to provide a quick overview as to why these are more appropriate/useful/better than the older stuff? Is there a reason to switch to them if the older OSC-route stuff works?
I had a (quick) look through the papers and it looks like these are multifunctional objects, rather than OSC connectivity objects.
So they would replace a bunch of regular max objects (and then some) rather than let you do the same kind of things using max objects (and only using OSC on the input).
Probably a gross oversimplification.
I just want native OSC parsing….
That big difference with these objects is that they are passing around actual OSC bundles, rather than OSC-style max messages. If you stick some regular print objects in some of the help patches, you’ll see that o.objects are sending "Full Packet" messages. These are similar to jitter matrices or dictionaries. What it really is is a memory pointer that’s being passed around. If you put updreceive into compatibility mode, you’ll see the same kind of output.
If you have time, read John’s paper: http://john-maccallum.com/writings/odot_icmc_2011/odot_icmc_2011.pdf But briefly, it’s an introduction of a new, powerful data type into Max. OSC messages can be grouped into bundles that are treated atomically, and have high resolution time tags. Passing memory pointers is more efficient than passing messages made of symbols and arguments. These objects enable a different style of programming inside of Max. That probably won’t appeal to everyone, but there are some big ideas here.
I see, so it’s a new data type, period. That data type just happens to be OSC.
So it doesn’t really do anything for regular OSC parsing (do the o objects replace OSC-route too?).
The way I understand it is basically as a streaming data structure, where you can operate on the data inside arbitrarily. For instance with a xyz controller that is sending OSC bundles, you set your udpreceive to cnmat mode, and then you will get your /x /y /z parameters streaming together in one OSC bundle — which is really nice for mapping, also useful for higher order processes.
o.route works with the old max message style too.
One nice thing with o.route when you’re using bundles rather than individual messages, is that you can choose which direction the bundle routing happens. Useful for when you need things in a specific order, for example getting amplitude last in a poly~ voice.
I don’t have a problem changing to new ways of doing things (in fact, I think it’s very critical to be open to change otherwise one gets left behind) but it should be reasonably clear what will be the benefit of the change. I’ve downloaded the papers so I’m hoping there will be an explanation for the different style AND the benefits of switching to it over what already exists.
These objects enable a different style of programming inside of Max.
jeez. that is an astonishing collection of externals. damn you cnmat.
it would be good for o.call and perhaps o.route to have internal mapping options before output, such as exponential etc, rather then max objects directly after taking up more time.
also, the o.grandstaff referred to in the article is not present in the download. why? i am interested in that option. although i can already imagine [o.2bach] or [llll2o.] and vice versa abstractions or so.
it is a worry the library is so big. not enough time to really go into it much now either. anyway, congratulations. some more quality third party stuff to try and ignore (!).
I’m still trying to understand the justification for it. I saw the comment about projects with large signal flows but it looks like this solution is an attempt to impose standard OO-style programming into Max and with the sequence of objects that you have to create to make things work, I don’t see how it’s any different than just writing lines of text that execute sequentially.
It’s not clear to me that trying to make an event-driven, almost dataflow-like programming model be a traditional OO language is a step forward.
What am I missing?
(Apologies if I sound like someone on a thesis committee :-) )
@pid — check out o.expr you can do all your processing on the bundle before routing it into max types, it’s kind of addictive : ) I had that thought also about the bach library, it seems like o.2bach/bach.2o could be interesting.
@dhjdhjdhj — basically it’s just the OSC format ( http://opensoundcontrol.org/introduction-osc ), but now you can actually do your processing on the bundle inside max, which lends itself to a certain elegance in programming style. for example, no need to unpack adjust and repack a list with different scalars, you can access individual array indexes and use them as you like, etc.
@dhjdhkdlkdjhlkd, and also, + what rama said, this means all handling of streams / data is much much faster with less (and predictable) latency than doing everything with osc + max messages. it seems, i think.
@John MacCullum, where is [o.grandstaff] then?!