 # How to properly implement modulation depth?

Hi all!
On example below I try to use SinOsc for very basic amplitude modulation,
but I can not control amount of modulation in a usefull way.

If I set lfoGain to 0, than lfo will out 0 and I’ll get no sound as result.

I feel that there is a very basic math behind it but I can not find an answer.

q = {
var sig = SinOsc.ar(220);
var lfoFreq = 2;
var lfoGain = 1;
var lfo = SinOsc.ar(lfoFreq).range(0, lfoGain);

Out.ar(0, sig * lfo);
}.play;

q.free;


So how can I implement signal modulato n with controllable depth?

You can do something like this

(
q = {
var sig = SinOsc.ar(220);
var lfoFreq = \lfoFreq.kr(2);
var lfoDepth = \lfoDepth.kr(0).linlin(0, 1, 1, 2);
var lfo = \lfoGain.kr(0.1) * SinOsc.ar(lfoFreq).range(lfoDepth.reciprocal, lfoDepth);

Out.ar(0, sig!2 * lfo.poll)
}.play;
)

q.set(\lfoDepth, 0.1)
q.set(\lfoDepth, 0.5)
q.set(\lfoDepth, 1)

q.free;


Your variant a bit closer but it have some strange effects.

Looks like lfo overdrive sig, so sig amplitude should be divided by some coeficient.
And also if I turn \lfoGain to zero it will also multiply sig by zero and I’ve got a silence

Is it by design?

I think what you’re looking for is for when the gain is zero, the original signal is passed unaltered, all the way up through when the gain is 1, the signal amp oscillates between x0 and x2, yes?

if so, this will do what you’re looking for:

  var lfo = SinOsc.ar(lfoFreq) * lfoGain + 1;


Multiply by lfoGain to increase or decrease by the gain amount, and then add 1 so that when the gain is zero, the lfo is just 1.

More suitable. But anyway result will from 0 to 2 and it will overdrive carrier signal.
I decided to clip it var lfo = (SinOsc.ar(lfoFreq) * lfoGain + 1).clip(0.0, 1.0);

But now, when lfo moves only with half of values looks like I need to compensate lfoFreq somehow;
At least it solve overdrive problem.

For amplitude modulation, you would want:

• lfoGain = 0, amplitude ranges from 1 to 1
• lfoGain = 1, amplitude ranges from 0 to 1
• lfoGain > 1, probably invalid

… I suppose… Defining this is really step 1 but I don’t see that anyone has done so in this thread.

So then: SinOsc.ar(lfoFreq).range(1 - lfoGain, 1) or spelling it all out, (SinOsc.ar(lfoFreq) * 0.5 + 0.5) * (1 - lfoGain) + 1 or its algebraic equivalent (SinOsc.ar(lfoFreq) + 1) * (1 - lfoGain) * 0.5 + 1 wait, those aren’t right…

Think of the range method in terms of the center of modulation and depth.

c = 1 - (g * 0.5)
d = g * 0.5

Then:
lfo * d + c
= lfo * g * 0.5 + 1 - (g * 0.5)
= lfo * g * 0.5 - (g * 0.5) + 1
= (g * 0.5) * (lfo - 1) + 1

= 0.5 * lfoGain * (SinOsc.ar(lfoFreq) - 1) + 1


Check it: if lfoGain = say 0.1, then lfo range -1 to +1 would produce 0.05 * -2 + 1 to 0.05 * 0 + 1 = 0.9 to 1, yep.

{
var lfoGain = EnvGen.ar(Env([0, 1], [0.02], \sin));
var lfo = SinOsc.ar(440);
0.5 * lfoGain * (lfo - 1) + 1
}.plot(duration: 0.02);


hjh