第11章

スペクトル解析と窓関数

この章のねらい

  • スペクトル解析の処理の流れ(LPF→サンプリング→切り出し→窓→DFT)を説明できるようになる
  • 有限区間の切り出しがスペクトル漏れを生む仕組みを「窓スペクトルとのたたみこみ」で理解する
  • メインローブ幅とサイドローブレベルのトレードオフを踏まえて窓関数を選べるようになる

11.1 離散フーリエ変換によるスペクトル解析

やる夫

ここまでで道具はだいぶ揃った気がするお。そろそろ実戦がしたいお。マイクで録った音を FFT に放り込んで、「スペクトルを見る」ってやつをやりたいんだお。

やらない夫

いいだろう、この章はまさにそれだ。ただし最初に言っておく。「FFT に放り込めば終わり」ではない。現実の信号のスペクトルをまともに見るには、決まった手順がある。

  1. アンチエイリアスフィルタ(アナログのローパスフィルタ)を通す
  2. サンプリングして離散時間信号にする(A/D 変換)
  3. 信号から N 点の有限区間を切り出す
  4. 切り出した区間に窓関数を掛ける
  5. DFT(実装は FFT) を計算して X[k]|X[k]| を眺める

世の中のオーディオスペクトラムアナライザも、測定器の FFT モードも、中身はこの流れだ。

やる夫

3 と 4 が初耳だお。1 はなんとなく第10章の続きっぽい雰囲気を感じるお。

やらない夫

感じたとおりだ。そしてこの手順の 1, 3, 4 にはそれぞれ「やらないと(あるいは無自覚にやると)嘘のスペクトルが表示される」という理由が付いている。この章はその理由を順番に潰していく。

先に1つだけ数を確認しておこう。サンプリング周波数 fsf_s で N 点の DFT を計算したとき、ビン kk が対応する実周波数は

fk=kNfs(k=0,1,,N1)(11.1)f_k = \frac{k}{N} f_s \qquad (k = 0, 1, \dots, N-1) \tag{11.1}

つまり DFT は fs/Nf_s/N [Hz] 刻みの「とびとびの周波数の物差し」だ。この刻みを周波数分解能と呼ぶ。

やる夫

ふむ…たとえば fs=48000f_s = 48000 Hz で N=1024N = 1024 点なら、48000/1024=46.87548000/1024 = 46.875 Hz 刻みかお。細かく見たければ N を増やせばいい、と。

やらない夫

計算は合ってる。「N を増やせば細かくなる」は半分正しくて半分罠なんだが、それは 11.3 節までお預けだ。

11.2 アンチエイリアスフィルタ

やらない夫

手順 1 から行く。第10章の結論を思い出せ。fs/2f_s/2(ナイキスト周波数)を超える成分が信号に残ったままサンプリングすると、どうなる?

やる夫

折り返してくるお。高い成分が低い周波数に化けて、もともとあった成分と足されて…混ざったら最後、二度と分離できないんだったお。

やらない夫

そのとおり。だから、サンプリングのfs/2f_s/2 以上の成分を物理的に削ぎ落としておくしかない。この目的で入れるローパスフィルタをアンチエイリアスフィルタと呼ぶ。

やる夫

前に、ってことは…ディジタルフィルタじゃダメなのかお? せっかくこの教材でフィルタの作り方をやってきたのに。

やらない夫

ダメだ、常識的に考えて。ディジタルフィルタが動けるのはサンプリングの後の世界だ。だがエイリアシングはサンプリングの瞬間に起きて、その時点で偽物の低周波成分が本物と区別不能な形で混入している。後段のディジタルフィルタがそれを見ても、本物か偽名かを判定する手段はない。手遅れなんだ。だからここだけはアナログ回路のフィルタでなければ務まらない。

やる夫

ディジタル信号処理の教材なのに、入り口だけはアナログに頼るしかないのかお。ちょっと悔しいお。

やらない夫

その悔しさは正しい認識だ。そして第10章の宿題もここで回収できる。CD はなぜ可聴域 20 kHz の2倍ちょうどの 40 kHz ではなく 44.1 kHz なのか。現実のアナログフィルタは理想フィルタと違って、通過域から阻止域へ崖のようには切り落とせない。なだらかな「遷移帯域」が必ず要る。20 kHz までを素通しして 22.05 kHz 以上を十分落とす、その坂道のための余白が 2 kHz ちょっとというわけだ。

11.3 有限区間の切り出し

やらない夫

手順 3 に進む。マイクの信号は流れ続けるが、DFT が食えるのは N 点の有限な数列だけだ。だからどこかの N 点を切り出すことになる。さて、「切り出す」を数式で書くとどうなる?

やる夫

区間の外を 0 にするんだから…区間の中で 1、外で 0 の信号を掛け算するのかお。あ、これ第10章のくし型のときと同じ発想だお。

やらない夫

いい勘だ。その「中で1、外で0」の数列

