Calling run(true) on a Group

Hi all,

I was under the impression that if you have a Group filled with paused Synths, you can call run(true) on the Group, and as a result all of the contained Synths will receive this message and start running, similar to calling freeAll and set on a Group. But, when I try to do this, I get no response.

My goal here is basically to save processing power. I’ve got a bank of Synths, and I’d like to get them all to become unpaused at the same time, preferably without having to talk to them individually. I’m aware I can store these Synths in a language-side array and iterate, but I’d rather do this by talking to their enclosing Group. I also want to point out that, regarding run, the Node help file says:

If this Node is a Group this will set the running state of all Nodes within the Group.

Here is a simplified example. Is this possible? Am I doing something wrong?

Eli

s.boot;

(
SynthDef(\testtone, {
	arg gate=1;
	var sig;
	sig = SinOsc.ar(200, mul: 0.1!2);
	sig = sig * EnvGen.ar(Env.asr(2,1,2), gate, doneAction:1);
	Out.ar(0, sig);
}).add;
)

g = Group.new;

x = Synth.newPaused(\testtone, [\gate, 0], g);

//I expected this line to produce sound, but nothing happens
g.set(\gate, 1).run(true);
g.set(\gate, 0);

//This works as expected
x.set(\gate, 1).run(true);
x.set(\gate, 0);

Another observation:

s.boot;

(
SynthDef(\testtone, {
	arg gate=1;
	var sig;
	sig = SinOsc.ar(200, mul: 0.1!2);
	sig = sig * EnvGen.ar(Env.asr(2,1,2), gate, doneAction:1);
	Out.ar(0, sig);
}).add;
)

(
g = Group.new().run(false).register;
x = Synth.newPaused(\testtone, [\gate, 0], g).register;
)

g.isRunning; //false
x.isRunning; //false

g.run(true);

g.isRunning; //returns true
x.isRunning; //returns false, expected true

this works though:

g = Group.new;
g.run(false)
x = Synth(\testtone, target:g)
g.run(true)

perhaps the running states of group and child node are logical ANDed.

g = Group.new;
g.run(false)
x = Synth.newPaused(\default, target:g)
y = Synth(\default, [\freq,500], target:g)
g.run(true)

g.run(true) only seems to start nodes which were paused by g.run(false).

This is not what the docs suggest but… you can start your synths in a paused group and they will wait apparently so no worries

Thanks for the insight and the workaround. Though, this still feels pretty weird. When we call run(true) on a Group, all of the nodes within should run, regardless of how they became paused in the first place…right? Or am I misunderstanding something?

I think its not a bad design maybe.

for any node except the RootNode (Group or Synth) .run simply sends the server a message to change that Node’s run flag . I guess a logic is applied:

nodes play if the run flag is true and the run flag is true for all parents.

So when you set a group’s run flag to false, the run flags for the children don’t change. But the children don’t run in any case.

So its a little like a mixer when you mute the main mix - the children don’t play, but their respective mute states don’t change. This seems useful - you might like to pause/play up a Group, some of whose children are paused without losing the state of the children.

the docs do suggest that setting the running state should propagate to the children and that’s wrong unless I’m not understanding something.

I expect there is be a way to get a list of the child nodes and act on them directly using .query or .queryTree

“This seems useful - you might like to pause/play up a Group, some of whose children are paused without losing the state of the children.”

I hadn’t considered this angle. That makes sense.

Let me explain a little more about what I’m doing, and ask a slightly different question.

I have a Group (g) that contains 5 nearly identical Synths, with the same release time. Each envelope has doneAction:1 (pause self when complete).

So, I can easily fade them all with the following, and they pause themselves when finished:

g.set(\gate, 0);

I was hoping to be able to re-awaken them with:

g.set(\gate, 1).run(true);

But this call does not cause propagation to occur to the children, as the help file suggests. So it seems like the documentation language should be changed or removed, because it is either wrong or confusing. (I can make a PR at some point).

My next thought was, “is there a doneAction that pauses the enclosing group when finished”? And the answer seems to be no — which kind of surprised me, considering how many different doneActions there are.

So now I’m thinking I might be going about this in the wrong way. I looked at query and queryTree – this is definitely a solution, but from a teaching perspective it seems a bit thorny. I could also switch to doneAction:0, but these Synths are relatively CPU-intensive, so I’m hoping to take advantage of pausing. I think I’m leaning toward just storing the Synths in a language-side Array and using iteration, e.g.:

~array.do({ |x| x.set(\gate, 1).run(true) });

But if there is a short and tidy solution using the parent Group, I’d love to hear it.