changeset 221:c9772a9f5271

Initial implementation or stubs for rewind method. Other cleanups.
author Ryan C. Gordon <icculus@icculus.org>
date Thu, 17 Jan 2002 20:53:53 +0000
parents ef72f3c490e7
children d6b24586822a
files decoders/aiff.c decoders/au.c decoders/flac.c decoders/midi.c decoders/mikmod.c decoders/modplug.c decoders/mp3.c decoders/ogg.c decoders/raw.c decoders/shn.c decoders/skeleton.c decoders/voc.c decoders/wav.c
diffstat 13 files changed, 289 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/decoders/aiff.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/aiff.c	Thu Jan 17 20:53:53 2002 +0000
@@ -65,6 +65,7 @@
 static int AIFF_open(Sound_Sample *sample, const char *ext);
 static void AIFF_close(Sound_Sample *sample);
 static Uint32 AIFF_read(Sound_Sample *sample);
+static int AIFF_rewind(Sound_Sample *sample);
 
 static const char *extensions_aiff[] = { "AIFF", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_AIFF =
@@ -76,11 +77,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    AIFF_init,      /*  init() method */
-    AIFF_quit,      /*  quit() method */
-    AIFF_open,      /*  open() method */
-    AIFF_close,     /* close() method */
-    AIFF_read       /*  read() method */
+    AIFF_init,      /*   init() method */
+    AIFF_quit,      /*   quit() method */
+    AIFF_open,      /*   open() method */
+    AIFF_close,     /*  close() method */
+    AIFF_read,      /*   read() method */
+    AIFF_rewind     /* rewind() method */
 };
 
 
@@ -90,8 +92,14 @@
 typedef struct S_AIFF_FMT_T
 {
     Uint32 type;
+
+    Uint32 total_bytes;
+    Uint32 data_starting_offset;
+
     void (*free)(struct S_AIFF_FMT_T *fmt);
-    Uint32(*read_sample)(Sound_Sample *sample);
+    Uint32 (*read_sample)(Sound_Sample *sample);
+    int (*rewind_sample)(Sound_Sample *sample);
+
 
 #if 0
 /*
@@ -315,6 +323,13 @@
 } /* read_sample_fmt_normal */
 
 
+static int rewind_sample_fmt_normal(Sound_Sample *sample)
+{
+    /* no-op. */
+    return(1);
+} /* rewind_sample_fmt_normal */
+
+
 static void free_fmt_normal(fmt_t *fmt)
 {
     /* it's a no-op. */
@@ -326,6 +341,7 @@
     /* (don't need to read more from the RWops...) */
     fmt->free = free_fmt_normal;
     fmt->read_sample = read_sample_fmt_normal;
+    fmt->rewind_sample = rewind_sample_fmt_normal;
     return(1);
 } /* read_fmt_normal */
 
@@ -487,7 +503,8 @@
         return(0);
     } /* if */
 
-    a->bytesLeft = bytes_per_sample * c.numSampleFrames;
+    a->fmt.total_bytes = a->bytesLeft = bytes_per_sample * c.numSampleFrames;
+    a->fmt.data_starting_offset = SDL_RWtell(rw);
     internal->decoder_private = (void *) a;
 
     sample->flags = SOUND_SAMPLEFLAG_NONE;
@@ -513,6 +530,18 @@
     return(a->fmt.read_sample(sample));
 } /* AIFF_read */
 
+
+static int AIFF_rewind(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    aiff_t *a = (aiff_t *) internal->decoder_private;
+    fmt_t *fmt = &a->fmt;
+    int rc = SDL_RWseek(internal->rw, fmt->data_starting_offset, SEEK_SET);
+    BAIL_IF_MACRO(rc != fmt->data_starting_offset, ERR_IO_ERROR, 0);
+    a->bytesLeft = fmt->total_bytes;
+    return(fmt->rewind_sample(sample));
+} /* AIFF_rewind */
+
 #endif /* SOUND_SUPPORTS_AIFF */
 
 /* end of aiff.c ... */
--- a/decoders/au.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/au.c	Thu Jan 17 20:53:53 2002 +0000
@@ -48,6 +48,7 @@
 static int AU_open(Sound_Sample *sample, const char *ext);
 static void AU_close(Sound_Sample *sample);
 static Uint32 AU_read(Sound_Sample *sample);
