Dynamic modulation summing to 1

Dear List,

i’m trying to have 3 dynamic signals modulating amplitude, whose sum should always be 1. So if one of the mod signals goes lower, another should compensate going higher, so the sum remains steady.
i have this way, but it still gives very sudden jumps, im looking for something that could be more subtle as well. Any ideas?

``````(
SynthDef(\summing_lfdnoise, {
arg out=0, freq=1, amp=0.5;

// generate three LFDNoise3 as modulating signals

var noise1 = LFDNoise3.ar(freq!3);

// normalize the signals to always sum up to 1 and have amplitude 1

var sum = noise1.sum;

var signals = [(noise1.at(0) / sum), (noise1.at(1) / sum), (noise1.at(2) / sum)];

var smoothed_sum = Lag.ar(signals, lagTime: 10);

var test = smoothed_sum.sum.poll(1);

var sig =Saw.ar(200*(1..3).linexp(1,3,1/2,5));

Out.ar(out, smoothed_sum * sig*amp);

)

Synth(\summing_lfdnoise, [\freq, 1, \amp, 0.05]);
``````

If sum is close to 0, dividing by the sum is the same as multiplying by a large number. This could cause erratic jumps.

LFDNoise’s native range is -1 to 1. And, the distribution of the sum of multiple linear random generators will tend toward the center, which is 0. So summing them increases the likelihood of the bad situation.

What if you map all 3 generators to a range that doesn’t touch 0? If you add `LFDNoise3.ar(freq!3).range(1, 2)`, then sum can only be between 3 and 6, so it would be impossible to divide by something like 0.000001 (which is possible in your original).

hjh

Thats right, actually

` var noise1 = LFDNoise3.ar(freq!3)+1;`

solves the problem!
Thank you!

btw. you can just write:

``````signals = noise / sum;
``````
1 Like

I would really recommend + 2 instead. With +1, it’s possible (though unlikely) that all 3 noise generators could be at the bottom of their range, in which case the sum of the three values each + 1 could still be very low.

I had a reason for suggesting to avoid 0; it wasn’t an arbitrary recommendation.

hjh

1 Like

@jamshark70’s solution is probably what you are after, however, there are a number of differences: notably,
your original solution had a phase flip in it and when the signal gets quite its derivative doesn’t change. This will make it sound different.

If you are willing to compromise on the following…

… and instead make it, ‘whose combined amplitude should never exceed 1, whilst maintaining as much high frequency content as possible’, the following might be a solution.

``````(
s.freeAll;
s.waitForBoot {
var x = {
var noise = LFDNoise3.ar(\freq.kr(1)!3);
var sum = noise.abs.sum;                                // note the abs
var scaled_noise = (noise / sum).blend(noise, sum < 1);
scaled_noise.abs.poll
}.scope();
};
)
``````

Compare the visual of how those signals move in comparison to @jamshark70’s solution,

``````(
s.freeAll;
s.waitForBoot {
var x = {
var noise = LFDNoise3.ar(\freq.kr(1)!3).range(1,2);
var sum = noise.sum;
var scaled_noise = (noise / sum);
scaled_noise.poll
}.scope();
};
)
``````

It is quite different, with the former having significantly higher frequency content and a bipolar domain, but again, Jame’s solution is probably what you want.

hi jordan,

while james’ solution was indeed perfectly enough for my case, your proposal is a significant improvement, also always good to know the limitations of a certain approach!
thank you very much!