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() { | ||||
|   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 (this->adc_) { | ||||
|     if (this->parent_->get_port() != I2S_NUM_0) { | ||||
| @@ -110,37 +102,38 @@ void I2SAudioMicrophone::stop_() { | ||||
|   this->high_freq_.stop(); | ||||
| } | ||||
|  | ||||
| void I2SAudioMicrophone::read_() { | ||||
| size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { | ||||
|   size_t bytes_read = 0; | ||||
|   esp_err_t err = | ||||
|       i2s_read(this->parent_->get_port(), this->buffer_, BUFFER_SIZE, &bytes_read, (100 / portTICK_PERIOD_MS)); | ||||
|   esp_err_t err = i2s_read(this->parent_->get_port(), buf, len, &bytes_read, (100 / portTICK_PERIOD_MS)); | ||||
|   if (err != ESP_OK) { | ||||
|     ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err)); | ||||
|     this->status_set_warning(); | ||||
|     return; | ||||
|     return 0; | ||||
|   } | ||||
|   this->status_clear_warning(); | ||||
|  | ||||
|   std::vector<int16_t> samples; | ||||
|   size_t samples_read = 0; | ||||
|   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); | ||||
|   if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) { | ||||
|     memcpy(samples.data(), this->buffer_, bytes_read); | ||||
|     return bytes_read; | ||||
|   } else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) { | ||||
|     std::vector<int16_t> samples; | ||||
|     size_t samples_read = bytes_read / sizeof(int32_t); | ||||
|     samples.resize(samples_read); | ||||
|     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); | ||||
|     } | ||||
|     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); | ||||
| } | ||||
|  | ||||
| @@ -152,7 +145,9 @@ void I2SAudioMicrophone::loop() { | ||||
|       this->start_(); | ||||
|       break; | ||||
|     case microphone::STATE_RUNNING: | ||||
|       this->read_(); | ||||
|       if (this->data_callbacks_.size() > 0) { | ||||
|         this->read_(); | ||||
|       } | ||||
|       break; | ||||
|     case microphone::STATE_STOPPING: | ||||
|       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_pdm(bool pdm) { this->pdm_ = pdm; } | ||||
|  | ||||
|   size_t read(int16_t *buf, size_t len) override; | ||||
|  | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   void set_adc_channel(adc1_channel_t channel) { | ||||
|     this->adc_channel_ = channel; | ||||
| @@ -42,7 +44,6 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub | ||||
|   bool adc_{false}; | ||||
| #endif | ||||
|   bool pdm_{false}; | ||||
|   uint8_t *buffer_; | ||||
|   i2s_channel_fmt_t channel_; | ||||
|   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) { | ||||
|     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_stopped() const { return this->state_ == STATE_STOPPED; } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user