ESP32をBluetoothスピーカーにするプログラム ESP32_bt_speakerを更新した。
作成後、esp-idfが、かなり更新されたので、 いろいろと問題があるだろうなとは思っていたのだが、 手を付けずにいたのだが、 githubにissueついたので、 対応することにした。
ESP32をBluetoothスピーカーにするプログラム ESP32_bt_speakerを更新した。
作成後、esp-idfが、かなり更新されたので、 いろいろと問題があるだろうなとは思っていたのだが、 手を付けずにいたのだが、 githubにissueついたので、 対応することにした。
最新の esp-idf環境でESP32_bt_speakerをコンパイルしてみるとエラーが沢山発生。 ひとつづつ対応するのも大変なんで、元となったサンプルプログラム bluetooth/a2dp_sinkから再び作り直すつもりで、a2dp_sinkを コンパイルしてみると、I2Sと内蔵DACへの出力機能が 追加されていることが判明した。
これが動くのであれば私のESP32_bt_speakerは、お役御免。 今後、私が面倒を見なくても良くなる、と思って プログラムをESP32開発ボードに書き込むも 音が出る様子は無い。
わたしのプログラムと見比べながら、修正と試行を繰り返し、 音が出るようになった。I2S出力側は、実験できないので わからないが、内蔵DAC出力側は、テストされていないような 感じがする。
修正は pull requestを出して esp-idf側に反映してもらいたい ところだが、やり方がよくわからないので、 とりあえず ESP32_bt_speaker側を更新しておいた。
変更点を以下に示すので、これを見て a2dp_sinkの ソースを変更してもらっても良いと思う。
diff --git a/examples/bluetooth/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/a2dp_sink/main/bt_app_av.c
index 289c1f16..4958e3d9 100644
--- a/examples/bluetooth/a2dp_sink/main/bt_app_av.c
+++ b/examples/bluetooth/a2dp_sink/main/bt_app_av.c
@@ -53,7 +53,27 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
{
- i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY);
+ TickType_t delay = 50 / portTICK_PERIOD_MS;
+ if(len % 8){
+ ESP_LOGE(BT_AV_TAG,"unexpected data len:%u",len);
+ return;
+ }
+
+ for(int i=0; i<len; i+= 4){
+ uint16_t d[2];
+
+ d[0] = data[i+0]|(data[i+1] << 8);
+ d[0] ^= (1 << 11);
+ d[0] <<= 4;
+ d[1] = data[i+2]|(data[i+3] << 8);
+ d[1] ^= (1 << 11);
+ d[1] <<= 4;
+
+ int n = i2s_push_sample(0, (const char *)d, delay);
+ if(n < 0)
+ ESP_LOGE(BT_AV_TAG, "i2s_write_bytes error:%d",n);
+ }
+
if (++m_pkt_cnt % 100 == 0) {
ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt);
}
diff --git a/examples/bluetooth/a2dp_sink/main/main.c b/examples/bluetooth/a2dp_sink/main/main.c
index a6093386..30ee28a2 100644
--- a/examples/bluetooth/a2dp_sink/main/main.c
+++ b/examples/bluetooth/a2dp_sink/main/main.c
@@ -54,14 +54,14 @@ void app_main()
i2s_config_t i2s_config = {
#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC
- .mode = I2S_MODE_DAC_BUILT_IN,
+ .mode = I2S_MODE_DAC_BUILT_IN | I2S_MODE_MASTER | I2S_MODE_TX,
#else
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
#endif
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
- .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
+ .communication_format = I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 6,
.dma_buf_len = 60, //
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
このプログラムには、まだ問題が残されている。 1つは音量を上げた時、音割れする問題で、 もう一つは 通信を中断させた場合DMAバッファに 音データが残り、鳴り続けてしまう問題である。
音割れの方は、DACが8bit, Bluetooth上のデータも12bitなので、 ボリュームを上げていけば音割れするのは仕方ないような 気もするが、 iPhone単体や、他のbluetoothスピーカーで試すと ボリュームを上げても音割れしない。
データ操作のバグも疑い、いろいろ試すがわからない。 仕様なのではないかという気もするのだが、 どうなのだろう。
切断後、音が鳴る問題は、音の出力先を切り替えるなどすると、 発生させることができる。通信の切断の検出はできるので、 ここでDMAバッファをクリアする処理を書いてみたのだが うまくいかなかった。やりかたがまずかったのかもしれない。
Bluetoothについての知識が乏しいので、 ちゃんと対策しようとすると、 なかなか苦しい。