自宅の近くに飛んでくる鳥の鳴き声を録音してみました。
録音はFreeBSDなMIPSルーターにUSBモジュールを接続して、Macの古いマイクを利用し自作のコマンドで行いました。録音フォーマットは44.1kHzの16BitモノでWAVEファイルにしました。
録音したものをMacのAudacityで開いてみるとこのようになっています。AudacityはApp Storeではなくインターネットからダウンロードしたものですが、開発者の証明書が貼ってあるようで、そのまま利用できるようです。
実際のデータはSoundCloudに上げてあります。
これの単位時間(0.1秒)のゼロクロスとパワーをざっくりrubyスクリプトで計算してみました。ゼロクロスとは波形データがゼロを通過するすなわち符号が逆転することで、パワーは振幅になります。雑音に比べて鳥の鳴き声は一般的に高い音が含まれるので、ゼロクロスが多くなるという理屈です。人間の音声認識でも使われる手法です。
WAVEデータのサンプルは無音が0で上下32767(0x7fff)から-32767(0xffff)まで変動します。Audacityの波形の1.0が32767で-1.0が-32767になります。
# check zero cross script
io = File.open(ARGV[0], "rb")
# skip wav header
io.seek(44)
i = 0
while TRUE do
sample = io.read(4410*2)
if sample.size != 4410*2 then
break
end
m = sample.unpack("s*")
zero = 0
power = m[0].abs;
num = 1
while num < 4410 do
if (m[num - 1] < 0 && m[num] > 0) ||
(m[num - 1] > 0 && m[num] < 0) then
zero = zero + 1
end
power = power + m[num].abs;
num = num + 1
end
sec = i / 10.0
power = power / 1000000
val = power * zero
print sec.to_s + "," + zero.to_s + "," + power.to_s + "," + val.to_s + "\n"
i = i + 1
end
結果
0.0,696,3,2088
0.1,660,3,1980
0.2,659,2,1318
0.3,774,2,1548
0.4,1343,13,17459
0.5,1311,10,13110
0.6,1314,11,14454
0.7,1270,8,10160
0.8,1317,9,11853
0.9,1172,4,4688
1.0,1096,6,6576
1.1,1057,4,4228
1.2,780,2,1560
1.3,661,2,1322
1.4,709,2,1418
1.5,626,3,1878
1.6,693,2,1386
1.7,707,2,1414
1.8,711,2,1422
1.9,750,2,1500
2.0,651,2,1302
2.1,673,2,1346
2.2,669,2,1338
2.3,654,3,1962
2.4,692,3,2076
2.5,830,3,2490
2.6,1063,4,4252
2.7,965,4,3860
2.8,988,4,3952
2.9,883,3,2649
3.0,807,3,2421
3.1,737,3,2211
3.2,800,3,2400
3.3,757,4,3028
3.4,712,3,2136
3.5,764,3,2292
3.6,798,3,2394
3.7,786,3,2358
3.8,761,3,2283
3.9,779,3,2337
4.0,724,3,2172
4.1,798,3,2394
4.2,740,3,2220
4.3,727,3,2181
4.4,737,3,2211
4.5,707,3,2121
4.6,722,3,2166
4.7,997,4,3988
最初が秒数で、次がゼロクロス数で、次が振幅の絶対値の合計を1000000で割ったもの、次が2番目の値と3番目の値を掛けたものになります。
振幅の合計を1000000で割っているのは数字が大きくなり分かりにくくなるためです。
FreeBSDではmixerコマンドでマイクのボリュームを変更できます。ボリームを変更するとゼロクロスはボリュームには影響しませんが、振幅は変わります。
最初の大きな鳴き声の0.4秒のところは、かなりきっちり判別ができますが、2.6秒や4.7秒の鳴き声は数字にはでていますが、微妙な感じです。何らか他の要素を加えないと判定は難しい気がします。
その時点の値ではなく、その直前の値との差で判断するのが良さそうです。
この録音はよく撮れた方で実際にはいろいろ試行錯誤が必要です。
とりあえず始まりを判定して適当な長さの録音を行い、それを認識ロジックに放り込むことを考えているので、終わりに判定は行いません。
鳥によって鳴くときの音量は違いますが、どの程度の距離にいるかでも違ってきます。8mのところと16mのところでは4分の1の音圧になります。周りの雑音にもよりますが、どの程度の距離までを対象にするかを検討する必要もありそうです。
これを始めたのは夏で、時間によっては蝉の鳴き声に消されてあまりうまく行えませんでした。また今年(2018)は猛暑で鳥が少ない気がします。涼しくなると夜中は鈴虫などが入ってきてしまうのでしょうね。
自動観測は24x7でやるのは無理があり、環境雑音の評価や天候なども考慮して、行うのが良い気がします。天候の情報は天気概況などをネットから拾って判断する方法もあると思います。
鳥の鳴き声録音用のAndroidアプリも作ってあるのですが、こちらは録音開始と停止を人間が行い、停止前5秒を保存するようにしてあります。
AudacityはpluginがPythonで書けるようなので、このロジックの検証用のpluginがあると良いのですが、python分からないので作れません。