arduinoでFFTをトライ22010/04/12 00:56

参考元のcのfftアルゴリズムでは、入力データはfloat型で定義されているが、これでは少々メモリを食うのでなんとかしたいと考えていた。int型で定義して、これを3桁の整数(256まで)と3桁の小数とみなして使用する事を考えたりもしたが、少々面倒な事になりそうなので、まず単純にfloatをintにした状態で精度を検証してみる事にした。その時のソースはこちら

■検証方法
あらかじめEXCELで入力データを用意して、これをシリアル画面からinputして、arduinoでfftを行う。同じデータをfftを行うEXCELマクロに入力して、両者のfftの処理結果の比較を行う。
※使用するEXCELマクロは下記で公開されているものを使用させて頂いた。
 Excel で学ぶ理論と技術 フーリエ変換入門
 http://brain.cc.kogakuin.ac.jp/~kanamaru/research/books-j.html
EXCELで用意したデータは、周波数がそれぞれ46.9Hz、937.5Hz、2187.5Hzの正弦波を重ねた値とした。arduino側は、マイクから値が入力された事を想定して、512付近を0とみなして処理する事とした。

■検証結果
比較した結果をグラフにしてみると、以下の通りとなった。検出した周波数成分のピーク位置が一致することが確認できた(絶対値で見た場合の話)。


他にも色々な周波数でデータを作成してみたが、だいたいイケてそうだった。その方面の学校の先生に見せたら激怒されそうな内容だが、お手軽認識なのでfftロジック的にはこれで良しとした。

■課題
検証の途中で気付いてしまったが、8khzまでの音をfftで周波数解析するなら、16khz向けにサンプリングしないといけなかった。根本的なミスだ…
サンプリング間隔を125μsから半分の63μsにすれば、8khzの音まで解析できるが、サンプリング数は256個で変更できないので、分解能が倍の62hzになってしまう。ちょっと認識精度としては落ちてしまう感じだ。

■今後の展開
ある周波数成分が発生していたらこの様なアクションをする、という事を定義すれば、当初目指していた機能が実現できそうだ。
データ数は256個までという制約があり、63us間隔でサンプリングする想定なので、1回の検出では16msの時間に起きた出来事しか分からない事になる。
計測した所、fftの処理時間は1回あたり約13 msなので、10回程繰り返して検出を行い、周波数成分毎にパワーを積み上げて、一定の価を越えていれば「あの音が鳴ってる!」と判断するのが良さそうだ。

この判断の基準にする周波数成分も、事前に用意するのは大変なので、学習出来るようにしたい所。学習モードで取得した音の周波数成分をライブラリとして保存しておき、これと入力値を比較して、ライブラリの0.8割か0.9割程度のパワーを越えていたら認識したと判断するようにしたい。
さらに発展させて、周波数成分の発生順序とかを学習パターンとし、検出するサンプリング数も十分多くすれば、音声認識も可能かもしれない。が、ちょっとaruduinoでは厳しそうだ。

ここらでブレッドボード上に実装したマイクから実際の音を拾って、それを入力データとして使って試してみたい所だが、マイクが無い…という事で、つづく

【2010/05/06 追記】
重大なミスが確認された。解析対象の値はAnalogRead関数で取得する予定だったが、値を読み取る処理に100μs必要とするのだ。(arduino日本語リファレンス参照)つまり、Arduinoでの音のサンプリングは10khzまで、周波数解析は5khzまでが上限となる。

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://isa.asablo.jp/blog/2010/04/12/5011864/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。