From 132a238913e990452122bb62bd32c33724c8686a Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 4 Jun 2026 11:47:26 -0400
Subject: [PATCH] vorbis, stb: Deal with Vorbis data with "deferred" samples at
start
It appears that some Ogg Vorbis files might have something at startup that
stb_vorbis wants to reject before it gets to the actual audio--I am vague on
the details of what this would be--but this can cause it to return zero while
it flushes through these.
Check if a given call to stb_vorbis_get_samples_float_interleaved started with
some pending "deferred" samples, and if it returns zero in this case, keep
trying until either we get real audio data or we hit EOF with nothing still
reported as deferred.
Arguably, this is a bug in stb_vorbis (the docs say that this call should
return zero for EOF, so it should probably be doing this loop to flush out
deferred samples itself), but it's easy enough to work around it in our code
for now.
(Manual port of fix for https://github.com/icculus/SDL_sound/issues/110)
(cherry picked from commit bd941e27ab4f9a9ab5bec70c0cc6b17033c6ec11)
---
src/codecs/music_ogg_stb.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/codecs/music_ogg_stb.c b/src/codecs/music_ogg_stb.c
index c3e7386e..8aa2fd26 100644
--- a/src/codecs/music_ogg_stb.c
+++ b/src/codecs/music_ogg_stb.c
@@ -318,6 +318,7 @@ static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
OGG_music *music = (OGG_music *)context;
SDL_bool looped = SDL_FALSE;
int filled, amount, samples, result;
+ int has_deferred;
Sint64 pcmPos;
filled = SDL_AudioStreamGet(music->stream, data, bytes);
@@ -331,10 +332,13 @@ static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
return 0;
}
- samples = stb_vorbis_get_samples_float_interleaved(music->vf,
+ do {
+ has_deferred = music->vf->discard_samples_deferred > 0;
+ samples = stb_vorbis_get_samples_float_interleaved(music->vf,
music->vi.channels,
(float *)music->buffer,
music->buffer_size / (int)sizeof(float));
+ } while ((samples == 0) && has_deferred); /* if it's still flushing out garbage at the start of the stream, keep trying. */
if (OGG_UpdateSection(music) < 0) {
return -1;