Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
70 views

Playing around with FM synthesis

Preliminaries

var('t')
t
# Fourier transform plotting function: # tmin and tmax give the range of values to sample. # size is the number of sample points: # According to the Nyquist–Shannon sampling theorem, # this must be at least twice the highest frequency component we wish to include. # barlimit is the largest frequency plotted. def plotFT(func, tmin, tmax, size, barlimit): delta = (tmax - tmin)/size # Create an empty Fast Fourier Transform object fft_data = FFT(size) # Populate it with data sampled from func. for t in range(size): fft_data[t] = func(tmin + t * delta) # Fourier transform to convert to frequency domain # (Modifies fft_data in place.) fft_data.forward_transform() # Create array for amplitudes fft_freq = [0 for k in range(1/delta)] # Populate fft_freq with the computed amplitudes # (For technical reasons, we only have to compute this for half of the sampled frequencies) for f in range(size/2): fft_freq[int(f/(size * delta))] = abs(vector(fft_data[f])) # Plot results return bar_chart(fft_freq[0:barlimit])

The formula

The formula is y=Asin(2πfct+Bsin(2π(fmt)))y = A\sin\left( 2\pi f_{c} t + B\sin(2\pi(f_{m}t)) \right) where fcf_{c} is the carrier frequency, fmf_{m} is the modulating frequency, and BB is the modulation index.

Here's an example with fc=20 Hzf_{c} = 20 \text{ Hz}, fm=2 Hzf_{m}= 2 \text{ Hz}, and B=1B = 1:

f1(t) = sin(2*pi*(20*t) + sin(2*pi*(2*t))) plot(f1, (t, 0, 1))

Here's the Fourier transform of that:

plotFT(f1, tmin = 0, tmax = 1, size = 100, barlimit = 40)

One can see the "side bands" around 20 Hz. These side bands spread as the modulation index increases.

f2(t) = sin(2*pi*(20*t) + 2*sin(2*pi*(2*t))) plot(f2, (t, 0, 1))
plotFT(f2, tmin = 0, tmax = 1, size = 100, barlimit = 40)
f3(t) = sin(2*pi*(20*t) + 3*sin(2*pi*(2*t))) plot(f3, (t, 0, 1))
plotFT(f3, tmin = 0, tmax = 1, size = 100, barlimit = 40)

TODO: Check that the amplitudes are scaled correctly. (Bessel functions.)

In the typical application, the modulating frequency is the same or close to the carrier frequency. If they are the same:

f4(t) = sin(2*pi*(20*t) + sin(2*pi*(20*t))) plot(f4, (t, 0, 0.2))
plotFT(f4, tmin = 0, tmax = 0.2, size = 500, barlimit = 200)
f5(t) = sin(2*pi*(20*t) + 5*sin(2*pi*(20*t))) plot(f5, (t, 0, 0.2))
plotFT(f5, tmin = 0, tmax = 0.2, size = 500, barlimit = 200)

What about a modulation frequency that is a perfect fifth away from the carrier frequency?

f6(t) = sin(2*pi*(20*t) + sin(2*pi*(30*t))) plot(f6, (t, 0, 0.2))
plotFT(f6, tmin = 0, tmax = 0.2, size = 500, barlimit = 200)
f7(t) = sin(2*pi*(20*t) + 5*sin(2*pi*(30*t))) plot(f7, (t, 0, 0.2))
plotFT(f7, tmin = 0, tmax = 0.2, size = 600, barlimit = 300)