music_mad.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Oct 2017 14:40:31 -0700
changeset 823 bcd59adacdcc
parent 815 cac4c0288bbd
child 848 3907db698eb5
permissions -rw-r--r--
Fixed linker order so -lmingw32 comes before -lSDL2main
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2017 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     int freesrc;
   142     struct mad_stream stream;
   143     struct mad_frame frame;
   144     struct mad_synth synth;
   145     mad_timer_t next_frame_start;
   146     int volume;
   147     int status;
   148     SDL_AudioStream *audiostream;
   149 
   150     unsigned char input_buffer[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
   151 } MAD_Music;
   152 
   153 
   154 static int MAD_Seek(void *context, double position);
   155 
   156 static void *MAD_CreateFromRW(SDL_RWops *src, int freesrc)
   157 {
   158     MAD_Music *music;
   159 
   160     music = (MAD_Music *)SDL_calloc(1, sizeof(MAD_Music));
   161     if (!music) {
   162         SDL_OutOfMemory();
   163         return NULL;
   164     }
   165     music->src = src;
   166     music->volume = MIX_MAX_VOLUME;
   167 
   168     mad_stream_init(&music->stream);
   169     mad_frame_init(&music->frame);
   170     mad_synth_init(&music->synth);
   171     mad_timer_reset(&music->next_frame_start);
   172 
   173     music->freesrc = freesrc;
   174     return music;
   175 }
   176 
   177 static void MAD_SetVolume(void *context, int volume)
   178 {
   179     MAD_Music *music = (MAD_Music *)context;
   180     music->volume = volume;
   181 }
   182 
   183 /* Starts the playback. */
   184 static int MAD_Play(void *context, int play_count)
   185 {
   186     MAD_Music *music = (MAD_Music *)context;
   187     music->play_count = play_count;
   188     return MAD_Seek(music, 0.0);
   189 }
   190 
   191 /* Reads the next frame from the file.
   192    Returns true on success or false on failure.
   193  */
   194 static SDL_bool read_next_frame(MAD_Music *music)
   195 {
   196     if (music->stream.buffer == NULL ||
   197         music->stream.error == MAD_ERROR_BUFLEN) {
   198         size_t read_size;
   199         size_t remaining;
   200         unsigned char *read_start;
   201 
   202         /* There might be some bytes in the buffer left over from last
   203            time.    If so, move them down and read more bytes following
   204            them. */
   205         if (music->stream.next_frame != NULL) {
   206             remaining = music->stream.bufend - music->stream.next_frame;
   207             memmove(music->input_buffer, music->stream.next_frame, remaining);
   208             read_start = music->input_buffer + remaining;
   209             read_size = MAD_INPUT_BUFFER_SIZE - remaining;
   210 
   211         } else {
   212             read_size = MAD_INPUT_BUFFER_SIZE;
   213             read_start = music->input_buffer;
   214             remaining = 0;
   215         }
   216 
   217         /* Now read additional bytes from the input file. */
   218         read_size = SDL_RWread(music->src, read_start, 1, read_size);
   219 
   220         if (read_size == 0) {
   221             if ((music->status & (MS_input_eof | MS_input_error)) == 0) {
   222                 /* FIXME: how to detect error? */
   223                 music->status |= MS_input_eof;
   224 
   225                 /* At the end of the file, we must stuff MAD_BUFFER_GUARD
   226                    number of 0 bytes. */
   227                 SDL_memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
   228                 read_size += MAD_BUFFER_GUARD;
   229             }
   230         }
   231 
   232         /* Now feed those bytes into the libmad stream. */
   233         mad_stream_buffer(&music->stream, music->input_buffer,
   234                                             read_size + remaining);
   235         music->stream.error = MAD_ERROR_NONE;
   236     }
   237 
   238     /* Now ask libmad to extract a frame from the data we just put in
   239        its buffer. */
   240     if (mad_frame_decode(&music->frame, &music->stream)) {
   241         if (MAD_RECOVERABLE(music->stream.error)) {
   242             return SDL_FALSE;
   243 
   244         } else if (music->stream.error == MAD_ERROR_BUFLEN) {
   245             return SDL_FALSE;
   246 
   247         } else {
   248             Mix_SetError("mad_frame_decode() failed, corrupt stream?");
   249             music->status |= MS_decode_error;
   250             return SDL_FALSE;
   251         }
   252     }
   253 
   254     mad_timer_add(&music->next_frame_start, music->frame.header.duration);
   255 
   256     return SDL_TRUE;
   257 }
   258 
   259 /* Scale a MAD sample to 16 bits for output. */
   260 static Sint16 scale(mad_fixed_t sample)
   261 {
   262     const int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
   263 
   264     /* round */
   265     sample += (1L << (n_bits_to_loose - 1));
   266 
   267 #ifdef MUSIC_MP3_MAD_GPL_DITHERING
   268     sample += triangular_dither_noise(n_bits_to_loose + 1);
   269 #endif
   270 
   271     /* clip */
   272     if (sample >= MAD_F_ONE)
   273         sample = MAD_F_ONE - 1;
   274     else if (sample < -MAD_F_ONE)
   275         sample = -MAD_F_ONE;
   276 
   277     /* quantize */
   278     return (Sint16)(sample >> n_bits_to_loose);
   279 }
   280 
   281 /* Once the frame has been read, copies its samples into the output buffer. */
   282 static SDL_bool decode_frame(MAD_Music *music)
   283 {
   284     struct mad_pcm *pcm;
   285     unsigned int i, nchannels, nsamples;
   286     mad_fixed_t const *left_ch, *right_ch;
   287     Sint16 *buffer, *dst;
   288     int result;
   289 
   290     mad_synth_frame(&music->synth, &music->frame);
   291     pcm = &music->synth.pcm;
   292 
   293     if (!music->audiostream) {
   294         music->audiostream = SDL_NewAudioStream(AUDIO_S16, pcm->channels, pcm->samplerate, music_spec.format, music_spec.channels, music_spec.freq);
   295         if (!music->audiostream) {
   296             return SDL_FALSE;
   297         }
   298     }
   299 
   300     nchannels = pcm->channels;
   301     nsamples = pcm->length;
   302     left_ch = pcm->samples[0];
   303     right_ch = pcm->samples[1];
   304     buffer = SDL_stack_alloc(Sint16, nsamples*nchannels);
   305     if (!buffer) {
   306         SDL_OutOfMemory();
   307         return SDL_FALSE;
   308     }
   309 
   310     dst = buffer;
   311     if (nchannels == 1) {
   312         for (i = nsamples; i--;) {
   313             *dst++ = scale(*left_ch++);
   314         }
   315     } else {
   316         for (i = nsamples; i--;) {
   317             *dst++ = scale(*left_ch++);
   318             *dst++ = scale(*right_ch++);
   319         }
   320     }
   321 
   322     result = SDL_AudioStreamPut(music->audiostream, buffer, (nsamples * nchannels * sizeof(Sint16)));
   323     SDL_stack_free(buffer);
   324 
   325     if (result < 0) {
   326         return SDL_FALSE;
   327     }
   328     return SDL_TRUE;
   329 }
   330 
   331 static int MAD_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   332 {
   333     MAD_Music *music = (MAD_Music *)context;
   334     int filled;
   335 
   336     if (music->audiostream) {
   337         filled = SDL_AudioStreamGet(music->audiostream, data, bytes);
   338         if (filled != 0) {
   339             return filled;
   340         }
   341     }
   342 
   343     if (!music->play_count) {
   344         /* All done */
   345         *done = SDL_TRUE;
   346         return 0;
   347     }
   348 
   349     if (read_next_frame(music)) {
   350         if (!decode_frame(music)) {
   351             return -1;
   352         }
   353     } else if (music->status & MS_input_eof) {
   354         int play_count = -1;
   355         if (music->play_count > 0) {
   356             play_count = (music->play_count - 1);
   357         }
   358         if (MAD_Play(music, play_count) < 0) {
   359             return -1;
   360         }
   361     } else if (music->status & MS_decode_error) {
   362         return -1;
   363     }
   364     return 0;
   365 }
   366 static int MAD_GetAudio(void *context, void *data, int bytes)
   367 {
   368     MAD_Music *music = (MAD_Music *)context;
   369     return music_pcm_getaudio(context, data, bytes, music->volume, MAD_GetSome);
   370 }
   371 
   372 static int MAD_Seek(void *context, double position)
   373 {
   374     MAD_Music *music = (MAD_Music *)context;
   375     mad_timer_t target;
   376     int int_part;
   377 
   378     int_part = (int)position;
   379     mad_timer_set(&target, int_part, (int)((position - int_part) * 1000000), 1000000);
   380 
   381     if (mad_timer_compare(music->next_frame_start, target) > 0) {
   382         /* In order to seek backwards in a VBR file, we have to rewind and
   383            start again from the beginning.    This isn't necessary if the
   384            file happens to be CBR, of course; in that case we could seek
   385            directly to the frame we want.    But I leave that little
   386            optimization for the future developer who discovers she really
   387            needs it. */
   388         mad_timer_reset(&music->next_frame_start);
   389         music->status &= ~MS_error_flags;
   390 
   391         SDL_RWseek(music->src, 0, RW_SEEK_SET);
   392     }
   393 
   394     /* Now we have to skip frames until we come to the right one.
   395        Again, only truly necessary if the file is VBR. */
   396     while (mad_timer_compare(music->next_frame_start, target) < 0) {
   397         if (!read_next_frame(music)) {
   398             if ((music->status & MS_error_flags) != 0) {
   399                 /* Couldn't read a frame; either an error condition or
   400                      end-of-file.    Stop. */
   401                 return Mix_SetError("Seek position out of range");
   402             }
   403         }
   404     }
   405 
   406     /* Here we are, at the beginning of the frame that contains the
   407        target time.    Ehh, I say that's close enough.    If we wanted to,
   408        we could get more precise by decoding the frame now and counting
   409        the appropriate number of samples out of it. */
   410     return 0;
   411 }
   412 
   413 static void MAD_Delete(void *context)
   414 {
   415     MAD_Music *music = (MAD_Music *)context;
   416 
   417     mad_stream_finish(&music->stream);
   418     mad_frame_finish(&music->frame);
   419     mad_synth_finish(&music->synth);
   420 
   421     if (music->audiostream) {
   422         SDL_FreeAudioStream(music->audiostream);
   423     }
   424     if (music->freesrc) {
   425         SDL_RWclose(music->src);
   426     }
   427     SDL_free(music);
   428 }
   429 
   430 Mix_MusicInterface Mix_MusicInterface_MAD =
   431 {
   432     "MAD",
   433     MIX_MUSIC_MAD,
   434     MUS_MP3,
   435     SDL_FALSE,
   436     SDL_FALSE,
   437 
   438     NULL,   /* Load */
   439     NULL,   /* Open */
   440     MAD_CreateFromRW,
   441     NULL,   /* CreateFromFile */
   442     MAD_SetVolume,
   443     MAD_Play,
   444     NULL,   /* IsPlaying */
   445     MAD_GetAudio,
   446     MAD_Seek,
   447     NULL,   /* Pause */
   448     NULL,   /* Resume */
   449     NULL,   /* Stop */
   450     MAD_Delete,
   451     NULL,   /* Close */
   452     NULL,   /* Unload */
   453 };
   454 
   455 #endif /* MUSIC_MP3_MAD */
   456 
   457 /* vi: set ts=4 sw=4 expandtab: */