SSBとDSB — AM変調の帯域効率を改善する方式

ラジオ放送やアマチュア無線では「AM」という言葉をよく耳にします。しかし、ひとくちにAM変調といっても、実際には複数のバリエーションがあることをご存知でしょうか? 標準的なAM(DSB-FC)では、送信電力の大部分が情報を含まない搬送波に費やされ、しかも同じ情報が上側波帯と下側波帯の両方に重複して載っています。これは、限られた周波数帯域と送信電力を使う無線通信にとって大きな無駄です。

この「無駄」を体系的に削減していく方式が、DSB-SC(Double Sideband Suppressed Carrier:搬送波抑圧両側波帯)SSB(Single Sideband:単側波帯) です。DSB-SCは搬送波を取り除いて電力効率を改善し、SSBはさらに片側の側波帯も除去して帯域効率を2倍に高めます。

これらの方式を理解すると、次のような応用に直結します:

  • アマチュア無線(HF帯): SSBは事実上の標準方式であり、長距離通信の効率を支えています
  • 航空無線・海上通信: 限られた帯域と電力の中で確実な音声通信を実現するためにSSBが用いられます
  • ディジタル通信の基盤: QAM(直交振幅変調)はDSB-SCの直交多重であり、Wi-FiやLTEの変調方式の基礎となっています

本記事の内容

  • DSB-SC変調の原理と同期検波による復調
  • SSBの必要性と2つの生成法(フィルタ法・位相法)
  • VSB(残留側波帯)の概念と用途
  • 帯域幅・電力効率の定量比較
  • Pythonによる時間波形とスペクトルの比較シミュレーション

前提知識

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

標準AM(DSB-FC)の復習 — 何が無駄なのか

SSBやDSB-SCの意義を理解するには、まず標準的なAM変調(DSB-FC: Double Sideband Full Carrier)の構造を押さえ、「何が無駄なのか」を明確にする必要があります。

標準AMでは、メッセージ信号 $m(t)$ を搬送波 $\cos(2\pi f_c t)$ に乗せるとき、次のように送信信号を生成します:

$$ s_{\text{AM}}(t) = A_c \bigl[1 + k_a m(t)\bigr] \cos(2\pi f_c t) $$

ここで $A_c$ は搬送波振幅、$k_a$ は変調感度(変調指数を制御するパラメータ)です。この式を展開すると:

$$ s_{\text{AM}}(t) = A_c \cos(2\pi f_c t) + A_c k_a m(t) \cos(2\pi f_c t) $$

第1項 $A_c \cos(2\pi f_c t)$ は搬送波そのもので、メッセージ情報を一切含みません。第2項がメッセージ情報を運ぶ成分です。

周波数領域での構造

フーリエ変換の変調定理(周波数シフト性質)を使うと、$m(t) \cos(2\pi f_c t)$ のスペクトルは $M(f)$ を $\pm f_c$ だけシフトしたものになります:

$$ \mathcal{F}\bigl[m(t)\cos(2\pi f_c t)\bigr] = \frac{1}{2}\bigl[M(f – f_c) + M(f + f_c)\bigr] $$

したがって、標準AM信号のスペクトルには次の3つの成分が現れます:

  1. 搬送波: $f = \pm f_c$ にデルタ関数(パワーを消費するが情報なし)
  2. 上側波帯(USB): $f_c$ より高い周波数帯に $M(f)$ のコピー
  3. 下側波帯(LSB): $f_c$ より低い周波数帯に $M(f)$ のコピー

USBとLSBは $M(f)$ の鏡像関係にあり、全く同じ情報を運んでいます。つまり、標準AMには2つの無駄があります:

無駄の種類 内容 影響
搬送波の送信 情報を含まない搬送波に電力の50%以上が使われる 電力効率が低い
両側波帯の送信 同じ情報が2回送られる 帯域効率が低い(帯域幅 = 2W)

この2つの無駄を段階的に解消していくのが、これから解説するDSB-SCとSSBです。まず、搬送波の無駄を取り除くDSB-SCから見ていきましょう。

DSB-SC(搬送波抑圧両側波帯)の原理

直感的な理解

DSB-SCのアイデアはシンプルです。標準AMの式 $s_{\text{AM}}(t) = A_c[1 + k_a m(t)]\cos(2\pi f_c t)$ で、搬送波成分 $A_c\cos(2\pi f_c t)$ は情報を運ばないのに電力を消費しています。ならば、搬送波を送らず、情報成分だけを送ればよいのです。

数学的定義

DSB-SC信号は、メッセージ信号と搬送波の単純な積として定義されます:

$$ \begin{equation} s_{\text{DSB}}(t) = m(t) \cos(2\pi f_c t) \end{equation} $$

