From b1fc474a780ce4821da4ea4b0ea2eba03ef820a7 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 27 May 2022 14:03:52 -0700
Subject: [PATCH] Better fix for music decoders that return no data, e.g. a
zero length song
If we get no music data twice in a row, we'll stop decoding music for that iteration of the callback.
Fixes https://github.com/libsdl-org/SDL_mixer/issues/293
---
src/music.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/music.c b/src/music.c
index 6ef8047d..7ca56f5d 100644
--- a/src/music.c
+++ b/src/music.c
@@ -288,6 +288,7 @@ int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
Uint8 *snd = (Uint8 *)data;
Uint8 *dst;
int len = bytes;
+ int zero_cycles = 0;
SDL_bool done = SDL_FALSE;
if (volume == MIX_MAX_VOLUME) {
@@ -300,6 +301,15 @@ int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
if (consumed < 0) {
break;
}
+ if (consumed == 0) {
+ ++zero_cycles;
+ if (zero_cycles > 1) {
+ /* We went more than one cycle with no data, we're done */
+ done = SDL_TRUE;
+ }
+ continue;
+ }
+ zero_cycles = 0;
if (volume == MIX_MAX_VOLUME) {
dst += consumed;
@@ -318,9 +328,11 @@ int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
/* Mixing function */
void SDLCALL music_mixer(void *udata, Uint8 *stream, int len)
{
+ SDL_bool done = SDL_FALSE;
+
(void)udata;
- while (music_playing && music_active && len > 0) {
+ while (music_playing && music_active && len > 0 && !done) {
/* Handle fading */
if (music_playing->fading != MIX_NO_FADING) {
if (music_playing->fade_step++ < music_playing->fade_steps) {
@@ -331,7 +343,7 @@ void SDLCALL music_mixer(void *udata, Uint8 *stream, int len)
if (music_playing->fading == MIX_FADING_OUT) {
volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
} else { /* Fading in */
- volume = ( music_volume * fade_step ) / fade_steps;
+ volume = (music_volume * fade_step) / fade_steps;
}
music_internal_volume(volume);
} else {
@@ -351,6 +363,7 @@ void SDLCALL music_mixer(void *udata, Uint8 *stream, int len)
if (left != 0) {
/* Either an error or finished playing with data left */
music_playing->playing = SDL_FALSE;
+ done = SDL_TRUE;
}
if (left > 0) {
stream += (len - left);