AM変調の理論と数学的導出を解説して実装する

AM(Amplitude Modulation: 振幅変調)は、最も古典的でありながら、変調理論を学ぶ上で最も基本的な変調方式です。搬送波の振幅を情報信号に応じて変化させることで、ベースバンド信号を高周波帯に乗せて送信します。

AMラジオ放送をはじめ、航空無線、非常通信など、現在でも広く利用されています。AM変調の数学的構造を理解することは、DSB-SC、SSB、QAMといった発展的な変調方式を理解する上での土台となります。

本記事の内容

  • AM変調の数学的表現と変調度の定義
  • スペクトル解析(フーリエ変換による搬送波・側帯波の導出)
  • 電力効率の導出
  • DSB-SC、SSB、VSBの比較
  • 包絡線検波と同期検波の原理
  • Pythonでの実装とシミュレーション

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

AM変調の数学的表現

搬送波とベースバンド信号

搬送波(キャリア)を次のように定義します。

$$ c(t) = A_c \cos(2\pi f_c t) $$

ここで $A_c$ は搬送波の振幅、$f_c$ は搬送波の周波数です。

情報を運ぶベースバンド信号(メッセージ信号)を $x(t)$ とし、最大振幅が1に正規化されているとします($|x(t)| \leq 1$)。

AM変調信号

AM変調信号 $s(t)$ は、搬送波の振幅をベースバンド信号に応じて変化させたものです。

$$ \boxed{ s(t) = A_c \left[ 1 + m \cdot x(t) \right] \cos(2\pi f_c t) } $$

ここで $m$ は変調度(modulation index)と呼ばれ、$0 \leq m \leq 1$ の範囲で設定します。

$1 + m \cdot x(t)$ の部分が搬送波の包絡線(envelope)を形成します。この包絡線が元のベースバンド信号の形を保持しているため、簡単な回路で復調が可能です。

変調度の物理的意味

変調度 $m$ は、搬送波の振幅変動の度合いを表します。AM信号の包絡線の最大値 $A_{\max}$ と最小値 $A_{\min}$ を用いて、

$$ A_{\max} = A_c(1 + m), \quad A_{\min} = A_c(1 – m) $$

これらを解くと、

$$ \boxed{ m = \frac{A_{\max} – A_{\min}}{A_{\max} + A_{\min}} } $$

$m = 1$ のとき、包絡線の最小値はちょうどゼロになります。$m > 1$ の場合(過変調)、包絡線が負になる区間が発生し、包絡線検波では正しく復調できなくなります。

AM信号のスペクトル解析

フーリエ変換による導出

AM信号のフーリエ変換を求めます。$x(t)$ のフーリエ変換を $X(f)$ とします。

$$ s(t) = A_c \cos(2\pi f_c t) + m A_c \, x(t) \cos(2\pi f_c t) $$

第1項のフーリエ変換は、

$$ \mathcal{F}\left[ A_c \cos(2\pi f_c t) \right] = \frac{A_c}{2} \left[ \delta(f – f_c) + \delta(f + f_c) \right] $$

第2項について、$x(t) \cos(2\pi f_c t)$ のフーリエ変換を求めます。周波数シフトの性質(変調定理)を用います。

$$ \mathcal{F}\left[ x(t) \cos(2\pi f_c t) \right] = \mathcal{F}\left[ x(t) \cdot \frac{e^{j2\pi f_c t} + e^{-j2\pi f_c t}}{2} \right] $$

$$ = \frac{1}{2} \mathcal{F}\left[ x(t) e^{j2\pi f_c t} \right] + \frac{1}{2} \mathcal{F}\left[ x(t) e^{-j2\pi f_c t} \right] $$

周波数シフトの性質 $\mathcal{F}[x(t) e^{j2\pi f_0 t}] = X(f – f_0)$ より、

$$ = \frac{1}{2} X(f – f_c) + \frac{1}{2} X(f + f_c) $$

したがって、AM信号のスペクトルは

$$ \boxed{ S(f) = \frac{A_c}{2} \left[ \delta(f – f_c) + \delta(f + f_c) \right] + \frac{mA_c}{2} \left[ X(f – f_c) + X(f + f_c) \right] } $$

