diff decoders/flac.c @ 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 c9772a9f5271
children c97be6e1bd27
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 */