[Commits] SDL_mixer: Added support for 'smpl' format loop points in music ...

libsdl.org revision control commits-owner at libsdl.org
Tue Jul 7 11:47:10 PDT 2015


details:   https://hg.libsdl.org/SDL_mixer/rev/1ef7c1254ffb
changeset: 709:1ef7c1254ffb
user:      Sam Lantinga <slouken at libsdl.org>
date:      Tue Jul 07 11:43:05 2015 -0700
description:
Added support for 'smpl' format loop points in music WAV files

diffstat:

 CHANGES.txt  |    2 +
 wavestream.c |  522 ++++++++++++++++++++++++++++++++++++----------------------
 wavestream.h |   17 +-
 3 files changed, 336 insertions(+), 205 deletions(-)

diffs (753 lines):

diff -r 4abaa52275ac -r 1ef7c1254ffb CHANGES.txt
--- a/CHANGES.txt	Fri Jun 26 19:27:27 2015 -0700
+++ b/CHANGES.txt	Tue Jul 07 11:43:05 2015 -0700
@@ -1,4 +1,6 @@
 2.0.1:
+Sam Lantinga - Tue Jul  7 11:40:33 PDT 2015
+ * Added support for 'smpl' format loop points in music WAV files
 Isaac Burns - Sun Sep 15 21:50:27 PDT 2013
  * Added support for loading MP3 files as sound chunks
 
diff -r 4abaa52275ac -r 1ef7c1254ffb wavestream.c
--- a/wavestream.c	Fri Jun 26 19:27:27 2015 -0700
+++ b/wavestream.c	Tue Jul 07 11:43:05 2015 -0700
@@ -47,22 +47,18 @@
 /*******************************************/
 #define RIFF        0x46464952      /* "RIFF" */
 #define WAVE        0x45564157      /* "WAVE" */
-#define FACT        0x74636166      /* "fact" */
-#define LIST        0x5453494c      /* "LIST" */
-#define BEXT        0x74786562      /* "bext" */
-#define JUNK        0x4B4E554A      /* "JUNK" */
 #define FMT         0x20746D66      /* "fmt " */
 #define DATA        0x61746164      /* "data" */
+#define SMPL        0x6c706d73      /* "smpl" */
 #define PCM_CODE    1
 #define ADPCM_CODE  2
 #define WAVE_MONO   1
 #define WAVE_STEREO 2
 