+static int AU_rewind(Sound_Sample *sample);
 
 /*
  * Sometimes the extension ".snd" is used for these files (mostly on the NeXT),
@@ -64,11 +65,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    AU_init,
-    AU_quit,
-    AU_open,
-    AU_close,
-    AU_read
+    AU_init,        /*   init() method */
+    AU_quit,        /*   quit() method */
+    AU_open,        /*   open() method */
+    AU_close,       /*  close() method */
+    AU_read,        /*   read() method */
+    AU_rewind       /* rewind() method */
 };
 
 /* no init/deinit needed */
@@ -115,7 +117,9 @@
 
 struct audec
 {
-    unsigned remaining;
+    Uint32 total;
+    Uint32 remaining;
+    Uint32 start_offset;
     int encoding;
 };
 
@@ -141,6 +145,10 @@
         return(0);
     } /* if */
 
+        /*
+         * !!! FIXME: For correctness, we should calculate this as a bigendian
+         * !!! FIXME:  number, which means swapping AU_MAGIC around.
+         */
     if (SDL_SwapLE32(hdr.magic) == AU_MAGIC)
     {
         /* valid magic */
@@ -204,6 +212,8 @@
     } /* else */
 
     sample->flags = SOUND_SAMPLEFLAG_NONE;
+    dec->total = dec->remaining;
+    dec->start_offset = SDL_RWtell(rw);
 
     SNDDBG(("AU: Accepting data stream.\n"));
     return(1);
@@ -273,7 +283,7 @@
         buf += maxlen;
     } /* if */
 
-    if(maxlen > dec->remaining)
+    if (maxlen > dec->remaining)
         maxlen = dec->remaining;
     ret = SDL_RWread(internal->rw, buf, 1, maxlen);
     if (ret == 0)
@@ -299,5 +309,16 @@
     return(ret);
 } /* AU_read */
 
+
+static int AU_rewind(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    struct audec *dec = (struct audec *) internal->decoder_private;
+    int rc = SDL_RWseek(internal->rw, dec->start_offset, SEEK_SET);
+    BAIL_IF_MACRO(rc != dec->start_offset, ERR_IO_ERROR, 0);
+    dec->remaining = dec->total;
+    return(1);
+} /* AU_rewind */
+
 #endif /* SOUND_SUPPORTS_AU */
 
--- a/decoders/flac.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/flac.c	Thu Jan 17 20:53:53 2002 +0000
@@ -53,6 +53,7 @@
 static int FLAC_open(Sound_Sample *sample, const char *ext);
 static void FLAC_close(Sound_Sample *sample);
 static Uint32 FLAC_read(Sound_Sample *sample);
+static int FLAC_rewind(Sound_Sample *sample);
 
 static const char *extensions_flac[] = { "FLAC", "FLA", NULL };
 
@@ -65,11 +66,12 @@
         "http://flac.sourceforge.net/"
     },
 
-    FLAC_init,       /* init() method       */
-    FLAC_quit,       /* quit() method       */
-    FLAC_open,       /* open() method       */
-    FLAC_close,      /* close() method       */
-    FLAC_read        /* read() method       */
+    FLAC_init,       /*   init() method */
+    FLAC_quit,       /*   quit() method */
+    FLAC_open,       /*   open() method */
+    FLAC_close,      /*  close() method */
+    FLAC_read,       /*   read() method */
+    FLAC_rewind      /* rewind() method */
 };
 
     /* This is what we store in our internal->decoder_private field. */
@@ -360,6 +362,15 @@
     return(f->frame_size);
 } /* FLAC_read */
 
+
+static int FLAC_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("FLAC_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* FLAC_rewind */
+
 #endif /* SOUND_SUPPORTS_FLAC */
 
 
--- a/decoders/midi.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/midi.c	Thu Jan 17 20:53:53 2002 +0000
@@ -52,6 +52,7 @@
 static int MIDI_open(Sound_Sample *sample, const char *ext);
 static void MIDI_close(Sound_Sample *sample);
 static Uint32 MIDI_read(Sound_Sample *sample);
+static int MIDI_rewind(Sound_Sample *sample);
 
 static const char *extensions_midi[] = { "MIDI", "MID", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_MIDI =
@@ -63,11 +64,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    MIDI_init,       /* init() method       */
-    MIDI_quit,       /* quit() method       */
-    MIDI_open,       /* open() method       */
-    MIDI_close,      /* close() method       */
-    MIDI_read        /* read() method       */
+    MIDI_init,       /*   init() method */
+    MIDI_quit,       /*   quit() method */
+    MIDI_open,       /*   open() method */
+    MIDI_close,      /*  close() method */
+    MIDI_read,       /*   read() method */
+    MIDI_rewind      /* rewind() method */
 };
 
 
@@ -145,6 +147,16 @@
     return(retval);
 } /* MIDI_read */
 