xN[n]=x[n]w[n],w[n]={1(0nN1)0(それ以外)(11.2)x_N[n] = x[n]\, w[n], \qquad w[n] = \begin{cases} 1 & (0 \le n \le N-1) \\ 0 & (\text{それ以外}) \end{cases} \tag{11.2}

矩形窓と呼ぶ。何もしていないつもりでも、N 点切り出した時点でお前は必ず矩形の窓を掛けている。そして第10章で学んだとおり、時間領域の積は周波数領域のたたみこみだ。離散時間版では

XN(ejω)=12π2πX(ejθ)W(ej(ωθ))dθ(11.3)X_N(e^{j\omega}) = \frac{1}{2\pi} \int_{2\pi} X(e^{j\theta})\, W(e^{j(\omega - \theta)})\, d\theta \tag{11.3}

切り出した信号のスペクトルは、本当のスペクトルに窓のスペクトル WW がたたみこまれてなまったものになる。

やる夫

うっ、また出たお、積とたたみこみ。で、矩形窓のスペクトルってどんな形なんだお。

やらない夫

矩形だから、第3章の「矩形 ⇄ sinc」の離散時間版だ。形だけ言葉で掴めば十分で、中央に背の高い山(メインローブ)が1つ、その両脇に振動しながら減衰する小さな山の列(サイドローブ)が続く——連続時間の sinc によく似た形だ。厳密な式は下の Note に置いておくが、細部は気にせず「中央の山+脇に減衰する波」という形だけ掴めばこの章は読める。

つまりこういうことだ。本当は1本の線であるはずの正弦波のスペクトルが、切り出した瞬間にこの「sinc に似た山」に化ける。メインローブの分だけにじみ、サイドローブの分だけ遠くまで漏れる。この現象をスペクトル漏れ(leakage)と呼ぶ。

やる夫

ただ切っただけで汚れるのかお…。じゃあ FFT の画面に出てるあの山々は、信号のスペクトルというより「信号と窓の合作」なのかお。

やらない夫

そういう自覚を持てたなら、この節の目的は半分達成だ。ただし面白いことに、汚れが見えなくなる特別な場合がある。下のデモで確かめろ。N = 64 点の cos 波の周波数を、ビン単位のスライダーで動かせる。まず 8.00(整数)にしてみろ。次に 8.30 にしてみろ。縦軸の単位 dB(デシベル)の読み方を下にまとめておくから、これ以降の「-13 dB」などはこれで読め。

WINDOW EXPLORER INTERACTIVE
周波数を 8.00(DFTビンにぴったり)にすると、矩形窓でも裾が消えて鋭い1本に見える。8.30 にずらすと裾が -13 dB の段々で盛大に漏れる=これがスペクトル漏れで、実際の信号はこちらが普通。窓を hann や blackman に替えると裾は激減するが、代わりに中央の山が太る(漏れと分解能のトレードオフ)。
やる夫

ほんとだお!? 8.00 だと教科書みたいにスパッと1本なのに、8.30 にしただけで裾がベローンと広がって、スペクトル全体がギザギザの階段だらけになったお。同じ「1本の cos」なのに別物だお。

やらない夫

種明かしをしよう。DFT が見ているのは式 (11.1) のとびとびの周波数だけだ。信号の周波数がちょうどビンに乗っている(= 切り出した N 点の中にちょうど整数周期収まっている)場合、sinc 状の山は確かにあるんだが、サンプルされる位置がたまたま全部 sinc のゼロ点に当たる。だからピーク以外は全部 0 に見えて、漏れが「観測されない」。

ところが 8.30 のような半端な周波数だと、ゼロ点からずれた位置で sinc が標本化されるから、全ビンに漏れがそのまま現れる。そして現実の信号、たとえばお前の声の基本周波数が、都合よく fs/Nf_s/N の整数倍であってくれるわけがないだろ。

やる夫

つまり実戦では「漏れる」のがデフォルトなのかお。8.00 の鋭い1本の方が、奇跡的なラッキーケースだったんだお…。

やらない夫

そうだ。漏れをゼロにはできない。だが漏れ方を設計することはできる。それが手順 4、窓関数だ。

11.4 窓関数とその特性

やらない夫

矩形窓の弱点を言葉にするとこうだ。区間の端で信号を断崖絶壁でぶった切る。鋭い不連続には広い周波数成分が要る、というのは第1章のギブス現象や第3章の「短いものほど広いスペクトル」以来の馴染みの感覚だろ。あの重いサイドローブ(最大で本体のたった -13 dB)は断崖の代償だ。

なら対策は自然に思いつく。区間の端でなめらかにゼロへ絞る重み w[n]w[n] を掛けてから DFT すればいい。代表選手を3人紹介する。

ハン窓(hann。発案者 Julius von Hann から):

w[n]=0.50.5cos(2πnN1)(11.5)w[n] = 0.5 - 0.5 \cos\left( \frac{2\pi n}{N-1} \right) \tag{11.5}

ハミング窓(hamming。端をわずかに浮かせて第1サイドローブを打ち消す改良版):

w[n]=0.540.46cos(2πnN1)(11.6)w[n] = 0.54 - 0.46 \cos\left( \frac{2\pi n}{N-1} \right) \tag{11.6}

ブラックマン窓(blackman。cos をもう1項足してさらに裾を沈める):

w[n]=0.420.5cos(2πnN1)+0.08cos(4πnN1)(11.7)w[n] = 0.42 - 0.5 \cos\left( \frac{2\pi n}{N-1} \right) + 0.08 \cos\left( \frac{4\pi n}{N-1} \right) \tag{11.7}
やる夫

さっきのデモで hann に切り替えたら、たしかに階段状の裾がストーンと消えたお。けど代わりに、てっぺんの山が太くなった気がしたお。

やらない夫

よく見てた。それがこの節の核心、トレードオフだ。各窓の特性を並べる。メインローブ幅は「山の太さ」=近い周波数を見分ける分解能、サイドローブレベルは「裾の高さ」=漏れの少なさだと思え。

メインローブ幅(ビン)最大サイドローブ
矩形2-13 dB
ハン4-31 dB
ハミング4-41 dB
ブラックマン6-58 dB

サイドローブを下げようとするほど、メインローブは太る。分解能(細い山)と漏れ耐性(低い裾)は両方同時には良くできない

やる夫

なんでそんな意地悪な法則になってるんだお。

やらない夫

直観的にはこうだ。端をなめらかに絞るというのは、区間の端のデータを「ほとんど捨てる」ということだ。つまり実質的な観測時間が短くなる。観測が短いほどスペクトルがにじむ、これは第3章からの「時間幅×周波数幅は縮められない」そのものだろ。窓選びは情報を増やす魔法ではなく、限られた N 点の情報を、分解能に振るか、漏れ耐性に振るかの配分なんだ。

それが実戦でどう効くか、仕上げのデモだ。周波数の近い2つの cos 波を混ぜた信号で、(1) 周波数差 Δ を縮めていったとき、(2) 片方の振幅をどんどん小さくしたとき、それぞれどの窓なら2本に見分けられるかを試せ。

TWO-TONE RESOLUTION INTERACTIVE
振幅差 0 dB のまま周波数差 Δ を縮めると、メインローブ幅の限界で2つの山が1山に融合する(細い矩形窓が最後まで2山を保つ=分解能で勝つ)。逆に Δ=4 に戻して振幅差を 30 dB にすると、弱いトーンは矩形窓のギザギザのサイドローブに埋もれて消えるが、blackman に替えると裾が深く沈んで弱い山が顔を出す=何を見たいかで最適な窓が変わる。
やる夫

おもしろいお! 振幅が同じときは、矩形窓が一番ギリギリまで2山に分かれてて、blackman は早々にくっついて1山になっちゃうお。なのに振幅差を 30 dB つけたら立場が逆転して、矩形窓だと弱い方の山がギザギザの裾に飲み込まれて行方不明だお。blackman にしたら裾が深く沈んで、ちゃんと小さい山が顔を出したお。

やらない夫

それが「どっちの窓が優秀か」ではなく「何を見たいかで最適な窓が変わる」ということだ。使い分けの目安をまとめておく。

  • 近接した、強さの近い2成分を分離したい → メインローブの細い窓(矩形・ハン)。分解能勝負
  • 強い成分のそばの弱い成分を探したい → サイドローブの低い窓(ブラックマン)。ダイナミックレンジ勝負
  • 迷ったら、まずハン窓。分解能と漏れのバランスが良く、スペクトル解析の標準的な初手だ
  • 矩形窓が正解になるのは、信号が区間にちょうど整数周期収まると分かっている特殊な場合(同期計測など)くらいだ
やる夫

万能の窓は無いのかお。

やらない夫

無い。あったら誰も窓の名前なんて覚えてない。N 点という限られた持ち時間の中で何を優先するか、それを決めるのは道具ではなく解析する人間だ。——これで「FFT でスペクトルを見る」の中身が全部つながったな。アンチエイリアスフィルタで折り返しを防ぎ(第10章)、切り出しで必ず窓が掛かることを自覚し、目的に合わせて窓を選ぶ。ここまでできて、ようやく画面のスペクトルを信用していい。

この章のまとめ
  • スペクトル解析の手順: アンチエイリアスフィルタ → サンプリング → N点切り出し → 窓掛け → DFT(FFT)。DFT のビンは fk=kfs/Nf_k = k f_s / N 刻み
  • アンチエイリアスフィルタはサンプリング前のアナログLPFでなければならない。折り返しは混入した時点で分離不可能(第10章の帰結)
  • N 点の切り出しは矩形窓の乗算であり、スペクトルは窓スペクトル(sinc状)とのたたみこみでにじむ=スペクトル漏れ。周波数がビンにぴったり乗る場合だけ漏れが観測されない
  • ゼロ詰めFFTは表示を滑らかにするだけで、分解能は切り出し長 N が決める
  • 窓関数はメインローブ幅(分解能)とサイドローブレベル(漏れの少なさ)のトレードオフ。矩形 -13 dB / ハン -31 dB / ハミング -41 dB / ブラックマン -58 dB と裾が下がるほどローブは太る
  • 分離勝負なら細いローブ、微弱成分探しなら低いサイドローブ、迷ったらハン窓