One oscillator modulating multiple parameters

hi everyone,

it may be a basic problem but I can’t figure it out. I am trying to use a single oscillator as a modulator to modulate multiple parameters simultaneously. The problem I have at the moment is the range of different parameters and operators for the modulation (i.e. should I add or multiply?). I want the modulator to have controllable modulating frequency and the index. Below is the simplified code sketch

Ndef(\multiparameterModulation, {| carFreq = 1, modFrequency = 1, modIndex = 0, pan = 0, amp = 0.5 |
	
	var modulator = modIndex * modFrequency * SinOsc.ar(modFrequency); 
	var carrier = SinOsc.ar(carFreq + modulator);
	//following mapping isn't right (pan and amp expect different ranges) 
	//How can I use the same modulator to modulate multiple parameters simultaneously 
	var panning = Pan2.ar(carrier, pan + modulator, amp + modulator);
	
	panning;
});

Ndef(\multiparameterModulation).play;

Thanks a lot for your help

best

faradi

Sometimes it is easier to use .range for these things.

If you have some signal that describes the shape you want and it has a range from -1 to 1 ,

var mod = SinOsc.ar(...);

you can change the range where you need it by using .range (note .range only works if the signal has a range from -1 to 1).

var carrierModRange = modFreq * modIndex;
var carrier = SinOsc.ar(carFreq + mod.range(carrierModRange.neg, carrierModRange));

This way you can easily reuse the signal, however you need to be careful when you add signals as they can easily exceed the -1 to 1 range. In that case, I like to use some type of clipping (e.g.,.clip, .tanh, .softclip…).
You panning line might look like this then.

Pan2.ar(
   carrier, 
   (pan + mod).clip(-1, 1), 
   (amp + mod).tanh.range(-25.dbamp, 0.dbamp)
)

If the oscillator is stored in a variable it could just be scaled by adding and multiplying, right? Is not very pretty but works

What about .linlin(inMin, inMax, outMin, outMax)? Then you aren’t stuck with -1 to 1

Sure, but I read the question as getting confused as to what the ranges currently are, and if you keep the source between -1 and 1, you can avoid this difficultly.

It kind of follows the idea of a voltage control, that you always know the reference range, 0.0-5.0 volts, -1 - 1.0, 0.0-1.0 etc

Thanks a lot, everyone. Keeping the ranges of the modulator between -1 and 1 solves the problem.

All the best

Fardidanko

I teach students what I informally call “three-point modulation.” The three points are:

  • Parameter’s set value
  • Modulation signal (assuming -1 <= y <= 1 or 0 <= y <= 1)
  • Modulation depth

The “set value” is the value that should be used when the modulation signal is 0 (or when there is no modulation depth).

Then, linear modulation is as follows (where depth == 0 means no modulation):

set_value + (depth * modulator)

And exponential modulation is like this (depth == 1 means no modulation) – note that this just “promotes” the math operators:

set_value * (depth ** modulator)

This follows the modulation model of Serum, Massive, hardware modules etc. so this way of thinking is familiar to a lot of electronic musicians.

hjh

2 Likes

Thanks a lot, James. This is clearer to me now.

would your approach with the .range part look like this?

set_value + (depth * modulator.range(newMinimum, newMaximum))

a follow-up question would be. How to handle multiple modulators (i.e modulators modulating modulators). Is this the right way?

set_value + (depth_01 * modulator_01) + (depth_02 * modulator_02) + (depth_02 * modulator_02)

thanks for your explanation

all the best

faradi

You wouldn’t use .range at all with this approach. The modulator signal is assumed to be normalized (-1.0 to 1.0 for bipolar, 0.0 to 1.0 for unipolar) – you don’t want to .range that and apply a depth.

Yes, I think you’d just accumulate them like this.

hjh

2 posts were split to a new topic: Harmonic distortion