mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add read interface to microphone (#5131)
This commit is contained in:
		| @@ -16,14 +16,6 @@ static const char *const TAG = "i2s_audio.microphone"; | |||||||
|  |  | ||||||
| void I2SAudioMicrophone::setup() { | void I2SAudioMicrophone::setup() { | ||||||
|   ESP_LOGCONFIG(TAG, "Setting up I2S Audio Microphone..."); |   ESP_LOGCONFIG(TAG, "Setting up I2S Audio Microphone..."); | ||||||
|   ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE); |  | ||||||
|   this->buffer_ = allocator.allocate(BUFFER_SIZE); |  | ||||||
|   if (this->buffer_ == nullptr) { |  | ||||||
|     ESP_LOGE(TAG, "Failed to allocate buffer!"); |  | ||||||
|     this->mark_failed(); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| #if SOC_I2S_SUPPORTS_ADC | #if SOC_I2S_SUPPORTS_ADC | ||||||
|   if (this->adc_) { |   if (this->adc_) { | ||||||
|     if (this->parent_->get_port() != I2S_NUM_0) { |     if (this->parent_->get_port() != I2S_NUM_0) { | ||||||
| @@ -110,37 +102,38 @@ void I2SAudioMicrophone::stop_() { | |||||||
|   this->high_freq_.stop(); |   this->high_freq_.stop(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void I2SAudioMicrophone::read_() { | size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { | ||||||
|   size_t bytes_read = 0; |   size_t bytes_read = 0; | ||||||
|   esp_err_t err = |   esp_err_t err = i2s_read(this->parent_->get_port(), buf, len, &bytes_read, (100 / portTICK_PERIOD_MS)); | ||||||
|       i2s_read(this->parent_->get_port(), this->buffer_, BUFFER_SIZE, &bytes_read, (100 / portTICK_PERIOD_MS)); |  | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err)); |     ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err)); | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     return; |     return 0; | ||||||
|   } |   } | ||||||
|   this->status_clear_warning(); |   this->status_clear_warning(); | ||||||
|  |   if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { | ||||||
|  |     return bytes_read; | ||||||
|  |   } else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) { | ||||||
|     std::vector<int16_t> samples; |     std::vector<int16_t> samples; | ||||||
|   size_t samples_read = 0; |     size_t samples_read = bytes_read / sizeof(int32_t); | ||||||
|   if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { |  | ||||||
|     samples_read = bytes_read / sizeof(int16_t); |  | ||||||
|   } else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) { |  | ||||||
|     samples_read = bytes_read / sizeof(int32_t); |  | ||||||
|   } else { |  | ||||||
|     ESP_LOGE(TAG, "Unsupported bits per sample: %d", this->bits_per_sample_); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|     samples.resize(samples_read); |     samples.resize(samples_read); | ||||||
|   if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { |  | ||||||
|     memcpy(samples.data(), this->buffer_, bytes_read); |  | ||||||
|   } else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) { |  | ||||||
|     for (size_t i = 0; i < samples_read; i++) { |     for (size_t i = 0; i < samples_read; i++) { | ||||||
|       int32_t temp = reinterpret_cast<int32_t *>(this->buffer_)[i] >> 14; |       int32_t temp = reinterpret_cast<int32_t *>(buf)[i] >> 14; | ||||||
|       samples[i] = clamp<int16_t>(temp, INT16_MIN, INT16_MAX); |       samples[i] = clamp<int16_t>(temp, INT16_MIN, INT16_MAX); | ||||||
|     } |     } | ||||||
|  |     memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); | ||||||
|  |     return samples_read * sizeof(int16_t); | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGE(TAG, "Unsupported bits per sample: %d", this->bits_per_sample_); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void I2SAudioMicrophone::read_() { | ||||||
|  |   std::vector<int16_t> samples; | ||||||
|  |   samples.resize(BUFFER_SIZE); | ||||||
|  |   size_t bytes_read = this->read(samples.data(), BUFFER_SIZE / sizeof(int16_t)); | ||||||
|  |   samples.resize(bytes_read / sizeof(int16_t)); | ||||||
|   this->data_callbacks_.call(samples); |   this->data_callbacks_.call(samples); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -152,7 +145,9 @@ void I2SAudioMicrophone::loop() { | |||||||
|       this->start_(); |       this->start_(); | ||||||
|       break; |       break; | ||||||
|     case microphone::STATE_RUNNING: |     case microphone::STATE_RUNNING: | ||||||
|  |       if (this->data_callbacks_.size() > 0) { | ||||||
|         this->read_(); |         this->read_(); | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|     case microphone::STATE_STOPPING: |     case microphone::STATE_STOPPING: | ||||||
|       this->stop_(); |       this->stop_(); | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub | |||||||
|   void set_din_pin(int8_t pin) { this->din_pin_ = pin; } |   void set_din_pin(int8_t pin) { this->din_pin_ = pin; } | ||||||
|   void set_pdm(bool pdm) { this->pdm_ = pdm; } |   void set_pdm(bool pdm) { this->pdm_ = pdm; } | ||||||
|  |  | ||||||
|  |   size_t read(int16_t *buf, size_t len) override; | ||||||
|  |  | ||||||
| #if SOC_I2S_SUPPORTS_ADC | #if SOC_I2S_SUPPORTS_ADC | ||||||
|   void set_adc_channel(adc1_channel_t channel) { |   void set_adc_channel(adc1_channel_t channel) { | ||||||
|     this->adc_channel_ = channel; |     this->adc_channel_ = channel; | ||||||
| @@ -42,7 +44,6 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub | |||||||
|   bool adc_{false}; |   bool adc_{false}; | ||||||
| #endif | #endif | ||||||
|   bool pdm_{false}; |   bool pdm_{false}; | ||||||
|   uint8_t *buffer_; |  | ||||||
|   i2s_channel_fmt_t channel_; |   i2s_channel_fmt_t channel_; | ||||||
|   i2s_bits_per_sample_t bits_per_sample_; |   i2s_bits_per_sample_t bits_per_sample_; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ class Microphone { | |||||||
|   void add_data_callback(std::function<void(const std::vector<int16_t> &)> &&data_callback) { |   void add_data_callback(std::function<void(const std::vector<int16_t> &)> &&data_callback) { | ||||||
|     this->data_callbacks_.add(std::move(data_callback)); |     this->data_callbacks_.add(std::move(data_callback)); | ||||||
|   } |   } | ||||||
|  |   virtual size_t read(int16_t *buf, size_t len) = 0; | ||||||
|  |  | ||||||
|   bool is_running() const { return this->state_ == STATE_RUNNING; } |   bool is_running() const { return this->state_ == STATE_RUNNING; } | ||||||
|   bool is_stopped() const { return this->state_ == STATE_STOPPED; } |   bool is_stopped() const { return this->state_ == STATE_STOPPED; } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user