load_mp3.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 22:12:31 -0800
changeset 712 7e59d684b070
parent 711 f40c5ac95b12
child 725 bdf7b8d20566
permissions -rw-r--r--
Updated to version 2.0.1
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2016 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   This is the source needed to decode an MP3 into a waveform.
    22 */
    23 
    24 /* $Id$ */
    25 
    26 #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    27 
    28 #include "SDL_mixer.h"
    29 
    30 #include "load_mp3.h"
    31 
    32 #if defined(MP3_MUSIC)
    33 #include "dynamic_mp3.h"
    34 #elif defined(MP3_MAD_MUSIC)
    35 #include "music_mad.h"
    36 #endif
    37 
    38 SDL_AudioSpec *Mix_LoadMP3_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
    39 {
    40 	/* note: spec is initialized to mixer spec */
    41 
    42 #if defined(MP3_MUSIC)
    43 	SMPEG* mp3;
    44 	SMPEG_Info info;
    45 #elif defined(MP3_MAD_MUSIC)
    46 	mad_data *mp3_mad;
    47 #endif
    48 	long samplesize;
    49 	int read_len;
    50 	const Uint32 chunk_len = 4096;
    51 	int err = 0;
    52 
    53 	if ((!src) || (!spec) || (!audio_buf) || (!audio_len))
    54 	{
    55 		return NULL;
    56 	}
    57 
    58 	if (!err)
    59 	{
    60 		*audio_len = 0;
    61 		*audio_buf = (Uint8*) SDL_malloc(chunk_len);
    62 		err = (*audio_buf == NULL);
    63 	}
    64 
    65 	if (!err)
    66 	{
    67 		err = ((Mix_Init(MIX_INIT_MP3) & MIX_INIT_MP3) == 0);
    68 	}
    69 
    70 	if (!err)
    71 	{
    72 #if defined(MP3_MUSIC)
    73 		mp3 = smpeg.SMPEG_new_rwops(src, &info, freesrc, 0);
    74 		err = (mp3 == NULL);
    75 #elif defined(MP3_MAD_MUSIC)
    76         mp3_mad = mad_openFileRW(src, spec, freesrc);
    77 		err = (mp3_mad == NULL);
    78 #endif
    79 	}
    80 
    81 #if defined(MP3_MUSIC)
    82 	if (!err)
    83 	{
    84 		err = !info.has_audio;
    85 	}
    86 #endif
    87 
    88 	if (!err)
    89 	{
    90 #if defined(MP3_MUSIC)
    91 
    92 		smpeg.SMPEG_actualSpec(mp3, spec);
    93 
    94 		smpeg.SMPEG_enableaudio(mp3, 1);
    95 		smpeg.SMPEG_enablevideo(mp3, 0);
    96 
    97 		smpeg.SMPEG_play(mp3);
    98 
    99 		/* read once for audio length */
   100 		while ((read_len = smpeg.SMPEG_playAudio(mp3, *audio_buf, chunk_len)) > 0)
   101 		{
   102 			*audio_len += read_len;
   103 		}
   104 
   105 		smpeg.SMPEG_stop(mp3);
   106 
   107 #elif defined(MP3_MAD_MUSIC)
   108 
   109         mad_start(mp3_mad);
   110 
   111 		/* read once for audio length */
   112 		while ((read_len = mad_getSamples(mp3_mad, *audio_buf, chunk_len)) > 0)
   113 		{
   114 			*audio_len += read_len;
   115 		}
   116 
   117 		mad_stop(mp3_mad);
   118 
   119 #endif
   120 
   121 		err = (read_len < 0);
   122 	}
   123 
   124 	if (!err)
   125 	{
   126 		/* reallocate, if needed */
   127 		if ((*audio_len > 0) && (*audio_len != chunk_len))
   128 		{
   129 			*audio_buf = (Uint8*) SDL_realloc(*audio_buf, *audio_len);
   130 			err = (*audio_buf == NULL);
   131 		}
   132 	}
   133 
   134 	if (!err)
   135 	{
   136 		/* read again for audio buffer, if needed */
   137 		if (*audio_len > chunk_len)
   138 		{
   139 #if defined(MP3_MUSIC)
   140 			smpeg.SMPEG_rewind(mp3);
   141 			smpeg.SMPEG_play(mp3);
   142 			err = (*audio_len != smpeg.SMPEG_playAudio(mp3, *audio_buf, *audio_len));
   143 			smpeg.SMPEG_stop(mp3);
   144 #elif defined(MP3_MAD_MUSIC)
   145 			mad_seek(mp3_mad, 0);
   146 			mad_start(mp3_mad);
   147 			err = (*audio_len != mad_getSamples(mp3_mad, *audio_buf, *audio_len));
   148 			mad_stop(mp3_mad);
   149 #endif
   150 		}
   151 	}
   152 
   153 	if (!err)
   154 	{
   155 		/* Don't return a buffer that isn't a multiple of samplesize */
   156 		samplesize = ((spec->format & 0xFF)/8)*spec->channels;
   157 		*audio_len &= ~(samplesize-1);
   158 	}
   159 
   160 #if defined(MP3_MUSIC)
   161 	if (mp3)
   162 	{
   163 		smpeg.SMPEG_delete(mp3); mp3 = NULL;
   164 		/* Deleting the MP3 closed the source if desired */
   165 		freesrc = SDL_FALSE;
   166 	}
   167 #elif defined(MP3_MAD_MUSIC)
   168 	if (mp3_mad)
   169 	{
   170 		mad_closeFile(mp3_mad); mp3_mad = NULL;
   171 		/* Deleting the MP3 closed the source if desired */
   172 		freesrc = SDL_FALSE;
   173 	}
   174 #endif
   175 
   176 	if (freesrc)
   177 	{
   178 		SDL_RWclose(src); src = NULL;
   179 	}
   180 
   181 	/* handle error */
   182 	if (err)
   183 	{
   184 		if (*audio_buf != NULL)
   185 		{
   186 			SDL_free(*audio_buf); *audio_buf = NULL;
   187 		}
   188 		*audio_len = 0;
   189 		spec = NULL;
   190 	}
   191 
   192 	return spec;
   193 }
   194 
   195 #endif