第6章

離散フーリエ変換

この章のねらい

  • 周波数 ω を ω_k=2πk/N でサンプリングして DFT の式を導ける
  • 周波数を離散化すると時間側が周期的になる双対を説明できる
  • N点⇄N点の有限変換であること、FFT が O(N log N) で同じ DFT を速く計算する仕組みを理解する

6.1 DTFT の困るところ

やる夫

第5章で数列のフーリエ変換(DTFT)が完成したお。X(ejω)=nx[n]ejωnX(e^{j\omega}) = \sum_n x[n] e^{-j\omega n} だお。これでコンピュータの信号も周波数に分解できる…はずだお?

やらない夫

理論上はな。だが章の最後にお前自身が言った困りごとが2つある。覚えているか。

やる夫

えーと…。ω\omega が連続変数だから、ω\omega 全部の値はコンピュータに持てない、って言ったお。あ、もう1個あるお。和 n\sum_nn=n = -\infty から ++\infty まで足すことになってるお。無限個は足せないお!

やらない夫

その2つだ。整理しよう。DTFT がそのままでは計算機に乗らない理由は、

  • 周波数 ω\omega が連続0ω<2π0 \le \omega < 2\pi の中に無限個の点がある)
  • 時間 nn が無限に長い(和が -\infty から \infty まで)

時間側の問題は、実は簡単に片付く。実際に手元にあるデータは有限個、例えば NNx[0],x[1],,x[N1]x[0], x[1], \dots, x[N-1] だけだ。それ以外を 00 とすれば和は NN 項で止まる。残るのは周波数が連続という問題だ。

やる夫

時間を有限で打ち切るのは分かるお。じゃあ周波数のほうは…。あ、第4章で時間を離散化したのと同じことを、今度は周波数でやればいいんじゃないかお?

やらない夫

それだ。発想がもう身についてきたな。時間軸でやった「とびとびに拾う」を、そっくり周波数軸でやる。

6.2 周波数領域を離散化する

やらない夫

連続な ω\omega の代わりに、00 から 2π2\pi までを NN 等分したとびとびの周波数だけを見る。

ωk=2πkN(k=0,1,,N1)(6.1)\omega_k = \frac{2\pi k}{N} \qquad (k = 0, 1, \dots, N-1) \tag{6.1}

DTFT の1周期 [0,2π)[0, 2\pi) に等間隔で NN 本の「物差しの目盛り」を打つイメージだ。この ωk\omega_k を式 (5.3) に代入し、和を有限の NN 項に切ると

X[k]=X(ejωk)=n=0N1x[n]ej2πkn/N(6.2)X[k] = X(e^{j\omega_k}) = \sum_{n=0}^{N-1} x[n]\, e^{-j 2\pi k n / N} \tag{6.2}

これが離散フーリエ変換(Discrete Fourier Transform、DFT)だ。NN 個の数列 x[n]x[n] から NN 個のスペクトル値 X[k]X[k] を作る。

やる夫

おお、\int も無限和も消えて、有限の足し算だけになったお! これならコンピュータで回せるお。X[k]X[k] もカギ括弧で、ただの配列だお。

やらない夫

そうだ。X[k]X[k] は「kk 番目の周波数ビン」と呼ばれる。kk が大きいほど高い周波数(ただし kkN/2N/2 を超えると負の周波数側になる、これは後で見る)。下のデモで、固定した信号(長さ8の矩形パルス)の DTFT 曲線の上に、NN 点 DFT のビンがどう乗るかを見てみろ。NN を動かせる。

DFT BINS ON DTFT INTERACTIVE
N を増やしてみる。緑の棒(N 点 DFT のビン)は密になるが、破線(連続の DTFT 曲線)はずっと同じ形のまま。これは DFT が DTFT を ω_k=2πk/N で拾った標本にすぎず、N は目盛りの細かさを変えるだけで信号の中身は変えないことを意味する。
やる夫

これ、第3章で見たやつと同じ気持ちになるお! あのとき周期 T0T_0 を伸ばすと線スペクトルの棒が密になっていったお。今回は NN を増やすと棒が密になる。けど…曲線(破線)はずっと同じ形だお。

やらない夫

