Supercollider tips, Q/A


makes it very enticing all over again


does this work for anyone? I’m seeing slang at 100%, but this is not causing the cpu to drop :frowning:


I’ve never experienced this 100% cpu bug in spite of running sclang without QT. No idea why I lucked out there.


ok, the guys behind Bela seem to have found a fix :slight_smile:

just applied to my local build at all works, without stopping aliveThread.

Im finding quite a few problems with SC headless, not only this, but also the issue with it throw exceptions when started without stdin (which took me a while to find a workaround for)
(Im using dev, so 3.9beta 1)


yeah that’s the same fix suggested here:

and suggested by the bela folks on the original GH issue thread (already linked above)

there have been mixed reports of the efficacy of this patch.

it’s very strange, simply stopping the keepalive thread works for me.
also, running a separate scsynth process and connecting to it as a remote bypasses the keepalive thread in the first place ( i think - anyway i don’t see the cpu spike.)

but if you are seeing the usage without the keepalive thread… that’s bizarre. a true heisenbug.


dumb question :slight_smile:
(as I’m pretty sure its showing a fundamental misunderstanding)

a = OSCFunc(
    { arg msg, time, addr, recvPort; [msg, time, addr, recvPort].postln; }, 

so the above is suppose to , connect to the remote scsynth. then register an osc hander listening on port 4000… but I don’t get any messages
yet the same OSCFunc run on SCLang locally on the box works

so im a little confused, I thought that the OSCFunc was passed to the server to execute, so should execute the same, locally or remote…
or is OSC handling part of client side? is it possible for it to be run on the server?



is it possible for it to be run on the server?

no, i don’t think so. server understands hardcoded set of commands:

to me, this suggests that in startup on organelle, you’d launch something that listens to some set of commands you define to do “stuff” from a host computer. in addition, presumably, to listening for OSC from the Organelle_controller woop, i mean Organelle_UI process.


ok, so no comms on the server , osc and midi done on client…
so I assume I could have a local client (sclang) processing midi and custom osc, and some how sending out notifications, which other (remote) clients of the server could pick up and process.

I’m thinking a bit like the addDependent / change events mentioned earlier in this thread… or are these local to an sclang?

for the ‘performance’ side its all going to be be local, but I want to be able to develop the SC synth defs on a mac using the SC IDE… then copy them across when working…
(I’ve got an OscProxy, but its easier if I can keep it all in SC)


makes sense.

in the SC world, it’s a pretty common paradigm to have one sclang/scsynth on a network connected to a sound system, and other clients that initiate stuff happening (think about a classroom / workshop / networked jam session.)

you can just remote-execute SC code directly:

n = NetAddr("", NetAddr.langPort);

OSCdef(\execRemote, {
	|msg, time, addr, recvPort|
	this.interpret(msg[1]); //  try to compile and execute the payload string 
},'/execRemote', n);

and/or you can have remote clients talk to the organelle’s scsynth directly (send synthdefs, control synths/busses, &c)

(or anything in between, including some kind of proxy class.)

i’d be interested to see any systems you develop for structuring this kind of thing!

yes. they are methods of Object. an instance of sclang (client) has its own interpreter state. multiple clients can communicate through OSC+UDP/TCP and thats about it.

client/server of course use OSC also; in one direction via the server commands (either raw, or wrapped in sclang class methods); in the other direction via ugens like SendTrig, SendReply, SendRMS.

since recent versions, client/server on the same machine can do some of their IPC over shared memory instead of UDP/TCP. this enabled the synchronous methods for polling and setting control busses. these are a lot more efficient if you are gonna do a lot of client-side operations on control busses, so might factor into any kind of multi-client design.

and woop, it occurred to me that JITLib has some features intended to facilitate collaborative networked live-coding, which you may be interested in (it’s not a library i’ve used much myself, beyond a bit of Pdef)


I’m very interested in your findings on this.

For quite some time I have planned to refactor a SC drum machine app I’m working on similarly: one part realtime audio process (scsynth), one part core logic/sequencing (data structures for sequencing, scheduling), one part UI, all three decoupled and communicating via well-defined OSC interfaces. This would make for a modular design where any part could be swapped out for a different implementation.

Erlang father Joe armstrong: “send messages to things and ask them to do things” rather than “performing open brain surgery” on things:

The latter two parts of my app are currently in the same “address space”. The Grrr based UI “listens to” to core/sequencing events via addDependant / update for incremental UI update and utilizes synchronous “getProperty()” calls for UI refresh that not triggered by events (ie, on startup). Decoupling the parts would, I think, boil down to changing addDependant / update events to OSC messages and find a way to work around and phase out the synchronous “getProperty()” calls. This would be a fun excercise but I’m not sure how it would end up in practice with regard to performance. The events communicated are fairly large and many. Feels like it all kind of moves towards Functional Reactive Programming.

@TheTechnobear @zebra you’re discussions on networked control of SuperCollider got me thinking about this library (which I haven’t tried myself):


another newbie Q. :slight_smile:

how from within sclang can I get it to interpret an sc script file?
(or even the equivalent of an ‘include’ file statement would do)

the best Ive come up with so far is:

g = File("~/Documents/SuperCollider/".standardizePath,"r");

but Id prefer to interpret the stream, so as not to load the entire file into memory (as it could be large)

other things Ive tried:
treat as a stream

g = File("~/Documents/SuperCollider/".standardizePath,"r");
		arg v; 

It does not like this, as interpret is actually needing a full SC command… rather than just adding to a buffer till its ‘complete’… so this indicates to me, any kind of parsing into interpret will fail, since things like brackets and scoping come into play…


ok, so what Im trying to do , is make it so the user only has to provide one file… and it to be run.

to do this, I have another file ‘mother.scd’ which sets up various system things, boots the server, and then I want to do something like

  s.waitForBoot { (

where main.scd is the users ‘patch’ file.

now i dont want to put everything in startup.scd, for a couple of (perhaps dubious) reasons
most importantly, I want the ‘mother.scd’ file to be overridable, to allow different behaviour , and startup.scd is ‘global’ afaik

I guess the main issue I’m facing is… that I dont want users to have put the waitForBoot in their script, as this is pretty ugly.
I suppose one other option, is for me to start scsynth directly, and then wait a second or two, before starting sclang, but that seems a bit hacky.

p.s.though Im an experience C++ programmer, I’m trying to keep it simple at the moment, as Im not that experience with SC… (so avoiding SC classes) and dont want to get side-tracked too much, as Id like to deliver at least the skeleton quickly… then I can improve it with custom class/ugens later :slight_smile:

Bonus Question:
anyone know of a (lightweight, think rPI!) ) web based editor for SC? (linux)
If not I’m thinking of a simple ACE based editor running on cherrypi, but this will only provide basic functionality, and I dont want to reinvent the wheel :wink:



thanks that didn’t work, loadPath, and excutePath, just report as ‘not understood’ (on SC 3.8) , but did allow me to find :


this is a much nicer syntax, thank you :slight_smile:


yeah, AFAIK there is no way to get that deep into the parser from within sclang; you can only interpret complete and valid statements. pretty normal for an interpreted language (same as lua and so forth.)

but, look at the methods for Interpreter in as in many interpreted languages, code execution has two steps: 1) compile to bytecode, 2) execute the bytecode

