Arduinoを用いて楽曲認識を行おうというパッとした思いつきですが、なかなか難しいことがわかってきました。
フーリエ変換のプログラムを1から組む気にはならなかったのでさっそくライブラリを探してみました。
http://wiki.openmusiclabs.com/wiki/ArduinoFFT
まずはこのライブラリを試してみます。というより実際に試している方がいるみたいなので取りあえず先人の知恵を借りて同じ装置を組み立ててみます。
あまり書く必要はないのかもしれませんが使ったもの
- Arduino Uno R3
- ジャンプワイヤ
- ブレッドボード
- エレクトレットコンデンサマイクモジュール(SparkFun社製)
- エレクトレットマイクアンプモジュール(Adafruit社製)
エレクトレットコンデンサマイクはArduinoを用いて音声入力をするモジュールとしては非常にすばらしいものですが非常にデリケートなので静電気などに注意してください(自分は製作中に一つ吹っ飛ばしました)
配線図は次のようになります。今回使ったAdafruit社製のマイクのパーツの図がなかったので、SparkFun社製のマイク(https://www.switch-science.com/catalog/374)の図で配線図を書いています。
ちなみに2つのマイクの違いは搭載されているアンプが音声信号を増幅する倍率が異なっている点です。Adafruit社製のマイクは25~125倍、SparkFun社製のマイクは100倍となっています。配線的には大きな違いはないので実験するときはどちらでもよいと思います。
つぎにライブラリですがArduinoのライブラリフォルダに入れるか、スケッチが含まれるフォルダに入れておいてください。(FFTライブラリがライブラリフォルダに入れる場合は#include <FFT.h>、スケッチが含まれるフォルダに入れる場合は#include “FFT.h”をソースコードの先頭に記述してください)。サンプルコードはダウンロードしたライブラリに含まれるExampleフォルダにあるfft_adcを使いました。
あと、ライブラリに更新がかかっている可能性があるため、読むのはかなりしんどいですが何番ピンで音声データを入力しているかできれば確認してください。
最後に自分がこのスケッチを実行した結果ですが、フーリエ変換そのものの知識が少ないため断定できないのですが、スピーカーから同じ音を聞かせたときの返ってきたデータを見る限り毎度返ってくるデータが違っていました。
iPhoneのスピーカーから出した音を聞かせたのですがもう少し環境を良くするべきかな…。
何にせよ、同じ音を聞かせたときの結果に再現性+実時間に近いFFT実行速度が欲しかったため今回の楽曲認識プロジェクトでは不採用になりそうです。(このライブラリではどこまで実時間で実行できているのかは実力不足で検証できませんでした。)
完成させるまでの残り時間を考えると乗り越えないといけない壁が多すぎて、これ以上このライブラリを追求せず別の方針(スペクトルアナライザー)を考えるつもりですが同じようなことを考えている誰かの助けになれば幸いです。
ちなみにフーリエ変換をArduinoで行うとき、なるべく早い処理(実時間での実行)を求めるならバタフライ演算を実装しているライブラリを選ぶこと+スケッチの行数を気にしてなるべく減らすこともポイントとなると思います。
バタフライ演算はFFTの対称性を利用した高速化のアルゴリズムです。計算回数が減ることによる高速化とそれによる誤差の減少が期待できます。
Arduinoの処理はC++風の言語から機械語に変換されるときに処理に時間がかかります。FFTのライブラリ、サンプルコードにも高速化のために一部にアセンブラ風の記述があります。(アセンブラは今まであまり読む機会がなかったためソースコードが読めなくて挫折しました。おそらくマイコンに直接命令をかける記述だと思うのですが…。)
つまり、FFTほど重い処理になると、たった1関数でさえも処理結果に影響する可能性があるということです。特に重い処理の例としてデータの確認に利用されるSerial.print()関数があります。フーリエ変換の結果を実際に比較したわけではないですが、サンプルコードでさえ実行時間に配慮されたコーディングがされていたため、ソースコードの大きさは少なからず実行時間に影響はあると思います。