Frequency Modulation (FM) - How to use Modulation Index in my implementation

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I'm working on a VST3 synthesizer. It has 8 Tone Generator Modules selectable from any of 10 engines, 8 Envelope Modules appliable to virtually all voice parameters, 8 Effect Module slots, 8 LFO Modules appliable to virtually all voice parameters, and many processor parameters, plus finally 8 Filter Modules each appliable to one or more tone generators. Each tone generator can be set to octave, semitone, or fine +/- pitch offset from norm as in middle A = 440Hz.

I have designed my synth so one sample is first gathered for each active tone generators. After that I apply modulation selectable by user, AM, RM, FM, PD, or PM.

Depended on the order you arrange carrier tone generator and modulation tone generator, a modulation tone generator can itself be modulation from another tone generator.

Anyways my implementation below, simplified to better illustrate my post question, works fine, however I don't know how, if even possible to fit in the Modulation Index.

As I understand it the modulation index is max carrier frequency deviation / modulator frequency, and the max carrier frequency deviation is carrier frequency * modulation level.

My tone generators, no matter what engine used, supply samples in the range of -1.0f to 1.0f.

Code: Select all

// FM Implementation
float modulator = sampleValue[modSource];

// I am below adding 1.0f to change the modulator * modLevel from -1 to 1, into 0 - 2.0
// modLevel is in the range of 0 (no modulation), to 1 (max modulation)
modulator = 1.0f + modulator * modLevel;

// The modulator is now multiplied with the carrier tone generator's Delta, which is reset 
// to proper relation between note frequency, table size, and sample rate, before 
// the modulation code part
delta[carrier] *= modulator;

// The above modified delta is then added to the carrier tone generator's phase variable
phase[carrier] += delta[carrier];

// Modulator tone generator's phase is also updated
phase [modSource] += delta[modSource];

// And yes I check and adjust all tone generator's phase as needed when they go beyond 
// max phase, which for any engine is 2047, omitted here for simplicity
So if for example the both the carrier and modulator's octave, semitone, and fine controls are set to '0', and I play a middle 'A', the frequency of both are 440Hz.

The max carrier frequency deviation would then be 440Hz * 2 (Multiply by 2 because a modulator sample is in the range from -1.0f to 1.0f, and I then add 1.0f later to adjust to 0.0f to 2.0f) * modLevel right?

If the above is correct, the Modulation Index would then be above result / modulation frequency (In this case 440Hz) right?

So if I calculated the Modulation Index right, how can I incorporate that into my above algorithm? Any advice, except to format my hard drive, is much appreciated, thanks!
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

I don't think "modulation index" is something important that could be heard in the output. Choose a specific formula for your modulated oscillators and sort out how different linear and exponential pitch scales should be combined: then scaling factors and their useful range of values will be easy to figure out.

Some modulation can be limited to a 2*pi range of phase and some to a conservatively small range of frequency to avoid aliasing; different mechanisms have a "natural" input range for the modulation source of -1 to 1, 0 to 1, 0 to 2*pi, -pi to pi, or something else; some intervals should scale with note frequency and some not.

Post