スペクトルの構造

上式から、AM信号のスペクトルは以下の3つの成分から構成されることがわかります。

  1. 搬送波成分: $f = \pm f_c$ に立つデルタ関数。情報を運んでおらず、電力を消費するだけです。
  2. 上側帯波(USB: Upper Side Band): $X(f – f_c)$ に対応。$f_c$ より高い周波数に元信号のスペクトルがシフトしたものです。
  3. 下側帯波(LSB: Lower Side Band): $X(f + f_c)$ のうち正の周波数部分に対応。$f_c$ より低い周波数側に元信号のスペクトルが反転してシフトしたものです。

元のベースバンド信号の帯域幅が $W$ の場合、AM信号の占有帯域幅は

$$ B_{\text{AM}} = 2W $$

USBとLSBにそれぞれ同じ情報が含まれているため、帯域効率の点では無駄があります。

正弦波変調の具体例

$x(t) = \cos(2\pi f_m t)$(単一トーン)の場合、

$$ s(t) = A_c \left[ 1 + m \cos(2\pi f_m t) \right] \cos(2\pi f_c t) $$

積和の公式 $\cos A \cos B = \frac{1}{2}[\cos(A-B) + \cos(A+B)]$ を適用すると、

$$ s(t) = A_c \cos(2\pi f_c t) + \frac{mA_c}{2} \cos\left[2\pi (f_c – f_m) t\right] + \frac{mA_c}{2} \cos\left[2\pi (f_c + f_m) t\right] $$

搬送波(振幅 $A_c$)、LSB(振幅 $mA_c/2$)、USB(振幅 $mA_c/2$)の3つの正弦波成分に分解されることが明確にわかります。

AM信号の電力と電力効率

各成分の電力

正弦波 $A\cos(\omega t)$ の平均電力は $A^2/2$ ですから、単一トーン変調の場合、

$$ P_{\text{carrier}} = \frac{A_c^2}{2} $$

$$ P_{\text{USB}} = P_{\text{LSB}} = \frac{1}{2}\left(\frac{mA_c}{2}\right)^2 = \frac{m^2 A_c^2}{8} $$

全体の平均電力は、

$$ P_{\text{total}} = P_{\text{carrier}} + P_{\text{USB}} + P_{\text{LSB}} = \frac{A_c^2}{2} + \frac{m^2 A_c^2}{4} = \frac{A_c^2}{2}\left(1 + \frac{m^2}{2}\right) $$

電力効率の導出

情報を運んでいるのは側帯波のみです。電力効率 $\eta$ は、全電力に対する側帯波電力の比として定義されます。

$$ \eta = \frac{P_{\text{USB}} + P_{\text{LSB}}}{P_{\text{total}}} = \frac{\frac{m^2 A_c^2}{4}}{\frac{A_c^2}{2}\left(1 + \frac{m^2}{2}\right)} $$

分子と分母を $A_c^2/4$ で割ると、

$$ \eta = \frac{m^2}{2 + m^2} $$

$$ \boxed{ \eta = \frac{m^2}{2 + m^2} } $$

$m = 1$(最大変調度、過変調なし)のとき、

$$ \eta = \frac{1}{2 + 1} = \frac{1}{3} \approx 33.3\% $$

つまり、AM変調では最良でも全電力の3分の1しか情報伝送に使われません。残りの3分の2は搬送波に消費されます。これがAMの電力効率が低いと言われる理由です。

一般のベースバンド信号 $x(t)$ に対しては、$m^2$ の代わりに $m^2 \overline{x^2(t)}$($x(t)$ の平均電力)を用います。

DSB-SC、SSB、VSBとの比較

AM変調の電力効率の低さを改善するため、いくつかの派生方式が考案されています。

DSB-SC(Double Side Band – Suppressed Carrier)

搬送波成分を除去した変調方式です。

$$ s_{\text{DSB-SC}}(t) = A_c \, x(t) \cos(2\pi f_c t) $$

搬送波電力がゼロになるため、電力効率は100%に改善されます。ただし、包絡線が情報信号の形を保持しないため、復調には同期検波が必要です。

スペクトルは、