+
+static int MIDI_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("MIDI_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* MIDI_rewind */
+
+
 #endif /* SOUND_SUPPORTS_MIDI */
 
 
--- a/decoders/mikmod.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/mikmod.c	Thu Jan 17 20:53:53 2002 +0000
@@ -50,6 +50,7 @@
 static int MIKMOD_open(Sound_Sample *sample, const char *ext);
 static void MIKMOD_close(Sound_Sample *sample);
 static Uint32 MIKMOD_read(Sound_Sample *sample);
+static int MIKMOD_rewind(Sound_Sample *sample);
 
 static const char *extensions_mikmod[] =
 {
@@ -83,11 +84,12 @@
         "http://www.mikmod.org/"
     },
 
-    MIKMOD_init,       /*  init() method */
-    MIKMOD_quit,       /*  quit() method */
-    MIKMOD_open,       /*  open() method */
-    MIKMOD_close,      /* close() method */
-    MIKMOD_read        /*  read() method */
+    MIKMOD_init,       /*   init() method */
+    MIKMOD_quit,       /*   quit() method */
+    MIKMOD_open,       /*   open() method */
+    MIKMOD_close,      /*  close() method */
+    MIKMOD_read,       /*   read() method */
+    MIKMOD_rewind      /* rewind() method */
 };
 
 
@@ -282,6 +284,17 @@
     return((Uint32) VC_WriteBytes(internal->buffer, internal->buffer_size));
 } /* MIKMOD_read */
 
+
+static int MIKMOD_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("MIKMOD_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* MIKMOD_rewind */
+
+
+
 #endif /* SOUND_SUPPORTS_MIKMOD */
 
 
--- a/decoders/modplug.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/modplug.c	Thu Jan 17 20:53:53 2002 +0000
@@ -49,6 +49,7 @@
 static int MODPLUG_open(Sound_Sample *sample, const char *ext);
 static void MODPLUG_close(Sound_Sample *sample);
 static Uint32 MODPLUG_read(Sound_Sample *sample);
+static int MODPLUG_rewind(Sound_Sample *sample);
 
 static const char *extensions_modplug[] =
 {
@@ -91,11 +92,12 @@
         "http://modplug-xmms.sourceforge.net/"
     },
 
-    MODPLUG_init,       /*  init() method */
-    MODPLUG_quit,       /*  quit() method */
-    MODPLUG_open,       /*  open() method */
-    MODPLUG_close,      /* close() method */
-    MODPLUG_read        /*  read() method */
+    MODPLUG_init,       /*   init() method */
+    MODPLUG_quit,       /*   quit() method */
+    MODPLUG_open,       /*   open() method */
+    MODPLUG_close,      /*  close() method */
+    MODPLUG_read,       /*   read() method */
+    MODPLUG_rewind      /* rewind() method */
 };
 
 
@@ -135,7 +137,8 @@
 } /* MODPLUG_quit */
 
 
-/* Most MOD files I've seen have tended to be a few hundred KB, even if some
+/*
+ * Most MOD files I've seen have tended to be a few hundred KB, even if some
  * of them were much smaller than that.
  */
 #define CHUNK_SIZE 65536
@@ -150,23 +153,25 @@
     int has_extension = 0;
     int i;
 
-    /* Apparently ModPlug's loaders are too forgiving. They gladly accept
-     * streams that they shouldn't. For now, rely on file extension instead.
+    /*
+     * Apparently ModPlug's loaders are too forgiving. They gladly accept
+     *  streams that they shouldn't. For now, rely on file extension instead.
      */
     for (i = 0; extensions_modplug[i] != NULL; i++)
     {
-	if (__Sound_strcasecmp(ext, extensions_modplug[i]) == 0)
-	{
-	    has_extension = 1;
-	    break;
-	} /* if */
+        if (__Sound_strcasecmp(ext, extensions_modplug[i]) == 0)
+        {
+            has_extension = 1;
+            break;
+        } /* if */
     } /* for */
 
     if (!has_extension)
     {
-	SNDDBG(("MODPLUG: Unrecognized file type: %s\n", ext));
-	return(0);
-    }
+        SNDDBG(("MODPLUG: Unrecognized file type: %s\n", ext));
+        Sound_SetError("MODPLUG: Not a module file.");
+        return(0);
+    } /* if */
     
         /* ModPlug needs the entire stream in one big chunk. I don't like it,
          * but I don't think there's any way around it.
@@ -229,6 +234,15 @@
     return(retval);
 } /* MODPLUG_read */
 