in sclang the .interpret method is just convenience. the underlying method is .compile, which returns a Function (compiled bytecode) if the argument is a valid SC chunk, and nil if it isn’t.

f = "1+1".compile; // f is a Function
f.value; // prints "2"
f = "1 + ".compile; // f is 'nil' 
f.value; // error

so if you really want to make a REPL that handles incomplete statements, it should be doable, in the same manner that most REPLs do it:

  1. make a buffer
  2. when you get input, add it to the buffer and try to compile
  3. if the result is nil, do nothing and wait for more input
  4. if the result is a Function, evaluate the function and clear the buffer

i don’t think this would work with local variables though. in the same way that you can’t use local variables from a lua REPL prompt.

try .executeFile (or i guess .load as you’ve discovered, i guess that’s a new alias?)

here’s a snippet that shows up a lot in my performance scripts, for local “includes.” (for a given performance i uusally have a directory with a master script, and some number of child scripts that do this or that. but really universal modules or boilerplate are done in classes, not scripts.)

p =;
x = { |f| this.executeFile(p ++ f); };

i don’t… and am working (a little bit) towards a similar goal actually. currently i’m just taking a sclang process and wrapping its stdin/stdout in a little nanomsg program. this makes it usable by local IPC sockets or websockets.

was thinking the next step would be a tiny webserver, but was thinking lighter than python - maybe monkey or mongoose.

