My synth's curve argument has no effect

I wanted to have a synth defined where I can pass in the curve shape as an argument:

(
SynthDef(\syn, {
	arg cv;
	Out.ar([0,1],
		SinOsc.ar(
			mul: EnvGen.kr(Env([0, 0.1, 0], curve: cv),
				doneAction: 2
			)
	))
}
).add;
)

// but playing it sounds like a sine curve shape
Synth(\syn, [\cv, \step]) // Why?

What is wrong with this code snippet for passing the curve shape as an arg?

This is, yet another, example where using NamedControl or \cv.kr is far superior.

Rather than doing…

SynthDef(\syn, { arg cv; ... });

If you had used named control with a default value…

SynthDef(\syn, {
   \cv.kr(\lin);  // or NamedControl.kr(\cv, \lin);
}).add;

…you would have immediately been greeted with an error.
The issue is that you cannot send a symbol to a synth. Synth Controls are much more like Buses (In in particular) than they are like function arguments, and can therefore, only accept floating point numbers, or arrays thereof.

The easiest way might be just to send the whole envelope:

(
SynthDef(\syn, {
    var env = \env.kr(Env([0, 0.1, 0], curve: \sin).asArray);
    Out.ar([0, 1],
        SinOsc.ar(mul: EnvGen.kr(env, doneAction: 2))
    );
}
).add;
)

Synth(\syn);
Synth(\syn, [\env, Env([0, 0.1, 0], curve: \step)]);

(The “curve” parameter gets translated into two values to be sent to the server:

Env([0, 0.1, 0]).asArray
Env([0, 0.1, 0], curve: \exp).asArray
Env([0, 0.1, 0], curve: 1).asArray

so you could do something more complicated to only send the curve values, here is how they are calculated:

f = { |cv| 
  [Env.shapeNumber(cv), Env().curveValue(cv)]
};

then you could recieve this array in your synth and inject it appropriately into the env array…)

3 Likes