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についての知識が乏しいので、 ちゃんと対策しようとすると、 なかなか苦しい。