完璧な観察だ。DFT は DTFT という連続曲線を、ωk=2πk/N\omega_k = 2\pi k/N という点で拾った標本値にすぎないNN は「周波数の物差しを何目盛りで刻むか」を決めるだけで、信号そのものの情報量を増やしも減らしもしない。棒が乗っている曲線が真実で、棒はその上の点を拾っているだけだ。

やる夫

サンプリングって、時間でも周波数でも結局おんなじことなんだお。

やらない夫

いいまとめだ。そして、ここでまた双対が顔を出す。第3章で「時間側が周期的だと周波数側は離散」、第5章で「時間側が離散だと周波数側は周期」を見た。今度は周波数側を離散化した。すると鏡写しに、時間側が周期的とみなされる

やる夫

え、時間が周期的? x[n]x[n] は別に周期信号じゃないお。長さ NN の有限の数列なだけだお。

やらない夫

そこが DFT の最大の落とし穴だ。逆変換でわかるが、X[k]X[k] から x[n]x[n] を組み立て直すと、nn0N10 \sim N-1 の外でも値が出てきて、それは周期 NN で同じパターンを繰り返す。DFT は心の中で「x[n]x[n] は周期 NN で無限に続く周期信号だ」と思い込んで計算している。だから第3章の対応の鏡写しが完成する。

  • 周波数を離散化(DFT のビン)した ⇒ 時間側が周期 NN とみなされる

第3章「時間が周期的⇔周波数が離散」を、左右ひっくり返した形だ。

6.3 離散フーリエ逆変換

やらない夫

順変換 (6.2) で NN 個の x[n]x[n] から NN 個の X[k]X[k] を作った。逆に戻す離散フーリエ逆変換(IDFT)はこうだ。

x[n]=1Nk=0N1X[k]ej2πkn/N(6.3)x[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k]\, e^{j 2\pi k n / N} \tag{6.3}
やる夫

順変換 (6.2) とそっくりだお。違いは、肩の符号が - から ++ に変わったのと、頭に 1/N1/N が付いたことだけだお。

やらない夫

その通り。第5章の逆変換 (5.5) では 12π\frac{1}{2\pi}\int だったのが、周波数も離散になったので積分が和に変わり1N\frac{1}{N}\sum になった。係数 12π\frac{1}{2\pi}1N\frac{1}{N} に化けたのも、周波数の刻み幅が 2πN\frac{2\pi}{N} になったことの帳尻合わせだ。順変換が「全周波数のビンで和」、逆変換も「全時間で和」。どちらも有限和で、対称的にきれいだろ。

やる夫

順も逆も有限の足し算で閉じてるお。やっと全部がコンピュータで完結するんだお。

やらない夫

そうだ。ここに至って、信号処理はついに「紙の上の積分」を完全に離れて、配列と足し算と掛け算だけの世界に降りてきた。これが実際に走るフーリエ変換だ。

6.4 離散フーリエ変換のまとめ — 行列として見る

やらない夫

DFT (6.2) をもう一度眺める。NN 個の入力 x[n]x[n] から NN 個の出力 X[k]X[k] への変換だ。各 X[k]X[k]x[0]x[N1]x[0] \dots x[N-1] の重み付き和。これは行列とベクトルの掛け算そのものだ。

X[k]=n=0N1WNknx[n],WN=ej2π/N(6.4)X[k] = \sum_{n=0}^{N-1} W_N^{kn}\, x[n], \qquad W_N = e^{-j 2\pi / N} \tag{6.4}

WNknW_N^{kn}(k,n)(k, n) 成分とする N×NN \times N 行列を xx ベクトルに掛ければ XX ベクトルが出る、というわけだ。

やる夫

WNW_N ってのは、NN 等分した円周を1目盛り進む回転因子かお。ej2π/Ne^{-j2\pi/N} は「1N\frac{1}{N} 周ぶん時計回りに回す」やつだお。

やらない夫

その通り、回転因子と呼ぶ。行列の各行 kk は「周波数 ωk=2πk/N\omega_k = 2\pi k/N の複素正弦波」、すなわち DFT の基底ベクトル ej2πkn/Ne^{j2\pi kn/N} になっている。DFT とは結局「入力ベクトルを、これら NN 本の正弦波基底に分解する」操作だ。各基底がどんな波か、下のデモで kk を動かして見てみろ。上が実部 cos\cos、下が虚部 sin\sin だ(N=16N=16 固定)。

