Why does my Pbind start playing without calling .play? (ProxySpace behaviour)

Hi all,

I’ve been scratching my head over something that I think might be a ProxySpace gotcha, and wanted to share it in case others run into the same thing.

The situation:

I’m working in a ProxySpace (using p = ProxySpace.push(s) or similar). I have a simple Pbind assigned to an environment variable:

supercollider

~sn = Pbind(
    \instrument, \s,
    \bufnum, d["s"][0],
    \rate, 1,
    \start, 0,
    \amp, 0.8,
    \dur, 1
);

The surprising behaviour: the moment I evaluate this block, the pattern starts playing — without ever calling ~sn.play.

Why does this happen?

In a normal environment, ~sn = Pbind(...) just assigns a pattern object to a variable. Nothing plays.

But inside a ProxySpace, environment variables like ~sn are not regular variables — they are NodeProxy objects. When you assign a Pbind (or any Stream/Pattern) to a NodeProxy that is already playing or has been accessed before, ProxySpace interprets the assignment as setting the source of that proxy, and if the proxy is already running, it starts playing the new source immediately.

This is actually the intended behaviour of ProxySpace — it’s designed for live coding where ~sn = something means “make ~sn sound like this, right now.” But it can be very surprising if you’re not expecting it.

How to avoid it:

If you want to define a pattern without triggering playback, use a regular (non-proxy) variable or define it outside the ProxySpace:

supercollider

// outside ProxySpace - just a pattern, won't autoplay
p = Pbind(\instrument, \s, \bufnum, d["s"][0], \dur, 1);
p.play; // explicit

Or pause the proxy first:

supercollider

~sn.pause;
~sn = Pbind(...); // reassign source without sound
~sn.resume;

The SynthDef side note:

Make sure your SynthDef always has doneAction: 2 in both EnvGen and PlayBuf, otherwise you’ll accumulate zombie nodes that keep playing silently (or not so silently) in the background. You can check with s.plotTree.

Hope this saves someone some confusion. Happy to hear if others have found cleaner workflows for this in ProxySpace.

1 Like

There is a simple way to set a proxy without running its object, namely the prime method:

p = ProxySpace.push;
~pat.prime(Pbind(\dur, 0.3, \note, Pseq([1, 5, 4], inf).trace));
~pat.play