147 const uint32_t frames_to_fill_single_dma_buffer = SPDIF_BLOCK_SAMPLES;
148 const size_t bytes_to_fill_single_dma_buffer =
150 const size_t dma_buffers_floor_bytes = bytes_to_fill_single_dma_buffer * SPDIF_DMA_BUFFERS_COUNT;
154 const size_t requested_ring_buffer_bytes =
156 const size_t ring_buffer_size = std::max(dma_buffers_floor_bytes, requested_ring_buffer_bytes);
158 bool successful_setup =
false;
159 std::unique_ptr<audio::RingBufferAudioSource> audio_source;
164 static_cast<uint8_t
>(bytes_per_frame));
165 if (audio_source !=
nullptr) {
167 successful_setup =
true;
177 auto preload_silence = [&]() ->
bool {
180 for (
size_t i = 0; i < SPDIF_DMA_BUFFERS_COUNT; i++) {
194 if (successful_setup) {
195 successful_setup = preload_silence();
198 if (successful_setup) {
201 const i2s_event_callbacks_t callbacks = {.on_sent = i2s_on_sent_cb};
202 i2s_channel_register_event_callback(this->
tx_handle_, &callbacks,
this);
203 successful_setup = i2s_channel_enable(this->
tx_handle_) == ESP_OK;
206 if (!successful_setup) {
216 const TickType_t write_timeout_ticks =
217 pdMS_TO_TICKS(((block_duration_us * (SPDIF_DMA_BUFFERS_COUNT + 1)) + 999) / 1000);
219 const TickType_t read_timeout_ticks = pdMS_TO_TICKS(((block_duration_us / 2) + 999) / 1000);
223 int64_t spdif_pending_timestamp = 0;
225 bool resync_needed =
false;
238 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::COMMAND_STOP);
242 ESP_LOGV(TAG,
"COMMAND_STOP received, continuing in silence mode");
247 xEventGroupClearBits(this->
event_group_, SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY);
251 ESP_LOGV(TAG,
"Exiting: stream info changed");
256 ESP_LOGE(TAG,
"ISR event queue overflow, resyncing DMA lockstep");
257 resync_needed =
true;
263 const uint32_t credited_frames = unrecorded_frames + spdif_pending_frames;
264 const bool resynced = this->resync_lockstep_(credited_frames, preload_silence);
265 unrecorded_frames = 0;
266 spdif_pending_frames = 0;
267 spdif_dma_event_count = 0;
268 resync_needed =
false;
269 if (credited_frames > 0) {
274 ESP_LOGE(TAG,
"DMA lockstep resync failed, restarting speaker task");
280 int64_t write_timestamp;
281 bool lockstep_broken =
false;
288 ESP_LOGE(TAG,
"Event without matching write record, resyncing DMA lockstep");
289 lockstep_broken =
true;
296 if (real_frames < SPDIF_BLOCK_SAMPLES) {
297 const uint32_t frames_zeroed = SPDIF_BLOCK_SAMPLES - real_frames;
301 spdif_dma_event_count++;
304 if (frames_sent > 0) {
305 spdif_pending_timestamp = write_timestamp;
306 spdif_pending_frames += frames_sent;
309 bool decimation_reached = (spdif_dma_event_count >= SPDIF_DMA_EVENTS_PER_CALLBACK);
313 bool partial_flush = (real_frames > 0 && real_frames < SPDIF_BLOCK_SAMPLES);
315 if (decimation_reached || partial_flush) {
316 if (spdif_pending_frames > 0) {
318 spdif_pending_frames = 0;
320 spdif_dma_event_count = 0;
323 if (lockstep_broken) {
324 resync_needed =
true;
331 bool block_committed =
false;
332 bool partial_write_failure =
false;
335 while (real_frames_in_block < SPDIF_BLOCK_SAMPLES) {
336 if (audio_source->available() == 0) {
337 size_t bytes_read = audio_source->fill(read_timeout_ticks);
338 if (bytes_read == 0) {
341 uint8_t *
new_data = audio_source->mutable_data();
342 this->apply_software_volume_(
new_data, bytes_read);
346 const uint32_t frames_still_needed = SPDIF_BLOCK_SAMPLES - real_frames_in_block;
348 const size_t bytes_to_feed = std::min(audio_source->available(), bytes_still_needed);
351 size_t pcm_consumed = 0;
352 esp_err_t err = this->
spdif_encoder_->
write(audio_source->data(), bytes_to_feed, write_timeout_ticks,
353 &blocks_sent, &pcm_consumed);
357 ESP_LOGE(TAG,
"SPDIF block send failed, resyncing DMA lockstep");
358 partial_write_failure =
true;
362 if (pcm_consumed > 0) {
363 audio_source->consume(pcm_consumed);
366 if (blocks_sent > 0) {
367 block_committed =
true;
373 if (partial_write_failure) {
374 unrecorded_frames += real_frames_in_block;
375 resync_needed =
true;
379 if (!block_committed) {
384 ESP_LOGE(TAG,
"SPDIF block send failed, resyncing DMA lockstep");
385 unrecorded_frames += real_frames_in_block;
386 resync_needed =
true;
394 ESP_LOGE(TAG,
"Write records queue full, resyncing DMA lockstep");
395 unrecorded_frames += real_frames_in_block;
396 resync_needed =
true;
401 if (real_frames_in_block == 0) {
408 if (silence_duration >= this->
timeout_.value()) {
409 ESP_LOGV(TAG,
"Silence timeout reached (%" PRIu32
"ms) - stopping speaker", silence_duration);
415 if (silence_duration > 100) {
416 ESP_LOGV(TAG,
"Exiting silence mode after %" PRIu32
"ms, have audio data", silence_duration);
431 audio_source.reset();
437 vTaskDelay(pdMS_TO_TICKS(10));
448 ESP_LOGE(TAG,
"Only supports a single sample rate (configured: %" PRIu32
" Hz, stream: %" PRIu32
" Hz)",
450 return ESP_ERR_NOT_SUPPORTED;
453 if (bits_per_sample != 16 && bits_per_sample != 24 && bits_per_sample != 32) {
454 ESP_LOGE(TAG,
"Only supports 16, 24, or 32 bits per sample (got %u)", (
unsigned) bits_per_sample);
455 return ESP_ERR_NOT_SUPPORTED;
458 ESP_LOGE(TAG,
"Only supports stereo (2 channels)");
459 return ESP_ERR_NOT_SUPPORTED;
465 if (!this->
parent_->try_lock()) {
466 ESP_LOGE(TAG,
"Parent bus is busy");
467 return ESP_ERR_INVALID_STATE;
472 uint32_t dma_buffer_length = SPDIF_BLOCK_I2S_FRAMES;
475 ESP_LOGV(TAG,
"I2S DMA config: %zu buffers x %lu frames = %lu bytes total", (
size_t) SPDIF_DMA_BUFFERS_COUNT,
476 (
unsigned long) dma_buffer_length,
477 (
unsigned long) (SPDIF_DMA_BUFFERS_COUNT * dma_buffer_length * 8));
479 i2s_chan_config_t chan_cfg = {
480 .id = this->
parent_->get_port(),
482 .dma_desc_num = SPDIF_DMA_BUFFERS_COUNT,
483 .dma_frame_num = dma_buffer_length,
489 i2s_std_clk_config_t clk_cfg = {
495 i2s_std_slot_config_t slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO);
497 i2s_std_gpio_config_t gpio_cfg = {
511 i2s_std_config_t std_cfg = {
513 .slot_cfg = slot_cfg,
514 .gpio_cfg = gpio_cfg,
517 esp_err_t err = this->init_i2s_channel_(chan_cfg, std_cfg, SPDIF_I2S_EVENT_QUEUE_COUNT);