@@ -26,6 +26,16 @@ struct sample_buffer {
2626 last_value = 0 ;
2727 }
2828
29+ auto skip (size_t len) -> void {
30+ size_t filled = get_filled ();
31+ size_t num = (len < filled) ? len : filled;
32+ if (num == 0 ) {
33+ return ;
34+ }
35+ size_t r = read_index.load (std::memory_order_relaxed);
36+ read_index.store ((r + num) % buffer.size (), std::memory_order_release);
37+ }
38+
2939 auto get_filled () const -> size_t {
3040 size_t r = read_index.load (std::memory_order_relaxed);
3141 size_t w = write_index.load (std::memory_order_relaxed);
@@ -137,7 +147,7 @@ static sample_buffer* g_mockMixBuffer = nullptr;
137147} // namespace
138148
139149void SoundCore_Initialize () {
140- constexpr size_t buffer_size = 65536 ;
150+ constexpr size_t buffer_size = 16384 ;
141151 if (g_spkrMixBuffer == nullptr ) {
142152 g_spkrMixBuffer = new sample_buffer (buffer_size);
143153 }
@@ -155,6 +165,15 @@ void SoundCore_Destroy() {
155165 g_mockMixBuffer = nullptr ;
156166}
157167
168+ void SoundCore_ClearBuffers () {
169+ if (g_spkrMixBuffer != nullptr ) {
170+ g_spkrMixBuffer->reinit ();
171+ }
172+ if (g_mockMixBuffer != nullptr ) {
173+ g_mockMixBuffer->reinit ();
174+ }
175+ }
176+
158177void SoundCore_UploadSpeakerSamples (const int16_t * buffer,
159178 uint32_t num_samples) {
160179 if (g_spkrMixBuffer != nullptr ) {
@@ -175,6 +194,22 @@ void SoundCore_GetSamples(int16_t* out, size_t num_samples) {
175194 return ;
176195 }
177196
197+ // Active Latency Recovery: skip oldest samples if the buffer backlog is too
198+ // large. We allow a cushion of 1024 elements (~23 ms) above the requested
199+ // block size to avoid underruns due to thread scheduling jitter.
200+ const size_t target_backlog =
201+ std::min (num_samples + 1024 , static_cast <size_t >(16384 - 2 ));
202+
203+ size_t spkr_filled = g_spkrMixBuffer->get_filled ();
204+ if (spkr_filled > target_backlog) {
205+ g_spkrMixBuffer->skip (spkr_filled - target_backlog);
206+ }
207+
208+ size_t mock_filled = g_mockMixBuffer->get_filled ();
209+ if (mock_filled > target_backlog) {
210+ g_mockMixBuffer->skip (mock_filled - target_backlog);
211+ }
212+
178213 if (g_spkrMixBuffer->get_filled () == 0 &&
179214 g_mockMixBuffer->get_filled () == 0 ) {
180215 memset (out, 0 , num_samples * sizeof (int16_t ));
0 commit comments