標準AMの式から定数項($1$ の部分)を取り除いただけです。これにより搬送波成分が消え、送信電力のすべてが情報伝送に使われます。

周波数スペクトル

先ほどの変調定理をそのまま適用すると:

$$ S_{\text{DSB}}(f) = \frac{1}{2}\bigl[M(f – f_c) + M(f + f_c)\bigr] $$

搬送波周波数 $f_c$ にデルタ関数は現れず、メッセージスペクトル $M(f)$ が $\pm f_c$ にシフトされた成分だけが残ります。帯域幅は標準AMと同じ $2W$($W$ はメッセージ信号の帯域幅)ですが、搬送波に使われていた電力がなくなった分、電力効率は大幅に向上します。

電力効率の比較

標準AMで変調度 $k_a \cdot \max|m(t)| = \mu$ のとき、メッセージ成分に使われる電力の割合は:

$$ \eta_{\text{AM}} = \frac{\mu^2 / 2}{1 + \mu^2 / 2} $$

$\mu = 1$(100%変調)でも $\eta_{\text{AM}} = 1/3 \approx 33\%$ に過ぎません。残りの67%は搬送波に費やされます。

一方、DSB-SCでは搬送波がないため:

$$ \eta_{\text{DSB-SC}} = 1 \quad (100\%) $$

送信電力のすべてが情報伝送に使われます。これは大きな改善です。

しかし、この効率の良さにはトレードオフがあります。搬送波を送らないということは、受信側で搬送波を復元する必要があるということです。次に、この復調方法を見ていきましょう。

DSB-SCの復調 — 同期検波

なぜ包絡線検波が使えないのか

標準AMでは、$1 + k_a m(t) \geq 0$(過変調でない場合)のとき、信号の包絡線が $A_c[1 + k_a m(t)]$ となり、ダイオードと簡単なRC回路でメッセージを取り出せます。しかしDSB-SCの信号 $m(t)\cos(2\pi f_c t)$ では、$m(t)$ が負になると信号の位相が $\pi$ だけ反転します。包絡線は $|m(t)|$ となり、元のメッセージとは異なります。

たとえば、$m(t) = \cos(2\pi f_m t)$ のような正弦波メッセージの場合、DSB-SC信号の包絡線は $|\cos(2\pi f_m t)|$ になります。これは元の信号を全波整流したような波形であり、正しい復調にはなりません。

同期検波(コヒーレント検波)の原理

DSB-SCの復調には、受信側で搬送波と位相が同期した局部発振器(ローカルオシレータ)を用意し、受信信号に掛け算する同期検波が必要です。

受信信号 $r(t) = s_{\text{DSB}}(t) = m(t)\cos(2\pi f_c t)$ に、局部発振器の信号 $\cos(2\pi f_c t + \phi)$ を掛けます:

$$ v(t) = r(t) \cdot \cos(2\pi f_c t + \phi) $$

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

$$ v(t) = \frac{1}{2}m(t)\cos(\phi) + \frac{1}{2}m(t)\cos(4\pi f_c t + \phi) $$

第2項は搬送波周波数の2倍の高周波成分であり、ローパスフィルタ(LPF)で除去できます。LPF通過後の出力は:

$$ y(t) = \frac{1}{2}m(t)\cos(\phi) $$

位相誤差 $\phi = 0$ のとき(完全同期のとき):

$$ y(t) = \frac{1}{2}m(t) $$

元のメッセージ信号が定数倍で復元されます。

位相誤差の影響

上の式から明らかなように、出力は $\cos(\phi)$ に比例します。位相誤差の影響を整理すると:

位相誤差 $\phi$ $\cos(\phi)$ 影響
$0°$ $1$ 完全復調
$30°$ $0.866$ 振幅が13%低下
$45°$ $0.707$ 振幅が29%低下
$90°$ $0$ 出力ゼロ(完全消失)

$\phi = 90°$ のとき出力がゼロになることは特に重要で、これを直交ヌル(quadrature null) と呼びます。このことは後で見るQAM(直交振幅変調)の原理にも関わってきます。

位相同期の必要性が、DSB-SCの主な実装上の課題です。実際の受信機では、PLL(位相同期ループ)やコスタスループなどの搬送波再生回路が必要になります。

ここまでで、DSB-SCが搬送波を除去して電力効率を改善することを見てきました。しかし、帯域幅は依然として $2W$ のままです。メッセージ帯域幅 $W$ に対して2倍の帯域を占有する — この「もう一つの無駄」を解消するのがSSBです。

SSB(単側波帯)変調の原理

なぜ片方の側波帯だけでよいのか