DFT BASIS — N=16 INTERACTIVE
k を上げていくと、基底 e^{j2πkn/16} の実部(cos)・虚部(sin)の振動が速くなり、k=8 で最高周波数(±1交互)になる。さらに上げると k=9 以降はまた遅く見え、k=15 は k=1 にそっくり。これは k>8 のビンが k=N-k の逆回転=負の周波数を表しているから。離散の世界の基底が一周して戻る様子が見える。
やる夫

k=0k=0 は全部 11 で平ら(直流)だお。kk を上げてくと振動が速くなって、k=8k=8+1,1+1, -1 の交互(一番速い)になるお。…で、k=9k=9 以上にすると、またゆっくりに戻るお! k=15k=15 なんて k=1k=1 にそっくりだお。

やらない夫

そこが急所だ。k=8k=8=N/2=N/2)を境に、k>N/2k > N/2 のビンは負の周波数を表す。k=15k=15k=1k=1 の逆回転、つまり ω=2π15/16\omega = 2\pi \cdot 15/16ω=2π/16\omega = -2\pi/16 と同じこと。第4章・第5章でやった「ω\omegaω+2π\omega + 2\pi(あるいは ω-\omega)は区別がつかない」がここでも生きている。だから NN 点 DFT の出力は、低い周波数から最高周波数(k=N/2k=N/2)まで上がって、また負側の低い周波数へ折り返す並びになる。

やる夫

基底が一回りして戻ってくるんだお。離散の世界はとことん周期的だお。

6.5 高速フーリエ変換

やらない夫

DFT は実用の本命だが、素直に計算すると重い。式 (6.2) で X[k]X[k] を1個求めるのに掛け算が NN 回。それを k=0N1k = 0 \sim N-1NN 個ぶん。合計 N2N^2 回の掛け算が要る。N=106N = 10^6 なら 101210^{12} 回。さすがに遅すぎる。

やる夫

N2N^2 は嫌な響きだお…。NN がちょっと増えるとドカンと重くなるやつだお。なんとかならないのかお。

やらない夫

なる。これを劇的に速くするのが高速フーリエ変換(Fast Fourier Transform、FFT)だ。まず強調しておく。FFT は DFT とは別物ではない式 (6.2) とまったく同じ X[k]X[k] を、計算の順番を工夫して速く出すだけの計算法だ。結果は1ビットも変わらない。

やる夫

別の変換じゃなくて、同じ答えへの近道なんだお。安心したお。で、どう工夫するんだお?

やらない夫

肝は「分割」だ。NN を偶数として、和を偶数番目の nn奇数番目の nn の2つに分ける。

X[k]=nx[n]WNkn+nx[n]WNkn(6.5)X[k] = \sum_{n\,\text{偶}} x[n] W_N^{kn} + \sum_{n\,\text{奇}} x[n] W_N^{kn} \tag{6.5}

偶数番を x[2m]x[2m]、奇数番を x[2m+1]x[2m+1]m=0N/21m = 0 \dots N/2-1)と書き直す。鍵は回転因子の指数が半分の長さの回転因子になることだ。偶数番の和に現れる WNk2mW_N^{k\cdot 2m} を変形すると

WN2km=ej2π(2km)/N=ej2πkm/(N/2)=WN/2km(6.6)W_N^{2km} = e^{-j 2\pi (2km)/N} = e^{-j 2\pi km/(N/2)} = W_{N/2}^{km} \tag{6.6}

22 が分母の NN と打ち消し合って、ちょうど長さ N/2N/2 の回転因子 WN/2W_{N/2} に化ける。つまり偶数番だけの和は、それ自身が長さ N/2N/2 の DFTになっている。奇数番のほうは、x[2m+1]x[2m+1] に掛かる WNk(2m+1)=WNkWN2km=WNkWN/2kmW_N^{k(2m+1)} = W_N^{k}\, W_N^{2km} = W_N^{k}\, W_{N/2}^{km} から、mm に依らない共通因子 WNkW_N^{k} を和の外にくくり出せて、残りがまた長さ N/2N/2 の DFT になる。

