|

Next: A simple tutorial of
Up: SND
Previous: Additive Synthesis on SND
- Description:
Frequency Modulation (or FM) synthesis was discovered and introduced
by John Chowning at Stanford around 1973. FM is one of the pillars of
CCRMA and was the underlying technology for a very successful
synthesizer manufactured by Yamaha and known as the DX-7 during the
1980's. Many of its trademark sounds are still a novel but in the past
FM has been an efficient and simple method for generating and
simulating complex textures as the vibrato of the singing voice. FM at
its core is a simple and powerful method for creating and controlling
complex spectra and is also categorized as a worshiping method of
audio synthesis. In its simplest form it involves a sine wave carrier
whose instantaneous frequency is modulated according to another
waveform called the modulator. If the mean frequency of the modulator
reaches as high as audio frequency range, sidebands appear as partials of
the new modulated sound. This model then is often called simple FM or
sine-wave FM. Other forms of FM are extensions of the basic model.
The position of each sideband is a function of the carrier modulator
ratio or C:M ratio, and its number and amplitude change as
function of the amplitude of the modulator or depth of the
modulation. While the precise relationship between the sidebands, the
c:m ratio and the amplitude of the modulator (better known as
modulation index) is determined by the use of Bessel functions, it is
common practice to say that the number of sidebands produced on either
side of the carrier equals to the modulation index plus 2.
- Implementation:
FM synthesis is done by means of signal generators. In Snd oscil is
Bill Shottstaedt's basic and outstanding signal generator among a very
vast array of other generators. Bill's description of a signal generator is
as follows:
``A generator is a function that returns the next sample in an
infinite stream of samples each time it is called. An oscillator,
for example, returns an endless sine wave, one sample at a time''.
For more on signal generators see Dick Moore's
Elements of Computer Music
or Charles Dodge's
Computer Music.
``Furthermore each generator is made of a set of functions: Make-[gen]
sets up the data structure associated with the generator at
initialization time; [gen] produces a new sample; [gen?] checks
whether a variable is that kind of generator''.
[gen] is the name of a generator like oscil therefore
make-oscil sets up a data structure (interpolation values) at
initialization time. Then oscil produces a new sample in an
stream of samples inside a loop which repeats itself the duration of
the desired sound in seconds times the current sampling-rate.
``The initialization function normally takes a number of optional
arguments, setting whatever state the given generator needs to
operate on. The run-time (loop) function's first argument is always its
associated structure. Its second argument is nearly always something
like an FM input, whatever run-time modulation might be desired; in
other cases it can be a function to provide input data or editing
operations. Amplitude envelopes are handled with a separate env
generator. Frequency sweeps of all kinds (vibrato, glissando, breath
noise, FM proper) are all forms of run-time frequency modulation''.
In Snd's Scheme the initialization function might be something like:
(sine-wave (make-oscil :frequency frequency))
|
|
where frequency is in Hz or cycles per second (cps). There is an
optional parameter to this function which is initial-phase or the
initial angle of phase for the oscillator (oscil uses the Sine
function for sine wave generation). The run-time (loop) function
might look like:
or using the optional parameters a more complex Oscil function call
with vibrato, glissando and frequency modulation value looks like:
(oscil sine-wave (+ vibrato glissando frequency-modulation))
|
|
The Oscil signal generator definition in Snd is:
``oscil produces a sine wave (using sin) with optional frequency change
(i.e. fm). Its first argument is an oscil created by
make-oscil. Oscil's second (optional) argument is the current
(sample-wise) frequency change (it defaults to 0). The optional third
argument is the (sample-wise) phase change (in addition to the carrier
increment and so on). So the second argument can be viewed as FM,
while the third is PM (phase modulation). The initial-phase argument
to make-oscil is in radians. You can use degrees->radians to convert
from degrees to radians. To get a cosine (as opposed to sin), set the
initial-phase to (/ pi 2)''.
As can be seen a simple signal generator like Oscil can be used for
Frequency Modulation and its closely related cousin Phase
Modulation.
The terms Frequency Modulation (FM) and Phase Modulation (PM) are
source of some confusion and ambiguities. The main source of the
diverging paths taken by FM implementers can be traced to a
discrepancy between the standard analytical FM formula cited above
and ``Music-V'' implementation which have appeared in most texts on
the subject. As to this issue Bill Schottstaedt points out: ``The
difference is that FM integrates, whereas PM does not. - this does
not make up any difference in computational speed, or musical results''.
FM.html
should clear this confussion:
``The terms "angle modulation", "phase modulation", and "frequency
modulation" (not to mention "exponential modulation" and "angular
modulation") are used almost interchangeably in the radio literature,
but the textbooks on the subject normally distinguish between PM and
FM as follows: if f(t) is directly proportional to the modulating
signal then it's PM; if f(t) is directly proportional to the
derivative of the modulating signal, then it's FM. Of course, you
can't tell which is in use either from the waveform or the
mathematical expression of the waveform - you have to know what the
modulating signal was. That is a roundabout way of saying that in
computer music applications there is no essential difference between
frequency and phase modulation. However, the fact that phase and
frequency modulation are just two ways of interpreting the same thing
should not mislead us into thinking "phase doesn't matter" - the
initial phases of the parts of the FM formula do make a difference, as
we'll see below''.
As a benefit for the reader, this tutorial shows ``both'' an
instrument doing simple FM and another doing simple PM. The reader
should listen for any audible or perceptual differences.
- Frequency Increment (Frequency change parameter)
In order to understand some of the details in Frequency Modulation it
is important to understand the notion of frequency
increment. Frequency increment is expressed in terms of radians per
second (RPS). In the case of vibrato, or FM or any time we need to
specify values to the optional 2nd argument of some oscillator, it is
necessary to deal explicitly in RPS. The Snd scheme function
hz->radians converts converts frequencies expressed in cycles per
second ``Hz'' to frequencies expressed in radians per second
over the actual sampling rate.
Since we know there are 2 pi radians in one cycle and if we know
Snd's sampling rate is 22050 therefore, if we want to express
this rate in terms of radians per second, the result should be also
equal to 2 pi. To make sure this is true you can try typing the
following command on Snd's listener window,
and you should get,
which indeed is two pi.
This also means that the radian frequency of half the sampling rate is
pi, the radian frequency of 1/4 the sampling rate or quarter
cycle is pi over two and so on.
- Frequency Increment Instrument
A frequency increment instrument and other instruments inspired on Nicky
Hind's tutorials will illustrate this issue on Snd's Scheme
(you can copy and paste them directly on Snd's listener window):
(define constant-freq-inc
(lambda (beg dur frequency amplitude freq-inc)
(let* ((start (floor (* beg (srate))))
(len (floor (* dur (srate))))
(sine-wave (make-oscil :frequency frequency))
(freq-inc-radians-per-sec (hz->radians freq-inc))
(output (make-vct len)))
(do ((i 0 (1+ i)))
((= i len))
(vct-set! output i (* amplitude (oscil sine-wave freq-inc-radians-per-sec ))
))
(vct->channel output start len ))))
|
|
- First start by opening a new sound window on Snd:
(new-sound "/zap/test.snd")
|
|
- Now you can try the following function calls on the constant-freq-inc
instrument:
-
(constant-freq-inc 0 1 440 0.3 0)
|
|
Will produce a single one second 440Hz sound.
-
(constant-freq-inc 0 1 440 0.3 440)
|
|
Notice a frequency change of 440 which synthesizes a tone one octave
higher than 440Hz at 880Hz.
-
(constant-freq-inc 0 1 440 0.3 220)
|
|
Will produce a tone a fifth higher than 440Hz at 660Hz.
-
(constant-freq-inc 0 1 440 0.3 -220)
|
|
A frequency change of -220 will produce a tone an octave lower than
440Hz at 220Hz.
- Sine-Wave Instrument with Enveloped Frequency-Increment
(define enveloped-freq-inc
(lambda* (beg dur frequency amplitude #:key (freq-inc 0))
(let* ((start (floor (* beg (srate))))
(len (floor (* dur (srate))))
(freq-inc-func '(0 0 50 1 100 0))
(sine-wave (make-oscil :frequency frequency))
(freq-env (make-env :envelope freq-inc-func
:scaler (hz->radians freq-inc)
:start beg
:duration dur))
(output (make-vct len)))
(do ((i 0 (1+ i)))
((= i len))
(vct-set! output i (* amplitude (oscil sine-wave (env freq-env) ))
))
(vct->channel output start len ))))
|
|
- Start by opening a new sound window on Snd if you don't already
have one.
(new-sound "/zap/test.snd")
|
|
- Now try the following function calls on the enveloped-freq-inc
instrument:
-
(enveloped-freq-inc 0 1 440 0.3)
|
|
Will produce a one second sound at 440Hz with no frequency increment.
-
(enveloped-freq-inc 0 1 440 0.3 :freq-inc 440)
|
|
This call produces a glissando up to one octave higher and back
again.
-
(enveloped-freq-inc 0 1 440 0.3 :freq-inc -220)
|
|
This call produces a glissando down to one octave below and back
again. Notice -220 frequency change.
Following we have Scheme code for a very simple FM instrument which
can be used as a template for more complex instruments and in fact
more complex projects in Snd. Notice that make-oscil and
make-env are the definitions for the the signal generators
oscil and env respectively. Here we are creating two
oscillators for the carrier and modulator plus one amplitude envelope
and a modulation-index envelopes which changes as sound unfolds.
- Simple FM Instrument
(define simple-fm
(lambda* (start dur freq amp #:key
(ampenv '(0 0 25 1 75 1 100 0))
(mratio 1) (index 1) (indenv '(0 1 100 1)))
;;
(let* ((beg (floor (* start (srate))))
(end (floor (* dur (srate))))
(car (make-oscil :frequency freq))
(mod (make-oscil :frequency (* freq mratio)))
(ampf (make-env :envelope ampenv :scaler amp
:start start :end end))
(devf (make-env :envelope indenv
:scaler (in-hz (* freq mratio index))
:start start :end end))
;;
;; Here we create a vector data structure to store
;; the processed audio data
;;
(out-data (make-vct end)))
;;
;; The part that follows is like the Run loop in CLM
;; or where the actual sound data is assigned to the
;; out-data vector
;;
(vct-map! out-data (lambda ()
(* (env ampf)
(oscil car (* (env devf)
(oscil mod))))
))
;;
;; This function outputs samples to the actice soundfile
;; window in SND
;;
(vct->channel out-data beg end ))
))
|
|
The function calls for this instrument are as follows:
- Open a new sound:
(new-sound "/zap/test.snd")
|
|
- A simple function call to the instrument with it default values:
There is a carrier frequency of 400Hz and a sideband of 800Hz with 0.65
the value of the amplitude of the carrier. You can activate the FFT
or (f) view of your Snd sound file to make sure these are the values
of this spectra.
- Changing the modulation-index to 0.75
(simple-fm 0 3 400 0.5 :index 0.75)
|
|
Here we get a different spectrum with a carrier frequency at its
maximum amplitude and a second sideband frequency which decreases 40%
the value of the peak amplitude.
- In the next function call we are manipulating the modulation
index as well as C:M ratio. In this case we are using a C:M ratio of
4:1
(simple-fm 0 3 400 0.5 :index 0.75 :mratio 4)
|
|
then we obtain sidebands on 100Hz with 0.95 amplitude and at 690Hz
and the same 0.95 amplitude.
- Now if we change both the modulation-index to 1.75 and the C:M
ratio also to 4,
(simple-fm 0 3 400 0.5 :index 1.75 :mratio 4)
|
|
here we get a fundamental frequency around 200Hz at the peak amplitude
and average sidebands at 200Hz and 975Hz each one with an average
amplitude of 0.925 the peak amplitude.
- In this last example of function call we change the default
modulation-index envelope to '(0 0.25 100 1.75) meaning that
the value of the modulation index increases from 0.25 to 1.75 along
the duration of the sound. Make sure to open the frequencies view or
F-view on Snd's graphic interface to get a good look at the spectra of
the sound. Move the sliders to see how the sound evolves.
(simple-fm 0 3 400 0.5 :index 0.75 :mratio 4 :indenv '(0 0.25 100 1.75))
|
|
Notice that we get a changing spectra with an average carrier
frequency of 400Hz.
- You can always play an active sound window in Snd by using the
(play) function call (you can always type ' C-x u ' to
undo or erase the active sound you just created on Snd's editing
window):
- Simple Phase Modulation Instrument
As previously discussed if f(t) is directly proportional to the
modulating signal then we have Phase Modulation. If f(t) is directly
proportional to the derivative of the modulating signal, then we have
Frequency Modulation or FM. This means that difference between PM and
FM lies in that FM integrates, whereas PM does not. This does not mean
that there is any difference in computational speed, musical or
perceptual results. Snd provides tools to check this analytically with
its spectrogram windows which can be dragged to change with time. Here
we have a simple ``Phase Modulation'' instrument. Notice the
modulating frequency at oscil's fourth parameter.
(define simple-pm
(lambda* (start dur freq amp #:key
(ampenv '(0 0 25 1 75 1 100 0))
(mratio 1) (index 1) (indenv '(0 1 100 1))
(fmp-inc 0.0)) ;; FM phase increment
;;
(let* ((beg (floor (* start (srate))))
(end (floor (* dur (srate))))
(freq-mod (hz->radians fmp-inc))
(phase-mod 0.00)
(car (make-oscil :frequency freq))
(mod (make-oscil :frequency (* freq mratio)))
(ampf (make-env :envelope ampenv :scaler amp
:start start :end end))
(devf (make-env :envelope indenv
:scaler (in-hz (* freq mratio index))
:start start :end end))
(out-data (make-vct end)))
;;
;; Here we generate an out-data vector.
;; Notice the phase-mod part inside "oscil" which is
;; incremented on each pass.This instrument is actually
;; doing Phase Modulation
;;
(do ((i 0 (1+ i)))
((= i end))
(vct-set! out-data i (* (env ampf)
(oscil car freq-mod (* (env devf)(oscil mod))))) )
;;
;; Output samples to the active soundfile window in SND
;;
(vct->channel out-data beg end ))
))
|
|
The same function calls for the Phase Modulation instrument are:
- Conclusion
Synthesis of audio by means of Frequency Modulation and its relatives
is still a powerful method for generating complex spectra. Many
instruments using this principle as a basis have been developed and
include violins, trumpets, plucked strings as well as bells, gongs,
drums and more. As John Chowning points out, the richness of FM lies
in the ability to manipulate on the time domain the spectrum of a
sound. We have seen that this can be easily accomplished by using
envelope generators which control the modulation-index over time.
- Further information:
- John Chowning. The synthesis of complex audio spectra by
means of frequency modulation. Journal of the Audio Engineering
Society, 7:pp:526-534, 1973.
- William Schottstaedt. The simulation of natural
instrument tones using frequency modulation with a complex
modulating wave. Computer Music Journal, 1(4), 1977.
- Barry Truax. Organizational techniques for c:m ratios in
frequency modulation. Computer Music Journal, pages 39-45, 1978.
Reprinted in Foundations of Computer Music, C. Roads and J. Strawn
(eds.). MIT Press, 1985.
- Dexter Morril. Trumpet algorithms for computer
composition. Computer Music Journal, 1(1):46-52, 1977. Reprinted
in Foundations of Computer Music, C. Roads and J. Strawn (eds.). MIT
Press, 1985.
- James Beauchamp. Letters to the editor: Will the real fm
equation please stand up ? Computer Music Journal, 16(4), 1992.
Next: A simple tutorial of
Up: SND
Previous: Additive Synthesis on SND
© Copyright 2001-2006 CCRMA, Stanford University. All rights reserved.
Created and Mantained by Juan Reyes
|