For some of you this may be an obvious thing and for others it may be an “aha” moment, as it was for me. I have always used Chowning’s formulas for FM to create lovely sidebands, like this:
({
var mod = SinOsc.ar(MouseX.kr(5,700));
var freq = 410;
SinOsc.ar(freq +(mod*1000), 0, 0.1)
}.play)
Playing with my analog today, I realized, while this can create brass tones galore, it is not how analog synths make those fat FM tones they do.
What the analog synth seems to be doing is using the FM voltage to change the octave of the carrier frequency. Assuming the oscillator is operating at +/-5v, in a 1v/oct input, plus 5v means up 5 octaves and -5v means down 5 octaves. So, if the carrier frequency is C and the modulator voltage is M, then the resulting frequency is C*(2**M). A carrier of 200hz, for instance, with a modulator at 1V, would transpose the frequency up one octave, resulting in 400. -5V will transpose M down 5 octaves, so we have 6.75hz
The difference is substantial, as the frequency of the carrier will never go below 0 (any positive number can be divided by two forever and not reach 0), and the sweep is exponential instead of linear (giving that focus on the lower frequencies that makes the analog so beefy). The frequency sweep is always between 0 and 10v.
In digital, this means we can take the +/- 1 of an oscillator output and convert that to an octave transformation, rather adding to the carrier frequency, giving us: freq = freq*(2**(mod5)) instead of freq = freq+(modmodMult). The result won’t give use predictable sidebands, but it does sound more like analog:
({
var mod = LFSaw.ar(MouseX.kr(5,700), 0, -1);
var freq = 410;
SinOsc.ar(freq*(2**(mod*5)), 0, 0.1)
}.play)
({
var mod = LFSaw.ar(MouseX.kr(5,700), 0, -1);
var freq = 410;
LFTri.ar(freq*(2**(mod*5)), 0, 0.1)
}.play)
If anyone has a better approach, I’m all ears.
Sam