tera-technology

プログラミングやIT技術中心のBlogです

ScilabでFFT(後編)

今回は前記事の続きでフィルタの作成から適用までを一通り解説しようと思います。

 こちらが前回の記事ですので見ていない方はこちらから見て下さいね

 

tera-tec.hatenablog.com

 この記事の目的は以下のようなことでした。

  • wavファイルをスペクトル解析して周波数成分を特定
  • ある周波数をカットするフィルタの作成

前回は音のデータに含まれている周波数を調べましたが今回はその含まれていた周波数のうち一部をカットするフィルタを作成したいと思います。ちなみに含まれていた周波数は494Hz, 587Hz, 784Hzの3つでしたね。このうち真ん中の周波数である587Hzをカットするフィルタを作成していきます。

 

フィルタを設計するにあたってFIRかIIRのどちらを使うかを決定する必要があります。

この2つがどんなものか軽く説明すると、FIRというものはFinite Impulse Response (有限インパルス応答) でIIRはInfinite Impulse Response (無限インパルス応答) の略です。両者の大きな違いとしては入力データを使う長さが違います。FIRはある決められた期間のみ入力データを使うのに対し、IIRはそれこそ無限に使います。FIRは主に信号に色を付けたくないとき、例えばオーディオなどに、IIRは信号の分離が重要となるとき、例えば無線の周波数などに用いられます。

今回は音声データを扱うということでFIRフィルタを選びました。

次にフィルタの種類を選んでいきます。フィルタの種類は以下のようなものがあります。

f:id:terakei818:20160510005416p:plain

ローパス(左上)は周波数の低域を通すフィルタで、ハイパス(右上)は逆に高域を通すフィルタです。さらにバンドパス(左下)は指定した範囲を通すフィルタで、バンドエリミネーション(右下)は逆に指定した範囲をカットする特徴を持つフィルタです。

今回は真ん中の周波数だけをカットしたいのでバンドエリミネーションフィルタを使います。

またFIRの設計法にも種類がありまして、以下のようなものが代表としてあります。

  • 窓関数法
  • 周波数標本化法
  • Parks-McClellanの方法(Remezの方法)

3つ目の方法が結構実用的なのですがフィルタを作っているときにうまく作れなかったのであえなく断念し、簡単な窓関数法を選択しました。(´・ω・`)

 scilabには便利な関数が用意されていてwfir()という関数があります。これを使うだけで簡単にFIRフィルタを作ることができます。早速使ってみましょう!

scilab

[h,hm,fr]=wfir();

と入力してみましょう。するとこんな画面が出てきます。

f:id:terakei818:20160510020017p:plain

GUIで設定を変更できるのはありがたいですね!フィルタタイプや窓関数の種類、サンプリング周波数にカットしたい周波数の範囲を入力します。Filter Orderとはフィルタの次数のことで、これが大きければ大きいほどフィルタの精度は上がりますが、計算量が多くなるので処理が大変になります。

このパラメータは各自でフィルタを適用させて結果を確認しながら変更していってください。ここでは例として上の画像のように設定します。

設定したパラメータでどんなフィルタになるかはViewのチェックボックスをクリックすることで簡単に確認できます。

f:id:terakei818:20160510012843p:plain

 

 コードの解説もします。hにはインパルス応答、hmにはシステム関数、frには周波数グリッド(周波数軸に対する1メモリの大きさ)が入ります。wfir()は引数でGUIで設定することができるパラメータを直接指定することもできるので繰り返し変更をするときはこっちを使った方がいいかもです。

フィルタの適用はこれまた簡単でインパルス応答とサウンドデータ(入力データ)の畳み込み積分を行うことでできます。これにはconval()という関数があるのでそれを使うだけです。めちゃくちゃ便利!!

最後は前編でやったのと同じようにフィルタ適用後のサウンドデータをFFTで周波数解析をして真ん中の周波数が消えてることを確認しましょう。上がフィルタ適用前、下が適用後です。

f:id:terakei818:20160510015631p:plain

きちんと真ん中の周波数だけ消えていますね。成功です!左の周波数が削れているのが気になる方はパラメータをいろいろいじってみてください。あと性能が同じならフィルタの次数は小さい方がいいです、その方が誤差が小さくなるので。ちなみに僕は399次まで落とすことに成功しました。

f:id:terakei818:20160510020432p:plain

最後は音声に出力して自分の耳で確かめてみてください。フィルタの効果を実感することができると思いますよ!

最後にscilabのサンプルコードを載せておきます。前回のコードの続きに描いていますので流れがわかりやすいと思います。

gist48a0e7cdb6028edfdfb3d7524b4c22d7

 

またまた長くなってしまいましたがこれでFIRフィルタを設計することができました。端折った部分や雑な解説でしたが参考にしていただけたら幸いです。