This is a general problem with SynthDef.wrap
, which is merely reflected in your use case. If you wrap
the same function several times in the same synthdef you are responsible for renaming its arguments on every instancce, sadly. Somewhat more practical is to use NamedControls instead of arg
, because the former are strings, so you can manipulate them more easily.
f = { arg ctrl; Poll.kr(Impulse.kr(1), ctrl) }
SynthDef("bad_idea", { SynthDef.wrap(f); SynthDef.wrap(f) }).add
// WARNING: Could not build msgFunc for this SynthDesc: duplicate control name ctrl
Unfortunately as discussed here with respect to out
, NodeProxy doesn’t print that kind of warning about duplicate control names in its custom graph builder.
Semi-proper solution #1, assuming you want it to be the same control shared by both functions (in your case don’t but we’ll get to that later)
f = { Poll.kr(Impulse.kr(1), \ctrl.kr) }
SynthDef("one_ctrl", { SynthDef.wrap(f); SynthDef.wrap(f) }).add
In your case you need a function generator that renames the controls. Alas I don’t know how to offer a super-general version of this that inspects the function and does some magic, but as a leaky abstraction you can have
g = { arg i; { Poll.kr(Impulse.kr(1), ("ctrl" ++ i).asSymbol.kr) } }
SynthDef("two_ctrls", { SynthDef.wrap(g.(1)); SynthDef.wrap(g.(2)) }).add
x = Synth("two_ctrls")
s.queryAllNodes(true)
would show something like
1102 two_ctrls
ctrl1: 0 ctrl2: 0
lgvr123’s solution above is more transparent than this, but it may run in trouble because it’s just doing string replacements on the function source code. You might accidentally replace something other than an argument name that way, but I suppose it’s useable if you’re careful on that angle, i.e. give your args names that won’t clash e.g. with some methods names and what not.
This discussion reminds of defmacro
in Lisp and its use in Nyquist to do score generation (score-gen
).