チュートリアル 25:分析
FFTの使用

フーリエの定理

フランスの数学者ジョーゼフ・フーリエは、どんな周期的波動でも、各々別個の振幅と位相をもつ調和関係(整数倍の周波数)にあるサイン波の総和として表されることを証明しました。周期的波動のデジタル的表現を与えられると、離散フーリエ変換(DFT)として知られる公式を用いることによって、波動のサイン波成分の周波数、位相、振幅を計算することができます。本質的に、DFTは音波の時間領域での表現を周波数領域でのスペクトルに変換するものです。

一般的に、フーリエ変換は時間の小さな「スライス」(理想的には分析されている波形の正確な1サイクルに等しいもの)の上で行われます。「現実的な世界」のサウンド(ほとんどの場合、厳密に一定の周期ではなく、周波数はわかっていません)に対してこの操作を実行する場合、連続したタイムスライスに対してDFTを実行することによって、時間軸上でのスペクトルの変化の動向を探ることができます。

各々のタイムスライスのデジタルサンプル数が2のべき(累乗)である場合、高速フーリエ変換(FFT)と呼ばれる、DFTのより速いバージョンを使用することができます。FFTの公式は、fft~ オブジェクトにカプセル化されています。

フーリエ変換の数学的な解説は、このマニュアルの範囲を越えています。そこで、チュートリアルのこの章では、シグナル解析のための fft~ オブジェクトの使用法について説明します。

シグナルのスペクトル:fft~

fft~ はインレットでシグナルを受け取ります。fft~ は受け取った各々の時間のスライス(デフォルトでは512サンプルの長さ)に対して、同じ長さの各周波数領域でのエネルギー量のリストのシグナルを送ります。fft~ から出力されるシグナルは、「何かを聞くためのもの」ではありません。むしろ、「異なる512の周波数帯における、受信シグナルの相対振幅のリスト」なのです。この「リスト」は、たまたま各々のタイムスライスで受信されるサンプルと全く同じ長さなので、受信したシグナルと同じ速さ(レート)で出力されます。fft~ から出力されるシグナルは、直前のタイムスライスで受け取ったサンプルの周波数領域での解析結果です。

変換はシグナルの形でfft~ から出力されますが、それは時間領域のシグナルではありません。この特別なシグナルを「理解する」唯一のオブジェクトはifft~ オブジェクトです。これはスペクトルに対して逆FFTを実行し、それを時間領域の波形に逆変換します。


fft~ から出力されるシグナルは時間領域のシグナルではなく、スペクトル情報です

capture~ オブジェクトによって、fft~ のアウトプットを捉え、シグナルの周波数分析をすることができます。

ezdac~ オブジェクトの1つをクリックし、オーディオをオンにして下さい。

オーディオがオンにされたとき、dspstate~ は中央のアウトレットからMSPサンプリングレートを送り出します。この値は、ちょうど512サンプルの周期を持つ周波数を計算するために使われます。これがFFT自身の基本周波数です。fft~ にこの周波数の波を送った場合、各々のタイムスライスは波形のちょうど1サイクルを含むことになります。ここでは実際に、その10倍の周波数をもつコサイン波を、分析のためのテストトーンとして使用します。


テストトーンの周波数はFFT自身の基本周波数の10倍です。

パッチャーウィンドウの左上隅では、fft~ の非常にシンプルな使用例を示しています。分析結果は capture~ オブジェクトに格納され、ifft~ オブジェクトは分析結果をオーディオシグナルに再変換します。(通常、このように理由もなくオーディオシグナルの変換、逆変換を行うことはないでしょう。このパッチでは、ifft~ は単に分析・再合成プロセスの働きを説明するためだけに用いられています。)

・パッチの左上の toggle をクリックして、再合成されたサウンドを聞いて下さい。再び toggle をクリックして gate~ をもう一度閉じて下さい。すぐに、パッチのその部分にある capture~ オブジェクトをダブルクリックして、fft~ によって実行された分析結果を見て下さい。

capture~ テキストウィンドウの最初の512の数は、全部0.0000になっています。これは、fft~ が最初のタイムスライスを分析している間の出力です。送り出される分析結果が1つ前のタイムスライスのものであることはぜひ覚えておいて下さい。最初にオーディオがオンになった時点では、それ以前にはオーディオが存在しないため、fft~ の分析結果はシグナルが無いことを示しています。

