Complex preset/automation data structure with mxj. Alternatives to preset/pattr?

Alexandre's icon

Hi,
I'm starting to build a rather complex modular instrument (using a DIY-intuos2-screen** with 2 pens, ipad, Magic Trackpad, etc. as interfaces and some personal 'sub-additive' synthesis for sound : https://cycling74.com/forums/sharing-expressive-resonance-on-moving-noises ). I'm building most of the instrument structure in mxj (i keep max for UI objects/sound/some Jitter). I'm planning to use the object-oriented structure of java to structure well my project in different 'modules' : various possible interfaces/sounds/displays, versions of my instrument, perhaps using different mxj objects* in different max patches loaded together.

...and i'm dreaming of some complex presets/automation data structure coming with it :

In the past, I was using a lot [preset] and [pattr] objects, but for the following reasons i think i will not use them in my new projet, or please tell me if you see an easy workaround or special hidden external object somewhere, to help on one of theses points :

1 - I would like real time automation of all my UI objects in my max patch. (and also automation of the preset changes) I would need functions like record/stop/play but also the ability to ask for the "state of my max patch" at one exact time at xxx millisec. in the recording. I guess there is no simple way to do that using pattr.

2 - I'd like a "2D" presets array instead of "1D". I mean that i would like a list of presets, and in each preset storage i could have various presets versions.

3 - When we add a new UI object/parameter in a patch where we already have a lot of presets, if we want this new UI object to be initialized with a 'standard' value in each previous preset, we need to recall/resave each preset, which can be a heavy process even if automated.

4 - In my patches, most UI objects in max send its state to an mxj routine, which have to recalculate some process when i modified an object state with my mouse. Then when i recall some preset, there are as many recalculations repeated in my mxj routine as UI objects in my patch... which can bring serious buggy delays each time i click on a preset. I would need to know, from inside java, which way the object state have been modified, with the mouse, or by a preset change?

5 - I'm also wondering about building a special UI object to replace the preset object (in a lcd, because no UI mxj until now in max), in order to have multicolor presets (it often hard to recover my dozens of presets in the actual object) and also to integrate this "2D" presets structure.

Plus knowing that for my sound presets i might want also to interpolate on the flight between 3 or more presets (for example when the frequency of my note is changing), from inside my mxj routine, i think i definitely need a custom preset structure all made inside java.

But again, if somebody have some ideas about resolving one of theses points above, using some existing objects, or maybe, you never know, patches/mxj work already made by someone sharing it, please tell me about it,

Thank you !

* with all the mxj objects statically connected together using a great Hans trick : https://cycling74.com/forums/various-mxj-objects-sharing-data-from-unique-java-array-static-not-working

** Deep pressure sensing on two points on a screen, see picture. (cintiqs only work with one pen)

1560.DIYintuos2screen.png
png
brendan mccloskey's icon

Hi Alexandre
do you have a weblink to your work on the interface?

Thanks
Brendan

Alexandre's icon

Hi Brendan, no I don't. I built it already one year ago, but my project was going really slow so i didn't really used it yet! Feel free to ask anything about it.

seejayjames's icon

for #1, in particular the ability to recall the exact state of the patch (where object values are in an automation) you can look at my "alternative to [mtr]" posting, which saves values in jit.qt.movie and uses jit.fill/spill to create and play back the values. Also Andrew Benson's post at the bottom points to the GestureRecord patch which does something similar (and is probably much more robust).

Sounds like an interesting project, let us know how it goes!

brendan mccloskey's icon

Hi Alexandre
thanks for being open to discussion on this;
without going into so much detail that i hijack your thread, i'm finalzing materials and sensors for a DIY force-sensing touch/track -pad, for single-finger use.
It would be very helpful if you were willing to share details of the materials and technology you have used in the DIYintuos.
Thanks again, your project looks/sounds very exciting.
Brendan

Alexandre's icon

Thanks for your interesting links seejayjames, i was looking at them and the thought that is coming to me about both methods in Andrew's GestureRecord(and yours too), with pattr or with jit.qt.record, is that it's copying EVERY parameters data at each frame, 30 times per second. If i have dozens of multisliders, numbersboxes, filtergraphs in my big patch, and recording for more than 15 minutes, that a HUGE amount of useless data... ...Knowing i'm only changing one object at a time with my mouse (or, ok, two at the same time thanks to my dual-pen DIY-intuos2screen !), and not as often than 30 times per seconds for 15 minutes. I hope the automation system that i'm planning in mxj to be much more light-weighted and manipulable.