DSB-SCのスペクトルは搬送波周波数 $f_c$ に対して対称です。つまり、上側波帯(USB: Upper Sideband)と下側波帯(LSB: Lower Sideband)は互いに鏡像であり、全く同じ情報を運んでいます。

実数信号 $m(t)$ のフーリエ変換 $M(f)$ は、$M(-f) = M^*(f)$ という共役対称性を持ちます。この対称性のため、USBの成分 $M(f – f_c)$($f > f_c$ の部分)を知れば、LSBの成分 $M(f + f_c)$($f < -f_c$ の対応部分)は自動的に決まります。

したがって、片方の側波帯だけを送信しても情報は失われません。これがSSBの基本的な発想です。SSBでは帯域幅が $W$ に半減し、帯域効率が2倍になります。

SSB信号の数学的表現

SSBの数学的定義にはヒルベルト変換が不可欠です。メッセージ信号 $m(t)$ のヒルベルト変換 $\hat{m}(t)$ は、$m(t)$ の全ての周波数成分の位相を $-90°$ 回転させたものです:

$$ \begin{equation} \hat{m}(t) = \mathcal{H}\{m(t)\} = \frac{1}{\pi} \text{p.v.} \int_{-\infty}^{\infty} \frac{m(\tau)}{t – \tau} d\tau \end{equation} $$

ここで p.v. はコーシーの主値積分を表します。ヒルベルト変換の周波数領域での効果は明快で、伝達関数は:

$$ H_{\text{HT}}(f) = -j \operatorname{sgn}(f) = \begin{cases} -j & (f > 0) \\ j & (f < 0) \end{cases} $$

すなわち、正の周波数成分の位相を $-90°$、負の周波数成分の位相を $+90°$ 回転させます。振幅スペクトルは変わりません。

SSB信号は次のように表されます:

$$ \begin{equation} s_{\text{SSB}}(t) = m(t)\cos(2\pi f_c t) \mp \hat{m}(t)\sin(2\pi f_c t) \end{equation} $$

ここで、$-$ を取るとUSB(上側波帯)、$+$ を取るとLSB(下側波帯)になります。

なぜこの式で片方の側波帯が消えるのかを理解するために、スペクトルを確認しましょう。$m(t)\cos(2\pi f_c t)$ のスペクトルは $\frac{1}{2}[M(f-f_c) + M(f+f_c)]$ です。一方、$\hat{m}(t)\sin(2\pi f_c t)$ のスペクトルは:

$$ \mathcal{F}[\hat{m}(t)\sin(2\pi f_c t)] = \frac{1}{2j}\bigl[\hat{M}(f-f_c) – \hat{M}(f+f_c)\bigr] $$

$\hat{M}(f) = -j\operatorname{sgn}(f) \cdot M(f)$ を代入すると、USBの場合($-$ 符号)、$f > f_c$ の成分は保存され、$0 < f < f_c$ の成分(元のLSBに対応)は打ち消し合って消えます。

この数学的導出は少し煩雑ですが、結論は明快です: ヒルベルト変換を使って適切な位相関係を作ることで、片方の側波帯を正確にキャンセルできるのです。

ここまでSSBの数学的表現を見てきました。では、実際にSSB信号を生成するにはどうすればよいのでしょうか? 2つの代表的な方法を見ていきましょう。

SSBの生成法

フィルタ法

最も直感的な方法は、まずDSB-SC信号を生成し、そこから不要な側波帯をフィルタで除去するアプローチです。

手順:

  1. メッセージ信号 $m(t)$ と搬送波 $\cos(2\pi f_c t)$ を乗算して DSB-SC 信号を生成
  2. 帯域通過フィルタ(BPF)でUSBまたはLSBのみを通過させる

長所: 原理が単純で理解しやすい

短所: 側波帯間の境界(搬送波周波数付近)でフィルタの遷移帯域が問題になります。音声信号のように低域に成分があるメッセージでは、USBとLSBが搬送波周波数付近で非常に接近しており、急峻なカットオフ特性を持つフィルタが必要です。

実用的には、搬送波周波数 $f_c$ をあえて低い中間周波数(IF)に設定して、そこでSSBフィルタリングを行い、その後に目的の送信周波数へアップコンバートする方法が取られます。水晶フィルタやセラミックフィルタが用いられ、IF段階では比較的急峻な特性が実現できます。

位相法(ヒルベルト変換法)

フィルタ法の「急峻なフィルタが必要」という課題を回避するのが位相法です。SSB信号の式:

$$ s_{\text{SSB}}(t) = m(t)\cos(2\pi f_c t) \mp \hat{m}(t)\sin(2\pi f_c t) $$

を直接実装します。

