Complex Waveforms III - Frequency Modulation
Another common method of obtaining complex waveforms is by frequency modulation (FM).[1] FM is produced by using one oscillator (the modulator) to vary the frequency of a second oscillator (the carrier).
The modulator amplitude (Am) determines the peak variation in frequency of the signal while the modulator frequency determines the rate at which the frequency changes. When the frequencies of both oscillators are in the audible range, the sidebands are also in the audible range. The result is a rich spectrum created by the varying sum and difference of the two frequencies. Modulator frequency is often specified as a multiple of the carrier and expressed by the term c:m ratio. Integer multiples produce a harmonic spectrum while non-integer multiples produce an inharmonic spectrum.
We can produce FM by calculating two waveforms simultaneously and use the value from the first waveform to calculate the phase increment of the second waveform.
frqRad = twoPI / sampleRate; modIncr = frqRad * modFrequency; modPhase = 0; modAmp = 100; carPhase = 0; for (n = 0; n < totalSamples; n++) { sample[n] = sin(carPhase); modValue = modAmp * sin(modPhase); carIncr = frqRad * (carFrequency + modValue); carPhase += carIncr; if (carPhase >= twoPI) carPhase -= twoPI; else if (carPhase < 0) carPhase += twoPI;
modPhase += modIncr; if (modPhase >= twoPI) modPhase -= twoPI; }
We can re-factor the calculation of the carrier phase as:
carIncr = frqRad * carFrequency; modValue = (frqRad * modAmp) * sin(modPhase); carPhase += carIncr + modValue
In this form, the values for frqRad*carFrequency and frqRad*modAmp are loop invariant and can be calculated once. Thus, instead of calculating the carrier phase increment repeatedly on each sample, we simply add the modulator value to the carrier phase.
modIncr = frqRad * modFrequency; carIncr = frqRad * carFrequency; modAmp = frqRad * 100; modPhase = 0; carPhase = 0; for (n = 0; n < totalSamples; n++) { sample[n] = volume * sin(carPhase); modValue = modAmp * sin(modPhase); carPhase += carIncr + modValue; modPhase += modIncr; }
In the first example we modified the phase increment, while the second example directly modifies the phase. For that reason it is sometimes called phase modulation rather than frequency modulation. However, both programs produce the same results.
The only significant difference between the two programs is in how we specify the modulator amplitude. The modulator amplitude affects the change in frequency of the carrier (Δf). When using the frequency modulation version, the modAmp value represents change in frequency and is limited to the maximum frequency range. When using the phase modulation version, the value represents change in radians of phase increment and we need to convert the value from frequency to radians.
The value for modulator amplitude must be chosen carefully to avoid driving the carrier past the Nyquist frequency while also providing a good range of sum and difference tones. A high value for modulator amplitude will produce a "noisy" signal, which can sometimes be used as a special sound effect. But a useful maximum for Δf is around 2,000, or about 1/10th of the Nyquist frequency.
The modulator amplitude affects the spectrum differently at varying carrier and modulator frequencies. For example, a carrier of 100Hz and a modulator amplitude of 50 will vary the carrier over the range of 50 to 150 Hz, or 50% of the carrier frequency. However, with a carrier at 1000Hz, a modulator amplitude of 50 will only vary the frequency from 950 to 1050Hz, or 5% of the frequency. This means that the timbre will vary considerably over the entire frequency range when we have a fixed modulator amplitude. For this reason, a good FM instrument uses the value of the "index of modulation" to calculate the modulator amplitude. Index of modulation is defined as I=Δf/fm where Δf is the peak frequency deviation and fm is the modulator frequency. The modulator amplitude determines the variation in frequency and is thus the same as Δf . We can calculate modulator amplitude as Am=I·fm. Using the index of modulation to calculate the modulator amplitude produces a timbre that remains constant across all frequencies.
We can extend this basic two-oscillator generator by adding an additional modulator and using two modulating signals on the carrier:
mod1Value = mod1Amp * sin(mod1Phase); mod2Value = mod2Amp * sin(mod2Phase); carPhase = carIncrement + mod1Value + mod2Value;
Or, we can cascade two or more modulators:
mod1Value = mod1Amp * sin(mod1Phase); mod2Phase = mod2Phase + mod2Increment + mod1Value; mod2Value = mod2Amp * sin(mod2Phase); carPhase = carIncrement + mod2Value;
Thus, by adding only a few additional lines of code, we can produce a very wide range of dynamically varying timbres. Note, however, that if we add multiple modulators to a single carrier, the index increment can potentially exceed the maximum phase increment. When adding multiple phase increments the total value must not exceed π or it will produce an alias frequency. Although we could test each modulator on each sample, it would be much more efficient to insure the peak amplitude of the modulators is within range before calculating samples, similar to what was done with summation of sine waves.
We are not limited to using sine waves for the carrier and modulator waveforms. We can start with a carrier that is produced as a sum of sine waves and then modulate that signal to produce an even more complex and rich spectrum. Finally, applying a separate envelope to each modulator allows modulation effects to grow or diminish, or vary in effect, over the duration of the sound and on a note to note basis. The wide variety of sounds available from only a few lines of programming is the reason so many synthesizer systems rely heavily on FM synthesis techniques.
FM Investigator
The FM Investigator utility performs simple FM synthesis using three oscillators.
The four buttons on the bottom left select the "algorithm." In the single modulator stack only Modulator I affects the carrier. In the double stack configuration, Modulator II is applied to Modulator I and then Modulator I is applied to the carrier. In the "Y" configuration, the modulators are summed and the sum applied to the carrier. The fourth version modulates the carrier directly with both modulators.
Carrier frequency is specified as a pitch number (0-120) with middle C at index 60 (ala MIDI). Modulator frequency is specified as a multiple of the carrier in the range 0-10 and may be harmonic (integer values) or inharmonic (real values).
The envelope generators are ADSR types with attack and decay rates in the range 0-1 second.
The amplitude of the carrier EG sets the volume level. The amplitude of a modulator sets the modulation depth and is specified as an index of modulation, per Chowning's method. The index of modulation has a range of 0-50.
Values can be entered using the sliders or by typing directly into the edit fields. Moving out of an edit field automatically updates the slider position.
Sound can be played from this program. The "Play" button (>) plays the sound once. The "Loop" button plays the sound repeatedly.
The sound can be saved as a single channel (monophonic) .WAV file.
Download the FM Investigator Program
[1] The use of FM for audio synthesis was discovered and developed by John M. Chowning in the late 1960's and described in "The Synthesis of Complex Audio Spectra by Means of Frequency Modulation", JAES 21:526-534, 1973. Chowning has said, "While performing some not very rigorous experiments with vibrato in 1967-68, I suddenly realized that with extreme vibrato, I was not hearing changes in pitch but rather changes in timbre." Those of us who learned synthesis on big Moog systems, discovered the same thing! Chowning was awarded U.S. Patent 4018121, which became the basis for the Yamaha DX series of synthesizers. The patent expired in 1995. |