mirror of
https://github.com/esphome/esphome.git
synced 2024-12-01 19:24:14 +01:00
Add read interface to microphone (#5131)
This commit is contained in:
parent
9980b9972f
commit
0b1b25191d
3 changed files with 25 additions and 28 deletions
|
@ -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; }
|
||||||
|
|
Loading…
Reference in a new issue