From b31f13a9251b4eac8edd790d9c53f619eedba904 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Mon, 27 Oct 2025 15:45:48 -0500 Subject: [PATCH 1/2] feat(esp-box): Improve audio configuration --- components/esp-box/include/esp-box.hpp | 3 +- components/esp-box/src/audio.cpp | 78 +++++++------------------- 2 files changed, 22 insertions(+), 59 deletions(-) diff --git a/components/esp-box/include/esp-box.hpp b/components/esp-box/include/esp-box.hpp index 5b56d61b3..d6225705a 100644 --- a/components/esp-box/include/esp-box.hpp +++ b/components/esp-box/include/esp-box.hpp @@ -521,11 +521,10 @@ class EspBox : public BaseComponent { std::unique_ptr audio_task_{nullptr}; // i2s / low-level audio i2s_chan_handle_t audio_tx_handle{nullptr}; + i2s_chan_handle_t audio_rx_handle{nullptr}; std::vector audio_tx_buffer; StreamBufferHandle_t audio_tx_stream; i2s_std_config_t audio_std_cfg; - i2s_event_callbacks_t audio_tx_callbacks_; - std::atomic has_sound{false}; // IMU std::shared_ptr imu_; diff --git a/components/esp-box/src/audio.cpp b/components/esp-box/src/audio.cpp index 2b602edaf..aa92939e6 100644 --- a/components/esp-box/src/audio.cpp +++ b/components/esp-box/src/audio.cpp @@ -6,15 +6,6 @@ using namespace espp; // Audio Functions // //////////////////////// -static TaskHandle_t play_audio_task_handle_ = NULL; - -static bool IRAM_ATTR audio_tx_sent_callback(i2s_chan_handle_t handle, i2s_event_data_t *event, - void *user_ctx) { - // notify the main task that we're done - vTaskNotifyGiveFromISR(play_audio_task_handle_, NULL); - return true; -} - bool EspBox::initialize_codec() { logger_.info("initializing codec"); @@ -27,15 +18,15 @@ bool EspBox::initialize_codec() { audio_hal_codec_config_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.codec_mode = AUDIO_HAL_CODEC_MODE_DECODE; - cfg.dac_output = AUDIO_HAL_DAC_OUTPUT_LINE1; + cfg.dac_output = AUDIO_HAL_DAC_OUTPUT_ALL; // Enable both L and R outputs cfg.i2s_iface.bits = AUDIO_HAL_BIT_LENGTH_16BITS; cfg.i2s_iface.fmt = AUDIO_HAL_I2S_NORMAL; cfg.i2s_iface.mode = AUDIO_HAL_MODE_SLAVE; - cfg.i2s_iface.samples = AUDIO_HAL_16K_SAMPLES; + cfg.i2s_iface.samples = AUDIO_HAL_48K_SAMPLES; ret_val |= es8311_codec_init(&cfg); - ret_val |= es8311_set_bits_per_sample(cfg.i2s_iface.bits); - ret_val |= es8311_config_fmt((es_i2s_fmt_t)cfg.i2s_iface.fmt); + ret_val |= es8311_config_fmt(ES_I2S_NORMAL); + ret_val |= es8311_set_bits_per_sample(AUDIO_HAL_BIT_LENGTH_16BITS); ret_val |= es8311_codec_set_voice_volume(volume_); ret_val |= es8311_codec_ctrl_state(cfg.codec_mode, AUDIO_HAL_CTRL_START); @@ -51,45 +42,25 @@ bool EspBox::initialize_codec() { bool EspBox::initialize_i2s(uint32_t default_audio_rate) { logger_.info("initializing i2s driver"); logger_.debug("Using newer I2S standard"); - i2s_chan_config_t chan_cfg = { - .id = i2s_port, - .role = I2S_ROLE_MASTER, - .dma_desc_num = 16, // TODO: calculate form audio rate - .dma_frame_num = 48, // TODO: calculate from audio rate - .auto_clear = true, - .auto_clear_before_cb = false, - .allow_pd = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &audio_tx_handle, nullptr)); + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port, I2S_ROLE_MASTER); + chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer + // chan_cfg.dma_desc_num = 16; + // chan_cfg.dma_frame_num = 48; + ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &audio_tx_handle, &audio_rx_handle)); audio_std_cfg = { - .clk_cfg = - { - .sample_rate_hz = default_audio_rate, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - }, + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(default_audio_rate), .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg = - { - .mclk = i2s_mck_io, - .bclk = i2s_bck_io, - .ws = i2s_ws_io, - .dout = i2s_do_io, - .din = i2s_di_io, - .invert_flags = - { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, + .gpio_cfg = {.mclk = i2s_mck_io, + .bclk = i2s_bck_io, + .ws = i2s_ws_io, + .dout = i2s_do_io, + .din = i2s_di_io, + .invert_flags = {.mclk_inv = false, .bclk_inv = false, .ws_inv = false}}, }; - audio_std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_256; + // audio_std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_256; ESP_ERROR_CHECK(i2s_channel_init_std_mode(audio_tx_handle, &audio_std_cfg)); @@ -98,12 +69,6 @@ bool EspBox::initialize_i2s(uint32_t default_audio_rate) { audio_tx_stream = xStreamBufferCreate(buffer_size * 4, 0); - play_audio_task_handle_ = xTaskGetCurrentTaskHandle(); - - memset(&audio_tx_callbacks_, 0, sizeof(audio_tx_callbacks_)); - audio_tx_callbacks_.on_sent = audio_tx_sent_callback; - i2s_channel_register_event_callback(audio_tx_handle, &audio_tx_callbacks_, NULL); - xStreamBufferReset(audio_tx_stream); ESP_ERROR_CHECK(i2s_channel_enable(audio_tx_handle)); @@ -194,6 +159,10 @@ void EspBox::audio_sample_rate(uint32_t sample_rate) { // stop the channel i2s_channel_disable(audio_tx_handle); // update the sample rate + auto err = es8311_codec_set_sample_rate(sample_rate); + if (err != ESP_OK) { + logger_.error("Could not set codec sample rate: {}", err); + } audio_std_cfg.clk_cfg.sample_rate_hz = sample_rate; i2s_channel_reconfig_std_clock(audio_tx_handle, &audio_std_cfg.clk_cfg); // clear the buffer @@ -205,11 +174,6 @@ void EspBox::audio_sample_rate(uint32_t sample_rate) { void EspBox::play_audio(const std::vector &data) { play_audio(data.data(), data.size()); } void EspBox::play_audio(const uint8_t *data, uint32_t num_bytes) { - play_audio_task_handle_ = xTaskGetCurrentTaskHandle(); - if (has_sound) { - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - } // don't block here xStreamBufferSendFromISR(audio_tx_stream, data, num_bytes, NULL); - has_sound = true; } From 9871ba79385cc3ff45b325a7cd63554edfda5a4f Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Tue, 28 Oct 2025 08:28:24 -0500 Subject: [PATCH 2/2] always write the full buffer --- components/esp-box/src/audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp-box/src/audio.cpp b/components/esp-box/src/audio.cpp index aa92939e6..28eecd731 100644 --- a/components/esp-box/src/audio.cpp +++ b/components/esp-box/src/audio.cpp @@ -120,7 +120,7 @@ bool EspBox::audio_task_callback(std::mutex &m, std::condition_variable &cv, boo i2s_channel_write(audio_tx_handle, buffer, buffer_size, NULL, portMAX_DELAY); } else { xStreamBufferReceive(audio_tx_stream, buffer, available, 0); - i2s_channel_write(audio_tx_handle, buffer, available, NULL, portMAX_DELAY); + i2s_channel_write(audio_tx_handle, buffer, buffer_size, NULL, portMAX_DELAY); } return false; // don't stop the task }