$$ S_{\text{DSB-SC}}(f) = \frac{A_c}{2}\left[ X(f – f_c) + X(f + f_c) \right] $$

占有帯域幅は通常AMと同じ $2W$ です。

SSB(Single Side Band)

USBまたはLSBの一方のみを送信する方式です。

$$ s_{\text{SSB}}(t) = \frac{A_c}{2}\left[ x(t) \cos(2\pi f_c t) \mp \hat{x}(t) \sin(2\pi f_c t) \right] $$

ここで $\hat{x}(t)$ は $x(t)$ のヒルベルト変換です。上側帯波(USB)のみの場合は $-$、下側帯波(LSB)のみの場合は $+$ を取ります。

長所: 占有帯域幅が $W$(AMの半分)、電力効率が高い

短所: 実装が複雑(ヒルベルト変換が必要)、位相同期が厳しい

VSB(Vestigial Side Band)

SSBの実装困難性を緩和するため、一方の側帯波のごく一部(残留側帯波)を残す方式です。アナログテレビ放送で使用されていました。

方式比較表

方式 搬送波 帯域幅 電力効率 復調
AM (DSB-FC) あり $2W$ $m^2/(2+m^2)$ 包絡線検波(簡単)
DSB-SC なし $2W$ 100% 同期検波(要同期)
SSB なし $W$ 100% 同期検波
VSB なし $W + f_v$ 高い 同期検波

包絡線検波の原理

包絡線検波とは

包絡線検波(Envelope Detection)は、AM信号の包絡線を抽出することで元のベースバンド信号を復元する最も簡単な復調方式です。ダイオードとRC回路で実現できます。

数学的導出

AM信号 $s(t) = A_c[1 + m \cdot x(t)]\cos(2\pi f_c t)$ の包絡線は、

$$ e(t) = \left| A_c[1 + m \cdot x(t)] \right| $$

$m \leq 1$(過変調なし)のとき、$1 + m \cdot x(t) \geq 0$ が保証されるので、

$$ e(t) = A_c[1 + m \cdot x(t)] = A_c + m A_c \, x(t) $$

DC成分 $A_c$ をキャパシタで除去すると、

$$ e_{\text{AC}}(t) = m A_c \, x(t) $$

これは元のベースバンド信号 $x(t)$ にスケール係数 $mA_c$ がかかったものです。したがって、包絡線検波により元の信号を忠実に復元できます。

包絡線検波の条件

包絡線検波が正しく動作するための条件は2つあります。

条件1: 過変調でないこと

$$ m \leq 1 \quad \Longleftrightarrow \quad 1 + m \cdot x(t) \geq 0 \quad \forall t $$

条件2: RC時定数の適切な設定

RC回路の時定数 $\tau = RC$ は以下を満たす必要があります。

$$ \frac{1}{f_c} \ll \tau \ll \frac{1}{W} $$

左の不等式は搬送波の高周波成分を除去するため、右の不等式は信号の変動に追従するためです。

同期検波の原理

同期検波とは

同期検波(Coherent Detection / Synchronous Detection)は、受信側で搬送波と同じ周波数・位相の局部発振器を用いて復調する方式です。DSB-SCやSSBの復調に必要ですが、通常のAM信号にも適用できます。

数学的導出

受信信号 $s(t)$ に局部発振信号 $\cos(2\pi f_c t)$ を掛けます。

$$ s(t) \cos(2\pi f_c t) = A_c[1 + m \cdot x(t)] \cos^2(2\pi f_c t) $$

倍角の公式 $\cos^2\theta = \frac{1 + \cos 2\theta}{2}$ を適用すると、

$$ = \frac{A_c}{2}[1 + m \cdot x(t)] + \frac{A_c}{2}[1 + m \cdot x(t)]\cos(4\pi f_c t) $$

第1項がベースバンド信号、第2項は $2f_c$ の高周波成分です。ローパスフィルタ(LPF)で第2項を除去すると、

$$ y(t) = \frac{A_c}{2}[1 + m \cdot x(t)] $$

DC成分を除去して、

$$ y_{\text{AC}}(t) = \frac{mA_c}{2} x(t) $$

元のベースバンド信号が復元されました。

位相誤差の影響

