Understanding 2 OP FM parameters in Plaits

Hello, I’m trying to learn about DSP and am trying to implement a simple two operator FM synth. I was wondering what range of values are used for the modulation index and ratio in Plaits’ Two Operator FM mode? That is, the base range, before any external modulation is applied.

I’ve been poking around in the Plaits source code but I can’t find where these ranges are defined.

Looking in fm_engine.cc, it looks like the relevant code is here:

const float note = parameters.note - 24.0f;

const float ratio = Interpolate(
lut_fm_frequency_quantizer,
parameters.harmonics,
128.0f);

float modulator_note = note + ratio;
float target_modulator_frequency = NoteToFrequency(modulator_note);
CONSTRAIN(target_modulator_frequency, 0.0f, 0.5f);

// Reduce the maximum FM index for high pitched notes, to prevent aliasing.
float hf_taming = 1.0f - (modulator_note - 72.0f) * 0.025f;
CONSTRAIN(hf_taming, 0.0f, 1.0f);
hf_taming *= hf_taming;

ParameterInterpolator carrier_frequency(
&previous_carrier_frequency_, NoteToFrequency(note), size);
ParameterInterpolator modulator_frequency(
&previous_modulator_frequency_, target_modulator_frequency, size);
ParameterInterpolator amount_modulation(
&previous_amount_,
2.0f * parameters.timbre * parameters.timbre * hf_taming,
size);
ParameterInterpolator feedback_modulation(
&previous_feedback_, 2.0f * parameters.morph - 1.0f, size);

I can’t figure out where these ParameterInterpolator functions are defined, or the Interpolate() function.

Thanks!

Did some more searching and found this thread where @pichenettes details the actual values, but I’d still love to know where in the code they’re defined.

Interpolate is defined here:

This function reads from a lookup table, with interpolation between values. The ratios are defined in lut_fm_frequency_quantizer (located in resources.cc) and go from -12 semitones (0.5) to +36 semitones (8).

The python code that generates this LUT is here:

The modulation index (amount_modulation here) goes from 0.0 to 2.0, follows a quadratic law (ie, when the knob is at 12 o’clock, the index is 0.5), and there’s a little magic in the hf_taming variable to reduce the range of the FM index when the root note and the FM ratio are high).

ParameterInterpolator is defined here: https://github.com/pichenettes/stmlib/blob/c0c42ec91d315a2ec9c0a3845e593b71ffa429db/dsp/parameter_interpolator.h#L36

It is an abstraction for linearly interpolating the value of a CV (usually acquired at a rate of a few kHz) so that it results in smoother audio-rate modulations.

1 Like

Perfect, thank you!