Visual Studio 2010 C# を使ってFFTを行う

森下功啓製作所 ONLINE

Microsoft社が無料で配布しているVisual Studio 2010 ExpressのVisual C#を使ってFFT演算クラスについての備忘録です。


FFT(高速フーリエ変換)をC#で行うためのクラスを作ってみました。 どうぞ使ってみて下さい。 設計思想的には、「簡単FFTとその結果の利用」を目指しています。 「サンプリング周波数の違いで結果の配列をどこまで取ったらどうのこうの~~・・・」 などと考えなくて済むようにしています。 また、帯域を指定してのパワーの取得やフィルタ操作が簡単にできるように工夫したつもりです。


プログラムパッケージのダウンロード

リリース日 プログラムパッケージ 更新内容 開発言語
2012/11/3 SpectrogramWithFft_20121103.zip

WAVEファイルを一定のフレーム数だけ呼び出してFFTを行い、それを画像化してスペクトログラムを作るサンプルプロジェクトファイルです。 できるだけソースコード数を減らすように心がけましたので、読みやすいと思います(たぶん)。 なお、本プロジェクトファイルはビルド済みなのでbinフォルダ内にある*.exeを起動させれば即実行可能です(セキュリティのため、ソースコードをビルドしてから実行することを勧めます)。 プロジェクトファイルを開いた後にライブラリファイルの参照設定でエラーが出るようなら、binフォルダ内にあるdllを参照するように設定し直して下さい。

スペクトログラム
Microsoft VC# 2010
2012/11/3 SignalLib_20121103.zip FFT関係のライブラリと、テスト用静的クラス及びテスト用のコンソールアプリプロジェクトのセットです。
以下、更新内容です。
  • [FFTdata構造体にて]Absの計算で冗長な部分があったので整理。ちっとだけ早くなったはず。
  • [FFTdata構造体にて]CompareTo()を実装し、比較に対応しました。これでパワー順にすばやく並べ替ることがList<>クラスを用いることで可能になりました。
  • [FFTresultクラスにて]プロパティに、MaxAbs, MedianAbsを追加
Microsoft VC# 2010
2012/6/17 SignalLib_20120617.zip 若干の更新と、テスト用静的クラス及びテスト用のコンソールアプリプロジェクトをソースコード付きで同梱しました。
以下、更新内容です。
  • Band構造体のコンストラクタにおいて、最低周波数が負値の場合に0とするようにエラー対策を追加
  • FFTresultクラスのメソッドGetFilterdResult()の綴りを間違えているのに気がついて、ついでにFilter()へ改名
Microsoft VC# 2010
2012/5/7 Signal_20120507.zip クラスライブラリを作ることを覚えましたので、クラスライブラリ(dll)にしてみました。
以下、更新内容です。
  • 名前空間をSignalProcessからSignal.FrequencyAnalysisへ変更
  • 独立ファイル化可能なクラス・構造体はファイルを分けて可読性を上げた(下図)。
ライブラリプロジェクトのファイル構成
図 ライブラリプロジェクトのファイル構成
ライブラリの利用方法は、プロジェクトの参照設定にdllを追加するか、以下の解説サイトにあるようにプロジェクトごと追加するかの2通りあります。
クラスライブラリの作成と使用方法(外部リンク)
前者の場合、そのままではコードを書いているときにメソッドの説明が表示されません。 表示させるためにはbinフォルダ内のXMLファイルもプロジェクトに追加してください。 なお、エラーを追っかけたい場合は後者の方法を採用してください。
Microsoft VC# 2010
2012/3/5 DFT_20120305.zip 色々と更新しました。 以下、更新内容です。
  • Windowing()メソッドで、矩形窓を指定した場合に全部0になるバグがあったのを修正
  • 名前空間をSignal_ProcessからSignalProcessに変更
  • Windowingは他の処理でも使うことがあるので、同じ名前空間にWindowクラスとして独立させた

  • それに伴い、ファイルを分割したので注意のこと
  • Band構造体のコンストラクタ生成時に、引数の異常を検出して例外をスローするように変更
  • 窓関数付の帯域パワー取得メソッド GetPSD(Band band, Window.WindowKind windowKind) を新設
  • FFTdata構造体に位相情報を追加
  • FFTウィンドウ幅を最小32になるように調整

  • 以前は条件によるものの、最小で2とされエラーがスローされることがあった。。。
  • 帯域を指定してパワーを得られる、GetPowerArray(Band band)とGetFilterdResult(Band band)を新設
  • 周波数の取り扱いをdoubleに変更
