Java, JavaScript or C

jazzisfaction's icon

Hey,
which language would u suggest for programming externals for max/msp?
i'm using Java for the moment but there seem to be serious CPU problems with Java externals within max.
i'd especially like to programme my own externals for using the kinect.

thanx
P

andrea agostini's icon

C!!!
- no, seriously, JavaScript is easier... but if you can write some Java then you'll have no problem with learning C, the Max API is somewhat trickier but if you have performance problems you'll see the difference!

my 2 cents...
aa

jazzisfaction's icon

okidoko...thanx a lot...that's what i heard, too. C is the solution, C it will be ;-)

Lee's icon

it really depends on what you want to do, if you need raw cpu power then C or Java, the call into Java is more expensive that a call into C, but the externals don't have to be compiled for mac and windows as they run in the JVM... then again, Javascript can directly script gui elements without having to break into MAX, but won't run as fast as C/Java (tho over time the js interpreters get smarter and faster....)

jazzisfaction's icon

Hmm, i have a friend who had very, very big CPU problems with a JAVA external he programmed and used in his patcher.
he had crackles in the sound and the patcher crashed regularly - he removed the JAVA stuff and everything works fine.
so he really recommends C....

Lee's icon

I use java externals regularly and have no issues, but I don't do anything audio intensive... Did he try sending his patch to c74 to see if they could identify any issues?

nick rothwell | project cassiel's icon

Java is pretty fast if you aren't passing too much stuff over the Java/native boundary (i.e. between Java and Max). If you're happy having a JVM installed then you can also use Python, Clojure or Ruby.

Javascript doesn't run in the scheduler, making it (IMHO) only really usable for UI, interaction and housekeeping. If you're happy with that, then you can also look into ClojureScript (which compiles into optimised Javascript), or CoffeeScript.

$Adam's icon

Your posts seem a bit like when you already had the answer in your mind and just needed some confirmation ;-)

Seriously, it really depends on what you're doing. The obvious answer is C; however, there are scenarios when, actually, C wouldn't be the fastest solution IMHO. For example, if you need to achieve something that has a highly optimized third-party solution in Java AND you don't need to pass too frequently data between Max and MXJ, then you might end up with a more CPU-efficient (hence, faster) solution by using an optimized library in Java compared to the case when you try to build the stuff in C on your own. Development time and maintenance might also affect your decision, since a simple Javascript code for a simple task is much easier to maintain than the code of an external in Java (which IMHO is still easier to maintain than the code of an external in C, but that's perhaps depending on your coding style and/or development tools as well). This last point is something that you won't really consider when you create the external, but you'll just hate yourself when you have to touch the code in, let's say, two years from now, and you won't even remember where to start with it...

HTH,
Ádám

$Adam's icon

BTW, my personal experience with Java in Max is that, unless you do some very specific task, there are no serious differences in CPU consumption compared to externals that achieve the same task in C (note that I mentioned 'achieving the same task' and not 'using the same coding solutions'). If there are, that's usually the symptom of bad design rather than an overall problem with Java. Indeed, to make something efficient, you need to optimize it, and by this I mean, as a first step, that when you design your external you should avoid things that would slow it down unnecessarily. In other words, if the task can be achieved in more than one way (which is usually the situation in complex situations when it is worth to build an external instead of using built-in objects), you should always choose the solution that best suits the actual language and environment.

dhjdhjdhj's icon

I didn't know that --- so if I'm sending MIDI data around (in overdrive mode, say) and one of the objects is a js object that processes that MIDI data, that's going to have a significant impact on real-time performance (other than the actual CPU cycles to process javascript functions)?

---Javascript doesn't run in the scheduler

nick rothwell | project cassiel's icon
Lee's icon

Hi Nick, I use js object to talk to live.remote~ objects with no (apparent) issue. seems that this is something i need to be thinking about from your post?

dhjdhjdhj's icon

So how are things scheduled in this case? Does the entire event sequence get moved off of the high priority thread at the point when a js object is encountered?

It sounds like I may need to replace a few of my javascript objects with C externals

nick rothwell | project cassiel's icon

Correct - calls entering js/jsui get deferred to low priority.

For better timing accuracy you could look at something Java-based, although then you have the overhead of spinning up a JVM and sending stuff across the JNI boundary. I've sequenced with JVM-hosted languages without serious problems.

Lee's icon

I've never had problems running in js or java either - I guess overall if it isn't affecting the high priority stuff that is going on then the only cost is extra cpu cycles of crossing the boundaries - this may become more apparent on lower spec machines, buy maybe as the js/java execution environments get better over time this becomes less of an issue... from conversations i've had with c74 guys, the gap between the overall performance of js and java is getting smaller over time....

dhjdhjdhj's icon

Apart from real-time stuff, this would explain some very anomalous behavior I've experienced for several years with my system, some of which I've reported on the forums, related to how does one know when a VST has finished loading.