thanks for pointing at, that’s the piece i hadn’t started thinking about


There’s also the annoying restriction that local variables can only be defined at the start of a block in SC.


well yeah, local variables really are of limited use in SC. i’ve never been a big fan of the style that you see so much in the help docs:

( // create a local scope
var bla; 
// do stuff with bla

it’s a weird idiosyncracy to have to select this whole chunk in the editor and evaluate it, and of course bla is out of scope as soon as you’ve done so

i like global variables just fine in SC. because they don’t really exist! there is actually just one global variable, which is an Environment, which is just a specialized identity dictionary. so this works:

~abc = 123;
e =;
e.push; // we've made a new "global namespace"
~abc.postln; // now this is nil
~bla = 456; // do some stuff

e.pop; // restore the old "global namespace"
~bla.postln; // nil
~abc.postln; // 123

to me, it’s best to just prototype with global (pseudo-)variables. if necessary, can swap Environments or use Events in a similar fashion. when something is “set in stone” it can be turned into a class.

this is again analogous to typical practice in Lua, where you would keep all your messy state stuff in a global table that can be easily marked for garbage collection or &c. when your prototyping is complete the table can be made local and put in a module.


sorry to reply to myself, but this is absolutely not true and i don’t know why i thought it.

this works fine:

// Environment acting as psuedo-class for prototyping an incremental interpreter
e = Environment.make({
	~buf = "";
	~reset = { ~buf = ""; };
	~eval = { |str|
		~buf = ~buf ++ str;
		~fn = ~buf.compile;
		if(~fn.notNil,  {
		}, {
			postln("..."); // incomplete statement?

e.push; // use this environment as global namespace

~eval.value("postln(1+1);"); // prints "2"
~eval.value("( var blarg = 2; "); // prints "..."
~eval.value(" postln(blarg * 5); )"); // prints "10"

e.pop; // restore last environment

so, we successfully opened a scope and declared a local variable with one call to this toy interpreter, then used the local and closed the scope in a second call. of course we can’t access the local now but that’s as expected.

(i’m tying to think of some edge case that would break this by successfully compiling before the scope is closed… feel like it exists)


SC not freeing nodes?

Ok, so Ive got a weird one, perhaps lack of understanding…
Im using done actions to free up synth nodes via a gate on an envelope

I can hear the synth gate is closed (due to sustain) , yet I can still occasionally see the node on the tree

~voices =;
~notesfunc = {
	arg func, msg, note, vel;
	if(vel>0 , {
		~voices[note] =\testSynth,[
			\freq, note.midicps,
			\cutoff, ~cutoff,
			\amp, (vel / 3.0) .clip(0,1.0)
	} , {
		~voices[note] = nil;
SynthDef(\testSynth, {
		arg freq=440,gate=1,cutoff=440,amp=0.3;
		var sig,env;
		sig =;
		env =,gate,doneAction:2);
		sig = sig * env * amp;
		sig =,cutoff.clip(10,24000));,sig!2);

code is trivial really…
as I say, I can hear the gate has closed, and there are no ‘hang notes’…
so why is the doneAction not freeing up the synth?
(I also can see the dictionary is ‘empty’, so definitely gone thru the code to cleanup)

(Ive tried on both 3.9 on the Organelle, and 3.8 on the mac, and same behaviour)

Bonus question :slight_smile:
Is there a way I can grab hold of the Synth given the nodeID in sclang?
e.g. if I know the synth is 1087

I want to do something like


Not sure of the answer, might be something subtle, but try with a simpler envelope like Env.perc for starters. Also your EnvGen should probably be .kr unless you like wasting CPU cycles for no reason :slight_smile:

Edit: nevermind, play doesn’t matter here…


I tried out this code in my local SC and it seemed to work just fine:

SynthDef(\testSynth, {
		arg freq=440,gate=1,cutoff=440,amp=0.3,out;
		var sig,env;
		sig =;
		env =,gate, doneAction:2);
		sig = sig * env * amp;
		sig =,cutoff.clip(10,24000));,sig!2);

x =\testSynth, [\freq, 60.midicps, \cutoff, 2000])
x.set(\gate, 0)

So maybe you have something else going on?