・最初の512個の数をスクロールさせて下さい(capture~ のテキストウィンドウはブロックごとに分かれているので、シグナルベクタサイズが256ならば2つの数値のグループはすべて0.0000になるはずです)。2番目のタイムスライスの512個の数を見て下さい。

512個の数値の各々は、FFT自身の周波数の高調波(第0次高調波(0Hz)から開始されます)を表しています。分析結果は第11番目の数でエネルギーを示していますが、これはFFTの第10次高調波を表し、サンプリングレートの 10/512 (まさに、テストトーンの周波数)です。(分析結果はまた、最後から第10番目の数でエネルギーを示していますが、これはサンプリングレートの 502/512 を表しています。この周波数は、ナイキスト・レートを上回っていて、サンプリングレートの -10/512 と同じです。)

技術的な詳細: FFTは、得られる周波数領域の全体を各々のタイムスライスのサンプル数と同じ数の帯域に分割します。従って、fft~ から出力される512の数値の集合の1つ1つは、0からサンプリングレートまでの周波数範囲を512分割したものを表しています。最初の数は、0Hzでのエネルギーを、第2の数は、サンプリングレートの1/512の周波数帯でのエネルギーを、第3の数は、サンプリングレートの2/512の周波数帯でのエネルギーを、・・・(以下同様)、という形で表しています。

第257番目の数値(サンプリングレートの 256/512)でナイキスト・レートに達してしまうと、それ以降のすべての数値は、ナイキスト・レートで「折り返され」てしまう点に注意しなければなりません。これについてのもう一つの考え方は、これらの数値が負のナイキストレートから上昇してくる負の周波数を表すと考えることです。こう考えると、第258番目の数値は、ナイキスト・レートからサンプリングレートの1/512の値を引いたものになります。(これはまた、サンプリングレートの-255/512と考えることもできます。)この例では、第11番目(サンプリングレートの10/512)と第503番目(サンプリングレートの -256/512 - -246/512) = -10/512)の周波数領域でエネルギーを見ることができます。

このようにして、fft~ が正確にシグナルを分析していることがわかります。しかし1つだけ問題があります・・。

FFTの実際上の問題

FFTは分析されているサンプルが周期的波動の1サイクルを含んでいるとみなします。前の例では、コサイン波はFFTの基本周波数の第10高調波だったので、FFTはうまく機能しました。しかし、ほとんどの場合、FFTの512のサンプルは波の正確な1サイクルではありません。このような場合でもなお、FFTは512のサンプルを波の1サイクルとして分析し、その波のスペクトルを出力しようとします。この分析結果には、実際のシグナルでは存在しないような多くの偽の周波数が含まれてしまいます。

capture~ のテキストウィンドウを閉じて下さい。オーディオをオンにしたままで、"Test Frequency" ナンバーボックスを1000にセットして下さい。これはまた、パッチの左上の clear メッセージをトリガし、capture~ オブジェクトの前の内容を消去します。もう一度 capture~ をダブルクリックし、テキストウィンドウをスクロールして新しい内容を見て下さい。、

1000Hzの音の分析結果は1000Hz(MSPサンプリングレートが44,100Hzならば、第12番目と第13番目の周波数領域)で、他より大きなエネルギーを示しますが、実際には、同時に他のすべての領域でもエネルギーを示します。この分析結果は、もはやサイン波ではありません。(正確なサイクル数が512サンプルと正確に一致していません。)このFFTで示されるすべての他のエネルギーは、これらの512サンプルを波の正しい1サイクルとする「不正確」な解釈によって生じた人為的なものです。

この問題を解決するために、振幅エンベロープを適用して各々のタイムスライスの末端を「先細り」にし、さらにエンベロープの使用を補正するためにタイムスライスのオーバーラップ(重ね合わせ)を試みてみましょう。

FFTのオーバーラップ