-/* Normally, these three chunks come consecutively in a WAVE file */
-typedef struct WaveFMT {
+typedef struct {
 /* Not saved in the chunk we read:
-    Uint32  FMTchunk;
-    Uint32  fmtlen;
+    Uint32  chunkID;
+    Uint32  chunkLen;
 */
     Uint16  encoding;
     Uint16  channels;       /* 1 = mono, 2 = stereo */
@@ -72,12 +68,31 @@
     Uint16  bitspersample;      /* One of 8, 12, 16, or 4 for ADPCM */
 } WaveFMT;
 
-/* The general chunk found in the WAVE file */
-typedef struct Chunk {
-    Uint32 magic;
-    Uint32 length;
-    Uint8 *data;            /* Data includes magic and length */
-} Chunk;
+typedef struct {
+    Uint32 identifier;
+    Uint32 type;
+    Uint32 start;
+    Uint32 end;
+    Uint32 fraction;
+    Uint32 play_count;
+} SampleLoop;
+
+typedef struct {
+/* Not saved in the chunk we read:
+    Uint32  chunkID;
+    Uint32  chunkLen;
+*/
+    Uint32  manufacturer;
+    Uint32  product;
+    Uint32  sample_period;
+    Uint32  MIDI_unity_note;
+    Uint32  MIDI_pitch_fraction;
+    Uint32  SMTPE_format;
+    Uint32  SMTPE_offset;
+    Uint32  sample_loops;
+    Uint32  sampler_data;
+    SampleLoop loops[];
+} SamplerChunk;
 
 /*********************************************/
 /* Define values for AIFF (IFF audio) format */
@@ -96,10 +111,8 @@
 static int wavestream_volume = MIX_MAX_VOLUME;
 
 /* Function to load the WAV/AIFF stream */
-static SDL_RWops *LoadWAVStream (SDL_RWops *rw, SDL_AudioSpec *spec,
-                    long *start, long *stop);
-static SDL_RWops *LoadAIFFStream (SDL_RWops *rw, SDL_AudioSpec *spec,
-                    long *start, long *stop);
+static SDL_bool LoadWAVStream(WAVStream *wave);
+static SDL_bool LoadAIFFStream(WAVStream *wave);
 
 /* Initialize the WAVStream player, with the given mixer settings
    This function returns 0, or -1 if there was an error.
@@ -119,33 +132,35 @@
 WAVStream *WAVStream_LoadSong_RW(SDL_RWops *src, int freesrc)
 {
     WAVStream *wave;
-    SDL_AudioSpec wavespec;
+    SDL_bool loaded = SDL_FALSE;
 
-    if ( ! mixer.format ) {
+    if (!mixer.format) {
         Mix_SetError("WAV music output not started");
         return(NULL);
     }
+
     wave = (WAVStream *)SDL_malloc(sizeof *wave);
-    if ( wave ) {
+    if (wave) {
         Uint32 magic;
 
         SDL_zerop(wave);
+        wave->src = src;
         wave->freesrc = freesrc;
 
         magic = SDL_ReadLE32(src);
-        if ( magic == RIFF || magic == WAVE ) {
-            wave->src = LoadWAVStream(src, &wavespec, &wave->start, &wave->stop);
-        } else if ( magic == FORM ) {
-            wave->src = LoadAIFFStream(src, &wavespec, &wave->start, &wave->stop);
+        if (magic == RIFF || magic == WAVE) {
+            loaded = LoadWAVStream(wave);
+        } else if (magic == FORM) {
+            loaded = LoadAIFFStream(wave);
         } else {
             Mix_SetError("Unknown WAVE format");
         }
-        if ( wave->src == NULL ) {
-            SDL_free(wave);
+        if (!loaded) {
+            WAVStream_FreeSong(wave);
             return(NULL);
         }
         SDL_BuildAudioCVT(&wave->cvt,
-            wavespec.format, wavespec.channels, wavespec.freq,
+            wave->spec.format, wave->spec.channels, wave->spec.freq,
             mixer.format, mixer.channels, mixer.freq);
     } else {
         SDL_OutOfMemory();
@@ -157,67 +172,118 @@
 /* Start playback of a given WAV stream */
 void WAVStream_Start(WAVStream *wave)
 {
-    SDL_RWseek (wave->src, wave->start, RW_SEEK_SET);
+    int i;
+    for (i = 0; i < wave->numloops; ++i) {
+        WAVLoopPoint *loop = &wave->loops[i];
+        loop->active = SDL_TRUE;
+        loop->current_play_count = loop->initial_play_count;
+    }
+    SDL_RWseek(wave->src, wave->start, RW_SEEK_SET);
     music = wave;
 }
 
 /* Play some of a stream previously started with WAVStream_Start() */
+static int PlaySome(Uint8 *stream, int len)
+{
+    Sint64 pos, stop;
+    WAVLoopPoint *loop;
+    Sint64 loop_start;
+    Sint64 loop_stop;
+    int i;
+    int consumed;
+
+    pos = SDL_RWtell(music->src);
+    stop = music->stop;
+    loop = NULL;
+    for (i = 0; i < music->numloops; ++i) {
+        loop = &music->loops[i];
+        if (loop->active) {
+            const int bytes_per_sample = (SDL_AUDIO_BITSIZE(music->spec.format) / 8) * music->spec.channels;
+            loop_start = music->start + loop->start * bytes_per_sample;
+            loop_stop = music->start + (loop->stop + 1) * bytes_per_sample;
+            if (pos >= loop_start && pos < loop_stop)
+            {
+                stop = loop_stop;
+                break;
+            }
+        }
+        loop = NULL;
+    }
+
+    if (music->cvt.needed) {
+        int original_len;
+
+        original_len = (int)((double)len/music->cvt.len_ratio);
+        if (music->cvt.len != original_len) {
+            int worksize;
+            if (music->cvt.buf != NULL) {
+                SDL_free(music->cvt.buf);
+            }
+            worksize = original_len*music->cvt.len_mult;
+            music->cvt.buf=(Uint8 *)SDL_malloc(worksize);
+            if (music->cvt.buf == NULL) {
+                return 0;
+            }
+            music->cvt.len = original_len;
+        }
+        if ((stop - pos) < original_len) {
+            original_len = (int)(stop - pos);
+        }
+        original_len = SDL_RWread(music->src, music->cvt.buf, 1, original_len);
+        /* At least at the time of writing, SDL_ConvertAudio()
+           does byte-order swapping starting at the end of the
+           buffer. Thus, if we are reading 16-bit samples, we
+           had better make damn sure that we get an even
+           number of bytes, or we'll get garbage.
+         */
+        if ((music->cvt.src_format & 0x0010) && (original_len & 1)) {
+            original_len--;
+        }
+        music->cvt.len = original_len;
+        SDL_ConvertAudio(&music->cvt);
+        SDL_MixAudio(stream, music->cvt.buf, music->cvt.len_cvt, wavestream_volume);
+        consumed = music->cvt.len_cvt;
+    } else {
+        Uint8 *data;
+        if ((stop - pos) < len) {
+            len = (int)(stop - pos);
+        }
+        data = SDL_stack_alloc(Uint8, len);
+        if (data) {
+            len = SDL_RWread(music->src, data, 1, len);
+            SDL_MixAudio(stream, data, len, wavestream_volume);
+            SDL_stack_free(data);
+        }
+        consumed = len;
+    }
+
+    if (loop && SDL_RWtell(music->src) >= stop) {
+        if (loop->current_play_count == 1) {
+            loop->active = SDL_FALSE;
+        } else {
+            if (loop->current_play_count > 0) {
+                --loop->current_play_count;
+            }
+            SDL_RWseek(music->src, loop_start, RW_SEEK_SET);
+        }
+    }
+    return consumed;
+}
+
 int WAVStream_PlaySome(Uint8 *stream, int len)
 {
-    Sint64 pos;
-    Sint64 left = 0;
+    if (!music)
+        return 0;
 
-    if ( music && ((pos=SDL_RWtell(music->src)) < music->stop) ) {
-        if ( music->cvt.needed ) {
-            int original_len;
+    while ((SDL_RWtell(music->src) < music->stop) && (len > 0)) {
+        int consumed = PlaySome(stream, len);
+        if (!consumed)
+            break;
 
-            original_len=(int)((double)len/music->cvt.len_ratio);
-            if ( music->cvt.len != original_len ) {
-                int worksize;
-                if ( music->cvt.buf != NULL ) {
-                    SDL_free(music->cvt.buf);
-                }
-                worksize = original_len*music->cvt.len_mult;
-                music->cvt.buf=(Uint8 *)SDL_malloc(worksize);
-                if ( music->cvt.buf == NULL ) {
-                    return 0;
-                }
-                music->cvt.len = original_len;
-            }
-            if ( (music->stop - pos) < original_len ) {
-                left = (original_len - (music->stop - pos));
-                original_len -= (int)left;
-                left = (int)((double)left*music->cvt.len_ratio);
-            }
-            original_len = SDL_RWread(music->src, music->cvt.buf,1,original_len);
-            /* At least at the time of writing, SDL_ConvertAudio()
-               does byte-order swapping starting at the end of the
-               buffer. Thus, if we are reading 16-bit samples, we
-               had better make damn sure that we get an even
-               number of bytes, or we'll get garbage.
-             */
-            if ( (music->cvt.src_format & 0x0010) && (original_len & 1) ) {
-                original_len--;
-            }
-            music->cvt.len = original_len;
-            SDL_ConvertAudio(&music->cvt);
-            SDL_MixAudio(stream, music->cvt.buf, music->cvt.len_cvt, wavestream_volume);
-        } else {
-            Uint8 *data;
-            if ( (music->stop - pos) < len ) {
-                left = (len - (music->stop - pos));
-                len -= (int)left;
-            }
-            data = SDL_stack_alloc(Uint8, len);
-            if (data)
-            {
-                SDL_RWread(music->src, data, len, 1);
-                SDL_MixAudio(stream, data, len, wavestream_volume);
-                SDL_stack_free(data);
-            }
-        }
+        stream += consumed;
+        len -= consumed;
     }
-    return (int)left;
+    return len;
 }
 
 /* Stop playback of a stream previously started with WAVStream_Start() */
@@ -229,12 +295,15 @@
 /* Close the given WAV stream */
 void WAVStream_FreeSong(WAVStream *wave)
 {
-    if ( wave ) {
+    if (wave) {
         /* Clean up associated data */
-        if ( wave->cvt.buf ) {
+        if (wave->loops) {
+            SDL_free(wave->loops);
+        }
+        if (wave->cvt.buf) {
             SDL_free(wave->cvt.buf);
         }
-        if ( wave->freesrc ) {
+        if (wave->freesrc) {
             SDL_RWclose(wave->src);
         }
         SDL_free(wave);
@@ -247,84 +316,45 @@
     int active;
 
     active = 0;
-    if ( music && (SDL_RWtell(music->src) < music->stop) ) {
+    if (music && (SDL_RWtell(music->src) < music->stop)) {
         active = 1;
     }
     return(active);
 }
 
-static int ReadChunk(SDL_RWops *src, Chunk *chunk, int read_data)
+static SDL_bool ParseFMT(WAVStream *wave, Uint32 chunk_length)
 {
-    chunk->magic    = SDL_ReadLE32(src);
-    chunk->length   = SDL_ReadLE32(src);
-    if ( read_data ) {
-        chunk->data = (Uint8 *)SDL_malloc(chunk->length);
-        if ( chunk->data == NULL ) {
-            Mix_SetError("Out of memory");
-            return(-1);
-        }
-        if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) {
-            Mix_SetError("Couldn't read chunk");
-            SDL_free(chunk->data);
-            return(-1);
-        }
-    } else {
-        SDL_RWseek(src, chunk->length, RW_SEEK_CUR);
+    SDL_RWops *src = wave->src;
+    SDL_AudioSpec *spec = &wave->spec;
+    WaveFMT *format;
+    Uint8 *data;
+    SDL_bool loaded = SDL_FALSE;
+
+    if (chunk_length < sizeof(*format)) {
+        Mix_SetError("Wave format chunk too small");
+        return SDL_FALSE;
     }
-    return(chunk->length);
-}
 
-static SDL_RWops *LoadWAVStream (SDL_RWops *src, SDL_AudioSpec *spec,
-                    long *start, long *stop)
-{
-    int was_error;
-    Chunk chunk;
-    int lenread;
-
-    /* WAV magic header */
-    Uint32 wavelen;
-    Uint32 WAVEmagic;
-
-    /* FMT chunk */
-    WaveFMT *format = NULL;
-
-    was_error = 0;
-
-    /* Check the magic header */
-    wavelen     = SDL_ReadLE32(src);
-    WAVEmagic   = SDL_ReadLE32(src);
-
-    /* Read the audio data format chunk */
-    chunk.data = NULL;
-    do {
-        /* FIXME! Add this logic to SDL_LoadWAV_RW() */
-        if ( chunk.data ) {
-            SDL_free(chunk.data);
-        }
-        lenread = ReadChunk(src, &chunk, 1);
-        if ( lenread < 0 ) {
-            was_error = 1;
-            goto done;
-        }
-    } while ((chunk.magic == FACT) || (chunk.magic == LIST) || (chunk.magic == BEXT) || (chunk.magic == JUNK));
+    data = (Uint8 *)SDL_malloc(chunk_length);
+    if (!data) {
+        Mix_SetError("Out of memory");
+        return SDL_FALSE;
+    }
+    if (!SDL_RWread(wave->src, data, chunk_length, 1)) {
+        Mix_SetError("Couldn't read %d bytes from WAV file", chunk_length);
+        return SDL_FALSE;
+    }
+    format = (WaveFMT *)data;
 
     /* Decode the audio data format */
-    format = (WaveFMT *)chunk.data;
-    if ( chunk.magic != FMT ) {
-        Mix_SetError("Complex WAVE files not supported");
-        was_error = 1;
-        goto done;
-    }
     switch (SDL_SwapLE16(format->encoding)) {
         case PCM_CODE:
             /* We can understand this */
             break;
         default:
             Mix_SetError("Unknown WAVE data format");
-            was_error = 1;
             goto done;
     }
-    SDL_memset(spec, 0, (sizeof *spec));
     spec->freq = SDL_SwapLE32(format->frequency);
     switch (SDL_SwapLE16(format->bitspersample)) {
         case 8:
@@ -335,32 +365,136 @@
             break;
         default:
             Mix_SetError("Unknown PCM data format");
-            was_error = 1;
             goto done;
     }
     spec->channels = (Uint8) SDL_SwapLE16(format->channels);
     spec->samples = 4096;       /* Good default buffer size */
 
-    /* Set the file offset to the DATA chunk data */
-    chunk.data = NULL;
-    do {
-        *start = (long)SDL_RWtell(src) + 2*sizeof(Uint32);
-        lenread = ReadChunk(src, &chunk, 0);
-        if ( lenread < 0 ) {
-            was_error = 1;
-            goto done;
-        }
-    } while ( chunk.magic != DATA );
-    *stop = (long)SDL_RWtell(src);
+    loaded = SDL_TRUE;
 
 done:
-    if ( format != NULL ) {
-        SDL_free(format);
+    SDL_free(data);
+    return loaded;
+}
+
+static SDL_bool ParseDATA(WAVStream *wave, Uint32 chunk_length)
+{
+    wave->start = SDL_RWtell(wave->src);
+    wave->stop = wave->start + chunk_length;
+    SDL_RWseek(wave->src, chunk_length, RW_SEEK_CUR);
+    return SDL_TRUE;
+}
+
+static SDL_bool AddLoopPoint(WAVStream *wave, Uint32 play_count, Uint32 start, Uint32 stop)
+{
+    WAVLoopPoint *loop;
+    WAVLoopPoint *loops = SDL_realloc(wave->loops, (wave->numloops + 1)*sizeof(*wave->loops));
+    if (!loops) {
+        Mix_SetError("Out of memory");
+        return SDL_FALSE;
     }
-    if ( was_error ) {
-        return NULL;
+
+    loop = &loops[ wave->numloops ];
+    loop->start = start;
+    loop->stop = stop;
+    loop->initial_play_count = play_count;
+    loop->current_play_count = play_count;
+
+    wave->loops = loops;
+    ++wave->numloops;
+    return SDL_TRUE;
+}
+
+static SDL_bool ParseSMPL(WAVStream *wave, Uint32 chunk_length)
+{
+    SamplerChunk *chunk;
+    Uint8 *data;
+    int i;
+    SDL_bool loaded = SDL_FALSE;
+
+    data = (Uint8 *)SDL_malloc(chunk_length);
+    if (!data) {
+        Mix_SetError("Out of memory");
+        return SDL_FALSE;
     }
-    return(src);
+    if (!SDL_RWread(wave->src, data, chunk_length, 1)) {
+        Mix_SetError("Couldn't read %d bytes from WAV file", chunk_length);
+        return SDL_FALSE;
+    }
+    chunk = (SamplerChunk *)data;
+
+    for (i = 0; i < SDL_SwapLE32(chunk->sample_loops); ++i) {
+        const Uint32 LOOP_TYPE_FORWARD = 0;
+        Uint32 loop_type = SDL_SwapLE32(chunk->loops[i].type);
+        if (loop_type == LOOP_TYPE_FORWARD) {
+            AddLoopPoint(wave, SDL_SwapLE32(chunk->loops[i].play_count), SDL_SwapLE32(chunk->loops[i].start), SDL_SwapLE32(chunk->loops[i].end));
+        }
+    }
+
+    loaded = SDL_TRUE;
+
+done:
+    SDL_free(data);
+    return loaded;
+}
+
+static SDL_bool LoadWAVStream(WAVStream *wave)
+{
+    SDL_RWops *src = wave->src;
+    Uint32 chunk_type;
+    Uint32 chunk_length;
+    SDL_bool found_FMT = SDL_FALSE;
+    SDL_bool found_DATA = SDL_FALSE;
+
+    /* WAV magic header */
+    Uint32 wavelen;
+    Uint32 WAVEmagic;
+
+    /* Check the magic header */
+    wavelen = SDL_ReadLE32(src);
+    WAVEmagic = SDL_ReadLE32(src);
+
+    /* Read the chunks */
+    for (; ;) {
+        chunk_type = SDL_ReadLE32(src);
+        chunk_length = SDL_ReadLE32(src);
+
+        if (chunk_length == 0)
+            break;
+
+        switch (chunk_type)
+        {
+        case FMT:
+            found_FMT = SDL_TRUE;
+            if (!ParseFMT(wave, chunk_length))
+                return SDL_FALSE;
+            break;
+        case DATA:
+            found_DATA = SDL_TRUE;
+            if (!ParseDATA(wave, chunk_length))
+                return SDL_FALSE;
+            break;
+        case SMPL:
+            if (!ParseSMPL(wave, chunk_length))
+                return SDL_FALSE;
+            break;
+        default:
+            SDL_RWseek(src, chunk_length, RW_SEEK_CUR);
+            break;
+        }
+    }
+
+    if (!found_FMT) {
+        Mix_SetError("Bad WAV file (no FMT chunk)");
+        return SDL_FALSE;
+    }
+
+    if (!found_DATA) {
+        Mix_SetError("Bad WAV file (no DATA chunk)");
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
 }
 
 /* I couldn't get SANE_to_double() to work, so I stole this from libsndfile.
@@ -385,16 +519,16 @@
     if (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C)
         return 800000000;
 
-    return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
-        | (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
+    return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7) |
+            (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
 }
 
-static SDL_RWops *LoadAIFFStream (SDL_RWops *src, SDL_AudioSpec *spec,
-                    long *start, long *stop)
+static SDL_bool LoadAIFFStream(WAVStream *wave)
 {
-    int was_error;
-    int found_SSND;
-    int found_COMM;
+    SDL_RWops *src = wave->src;
+    SDL_AudioSpec *spec = &wave->spec;
+    SDL_bool found_SSND = SDL_FALSE;
+    SDL_bool found_COMM = SDL_FALSE;
 
     Uint32 chunk_type;
     Uint32 chunk_length;
@@ -412,27 +546,20 @@
     Uint8 sane_freq[10];
     Uint32 frequency = 0;
 
-    was_error = 0;
-
     /* Check the magic header */
-    chunk_length    = SDL_ReadBE32(src);
-    AIFFmagic   = SDL_ReadLE32(src);
-    if ( AIFFmagic != AIFF ) {
+    chunk_length = SDL_ReadBE32(src);
+    AIFFmagic = SDL_ReadLE32(src);
+    if (AIFFmagic != AIFF) {
         Mix_SetError("Unrecognized file type (not AIFF)");
-        was_error = 1;
-        goto done;
+        return SDL_FALSE;
     }
 
     /* From what I understand of the specification, chunks may appear in
-         * any order, and we should just ignore unknown ones.
+     * any order, and we should just ignore unknown ones.
      *
      * TODO: Better sanity-checking. E.g. what happens if the AIFF file
      *       contains compressed sound data?
      */
-
-    found_SSND = 0;
-    found_COMM = 0;
-
     do {
         chunk_type      = SDL_ReadLE32(src);
         chunk_length    = SDL_ReadBE32(src);
@@ -440,25 +567,25 @@
 
         /* Paranoia to avoid infinite loops */
         if (chunk_length == 0)
-        break;
+            break;
 
         switch (chunk_type) {
         case SSND:
-            found_SSND      = 1;
-            offset      = SDL_ReadBE32(src);
-            blocksize       = SDL_ReadBE32(src);
-            *start      = (long)SDL_RWtell(src) + offset;
+            found_SSND = SDL_TRUE;
+            offset = SDL_ReadBE32(src);
+            blocksize = SDL_ReadBE32(src);
+            wave->start = SDL_RWtell(src) + offset;
             break;
 
         case COMM:
-            found_COMM      = 1;
+            found_COMM = SDL_TRUE;
 
             /* Read the audio data format chunk */
-            channels        = SDL_ReadBE16(src);
-            numsamples      = SDL_ReadBE32(src);
-            samplesize      = SDL_ReadBE16(src);
+            channels = SDL_ReadBE16(src);
+            numsamples = SDL_ReadBE32(src);
+            samplesize = SDL_ReadBE16(src);
             SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
-            frequency       = SANE_to_Uint32(sane_freq);
+            frequency = SANE_to_Uint32(sane_freq);
             break;
 
         default:
@@ -469,17 +596,15 @@
 
     if (!found_SSND) {
         Mix_SetError("Bad AIFF file (no SSND chunk)");
-        was_error = 1;
-        goto done;
+        return SDL_FALSE;
     }
 
     if (!found_COMM) {
         Mix_SetError("Bad AIFF file (no COMM chunk)");
-        was_error = 1;
-        goto done;
+        return SDL_FALSE;
     }
 
-    *stop = *start + channels * numsamples * (samplesize / 8);
+    wave->stop = wave->start + channels * numsamples * (samplesize / 8);
 
     /* Decode the audio data format */
     SDL_memset(spec, 0, (sizeof *spec));
@@ -493,16 +618,11 @@
             break;
         default:
             Mix_SetError("Unknown samplesize in data format");
-            was_error = 1;
-            goto done;
+            return SDL_FALSE;
     }
     spec->channels = (Uint8) channels;
     spec->samples = 4096;       /* Good default buffer size */
 
-done:
-    if ( was_error ) {
-        return NULL;
-    }
-    return(src);
+    return SDL_TRUE;
 }
 
diff -r 4abaa52275ac -r 1ef7c1254ffb wavestream.h
--- a/wavestream.h	Fri Jun 26 19:27:27 2015 -0700
+++ b/wavestream.h	Tue Jul 07 11:43:05 2015 -0700
@@ -21,16 +21,25 @@
 
 /* $Id$ */
 
-/* This file supports streaming WAV files, without volume adjustment */
+/* This file supports streaming WAV files */
 
-#include <stdio.h>
+typedef struct {
+    SDL_bool active;
+    Uint32 start;
+    Uint32 stop;
+    Uint32 initial_play_count;
+    Uint32 current_play_count;
+} WAVLoopPoint;
 
 typedef struct {
     SDL_RWops *src;
     SDL_bool freesrc;
-    long  start;
-    long  stop;
+    SDL_AudioSpec spec;
+    Sint64 start;
+    Sint64 stop;
     SDL_AudioCVT cvt;
+    int numloops;
+    WAVLoopPoint *loops;
 } WAVStream;
 
 /* Initialize the WAVStream player, with the given mixer settings


More information about the commits mailing list