So.. in principle "modulation index" is really just the modulation depth for FM (or phase modulation as used in classic FM synths). Apparently some sources define "modulation index" as a ratio of FM depth vs. carrier frequency, but for music purposes the exact definition is mostly irrelevant. What is potentially relevant though is that in order to get similar sidebands on the logarithmic pitch scale (ie. what we hear), it should be the modulation index rather than the raw FM modulation depth that should be held constant. If I'm not mistaken (it's been a while since I even thought about FM), this is one of the reasons why phase-modulation is often preferred in digital implementations, because with phase modulation (again, if my memory isn't completely messed up) you obtain fixed "modulation index" by fixed modulation depth, without having to scale anything for the carrier frequency.

Post

Ok thanks for that information, I will experiment with a constant index. My synths have a bunch of modulation options, and one of them is a variation of the original post, as phase modulation.

One note is having looked at some online FM Algorithm block diagrams, I can actually see there that the modulator frequency is actually added to the carrier frequency, where as I multiply, as in obtain a modulator sample from -1 to 1, which I then multiply to my Delta like this; delta *= 1.0f + modulatorSample * modLevel
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

DKDiveDude wrote: Tue Feb 27, 2024 7:25 pm Ok thanks for that information, I will experiment with a constant index. My synths have a bunch of modulation options, and one of them is a variation of the original post, as phase modulation.

One note is having looked at some online FM Algorithm block diagrams, I can actually see there that the modulator frequency is actually added to the carrier frequency, where as I multiply, as in obtain a modulator sample from -1 to 1, which I then multiply to my Delta like this; delta *= 1.0f + modulatorSample * modLevel
Make sure you're careful whether a given document about FM is talking about true FM or phase modulation (most classic digital FM synthesizers actually do phase modulation). In terms of algorithms, the difference between the two is whether you add the modulation to the phase delta before accumulation (true FM) or simply offset the waveform lookup (phase modulation). Sometimes what is explained as FM is actually "digital FM" (referring to classic digital "FM" synths) aka. phase modulation.

Mathematically (true) FM is equivalent to phase modulation by the integral of the modulation signal and similarly phase modulation is equivalent to FM by the derivative of the modulation. If the modulation is a sinusoid, then it's integral and derivative are also sinusoids, so this distinction makes little difference (with sinusoidal modulators) except as far as integration has a frequency response of 1/f and derivative is the inverse... and this is where we get into the whole "modulation index" business, because if the modulator is at some fixed frequency ratio of the carrier, then (for a sinusoidal modulator) taking the derivative (going from FM to PM) is basically the same as dividing the modulation amount by carrier frequency.. which is exactly how modulation index is defined for FM, so for PM all you have to do is keep a fixed modulation depth.

When the modulator is not a sinusoid, the modulation waveform (obviously?) changes when we integrate or take the derivative, but one can still obtain the same results simply by choosing another modulation waveform that would have the desired integral or derivative. For example, phase modulation by a triangle is equivalent to FM with a square.

One practical difference between the two is that taking the derivative loses any DC offset (because the frequency response of derivative operator is 0 at DC), so phase modulation can never cause the fundamental frequency to shift (going the other way, that's basically your integration constant, traditionally denoted C)... which is great if you ever do cascaded modulators or "feedback FM" because you no longer need to worry about modulation causing DC offsets that then throw everything out of tune... but it also means that if you want to do pitchbends or something, that needs to be true FM if you want anything more than phase offset.

Finally, the reason that phase modulation is sometimes called "digital FM" in the context of musical synthesis might also have something to do with the fact that even though it's actually often the better choice in terms of getting predictable results, doing phase modulation is quite unnatural (ie. problematic) in analog context... where as with digital it's just a matter of changing where the modulation is added in.

Post

Yes out of my 17 modulation types, one of them is "True" FM as in I modulate the Delta, and then use that to accumulate the Phase.

Code: Select all

// modSample is between -1 and 1
// After below calculator is modulator is between 0 and 2
// If modLevel is 0, modulator is = 1
modulator = 1.0f + modSample * modLevel;
delta[carrier] *= modulator;
Where as my Phase Modulation variation, is actually a mix of the two, as in I modulate the Delta, however amount depend on the phase. So I guess you can call it phase dependent FM.

Code: Select all

// modSample is between -1 and 1
// After below calculation  modulator is between 0 and 2
// If modLevel is 0, modulator is = 1
modulator = 1.0f + (modSample / 2) * modLevel * 
     ((phaseAngle[carrier] * 2) / phaseSizeVoice[carrier]);

delta[carrier] *= modulator;
I have also tried a variation where I actually modulate the phase itself, but then I have to include phase wrap check if it exceeds end of phase
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post Reply

Return to “DSP and Plugin Development”