局部発振器に位相誤差 $\phi$ がある場合、$\cos(2\pi f_c t + \phi)$ を掛けることになります。

$$ y(t) = \frac{A_c}{2}[1 + m \cdot x(t)] \cos\phi $$

出力は $\cos\phi$ だけ減衰します。$\phi = 90°$ のとき出力はゼロになるため、位相同期が重要です。

Pythonでの実装

AM変調信号の生成とスペクトル表示

import numpy as np
import matplotlib.pyplot as plt

# パラメータ設定
fs = 100000         # サンプリング周波数 [Hz]
T = 0.1             # 信号長 [s]
t = np.arange(0, T, 1/fs)
fc = 10000          # 搬送波周波数 [Hz]
fm = 500            # 信号周波数 [Hz]
Ac = 1.0            # 搬送波振幅

# ベースバンド信号(正弦波)
x = np.cos(2 * np.pi * fm * t)

# 搬送波
carrier = np.cos(2 * np.pi * fc * t)

# 各変調度でのAM信号
m_list = [0.3, 0.7, 1.0, 1.5]

fig, axes = plt.subplots(len(m_list), 2, figsize=(16, 14))

for i, m in enumerate(m_list):
    # AM変調信号
    s_am = Ac * (1 + m * x) * carrier

    # 包絡線
    envelope_upper = Ac * (1 + m * x)
    envelope_lower = -Ac * (1 + m * x)

    # 時間波形
    axes[i, 0].plot(t * 1000, s_am, 'b-', linewidth=0.5, alpha=0.7)
    axes[i, 0].plot(t * 1000, envelope_upper, 'r--', linewidth=1.5,
                    label='Envelope')
    axes[i, 0].plot(t * 1000, envelope_lower, 'r--', linewidth=1.5)
    axes[i, 0].set_xlabel('Time [ms]')
    axes[i, 0].set_ylabel('Amplitude')
    axes[i, 0].set_title(f'AM Signal (m = {m})')
    axes[i, 0].set_xlim(0, 10)
    axes[i, 0].legend(loc='upper right')
    axes[i, 0].grid(True, alpha=0.3)

    if m > 1.0:
        axes[i, 0].set_title(f'AM Signal (m = {m}, Over-modulation!)',
                              color='red')

    # スペクトル
    N_fft = len(t)
    freq = np.fft.fftfreq(N_fft, 1/fs)
    S = np.abs(np.fft.fft(s_am)) / N_fft
    pos_mask = freq >= 0

    axes[i, 1].plot(freq[pos_mask] / 1000, 2 * S[pos_mask], 'b-',
                    linewidth=1)
    axes[i, 1].set_xlabel('Frequency [kHz]')
    axes[i, 1].set_ylabel('Magnitude')
    axes[i, 1].set_title(f'Spectrum (m = {m})')
    axes[i, 1].set_xlim(8, 12)
    axes[i, 1].grid(True, alpha=0.3)

    # 搬送波・USB・LSBの位置を注釈
    axes[i, 1].axvline(x=fc/1000, color='r', linestyle=':', alpha=0.5)
    axes[i, 1].axvline(x=(fc+fm)/1000, color='g', linestyle=':',
                        alpha=0.5)
    axes[i, 1].axvline(x=(fc-fm)/1000, color='g', linestyle=':',
                        alpha=0.5)

plt.tight_layout()
plt.show()

変調度 $m$ を大きくすると側帯波の振幅が増加し、$m > 1$ では包絡線が負になって歪みが生じることがわかります。

電力効率の計算

import numpy as np
import matplotlib.pyplot as plt

# 変調度と電力効率の関係
m_range = np.linspace(0, 1, 100)
eta = m_range**2 / (2 + m_range**2)

fig, ax = plt.subplots(figsize=(10, 6))

ax.plot(m_range, eta * 100, 'b-', linewidth=2)
ax.set_xlabel('Modulation Index m')
ax.set_ylabel('Power Efficiency η [%]')
ax.set_title('AM Power Efficiency vs Modulation Index')
ax.grid(True, alpha=0.3)