+
+static int MODPLUG_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("MODPLUG_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* MODPLUG_rewind */
+
 #endif /* SOUND_SUPPORTS_MODPLUG */
 
 
--- a/decoders/mp3.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/mp3.c	Thu Jan 17 20:53:53 2002 +0000
@@ -56,6 +56,7 @@
 static int MP3_open(Sound_Sample *sample, const char *ext);
 static void MP3_close(Sound_Sample *sample);
 static Uint32 MP3_read(Sound_Sample *sample);
+static int MP3_rewind(Sound_Sample *sample);
 
 static const char *extensions_smpeg[] = { "MP3", "MPEG", "MPG", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_MP3 =
@@ -67,11 +68,12 @@
         "http://www.lokigames.com/development/smpeg.php3"
     },
 
-    MP3_init,       /*  init() method */
-    MP3_quit,       /*  quit() method */
-    MP3_open,       /*  open() method */
-    MP3_close,      /* close() method */
-    MP3_read        /*  read() method */
+    MP3_init,       /*   init() method */
+    MP3_quit,       /*   quit() method */
+    MP3_open,       /*   open() method */
+    MP3_close,      /*  close() method */
+    MP3_read,       /*   read() method */
+    MP3_rewind      /* rewind() method */
 };
 
 
@@ -254,6 +256,15 @@
     return(retval);
 } /* MP3_read */
 
+
+static int MP3_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("MP3_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* MP3_rewind */
+
 #endif /* SOUND_SUPPORTS_MP3 */
 
 /* end of mp3.c ... */
--- a/decoders/ogg.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/ogg.c	Thu Jan 17 20:53:53 2002 +0000
@@ -58,6 +58,7 @@
 static int OGG_open(Sound_Sample *sample, const char *ext);
 static void OGG_close(Sound_Sample *sample);
 static Uint32 OGG_read(Sound_Sample *sample);
+static int OGG_rewind(Sound_Sample *sample);
 
 static const char *extensions_ogg[] = { "OGG", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_OGG =
@@ -69,11 +70,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    OGG_init,       /*  init() method */
-    OGG_quit,       /*  quit() method */
-    OGG_open,       /*  open() method */
-    OGG_close,      /* close() method */
-    OGG_read        /*  read() method */
+    OGG_init,       /*   init() method */
+    OGG_quit,       /*   quit() method */
+    OGG_open,       /*   open() method */
+    OGG_close,      /*  close() method */
+    OGG_read,       /*   read() method */
+    OGG_rewind      /* rewind() method */
 };
 
 
@@ -263,6 +265,15 @@
     return((Uint32) rc);
 } /* OGG_read */
 
+
+static int OGG_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("OGG_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* OGG_rewind */
+
 #endif /* SOUND_SUPPORTS_OGG */
 
 
--- a/decoders/raw.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/raw.c	Thu Jan 17 20:53:53 2002 +0000
@@ -59,6 +59,7 @@
 static int RAW_open(Sound_Sample *sample, const char *ext);
 static void RAW_close(Sound_Sample *sample);
 static Uint32 RAW_read(Sound_Sample *sample);
+static int RAW_rewind(Sound_Sample *sample);
 
 static const char *extensions_raw[] = { "RAW", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_RAW =
@@ -70,11 +71,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    RAW_init,       /*  init() method */
-    RAW_quit,       /*  quit() method */
-    RAW_open,       /*  open() method */
-    RAW_close,      /* close() method */
-    RAW_read        /*  read() method */
+    RAW_init,       /*   init() method */
+    RAW_quit,       /*   quit() method */
+    RAW_open,       /*   open() method */
+    RAW_close,      /*  close() method */
+    RAW_read,       /*   read() method */
+    RAW_rewind      /* rewind() method */
 };
 
 
@@ -159,6 +161,15 @@
     return(retval);
 } /* RAW_read */
 