It turns out that I am using a Javascript based dictionary for persistance and so I have a few objects that are used to load VSTs and configure their parameters. When I first built this and tried to play notes as soon as it seemed VSTs were loaded, I had many problems and so had to introduce several seconds of artificial delay.

If that javascript object is causing the entire loading process to be defered, such that regular event processing continues immediately, that would completely explain the problem.

It would also explain why it seemed to take longer to load a VST in my environment than if I just load one raw in a simple patcher.

This is VERY useful info.

Lee's icon

I'd be very surprised if that was due to js... If we put this into perspective, whether we're in the high priority thread or the lower priority thread, we're still going to be running millions of ops per second... I'm not sure having to put a several second delay into your patch is due to running in js....

dhjdhjdhj's icon

It's not about speed or number of cycles/second.
Deferring the execution changes the order of execution. That can break stuff.

Max Patch
Copy patch and select New From Clipboard in Max.

Consider for example the following patcher running in overdrive. The js object simply adds 1 to the incoming inlet and sends out the result. For the very first MIDI event, I would expect (and want) the output (in the max window) to be 3 but in fact I will get 1 because the js object is deferred and so the right inlet of the [+] is still 0

broc's icon

"The first thing to note is that at the time of this writing the Javascript implementation is single threaded and will only execute at low priority. For timing sensitive events the js and jsui objects should not be used for this reason."

Quoted from this article

Unfortunately such essential info is not mentioned in the standard documentation.

andrea agostini's icon

well, actually you can set
immediate = 1
in your javascript code. this will allow your methods to run in the scheduler. not everything can be made immediate (no scripting, no UI iirc) but as long as it's just plain computation you should have no problems.

hth
aa

andrea agostini's icon
andrea agostini's icon

... but in the Max6 doc is stated
Note: Immediate mode has been deprecated as of Max version 6.0.

... ok, forget about that! and then, frankly, C is soooo much better... ;)

Lee's icon

I would definitely go C or Java if possible, unfortunately I'm doing m4l stuff so need js to talk to the LOM.....

Lee's icon

dhjdhjdhj, i see your point... you could always defer the input in this case - midi is control rate, not audio rate after all....

broc's icon

But I think if you defer the midi input, scheduling at control rate (1 ms) is not applied anymore which may result in unpredictable latency.

dhjdhjdhj's icon

Defering MIDI processing is not an option. MIDI event processing has to be done in real time otherwise the results will be very sloppy.

The solution (for me) will be to rewrite my javascript routines as C (or C++) externals.

Lee's icon

yup...

would like to know what issued caused c74 to drop the ability of running js in the high pri thread.....

KrisW's icon

HI !

@Lee
It might be due to dynamic memory allocation , garbage collection that might introduce some memory leaks as JS might be clearing itself slower , but thats just a dirty guess

Lee's icon

yeah, i would think something along those lines, would be interesting to know exactly what tho....

nick rothwell | project cassiel's icon

The Javascript engine doesn't support multithreading. (It's not an issue with garbage collection; there are many GC'd languages which multithread happily; in fact, it often helps to run the garbage collector in its own thread.)

nick rothwell | project cassiel's icon

Have a look at Rhino (the JS engine for the JVM); this might run JS code at high priority.

Lee's icon

which js engine is currently used? I read somewhere it was SpiderMonkey... are you saying that it is Rhino or just to take a look at Rhino?

nick rothwell | project cassiel's icon

Rhino is the pure-Java Javascript engine in Java 6. It seems to support multithreading:

It might therefore work at high priority (as well as in the UI thread).

dhjdhjdhj's icon

I've been experimenting with the "immediate" stuff in Max 5.1.9 and it completely solves the issues for which I had used artificial delays and defers as hacks.
However, even though I'm not able to switch over to Max 6, I've made sure so far that all my patchers do work in 6. If I start using "immediate", I'll break that migration path.
Is there something different I have to do to get the high priority behavior with Max 6 and Rhino? If so then I'll just isolate my changes as much as possible.

Lee's icon

Can someone from c74 pls shed some light on this and also why the behaviour was changed between 5 and 6 - seems like a bit of a backwards step...

Funk Eater's icon

Rhino as engine in Max would be awesome. This would enable us to use the Max 4 Live API within Java too (same for all the other JS APIs in Max). This would allow some really cool coding.

nick rothwell | project cassiel's icon

I doubt it. The native Javascript will have been extended specifically with C linkage for the LiveAPI (as for patcher access, Dict, Sketch, MGraphics and so on). Rhino would only have access to anything that the JVM has access to.

Lee's icon

Also, if calling js caused a crossing from max into java it would make it more expensive to call...

woodslanding's icon

DHJ wrote:

>>
Apart from real-time stuff, this would explain some very anomalous behavior I’ve experienced for several years with my system, some of which I’ve reported on the forums, related to how does one know when a VST has finished loading.<<