Brendan, you're welcome, tomorrow i'll post another topic with details about my intuos2screen.

seejayjames's icon

Sounds pretty ambitious!

Of course you could go 10 fps or whatever, as you know, but with enough parameters it would still eat up a lot of data. Possibly you could work out some system where only the changes would get recorded, but of course you'd need a second data stream which keeps track of the overall time when each new event happens (maybe just a jit.matrix with float32, and the values scale to the overall time length). For long chunks where nothing changes, this could be well worth the saved data... but maybe not worth the extra programming... :)

Anyway, looking forward to seeing what you come up with!

Alexandre's icon

The structure i'm thinking about for my sequence data would be like this (all in an array in java/mxj) :
For each line of data to store :
Current_time_in_millisec / Type_of_the_data (parameter change in max, or also.. gesture data from my interface) / ID_number_of_the_object_in_my_max_patch / size_of_the_list_to_store (1 if it's a number-box, many if it's a multislider) / data_array_from_the_max_object[]

I'm still questioning myself on several things :

- 'Current_time_in_millisec' should be int or long, while 'data_array_from_the_max_object[]' should be floats values... 1: So what a call 'an array' would be in fact an array of objects of type 'line_of_data()', with different types of datas inside it. 2: Or maybe just two array, an int[] one, and a float[][] one. the first solution might be more convenient while the second one might be more efficient** (when retrieving the data to display it as a visual sequence, in the future, for example).

- Tracks. Should i use different tracks for different gestures data from my interfaces and parameter changes in max ? Or should i do one simple track for EVERYTHING ? (parameter changes in max, the thing we are talking about here, and also gestures data from my interfaces)

** I know i'm mad about 'efficiency', maybe because i've been traumatized with slow softwares running on fast computers, in the past? but maybe also because being mad with efficiency may be the only way to go to make real-time instruments working with gestures 200 times a second that are REALLY working smoothly in any case. So in my case, my rule one about optimization is 'think about optimization the sooner possible' maybe in total contradiction to this Donald Knuth principle claiming 'premature optimization is the root of all evil'. That said, in the present above case, i might still be tempted by the first solution :-)

Alexandre's icon

Hey n00b_meister,

I finally made my blog: http://musique.alexandrehd.org/

Here are some details about my prototype as requested :

Cheers,

AudioMatt's icon

I've been learning java through programming a single max program for about four years. It's structured the same way: mxj and max GUI objects and nearly zero max logic. I'm going to humbly suggest you work off my variant of model view controller. When I switched to this way of working, things got less buggy very quickly. If I have a complex patch that has crazy logic to it, I sometimes give the view, it's own model-view-controller so that you don't have to store button states in the main model. I have almost 25,000 lines of code written like this and I'm doing very well.

1774.MattsMVCMap.png
png
Alexandre's icon

Thanks AudioMatt,
You exactly posted the kind of msg i was expecting to help me to go forward in structuring my project. Since yesterday, i was then discovering on the web this concept of "MVC", and wondering about your very interesting post, even if your diagram is still a bit obscure to me about this "controller" part. (Also, most of the pages on the net about this concept, are about web development, not very enlightening for me) I understood that this "controller" part is the central part of the MVC concept, the french wikipedia MVC article (a bit clearer than the english version to me) says about it :

"The controller manage the events to update the view or the model and synchronize them. It receives all user event, and triggers actions to take. If an action requires a change in the data, the controller changes the model data, then the model notifies the view* that the data has changed for it to update. Some events do not affect user data, but the view. In this case, the controller ask it for the change. The controller doesn't performs any processing, and doesn't alter any data. It analyzes the client's request and simply call the appropriate model and return the view corresponding to the request."

Then I have several questions about all this :

First question :

-> To make it clearer in my head, do you have an example of a situation were it is less buggy to use this "controller" separated object, instead of connecting 'view'/'interface' objects directly to the heart of the program ? What kind of bug did you get that you don't have anymore ?

Second question :

In my case I will have many Views and many Models, but then... one "controller" object ? or many ?

