music_mad.c
author Ozkan Sezer <sezeroz@gmail.com>
Sun, 17 Nov 2019 01:10:02 +0300
changeset 972 4e24cc4bcf1e
parent 931 4e7795a92332
permissions -rw-r--r--
remove an .orig file
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #ifdef MUSIC_MP3_MAD
    23 
    24 #include "music_mad.h"
    25 
    26 #include "mad.h"
    27 
    28 
    29 /* NOTE: The dithering functions are GPL, which should be fine if your
    30          application is GPL (which would need to be true if you enabled
    31          libmad support in SDL_mixer). If you're using libmad under the
    32          commercial license, you need to disable this code.
    33 */
    34 /************************ dithering functions ***************************/
    35 
    36 #ifdef MUSIC_MP3_MAD_GPL_DITHERING
    37 
    38 /* All dithering done here is taken from the GPL'ed xmms-mad plugin. */
    39 
    40 /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
    41 /* Any feedback is very welcome. For any question, comments,       */
    42 /* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
    43 /* matumoto@math.keio.ac.jp                                        */
    44 
    45 /* Period parameters */
    46 #define MP3_DITH_N 624
    47 #define MP3_DITH_M 397
    48 #define MATRIX_A 0x9908b0df   /* constant vector a */
    49 #define UPPER_MASK 0x80000000 /* most significant w-r bits */
    50 #define LOWER_MASK 0x7fffffff /* least significant r bits */
    51 
    52 /* Tempering parameters */
    53 #define TEMPERING_MASK_B 0x9d2c5680
    54 #define TEMPERING_MASK_C 0xefc60000
    55 #define TEMPERING_SHIFT_U(y)  (y >> 11)
    56 #define TEMPERING_SHIFT_S(y)  (y << 7)
    57 #define TEMPERING_SHIFT_T(y)  (y << 15)
    58 #define TEMPERING_SHIFT_L(y)  (y >> 18)
    59 
    60 static unsigned long mt[MP3_DITH_N]; /* the array for the state vector  */
    61 static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */
    62 
    63 /* initializing the array with a NONZERO seed */
    64 static void sgenrand(unsigned long seed)
    65 {
    66     /* setting initial seeds to mt[MP3_DITH_N] using         */
    67     /* the generator Line 25 of Table 1 in          */
    68     /* [KNUTH 1981, The Art of Computer Programming */
    69     /*    Vol. 2 (2nd Ed.), pp102]                  */
    70     mt[0]= seed & 0xffffffff;
    71     for (mti=1; mti<MP3_DITH_N; mti++)
    72         mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
    73 }
    74 
    75 static unsigned long genrand(void)
    76 {
    77     unsigned long y;
    78     static unsigned long mag01[2]={0x0, MATRIX_A};
    79     /* mag01[x] = x * MATRIX_A  for x=0,1 */
    80 
    81     if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */
    82         int kk;
    83 
    84         if (mti == MP3_DITH_N+1)   /* if sgenrand() has not been called, */
    85             sgenrand(4357); /* a default initial seed is used   */
    86 
    87         for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) {
    88             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
    89             mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1];
    90         }
    91         for (;kk<MP3_DITH_N-1;kk++) {
    92             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
    93             mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
    94         }
    95         y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
    96         mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1];
    97 
    98         mti = 0;
    99     }
   100 
   101     y = mt[mti++];
   102     y ^= TEMPERING_SHIFT_U(y);
   103     y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
   104     y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
   105     y ^= TEMPERING_SHIFT_L(y);
   106 
   107     return y;
   108 }
   109 
   110 static long triangular_dither_noise(int nbits) {
   111     /* parameter nbits : the peak-to-peak amplitude desired (in bits)
   112      *  use with nbits set to    2 + nber of bits to be trimmed.
   113      * (because triangular is made from two uniformly distributed processes,
   114      * it starts at 2 bits peak-to-peak amplitude)
   115      * see The Theory of Dithered Quantization by Robert Alexander Wannamaker
   116      * for complete proof of why that's optimal
   117      */
   118     long v = (genrand()/2 - genrand()/2); /* in ]-2^31, 2^31[ */
   119     long P = 1 << (32 - nbits); /* the power of 2 */
   120     v /= P;
   121     /* now v in ]-2^(nbits-1), 2^(nbits-1) [ */
   122 
   123     return v;
   124 }
   125 
   126 #endif /* MUSIC_MP3_MAD_GPL_DITHERING */
   127 
   128 
   129 #define MAD_INPUT_BUFFER_SIZE   (5*8192)
   130 
   131 enum {
   132     MS_input_eof      = 0x0001,
   133     MS_input_error    = 0x0001,
   134     MS_decode_error   = 0x0002,
   135     MS_error_flags    = 0x000f,
   136 };
   137 
   138 typedef struct {
   139     int play_count;
   140     SDL_RWops *src;
   141     Sint64 start, length, pos;
   142     int freesrc;
   143     struct mad_stream stream;
   144     struct mad_frame frame;
   145     struct mad_synth synth;
   146     mad_timer_t next_frame_start;
   147     int volume;
   148     int status;
   149     SDL_AudioStream *audiostream;
   150 
   151     unsigned char input_buffer[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
   152 } MAD_Music;
   153 
   154 
   155 static size_t MAD_RWread(MAD_Music *music, void *ptr, size_t size, size_t maxnum) {
   156     size_t remaining = (size_t)(music->length - music->pos);
   157     size_t ret;
   158     maxnum *= size;
   159     if (maxnum > remaining) maxnum = remaining;
   160     ret = SDL_RWread(music->src, ptr, 1, maxnum);
   161     music->pos += (Sint64)ret;
   162     return ret;
   163 }
   164 
   165 static Sint64 MAD_RWseek(MAD_Music *music, Sint64 offset, int whence) {
   166     Sint64 ret;
   167     switch (whence) { /* assumes a legal whence value */
   168     case RW_SEEK_CUR:
   169         offset += music->pos;
   170         break;
   171     case RW_SEEK_END:
   172         offset = music->length + offset;
   173         break;
   174     }
   175     if (offset < 0) return -1;
   176     if (offset > music->length)
   177         offset = music->length;
   178     ret = SDL_RWseek(music->src, music->start + offset, RW_SEEK_SET);
   179     if (ret < 0) return ret;
   180     music->pos = offset;
   181     return (music->pos - music->start);
   182 }
   183 
   184 
   185 static int MAD_Seek(void *context, double position);
   186 static int skip_tags(MAD_Music *music);
   187 
   188 static void *MAD_CreateFromRW(SDL_RWops *src, int freesrc)
   189 {
   190     MAD_Music *music;
   191 
   192     music = (MAD_Music *)SDL_calloc(1, sizeof(MAD_Music));
   193     if (!music) {
   194         SDL_OutOfMemory();
   195         return NULL;
   196     }
   197     music->src = src;
   198     music->volume = MIX_MAX_VOLUME;
   199 
   200     music->length = SDL_RWsize(src);
   201     if (skip_tags(music) < 0) {
   202         SDL_free(music);
   203         Mix_SetError("music_mad: corrupt mp3 file.");
   204         return NULL;
   205     }
   206 
   207     mad_stream_init(&music->stream);
   208     mad_frame_init(&music->frame);
   209     mad_synth_init(&music->synth);
   210     mad_timer_reset(&music->next_frame_start);
   211 
   212     music->freesrc = freesrc;
   213     return music;
   214 }
   215 
   216 static void MAD_SetVolume(void *context, int volume)
   217 {
   218     MAD_Music *music = (MAD_Music *)context;
   219     music->volume = volume;
   220 }
   221 
   222 /* Starts the playback. */
   223 static int MAD_Play(void *context, int play_count)
   224 {
   225     MAD_Music *music = (MAD_Music *)context;
   226     music->play_count = play_count;
   227     return MAD_Seek(music, 0.0);
   228 }
   229 
   230 
   231 /*************************** TAG HANDLING: ******************************/
   232 
   233 static SDL_INLINE SDL_bool is_id3v1(const unsigned char *data, size_t length)
   234 {
   235     /* http://id3.org/ID3v1 :  3 bytes "TAG" identifier and 125 bytes tag data */
   236     if (length < 3 || SDL_memcmp(data,"TAG",3) != 0) {
   237         return SDL_FALSE;
   238     }
   239     return SDL_TRUE;
   240 }
   241 static SDL_INLINE SDL_bool is_id3v1ext(const unsigned char *data, size_t length)
   242 {
   243     /* ID3v1 extended tag: just before ID3v1, always 227 bytes.
   244      * https://www.getid3.org/phpBB3/viewtopic.php?t=1202
   245      * https://en.wikipedia.org/wiki/ID3v1#Enhanced_tag
   246      * Not an official standard, is only supported by few programs. */
   247     if (length < 4 || SDL_memcmp(data,"TAG+",4) != 0) {
   248         return SDL_FALSE;
   249     }
   250     return SDL_TRUE;
   251 }
   252 static SDL_INLINE SDL_bool is_id3v2(const unsigned char *data, size_t length)
   253 {
   254     /* ID3v2 header is 10 bytes:  http://id3.org/id3v2.4.0-structure */
   255     /* bytes 0-2: "ID3" identifier */
   256     if (length < 10 || SDL_memcmp(data,"ID3",3) != 0) {
   257         return SDL_FALSE;
   258     }
   259     /* bytes 3-4: version num (major,revision), each byte always less than 0xff. */
   260     if (data[3] == 0xff || data[4] == 0xff) {
   261         return SDL_FALSE;
   262     }
   263     /* bytes 6-9 are the ID3v2 tag size: a 32 bit 'synchsafe' integer, i.e. the
   264      * highest bit 7 in each byte zeroed.  i.e.: 7 bit information in each byte ->
   265      * effectively a 28 bit value.  */
   266     if (data[6] >= 0x80 || data[7] >= 0x80 || data[8] >= 0x80 || data[9] >= 0x80) {
   267         return SDL_FALSE;
   268     }
   269     return SDL_TRUE;
   270 }
   271 static SDL_INLINE long get_id3v2_len(const unsigned char *data, long length)
   272 {
   273     /* size is a 'synchsafe' integer (see above) */
   274     long size = (long)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
   275     size += 10; /* header size */
   276     /* ID3v2 header[5] is flags (bits 4-7 only, 0-3 are zero).
   277      * bit 4 set: footer is present (a copy of the header but
   278      * with "3DI" as ident.)  */
   279     if (data[5] & 0x10) {
   280         size += 10; /* footer size */
   281     }
   282     /* optional padding (always zeroes) */
   283     while (size < length && data[size] == 0) {
   284         ++size;
   285     }
   286     return size;
   287 }
   288 static SDL_INLINE SDL_bool is_apetag(const unsigned char *data, size_t length)
   289 {
   290    /* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
   291     * Header/footer is 32 bytes: bytes 0-7 ident, bytes 8-11 version,
   292     * bytes 12-17 size. bytes 24-31 are reserved: must be all zeroes. */
   293     Uint32 v;
   294 
   295     if (length < 32 || SDL_memcmp(data,"APETAGEX",8) != 0) {
   296         return SDL_FALSE;
   297     }
   298     v = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]; /* version */
   299     if (v != 2000U && v != 1000U) {
   300         return SDL_FALSE;
   301     }
   302     v = 0; /* reserved bits : */
   303     if (SDL_memcmp(&data[24],&v,4) != 0 || SDL_memcmp(&data[28],&v,4) != 0) {
   304         return SDL_FALSE;
   305     }
   306     return SDL_TRUE;
   307 }
   308 static SDL_INLINE long get_ape_len(const unsigned char *data, long datalen, Uint32 *version)
   309 {
   310     long size = (long)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
   311     *version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
   312     return size; /* caller will handle the additional v2 header length */
   313 }
   314 
   315 static int skip_tags(MAD_Music *music)
   316 {
   317     long len; size_t readsize;
   318 
   319     readsize = MAD_RWread(music, music->input_buffer, 1, MAD_INPUT_BUFFER_SIZE);
   320     if (!readsize) return -1;
   321 
   322     /* ID3v2 tag is at the start */
   323     if (is_id3v2(music->input_buffer, readsize)) {
   324         len = get_id3v2_len(music->input_buffer, (long)readsize);
   325         if (len >= music->length) return -1;
   326         music->start += len;
   327         music->length -= len;
   328         MAD_RWseek(music, 0, RW_SEEK_SET);
   329     }
   330     /* APE tag _might_ be at the start: read the header */
   331     else if (is_apetag(music->input_buffer, readsize)) {
   332         Uint32 v;
   333         len = get_ape_len(music->input_buffer, (long)readsize, &v);
   334         len += 32; /* we're at top: have a header. */
   335         if (len >= music->length) return -1;
   336         music->start += len;
   337         music->length -= len;
   338         MAD_RWseek(music, 0, RW_SEEK_SET);
   339     }
   340 
   341     /* ID3v1 tag is at the end */
   342     if (music->length < 128) goto ape;
   343     MAD_RWseek(music, -128, RW_SEEK_END);
   344     readsize = MAD_RWread(music, music->input_buffer, 1, 128);
   345     MAD_RWseek(music, 0, RW_SEEK_SET);
   346     if (readsize != 128) return -1;
   347     if (is_id3v1(music->input_buffer, 128)) {
   348         music->length -= 128;
   349 
   350         /* APE tag may be before the ID3v1: read the footer */
   351         if (music->length < 32) goto end;
   352         MAD_RWseek(music, -32, RW_SEEK_END);
   353         readsize = MAD_RWread(music, music->input_buffer, 1, 32);
   354         MAD_RWseek(music, 0, RW_SEEK_SET);
   355         if (readsize != 32) return -1;
   356         if (is_apetag(music->input_buffer, 32)) {
   357             Uint32 v;
   358             len = get_ape_len(music->input_buffer, (long)readsize, &v);
   359             if (v == 2000U) len += 32; /* header */
   360             if (len >= music->length) return -1;
   361             if (v == 2000U) { /* verify header : */
   362                 MAD_RWseek(music, -len, RW_SEEK_END);
   363                 readsize = MAD_RWread(music, music->input_buffer, 1, 32);
   364                 MAD_RWseek(music, 0, RW_SEEK_SET);
   365                 if (readsize != 32) return -1;
   366                 if (!is_apetag(music->input_buffer, 32)) return -1;
   367             }
   368             music->length -= len;
   369             goto end;
   370         }
   371         /* extended ID3v1 just before the ID3v1 tag? (unlikely)  */
   372         if (music->length < 227) goto end;
   373         MAD_RWseek(music, -227, RW_SEEK_END);
   374         readsize = MAD_RWread(music, music->input_buffer, 1, 227);
   375         MAD_RWseek(music, 0, RW_SEEK_SET);
   376         if (readsize != 227) return -1;
   377         if (is_id3v1ext(music->input_buffer, 227)) {
   378             music->length -= 227;
   379             goto end;
   380         }
   381     }
   382     ape: /* APE tag may be at the end: read the footer */
   383     if (music->length >= 32) {
   384         MAD_RWseek(music, -32, RW_SEEK_END);
   385         readsize = MAD_RWread(music, music->input_buffer, 1, 32);
   386         MAD_RWseek(music, 0, RW_SEEK_SET);
   387         if (readsize != 32) return -1;
   388         if (is_apetag(music->input_buffer, 32)) {
   389             Uint32 v;
   390             len = get_ape_len(music->input_buffer, (long)readsize, &v);
   391             if (v == 2000U) len += 32; /* header */
   392             if (len >= music->length) return -1;
   393             if (v == 2000U) { /* verify header : */
   394                 MAD_RWseek(music, -len, RW_SEEK_END);
   395                 readsize = MAD_RWread(music, music->input_buffer, 1, 32);
   396                 MAD_RWseek(music, 0, RW_SEEK_SET);
   397                 if (readsize != 32) return -1;
   398                 if (!is_apetag(music->input_buffer, 32)) return -1;
   399             }
   400             music->length -= len;
   401         }
   402     }
   403 
   404     end:
   405     return (music->length > 0)? 0: -1;
   406 }
   407 
   408 /* Reads the next frame from the file.
   409    Returns true on success or false on failure.
   410  */
   411 static SDL_bool read_next_frame(MAD_Music *music)
   412 {
   413     if (music->stream.buffer == NULL ||
   414         music->stream.error == MAD_ERROR_BUFLEN) {
   415         size_t read_size;
   416         size_t remaining;
   417         unsigned char *read_start;
   418 
   419         /* There might be some bytes in the buffer left over from last
   420            time.    If so, move them down and read more bytes following
   421            them. */
   422         if (music->stream.next_frame != NULL) {
   423             remaining = music->stream.bufend - music->stream.next_frame;
   424             memmove(music->input_buffer, music->stream.next_frame, remaining);
   425             read_start = music->input_buffer + remaining;
   426             read_size = MAD_INPUT_BUFFER_SIZE - remaining;
   427 
   428         } else {
   429             read_size = MAD_INPUT_BUFFER_SIZE;
   430             read_start = music->input_buffer;
   431             remaining = 0;
   432         }
   433 
   434         /* Now read additional bytes from the input file. */
   435         read_size = MAD_RWread(music, read_start, 1, read_size);
   436 
   437         if (read_size == 0) {
   438             if ((music->status & (MS_input_eof | MS_input_error)) == 0) {
   439                 /* FIXME: how to detect error? */
   440                 music->status |= MS_input_eof;
   441 
   442                 /* At the end of the file, we must stuff MAD_BUFFER_GUARD
   443                    number of 0 bytes. */
   444                 SDL_memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
   445                 read_size += MAD_BUFFER_GUARD;
   446             }
   447         }
   448 
   449         /* Now feed those bytes into the libmad stream. */
   450         mad_stream_buffer(&music->stream, music->input_buffer,
   451                                             read_size + remaining);
   452         music->stream.error = MAD_ERROR_NONE;
   453     }
   454 
   455     /* Now ask libmad to extract a frame from the data we just put in
   456        its buffer. */
   457     if (mad_frame_decode(&music->frame, &music->stream)) {
   458         if (MAD_RECOVERABLE(music->stream.error)) {
   459             mad_stream_sync(&music->stream); /* to frame seek mode */
   460             return SDL_FALSE;
   461 
   462         } else if (music->stream.error == MAD_ERROR_BUFLEN) {
   463             return SDL_FALSE;
   464 
   465         } else {
   466             Mix_SetError("mad_frame_decode() failed, corrupt stream?");
   467             music->status |= MS_decode_error;
   468             return SDL_FALSE;
   469         }
   470     }
   471 
   472     mad_timer_add(&music->next_frame_start, music->frame.header.duration);
   473 
   474     return SDL_TRUE;
   475 }
   476 
   477 /* Scale a MAD sample to 16 bits for output. */
   478 static Sint16 scale(mad_fixed_t sample)
   479 {
   480     const int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
   481 
   482     /* round */
   483     sample += (1L << (n_bits_to_loose - 1));
   484 
   485 #ifdef MUSIC_MP3_MAD_GPL_DITHERING
   486     sample += triangular_dither_noise(n_bits_to_loose + 1);
   487 #endif
   488 
   489     /* clip */
   490     if (sample >= MAD_F_ONE)
   491         sample = MAD_F_ONE - 1;
   492     else if (sample < -MAD_F_ONE)
   493         sample = -MAD_F_ONE;
   494 
   495     /* quantize */
   496     return (Sint16)(sample >> n_bits_to_loose);
   497 }
   498 
   499 /* Once the frame has been read, copies its samples into the output buffer. */
   500 static SDL_bool decode_frame(MAD_Music *music)
   501 {
   502     struct mad_pcm *pcm;
   503     unsigned int i, nchannels, nsamples;
   504     mad_fixed_t const *left_ch, *right_ch;
   505     Sint16 *buffer, *dst;
   506     int result;
   507 
   508     mad_synth_frame(&music->synth, &music->frame);
   509     pcm = &music->synth.pcm;
   510 
   511     if (!music->audiostream) {
   512         music->audiostream = SDL_NewAudioStream(AUDIO_S16, pcm->channels, pcm->samplerate, music_spec.format, music_spec.channels, music_spec.freq);
   513         if (!music->audiostream) {
   514             return SDL_FALSE;
   515         }
   516     }
   517 
   518     nchannels = pcm->channels;
   519     nsamples = pcm->length;
   520     left_ch = pcm->samples[0];
   521     right_ch = pcm->samples[1];
   522     buffer = SDL_stack_alloc(Sint16, nsamples*nchannels);
   523     if (!buffer) {
   524         SDL_OutOfMemory();
   525         return SDL_FALSE;
   526     }
   527 
   528     dst = buffer;
   529     if (nchannels == 1) {
   530         for (i = nsamples; i--;) {
   531             *dst++ = scale(*left_ch++);
   532         }
   533     } else {
   534         for (i = nsamples; i--;) {
   535             *dst++ = scale(*left_ch++);
   536             *dst++ = scale(*right_ch++);
   537         }
   538     }
   539 
   540     result = SDL_AudioStreamPut(music->audiostream, buffer, (nsamples * nchannels * sizeof(Sint16)));
   541     SDL_stack_free(buffer);
   542 
   543     if (result < 0) {
   544         return SDL_FALSE;
   545     }
   546     return SDL_TRUE;
   547 }
   548 
   549 static int MAD_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   550 {
   551     MAD_Music *music = (MAD_Music *)context;
   552     int filled;
   553 
   554     if (music->audiostream) {
   555         filled = SDL_AudioStreamGet(music->audiostream, data, bytes);
   556         if (filled != 0) {
   557             return filled;
   558         }
   559     }
   560 
   561     if (!music->play_count) {
   562         /* All done */
   563         *done = SDL_TRUE;
   564         return 0;
   565     }
   566 
   567     if (read_next_frame(music)) {
   568         if (!decode_frame(music)) {
   569             return -1;
   570         }
   571     } else if (music->status & MS_input_eof) {
   572         int play_count = -1;
   573         if (music->play_count > 0) {
   574             play_count = (music->play_count - 1);
   575         }
   576         if (MAD_Play(music, play_count) < 0) {
   577             return -1;
   578         }
   579     } else if (music->status & MS_decode_error) {
   580         return -1;
   581     }
   582     return 0;
   583 }
   584 static int MAD_GetAudio(void *context, void *data, int bytes)
   585 {
   586     MAD_Music *music = (MAD_Music *)context;
   587     return music_pcm_getaudio(context, data, bytes, music->volume, MAD_GetSome);
   588 }
   589 
   590 static int MAD_Seek(void *context, double position)
   591 {
   592     MAD_Music *music = (MAD_Music *)context;
   593     mad_timer_t target;
   594     int int_part;
   595 
   596     int_part = (int)position;
   597     mad_timer_set(&target, int_part, (int)((position - int_part) * 1000000), 1000000);
   598 
   599     if (mad_timer_compare(music->next_frame_start, target) > 0) {
   600         /* In order to seek backwards in a VBR file, we have to rewind and
   601            start again from the beginning.    This isn't necessary if the
   602            file happens to be CBR, of course; in that case we could seek
   603            directly to the frame we want.    But I leave that little
   604            optimization for the future developer who discovers she really
   605            needs it. */
   606         mad_timer_reset(&music->next_frame_start);
   607         music->status &= ~MS_error_flags;
   608 
   609         MAD_RWseek(music, 0, RW_SEEK_SET);
   610     }
   611 
   612     /* Now we have to skip frames until we come to the right one.
   613        Again, only truly necessary if the file is VBR. */
   614     while (mad_timer_compare(music->next_frame_start, target) < 0) {
   615         if (!read_next_frame(music)) {
   616             if ((music->status & MS_error_flags) != 0) {
   617                 /* Couldn't read a frame; either an error condition or
   618                      end-of-file.    Stop. */
   619                 return Mix_SetError("Seek position out of range");
   620             }
   621         }
   622     }
   623 
   624     /* Here we are, at the beginning of the frame that contains the
   625        target time.    Ehh, I say that's close enough.    If we wanted to,
   626        we could get more precise by decoding the frame now and counting
   627        the appropriate number of samples out of it. */
   628     return 0;
   629 }
   630 
   631 static void MAD_Delete(void *context)
   632 {
   633     MAD_Music *music = (MAD_Music *)context;
   634 
   635     mad_stream_finish(&music->stream);
   636     mad_frame_finish(&music->frame);
   637     mad_synth_finish(&music->synth);
   638 
   639     if (music->audiostream) {
   640         SDL_FreeAudioStream(music->audiostream);
   641     }
   642     if (music->freesrc) {
   643         SDL_RWclose(music->src);
   644     }
   645     SDL_free(music);
   646 }
   647 
   648 Mix_MusicInterface Mix_MusicInterface_MAD =
   649 {
   650     "MAD",
   651     MIX_MUSIC_MAD,
   652     MUS_MP3,
   653     SDL_FALSE,
   654     SDL_FALSE,
   655 
   656     NULL,   /* Load */
   657     NULL,   /* Open */
   658     MAD_CreateFromRW,
   659     NULL,   /* CreateFromFile */
   660     MAD_SetVolume,
   661     MAD_Play,
   662     NULL,   /* IsPlaying */
   663     MAD_GetAudio,
   664     MAD_Seek,
   665     NULL,   /* Pause */
   666     NULL,   /* Resume */
   667     NULL,   /* Stop */
   668     MAD_Delete,
   669     NULL,   /* Close */
   670     NULL,   /* Unload */
   671 };
   672 
   673 #endif /* MUSIC_MP3_MAD */
   674 
   675 /* vi: set ts=4 sw=4 expandtab: */