Saving a Preset Sequence of SynthDefs

Indeed. The linearity of Ndef is a problem if you want to express (sig1 * env1) + (sig2 * env2). It’s not possible to have that as single Ndef (and still have all of sigs and envs be individually “hot-swappabe”. But Ndefs can refer to each other.

So you can can write something like (simplifying a bit the)

Ndef(\chain1)[0] = sig1;
Ndef(\chain1)[1] = \filter -> env1; // pseudocode

Ndef(\chain2)[0] = sig2;
Ndef(\chain2)[1] = \filter -> env2; // pseudocode

Ndef(\bigmix) = Ndef(\chain1) + Ndef(\chain2)

That does work because of a not so advertised feature that “Ndef math” mostly works.

You can even write

Ndef(\bigmix) = { (\wet1.kr * Ndef(\chain1).ar) + (\wet2.kr * Ndef(\chain2).ar) }

to give yourself mixer level controls for each. The simpler “Ndef math” version right above just does that as if you had written { Ndef(\chain1).ar + Ndef(\chain2).ar }.

But \bigmix will not have all the controls that \chain1 and \chain2 have in a single convenient location, because it’s a different Ndef on a different Group. Basically Ndef’s can’t really wrap one another as plain Groups can. Ndefs can only refer to another Ndefs.

You can just wrap all 3 Ndef groups \bigmix, \chain1 and \chain2 in a single Group using the rather obscure parentGroup feature of Ndef, so can set parameters in one place form the command line, but that Group wont be a Ndef itself, so you’ll have this unpleasant asymmetry in interfaces, e.g. it won’t be representable as a NdefGui.

What you really need to consider in cases like this is whether you really need the ability to swap the filters on each chain at runtime, while the “base” signal is still running. Because if you don’t need that much flexibility, and e.g. you can restart the 'base" signal when the filter changes, then it’s much simpler to write a single Ndef (or SynthDef) for each chain so that it includes both the “base” signal and the filter. Basically, the difference between:

Ndef(\combo1) { sig1 * env1}

and

Ndef(\chailn)[0] = { sig1 }
Ndef(\chailn)[1] = \filter -> env1 // pseudocode

is that in the latter case you can later do just

Ndef(\chailn)[1] = \filter -> something else // pseudocode

and the phase of sig1 will stay exactly the same during the change, so no “drop outs” etc. In the case of Ndef(\combo1) changes you’d probably have to do at least a cross fade for things to sound acceptable, and the xfade will sound different than merely changing filter.

Yeah, it really depends. Sometimes it does matter, but mostly in cases where you need to keep phase alignment.