AM & Ringmodulation: Formula & Spectrum

Amplitude Modulation vs Ringmodulation

The basic formula is the same for amplitude modulation and ringmodulation:

\(y[n] = x[n] \cdot m[n]\)

However, for ringmodulation the modulation signal is symmetric:

\(y[n] = \sin\left(2 \pi f_1 \frac{n}{f_s}\right) \cdot \left(\sin\left[2 \pi f_m \frac{n}{f_s}\right]\right)\)

Whereas for amplitude modulation, the signal ist asymetric:

\(y[n] = \sin\left(2 \pi f_1 \frac{n}{f_s}\right) \cdot \left( 1+ \sin\left[2 \pi f_m \frac{n}{f_s}\right]\right)\)

This differnce has an influence on the resulting spectrum and on the sound, as the following examples show.

import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
from scipy import signal
from IPython.display import display, Markdown, clear_output
import IPython.display as ipd

from ipywidgets import *

# define functions for AM and ringmod

def am(f1, f2, t):

    x = np.sin(2*np.pi*f1*t)
    m = 1+np.sin(2*np.pi*f2*t)

    y = x*m
    return(y,m,x)



def ringmod(f1, f2, t):

    x = np.sin(2*np.pi*f1*t)
    m = np.sin(2*np.pi*f2*t)

    y = x*m
    return(y,m,x)

AM Spectrum

\(Y = DFT(y)\)

The spectrum for amplitude modulation can be calculated as follows:

\(Y[k] = \sum_{n=0}^{N-1} y[n] \cdot e^{-j 2 \pi k \frac{n}{N}}\)

\(= \sum_{n=0}^{N-1} \sin\left(2 \pi f_1 \frac{n}{f_s}\right) \cdot \left( 1+ \sin\left[2 \pi f_m \frac{n}{f_s}\right]\right) \cdot e^{-j 2 \pi k \frac{n}{N}}\)

\(=\sum_{n=0}^{N-1} \left( \sin\left(2 \pi f_1 \frac{n}{f_s}\right) + 0.5 \left( \cos\left(2 \pi (f_1 - f_m)\frac{n}{f_s}\right) - \cos\left(2 \pi (f_1 + f_m)\frac{n}{f_s}\right) \right) \right) \cdot e^{-j 2 \pi k \frac{n}{N}}\)

\(= delta[f_1] + 0.5 \delta[f_1 - f_m] + 0.5 \ \delta[f_1 + f_m]\)

AM creates a spectrum with a peak at the carrier frequency and two peaks below and above it. Their position is defined by the difference between carrier and modulator.

# visualization in the time domain

# basic parameters
fs = 48000
L  = 48000

t  = np.linspace(0,1,L)
f  = np.linspace(-0.5,0.5,L)


f_car = 400
f_mod = 170
[x, x_car, x_sig] = ringmod(f_mod, f_car, t)


fig1, ax1 = plt.subplots()

plt.title("Modulated Signal")

ax1.set_xlabel('t/s')
ax1.set_ylabel('x' ,color = [ 0.3, 0.3, 0.3])
ax1.set_xlim(0, 0.15)

ipd.display(ipd.Audio(x, rate=fs))

line, = ax1.plot(t,x);

def update( f_mod = widgets.IntSlider(min = 1, max= 1000, step=1, value=170),
            f_car = widgets.IntSlider(min = 1, max= 1000, step=1, value=400)):

    [x, x_car, x_sig] = ringmod(f_mod, f_car, t)


    line.set_ydata(x)
    fig1.canvas.draw_idle()

    ipd.display(ipd.Audio(x, rate=fs))