# 特定の点を注釈
for m_val in [0.3, 0.5, 0.7, 1.0]:
    eta_val = m_val**2 / (2 + m_val**2) * 100
    ax.plot(m_val, eta_val, 'ro', markersize=8)
    ax.annotate(f'm={m_val}: η={eta_val:.1f}%',
                xy=(m_val, eta_val),
                xytext=(m_val + 0.05, eta_val + 2),
                fontsize=10, color='red')

ax.set_xlim(0, 1.05)
ax.set_ylim(0, 40)
plt.tight_layout()
plt.show()

# 数値確認
print("=== AM変調の電力効率 ===")
for m_val in [0.3, 0.5, 0.7, 1.0]:
    eta_val = m_val**2 / (2 + m_val**2) * 100
    print(f"  m = {m_val:.1f}: η = {eta_val:.2f}%")

包絡線検波シミュレーション

import numpy as np
import matplotlib.pyplot as plt

# パラメータ
fs = 200000
T = 0.05
t = np.arange(0, T, 1/fs)
fc = 20000
Ac = 1.0
m = 0.8

# 複合ベースバンド信号
x = 0.6 * np.cos(2 * np.pi * 300 * t) + 0.4 * np.cos(2 * np.pi * 800 * t)
x = x / np.max(np.abs(x))  # 正規化

# AM変調
s_am = Ac * (1 + m * x) * np.cos(2 * np.pi * fc * t)

# 雑音付加(SNR = 20 dB)
snr_dB = 20
signal_power = np.mean(s_am**2)
noise_power = signal_power / (10**(snr_dB/10))
noise = np.sqrt(noise_power) * np.random.randn(len(t))
s_noisy = s_am + noise

# --- 包絡線検波(ヒルベルト変換を使用) ---
from scipy.signal import hilbert
analytic_signal = hilbert(s_noisy)
envelope = np.abs(analytic_signal)

# DCブロック(ハイパスフィルタ代用: 平均値を引く)
envelope_ac = envelope - np.mean(envelope)

# --- 同期検波 ---
# 局部発振器
lo = np.cos(2 * np.pi * fc * t)
demod_sync = s_noisy * lo * 2  # 2倍は振幅補正

# ローパスフィルタ
from scipy.signal import butter, filtfilt
b, a = butter(5, 2000 / (fs/2), btype='low')
demod_sync_filtered = filtfilt(b, a, demod_sync)
demod_sync_ac = demod_sync_filtered - np.mean(demod_sync_filtered)

# 可視化
fig, axes = plt.subplots(4, 1, figsize=(14, 14))

# 元の信号
axes[0].plot(t * 1000, x, 'b-', linewidth=1.5)
axes[0].set_xlabel('Time [ms]')
axes[0].set_ylabel('Amplitude')
axes[0].set_title('Original Baseband Signal x(t)')
axes[0].set_xlim(0, 20)
axes[0].grid(True, alpha=0.3)

# AM変調信号(雑音付き)
axes[1].plot(t * 1000, s_noisy, 'b-', linewidth=0.3, alpha=0.5)
axes[1].plot(t * 1000, Ac * (1 + m * x), 'r-', linewidth=1.5,
             label='True Envelope')
axes[1].set_xlabel('Time [ms]')
axes[1].set_ylabel('Amplitude')
axes[1].set_title(f'Noisy AM Signal (SNR = {snr_dB} dB)')
axes[1].set_xlim(0, 20)
axes[1].legend()
axes[1].grid(True, alpha=0.3)

# 包絡線検波結果
scale_env = m * Ac
axes[2].plot(t * 1000, m * x, 'b-', linewidth=1.5, label='Original (scaled)')
axes[2].plot(t * 1000, envelope_ac / Ac, 'r-', linewidth=1.5, alpha=0.7,
             label='Envelope Detection')
axes[2].set_xlabel('Time [ms]')
axes[2].set_ylabel('Amplitude')
axes[2].set_title('Envelope Detection Result')
axes[2].set_xlim(0, 20)
axes[2].legend()
axes[2].grid(True, alpha=0.3)

# 同期検波結果
axes[3].plot(t * 1000, m * x, 'b-', linewidth=1.5, label='Original (scaled)')
axes[3].plot(t * 1000, demod_sync_ac / Ac, 'g-', linewidth=1.5, alpha=0.7,
             label='Synchronous Detection')
