From b477596c41952d4545bb9f6eeb6d44f4f44275bf Mon Sep 17 00:00:00 2001 From: ainyan03 Date: Tue, 18 Aug 2026 04:00:31 +0000 Subject: [PATCH 1/2] Flush the final partial speaker buffer --- src/utility/Speaker_Class.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utility/Speaker_Class.cpp b/src/utility/Speaker_Class.cpp index 38d2fc9..061bc9c 100644 --- a/src/utility/Speaker_Class.cpp +++ b/src/utility/Speaker_Class.cpp @@ -682,6 +682,7 @@ namespace m5 uint8_t next_state = ch_info->wavinfo[flip].state.load(std::memory_order_acquire); size_t idx = 0; + bool flush_partial = false; if (current_wav->repeat == 0 || ((next_state & (wav_phase_mask | wav_state_stop_current)) == (wav_phase_published | wav_state_stop_current))) @@ -703,6 +704,7 @@ namespace m5 // further below, once flip has moved off of it - freeing it // here would let a writer claim it while flip still points at // it, and the later retirement would wipe that claim out. + flush_partial = false; current_wav->clear(); } // the finished (or cut) request goes back to the writers before @@ -737,6 +739,7 @@ namespace m5 { // nothing to do; a writer caught mid-publish raises the bit itself. ch_info->diff = 0; ch_info->index = 0; + if (flush_partial && data_length < idx) { data_length = idx; } continue; } self->_play_channel_bits.fetch_or(1 << ch); @@ -768,6 +771,7 @@ namespace m5 current_wav->repeat = --repeat; if (repeat == 0) { + flush_partial = true; goto label_next_wav; } } From 94dffd8fda11b864afeb8ba3c0e34522ab079ec1 Mon Sep 17 00:00:00 2001 From: ainyan03 Date: Tue, 18 Aug 2026 04:23:59 +0000 Subject: [PATCH 2/2] Round the flushed sample count up to even --- src/utility/Speaker_Class.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utility/Speaker_Class.cpp b/src/utility/Speaker_Class.cpp index 061bc9c..a0df266 100644 --- a/src/utility/Speaker_Class.cpp +++ b/src/utility/Speaker_Class.cpp @@ -739,7 +739,11 @@ namespace m5 { // nothing to do; a writer caught mid-publish raises the bit itself. ch_info->diff = 0; ch_info->index = 0; - if (flush_partial && data_length < idx) { data_length = idx; } + if (flush_partial) + { // Keep I2S words aligned and avoid a trailing half-word on HW v1. + const size_t flush_length = (idx + 1) & ~size_t{1}; + if (data_length < flush_length) { data_length = flush_length; } + } continue; } self->_play_channel_bits.fetch_or(1 << ch);