[mbedbot] 録音音声をメモリに蓄積

April 01, 2017

結局今のmbedbotで取り込んだ音声はgoogleでもmicrosoftでも認識できなかったので、何とかして音声の品質を上げたい、と思ったのですが、BLEで送りつつ取り込む方法だとやはり通信速度がネックになって限界があるので、一旦メモリに音声データを全部取り込んでから、あとでまとめてPCに送る、という方法を試してみることにしました。

もし、サンプリングレートを8kHzにするのであれば、ADPCMが1サンプルあたり3bitとすると、8000*3/8=3000バイト/秒のメモリが必要になります。2秒だと6kByteです。HRM1017のRAMは16kByteらしいのですが、6kByteのサイズの配列をグローバル領域で確保しようとするとコンパイルエラーになりました。なぜこんなに少ないのか、と思って調べてみると、HRM1017はBLEスタック等の下回りで大量にメモリーを使うので、その分使えないようでした。さらに調べてみると、HRM1017はSoftdevice(プロトコルスタックや省電力のためのスケジューリングなどの実装)としてS130(BLEのPeripheral,Centralを含んでいる)を使用しているとのこと。今回はPeripheralしか使わないので、Pripheral/Broadcasterのみに対応したS110に変更できないか色々調査しましたが、なかなか情報が見つからなかったので、自分でmbedのオフラインコンパイル環境をこちらこちらを参考に作ってS110でコンパイルできないか試したところ、mbedのビルドツールに含まれる各ターゲットの依存関係を記述しているtargets/targets.jsonのHRM1017のところを編集するとS110でコンパイルできることがわかりました。

具体的には、

{
    "HRM1017": {
        "inherits": ["MCU_NRF51_16K"],
        "macros_add": ["TARGET_NRF_LFCLK_RC"],
        "release_versions": ["2"],
        "device_name": "nRF51822_xxAA"
    }
}

となっていたのを

{
    "HRM1017": {
        "inherits": ["MCU_NRF51_16K_S110"],
        "macros_add": ["TARGET_NRF_LFCLK_RC"],
        "release_versions": ["2"],
        "device_name": "nRF51822_xxAA"
    }
}

に変更しただけ(inheritsだけ変更)です。これでビルドすると、アプリで使えるメモリが2kbyteくらい増えて、合計8kByteほど使えるようになりました。

このバッファを利用して、サンプリング周波数をあげてメモリに取り込んでみたのですが、それでも8kHzは厳しいようでした。どこがボトルネックになっているかはわかりませんが、可能性としては、アナログ値の取り込み(AD変換)か、ADPCMへの変換、メモリコピーあたりが遅いのではないかと思われます。結局ノーウェイトで音声を取り込んでも4kHz弱が限界でした。

この方法に切り替えて音声を取り込んだものをgoogle,microsoftの認識エンジンで認識させてみたところ、少しですが認識率がアップしました。