esp32: adapt i2s buffer size to sample rate

This commit is contained in:
Matthias Ringwald 2022-11-14 16:14:51 +01:00
parent c764140abd
commit 76a7b6f546

View File

@ -94,9 +94,10 @@ static void btstack_audio_esp32_source_process_buffer(void);
#define DRIVER_POLL_INTERVAL_MS 5 #define DRIVER_POLL_INTERVAL_MS 5
#define DMA_BUFFER_COUNT 2 #define DMA_BUFFER_COUNT 2
#define DMA_BUFFER_SAMPLES 512
#define BYTES_PER_SAMPLE_STEREO 4 #define BYTES_PER_SAMPLE_STEREO 4
// one DMA buffer for max sample rate
#define MAX_DMA_BUFFER_SAMPLES (48000 * 2 * DRIVER_POLL_INTERVAL_MS/ 1000)
typedef enum { typedef enum {
BTSTACK_AUDIO_ESP32_OFF = 0, BTSTACK_AUDIO_ESP32_OFF = 0,
@ -107,6 +108,7 @@ typedef enum {
static bool btstack_audio_esp32_i2s_installed; static bool btstack_audio_esp32_i2s_installed;
static bool btstack_audio_esp32_i2s_streaming; static bool btstack_audio_esp32_i2s_streaming;
static uint32_t btstack_audio_esp32_i2s_samplerate; static uint32_t btstack_audio_esp32_i2s_samplerate;
static uint16_t btstack_audio_esp32_samples_per_dma_buffer;
// timer to fill output ring buffer // timer to fill output ring buffer
static btstack_timer_source_t btstack_audio_esp32_driver_timer; static btstack_timer_source_t btstack_audio_esp32_driver_timer;
@ -230,6 +232,7 @@ static void btstack_audio_esp32_init(void){
btstack_assert(btstack_audio_esp32_i2s_samplerate == btstack_audio_esp32_sink_samplerate); btstack_assert(btstack_audio_esp32_i2s_samplerate == btstack_audio_esp32_sink_samplerate);
} }
btstack_audio_esp32_i2s_samplerate = btstack_audio_esp32_sink_samplerate; btstack_audio_esp32_i2s_samplerate = btstack_audio_esp32_sink_samplerate;
btstack_audio_esp32_samples_per_dma_buffer = btstack_audio_esp32_sink_samplerate * 2 * DRIVER_POLL_INTERVAL_MS / 1000;
} }
if (btstack_audio_esp32_source_state != BTSTACK_AUDIO_ESP32_OFF){ if (btstack_audio_esp32_source_state != BTSTACK_AUDIO_ESP32_OFF){
@ -239,8 +242,11 @@ static void btstack_audio_esp32_init(void){
btstack_assert(btstack_audio_esp32_i2s_samplerate == btstack_audio_esp32_source_samplerate); btstack_assert(btstack_audio_esp32_i2s_samplerate == btstack_audio_esp32_source_samplerate);
} }
btstack_audio_esp32_i2s_samplerate = btstack_audio_esp32_source_samplerate; btstack_audio_esp32_i2s_samplerate = btstack_audio_esp32_source_samplerate;
btstack_audio_esp32_samples_per_dma_buffer = btstack_audio_esp32_source_samplerate * 2 * DRIVER_POLL_INTERVAL_MS / 1000;
} }
btstack_assert(btstack_audio_esp32_samples_per_dma_buffer <= MAX_DMA_BUFFER_SAMPLES);
i2s_config_t config = i2s_config_t config =
{ {
.mode = i2s_mode, .mode = i2s_mode,
@ -248,8 +254,8 @@ static void btstack_audio_esp32_init(void){
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S, .communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = DMA_BUFFER_COUNT, // Number of DMA buffers. Max 128. .dma_buf_count = DMA_BUFFER_COUNT, // Number of DMA buffers. Max 128.
.dma_buf_len = DMA_BUFFER_SAMPLES, // Size of each DMA buffer in samples. Max 1024. .dma_buf_len = btstack_audio_esp32_samples_per_dma_buffer, // Size of each DMA buffer in samples. Max 1024.
.use_apll = true, .use_apll = true,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
}; };
@ -266,7 +272,8 @@ static void btstack_audio_esp32_init(void){
btstack_audio_esp32_set_i2s0_mclk(); btstack_audio_esp32_set_i2s0_mclk();
#endif #endif
log_info("i2s init mode 0x%02x, samplerate %" PRIu32, i2s_mode, btstack_audio_esp32_sink_samplerate); log_info("i2s init mode 0x%02x, samplerate %" PRIu32 ", samples per DMA buffer: %u",
i2s_mode, btstack_audio_esp32_sink_samplerate, btstack_audio_esp32_samples_per_dma_buffer);
i2s_driver_install(BTSTACK_AUDIO_I2S_NUM, &config, DMA_BUFFER_COUNT, &btstack_audio_esp32_i2s_event_queue); i2s_driver_install(BTSTACK_AUDIO_I2S_NUM, &config, DMA_BUFFER_COUNT, &btstack_audio_esp32_i2s_event_queue);
i2s_set_pin(BTSTACK_AUDIO_I2S_NUM, &pins); i2s_set_pin(BTSTACK_AUDIO_I2S_NUM, &pins);
@ -297,14 +304,18 @@ static void btstack_audio_esp32_deinit(void){
static void btstack_audio_esp32_sink_fill_buffer(void){ static void btstack_audio_esp32_sink_fill_buffer(void){
size_t bytes_written; size_t bytes_written;
uint8_t buffer[DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO]; uint8_t buffer[MAX_DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO];
btstack_assert(btstack_audio_esp32_samples_per_dma_buffer <= MAX_DMA_BUFFER_SAMPLES);
uint16_t data_len = btstack_audio_esp32_samples_per_dma_buffer * BYTES_PER_SAMPLE_STEREO;
if (btstack_audio_esp32_sink_state == BTSTACK_AUDIO_ESP32_STREAMING){ if (btstack_audio_esp32_sink_state == BTSTACK_AUDIO_ESP32_STREAMING){
(*btstack_audio_esp32_sink_playback_callback)((int16_t *) buffer, DMA_BUFFER_SAMPLES); (*btstack_audio_esp32_sink_playback_callback)((int16_t *) buffer, btstack_audio_esp32_samples_per_dma_buffer);
// duplicate samples for mono // duplicate samples for mono
if (btstack_audio_esp32_sink_num_channels == 1){ if (btstack_audio_esp32_sink_num_channels == 1){
int16_t i; int16_t i;
int16_t * buffer16 = (int16_t *) buffer; int16_t * buffer16 = (int16_t *) buffer;
for (i=DMA_BUFFER_SAMPLES-1;i >= 0; i--){ for (i=btstack_audio_esp32_samples_per_dma_buffer-1;i >= 0; i--){
buffer16[2*i ] = buffer16[i]; buffer16[2*i ] = buffer16[i];
buffer16[2*i+1] = buffer16[i]; buffer16[2*i+1] = buffer16[i];
} }
@ -313,11 +324,11 @@ static void btstack_audio_esp32_sink_fill_buffer(void){
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
} }
i2s_write(BTSTACK_AUDIO_I2S_NUM, buffer, sizeof(buffer), &bytes_written, 0); i2s_write(BTSTACK_AUDIO_I2S_NUM, buffer, data_len, &bytes_written, 0);
if (bytes_written != sizeof(buffer)){ if (bytes_written != data_len){
log_error("i2s_write: only %u of %u!!!", (int) bytes_written, (int) sizeof(buffer)); log_error("i2s_write: only %u of %u!!!", (int) bytes_written, (int) sizeof(buffer));
} }
btstack_assert(bytes_written == sizeof(buffer)); btstack_assert(bytes_written == data_len);
} }
static int btstack_audio_esp32_sink_init( static int btstack_audio_esp32_sink_init(
@ -404,21 +415,24 @@ const btstack_audio_sink_t * btstack_audio_esp32_sink_get_instance(void){
static void btstack_audio_esp32_source_process_buffer(void){ static void btstack_audio_esp32_source_process_buffer(void){
size_t bytes_read; size_t bytes_read;
uint8_t buffer[DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO]; uint8_t buffer[MAX_DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO];
i2s_read(BTSTACK_AUDIO_I2S_NUM, buffer, sizeof(buffer), &bytes_read, 0); btstack_assert(btstack_audio_esp32_samples_per_dma_buffer <= MAX_DMA_BUFFER_SAMPLES);
btstack_assert(bytes_read == sizeof(buffer));
uint16_t data_len = btstack_audio_esp32_samples_per_dma_buffer * BYTES_PER_SAMPLE_STEREO;
i2s_read(BTSTACK_AUDIO_I2S_NUM, buffer, data_len, &bytes_read, 0);
btstack_assert(bytes_read == data_len);
int16_t * buffer16 = (int16_t *) buffer; int16_t * buffer16 = (int16_t *) buffer;
if (btstack_audio_esp32_source_state == BTSTACK_AUDIO_ESP32_STREAMING) { if (btstack_audio_esp32_source_state == BTSTACK_AUDIO_ESP32_STREAMING) {
// drop second channel if configured for mono // drop second channel if configured for mono
if (btstack_audio_esp32_source_num_channels == 1){ if (btstack_audio_esp32_source_num_channels == 1){
uint16_t i; uint16_t i;
for (i=0;i<DMA_BUFFER_SAMPLES;i++){ for (i=0;i<btstack_audio_esp32_samples_per_dma_buffer;i++){
buffer16[i] = buffer16[2*i]; buffer16[i] = buffer16[2*i];
} }
} }
(*btstack_audio_esp32_source_recording_callback)(buffer16, DMA_BUFFER_SAMPLES); (*btstack_audio_esp32_source_recording_callback)(buffer16, btstack_audio_esp32_samples_per_dma_buffer);
} }
} }