interact(update);
<IPython.core.display.Javascript object>
interactive(children=(IntSlider(value=170, description='f_mod', max=1000, min=1), IntSlider(value=400, descrip…
# visualization in the frequency domain

f_car = 400
f_mod = 170
[x, x_car, x_sig] = ringmod(f_mod, f_car, t)

# fft stuff
X = np.fft.fftshift(np.fft.fft(x))
X = X/(L)

X_car = np.fft.fftshift(np.fft.fft(x_car))
X_car = X_car/(L)

X_sig = np.fft.fftshift(np.fft.fft(x_sig))
X_sig = X_sig/(L)


fig1, ax1 = plt.subplots()

ax1.set_xlabel('$\omega$')
ax1.set_ylabel('|X|' ,color = [ 0.3, 0.3, 0.3])
ax1.set_xlim(-0.1, 0.1)

# for static HTML output:
line, = ax1.plot(f,abs(X));
ipd.display(ipd.Audio(x, rate=fs))

# for interactive output:
def update(  f_mod = widgets.IntSlider(min = 1, max= 1000, step=1, value=170),
             f_car = widgets.IntSlider(min = 1, max= 1000, step=1, value=400)):

    [x, x_car, x_sig] = ringmod(f_mod, f_car, t)


    X = np.fft.fftshift(np.fft.fft(x))
    X = X/(L)

    X_car = np.fft.fftshift(np.fft.fft(x_car))
    X_car = X_car/(L)

    X_sig = np.fft.fftshift(np.fft.fft(x_sig))
    X_sig = X_sig/(L)

    line.set_ydata(abs(X))
    fig1.canvas.draw_idle()

    ipd.display(ipd.Audio(x, rate=fs))

interact(update);
<IPython.core.display.Javascript object>
interactive(children=(IntSlider(value=170, description='f_mod', max=1000, min=1), IntSlider(value=400, descrip…

Ringmod Spectrum

\(\mathcal{F} [ y(t)] = \int\limits_{-\inf}^{\inf} y(t) e^{-j 2 \pi f t} \mathrm{d}t\)

\(= \int\limits_{-\inf}^{\inf} \left( \sin(2 \pi f_c t) \sin(2 \pi f_s t) \right) e^{-j 2 \pi f t} \mathrm{d}t\)

\(= \frac{1}{2 j} \int\limits_{-\inf}^{\inf} \left( (-e^{-j 2 \pi f_c t} +e^{j 2 \pi f_c t}) (-e^{-j 2 \pi f_s t} +e^{j 2 \pi f_s t}) \right) \ e^{-j 2 \pi f t} \mathrm{d}t\)

\(= \frac{1}{2 j} \int\limits_{-\inf}^{\inf} \left( e^{j 2 \pi (f_c+f_s) t} - e^{j 2 \pi (f_c-f_s) t} - e^{j 2 \pi (-f_c+f_s) t} + e^{j 2 \pi (-f_c-f_s) t} \right) e^{-j 2 \pi f t}\)

\(= \frac{1}{2 j} \left[ \delta(f_c+f_s) -\delta(f_c-f_s) - \delta(-f_c+f_s) + \delta(-f_c-f_s) \right]\)

Ringmodulation creates a spectrum with
two peaks below and above the carrier frequency. Their position is defined by the difference between carrier and modulator.
The modulator is supressed, since it is symmetric.
# visualization in the time domain

# basic parameters
fs = 48000
L  = 48000

t  = np.linspace(0,1,L)
f  = np.linspace(-0.5,0.5,L)


f_car = 500
f_mod = 100
[x, x_car, x_sig] = am(f_mod, f_car, t)


fig1, ax1 = plt.subplots()

plt.title("Modulated Signal")

ax1.set_xlabel('t/s')
ax1.set_ylabel('x' ,color = [ 0.3, 0.3, 0.3])
ax1.set_xlim(0, 0.15)

ipd.display(ipd.Audio(x, rate=fs))

line, = ax1.plot(t,x);

def update( f_mod = widgets.IntSlider(min = 1, max= 1000, step=1, value=40),
            f_car = widgets.IntSlider(min = 1, max= 1000, step=1, value=500)):

    [x, x_car, x_sig] = am(f_mod, f_car, t)


    line.set_ydata(x)
    fig1.canvas.draw_idle()

    ipd.display(ipd.Audio(x, rate=fs))

interact(update);
<IPython.core.display.Javascript object>
interactive(children=(IntSlider(value=40, description='f_mod', max=1000, min=1), IntSlider(value=500, descript…
# visualization in the frequency domain

f_car = 400
f_mod = 170
[x, x_car, x_sig] = am(f_mod, f_car, t)

# fft stuff
X = np.fft.fftshift(np.fft.fft(x))
X = X/(L)

X_car = np.fft.fftshift(np.fft.fft(x_car))
X_car = X_car/(L)

X_sig = np.fft.fftshift(np.fft.fft(x_sig))
X_sig = X_sig/(L)


fig1, ax1 = plt.subplots()

ax1.set_xlabel('$\omega$')
ax1.set_ylabel('|X|' ,color = [ 0.3, 0.3, 0.3])
ax1.set_xlim(-0.1, 0.1)

# for static HTML output:
line, = ax1.plot(f,abs(X));
ipd.display(ipd.Audio(x, rate=fs))

# for interactive output:
def update(  f_mod = widgets.IntSlider(min = 1, max= 1000, step=1, value=400),
             f_car = widgets.IntSlider(min = 1, max= 1000, step=1, value=170)):

    [x, x_car, x_sig] = am(f_mod, f_car, t)


    X = np.fft.fftshift(np.fft.fft(x))
    X = X/(L)

    X_car = np.fft.fftshift(np.fft.fft(x_car))
    X_car = X_car/(L)

    X_sig = np.fft.fftshift(np.fft.fft(x_sig))
    X_sig = X_sig/(L)

    line.set_ydata(abs(X))
    fig1.canvas.draw_idle()

    ipd.display(ipd.Audio(x, rate=fs))

interact(update);
<IPython.core.display.Javascript object>