スキップしてメイン コンテンツに移動

SimpleVoxのあとがき

本文はなくてもあとがき

はじめに

M5Stack(ESP32)向けにSimpleVoxというライブラリを開発しました。折角の記念に実装に当たってのこぼれ話のようなものを書いておこうと思います。

SimpleVoxは音声認識、とりわけ孤立単語音声認識(Isolated word recognition)の機能を提供するライブラリです。本ライブラリはVAD(Voice Activity Detection)、音声からのMFCC(Mel-frequency cepstral coefficients)の計算、および2つのMFCC間の距離を計算するためのDTW(Dynamic Time Warping)などの基本的な機能を提供します。

実際のところ、より優れた方法やアルゴリズムは他にも存在しますが、M5Stack(ESP32)のようなリソース成約のあるデバイスでの音声処理ライブラリは充実しているとは言えず、本ライブラリは選択肢の一つになるかと思います。

参考までに以下に紹介のあるESP-SRでは学習済みのモデルを使って200以上のコマンドを識別できるそうです。

Unleashing the Power of OpenAI and ESP-BOX: A Guide to Fusing ChatGPT with Espressif SOCs

本ライブラリでは同様のことを実現するのは難しいですが、自分のためのいくつかのコマンドに対応することは比較的容易です。したがって、一方は精度良く規模の大きな識別が可能だがトレーニングコストが大きい、もう一方は精度はそこそこでいくつかの識別しか出来ないがトレーニングコストは少ないといったトレードオフの関係にあるかと思います。

VAD

VADは音声が存在する区間を検出する技術で、音声区間を予め検出することで、ノイズの除去、リソースの節約などの利点があり、音声セグメントの境界を正確に検出することで、音声認識の精度を向上させることに繋がります。

シンプルな実装としては信号のパワーとZero-crossingを用いた手法があり、元々ライブラリでも同様の手法を採用していたのですが、Espressifが公開していたESP-SRのVADがなかなか良かったことがあり、置き換えた経緯があります。

とはいえ、シンプルな実装もまるでダメってわけではなくて、意外とうまくいくので実装してみると驚くこと請け合いです。難点は摩擦音や破裂音などの検出が難しいところで、例えば「スタックチャン」は「(スタッ)クチャン」と検出されます(それでも、毎回同じように欠落して検出されるので孤立単語音声認識的には問題なく動作したりします)。

以下にわかりやすくまとめられているので気になる方はぜひ目を通されてください。

AI Shift,inc, 信号パワーと零交差数を用いた音声区間検出

MFCC

MFCCについての詳しい解説は既に他で多く語られているのでそちらをご確認ください。

電気通信大学, 第3章 スペクトル分析

MFCC(メル周波数ケプストラム係数)入門

簡単にまとめると、音声を短い区間に分割し、それらにいくつかのステップで変換を行うことで1区間の音声信号が(ライブラリの初期値だと)12次元のMFCCに変換される、ふんわり考えるとデータ圧縮として考えられると思います。

世の中には結構参考プログラムがあるといえばあるんですが、pythonでlibrosaを使っているのが多くて実装に難儀しました。改めてgithubを探してみるとC++でMFCCを実装したものもあるみたいですが・・・。

それにしても大学とか研究室の資料があるので、実装したことある人もいるんじゃないのかなぁ。

DTW

DTW (Dynamic Time Warping) は、音声データや時系列データの比較に使われる手法です。DTWは、時間の伸縮性を考慮して2つのデータ系列の類似度を評価します。音声データは話し方で時間的な変動や発話速度の違いがあるため、単純な距離計算では正確な比較ができません。DTWを使うと、音声データの時間的な変動を考慮しながら、より正確な類似度の評価ができます。

シンプルな実装だとN×Mの行列を予め作ってコサイン距離やDTW距離をメモすることが多いです。ただこれをM5Stackでやると使用可能なRAMを食いつぶすのでそのまま採用することは出来ませんでした。

英語版のWikipediaを見るとHirschberg's alogrithmを使うことでO(min(N, M))になるよ!ってあるんですが、リンク先を見ても「はぁ?何いってんの?」って感じでした。元々のコードを眺めていた直感として、直前のデータだけあれば計算できるから減らせそうだよねとは感じていたんですが、何だかんだウンウン言いながらひねり出して作った感じです。諸々終わってHirschbergを再度見直すと、「うーん、同じことしてるなぁ」ってなったのでちゃんと読み込める力って大事だなぁって思いました。

イメージは下図のような感じで、計算しながら直近の値を更新すれば片方の長さ(N or M)で事足りるということです。閃いたときは唸ったね。

  1.  (0, 0) は初期値として設定し、(0, j) は地続きなので初期値から算出
  2.  (1, 0) は (0, 0) から算出
  3.  (1, 1) は (0, 0), (0, 1), (1, 0)から算出
  4.  以降、(i, j) は (i-1, j-1), (i-1, j), (i, j-1)から算出
    1. このとき(i, j)の計算に(i-1, j-2)は必要ないので(i, j-2)の値で更新する

コメント

このブログの人気の投稿

KoeMill V.0.9.0.0 リリース

KoeMillのV.0.9.0.0をリリース KoeMillは、音声認識による文字起こしを行うソフトウェアです。音声認識モデルにはWhisperが採用されており動画や音声から自動的に高品質な文字起こしができるため、煩雑な手作業を省くことができます。 オフラインで動作するため、ネットワークの遅延などによる遅れやプライバシーに関する懸念もありません。また、GPUを利用することで高速な処理を実現します。 ダウンロードページ

CapCap V.0.9.2.7 リリース

CapCapのV.0.9.2.7をリリース 主な変更内容 HTTP POST設定でヘッダの設定に対応 HTTP POST設定でJSONのオブジェクトおよび配列に対応 HTTP POST設定を大項目ごとに折りたためる機能に対応 サンプルプリセット(ChatGPT API)を追加 プリセット複製時に複製先の変更が複製元に及んでいた不具合を修正 HTTP POST設定 新たにリクエストヘッダを設定できるようになりました。これによりAuthorizationによる認証などヘッダが必要なAPIにも対応できるようになりました。合わせて、これまで設定することが出来なかったJSON ObjectおよびArrayについても設定できるようになりました。 ChatGPT APIについて サンプルプリセットを追加しました。HTTP POSTのヘッダおよびJSON ArrayとObjectに対応したため、その対応例となります。 継続的に使おうとすると費用が発生することになるので、無料枠が残っている間に遊んでもらえると幸いです。 DLページ: Home

CapCap V0.9.2.5 リリース

CapCapのV0.9.2.5をリリース 主な変更内容 段落検出機能を追加 字幕モードの名称を変更(Readability -> Text, Layout -> Item) 段落検出 テキストの行同士の距離をもとに段落を検出することが出来るようになりました。 段落の検出および段落間への空行挿入が行なえます。 これまではテキストをひと繋がりの文章として認識していましたが、段落ごとに分離されることで可読性の向上が見込めます。 文章に対して段落が多い場合や段落が2行からなる場合などには精度が落ちる傾向にあります。また実験的機能の側面があるため問題点等あればご報告いただけると助かります。 DLページ: Home