Conditionaly decide for an envelope type inside a Synth

How could I conditionally decide for making an envelope inside a synth? What I am trying is:

(
SynthDef(\wavedrop, {
	arg env_shape, dur, fr, amp;
	var snd, env;
	snd = SinOsc.ar(freq: fr);
	switch (env_shape
		\sin, {env = EnvGen.kr(Env.sine(dur: dur, level: amp), doneAction: 2)},
		\perc, {env = EnvGen.kr(Env.perc(dur: dur, level: amp), doneAction: 2)}
	);
	Out.ar(0, (snd * env) ! 2);
}).add;
)

but this is giving me errors, I suppose because the server doesn’t understand conditionals?
Any help is appreciated!

Since they are the same length, just make both envelopes and .blend between them.

You could also use Select or SelectX, putting the EnvGens into the array of signals to select from.

It’s worth reading this example from the documentation: EnvGen | SuperCollider 3.12.2 Help

IF you really want to use arbitrary envelopes with your Synth, you can pass your envelope in as a parameter using this technique - this is probably the most powerful and flexible. But, if it makes more sense to have a fixed set of several pre-defined envelopes baked in to your SynthDef, you can use the same technique but using a fixed list of envelopes in place of envctl = \env.kr(env.asArray);, and then using Select to choose one of them.

(

SynthDef(\envelopeInput, {
    var sig, env;
    
    env = \env.ir(Env.newClear(8));
    env = EnvGen.ar(env, gate:1, doneAction:2);
    
    sig = LPF.ar(
        env * LFSaw.ar(\freq.ir),
        env.lincurve(0, 1, 10, 9000, 8),
        1
    ) * [1, 1];
    
    Out.ar(\out.kr, \amp.ir * sig)
}).add;

SynthDef(\envelopeSelect, {
    var sig, env;
    
    env = Select.kr(
        \env.ir(0),
        [    
            Env.sine(1).asArray,
            Env.perc(0, 0.5).asArray,
            Env.perc(0.01, 0.4).asArray,
            Env.perc(0.7, 0.3).asArray,
        ]
    );
    env = EnvGen.ar(env, gate:1, doneAction:2);
    
    sig = LPF.ar(
        env * LFSaw.ar(\freq.ir),
        env.lincurve(0, 1, 10, 9000, 8),
        1
    ) * [1, 1];
    
    Out.ar(\out.kr, \amp.ir * sig)
}).add;

Pdef(\pattern, Pbind(
    \dur, 1/4, \legato, 2,
    \octave, Prand([3, 4, 5], inf),
    \degree, Pstep(Pseq([0, -3, -5, -2], inf), 1.5),
));
)

(
Pdef(\inputTest, Pbind(
    \instrument, \envelopeInput,
    \env, Pxrand([
        [Env.sine(1)],
        [Env.perc(0, 0.5)],
        [Env.perc(0.01, 0.4)],
        [Env.perc(0.7, 0.3)],
    ], inf)
) <> Pdef(\pattern)).play
)

(
Pdef(\selectTest, Pbind(
    \instrument, \envelopeSelect,
    \env, Pxrand([0, 1, 2, 3], inf)
) <> Pdef(\pattern)).play
)


This is similar to @dkmeyer’s suggestion (and @jordans as well), but you only run one EnvGen instead of multiple. For a simple Synth, any of these solutions should be exactly the same (and you should probably choose based on which code makes the most sense to you) - for something more complex or with lots of envelopes, this is a bit more efficient. I like the fact that \envelopeSelect and \envelopeInput look so similar so I can easily switch them later on, but that’s purely personal preference (I use the “envelope-as-parameter” pattern a lot).

That’s cool! Never though about Env as an control rate array, but, how does Select work with different sized arrays? Does it do multichannel expansion and wrap to always fill?

EnvGen doesn’t multichannel expand for it’s envelope input. Tbh, I’m not sure HOW Select expands, my guess is that it is expands to the max length of the sub-arrays.