5 #include <driver/i2s.h> 16 static const uint8_t DMA_BUFFER_DURATION_MS = 15;
17 static const size_t DMA_BUFFERS_COUNT = 4;
19 static const size_t TASK_DELAY_MS = DMA_BUFFER_DURATION_MS * DMA_BUFFERS_COUNT / 2;
21 static const size_t TASK_STACK_SIZE = 4096;
22 static const ssize_t TASK_PRIORITY = 23;
24 static const size_t I2S_EVENT_QUEUE_COUNT = DMA_BUFFERS_COUNT + 1;
26 static const char *
const TAG =
"i2s_audio.speaker";
48 static esp_err_t err_bit_to_esp_err(uint32_t bit) {
51 return ESP_ERR_INVALID_STATE;
53 return ESP_ERR_INVALID_ARG;
55 return ESP_ERR_INVALID_SIZE;
57 return ESP_ERR_NO_MEM;
72 static void q15_multiplication(
const int16_t *input, int16_t *output,
size_t len, int16_t c) {
73 for (
int i = 0; i <
len; i++) {
74 int32_t acc = (int32_t) input[i] * (int32_t) c;
75 output[i] = (int16_t) (acc >> 15);
83 static const std::vector<int16_t> Q15_VOLUME_SCALING_FACTORS = {
84 0, 116, 122, 130, 137, 146, 154, 163, 173, 183, 194, 206, 218, 231, 244,
85 259, 274, 291, 308, 326, 345, 366, 388, 411, 435, 461, 488, 517, 548, 580,
86 615, 651, 690, 731, 774, 820, 868, 920, 974, 1032, 1094, 1158, 1227, 1300, 1377,
87 1459, 1545, 1637, 1734, 1837, 1946, 2061, 2184, 2313, 2450, 2596, 2750, 2913, 3085, 3269,
88 3462, 3668, 3885, 4116, 4360, 4619, 4893, 5183, 5490, 5816, 6161, 6527, 6914, 7324, 7758,
89 8218, 8706, 9222, 9770, 10349, 10963, 11613, 12302, 13032, 13805, 14624, 15491, 16410, 17384, 18415,
90 19508, 20665, 21891, 23189, 24565, 26022, 27566, 29201, 30933, 32767};
93 ESP_LOGCONFIG(TAG,
"Setting up I2S Audio Speaker...");
98 ESP_LOGE(TAG,
"Failed to create event group");
105 uint32_t event_group_bits = xEventGroupGetBits(this->
event_group_);
108 ESP_LOGD(TAG,
"Starting Speaker");
110 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::STATE_STARTING);
113 ESP_LOGD(TAG,
"Started Speaker");
115 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::STATE_RUNNING);
120 ESP_LOGD(TAG,
"Stopping Speaker");
122 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::STATE_STOPPING);
126 ESP_LOGD(TAG,
"Stopped Speaker");
135 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START);
139 this->
status_set_error(
"Failed to adjust I2S bus to match the incoming audio");
141 "Incompatible audio format: sample rate = %" PRIu32
", channels = %" PRIu8
", bits per sample = %" PRIu8,
143 this->audio_stream_info_.bits_per_sample);
148 ESP_LOGW(TAG,
"Error writing to I2S: %s", esp_err_to_name(err_bit_to_esp_err(error_bits)));
165 ssize_t decibel_index = remap<ssize_t, float>(volume, 0.0f, 1.0f, 0, Q15_VOLUME_SCALING_FACTORS.size() - 1);
194 ESP_LOGE(TAG,
"Cannot play audio, speaker failed to setup");
201 size_t bytes_written = 0;
208 bytes_written = temp_ring_buffer->write_without_replacement((
void *) data, length, ticks_to_wait);
211 return bytes_written;
223 uint32_t event_group_bits =
240 const uint8_t number_of_channels = audio_stream_info.
channels;
242 const size_t dma_buffers_size = DMA_BUFFERS_COUNT * DMA_BUFFER_DURATION_MS * this_speaker->
sample_rate_ / 1000 *
243 bytes_per_sample * number_of_channels;
244 const size_t ring_buffer_size =
263 bool stop_gracefully =
false;
264 uint32_t last_data_received_time =
millis();
265 bool tx_dma_underflow =
false;
269 event_group_bits = xEventGroupGetBits(this_speaker->
event_group_);
275 stop_gracefully =
true;
278 i2s_event_t i2s_event;
280 if (i2s_event.type == I2S_EVENT_TX_Q_OVF) {
281 tx_dma_underflow =
true;
285 size_t bytes_to_read = dma_buffers_size;
287 pdMS_TO_TICKS(TASK_DELAY_MS));
289 if (bytes_read > 0) {
290 size_t bytes_written = 0;
299 i2s_write(this_speaker->
parent_->get_port(), this_speaker->
data_buffer_, bytes_read, &bytes_written,
302 i2s_write_expand(this_speaker->
parent_->get_port(), this_speaker->
data_buffer_, bytes_read,
307 if (bytes_written != bytes_read) {
310 tx_dma_underflow =
false;
311 last_data_received_time =
millis();
314 if (stop_gracefully && tx_dma_underflow) {
323 i2s_zero_dma_buffer(this_speaker->
parent_->get_port());
327 i2s_driver_uninstall(this_speaker->
parent_->get_port());
329 this_speaker->
parent_->unlock();
373 case ESP_ERR_INVALID_STATE:
376 case ESP_ERR_INVALID_ARG:
379 case ESP_ERR_INVALID_SIZE:
399 return ESP_ERR_NO_MEM;
408 return ESP_ERR_NO_MEM;
415 if (!this->
parent_->try_lock()) {
416 return ESP_ERR_INVALID_STATE;
419 int dma_buffer_length = DMA_BUFFER_DURATION_MS * this->
sample_rate_ / 1000;
421 i2s_driver_config_t config = {
422 .mode = (i2s_mode_t) (this->
i2s_mode_ | I2S_MODE_TX),
427 .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
428 .dma_buf_count = DMA_BUFFERS_COUNT,
429 .dma_buf_len = dma_buffer_length,
431 .tx_desc_auto_clear =
true,
432 .fixed_mclk = I2S_PIN_NO_CHANGE,
433 .mclk_multiple = I2S_MCLK_MULTIPLE_256,
435 #if SOC_I2S_SUPPORTS_TDM 436 .chan_mask = (i2s_channel_t) (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1),
440 .bit_order_msb =
false,
444 #if SOC_I2S_SUPPORTS_DAC 446 config.mode = (i2s_mode_t) (config.mode | I2S_MODE_DAC_BUILT_IN);
458 #if SOC_I2S_SUPPORTS_DAC 461 i2s_pin_config_t pin_config = this->
parent_->get_pin_config();
462 pin_config.data_out_num = this->
dout_pin_;
464 err = i2s_set_pin(this->
parent_->get_port(), &pin_config);
465 #if SOC_I2S_SUPPORTS_DAC 473 i2s_driver_uninstall(this->
parent_->get_port());
487 return ESP_ERR_INVALID_ARG;
492 return ESP_ERR_INVALID_ARG;
495 if (audio_stream_info.
channels == 1) {
497 }
else if (audio_stream_info.
channels == 2) {
501 return ESP_ERR_INVALID_ARG;
516 vTaskDelete(
nullptr);
value_type const & value() const
size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override
Plays the provided audio data.
EventGroupHandle_t event_group_
void stop_(bool wait_on_empty)
Sends a stop command to the speaker task via event_group_.
bool send_esp_err_to_event_group_(esp_err_t err)
Sets the corresponding ERR_ESP event group bits.
esp_err_t allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size)
Allocates the data buffer and ring buffer.
virtual bool set_mute_off()=0
virtual bool set_mute_on()=0
static void speaker_task(void *params)
Function for the FreeRTOS task handling audio output.
void status_set_warning(const char *message="unspecified")
void set_volume(float volume) override
Sets the volume of the speaker.
i2s_dac_mode_t internal_dac_mode_
esp_err_t reconfigure_i2s_stream_info_(audio::AudioStreamInfo &audio_stream_info)
Adjusts the I2S driver configuration to match the incoming audio stream.
uint32_t IRAM_ATTR HOT millis()
bool status_has_error() const
void status_set_error(const char *message="unspecified")
i2s_channel_fmt_t channel_
void status_clear_warning()
TaskHandle_t speaker_task_handle_
optional< uint32_t > timeout_
void set_mute_state(bool mute_state) override
Mutes or unmute the speaker.
void deallocate(T *p, size_t n)
virtual bool set_volume(float volume)=0
void status_clear_error()
i2s_bits_per_sample_t bits_per_sample_
virtual void mark_failed()
Mark this component as failed.
audio_dac::AudioDac * audio_dac_
void delete_task_(size_t buffer_size)
Deletes the speaker's task.
std::shared_ptr< RingBuffer > audio_ring_buffer_
esp_err_t start_i2s_driver_()
Starts the ESP32 I2S driver.
size_t get_bytes_per_sample() const
Implementation of SPI Controller mode.
bool has_buffered_data() const override
i2s_bits_per_chan_t bits_per_channel_
QueueHandle_t i2s_event_queue_
An STL allocator that uses SPI or internal RAM.
static std::unique_ptr< RingBuffer > create(size_t len)
uint32_t buffer_duration_ms_
audio::AudioStreamInfo audio_stream_info_
i2s_comm_format_t i2s_comm_fmt_
int16_t q15_volume_factor_