music_mad.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 23:28:23 -0500
changeset 528 bc0dfe8ae026
parent 521 565549e046b0
child 542 3de4970b36d4
permissions -rw-r--r--
Backed out changeset 1eddea51f162
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2012 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 MP3_MAD_MUSIC
    23 
    24 #include <string.h>
    25 
    26 #include "music_mad.h"
    27 
    28 mad_data *
    29 mad_openFile(const char *filename, SDL_AudioSpec *mixer)
    30 {
    31   SDL_RWops *rw;
    32   mad_data *mp3_mad;
    33 
    34   rw = SDL_RWFromFile(filename, "rb");
    35   if (rw == NULL) {
    36 	return NULL;
    37   }
    38 
    39   return mad_openFileRW(rw, mixer, 1);
    40 }
    41 
    42 mad_data *
    43 mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw)
    44 {
    45   mad_data *mp3_mad;
    46 
    47   mp3_mad = (mad_data *)malloc(sizeof(mad_data));
    48   if (mp3_mad) {
    49 	mp3_mad->rw = rw;
    50 	mp3_mad->freerw = freerw;
    51 	mad_stream_init(&mp3_mad->stream);
    52 	mad_frame_init(&mp3_mad->frame);
    53 	mad_synth_init(&mp3_mad->synth);
    54 	mp3_mad->frames_read = 0;
    55 	mad_timer_reset(&mp3_mad->next_frame_start);
    56 	mp3_mad->volume = MIX_MAX_VOLUME;
    57 	mp3_mad->status = 0;
    58 	mp3_mad->output_begin = 0;
    59 	mp3_mad->output_end = 0;
    60 	mp3_mad->mixer = *mixer;
    61   }
    62   return mp3_mad;
    63 }
    64 
    65 void
    66 mad_closeFile(mad_data *mp3_mad)
    67 {
    68   mad_stream_finish(&mp3_mad->stream);
    69   mad_frame_finish(&mp3_mad->frame);
    70   mad_synth_finish(&mp3_mad->synth);
    71 
    72   if (mp3_mad->freerw) {
    73 	SDL_RWclose(mp3_mad->rw);
    74   }
    75   free(mp3_mad);
    76 }
    77 
    78 /* Starts the playback. */
    79 void
    80 mad_start(mad_data *mp3_mad) {
    81   mp3_mad->status |= MS_playing;
    82 }
    83 
    84 /* Stops the playback. */
    85 void 
    86 mad_stop(mad_data *mp3_mad) {
    87   mp3_mad->status &= ~MS_playing;
    88 }
    89 
    90 /* Returns true if the playing is engaged, false otherwise. */
    91 int
    92 mad_isPlaying(mad_data *mp3_mad) {
    93   return ((mp3_mad->status & MS_playing) != 0);
    94 }
    95 
    96 /* Reads the next frame from the file.  Returns true on success or
    97    false on failure. */
    98 static int
    99 read_next_frame(mad_data *mp3_mad) {
   100   if (mp3_mad->stream.buffer == NULL || 
   101 	  mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
   102 	size_t read_size;
   103 	size_t remaining;
   104 	unsigned char *read_start;
   105 	
   106 	/* There might be some bytes in the buffer left over from last
   107 	   time.  If so, move them down and read more bytes following
   108 	   them. */
   109 	if (mp3_mad->stream.next_frame != NULL) {
   110 	  remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
   111 	  memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
   112 	  read_start = mp3_mad->input_buffer + remaining;
   113 	  read_size = MAD_INPUT_BUFFER_SIZE - remaining;
   114 	  
   115 	} else {
   116 	  read_size = MAD_INPUT_BUFFER_SIZE;
   117 	  read_start = mp3_mad->input_buffer;
   118 	  remaining = 0;
   119 	}
   120 
   121 	/* Now read additional bytes from the input file. */
   122 	read_size = SDL_RWread(mp3_mad->rw, read_start, 1, read_size);
   123 	
   124 	if (read_size <= 0) {
   125 	  if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
   126 		if (read_size == 0) {
   127 		  mp3_mad->status |= MS_input_eof;
   128 		} else {
   129 		  mp3_mad->status |= MS_input_error;
   130 		}
   131 		
   132 		/* At the end of the file, we must stuff MAD_BUFFER_GUARD
   133 		   number of 0 bytes. */
   134 		memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
   135 		read_size += MAD_BUFFER_GUARD;
   136 	  }
   137 	}
   138 	
   139 	/* Now feed those bytes into the libmad stream. */
   140 	mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
   141 					  read_size + remaining);
   142 	mp3_mad->stream.error = MAD_ERROR_NONE;
   143   }
   144   
   145   /* Now ask libmad to extract a frame from the data we just put in
   146 	 its buffer. */
   147   if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
   148 	if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
   149 	  return 0;
   150 	  
   151 	} else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
   152 	  return 0;
   153 	  
   154 	} else {
   155 	  mp3_mad->status |= MS_decode_error;
   156 	  return 0;
   157 	}
   158   }
   159   
   160   mp3_mad->frames_read++;
   161   mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
   162 
   163   return 1;
   164 }
   165 
   166 /* Scale a MAD sample to 16 bits for output. */
   167 static signed int
   168 scale(mad_fixed_t sample) {
   169   /* round */
   170   sample += (1L << (MAD_F_FRACBITS - 16));
   171 
   172   /* clip */
   173   if (sample >= MAD_F_ONE)
   174     sample = MAD_F_ONE - 1;
   175   else if (sample < -MAD_F_ONE)
   176     sample = -MAD_F_ONE;
   177 
   178   /* quantize */
   179   return sample >> (MAD_F_FRACBITS + 1 - 16);
   180 }
   181 
   182 /* Once the frame has been read, copies its samples into the output
   183    buffer. */
   184 static void
   185 decode_frame(mad_data *mp3_mad) {
   186   struct mad_pcm *pcm;
   187   unsigned int nchannels, nsamples;
   188   mad_fixed_t const *left_ch, *right_ch;
   189   unsigned char *out;
   190   int ret;
   191 
   192   mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
   193   pcm = &mp3_mad->synth.pcm;
   194   out = mp3_mad->output_buffer + mp3_mad->output_end;
   195 
   196   if ((mp3_mad->status & MS_cvt_decoded) == 0) {
   197 	mp3_mad->status |= MS_cvt_decoded;
   198 
   199 	/* The first frame determines some key properties of the stream.
   200 	   In particular, it tells us enough to set up the convert
   201 	   structure now. */
   202 	SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels, mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);
   203   }
   204 
   205   /* pcm->samplerate contains the sampling frequency */
   206 
   207   nchannels = pcm->channels;
   208   nsamples  = pcm->length;
   209   left_ch   = pcm->samples[0];
   210   right_ch  = pcm->samples[1];
   211 
   212   while (nsamples--) {
   213     signed int sample;
   214 
   215     /* output sample(s) in 16-bit signed little-endian PCM */
   216 
   217     sample = scale(*left_ch++);
   218     *out++ = ((sample >> 0) & 0xff);
   219     *out++ = ((sample >> 8) & 0xff);
   220 
   221     if (nchannels == 2) {
   222       sample = scale(*right_ch++);
   223       *out++ = ((sample >> 0) & 0xff);
   224       *out++ = ((sample >> 8) & 0xff);
   225     }
   226   }
   227 
   228   mp3_mad->output_end = out - mp3_mad->output_buffer;
   229   /*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
   230 }
   231 
   232 int
   233 mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len) {
   234   int bytes_remaining;
   235   int num_bytes;
   236   Uint8 *out;
   237 
   238   if ((mp3_mad->status & MS_playing) == 0) {
   239 	/* We're not supposed to be playing, so send silence instead. */
   240 	memset(stream, 0, len);
   241 	return;
   242   }
   243 
   244   out = stream;
   245   bytes_remaining = len;
   246   while (bytes_remaining > 0) {
   247 	if (mp3_mad->output_end == mp3_mad->output_begin) {
   248 	  /* We need to get a new frame. */
   249 	  mp3_mad->output_begin = 0;
   250 	  mp3_mad->output_end = 0;
   251 	  if (!read_next_frame(mp3_mad)) {
   252 		if ((mp3_mad->status & MS_error_flags) != 0) {
   253 		  /* Couldn't read a frame; either an error condition or
   254 			 end-of-file.  Stop. */
   255 		  memset(out, 0, bytes_remaining);
   256 		  mp3_mad->status &= ~MS_playing;
   257 		  return bytes_remaining;
   258 		}
   259 	  } else {
   260 		decode_frame(mp3_mad);
   261 
   262 		/* Now convert the frame data to the appropriate format for
   263 		   output. */
   264 		mp3_mad->cvt.buf = mp3_mad->output_buffer;
   265 		mp3_mad->cvt.len = mp3_mad->output_end;
   266 		
   267 		mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
   268 		/*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
   269 		SDL_ConvertAudio(&mp3_mad->cvt);
   270 	  }
   271 	}
   272 
   273 	num_bytes = mp3_mad->output_end - mp3_mad->output_begin;
   274 	if (bytes_remaining < num_bytes) {
   275 	  num_bytes = bytes_remaining;
   276 	}
   277 
   278 	if (mp3_mad->volume == MIX_MAX_VOLUME) {
   279 	  memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
   280 	} else {
   281 	  SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
   282 				   num_bytes, mp3_mad->volume);
   283 	}
   284 	out += num_bytes;
   285 	mp3_mad->output_begin += num_bytes;
   286 	bytes_remaining -= num_bytes;
   287   }
   288   return 0;
   289 }
   290 
   291 void
   292 mad_seek(mad_data *mp3_mad, double position) {
   293   mad_timer_t target;
   294   int int_part;
   295 
   296   int_part = (int)position;
   297   mad_timer_set(&target, int_part, 
   298 				(int)((position - int_part) * 1000000), 1000000);
   299 
   300   if (mad_timer_compare(mp3_mad->next_frame_start, target) > 0) {
   301 	/* In order to seek backwards in a VBR file, we have to rewind and
   302 	   start again from the beginning.  This isn't necessary if the
   303 	   file happens to be CBR, of course; in that case we could seek
   304 	   directly to the frame we want.  But I leave that little
   305 	   optimization for the future developer who discovers she really
   306 	   needs it. */
   307 	mp3_mad->frames_read = 0;
   308 	mad_timer_reset(&mp3_mad->next_frame_start);
   309 	mp3_mad->status &= ~MS_error_flags;
   310 	mp3_mad->output_begin = 0;
   311 	mp3_mad->output_end = 0;
   312 
   313 	SDL_RWseek(mp3_mad->rw, 0, RW_SEEK_SET);
   314   }
   315 
   316   /* Now we have to skip frames until we come to the right one.
   317 	 Again, only truly necessary if the file is VBR. */
   318   while (mad_timer_compare(mp3_mad->next_frame_start, target) < 0) {
   319 	if (!read_next_frame(mp3_mad)) {
   320 	  if ((mp3_mad->status & MS_error_flags) != 0) {
   321 		/* Couldn't read a frame; either an error condition or
   322 		   end-of-file.  Stop. */
   323 		mp3_mad->status &= ~MS_playing;
   324 		return;
   325 	  }
   326 	}
   327   }
   328 
   329   /* Here we are, at the beginning of the frame that contains the
   330 	 target time.  Ehh, I say that's close enough.  If we wanted to,
   331 	 we could get more precise by decoding the frame now and counting
   332 	 the appropriate number of samples out of it. */
   333 }
   334 
   335 void
   336 mad_setVolume(mad_data *mp3_mad, int volume) {
   337   mp3_mad->volume = volume;
   338 }
   339 
   340 
   341 #endif  /* MP3_MAD_MUSIC */