axes[3].set_xlabel('Time [ms]')
axes[3].set_ylabel('Amplitude')
axes[3].set_title('Synchronous Detection Result')
axes[3].set_xlim(0, 20)
axes[3].legend()
axes[3].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

包絡線検波と同期検波の両方で元のベースバンド信号が復元されていることがわかります。雑音環境下でも比較的良好に動作しますが、同期検波のほうが雑音耐性に優れています。

DSB-SCとSSBの比較

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import hilbert

# パラメータ
fs = 100000
T = 0.05
t = np.arange(0, T, 1/fs)
fc = 10000
Ac = 1.0

# ベースバンド信号
fm1, fm2 = 400, 900
x = 0.7 * np.cos(2 * np.pi * fm1 * t) + 0.3 * np.cos(2 * np.pi * fm2 * t)

# AM (DSB-FC)
m = 0.8
s_am = Ac * (1 + m * x) * np.cos(2 * np.pi * fc * t)

# DSB-SC
s_dsb = Ac * x * np.cos(2 * np.pi * fc * t)

# SSB (USB) — ヒルベルト変換を使用
x_hat = np.imag(hilbert(x))  # x(t)のヒルベルト変換
s_ssb = 0.5 * Ac * (x * np.cos(2 * np.pi * fc * t)
                     - x_hat * np.sin(2 * np.pi * fc * t))

# スペクトル計算
def compute_spectrum(signal, fs):
    N_fft = len(signal)
    freq = np.fft.fftfreq(N_fft, 1/fs)
    S = np.abs(np.fft.fft(signal)) / N_fft
    pos = freq >= 0
    return freq[pos], 2 * S[pos]

fig, axes = plt.subplots(3, 2, figsize=(16, 12))

signals = [('AM (DSB-FC)', s_am), ('DSB-SC', s_dsb), ('SSB (USB)', s_ssb)]

for i, (name, s) in enumerate(signals):
    # 時間波形
    axes[i, 0].plot(t * 1000, s, 'b-', linewidth=0.5)
    axes[i, 0].set_xlabel('Time [ms]')
    axes[i, 0].set_ylabel('Amplitude')
    axes[i, 0].set_title(f'{name} - Time Domain')
    axes[i, 0].set_xlim(0, 10)
    axes[i, 0].grid(True, alpha=0.3)

    # スペクトル
    f, S_mag = compute_spectrum(s, fs)
    axes[i, 1].plot(f / 1000, S_mag, 'b-', linewidth=1)
    axes[i, 1].set_xlabel('Frequency [kHz]')
    axes[i, 1].set_ylabel('Magnitude')
    axes[i, 1].set_title(f'{name} - Spectrum')
    axes[i, 1].set_xlim(8, 12)
    axes[i, 1].grid(True, alpha=0.3)

    # 搬送波位置
    axes[i, 1].axvline(x=fc/1000, color='r', linestyle=':', alpha=0.5)

plt.tight_layout()
plt.show()

# 電力比較
powers = {}
for name, s in signals:
    powers[name] = np.mean(s**2)

print("=== 各方式の平均電力 ===")
for name, p in powers.items():
    print(f"  {name}: {p:.4f}")

AM(DSB-FC)では搬送波のスペクトルが大きく立っていますが、DSB-SCでは搬送波成分がなく、SSBでは片方の側帯波のみになっていることが確認できます。

まとめ

本記事では、AM変調の理論と数学的導出について解説しました。

  • AM変調信号は $s(t) = A_c[1 + m \cdot x(t)]\cos(2\pi f_c t)$ で表される
  • スペクトルは搬送波成分と上下側帯波の3つの成分からなる
  • 電力効率は $\eta = m^2/(2 + m^2)$ であり、最大でも約33%と低い
  • DSB-SCは搬送波を除去して電力効率を改善し、SSBはさらに帯域幅も半減する
  • 包絡線検波は最も簡単な復調方式だが、過変調では動作しない
  • 同期検波は位相同期が必要だが、DSB-SCやSSBの復調にも対応でき雑音耐性が高い

次のステップとして、以下の記事も参考にしてください。