手順:

  1. メッセージ信号 $m(t)$ を2つに分岐
  2. 一方はそのまま $\cos(2\pi f_c t)$ と乗算
  3. 他方はヒルベルト変換器(全域で $90°$ の位相シフトを与える回路)を通してから $\sin(2\pi f_c t)$ と乗算
  4. 2つの出力を加算(USB)または減算(LSB)

長所: フィルタに依存しないため、任意の搬送波周波数でSSBを生成できる

短所: 広帯域にわたって正確に $90°$ の位相シフトを実現するヒルベルト変換器の実装が難しい。アナログ回路では完全なヒルベルト変換は不可能で、近似回路(ポリフェーズフィルタなど)が使われます。

ディジタル信号処理では、FIRフィルタやFFTを使ってヒルベルト変換を高精度に実装できるため、位相法がソフトウェア無線(SDR)で広く使われています。

ウィーバー法(第3の方法)

フィルタ法と位相法のハイブリッドとして、ウィーバー法(Weaver method) もあります。メッセージ信号を帯域の中心周波数 $f_m/2$ でベースバンドに落とし、ローパスフィルタで片側を除去してから搬送波周波数にアップコンバートします。急峻なBPFもワイドバンドの位相シフタも不要で、ローパスフィルタだけでSSBを生成できる優れた方式です。

2つの主要なSSB生成法を理解したところで、次にSSBと標準AMの中間に位置するVSBについて触れておきましょう。

VSB(残留側波帯)変調

SSBの実用上の課題

SSBは帯域効率に優れていますが、実用上の問題があります。メッセージ信号に直流(DC)成分や非常に低い周波数成分が含まれる場合、USBとLSBが搬送波周波数付近で重なり合い、フィルタ法でもきれいに分離できません。

テレビ映像信号がまさにこのケースです。映像信号は直流成分(画面の平均輝度)から数MHzまでの広い帯域を占め、低域成分が豊富です。SSBを適用しようとすると、搬送波近傍の低域成分が失われ、画質が劣化します。

VSBのアイデア

VSB(Vestigial Sideband: 残留側波帯) は、片方の側波帯を完全には除去せず、搬送波近傍の「残留(vestige)」だけを残す方式です:

  • 片方の側波帯は全て送信(例えばUSB全体)
  • もう片方の側波帯は大部分をカットするが、搬送波近傍の低周波成分だけは残す

これにより:

  1. 帯域幅は $W < B_{\text{VSB}} < 2W$ となり、DSBよりは狭い
  2. フィルタの遷移帯域に余裕ができ、急峻なフィルタが不要
  3. 低域成分が保存されるため、DC成分を含む信号にも対応可能

VSBフィルタの条件

VSBが正しく復調されるためには、VSBフィルタ $H(f)$ が搬送波周波数 $f_c$ を中心として次の対称条件(vestigial symmetry condition) を満たす必要があります:

$$ \begin{equation} H(f – f_c) + H(-f – f_c) = \text{const}, \quad |f| \leq W \end{equation} $$

この条件は、「上側波帯で削られた分と下側波帯で残された分を足すと一定になる」ことを要求しています。これにより、復調後にフラットなメッセージスペクトルが復元されます。

各方式の帯域幅比較

ここまでに登場した各AM変調方式の帯域幅を整理しましょう。メッセージ信号の帯域幅を $W$ とすると:

方式 帯域幅 搬送波 電力効率 復調方式
DSB-FC(標準AM) $2W$ あり 低い($\leq 33\%$) 包絡線検波
DSB-SC $2W$ なし 高い(100%) 同期検波
SSB $W$ なし 高い(100%) 同期検波
VSB $W + f_v$ あり/なし 中〜高 同期検波/包絡線

ここで $f_v$ はVSBの残留帯域幅です。

各方式の特徴と使い分けが整理できたところで、いよいよPythonで各方式の信号を実際に生成し、時間波形とスペクトルを視覚的に比較してみましょう。

Pythonでの実装: DSB-SC・SSBの時間波形とスペクトル比較

まず、DSB-FCとDSB-SCの信号を生成し、時間波形とスペクトルの違いを確認します。

import numpy as np
import matplotlib.pyplot as plt

# パラメータ設定
fs = 10000        # サンプリング周波数 [Hz]
T = 0.5           # 信号長 [s]
t = np.arange(0, T, 1/fs)
fm = 20           # メッセージ周波数 [Hz]
fc = 200          # 搬送波周波数 [Hz]
mu = 0.8          # 変調度

# メッセージ信号(単一正弦波)
m = np.cos(2 * np.pi * fm * t)

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

# 標準AM(DSB-FC)
s_am = (1 + mu * m) * carrier

# DSB-SC
s_dsb = m * carrier

# 時間波形の比較
fig, axes = plt.subplots(3, 1, figsize=(12, 8), sharex=True)