チュートリアルパッチの右下の部分は、この「タイムスライスのオーバーラップを使用する」というアプローチをとっており、各々のスライスを分析する前に三角形の振幅エンベロープを適用しています。(多くの場合、他の振幅エンベロープの形がこの処理のために使用されます。三角形のウィンドウはシンプルで、かつ効果的です。)この方法では、fft~ オブジェクトは、各々のタイムスライスを、その端を先細りにする三角形のウィンドウを通して見ることになり、波の不連続によって生じる多くの偽の周波数をフィルタにかけています。


100Hzのコサイン波に適用された、オーバーラップする三角形のウィンドウ(エンベロープ)

この「窓関数」の適用とタイムスライスのオーバーラップを実現するためには、どちらが一つがもう一方より256サンプル後ろにオフセットされているような2つのFFTを実行しなければなりません。(fft~ はベクタサイズの倍数によってしかオフセットされないので、パッチのこの部分はMSPシグナルベクタサイズが256かそれ以下のときにのみ動作する点に注意して下さい。)FFTのオフセットは fft~ の(3番目の)タイプイン・アーギュメント(書き込まれたアーギュメント)として与えられ、右側の fft~ オブジェクトによって実行されます。この結果、タイムスライスのオーバーラップを実現することができます。

窓関数の適用は、FFTと同じ周波数(512サンプルごとに1回)で繰り返される三角形の波形(buffer~オブジェクトに格納されています)をシグナルに掛け合わせることによって行われます。ウィンドウは、2番目のfft~ のために1/2サイクル(256サンプル)オフセットされます。

buffer~オブジェクトをダブルクリックしてその内容を見て下さい。その後、buffer~ ウィンドウを閉じて、窓関数を適用されたシグナルのFFTの内容が格納されたcapture~ オブジェクトをダブルクリックして下さい。最初のブロックか2つの数値グループをスクロールして、窓関数を適用された1000Hzの音の、FFTの分析結果を見て下さい。

窓関数を用いていないFFTと同様にエネルギーは1000Hzのあたりで最も大きくなっていますが、ここでは、すべての他の周波数領域での(偽の)エネルギーは、窓関数を用いていないバージョンと比べて非常に減少しています。

FFTを用いた信号処理

このパッチでは、シグナルを見たり、分析したりするために、またシグナルに窓関数を適用してFFTをオーバーラップする効果を説明するために、fft~ オブジェクトを用いました。しかしまた、fft~ から出力されるシグナルを変換するようなパッチを書くこともできます。そして、再合成のために ifft~ に対して変換された分析結果を送ることもできます。このような周波数領域をフィルタリングする方法の実装例は、後のチュートリアルで見ることができます。

まとめ

高速フーリエ変換(FFT)は、時間領域のデジタルシグナルを、周波数領域での表現(シグナルの中の異なる周波数領域間の相対振幅による表現)に変換するためのアルゴリズムです。FFTは、シグナルの比較的小さい「部分」(通常512または1024サンプルの長さの時間のスライス)を使用して計算されます。より長いシグナルを分析するためには、連続した(またはオーバーラップされた)タイムスライスを使用する複合FFTを実行します。

fft~ オブジェクトは、受信したシグナルのFFTを実行し、受信シグナルの周波数領域の解析結果を(これもまた、シグナルの形で)送り出します。fft~ のアウトプットを理解する唯一のオブジェクトはifft~ で、これは周波数領域の情報に基づいて時間領域のシグナルを合成するために逆FFTを実行します。スペクトルを変化させるために、fft~ から ifft~ へ送られる間にシグナルに変化を与えることができます。

ちょうど1サイクル(またはサイクルのちょうど整数倍)の音を分析するときにだけ、FFTは完璧に作用します。他の場合に作り出されてしまう人為的な数値を減らすために、各々のタイムスライスの末端を先細りにするような振幅エンベロープを利用して、分析するシグナルに「窓関数」を適用することができます。cycle~ オブジェクトを利用して、FFTと同じレート(すなわち、各タイムスライスにつき1回)で繰り返しbuffer~ から窓関数を読み、それをシグナルに乗じることで振幅エンベロープを適用することができます。

参照

buffer~ オーディオサンプルを格納します
capture~ シグナルをテキストとして見るために格納します
fft~ 高速フーリエ変換
ifft~ 逆高速フーリエ変換