やらない夫

偶数番だけの DFT を E[k]E[k]、奇数番だけの DFT を O[k]O[k] と名付ければ、くくり出した WNkW_N^{k} を奇数側に掛けて足し合わせるだけで

X[k]=E[k]+WNkO[k](6.7)X[k] = E[k] + W_N^{k}\, O[k] \tag{6.7}

長さ NN の DFT が、長さ N/2N/2 の DFT 2個と、たった1回の掛け算+足し算でつながった。

やる夫

長さ NN の DFT 1個が、長さ N/2N/2 の DFT 2個+ちょっとの結合になったお。22 が消えて回転因子が半分サイズになるのが効いてるんだお。…これ、半分のやつをまた半分に割れば、どんどん小さくできそうだお!

やらない夫

そこに気づけば勝ちだ。N/2N/2 の DFT を、また偶数・奇数に割って N/4N/4 の DFT 2個に。それをまた割って…と再帰的に繰り返す。NN22 のべき乗なら、最後は長さ 11 の DFT(=そのまま)まで割れる。

ここがコストの急所だ。半分に割る段数は log2N\log_2 N 回。各段で全 NN 個のデータを結合 (6.7) するのに NN 回程度の計算。だから全体は

O(N2)    O(NlogN)(6.8)O(N^2) \;\longrightarrow\; O(N \log N) \tag{6.8}

N=106N = 10^6 なら N2=1012N^2 = 10^{12}Nlog2N2×107N \log_2 N \approx 2 \times 10^7約5万倍速い。リアルタイム音声処理も画像のスペクトル解析も、この差で初めて実用になった。

FFT — DIVIDE & CONQUER INTERACTIVE
N を上げると DFT が偶数番・奇数番へ二分される再帰木が log₂N 段に深くなる。下部の演算回数を見ると、素朴な O(N²) は急増し FFT の O(N log₂N) との差が一気に開く。これが分割統治で速くなる理由。
やる夫

5万倍! 同じ答えなのに、足す順番を変えただけでそんなに違うのかお。半分に割ると、片方の計算がもう片方と使い回せるからかお。

やらない夫

その通り。素朴な計算は、kk ごとに同じ部分和を何度も計算し直していた。FFT はそれを共有して二度手間を省く。発想は「分割統治」、賢いプログラムの王道だ。

やる夫

ところで、結合の式 (6.7) は X[k]=E[k]+WNkO[k]X[k] = E[k] + W_N^{k} O[k]k=0N/21k = 0 \dots N/2-1 までしか作ってないお。残り半分の X[k+N/2]X[k + N/2] はどうするんだお? また別に計算するのかお?

やらない夫

そこが一番うまい所だ。実はただ同然で手に入る。E[k]E[k]O[k]O[k] も長さ N/2N/2 の DFT だから N/2N/2 で周期的、つまり E[k+N/2]=E[k]E[k+N/2] = E[k]O[k+N/2]=O[k]O[k+N/2] = O[k]。さらに回転因子は WNk+N/2=WNN/2WNk=WNkW_N^{k+N/2} = W_N^{N/2} W_N^{k} = -W_N^{k}(半周ぶん回すと符号が反転)だ。これを (6.7) に入れると