axes[0].plot(t[:1000], m[:1000], 'b-', linewidth=1.5)
axes[0].set_ylabel('Amplitude')
axes[0].set_title('Message signal m(t)')
axes[0].grid(True, alpha=0.3)

axes[1].plot(t[:1000], s_am[:1000], 'g-', linewidth=0.8, label='DSB-FC (AM)')
axes[1].plot(t[:1000], 1 + mu * m[:1000], 'r--', linewidth=1.5, label='Envelope')
axes[1].plot(t[:1000], -(1 + mu * m[:1000]), 'r--', linewidth=1.5)
axes[1].set_ylabel('Amplitude')
axes[1].set_title('Standard AM (DSB-FC)')
axes[1].legend(loc='upper right')
axes[1].grid(True, alpha=0.3)

axes[2].plot(t[:1000], s_dsb[:1000], 'm-', linewidth=0.8, label='DSB-SC')
axes[2].plot(t[:1000], m[:1000], 'r--', linewidth=1.5, label='|m(t)| envelope')
axes[2].plot(t[:1000], -m[:1000], 'r--', linewidth=1.5)
axes[2].set_ylabel('Amplitude')
axes[2].set_title('DSB-SC')
axes[2].set_xlabel('Time [s]')
axes[2].legend(loc='upper right')
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('am_dsbsc_time.png', dpi=150, bbox_inches='tight')
plt.show()

上のグラフから、3つの重要な違いが読み取れます:

  1. 標準AMの包絡線は常に正 — $1 + \mu m(t)$ は $\mu < 1$ のとき常に正であり、包絡線がメッセージ波形の形を保っています。これがダイオード検波で復調できる理由です。
  2. DSB-SCでは位相反転が起こる — $m(t)$ が負になるとき、DSB-SC信号の搬送波位相が $180°$ 反転します。これが包絡線検波では正しく復調できない原因です。
  3. DSB-SCは搬送波成分がない — 標準AMと比べて、DSB-SCのピーク振幅は小さく、送信電力が効率的に使われていることが視覚的にもわかります。

次に、周波数スペクトルを比較してDSB-SCとSSBの帯域幅の違いを確認しましょう。

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

# パラメータ設定
fs = 10000
T = 1.0
t = np.arange(0, T, 1/fs)
fc = 500

# 複合メッセージ信号(複数周波数を含む)
m = np.cos(2 * np.pi * 30 * t) + 0.5 * np.cos(2 * np.pi * 60 * t) + 0.3 * np.cos(2 * np.pi * 90 * t)

# 搬送波
carrier_cos = np.cos(2 * np.pi * fc * t)
carrier_sin = np.sin(2 * np.pi * fc * t)

# DSB-SC
s_dsb = m * carrier_cos

# SSB-USB(ヒルベルト変換を使用)
m_hilbert = np.imag(hilbert(m))  # ヒルベルト変換
s_ssb_usb = m * carrier_cos - m_hilbert * carrier_sin

# SSB-LSB
s_ssb_lsb = m * carrier_cos + m_hilbert * carrier_sin

# スペクトル計算
def compute_spectrum(signal, fs):
    N = len(signal)
    freqs = np.fft.fftfreq(N, 1/fs)
    spectrum = np.fft.fft(signal) / N
    # 正の周波数のみ
    pos_mask = freqs >= 0
    return freqs[pos_mask], 2 * np.abs(spectrum[pos_mask])

f_dsb, S_dsb = compute_spectrum(s_dsb, fs)
f_usb, S_usb = compute_spectrum(s_ssb_usb, fs)
f_lsb, S_lsb = compute_spectrum(s_ssb_lsb, fs)

# スペクトル比較プロット
fig, axes = plt.subplots(3, 1, figsize=(12, 9))

axes[0].plot(f_dsb, S_dsb, 'b-', linewidth=1)
axes[0].set_xlim([300, 700])
axes[0].set_ylabel('|S(f)|')
axes[0].set_title('DSB-SC Spectrum')
axes[0].axvline(x=fc, color='r', linestyle='--', alpha=0.5, label=f'fc = {fc} Hz')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

axes[1].plot(f_usb, S_usb, 'g-', linewidth=1)
axes[1].set_xlim([300, 700])
axes[1].set_ylabel('|S(f)|')
axes[1].set_title('SSB-USB Spectrum')
axes[1].axvline(x=fc, color='r', linestyle='--', alpha=0.5, label=f'fc = {fc} Hz')
axes[1].legend()
axes[1].grid(True, alpha=0.3)