Details :
My project will have many different java objects or "modules" used together at the same time, EACH ONE WOULD BE LOADED IN AN ASSOCIATED MAX PATCHER, basically of 3 types :
1- Different interfaces (not in the java meaning, but in the standard meaning) : an ipad is an interface to me with gesture in and display out. An iphone too. My 'wacom-screen' too. The point is to be able to change the interface used to perform my instrument without changing the code, and also to use many in-out devices like that at the same time.
2- Different versions of the instrument itself. Also with the possibility to use together several instruments using several interfaces..
3- Different sound synthesis. (An 'instrument' can need 1, 2 or 3 different kind of sound synthesis at the same time) Also with the possibility to process audio on different computers, one sound synthesis on one computer, for example. (I'd really like it the more modular possible)

So for example, while performing, I would load an object of type Interface_ipad_fs() and another Interface_magic_trackpad(), an object of type Instrument_prototype_1(), an object of type Sound_synthesis_1() and another Sound_synthesis_2(), and then i would have 5 different associated patchers loaded in max, with an mxj object in each one... that's the beginning...

So if i understand well, in my case, what i call "interfaces" can be just several "views" in the MVC concept, right? After i don't know if i have to divide instrument and sound classes in "view" and "model"...
But the main question is :

-> Do i need one single "controller" object** to manage all the communications between all my objects in my different patchers ? (This would be possible using Hans trick to share context between many mxj objects https://cycling74.com/forums/various-mxj-objects-sharing-data-from-unique-java-array-static-not-working ) ...Or should I use several "controller" objects ?
All this is not clear to me.

*Third question :

-> You write in your diagram: no direct msg from model to view... but in this wikipedia article and on the internet there is... So what is the advantage, clearly ? Do you have an example to show why it would be a "bad programmer" habit in your usage ?

** This "controller" mxj object would be, in fact, inside a sixth max patcher in max, and would keep track of which, and how many, objects/patchers are loaded in my modular system...

Thanks, really,

AudioMatt's icon

This is how *I* have things laid out. As I said I'm self taught and there are many more professional programmers. But this is how I figured out how to work. I'd probably check with someone else to make sure I'm not totally insane. It may seem a bit bureaucratic at first but it stays almost exactly this simple as it scales up.

The reason I think that get and set should be avoided is because the word "get" is a misnomer. it's far to easy and tempting to say moo.getNeverChangeThisArray()[0]=5;

Also, it's far to easy to fall into the habit of a.getB().getC()...getD();

Set, in this context is event worse because you could go directly to your model, change something and no event is fired and your view will end up out of sync. To fire an event for ever set message seems a little extreme. Maybe that's the way other people work.

So this example shows how you can show the same data in various contexts. In extreme cases is if you want to display a big complex model, I would send the view a path, have the view "get" the model and make a seperate copy in the view object. So, for instance, say you want to have a seperate module name editor dialog. You would call some function that creates a nameEditDialog object and feed it a ModuleSoup, then it would copy all the module names into the nameEditDialog.

So, yes, you have the same data in two places but the strength is that if you stick to the concept (MVC) your object will always work even if things get out of sync.

Another strength of this way of working is that it makes it easy to work in one place and not worry about the rest. If you're working on the interface all you do is send events "into the ether" when the user clicks, and update the interface when they come back.

It also means that you can control and view your data from anywhere in the patch. Just write a subclass the View object and all the other views update.

In your case, you might write a View for audio and a view for GUI.

Let me know what you think. Also, I wouldn't suggest using this example for your patch... It's just something generic to get you thinking like I do about this.

1798.Archive.zip
zip
Alexandre's icon

Hey, many thanks for spending time to make an example like this..

I was examining your code and patch for an hour and a half, and one first thing is that i'm a bit lost with all the "event" and "eventListener" concept, and the way you use it in the code, my level in java didn't reach that since all the true events first happen in max and that i then just send them to java methods.
I really understand how important it is to structure well a big complex project - this is the point of this discussion - but when i dream about something 'simple-and-clear', then well, your example code, with all that events classes everywhere doesn't look simple to me... But true i need the help of some good java developer, i'm actually thinking about employing one, here where i am for the moment (Argentina, Cordoba, and in 2 weeks Buenos Aires!). But sometimes i even think that it would be even better if i had the chance to find a good max/java developer to help me to boost my slow and big project... (maybe i could find one on this forum, and even come to San Francisco ?)

Second, through that the way you are adding modules/patchs/views-associated in a max patcher and connect them together is nice and inspiring, i will not use that way of doing for a simple reason:
What i love in max is that you can EDIT a patch and CHANGE everything at EVERY moment, WHILE EVERYTHING IS RUNNING, it's an interpreted language. I'm experimenting, i always want to edit patches on the fly, i would really want to keep that even while my project is getting complex... (And what is nice with max associated with mxj is that you can edit java then reinstantiate in two seconds.) I always want a new parameter in the patch... (let's say : "sound_blur" parameter) Then I add a numberbox in the patch, a little abstraction [send_to_java_and_receive_back 'sound_blur' float_parameter_number], two patchcords, then I edit java with a new final int 'sound_blur'= float_parameter_number ; then i add my param_array[sound_blur] where i need and i'm done !

Therefore, i use abstractions patches only when i really need it... So i will not use abstractions like your "ViewAModule.maxpat" in your example.

Instead, I would have :
- Many independent max patchers that are my "modules", that i will load when i need, manually for the moment. (So i can edit one of them when i want, while everything is running)
- One "Manager" max patch called something like "This_Computer" containing a java object with some static datas. This one would keep track of all the max-patches(or "Modules") loaded (simply using few [loadbang],[send] & [receive]), and would make the communication between them.
-> My "modules"/max-patchers DOES NOT NEED at all to be connected by PATCHCORDS, instead, a shared static context inside java, shared by all the objects in the different patchers, is the way to go i think...

>> AudioMatt says: "So, yes, you have the same data in two places but the strength is that if you stick to the concept (MVC) your object will always work even if things get out of sync."

Not sure why you want to "have the same data in two places" ??
I probably wasn't clear but i don't need to "show the same data in various contexts"... ?
I just need to share datas between my modules, but each module (interface_ipad, instrum_proto_1, instrum_proto_2, sound_1,etc...) will show its own parameters and separated presets.
(the displays of the iThings and wacom-screen will not be used to show parameters but 'instrument-keyboards')

I'm also a bit lost in your get/set discussion.. And about getters&setters, perhaps i'm gonna look even more like a newbie, but not sure if i like this pragmatism yet... (And where i need efficiency, for example in sound synthesis, hundreds of harmonics to compute each millisec, i'm sure i will not use them, but will have direct access to public data instead.)

But again, structuring well my project is VERY important for me at this point. I think i will use many "abstract-classes" to define well each different type of module that can be connected together.

Thanks,

AudioMatt's icon

Perhaps I should have commented a bit more. First of all, the event stuff, I just copied from the included link. In use, all an event is is an object that gets sent to all the objects that have signed up to listen to it. It's very similar to a [counter 0 0 16]-->[send clock] and [receive clock] setup. All you have to do to listen for events is implement the Listener interface and write EventSenderObject.addListener(this).

As for views, we can only wish for the day that we could write a modular patch that functioned like mine! The point is that you are manipulating and viewing the status of the data out in a patcher in a very flexible and decentralized way. If your doing your audio processing in MXJ, you're still going to need parameters in max gui. So the data you might display would be all the parameter values. Setting and updating those parameter values is easy with MVC. It would be easier to write ChorusModuleInterface extends UserInterface than it would be to recode the whole thing. It's also much easier to write a document from a data object that doesn't contain information about the UI. It's easier to send a preset to the controller and have the controller take care of the data and update the UI.

In you're example it would be easier to subclass a View two different ways, one would be a java object that takes all the parameter information and processes audio, and another would be a MaxObject that interfaces with the UI.

Picture this: you want to make a chorus module. You write a mono chorus in Java. All you do to make it stereo is instantiate two of those objects, both of them listen for update events and you're done. Further more, maybe you want to display the LFO in your UI. All you have to do is send the LFO info from inside the left Module, and it updates both the right one and a max slider. Why? Because they are all listening for the same event.

So that's what I got.

Alexandre's icon

> About events

Thanks for your explanations. Well, my feeling is that the situations - like in your chorus example - where i will have more than one module/object that listen to an input info are not going to happen really often... So i'm wondering that i might not use all this 'event-java-stuff', but call object's method directly instead..

(Also this is not clear in my head: If you have many listeners to an event, in which order are they called? and... On same java thread? the one after the other?)

> "It's also much easier to write a document from a data object that doesn't contain information about the UI"

Of course, as the best O.O. approach, i think i will create as many objects as possible to structure my code, but this have nothing to do with the MVC concept, or have it ?

Perhaps i will post a diagram of my patches/mxj classes structure when i will get it better in my head, for the moment i'm wondering also about the best way to connect max UI and Java : https://cycling74.com/forums/need-local-sendreceive-can-i-use-pattr-to-do-that

Thanks!