+
+static int RAW_rewind(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
+    return(1);
+} /* RAW_rewind */
+
+
 #endif /* SOUND_SUPPORTS_RAW */
 
 
--- a/decoders/shn.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/shn.c	Thu Jan 17 20:53:53 2002 +0000
@@ -66,6 +66,7 @@
 static int SHN_open(Sound_Sample *sample, const char *ext);
 static void SHN_close(Sound_Sample *sample);
 static Uint32 SHN_read(Sound_Sample *sample);
+static int SHN_rewind(Sound_Sample *sample);
 
 static const char *extensions_shn[] = { "SHN", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_SHN =
@@ -77,11 +78,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    SHN_init,       /* init() method       */
-    SHN_quit,       /* quit() method       */
-    SHN_open,       /* open() method       */
-    SHN_close,      /* close() method       */
-    SHN_read        /* read() method       */
+    SHN_init,       /*   init() method */
+    SHN_quit,       /*   quit() method */
+    SHN_open,       /*   open() method */
+    SHN_close,      /*  close() method */
+    SHN_read,       /*   read() method */
+    SHN_rewind      /* rewind() method */
 };
 
 
@@ -1296,6 +1298,15 @@
     return(retval);
 } /* SHN_read */
 
+
+static int SHN_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("SHN_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* SHN_rewind */
+
 #endif  /* defined SOUND_SUPPORTS_SHN */
 
 /* end of shn.c ... */
--- a/decoders/skeleton.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/skeleton.c	Thu Jan 17 20:53:53 2002 +0000
@@ -24,6 +24,9 @@
  *  have done a search and replace on "fmt" and "FMT" and changed this
  *  comment. This is the default comment in the skeleton decoder file...
  *
+ * None of this code, even the parts that LOOK right, have been compiled,
+ *  so you cut-and-paste at your own risk.
+ *
  * Please see the file COPYING in the source's root directory.
  *
  *  This file written by Ryan C. Gordon. (icculus@clutteredmind.org)
@@ -55,6 +58,7 @@
 static int FMT_open(Sound_Sample *sample, const char *ext);
 static void FMT_close(Sound_Sample *sample);
 static Uint32 FMT_read(Sound_Sample *sample);
+static int FMT_rewind(Sound_Sample *sample);
 
 static const char *extensions_fmt[] = { "FMT", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_FMT =
@@ -66,11 +70,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    FMT_init,       /* init() method       */
-    FMT_quit,       /* quit() method       */
-    FMT_open,       /* open() method       */
-    FMT_close,      /* close() method       */
-    FMT_read        /* read() method       */
+    FMT_init,       /*   init() method */
+    FMT_quit,       /*   quit() method */
+    FMT_open,       /*   open() method */
+    FMT_close,      /*  close() method */
+    FMT_read,       /*   read() method */
+    FMT_rewind      /* rewind() method */
 };
 
 
@@ -143,6 +148,19 @@
     return(retval);
 } /* FMT_read */
 
+
+static int FMT_rewind(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+
+        /* seek to the appropriate place... */
+    BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
+
+    (reset state as necessary.)
+
+    return(1);  /* success. */
+} /* FMT_rewind */
+
 #endif /* SOUND_SUPPORTS_FMT */
 
 
--- a/decoders/voc.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/voc.c	Thu Jan 17 20:53:53 2002 +0000
@@ -58,6 +58,7 @@
 static int VOC_open(Sound_Sample *sample, const char *ext);
 static void VOC_close(Sound_Sample *sample);
 static Uint32 VOC_read(Sound_Sample *sample);
+static int VOC_rewind(Sound_Sample *sample);
 
 static const char *extensions_voc[] = { "VOC", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC =
@@ -69,11 +70,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    VOC_init,       /*  init() method */
-    VOC_quit,       /*  quit() method */
-    VOC_open,       /*  open() method */
-    VOC_close,      /* close() method */
-    VOC_read        /*  read() method */
+    VOC_init,       /*   init() method */
+    VOC_quit,       /*   quit() method */
+    VOC_open,       /*   open() method */
+    VOC_close,      /*  close() method */
+    VOC_read,       /*   read() method */
+    VOC_rewind      /* rewind() method */
 };
 
 
@@ -487,6 +489,15 @@
     return(v->bufpos);
 } /* VOC_read */
 
