changeset 231:d3dc34315ac7

Rewind method implemented by Torbj�rn.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 19 Jan 2002 16:58:34 +0000
parents aa4137f121e4
children 34000a50353b
files decoders/flac.c decoders/midi.c decoders/mikmod.c decoders/modplug.c decoders/mp3.c decoders/ogg.c
diffstat 6 files changed, 65 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/decoders/flac.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/flac.c	Sat Jan 19 16:58:34 2002 +0000
@@ -45,6 +45,12 @@
 #define __SDL_SOUND_INTERNAL__
 #include "SDL_sound_internal.h"
 
+/*
+ * libFLAC 1.0.1 added a seekable stream decoder, but if I understand the
+ * documentation correctly it's still much easier for us to handle the rewind
+ * method ourselves.
+ */
+
 #include "FLAC/stream_decoder.h"
 
 
@@ -80,6 +86,7 @@
     FLAC__StreamDecoder *decoder;
     SDL_RWops *rw;
     Sound_Sample *sample;
+    Uint32 data_starting_offset;
     Uint32 frame_size;
     Uint8 is_flac;
 } flac_t;
@@ -302,6 +309,13 @@
     FLAC__stream_decoder_init(decoder);
 
         /*
+         * Annoyingly, the rewind method will put the FLAC decoder in a state
+         * where it expects to read metadata, so we have to set this marker
+         * before the metadata block.
+         */
+    f->data_starting_offset = SDL_RWtell(f->rw);
+    
+        /*
          * If we are not sure this is a FLAC stream, check for the STREAMINFO
          * metadata block. If not, we'd have to peek at the first audio frame
          * and get the sound format from there, but that is not yet
@@ -342,12 +356,6 @@
     flac_t *f = (flac_t *) internal->decoder_private;
     Uint32 len;
 
-    if (FLAC__stream_decoder_get_state(f->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
-    {
-        sample->flags |= SOUND_SAMPLEFLAG_EOF;
-        return(0);
-    } /* if */
-
     if (!FLAC__stream_decoder_process_one_frame(f->decoder))
     {
         Sound_SetError("FLAC: Couldn't decode frame.");
@@ -355,20 +363,31 @@
         return(0);
     } /* if */
 
+    if (FLAC__stream_decoder_get_state(f->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+    {
+        sample->flags |= SOUND_SAMPLEFLAG_EOF;
+        return(0);
+    } /* if */
+
         /* An error may have been signalled through the error callback. */    
     if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
         return(0);
-    
+
     return(f->frame_size);
 } /* FLAC_read */
 
 
 static int FLAC_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("FLAC_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    flac_t *f = (flac_t *) internal->decoder_private;
+    int rc = SDL_RWseek(f->rw, f->data_starting_offset, SEEK_SET);
+    
+    BAIL_IF_MACRO(rc != f->data_starting_offset, ERR_IO_ERROR, 0);
+    BAIL_IF_MACRO(!FLAC__stream_decoder_reset(f->decoder),
+                  "FLAC: could not reset decoder", 0);
+    FLAC__stream_decoder_process_metadata(f->decoder);
+    return(1);
 } /* FLAC_rewind */
 
 #endif /* SOUND_SUPPORTS_FLAC */
--- a/decoders/midi.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/midi.c	Sat Jan 19 16:58:34 2002 +0000
@@ -150,13 +150,13 @@
 
 static int MIDI_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("MIDI_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    MidiSong *song = (MidiSong *) internal->decoder_private;
+    
+    Timidity_Start(song);
+    return(1);
 } /* MIDI_rewind */
 
-
 #endif /* SOUND_SUPPORTS_MIDI */
 
 
--- a/decoders/mikmod.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/mikmod.c	Sat Jan 19 16:58:34 2002 +0000
@@ -287,10 +287,12 @@
 
 static int MIKMOD_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("MIKMOD_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    MODULE *module = (MODULE *) internal->decoder_private;
+
+    Player_Start(module);
+    Player_SetPosition(0);
+    return(1);
 } /* MIKMOD_rewind */
 
 
--- a/decoders/modplug.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/modplug.c	Sat Jan 19 16:58:34 2002 +0000
@@ -237,10 +237,11 @@
 
 static int MODPLUG_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("MODPLUG_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
+
+    ModPlug_Seek(module, 0);
+    return(1);
 } /* MODPLUG_rewind */
 
 #endif /* SOUND_SUPPORTS_MODPLUG */
--- a/decoders/mp3.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/mp3.c	Sat Jan 19 16:58:34 2002 +0000
@@ -239,7 +239,7 @@
          * We have to clear the buffer because apparently SMPEG_playAudio()
          * will mix the decoded audio with whatever's already in it. Nasty.
          */
-    memset(internal->buffer, 0, internal->buffer_size);
+    memset(internal->buffer, '\0', internal->buffer_size);
     retval = SMPEG_playAudio(smpeg, internal->buffer, internal->buffer_size);
     if (retval < internal->buffer_size)
     {
@@ -259,10 +259,19 @@
 
 static int MP3_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("MP3_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    SMPEG *smpeg = (SMPEG *) internal->decoder_private;
+    SMPEGstatus status;
+
+        /*
+         * SMPEG_rewind() really means "stop and rewind", so we may have to
+         * restart it afterwards.
+         */
+    status = SMPEG_status(smpeg);
+    SMPEG_rewind(smpeg);
+    if (status == SMPEG_PLAYING)
+        SMPEG_play(smpeg);
+    return(1);
 } /* MP3_rewind */
 
 #endif /* SOUND_SUPPORTS_MP3 */
--- a/decoders/ogg.c	Sat Jan 19 03:11:26 2002 +0000
+++ b/decoders/ogg.c	Sat Jan 19 16:58:34 2002 +0000
@@ -268,10 +268,11 @@
 
 static int OGG_rewind(Sound_Sample *sample)
 {
-    /* !!! FIXME. */
-    SNDDBG(("OGG_rewind(): Write me!\n"));
-    assert(0);
-    return(0);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
+
+    BAIL_IF_MACRO(ov_raw_seek(vf, 0) < 0, ERR_IO_ERROR, 0);
+    return(1);
 } /* OGG_rewind */
 
 #endif /* SOUND_SUPPORTS_OGG */