AM → FM への拡張「窓関数って何だ?」

いいですね…そこに行きましたか 😄
AM → FM は、今日の流れの「正統進化ルート」です。

しかもやることは意外とシンプルで、
**「どこを変えるか」**が分かると一気に腑に落ちます。


まず概念の違い(超重要)

AM(振幅変調)

振幅が揺れる

sAM(t)=(1+μcos(2πfmt))cos(2πfct)s_{AM}(t) = \bigl(1 + \mu \cos(2\pi f_m t)\bigr)\cos(2\pi f_c t)


FM(周波数変調)

周波数(位相の進み方)が揺れる

sFM(t)=cos(2πfct+βsin(2πfmt))s_{FM}(t) = \cos\Bigl(2\pi f_c t + \beta \sin(2\pi f_m t)\Bigr)

  • β(ベータ)= 変調指数

  • AM の μ に対応する“効きの強さ”

👉 振幅は一定、でも中身は激しく変化


ipynb での最小変更ポイント

あなたの AM ノート、
③セルまでは ほぼそのまま使えます


③セル(FM 信号生成)

AM の代わりに、ここだけ変えます👇

# 時間軸
t = np.arange(0, T, 1/fs)
# パラメータ
beta = 5.0 # FM変調指数(ここを変えて遊ぶ)

# FM信号
fm_signal = np.cos(
2*np.pi*fc*t + beta * np.sin(2*np.pi*fm*t)
)

carriermessage を分けて書いてもOKですが、
FMは「位相に直接入る」のがポイントです。


④セル(時間波形表示)

AM のときと 全く同じ書き方でOK:

plt.figure(figsize=(8, 4))
plt.plot(t[:2000], fm_signal[:2000])
plt.xlabel("Time [s]")
plt.ylabel("Amplitude")
plt.title("FM waveform (time domain)")
plt.grid()
plt.show()

👉 見た目は
**「AMよりずっとゴチャッとしてる」**はず。

でも振幅は一定。


⑤セル(FFT)

これも AM と同じで、変数名だけ変更:

S = np.fft.fft(fm_signal)
freq = np.fft.fftfreq(len(S), d=1/fs)
amp = np.abs(S) / len(S)

⑥セル(スペクトル表示)

plt.figure(figsize=(8, 4))
plt.plot(freq, amp)
plt.xlim(0, 2_000_000)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Amplitude")
plt.title("FM spectrum")
plt.grid()
plt.show()

見える世界の違い(ここが感動ポイント)

AM

  • 中心:fc

  • 両脇:fc ± fm(細い)

FM

  • fc の周りに 無数の側波帯

  • β を上げると 一気に広帯域化

👉
「FM は音質がいいが、帯域を食う」
という教科書の一文が 目で分かる瞬間です。


まず試してほしい β の値

beta = 0.5 # ほぼAMっぽい
beta = 2.0
beta = 5.0
beta = 10.0 # 完全に広帯域

FFT を並べて見ると、
通信方式の思想の違いが一気に見えてきます。


今日のあなたに起きていること(ちょっとだけ)

もうこれは
「Python の勉強」ではなく、

信号処理を“自分の手で再発見している”状態

です。

次はきっと

  • Carson の帯域幅

  • Bessel 関数

  • FM 復調

あたりが自然に気になってきます 😄

また一歩進みたくなったら、
どこでも一緒に掘り下げましょう。

「窓関数って何だ?」

来ましたね、その疑問。
**「窓関数って何だ?」**と自然に思った時点で、もう“本物の入口”です。

今日は FFTを使って実感できるレベルで説明します。
数式より なぜ必要か → 何が変わるか を重視します。


まず直感から

FFT するとき、実はあなたはこういうことをしています👇

「信号を、ある区間でブツッと切り取って周波数解析」

この「ブツッ」が問題の正体です。


問題:矩形窓(何もしない状態)

今までやっていた FFT は、暗黙的に:

信号 × 矩形窓(0 or 1)

つまり、

| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|

という窓で切っています。

何が起きるか?

  • 端で 急激に 0 になる

  • → 高周波成分が大量発生

  • スペクトルがにじむ(リーケージ)

👉 これが
「側波帯が分離しない」
「ピークが太い」
正体です。


窓関数とは?

「端をなめらかにしてから FFT しよう」
という工夫です。


代表例:Hann(ハン)窓

形はこんな感じ👇

/\
/ \
/ \
  • 両端が 0

  • 中央が最大

  • 急な変化が無い

👉 高周波ノイズが激減します。


ipynb で一発体験

窓なし(今まで)

S = np.fft.fft(fm_signal)

Hann 窓あり

window = np.hanning(len(fm_signal))
S = np.fft.fft(fm_signal * window)

👉 これだけです。


スペクトルの違い(見どころ)

窓なし

  • ピークが太い

  • にじむ

  • 偽の成分が多い

窓あり

  • ピークが細い

  • 側波帯が分離

  • 見た目が「きれい」

※ ただし振幅は少し下がります(副作用)


よく使う窓関数(実用)

特徴
Rectangular 何もしない(リーケージ最大)
Hann 万能・まずこれ
Hamming 低サイドローブ
Blackman 超きれい・分解能低下

👉 迷ったら Hann


なぜ通信・音声で重要?

  • FM / 音声解析

  • スペクトラムアナライザ

  • SDR

全部
👉 窓あり前提で設計されています。


今日の一言まとめ

  • FFT は「有限区間を切る」解析

  • 切り方が悪いと周波数が汚れる

  • 窓関数 = 切り口をなめらかにする技

次にやると感動するのは:

  • 同じ信号で「窓なし vs Hann」を並べて比較

  • β を変えた FM に窓をかける

「なんか FFT きれいになった気がする」
から
**「理屈が分かって使ってる」**に変わる瞬間です。

コメント