PaPeRo iのカメラとマイクでリアルタイムモニタではPaPeRo iのマイク音声をWebブラウザで音声再生してみましたが、画面にグラフ表示できるか試してみました。
音声データの取得とブラウザへの送信
今回もアプリの作成にはGolangを使用しました。マイクからの音声データの取得とブラウザへの送信方法は、音声再生する場合と全く同じで、
/usr/bin/arecord -
で標準出力から取り出した8kHzサンプリング8bitモノラル音声を、0.1秒分800バイトごとにブラウザに送ります。このためにGorilla WebSocketを利用した音声データ専用のWebSocketサーバを動かします。
音声のグラフ表示
ブラウザでのグラフ表示には、センサー値をリアルタイムグラフ表示するでも使用したSmoothie Chartsを使用しました。使い方は、表示領域用にcanvasを用意し、
<html lang="ja">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/smoothie/1.34.0/smoothie.js"></script>
<script type="text/javascript" src="/_graph.js"></script>
<title>
graph
</title>
</head>
<body>
<canvas id="graph1" width="1000" height="400"></canvas>
</body>
</html>
JavaScript側では初期化を
var chartData1 = new TimeSeries();
var chart1 = new SmoothieChart({interpolation:'linear'});
chart1.options.minValue = -1.0;
chart1.options.maxValue = 1.0;
var startChart = function () {
chart1.addTimeSeries(chartData1, {
strokeStyle: 'rgba(0, 255, 0, 1)', // 0-2-0
lineWidth: 4 });
chart1.streamTo(document.getElementById("graph1"), 1);
chart1.start();
chart1.options.millisPerPixel = 1;
};
としています。Smoothie Chartsのスクロール速度は最高で1ピクセル/ms、つまり1kHzサンプリングということになり、8kHzサンプリングの全データを表示することはできませんでした。こうした場合、本来であれば1kHz以上の信号をローパスフィルタでカットする必要がありますが、省略しています。
音声データ受信時にはWebブラウザで音声再生する場合と同じく32bit floatの配列に変換したものを利用し、
function ui8ary2f32ary(inbuf) {
var sz = inbuf.length;
var res = new Float32Array(inbuf.length);
for (var j = 0; j < sz; j++) {
res[j] = (inbuf[j] - 128) / 128.0;
}
return res;
}
function dispBlock(adat) {
var nowdate = new Date();
var now = nowdate.getTime();
for (var j = 0; j < adat.length; j+=8) {
chartData1.append(now+j/8.0, adat[j]);
}
}
wsaudio.onmessage = function(event){
var ui = new Uint8Array(event.data)
var fa = ui8ary2f32ary(ui);
//playBlock(fa);
dispBlock(fa);
}
と8個とびにデータをグラフコントロールに追加しています。
動作確認
ソースとコンパイル済みバイナリをこちらに用意しました。paperosoundgraph/paperosoundgraphをPaPeRo iに転送し任意の場所で実行してください。ブラウザで
PaPeRoのIPアドレス:8865/graph
を開き、音声チェックボックスにチェックを入れるとパペロの音声が画面にグラフ表示されます。
話しかけたり頭を撫でたりするとリアルタイムで表示され、遅延は体感で300ms程度に思われました。