Skip to content

Commit

Permalink
Fixed bug 4849 - [PATCH] Expand OGG looping support
Browse files Browse the repository at this point in the history
Michael Day

Attached is a patch for music_ogg.c which offers two improvements to the built-in OGG looping:

1. Valid tag/comment key names currently take the form of LOOPxxx. Add support for LOOP_xxx and LOOP-xxx as well.
2. Add support for loop points specified by time strings of the form HH:MM:SS.ss.

The impetus for this change is to help improve music looping for Doom source ports which expect users to use music files with tags based on the tag standard established by ZDoom. (See https://zdoom.org/wiki/Audio_loop)
  • Loading branch information
slouken committed Nov 1, 2019
1 parent 3fb9037 commit b499742
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions music_ogg.c
Expand Up @@ -223,6 +223,43 @@ static int OGG_UpdateSection(OGG_music *music)
return 0;
}

/* Parse time string of the form HH:MM:SS.mmm and return equivalent sample
* position */
static ogg_int64_t parse_time(char *time, long samplerate_hz)
{
char *num_start, *p;
ogg_int64_t result = 0;
char c;

// Time is directly expressed as a sample position
if (SDL_strchr(time, ':') == NULL)
{
return SDL_strtoull(time, NULL, 0);
}

result = 0;
num_start = time;

for (p = time; *p != '\0'; ++p)
{
if (*p == '.' || *p == ':')
{
c = *p; *p = '\0';
result = result * 60 + SDL_atoi(num_start);
num_start = p + 1;
*p = c;
}

if (*p == '.')
{
return result * samplerate_hz
+ (ogg_int64_t) (SDL_atof(p) * samplerate_hz);
}
}

return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
}

/* Load an OGG stream from an SDL_RWops object */
static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
{
Expand All @@ -231,6 +268,7 @@ static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
vorbis_comment *vc;
int isLoopLength = 0, i;
ogg_int64_t fullLength;
long rate;

music = (OGG_music *)SDL_calloc(1, sizeof *music);
if (!music) {
Expand Down Expand Up @@ -262,6 +300,7 @@ static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
}

vc = vorbis.ov_comment(&music->vf, -1);
rate = music->vi.rate;
for (i = 0; i < vc->comments; i++) {
char *param = SDL_strdup(vc->user_comments[i]);
char *argument = param;
Expand All @@ -272,14 +311,21 @@ static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
*(value++) = '\0';
}

/* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
* string if it is present at position 4. */

if ((argument[4] == '_') || (argument[4] == '-')) {
SDL_memmove(argument + 4, argument + 5, SDL_strlen(argument) - 4);
}

if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
music->loop_start = SDL_strtoull(value, NULL, 0);
music->loop_start = parse_time(value, rate);
else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
music->loop_len = SDL_strtoull(value, NULL, 0);
isLoopLength = 1;
} else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
isLoopLength = 0;
music->loop_end = SDL_strtoull(value, NULL, 0);
music->loop_end = parse_time(value, rate);
}
SDL_free(param);
}
Expand Down

0 comments on commit b499742

Please sign in to comment.