Here is a riddle I struggle with. Maybe some of you has an idea of how to solve it. The basic idea is to free synths not via their nodeID, but via some id
, and a group.set
message to their group. The motivation is:
- the synths are grains, so no bookkeeping of nodeIDs in sclang should be necessary
- the groups are used to keep node order
- synths may need to be freed together that are in different groups
So I keep all synths in a large global group and send the id message to it. The synth knows how to free itself if the id matches with its own.
The problem is the following: when two group.set
messages happen within one control block, they override each other before the synth is freed.
All this happens in SuperDirt, but here is a minimal example:
(
SynthDef(\test, { |id, gate_id = -1, freq = 440|
var sound = SinOsc.ar(freq);
var env = FreeSelf.kr(absdif(id, gate_id) < 0.5);
Out.ar(0, sound * 0.03)
}).add
)
// free it by setting the gate id.
k = Synth.new(\test, [\id, 4])
k.set(\gate_id, 4);
// now more synths
(
g = {
var group = Group.new;
4.do { |i|
5.do { |j|
var freq = [300, 700, 2000, 3000].at(i) * 4.0.rand2.midiratio;
var id = [4, 5, 6, 7].at(i);
Synth.grain(\test, [\id, id, \freq, freq], group)
}
};
{ |dt = 0.01|
fork {
[4, 5, 6, 7].do { |id|
group.set(\gate_id, id);
dt.wait;
};
}
};
};
)
f = g.value;
f.(0.7);
f = g.value;
f.(0.0001); // some notes hang
Does anyone have a trick of how to handle this situation? It seems to be a fudamental limitation of scsynth that comes from the double use of groups as messaging relay and node order scheme.