From e557bca4207f52a9957d8172c04c1eed65d09b38 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Sun, 27 Apr 2025 18:19:01 -0500 Subject: [PATCH] [i2s_audio] Microphone reads in loop for callbacks shouldn't ever delay (#8625) --- .../i2s_audio/microphone/i2s_audio_microphone.cpp | 14 ++++++++------ .../i2s_audio/microphone/i2s_audio_microphone.h | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index ef375954cd..3ab3c88142 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -284,19 +284,21 @@ void I2SAudioMicrophone::stop_() { this->status_clear_error(); } -size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { +size_t I2SAudioMicrophone::read(int16_t *buf, size_t len, TickType_t ticks_to_wait) { size_t bytes_read = 0; #ifdef USE_I2S_LEGACY - esp_err_t err = i2s_read(this->parent_->get_port(), buf, len, &bytes_read, (100 / portTICK_PERIOD_MS)); + esp_err_t err = i2s_read(this->parent_->get_port(), buf, len, &bytes_read, ticks_to_wait); #else - esp_err_t err = i2s_channel_read(this->rx_handle_, buf, len, &bytes_read, (100 / portTICK_PERIOD_MS)); + // i2s_channel_read expects the timeout value in ms, not ticks + esp_err_t err = i2s_channel_read(this->rx_handle_, buf, len, &bytes_read, pdTICKS_TO_MS(ticks_to_wait)); #endif - if (err != ESP_OK) { + if ((err != ESP_OK) && ((err != ESP_ERR_TIMEOUT) || (ticks_to_wait != 0))) { + // Ignore ESP_ERR_TIMEOUT if ticks_to_wait = 0, as it will read the data on the next call ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err)); this->status_set_warning(); return 0; } - if (bytes_read == 0) { + if ((bytes_read == 0) && (ticks_to_wait > 0)) { this->status_set_warning(); return 0; } @@ -350,7 +352,7 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { void I2SAudioMicrophone::read_() { std::vector samples; samples.resize(BUFFER_SIZE); - size_t bytes_read = this->read(samples.data(), BUFFER_SIZE / sizeof(int16_t)); + size_t bytes_read = this->read(samples.data(), BUFFER_SIZE * sizeof(int16_t), 0); samples.resize(bytes_read / sizeof(int16_t)); this->data_callbacks_.call(samples); } diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 2ff46fabab..2dbacb447e 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -25,7 +25,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub void set_pdm(bool pdm) { this->pdm_ = pdm; } - size_t read(int16_t *buf, size_t len) override; + size_t read(int16_t *buf, size_t len, TickType_t ticks_to_wait); + size_t read(int16_t *buf, size_t len) override { return this->read(buf, len, pdMS_TO_TICKS(100)); } #ifdef USE_I2S_LEGACY #if SOC_I2S_SUPPORTS_ADC