X[k+N/2]=E[k]WNkO[k](6.7’)X[k + N/2] = E[k] - W_N^{k}\, O[k] \tag{6.7'}
やる夫

WNkO[k]W_N^{k} O[k] は (6.7) でもう計算済みだお! 符号を ++ から - に変えるだけで、上半分 X[k]X[k] と下半分 X[k+N/2]X[k+N/2]一度の掛け算から2つ同時に出てくるんだお!

やらない夫

それが「バタフライ」と呼ばれる演算だ。入力 a=E[k]a = E[k]b=O[k]b = O[k] から、掛け算 WNkbW_N^{k} b をたった1回やって、a+WNkba + W_N^{k} baWNkba - W_N^{k} b の2出力を作る。流れ図に描くと羽を広げた蝶のように線が交差するから蝶々形だ。下のデモで、その配線そのものを見てみろ。

FFT — BUTTERFLY FLOW GRAPH INTERACTIVE
N を 4/8 で切り替え、強調ステージを動かす(操作)→ 各段で行が上下ペア(バタフライ)に結ばれ、下入力に回転因子 W が掛かり、上出力=a+W·b・下出力=a−W·b になっている(観察)→ 掛け算1回で2出力、これが log₂N 段重なって O(N log N) を実現する。入力がビット反転順なのは分割を繰り返した名残(意味)。
やらない夫

配線の交差が「再帰木をほどいて1枚に広げた姿」だと思えばいい。再帰木(さっきのデモ)が縦の分割を、このバタフライ図が横の結合を見せている。両方あわせて FFT の全体像だ。とはいえ細かい配線を暗記する必要はない。FFT は DFT の高速計算法、答えは同じ——これだけは絶対に外すな。

6.6 4種類のフーリエ変換のまとめ

やらない夫

これで4つのフーリエ変換が出そろった。バラバラに見えるが、**「時間と周波数が、それぞれ連続/離散・周期/非周期のどれか」**で整理すると、見事に1枚の表に収まる。

変換時間領域周波数領域
フーリエ変換(FT、第3章)連続・非周期連続・非周期
フーリエ級数(FS、第1〜2章)連続・周期離散・非周期(線スペクトル)
離散時間フーリエ変換(DTFT、第5章)離散・非周期連続・周期2π2\pi
離散フーリエ変換(DFT、本章)離散周期NN離散周期NN
やる夫

これ、すごくきれいだお…。表の中の「離散」と「周期」が、時間側と周波数側で必ずペアで入れ替わってるお。

やらない夫

それがこの2章で何度も言ってきた双対の正体だ。法則はたった一行にまとまる。

片方の領域が「離散」なら、もう片方は必ず「周期的」。片方が「周期的」なら、もう片方は必ず「離散」。

  • FS: 時間が周期的 ⇒ 周波数が離散(第3章 (3.8))
  • DTFT: 時間が離散 ⇒ 周波数が周期的(第5章 (5.4))
  • DFT: 時間も離散かつ周期、周波数も離散かつ周期(両方の合わせ技)

DFT が両方とも「離散・周期」なのは、時間も周波数も離散化した当然の帰結だ。そして両方が離散・有限だからこそ、唯一コンピュータの中で完全に閉じられる。

やる夫

FS・FT・DTFT・DFT って名前で4つもあるから別々の難しい話かと身構えてたお。でも全部「波を周波数に分ける」同じ思想で、ただ時間と周波数を連続にするか離散にするかの組み合わせ違いだったんだお。スッキリしたお!

やらない夫

それがこの章までの一番の収穫だ。ここまでで「フーリエ解析」という大きな道具立ては完成した。次章からは、この道具を使って信号を操作するときに成り立つ便利な性質——線形性、時間シフト、そして信号処理の心臓部である「たたみこみ」——を見ていく。変換の式を覚える段階から、変換を武器として使う段階へ進むぞ。

この章のまとめ
  • DTFT は ω\omega が連続でそのままでは計算機に乗らない。周波数を ωk=2πk/N\omega_k = 2\pi k/N で離散化し、和を NN 項に切ると DFT X[k]=n=0N1x[n]ej2πkn/NX[k] = \sum_{n=0}^{N-1} x[n] e^{-j2\pi kn/N}
  • DFT は DTFT 曲線を ωk\omega_k で拾った標本NN は目盛りの細かさで、信号の中身は変えない
  • 周波数を離散化すると、双対により時間側が周期 NN とみなされる。DFT は時間も周波数も「離散・周期」で、唯一コンピュータ内で完全に閉じる
  • IDFT は x[n]=1NkX[k]ej2πkn/Nx[n] = \frac{1}{N}\sum_k X[k] e^{j2\pi kn/N}。順変換と肩の符号と 1/N1/N だけ違う
  • DFT は行列 WNknW_N^{kn}WN=ej2π/NW_N = e^{-j2\pi/N})の掛け算。各行は基底正弦波で、k>N/2k > N/2 は負の周波数
  • FFT は DFT の高速計算法(別物ではない)。偶奇分割の再帰で O(N2)O(NlogN)O(N^2) \to O(N\log N)
  • 4変換は「時間・周波数が連続/離散・周期/非周期」の組み合わせ。片方が離散なら他方は周期という双対が貫く