Send I2S audio from A2DP sink to A2DP Source and then to Bluetooth Speaker
Posted: Wed Dec 23, 2020 1:47 pm
Dear all,
I am building a kind of Bluetooth audio extender. The setup includes two ESP32. The idea is to receive
an a2dp audio stream with ESP32#1, send it via i2s to ESP32#2 and from there via Bluetooth to a Bluetooth speaker.
ESP32 #1 (Audio Sink):
A classical A2DP audio sink. Receiving audio data via Bluetooth and sends the audio via I2S
Configuration:
This works and I can also listen to the audio when connecting a PCM5102 DA converter.
ESP32 #2 (Audio Source):
This ESP32 is connected to the I2S bus as SLAVE. The goal is to receive the audio stream from ESP32#1 and send it to a Bluetooth speaker.
I can see that there are many examples where the source of the I2S signal is a microphone or SD Cards, but I could not find an example
which takes a I2S signal and sends it via Bluetooth A2DP to a speaker. I was experimenting a lot and since I was not successful I thought
I post here and see if someone can point me into the right direction. Here is what I have done so far w/o success:
Configuration:
The pin_config is correct and corresponds to the I2S pins of module #1
I assume the magic has to happen here:
I do have several problems here:
1. I am not sure if I can directly handover the I2S data w/o putting it into a buffer
2. I could not find a good documentation about the parameters of i2s_read and so I am lost on what to put there for e.g. SIZE
3. The return value is int32_t len. Where do I get this from? Maybe sizeof(data)?
4. I have problems to understand the bytes_read variable. Seems like that there is not usage for it.
Can anybody kindly help me out here?
Thank you very much in advance
Mike
I am building a kind of Bluetooth audio extender. The setup includes two ESP32. The idea is to receive
an a2dp audio stream with ESP32#1, send it via i2s to ESP32#2 and from there via Bluetooth to a Bluetooth speaker.
ESP32 #1 (Audio Sink):
A classical A2DP audio sink. Receiving audio data via Bluetooth and sends the audio via I2S
Configuration:
Code: Select all
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 6,
.dma_buf_len = 60,
.intr_alloc_flags = 0, //Default interrupt priority
.tx_desc_auto_clear = true //Auto clear tx descriptor on underflow
};
i2s_driver_install(0, &i2s_config, 0, NULL);
i2s_pin_config_t pin_config = {
.bck_io_num = CONFIG_EXAMPLE_I2S_BCK_PIN,
.ws_io_num = CONFIG_EXAMPLE_I2S_LRCK_PIN,
.data_out_num = CONFIG_EXAMPLE_I2S_DATA_PIN,
.data_in_num = -1 //Not used
};
i2s_set_pin(0, &pin_config);
This works and I can also listen to the audio when connecting a PCM5102 DA converter.
ESP32 #2 (Audio Source):
This ESP32 is connected to the I2S bus as SLAVE. The goal is to receive the audio stream from ESP32#1 and send it to a Bluetooth speaker.
I can see that there are many examples where the source of the I2S signal is a microphone or SD Cards, but I could not find an example
which takes a I2S signal and sends it via Bluetooth A2DP to a speaker. I was experimenting a lot and since I was not successful I thought
I post here and see if someone can point me into the right direction. Here is what I have done so far w/o success:
Configuration:
Code: Select all
static const int i2s_num = 0; // i2s port number
static const i2s_config_t i2s_config = {
.mode = I2S_MODE_SLAVE | I2S_MODE_RX,
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false
};
static const i2s_pin_config_t pin_config = {
.bck_io_num = 26,
.ws_io_num = 22,
.data_out_num = -1,
.data_in_num = 25
};
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
i2s_set_pin(i2s_num, &pin_config);
I assume the magic has to happen here:
Code: Select all
static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len)
{
if (len < 0 || data == NULL) {
return 0;
}
size_t bytes_read = 0;
//int a = bytes_read;
//int b = (int)data;
i2s_read(0, data, SIZE???, &bytes_read, portMAX_DELAY);
//ESP_LOGI(BT_AV_TAG, "bytes read: %d ", a);
//ESP_LOGI(BT_AV_TAG, "data:%d ",b);
return len;
}
I do have several problems here:
1. I am not sure if I can directly handover the I2S data w/o putting it into a buffer
2. I could not find a good documentation about the parameters of i2s_read and so I am lost on what to put there for e.g. SIZE
3. The return value is int32_t len. Where do I get this from? Maybe sizeof(data)?
4. I have problems to understand the bytes_read variable. Seems like that there is not usage for it.
Can anybody kindly help me out here?
Thank you very much in advance
Mike