Microsoft VC# 2010
2011/12/02 FFTandWaveClass.chm サンプルプログラムのヘルプファイルです。
中にFFTを取り扱うDFTクラスのヘルプを含んでいるので参考にされて下さい。
Microsoft VC# 2010
2011/11/21 Signal_Process_class_20111121.zip コメントの見直し,一部の関数を整理,FFTdata構造体を少し改良してパワーを追加・・・を実施しました。
加えて、FFT後のデータを取り扱いやすくするためのFFTresultクラスを整備しました。

サンプルプログラムはこちら
サンプルプログラムでは、FFTの結果から音声データ中における発声部分を検出する機能を実現しています。 ご興味があればソースコードを読んでみて下さい。 自分なりに考えたアルゴリズムを実装しています。
 なお、グラフの描画をリアルタイムに実施するためのコードの改良や、FFTと同時にwaveファイルを再生する機能を追加しています。 ただし、副作用として64bit OSでは動かなくなりましたorz。
Microsoft VC# 2010
2011/3/6 Signal_Process_class_20110306.zip メソッド等に、<param>による説明文を追加しました。 コードの記述中に便利な案内が表示されます。 Microsoft VC# 2010
2011/2/23 Signal_Process_class.cs double型の実数配列や複素配列(クラス内に構造体を宣言済み)を使用してFFTを実施することが可能になりました。

サンプルプログラムはこちら
Microsoft VC# 2010
2010/5/29 fft_ver1.0_VCs2008.cs 初公開
とりあえず、実数データのみの場合に対応しています。
Microsoft VC# 2008

使い方(2011/11/21のリリースに関して)

先ずは開発中のプロジェクトにクラスファイルを追加して下さい。 追加後に、メインソースで使用できるようにusingを使用して名前空間を登録します。

その後は、下記の様に宣言と呼び出しを実行すればOKです。 newでのインスタンス生成時の引数は省略も可能です。 省略時には4096ポイントFFT,窓関数はハミングウィンドウとなります。 FFT実施時に引き渡しているtempは、double型の配列です。 この中に解析を行いたいデータを格納しておきます。

			DFT a = new DFT(DFT.FFT_point.size256 , DFT.Window.Perzen); // DFTクラスを宣言して、実態も確保
			FFTresult result = a.FFT(temp);                             // 実数配列を渡してFFT演算を実行。
		

FFTの実行結果は、FFTresultクラスオブジェクトに格納されます。 FFTの結果一つ一つはresult.GetData()メソッドの引数に要素番号を渡すことで得られます。 GetData()メソッドの返値はFFTresultPlusFreq構造体となっています。 この構造体はFFT()を実行時にサンプリング周波数を渡しておくと、FFTの結果とそのデータの中心周波数を結び付けてくれる便利な構造体です。 また、FFTの結果はFFTdata構造体で表現されており、リアルパート・イマジナリパート・絶対値・絶対値のLog10・パワーを要素に持っています。 なお、GetData()メソッドは将来的にはインデクサに置換するかも知れません。

サンプルプログラムは、waveファイルを読み出してFFTを実施するものです。 以下にスクリーンショットを示します。 FFTresultクラスには指定した帯域のパワー密度を返す機能も実装していますので、後処理は比較的簡単だと思います。

サンプルプログラム

クラスの詳細解説[2012/5/7更新]

FFTを実行するメソッドを実装したDFTクラスをSignal.FrequencyAnalysis名前空間内に置いています。 説明しようと思ったのですが・・・面倒ですので以下の図を見て想像してくださいw。 恐らく想像を逸脱するような名前は付けていないはずです。 詳細はソースコードをご覧ください。 コメントをかなり入れていますので初心者でも読むのに苦労はあまりしないはずですし、そもそも読まなくても使えると思います。 なお、鍵のかかっているメンバへはアクセスできません。

DFTクラスのクラスダイアクラム
図 DFTクラスのクラスダイアクラム

参考文献

inserted by FC2 system