FWIW, here is how to model “source → filter” as distinct entities in my ddwPlug quark.
(
a = Syn({ |ffreq = 600, rq = 0.1|
var in = NamedControl.ar(\in, 0 ! 2);
RHPF.ar(in, ffreq, rq)
}, [in: Plug { |freq = #[86, 87], amp = 0.1|
Pulse.ar(freq) * amp
}]);
)
a.set(\ffreq, 1200); // set number
// "plug" in a signal
a.set(\ffreq, Plug { LFDNoise3.kr(3.5).exprange(200, 1200) });
// sub-nodes' controls are addressed tree-style
a.set("in/freq", [300, 301]);
// and these can plug in signals too
// (your responsibility to match rate and numChannels)
a.set("in/freq", Plug {
LFNoise0.kr(7).exprange(100, 800).lag(0.05) + #[0, 1]
});
// find a plug by path
a.argAtPath("in/freq") // a Plug
// ... and overwrite its source
// (EDIT: now works for the top-level Syn as well as Plugs)
a.argAtPath("in/freq").source = {
Latch.kr(
LFSaw.kr(1.2).exprange(100, 800),
Impulse.kr(9)
).lag(0.05) + #[0, 1]
};
a.free;
Syn and Plug sources can be synthdef names too.
This structure can be played polyphonically; Ndefs can’t (at least not easily).
(Not strictly a JITLib answer, but… the general problem in the initial post is “how to set a synth control to either a value or a signal” and this is an alternate solution.)
Very interesting. Can you compose more Syns together? Does it add to latency as jitlib?
I think a nice design would be to evaluate as many SynthDefs early (with some kind of macro, to produce variations of the functions); but also allow low latency and composability