ESP32 esp-idf bluetooth a2dp_sink への aptx decode 実装の考察 #7

ESP32 esp-idf bluetooth a2dp_sink への aptx decode 実装の考察 の続き、 #7 です。

なんとか、APTXのデコード部分を、2つのタスクを起動して、負荷の分散を行わせる事ができました。
これで、先般の、 "Pkt dropped" の表示がでなくなりました。

概要は、btc_a2dp_sink_data_ready()::btc_a2dp_sink.c が元々ありますが、
ここから、従来は、btc_a2dp_sink_handle_inc_media_Aptx(int8_t id,tBT_SBC_HDR *p_msg)::btc_a2dp_sink.c
(注: これは、 APTX 用に、btc_a2dp_sink_handle_inc_media(int8_t id,tBT_SBC_HDR *p_msg)::btc_a2dp_sink.c を改造したもの)
を直接コールしていた流れを、
別タスクを2つを起動させて置いて、そこから、上記関数をコールさせるようにしました。
これで、受信した音楽フレームを交互に振り分けて、APTXのデコード処理以降を分散させます。

なほ、上記2つのタスクは、それぞれ、別コアでの起動にします。

さて、音の方は言うと、音楽として判るようにはなりましたが、
まだまだ、まともには聴ける音ではありません。

常に、ビーンビーンと、かそれに近い雑音が出ていて、たまに、ピチピチ(チッピング音)が出ています。
まだまだ、プログラムとして問題があるようです。

デコード部分を、デュアル化したプログラムで、Windows10 + Bluetooth + SBC コーデックで
音楽が聴けるか試してみましたが、こちらも、同じような傾向のノイズが出るようになりました。

もう一度プログラムを見直して、タスクのネストが、シングルの時と同じになるように、
btc_a2dp_sink_enque_buf()::btc_a2dp_sink.c から、デュアル化したデコード部分をへ直接メッセージを送るよう変更しました。

これでも、結果は、余りよくなりません。
元々が、SBC コーデックで普通に聴けていたのが、デュアル化した事で、却って
音が悪くなったのは、デュアル化では無理との事でしょうか。

APTX で、デコード部分を、デュアル化する事により、"Packt Dropped" は無くなったのですが、音のつながりがうまくできない事のようです。

まっこと残念ぞね。

気を取り直して、もしかしたら、I2Sへ出力するデータの順番が狂っているのでは、と思って2つのデコードのタスクに順番に割り振ってみました。
そしたら、SBC ではすんなりときれいな音がでました。

どうやら、最初に危惧していた、データの順番の狂いが生じていたようです。
それではと、APTX の方にも、プログラムの修正を加えたのですが、

どう言う訳か、"Packet Dropped" が出始めたので、急遽、加えた修正を元に戻したのですが、状況は変わりません。
それではと、プログラムのバックアップを引っ張り出して、そちらで修正前の状態で、試してみました。

そしたら、Packet Dropped は出ていないので、こちらの方に再度、今回のプログラムの変更を
加えたところ、なぜか
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
が出るようになってしまいました。
再度、加えた修正を元に戻しても、一向に状況は改善しません。

一体どうなってしまったのか?

結局、もっと前のバックアップにもどして、それに今回の、SRCから送られてきた順番を守って、I2Sへ出力する処理をAPXの方にも組み込んでみました。

今回は、SBCの様に単純に2のデコードタスクに順番に受信データを割り振っただけではだめで、
I2SへWriteする際に、受信した時と、データの順番が狂わないように、受信したデータにシーケンス番号を割り振って、
2つのタスクにその順番通りにI2SへWite する、シリアライズ処理を加えました。
これで、音質は、かなり、改善されました。が、雑音の無い、きれいな音にはなりません。

音質は、SBC と比べて、かなりパンチがあります。
ですが、常にシュシュ、キュリュキュリュ と言うノイズと、たまにピチピチ ( こちらは、多分、I2S への書き込みに切れ間が出来ている。 ) がでます。

これで、ノイズが無いクリアな音になれば、もう最高ですが。残念です。

今回は、デコード部分のデュアルタスク化で、色々な方法で試してみました。

1. 受信した音楽フレームを、2つのメッセージキューに割り振って、2つのデコードタスクでデコードして、I2SへWrite する構成。
2. 受信した音楽フレームを、1つのメッセージキューにいれて、後は、2つのデコードタスクで早い順にキューにアクセスしてしてフレームを受けっとって、後は、デコードして、I2SへWrite する構成。
但し、どちらも、I2SへWrite する際は、受信した順番のまま、Write するように同期させています。

結局、2. の方は、"Packet Dropped" がかなり出るので、1. の方の採用となりました。

1. の方も、受信した音楽フレームを2つのタスクに割り振る方法を変えただけで、"Packet Dropped" が出たり出なかったりします。
結局、割り振り方は、単純に2つのタスクに順番に割り振る方法をとりました。
より負荷が少ない方へ割り振る方法だと、その違いだけで、"Packet Dropped" が出てしまいます。

2. の方も、受信した音楽フレームを、2つのデコードタスクに交互にイベントを送って知らせるようにしたら、OK となりました。
最初は、両方にイベントを送っていたので、1つのメッセージキューの取り合いになって、排他制御のオーバーヘッドが生じていたようです。
今後は、2. の方を採用することにします。(2019.2.12)

APTXのデュアルタスク版では、本当に微妙なバランスで何とか、"Packet Dropped" を出さない所で動作しているようです。
ほとんど、限界に近い所の様です。

これ以上の改善は、トータルのスループットを上げるしか方法が無いのでは。
特に、ピチピチの雑音は、I2SへのWite がデータが間に合っていないのでは。
基本的に、ESP32 ではAPTX のデコード処理は、重たすぎるのか。

雑音の、シュシュ、キュリュキュリュ と言うのは、APTX のデコード部分の問題か?

なほ、SBC の場合も、デコード部分デュアルタスク版では、少しピチピチが出ます。(シングル版では、問題ありません)。

その後、2. の方をさらに改造して、
今までは、デコードが完了した時に、I2SWrite で自分のデータの順番になるまで、無限ループで、待たせていたのですが、
無限ループを止めて、順番が来る間は、さらに次のデータをデコードする処理をしながら、I2SWrite で自分のデータの順番を待つ事にしました。

そうしたら、どうも、 I2SWrite での処理が間に合っていない事が判りました。
APTX のデコード処理のデュアル化で、デコードは十分に間に合っているようです。

このブログ記事について

このページは、おんちゃんが2019年2月 5日 12:19に書いたブログ記事です。

ひとつ前のブログ記事は「ESP32 esp-idf bluetooth a2dp_sink への aptx decode 実装の考察 6」です。

次のブログ記事は「ESP32 esp-idf bluetooth a2dp_sink への aptx decode 実装の考察 #8」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

カテゴリ

ウェブページ

サイトナビ