音響カメラが欲しいという話その2
皆さんこんにちは。まさか2が出るとは思っていなかった作品とかあると思いますが、これが続くとは思っていなかった者です。前回は同じ音源の時間をずらして、2つの音声データをずらしてそこから逆算してどの程度ずらしたかどうか計算するソフトを作っていました。
しかしです、当然そんな理想的な条件はあるわけでもないので実用的ではないわけですので今回はより実用的な条件で位置を特定してみよーというわけです。
今回の目的
というのは実際に2つのマイクを用意し、同時に録音したデータから時間差を計算するという事です。実際の音響カメラは数百単位のマイクを利用している訳なのですが、多分やっていることは似たようなもので2つの場所がわかっているマイクに届く特定の周波数の音がどの程度ずれているかを計算することだと思っています。という事で最小の構成である2マイクで作ってみよーと思ったわけです。
ハードってどうしようか
いままではテキトーに撮っていた音声データ1個があれば何とかなってきましたが、今回の実験ではマイクというリアルな物体が必要になってきます。市販のマイクとかだとまず値段がそこそこしますし、そもそも生のデータってどうやって取り出すのかわからないんですよね…
完……とするわけにもいかないので、学生の頃に利用していたArduinoさんに活躍していただくことにしました。Arduinoは簡単に言いおうとすると難しいのですが、今回の音データの処理に必要なセンサー(今回だとマイクがそれにあたります)を簡単に取り扱ったり、センサーとPCを接続するためのものと思っていただければと。
ちなみにアマゾンで調べますと無限に出てきますので、ご購入される方はまずここからでもいいのではないでしょうか?
次に肝心のマイクなのですが、これは流石に持っておりませんでした。という事で秋月電子さんに出撃しデジタル式のものとアナログ式の2つのセンサーを購入してきました。アナログ式の物はSPU0414HR5Hとかいう型番で、デジタル式の物はSPM0405HD4Hとかいう物です。
ちなみにネタバレになってしまいますが、デジタル式は私の技量がなかったのでお蔵入りになりましたので、今回のことを再現したいと思った方はとりあえずアナログを買えばOKです。ただしArduinoのアナログ端子は6つしかありませんので、それ以上のセンサーを取り付けたいときはその時考える必要があります。
これでマイクとそれをPCに入れるハードがそろったーと思っていたのですが、実際には以下の物も追加で必要になりました。
・はんだごてセット
・2.54mmピッチのピンヘッダ:デジタルの方はあるのになぜかアナログの方はついてない…
・ブレッドボードとジャンパー線
・抵抗とかコンデンサーとかのセット:今回は670Ωと10kΩの抵抗、47uFのコンデンサーを利用しました。なぜか家に会ってよかった。
・オペアンプ:なんとなく察されているかもしれませんが、信号がしょぼすぎてどうしようもなかったので必要です。
秋葉に行くにも金かかるんだから初めからいるって言ってよーと思いました
まずマイクをArduino で使おうというところから
始める必要ありますね。秋月電子さんは優しいことにこんな小さなマイクに対しても取説がついているのですね…
2行にまとめると
・ピンをつけてね
・ふつうは裏面の端子をショートさせてね
という事でしたので早速それを実行。全く難しいものではないのでとりあえずこれはクリア。早速配線してArduinoにぶち込んだ結果…
![](https://assets.st-note.com/img/1717314606433-w7r7YcIhUw.png?width=1200)
マジで何も信号が出ない!完!
となりそうだったのですが、ここでおばあちゃんの知恵袋、感度が低いなら増幅すればいいという事を思い出し、こんな感じに変換。
![](https://assets.st-note.com/img/1717314907509-QeZmEyrUyV.png?width=1200)
なぜか家にオペアンプがあってよかったですね~
一回マイクから出た電圧を増幅してやりゃええやないかという事でこんな感じにしてみました。
なんとなくこれでいんじゃないか?と思われるかもしれませんが、これDC成分も倍増しれしまうんですよね…欲しいのは変動する成分なのに…という事でR1-GND間にコンデンサーを取り付けることをお勧めしております。
まあそんなこんなでやっとこさアナログ式のマイクを使うことができるようになりましたので、これを同時に2つ使って音のずれ量をチェックしようではありませんか
2つのマイクをつけてみよう
というところにアップデートするわけですが、こんなのはめちゃ簡単。
2個くっつければいいだけですなHaHaHa
音のずれ量を計算しよう
ここまでできてしまえば音響カメラ1の記事と同様に計算すればいいわけですね…一言でまとめますとFFTしてピークの周波数を計算してその位相差から時間を計算するというわけでございます。
幸いArduio につきましては普通にarduinoFFTという神ライブラリがありますので、ここでも特に何もせずCtrl+CとCtrl+Vがあればソフトは完成させることができると思います。
あ、ただ一点困ったことがございまして、どうやらArduinoがアップデートしたそうです。バージョン情報を見ると2.x.xのようになっていたのですが、1.x.xの構文と異なっているようです。ネットで"Arduino FFT"とかで調べると無限に記事が出てきますが、結構1.x.xの情報で書かれているのでそのままコピペしようとするとエラーで止まってしまいます。
ということで下のような構成で書いてあげればOKでございます。
#define SAMPLES 256 //Must be a power of 2
#define SAMPLING_FREQUENCY 8000 //Hz, must be less than 10000 due to ADC
float vReal[SAMPLES];
float vImag[SAMPLES];
ArduinoFFT<float> FFT = ArduinoFFT<float>(vReal, vImag, SAMPLES, SAMPLING_FREQUENCY);
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
FFTL.windowing(FFTWindow::Hamming, FFTDirection::Forward); /* Weigh data */
FFTL.compute(FFTDirection::Forward); /* Compute FFT */
FFTL.complexToMagnitude(); /* Compute magnitudes */
float peak = FFT.majorPeak();
}
裏話的な事なのですが、今回の音響カメラの目的としては鳥さんの位置がわかればいいだけですので、
1,特定の周波数を決め打ち
2,習得したデータをその周波数でフーリエ変換する
3,sin成分とcos成分の日から位相を計算する
という事を考えておりました。で、なんでこんなことをするかといいますと明らかにFFTの計算コストが高いとわかっていたからです。
![](https://assets.st-note.com/img/1717423206205-kQilF6WETg.png)
現代のPCくらいの処理能力があれば何ら問題ないと思いますが、マイコン程度のパワーではあまり負荷をかけてしまいますと1秒に1回とかしか計算ができなくなってしまうとか考えられます。特に今後マイクの数を増やすとしたらその問題は深刻になることは明らかです。
Arduinoで電圧を読み取る際には0~1023までのint型で出力されます。このため例えば正弦波からは歪んでしまいますが、疑似的に整数型で特定の周波数風の波型の配列を用意し、それと収録した音データを掛け合わせて総和計算する方法を考えました。
![](https://assets.st-note.com/img/1717423875217-wkFRoLbeNT.png?width=1200)
このようにするとfloat型の計算は不要で、ただの掛け算、足し算にすることができますね。という風に思っていたのですが、これをエクセルでシミュレーションした結果結構位相差がついてしまうことがわかり、とりあえず現実的ではないなという事がわかりましたので却下してしまったというわけでございます。
まあそのような試行錯誤?を行った結果、無事に音源の位置に応じて特定の数値を出すものができました。詳細は下の動画を見ていただければ明らかで、音が出ているスマホを動かすと後ろのPC上に表示されているグラフが変化していることがわかると思います。
例の音響カメラの件
— TouhuyaTom (@touhuyatouhu) June 2, 2024
スマホから音を鳴らすとその方向にを検知する系のものを作っていましたので今日の鳥さん撮影は無しです pic.twitter.com/EgN6LnkkB1
2マイクで分かった反省点
これを3マイク以上にすることができれば位置を特定できるんじゃない?とか思いますが、実はそーでもなさそうと思っております。その理由をいくつかあげたいと思います。
解像度が低い!
まあArduino ではしゃーないことなのですが、Arduinoのアナログ読み込みは0~5Vまでを1024等分しておりますのでいわゆる10bitの分解能しかないんですよねー
要するにハイレゾではなく、ラジオくらいの音質しか出てないというわけです(?)。その結果当然精度が出ないというわけでございます。
これを解決するにはこのAD変換部の解像度が高いESP系の開発ボードを使うとかする必要がありそうですね…あちらは12bitなので4倍細かく電圧を測れるんですよねー
マイクの感度が低い!
これはアンプ部分をどうにかすればいいと思うのですが、普通に感度低すぎてノイズの方が大きかったり、動画のように音源とマイクが激地かな条件ではないとまともに動作しないんですね…
今回は家にある適当な材料で作成したのですが、きちんと秋月さんのアンプキットを参考にまともな増幅回路を作っていきたいと思います。
これらを改善することでより精度の高い位置情報の特定をすることができると思っております。
まずは上記の改善点を実施⇒3マイクでの検証と進めていきたいと思います。
今週出来たところはこれくらいでしょうか……
また続きがありましたらこちらにUpしようと思います
ではまた
この記事が気に入ったらサポートをしてみませんか?