esp32で音声再生、ついでにモールス

2025年7月14日月曜日

t f B! P L

 DVPloggerの開発で、esp32での音声再生のライブラリを作っています。なかなかいろいろ難しいところがあるのですが、こんな感じで試行錯誤をしています。ってことを書いておきます。

どんなことをやろうとしているか

SPIFFSファイルシステムに音声をまとめて書いたWAVファイルを置き、また、音声シラバス(文字)とWAVファイルの位置(秒数)のラベルファイルも置きます。ライブラリはそのWAVファイルを与えられた文字列に従ってesp32の内蔵DACから再生を行う。という単純なものです。
電信(CW)では、キーボードで打った文字に従いをモールス符号で打鍵するように作りこんでいますので、同様の操作をしたときにesp32に音声応答を送信してもらおう、ということです。

工夫をしたところ

SPIFFSに置けるファイルは最大2MBytes程度と大きくはありませんので、WAVファイルはすべてのアルファベット・数字・それからフォネティックコード+αを入れても収まるように、16bit/sample の8kHzとかなり小さなものにしました。ただ、データ作成は、ただただ文字を読み上げて録音すればよいようにするため、かなり空白を含んでいますが、それでも良いようにサイズ感を考えました。

8kHzのデータを内蔵DAC(8ビット)に送るのでかなり荒い感じになります。また、CPUの負荷を減らす必要があり、また、esp32のI2S(DACにデータを送るインターフェース)は、8kHzのデータをそのまま送ることができませんので、32kHzのレートで8kHzの元データを補間して送るようにしました。

また、無線機で使うためには、音声再生中にPTTを制御する必要があります。再生の最初はPTTをONにして、再生すればよいのですが、再生が終わったタイミングがesp32では簡単にわからないのが問題です。そこで、I2Sバッファに送り込んだデータ量からある程度予測をして、終わったと考えられるタイミングでPTTを切るようにしました。

PTTを切るタイミングでは、ライブラリがコールバックをするように作っていますので、簡単に制御ができます。

音声再生が自由にできるようになったので、この仕組みを使ってモールス符号も再生しようと考えました。
そこで、別の関数に文字列を送った場合に、モールス符号を再生するように作りました。モールス符号は、周波数、それから、速度が可変ですので、それらが変わった場合には、再生データ(短点・長点)を作り直すようにしました。また、モールス符号は、まじめに立ち上がり・立下りに振幅にテーパーをつけて自然な音響になるようにしています。モールス符号は、0-9, A-Z, / などに加えてAR, BT, SK など、それから、調子に乗って和文コード(ホレ・ラタ含む)も対応しています。ライブラリにUTF-8でカタカナ文字を送ると和文再生するという便利仕様にしました。

さらに、これらの再生中の音声・モールス符号の文字列をリアルタイムで取得できるようにしています。CWではtickerのように送信中+送信前の文字列が出力されていましたが、それと同様のを音声でもやるという感じです。






苦心点

既にある程度書きましたが、esp32のI2Sは癖が強いです。内蔵DACにどの部分のデータが送られるのかも明確な記述がないため、試行錯誤が必要でした。
また、内蔵DACは符号なしデータを送る必要があり、また、ディフォルトで0がI2Sからセットされてしまうため、無音時にほったらかしにしておくと、非常に大きなプツ音が出てしまいます。ですので、無音時は、常時中点電圧をだすようなデータをI2Sに送るようにしています。
それから、内蔵DACは、負荷が重いとリニアリティが非常に悪くなります。こちらは、イヤホンを直接駆動した際のオシロ波形ですが、上が圧縮されて波形がひどく歪んでいることがわかります。
なので、負荷は10kオーム程度にしておく必要があります。10kオーム程度の負荷であれば、ほぼ線形で0V近くから3.3V近くが出力できるようです(アバウトですが)。

こちらは、DVPロガーのマイク端子からの出力ですが、最大100mV程度の音声出力としています。

このブログを検索

このブログを検索

esp32で音声再生、ついでにモールス

 DVPloggerの開発で、esp32での音声再生のライブラリを作っています。なかなかいろいろ難しいところがあるのですが、こんな感じで試行錯誤をしています。ってことを書いておきます。 どんなことをやろうとしているか SPIFFSファイルシステムに音声をまとめて書いたWAVファイ...

QooQ