Triggering/Freeing multiple Synths

Hey,

I’m trying to trigger a number of Synths at (basically) the same time and then free them later at (basically) the same time. I’ve tried to do this with iteration, as seen in the last few lines of code here, but this doesn’t seem to work. Would love feedback on how to make this work, or better ways to do the same thing!

(
SynthDef(\a, {
        var env, sig;
        var buf = \buf.kr(0);

        env = Env.asr(\atk.kr(1), 1, \rel.kr(10)).ar(Done.freeSelf, \gate.kr(1));
        sig = PlayBuf.ar(1, buf, BufRateScale.ir(buf) * \rate.kr(1, 1.5) * \direction.kr(1), 0, \startPos.kr(0), \loop.kr(0));
        sig = sig * env * \amp.kr(1);
        sig = Pan2.ar(sig, \pan.kr(0));
        Out.ar(\out.kr(0), sig);

}).add;
)

(
Routine {
var rate = Pstutter(2, Pxrand([1, 9/8, 1.5, 0.75, 2], inf)).asStream;
var rate0 = Pxrand([1, 9/8, 1.5, 0.75, 2], inf).asStream;

l = Synth(\a, [buf: ~git[0], rate: rate.next, pan: -1, loop: 1]);
r = Synth(\a, [buf: ~git[0], rate: rate.next * 1.01, pan: 1, loop: 1]);

10.wait;

10.do {
        [l,r].do{ |i| i.set(\rate, rate.next) };
        rrand(2, 10).wait;
};



10.do {


        l.set(\rate, rate0.next);
        rrand(2, 10).wait;
        r.set(\rate, rate0.next);
};



[a,b,c,d,e,f,g].do { |name| rrand(2,10).wait; name = Synth(\a, [buf: ~git[0], rate: [0.25, 1, 9/8, 1.5, 0.75, 2, 3].choose, pan: rrand(-1.0, 1.0), loop: 1])};

45.wait;

[a,b,c,d,e,f,g,l,r].do { |name| name.set(\gate, 0) };

}.play;
)

Cheers,
Jordan

the problem here is that when you pass a,b,c etc into your function, you are passing the value of interpreter variables a, b c etc (probably nil!)

you could store your synths in an array by using collect instead of do:

~synths = 9.collect{Synth(blah blah)}

then free them: ~synths.do{|i| i.free}

(or I like to write: ~synths.do( _.free ) )

you could alternatively use a Dictionary if you want to associate the synths with names

~synths=();
[\a,\b,\c].do{ |name| ~synths.put(name,Synth(\default))};
~synths.a.free;
or [\a,\b].do{|i| ~synths.at(i).free}

finally a different way to handle it is to use a Group - is you set the target parameter of a Synth to a particular group

g = Group.new; Synth(\default,target:g) etc

you can free, release or set all nodes in the group at once with g.free etc

1 Like

Just for fun – this is what it would look like to use a bunch of interpreter variables. (Note that this is not a good solution – on the contrary, it’s deliberately ridiculous. I’m posting it to illustrate why it’s the wrong road to go down. Do not use multiple variables for a case like this!)

// #[] makes them into 'a' 'b' 'c' etc.
#[a, b, c, d, e].do { |varname|
	thisProcess.interpreter.perform(
		varname.asSetter,
		Synth(\default, [freq: exprand(200, 800), amp: 0.05])
	)
};

#[a, b, c, d, e].do { |varname|
	thisProcess.interpreter.perform(varname).free;
};

semiquaver is correct – if you’re managing a collection of similar, related objects, then the thing to do is to put them into one of the Collection classes. Usually that’s an Array. There are also sets and dictionaries, depending on the use case.

hjh

2 Likes

Thanks to you both for the help!

I’ve landed back here again - in my warm up today I’ve been trying to have multiple synths creating a pad effect, then freeing them a bit later. What I’m trying here doesn’t work, and using a global variable as suggested above also doesn’t seem to help:

(
SynthDef(\a, {
        var env, sig;
        var freq = \freq.kr(300, 1) + Array.fill(8, {LFNoise2.kr(Rand(2.0, 4.0))});
        var width = Array.fill(8, {LFNoise2.kr(Rand(2.0, 4.0)).range(0.1, 0.9)});
        env = Env.asr(1, 1, 3).ar(Done.freeSelf, \gate.kr(1));
        sig = Pulse.ar(freq, width);
        sig = LPF.ar(sig, 10000);
        sig = HPF.ar(sig, 30);
        sig = sig * env * \amp.kr(0.2);
        sig = Splay.ar(sig);
        Out.ar(\out.kr(0), sig);

}).add;
)

(
Tdef(\a, {
 // replacing var synths with ~synths hasn't made a difference
   var synths = Array.new(10);
    var freq = 60;

    fork {
        loop {
        synths = synths.add(Synth(\a, [freq: freq * [1, 2, 3, 3/2, 9/4].choose]));
        rrand(3,5).wait;
        };
    };

    fork {
        loop {
        var i;
        rrand(5, 10).wait;
        synths[i].set(\gate, 0);
     };
    };

}).play;
)

you need to iterate over synths

synths.do{
    | i |
    rrand(5, 10).wait;
    synths[i].set(\gate, 0)
}

in your example you forgot to set i to anything.

Ok, this one is kinda counterintuitive for me. Thanks for the help!