I'm getting a little annoyed that every time I discover something not working as I expect in MAX, either you've had the same problem 2 years earlier, and nothing as been done in the interim to improve it-- or worse yet, your workaround has been deprecated.

Let me understand: If I want midi processing in high priority in max7 via scripting, my only option is writing my own C or C++ externals? Any scripting based on the JVM ( i,e.Java, Ruby) will introduce latency in the MIDI path?

Such horrible news. I hate doing MIDI processing with max objects, and have been so much happier with JS. But I am having exactly the same problems with loading VSTs, and apparently I can look forward to problems with my MIDI processing as well.

Starting to feel like I have wasted a lot of time and $$ with Max. Should have spent that time learning C++, and Juce.

Iain Duncan's icon

Well, from my experience, interpreted languages and sample accurate timing don't tend to play well together. If you want your timing to be dead accurate you are probably going to be dropping into C family languages. But I don't think this makes time and money spent on max a waste at all, when you do stuff in raw C, you are responsible for your ENTIRE environment, and having wasted way too much time doing that years ago, I'm now a convert to leting Max/MSP take care of all that housekeeping so it can just be the containing environment for my work, whether those are in C, Csound, SuperCollider, or what not. IM(humble)Opinion, the lure of doing it all in C++ is tempting, but leads to a truly massive amount of time spent doing application architecture. (So much more than you think if you haven't done it yet.....sigh! ) C++ and JUCE are great for writing *applications* that you are going to sell as a career, but man, I wouldn't recommend that rabbit hole for making musical projects your using by yourself. My two cents!

dhjdhjdhj's icon

Actually, I ultimately gave up on using Max with audio plugins and we developed our own product (http://gigperformer.com) that went to market last week (and yes, it's written in C++ and JUCE :-). Having done that, for now I'm still using Max to manage my environment but instead of trying to load [vst~] objects and control them inside Max, I just send OSC messages from Max to Gig Performer where all the audio processing takes place. All plugins are preloaded so there are no concerns about waiting for plugins to load any more (and yes, plugins not in use are sleeping so don't take CPU cycles)

But contrary to @woodslanding, I actually like doing the MIDI processing using Max objects (to me, that's its major strength) so we now have the best of both worlds.

Iain Duncan's icon

@DHJDHJDHJ, that's interesting, if you don't mind sharing, what made you decide to run the audio code outside of Max instead of in externals? And do you then return the audio into max or does it just go out the audio drivers from gigperformer?

Out of curiosity, did you experiment with SuperCollider at all?

dhjdhjdhj's icon

Candidly, I have been stuck in Max 5 for years. Both Max 6 and Max 7 have never been reliable for me, mostly related to loading/replacing plugins although I have also continued to see intermittent problems when I edit/save deeply nested abstractions or load/replace embedded bpatchers. Externals (if they existed, I never found one) that could really handle VST and AU plugins reliably would still have left me with the other intermittent issues.

Max 5 has been rock solid on all of these things. So I've had it in mind for several years to use an external host for managing plugins but was never able to find something that really did the job properly and targeted towards live musicians performing with traditional instruments and suitable for an entire show as opposed to being song based.

So last year we bit the bullet and started working on our own solution which turned into Gig Performer. Its feature set has really been driven by how live musicians (not just keyboard players but also guitarists, vocalists and even sound engineers) really want to work, both during the design stage creating the sounds for the shows and in actual on-stage use.

In my own use, I don't return the audio back to Max as my main goal is to just leverage VST and AU plugins to produce the sounds I need. Max's value here is really more related to doing sophisticated MIDI processing and triggering changes in the plugins depending on what I'm playing. However, I do use a tool called Loopback, created by Rogue Amoeba (who also are maintaining Soundflower these days), to create virtual audio interfaces through which I CAN send audio from Max directly into GP but as GP has matured, I've had no need to do that anymore.

As for SuperCollider, yeah I've played with tools like that in the (distant) past but (a) I'm not really interested in creating my own synthesis algorithms, I'm really just a performer wanting to use VSTs and AUs instead of carrying a lot of heavy synths around. For example, one of my bands will be performing in Japan in a few months and it's going to be much easier to just rent 4 controllers there and show up with a laptop and audio interface and an iPad (for controlling my GP mix) than to either ship or depend on the venues getting all the right gear for me, to say nothing if my then having to configure everything from USB backups and so forth.

I think perhaps that I'm the rare example of someone performing in a regular band using Max to help manage my system as opposed to someone who is focused entirely on making tools/applications/experimental music with Max itself.

Iain Duncan's icon

Thanks for the details, I have a foot in both of those worlds so to speak, (I perform as a jazz musician, but earn my living slinging code), so I totally get what you mean about needing rock solid vst containing environments suitable for live players. I hope gig performer works out for you, that must have been a lot of work! :)

dhjdhjdhj's icon

The work hasn't stopped. Apart from marketing, we have a list of features that will keep us busy for years. But if you're a live player, you should try GP. What instrument do you play?