+
+static int VOC_rewind(Sound_Sample *sample)
+{
+    /* !!! FIXME. */
+    SNDDBG(("VOC_rewind(): Write me!\n"));
+    assert(0);
+    return(0);
+} /* VOC_rewind */
+
 #endif /* SOUND_SUPPORTS_VOC */
 
 /* end of voc.c ... */
--- a/decoders/wav.c	Thu Jan 17 20:53:03 2002 +0000
+++ b/decoders/wav.c	Thu Jan 17 20:53:53 2002 +0000
@@ -49,6 +49,7 @@
 static int WAV_open(Sound_Sample *sample, const char *ext);
 static void WAV_close(Sound_Sample *sample);
 static Uint32 WAV_read(Sound_Sample *sample);
+static int WAV_rewind(Sound_Sample *sample);
 
 static const char *extensions_wav[] = { "WAV", NULL };
 const Sound_DecoderFunctions __Sound_DecoderFunctions_WAV =
@@ -60,11 +61,12 @@
         "http://www.icculus.org/SDL_sound/"
     },
 
-    WAV_init,       /*  init() method */
-    WAV_quit,       /*  quit() method */
-    WAV_open,       /*  open() method */
-    WAV_close,      /* close() method */
-    WAV_read        /*  read() method */
+    WAV_init,       /*   init() method */
+    WAV_quit,       /*   quit() method */
+    WAV_open,       /*   open() method */
+    WAV_close,      /*  close() method */
+    WAV_read,       /*   read() method */
+    WAV_rewind      /* rewind() method */
 };
 
 
@@ -139,9 +141,12 @@
     Uint16 wBitsPerSample;
 
     Uint32 sample_frame_size;
+    Uint32 data_starting_offset;
+    Uint32 total_bytes;
 
     void (*free)(struct S_WAV_FMT_T *fmt);
     Uint32 (*read_sample)(Sound_Sample *sample);
+    int (*rewind_sample)(Sound_Sample *sample);
 
     union
     {
@@ -268,12 +273,19 @@
 } /* read_sample_fmt_normal */
 
 
+static int rewind_sample_fmt_normal(Sound_Sample *sample)
+{
+    /* no-op. */
+    return(1);
+} /* rewind_sample_fmt_normal */
+
 
 static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
 {
     /* (don't need to read more from the RWops...) */
     fmt->free = NULL;
     fmt->read_sample = read_sample_fmt_normal;
+    fmt->rewind_sample = rewind_sample_fmt_normal;
     return(1);
 } /* read_fmt_normal */
 
@@ -486,6 +498,15 @@
 } /* free_fmt_adpcm */
 
 
+static int rewind_sample_fmt_adpcm(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    wav_t *w = (wav_t *) internal->decoder_private;
+    w->fmt->fmt.adpcm.samples_left_in_block = 0;
+    return(1);
+} /* rewind_sample_fmt_adpcm */
+
+
 /*
  * Read in a the adpcm-specific info from disk. This makes this process 
  *  safe regardless of the processor's byte order or how the fmt_t 
@@ -498,6 +519,7 @@
     memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm));
     fmt->free = free_fmt_adpcm;
     fmt->read_sample = read_sample_fmt_adpcm;
+    fmt->rewind_sample = rewind_sample_fmt_adpcm;
 
     BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0);
     BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0);
@@ -629,7 +651,8 @@
     w = (wav_t *) malloc(sizeof(wav_t));
     BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0);
     w->fmt = fmt;
-    w->bytesLeft = d.chunkSize;
+    fmt->total_bytes = w->bytesLeft = d.chunkSize;
+    fmt->data_starting_offset = SDL_RWtell(rw);
 
     /* !!! FIXME: Move this to Sound_SampleInfo ? */
     fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) *
@@ -684,6 +707,18 @@
     return(w->fmt->read_sample(sample));
 } /* WAV_read */
 
+
+static int WAV_rewind(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    wav_t *w = (wav_t *) internal->decoder_private;
+    fmt_t *fmt = w->fmt;
+    int rc = SDL_RWseek(internal->rw, fmt->data_starting_offset, SEEK_SET);
+    BAIL_IF_MACRO(rc != fmt->data_starting_offset, ERR_IO_ERROR, 0);
+    w->bytesLeft = fmt->total_bytes;
+    return(fmt->rewind_sample(sample));
+} /* WAV_rewind */
+
 #endif /* SOUND_SUPPORTS_WAV */
 
 /* end of wav.c ... */