目的
Module-LLMのマイクにて録音を行い、wavファイルのデータ評価を行いました。
注意事項
Module-LLMの初期ファームウェアで評価した結果です。今後のファームウェアバージョンアップで修正が入る可能性があります。
audioデータは、AXERA-TECHのSDKを使ってデータ取得することが推奨されています。
Pythonのプログラムでは、AXERA-TECH SDK対応のaudioライブラリは現状用意されていないため、Linuxの標準環境であるALSAを使って録音する手段を主に評価しました。
結論
現状、ALSAを経由してマイクからのデータを扱う場合には、BitRate設定:24Bitもしくは32Bitで取り込み、16BitのBitRateへ変換することがお勧めとなります。
また、AXERA-TECHのSDKを使って、マイクから録音する手段がお勧めとなります。
背景
Module-LLMの発売直後、@devemin 氏、@devemin 氏と@tokkyo氏 によって、マイクから音声がとれたと報告と、設定によってマイクの音が変であるという報告がありました。
録音は、
— でべ (@devemin) November 5, 2024
cd /root
arecord -D plughw:0,0 -f S24_LE -r 24000 mic2.wav
再生は、
aplay -D plughw:0,1 /root/mic2.wav
でうまくできた。
録音のオプションの Hz / bitrate の組合わせによって、ノイズのでる変な音になる。組み合わせによって正しく録音される?
-f S16_LE or 未指定 (bitrate)
-r…
いろいろALSAを試した感じ、S16_LEのときは指定した2倍のデータをsnd_pcm_readi()で取得してしまっているような感じっぽいな👀 (S32_LEのときはOK)
— tokkyo (@tokkyo) November 29, 2024
その後、 @mongonta555 氏によって、ffmpegでの変換を組み合わせることによって、
日本語認識できるwavファイルが生成できたと報告がありました。
・arecordで5秒録音
— タカヲ(Takao) (@mongonta555) November 30, 2024
・ファイルヘッダを32000Hzに書き換え
・ffmpegで32000HzのWAVファイルを16000Hzに変換
・Juliusでファイルを読み込んで音声認識
という手順です。#M5StackLLM #M5Stack
調査内容
これまでのXでの経緯を踏まえて、ALSA経由のマイクに不具合がありそうだということで、スマートフォンから、toneジェネレータのアプリを使って、1kHzの音をModule-LLMの近くで鳴らしてマイクから録音してみました。
Module-LLMで、ALSA経由でマイクから音を1秒取得するPythonのプログラムを起動しました。
音のデータをwavファイルに保存しました。
事前に、alsa-utils,portaudio,pyaudioをインストールします。
root@m5stack-LLM:# sudo apt install alsa-utils portaudio19-dev
root@m5stack-LLM:# pip install pyaudio
root@m5stack-LLM:# python3 mic_input_data.py
if __name__ == "__main__":
#Bitrate 16Bit
record_audio("S16_LE_08000Hz.wav", duration=1,format_bit=pyaudio.paInt16,sample_rate=8000)
record_audio("S16_LE_16000Hz.wav", duration=1,format_bit=pyaudio.paInt16,sample_rate=16000)
record_audio("S16_LE_24000Hz.wav", duration=1,format_bit=pyaudio.paInt16,sample_rate=24000)
record_audio("S16_LE_32000Hz.wav", duration=1,format_bit=pyaudio.paInt16,sample_rate=32000)
#Bitrate 32Bit
record_audio("S32_LE_08000Hz.wav", duration=1,format_bit=pyaudio.paInt32,sample_rate=8000)
record_audio("S32_LE_16000Hz.wav", duration=1,format_bit=pyaudio.paInt32,sample_rate=16000)
record_audio("S32_LE_24000Hz.wav", duration=1,format_bit=pyaudio.paInt32,sample_rate=24000)
record_audio("S32_LE_32000Hz.wav", duration=1,format_bit=pyaudio.paInt32,sample_rate=32000)
#Bitrate 24Bit
record_audio("S24_LE_08000Hz.wav", duration=1,format_bit=pyaudio.paInt24,sample_rate=8000)
record_audio("S24_LE_16000Hz.wav", duration=1,format_bit=pyaudio.paInt24,sample_rate=16000)
record_audio("S24_LE_24000Hz.wav", duration=1,format_bit=pyaudio.paInt24,sample_rate=24000)
record_audio("S24_LE_32000Hz.wav", duration=1,format_bit=pyaudio.paInt24,sample_rate=32000)
ソースコードの全文は以下です。
https://github.com/nnn112358/M5_LLM_Module_Report/blob/main/audio/mic_in_to_wave.py
次に、wavファイルをテキストファイルに変換するpythonプログラムを実行しました。
root@m5stack-LLM:# python3 wav_to_csv.py
if __name__ == "__main__":
wav_to_csv("S16_LE_08000Hz.wav", "S16_LE_08000Hz.csv")
wav_to_csv("S16_LE_16000Hz.wav", "S16_LE_16000Hz.csv")
wav_to_csv("S16_LE_24000Hz.wav", "S16_LE_24000Hz.csv")
wav_to_csv("S16_LE_32000Hz.wav", "S16_LE_32000Hz.csv")
wav_to_csv("S24_LE_08000Hz.wav", "S24_LE_08000Hz.csv")
wav_to_csv("S24_LE_16000Hz.wav", "S24_LE_16000Hz.csv")
wav_to_csv("S24_LE_24000Hz.wav", "S24_LE_24000Hz.csv")
wav_to_csv("S32_LE_08000Hz.wav", "S32_LE_08000Hz.csv")
wav_to_csv("S32_LE_16000Hz.wav", "S32_LE_16000Hz.csv")
wav_to_csv("S32_LE_24000Hz.wav", "S32_LE_24000Hz.csv")
wav_to_csv("S32_LE_32000Hz.wav", "S32_LE_32000Hz.csv")
ソースコードの全文は以下です。
https://github.com/nnn112358/M5_LLM_Module_Report/blob/main/audio/wav_to_csv.py
調査結果
テキスト化したwavファイルのデータをグラフ化したものが以下になります。
32Bitと24Bitのwavファイルのデータは、16Bitのwavファイルにあわせるように振幅を換算する後処理を入れています。具体的にはpythonプログラムを参照してください。
考察
・BirRate:16Bitでは、1kHzの音が、500Hzに変化しています。1個のデータを採取するごとに、振幅 0 のデータが挿入されています。16Bitごとのデータをやり取りするべきところを、誤って32Bitずつやり取りしているなどの不具合がある可能性があります。
・32Bitと24Bitのwavはそのような異常が見られないので、32Bitもしくは24Bitで録音するのがよいと考えられます。
次の評価
Module-LLMのマイクでは、LinuxのALSA Driverを経由して録音を行うと、16Bitのときに異常が見られました。
そこで、次は推奨されているAXERA-TECHのSDKを使って、マイクから録音する手段を試してみました。
sample_audioでの録音
Module-LLMでは、sample_audioコマンドを使って、AXERA-TECHのSDKを使ったマイクの操作を行うことができます。
sample_audioは、AXERA-TECHが提供しているSDK(ax620e_bsp_sdk)のサンプルプログラムです。
Module-LLMで、以下のコマンドを打つことでマイクから録音することができます。
# 16Bit 8kHzで録音
root@m5stack-LLM:# sample_audio ai -D 0 -d 0 -r 8000 -p 160 -w 1 -o sample_audio_S16_LE_08000Hz.wav
# 16Bit 16kHzで録音
root@m5stack-LLM:# sample_audio ai -D 0 -d 0 -r 16000 -p 160 -w 1 -o sample_audio_S16_LE_16000Hz.wav
# 16Bit 24kHzで録音
root@m5stack-LLM:# sample_audio ai -D 0 -d 0 -r 24000 -p 160 -w 1 -o sample_audio_S16_LE_24000Hz.wav
# 16Bit 32kHzで録音
root@m5stack-LLM:# sample_audio ai -D 0 -d 0 -r 32000 -p 160 -w 1 -o sample_audio_S16_LE_32000Hz.wav
Module-LLMのマイクを調べてみた件(ALSA編)と同じく、
Module-LLMで、スマホからの1kHzのトーン音を録音しました。
こちらのプログラムからは、16Bitで取り込んでも目立った異常はないことを確認しました。
sample audioの説明
こちらにある、sample audioのドキュメントを翻訳しました。
https://github.com/AXERA-TECH/ax620e_bsp_sdk/tree/main/msp/sample/audio
1)機能の説明::
audioフォルダーの下にあるコードは、顧客がオーディオ モジュール全体の構成プロセスをすぐに理解できるように、AXERA-TECHの SDK パッケージによって提供されるサンプル リファレンス コードです。サンプル コードでは、ai 記録、ao 再生、ai_aenc エンコード、adec_ao デコードの関数を示します。AXERA-TECHは、Everest メーカーのコーデック ドライバー( es8388、es7210、es8311、es7243l、および es8156)に対応しています。
2)使用例:
例 1: ヘルプ情報を表示する
sample_audio -h
例 2: 16kHz オーディオを録音する
sample_audio ai -D 0 -d 0 -r 16000 -p 160 -w 1
例 3: FIXED モードのエコー キャンセルを有効にして 16kHz オーディオを録音する
sample_audio ai -D 0 -d 0 -r 16000 -p 160 --aec-mode 2 --routing-mode 0 --layout 1 -w 1
例 4: 16kHz オーディオを再生する
sample_audio ao -D 0 -d 1 -r 16000
例 5: 16kHz オーディオを録音してエンコードする
sample_audio ai_aenc -D 0 -d 0 -r 16000 -p 160 -w 1
例 6: 16kHz オーディオを録音し、モノラルでエンコードする
sample_audio ai_aenc -D 0 -d 0 -r 16000 -p 160 --layout 1 --aenc-chns 1 -w 1
例 7: 16kHz オーディオをデコードして再生する
sample_audio adec_ao -D 0 -d 1 -r 16000
例 8: 内蔵コーデック アップストリーム HPF LPF EQ
sample_audio ai -D 0- d 0 --hpf 1 --hpf-freq 200 --hpf-db -12 --lpf 1 --lpf-freq 3000 --lpf-db 0 --eq 1
例 9: 内蔵コーデック ダウンストリーム HPF LPF EQ
sample_audio ao -D 0 -d 1 --hpf 1 --hpf-freq 200 --hpf-db -12 --lpf 1 --lpf-freq 3000 --lpf-db 0 --eq 1
-
実行結果の例:
正常に実行したら、Ctrl+C を実行して終了します。wave ファイルが現在のディレクトリに生成され、ユーザーはそれを開いて実際の効果を確認できます。 -
注意事項:
(1) サウンド カード番号とデバイス番号については、/dev/snd/ を参照してください。例:
pcmC0D0c: カード 0、デバイス 0、キャプチャ デバイス
pcmC0D1p: カード 0、デバイス 1、再生デバイス
謝辞
情報を頂いた、@devemin氏 @tokkyo氏、@mongonta555氏に感謝を申し上げます m(_ _)m
参考リンク
https://x.com/nnn112358/status/1863508092471930989
https://x.com/devemin/status/1853944346556719523
https://x.com/HanxiaoM/status/1853866167137644827
https://x.com/HanxiaoM/status/1862455344288735508
https://x.com/mongonta555/status/1862872794406773242
https://wiki.onakasuita.org/pukiwiki/?Module%20LLM%2FJulius
https://x.com/tokkyo/status/1862655788202041414
https://x.com/nnn112358/status/1862636059571708066