axes[2].plot(f_lsb, S_lsb, 'm-', linewidth=1)
axes[2].set_xlim([300, 700])
axes[2].set_ylabel('|S(f)|')
axes[2].set_title('SSB-LSB Spectrum')
axes[2].set_xlabel('Frequency [Hz]')
axes[2].axvline(x=fc, color='r', linestyle='--', alpha=0.5, label=f'fc = {fc} Hz')
axes[2].legend()
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('dsb_ssb_spectrum.png', dpi=150, bbox_inches='tight')
plt.show()

このスペクトル比較から、SSBの核心的な特徴が明確に確認できます:

  1. DSB-SCは搬送波の両側に対称なスペクトルを持つ — 30Hz, 60Hz, 90Hzのメッセージ成分が、$f_c = 500$ Hzの上下にそれぞれ現れます(470, 440, 410 Hz と 530, 560, 590 Hz)。占有帯域幅は $2 \times 90 = 180$ Hzです。
  2. SSB-USBは上側波帯のみ — 530, 560, 590 Hzにだけスペクトルが現れ、500 Hz以下の成分はほぼゼロです。占有帯域幅は90 Hzに半減しています。
  3. SSB-LSBは下側波帯のみ — 470, 440, 410 Hzにだけスペクトルが現れ、USB と鏡像関係にあります。

DSB-SCからSSBへの変更で帯域幅が半分になることが、スペクトル上で直接確認できました。続いて、ヒルベルト変換によるSSB生成の詳細をコードで確認しましょう。

ヒルベルト変換によるSSB生成の詳細

先ほどのコードではSciPyの hilbert() 関数を使いましたが、その内部で何が起きているかを理解しておくことは重要です。ここでは、ヒルベルト変換の動作を周波数領域で可視化し、SSB生成のメカニズムを確認します。

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

# パラメータ
fs = 10000
T = 1.0
t = np.arange(0, T, 1/fs)
N = len(t)

# メッセージ信号
fm1, fm2 = 30, 70
m = np.cos(2 * np.pi * fm1 * t) + 0.6 * np.cos(2 * np.pi * fm2 * t)

# ヒルベルト変換
analytic_signal = hilbert(m)
m_hilbert = np.imag(analytic_signal)

# 周波数軸
freqs = np.fft.fftfreq(N, 1/fs)
freq_pos = freqs[:N//2]

# スペクトル比較
M = np.fft.fft(m) / N
M_h = np.fft.fft(m_hilbert) / N

fig, axes = plt.subplots(2, 2, figsize=(14, 8))

# 時間波形
axes[0, 0].plot(t[:500], m[:500], 'b-', linewidth=1.5, label='m(t)')
axes[0, 0].plot(t[:500], m_hilbert[:500], 'r-', linewidth=1.5, label='$\\hat{m}(t)$ (Hilbert)')
axes[0, 0].set_xlabel('Time [s]')
axes[0, 0].set_ylabel('Amplitude')
axes[0, 0].set_title('Time domain')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)

# 振幅スペクトル
axes[0, 1].stem(freq_pos[:200], 2*np.abs(M[:N//2])[:200], linefmt='b-', markerfmt='bo', basefmt='b-', label='|M(f)|')
axes[0, 1].stem(freq_pos[:200], 2*np.abs(M_h[:N//2])[:200], linefmt='r-', markerfmt='r^', basefmt='r-', label='|$\\hat{M}$(f)|')
axes[0, 1].set_xlabel('Frequency [Hz]')
axes[0, 1].set_ylabel('Magnitude')
axes[0, 1].set_title('Magnitude spectrum')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)

# 位相スペクトル(主要成分のみ)
phase_m = np.angle(M)
phase_mh = np.angle(M_h)
axes[1, 0].stem(freq_pos[:200], phase_m[:N//2][:200], linefmt='b-', markerfmt='bo', basefmt='b-', label='arg M(f)')
axes[1, 0].stem(freq_pos[:200], phase_mh[:N//2][:200], linefmt='r-', markerfmt='r^', basefmt='r-', label='arg $\\hat{M}$(f)')
axes[1, 0].set_xlabel('Frequency [Hz]')
axes[1, 0].set_ylabel('Phase [rad]')
axes[1, 0].set_title('Phase spectrum')
axes[1, 0].legend()
axes[1, 0].grid(True, alpha=0.3)

# 位相差の確認
phase_diff = phase_mh[:N//2] - phase_m[:N//2]
# 有意な成分のみ表示
significant = 2*np.abs(M[:N//2]) > 0.01
axes[1, 1].stem(freq_pos[significant[:len(freq_pos)]], phase_diff[significant[:len(freq_pos)]],
                linefmt='g-', markerfmt='go', basefmt='g-')
axes[1, 1].axhline(y=-np.pi/2, color='k', linestyle='--', alpha=0.5, label='$-\\pi/2$')
axes[1, 1].set_xlabel('Frequency [Hz]')
axes[1, 1].set_ylabel('Phase difference [rad]')
axes[1, 1].set_title('Phase shift by Hilbert transform')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('hilbert_analysis.png', dpi=150, bbox_inches='tight')
plt.show()

この4枚のグラフから、ヒルベルト変換の本質が確認できます:

  1. 時間波形: $\hat{m}(t)$ は $m(t)$ と振幅が同じですが、位相がずれています。余弦波 $\cos(2\pi f t)$ のヒルベルト変換は $\sin(2\pi f t)$ になるため、90度の遅れとして現れます。
  2. 振幅スペクトル: $|M(f)|$ と $|\hat{M}(f)|$ は完全に一致しています。ヒルベルト変換は振幅を変えず、位相だけを操作することが確認できます。
  3. 位相スペクトル: ヒルベルト変換後の位相は元の位相から一定量シフトしています。
  4. 位相差: 有意な全ての周波数成分において、位相差がちょうど $-\pi/2$($-90°$)になっています。これがヒルベルト変換の定義 $H(f) = -j\operatorname{sgn}(f)$ の効果を直接的に示しています。

この「全帯域で一律 $-90°$ の位相シフト」が、SSB生成の鍵です。$m(t)\cos(2\pi f_c t)$ で生まれるUSBとLSBに対して、$\hat{m}(t)\sin(2\pi f_c t)$ は適切な位相関係を持ち、一方を強め合い他方を打ち消し合うのです。

ここまでヒルベルト変換のメカニズムを確認しました。次に、実際の復調過程をシミュレーションし、SSBから元のメッセージがどのように復元されるかを確認しましょう。

SSBの復調シミュレーション

SSBの復調もDSB-SCと同様に同期検波で行います。受信したSSB信号に搬送波を掛けてローパスフィルタを通す、という手順です。ここでは、復調精度と位相誤差の影響を数値的に確認します。

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

# パラメータ
fs = 10000
T = 1.0
t = np.arange(0, T, 1/fs)
fc = 500
fm1, fm2, fm3 = 30, 60, 90

# メッセージ信号
m = np.cos(2 * np.pi * fm1 * t) + 0.5 * np.cos(2 * np.pi * fm2 * t) + 0.3 * np.cos(2 * np.pi * fm3 * t)

# SSB-USB生成
m_h = np.imag(hilbert(m))
carrier_cos = np.cos(2 * np.pi * fc * t)
carrier_sin = np.sin(2 * np.pi * fc * t)
s_ssb = m * carrier_cos - m_h * carrier_sin

# ローパスフィルタの設計
b, a = butter(5, 150 / (fs/2), btype='low')

# 同期検波(位相誤差なし)
demod_0 = 2 * s_ssb * np.cos(2 * np.pi * fc * t)
demod_0_filtered = filtfilt(b, a, demod_0)

# 同期検波(位相誤差30度)
phi = np.deg2rad(30)
demod_30 = 2 * s_ssb * np.cos(2 * np.pi * fc * t + phi)
demod_30_filtered = filtfilt(b, a, demod_30)

# 同期検波(位相誤差90度)
phi90 = np.deg2rad(90)
demod_90 = 2 * s_ssb * np.cos(2 * np.pi * fc * t + phi90)
demod_90_filtered = filtfilt(b, a, demod_90)

# 結果のプロット
fig, axes = plt.subplots(4, 1, figsize=(12, 10), sharex=True)

axes[0].plot(t[:2000], m[:2000], 'b-', linewidth=1.5)
axes[0].set_ylabel('Amplitude')
axes[0].set_title('Original message m(t)')
axes[0].grid(True, alpha=0.3)

axes[1].plot(t[:2000], demod_0_filtered[:2000], 'g-', linewidth=1.5)
axes[1].plot(t[:2000], m[:2000], 'b--', linewidth=1, alpha=0.5, label='Original')
axes[1].set_ylabel('Amplitude')
axes[1].set_title('Demodulated (phase error = 0°)')
axes[1].legend()
axes[1].grid(True, alpha=0.3)

axes[2].plot(t[:2000], demod_30_filtered[:2000], 'orange', linewidth=1.5)
axes[2].plot(t[:2000], m[:2000] * np.cos(np.deg2rad(30)), 'b--', linewidth=1, alpha=0.5, label='m(t)cos(30°)')
axes[2].set_ylabel('Amplitude')
axes[2].set_title('Demodulated (phase error = 30°)')
axes[2].legend()
axes[2].grid(True, alpha=0.3)

axes[3].plot(t[:2000], demod_90_filtered[:2000], 'r-', linewidth=1.5)
axes[3].set_ylabel('Amplitude')
axes[3].set_title('Demodulated (phase error = 90°)')
axes[3].set_xlabel('Time [s]')
axes[3].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('ssb_demod.png', dpi=150, bbox_inches='tight')
plt.show()

# 復調精度の定量評価
print("=== 復調精度 ===")
# 過渡応答を避けるため中央部分で評価
mid = slice(2000, 8000)
for phi_deg in [0, 10, 20, 30, 45, 60, 90]:
    phi_r = np.deg2rad(phi_deg)
    d = 2 * s_ssb * np.cos(2 * np.pi * fc * t + phi_r)
    d_f = filtfilt(b, a, d)
    # 理論的に cos(phi) 倍のスケーリング
    expected = m * np.cos(phi_r)
    mse = np.mean((d_f[mid] - expected[mid])**2)
    print(f"  phi = {phi_deg:3d}°: cos(phi) = {np.cos(phi_r):.4f}, MSE = {mse:.2e}")

シミュレーション結果から、以下のことが確認できます:

  1. 位相誤差0度: 復調信号は元のメッセージと完全に一致します。SSBでも同期検波が正しく機能することが確認できました。
  2. 位相誤差30度: 振幅が $\cos(30°) \approx 0.866$ 倍にスケーリングされます。波形の形状は保たれるため、音声通信では許容範囲内とされることが多いです。
  3. 位相誤差90度: DSB-SCの場合と同様に、出力がほぼゼロになります。ただし、SSBでは厳密にはゼロではなく、ヒルベルト変換成分がわずかに残ります。これはSSBの復調でも位相同期が本質的に重要であることを示しています。
  4. MSE(平均二乗誤差) の値から、位相誤差が増大するにつれて復調精度が低下することが定量的に確認できます。

位相同期の重要性が改めて確認できたところで、最後にこれまでの内容を総合的にまとめましょう。

各AM変調方式の総合比較

ここまでに解説した各方式の特徴を、定量的にまとめます。

数式による比較

メッセージ信号 $m(t)$、搬送波 $\cos(2\pi f_c t)$、ヒルベルト変換 $\hat{m}(t)$ を用いると:

方式 送信信号 $s(t)$
DSB-FC $A_c[1 + k_a m(t)]\cos(2\pi f_c t)$
DSB-SC $m(t)\cos(2\pi f_c t)$
SSB-USB $m(t)\cos(2\pi f_c t) – \hat{m}(t)\sin(2\pi f_c t)$
SSB-LSB $m(t)\cos(2\pi f_c t) + \hat{m}(t)\sin(2\pi f_c t)$

性能指標の比較

指標 DSB-FC DSB-SC SSB VSB
帯域幅 $2W$ $2W$ $W$ $W + f_v$
電力効率 $\leq 33\%$ $100\%$ $100\%$ 中〜高
復調の複雑さ 低(包絡線検波) 高(同期検波) 高(同期検波)
受信機コスト
主な用途 AM放送 QAMの基礎 HF通信 アナログTV

QAMとの関係

DSB-SCの直交性は、現代のディジタル通信の基礎となっています。互いに直交する2つの搬送波 $\cos(2\pi f_c t)$ と $\sin(2\pi f_c t)$ にそれぞれ独立なメッセージ信号を載せると:

$$ s_{\text{QAM}}(t) = m_I(t)\cos(2\pi f_c t) – m_Q(t)\sin(2\pi f_c t) $$

これはQAM(直交振幅変調) であり、同じ帯域幅で2倍のデータを伝送できます。先ほど確認した $\phi = 90°$ での直交ヌルは、I成分とQ成分が互いに干渉しないことの数学的根拠です。Wi-Fi (802.11)、LTE、5G NRなど、現代の高速無線通信はすべてQAMを基盤としており、その原理はDSB-SCの直交多重にあります。

まとめ

本記事では、AM変調の帯域効率と電力効率を改善する各方式について解説しました。

  • DSB-SC は搬送波を除去して電力効率を100%に高めるが、復調に同期検波(搬送波再生)が必要
  • SSB はさらに片方の側波帯を除去し、帯域幅を半分に削減。生成にはフィルタ法または位相法(ヒルベルト変換)を用いる
  • VSB はSSBとDSBの中間で、低域成分を含む信号(映像など)に適する
  • 位相同期 がDSB-SCとSSBの復調の鍵であり、位相誤差は $\cos(\phi)$ に比例して出力を劣化させる
  • QAM はDSB-SCの直交多重であり、現代のディジタル通信の基礎をなしている

DSB-SCとSSBの理解は、変調・復調の体系的な理解の中核をなします。特にSSBのヒルベルト変換は、信号解析やSDR(ソフトウェア無線)でも頻繁に登場する重要な概念です。

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