music_flac.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 18:32:49 -0500
changeset 521 565549e046b0
parent 518 8bc9b5fd2aae
child 522 a70c0ee38c9f
permissions -rw-r--r--
Fixed bugs 1003, 1021, 1168 - fixed memory leak loading music

jjs@jjs.at 2011-03-11 11:37:57 PST
When using SDL_Mixer to play WAVE music, the call to Mix_FreeMusic does not
close the associated file handle.

There is a check in WAVStream_FreeSong() of wavestream.c like this:

if ( wave->freerw ) {
SDL_FreeRW(wave->rw);
}

But the variable freerw is not referenced anywhere else. SDL_FreeRW would also
not close the file from what I can tell.
     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   This file is used to support SDL_LoadMUS playback of FLAC files.
    22   	~ Austen Dicken (admin@cvpcs.org)
    23 */
    24 
    25 #ifdef FLAC_MUSIC
    26 
    27 #include <stdio.h>
    28 #include <stdlib.h>
    29 #include <string.h>
    30 
    31 #include "SDL_mixer.h"
    32 #include "dynamic_flac.h"
    33 #include "music_flac.h"
    34 
    35 /* This is the format of the audio mixer data */
    36 static SDL_AudioSpec mixer;
    37 
    38 /* Initialize the FLAC player, with the given mixer settings
    39    This function returns 0, or -1 if there was an error.
    40  */
    41 int FLAC_init(SDL_AudioSpec *mixerfmt)
    42 {
    43 	mixer = *mixerfmt;
    44 	return(0);
    45 }
    46 
    47 /* Set the volume for an FLAC stream */
    48 void FLAC_setvolume(FLAC_music *music, int volume)
    49 {
    50 	music->volume = volume;
    51 }
    52 
    53 /* Load an FLAC stream from the given file */
    54 FLAC_music *FLAC_new(const char *file)
    55 {
    56 	SDL_RWops *rw;
    57 
    58 	rw = SDL_RWFromFile (file, "rb");
    59 	if (rw == NULL) {
    60 		SDL_SetError ("Couldn't open %s", file);
    61 		return NULL;
    62 	}
    63 	return FLAC_new_RW (rw, 1);
    64 }
    65 
    66 static FLAC__StreamDecoderReadStatus flac_read_music_cb(
    67 									const FLAC__StreamDecoder *decoder,
    68 									FLAC__byte buffer[],
    69 									size_t *bytes,
    70 									void *client_data)
    71 {
    72 	FLAC_music *data = (FLAC_music*)client_data;
    73 
    74 	// make sure there is something to be reading
    75 	if (*bytes > 0) {
    76 		*bytes = SDL_RWread (data->rwops, buffer, sizeof (FLAC__byte), *bytes);
    77 
    78 		if (*bytes < 0) { // error in read
    79 			return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
    80 		}
    81 		else if (*bytes == 0 ) { // no data was read (EOF)
    82 			return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
    83 		}
    84 		else { // data was read, continue
    85 			return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
    86 		}
    87 	}
    88 	else {
    89 		return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
    90 	}
    91 }
    92 
    93 static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
    94 									const FLAC__StreamDecoder *decoder,
    95 									FLAC__uint64 absolute_byte_offset,
    96 									void *client_data)
    97 {
    98 	FLAC_music *data = (FLAC_music*)client_data;
    99 
   100 	if (SDL_RWseek (data->rwops, absolute_byte_offset, RW_SEEK_SET) < 0) {
   101 		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
   102 	}
   103 	else {
   104 		return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
   105 	}
   106 }
   107 
   108 static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
   109 									const FLAC__StreamDecoder *decoder,
   110 									FLAC__uint64 *absolute_byte_offset,
   111 									void *client_data )
   112 {
   113 	FLAC_music *data = (FLAC_music*)client_data;
   114 
   115 	int pos = SDL_RWtell (data->rwops);
   116 
   117 	if (pos < 0) {
   118 		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
   119 	}
   120 	else {
   121 		*absolute_byte_offset = (FLAC__uint64)pos;
   122 		return FLAC__STREAM_DECODER_TELL_STATUS_OK;
   123 	}
   124 }
   125 
   126 static FLAC__StreamDecoderLengthStatus flac_length_music_cb (
   127 									const FLAC__StreamDecoder *decoder,
   128 									FLAC__uint64 *stream_length,
   129 									void *client_data)
   130 {
   131 	FLAC_music *data = (FLAC_music*)client_data;
   132 
   133 	int pos = SDL_RWtell (data->rwops);
   134 	int length = SDL_RWseek (data->rwops, 0, RW_SEEK_END);
   135 
   136 	if (SDL_RWseek (data->rwops, pos, RW_SEEK_SET) != pos || length < 0) {
   137 		/* there was an error attempting to return the stream to the original
   138 		 * position, or the length was invalid. */
   139 		return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
   140 	}
   141 	else {
   142 		*stream_length = (FLAC__uint64)length;
   143 		return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
   144 	}
   145 }
   146 
   147 static FLAC__bool flac_eof_music_cb(
   148 								const FLAC__StreamDecoder *decoder,
   149 								void *client_data )
   150 {
   151 	FLAC_music *data = (FLAC_music*)client_data;
   152 
   153 	int pos = SDL_RWtell (data->rwops);
   154 	int end = SDL_RWseek (data->rwops, 0, RW_SEEK_END);
   155 
   156 	// was the original position equal to the end (a.k.a. the seek didn't move)?
   157 	if (pos == end) {
   158 		// must be EOF
   159 		return true;
   160 	}
   161 	else {
   162 		// not EOF, return to the original position
   163 		SDL_RWseek (data->rwops, pos, RW_SEEK_SET);
   164 
   165 		return false;
   166 	}
   167 }
   168 
   169 static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
   170 									const FLAC__StreamDecoder *decoder,
   171 									const FLAC__Frame *frame,
   172 									const FLAC__int32 *const buffer[],
   173 									void *client_data)
   174 {
   175 	FLAC_music *data = (FLAC_music *)client_data;
   176 	size_t i;
   177 
   178 	if (data->flac_data.total_samples == 0) {
   179 		SDL_SetError ("Given FLAC file does not specify its sample count.");
   180 		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   181 	}
   182 
   183 	if (data->flac_data.channels != 2 ||
   184 		data->flac_data.bits_per_sample != 16) {
   185 		SDL_SetError("Current FLAC support is only for 16 bit Stereo files.");
   186 		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   187 	}
   188 
   189 	for (i = 0; i < frame->header.blocksize; i++) {
   190 		FLAC__int16 i16;
   191 		FLAC__uint16 ui16;
   192 
   193 		// make sure we still have at least two bytes that can be read (one for
   194 		// each channel)
   195 		if (data->flac_data.max_to_read >= 4) {
   196 			// does the data block exist?
   197 			if (!data->flac_data.data) {
   198 				data->flac_data.data_len = data->flac_data.max_to_read;
   199 				data->flac_data.data_read = 0;
   200 
   201 				// create it
   202 				data->flac_data.data =
   203 									(char *)malloc (data->flac_data.data_len);
   204 
   205 				if (!data->flac_data.data) {
   206 					return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   207 				}
   208 			}
   209 
   210 			i16 = (FLAC__int16)buffer[0][i];
   211 			ui16 = (FLAC__uint16)i16;
   212 
   213 			*((data->flac_data.data) + (data->flac_data.data_read++)) =
   214 															(char)(ui16);
   215 			*((data->flac_data.data) + (data->flac_data.data_read++)) =
   216 															(char)(ui16 >> 8);
   217 
   218 			i16 = (FLAC__int16)buffer[1][i];
   219 			ui16 = (FLAC__uint16)i16;
   220 
   221 			*((data->flac_data.data) + (data->flac_data.data_read++)) =
   222 															(char)(ui16);
   223 			*((data->flac_data.data) + (data->flac_data.data_read++)) =
   224 															(char)(ui16 >> 8);
   225 
   226 			data->flac_data.max_to_read -= 4;
   227 
   228 			if (data->flac_data.max_to_read < 4) {
   229 				// we need to set this so that the read halts from the
   230 				// FLAC_getsome function.
   231 				data->flac_data.max_to_read = 0;
   232 			}
   233 		}
   234 		else {
   235 			// we need to write to the overflow
   236 			if (!data->flac_data.overflow) {
   237 				data->flac_data.overflow_len =
   238 											4 * (frame->header.blocksize - i);
   239 				data->flac_data.overflow_read = 0;
   240 
   241 				// make it big enough for the rest of the block
   242 				data->flac_data.overflow =
   243 								(char *)malloc (data->flac_data.overflow_len);
   244 
   245 				if (!data->flac_data.overflow) {
   246 					return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   247 				}
   248 			}
   249 
   250 			i16 = (FLAC__int16)buffer[0][i];
   251 			ui16 = (FLAC__uint16)i16;
   252 
   253 			*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   254 															(char)(ui16);
   255 			*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   256 															(char)(ui16 >> 8);
   257 
   258 			i16 = (FLAC__int16)buffer[1][i];
   259 			ui16 = (FLAC__uint16)i16;
   260 
   261 			*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   262 															(char)(ui16);
   263 			*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   264 															(char)(ui16 >> 8);
   265 		}
   266 	}
   267 
   268 	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
   269 }
   270 
   271 static void flac_metadata_music_cb(
   272 					const FLAC__StreamDecoder *decoder,
   273 					const FLAC__StreamMetadata *metadata,
   274 					void *client_data)
   275 {
   276 	FLAC_music *data = (FLAC_music *)client_data;
   277 
   278 	if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
   279 		data->flac_data.sample_rate = metadata->data.stream_info.sample_rate;
   280 		data->flac_data.channels = metadata->data.stream_info.channels;
   281 		data->flac_data.total_samples =
   282 							metadata->data.stream_info.total_samples;
   283 		data->flac_data.bits_per_sample =
   284 							metadata->data.stream_info.bits_per_sample;
   285 		data->flac_data.sample_size = data->flac_data.channels *
   286 										((data->flac_data.bits_per_sample) / 8);
   287 	}
   288 }
   289 
   290 static void flac_error_music_cb(
   291 				const FLAC__StreamDecoder *decoder,
   292 				FLAC__StreamDecoderErrorStatus status,
   293 				void *client_data)
   294 {
   295 	// print an SDL error based on the error status
   296 	switch (status) {
   297 		case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
   298 			SDL_SetError ("Error processing the FLAC file [LOST_SYNC].");
   299 		break;
   300 		case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
   301 			SDL_SetError ("Error processing the FLAC file [BAD_HEADER].");
   302 		break;
   303 		case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
   304 			SDL_SetError ("Error processing the FLAC file [CRC_MISMATCH].");
   305 		break;
   306 		case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
   307 			SDL_SetError ("Error processing the FLAC file [UNPARSEABLE].");
   308 		break;
   309 		default:
   310 			SDL_SetError ("Error processing the FLAC file [UNKNOWN].");
   311 		break;
   312 	}
   313 }
   314 
   315 /* Load an FLAC stream from an SDL_RWops object */
   316 FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw)
   317 {
   318 	FLAC_music *music;
   319 	int init_stage = 0;
   320 	int was_error = 1;
   321 
   322 	music = (FLAC_music *)malloc ( sizeof (*music));
   323 	if (music) {
   324 		/* Initialize the music structure */
   325 		memset (music, 0, (sizeof (*music)));
   326 		FLAC_stop (music);
   327 		FLAC_setvolume (music, MIX_MAX_VOLUME);
   328 		music->section = -1;
   329 		music->rwops = rw;
   330 		music->freerw = freerw;
   331 		music->flac_data.max_to_read = 0;
   332 		music->flac_data.overflow = NULL;
   333 		music->flac_data.overflow_len = 0;
   334 		music->flac_data.overflow_read = 0;
   335 		music->flac_data.data = NULL;
   336 		music->flac_data.data_len = 0;
   337 		music->flac_data.data_read = 0;
   338 
   339 		if (Mix_Init(MIX_INIT_FLAC)) {
   340 			init_stage++; // stage 1!
   341 
   342 			music->flac_decoder = flac.FLAC__stream_decoder_new ();
   343 
   344 			if (music->flac_decoder != NULL) {
   345 				init_stage++; // stage 2!
   346 
   347 				if (flac.FLAC__stream_decoder_init_stream(
   348 							music->flac_decoder,
   349 							flac_read_music_cb, flac_seek_music_cb,
   350 							flac_tell_music_cb, flac_length_music_cb,
   351 							flac_eof_music_cb, flac_write_music_cb,
   352 							flac_metadata_music_cb, flac_error_music_cb,
   353 							music) == FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
   354 					init_stage++; // stage 3!
   355 
   356 					if (flac.FLAC__stream_decoder_process_until_end_of_metadata
   357 											(music->flac_decoder)) {
   358 						was_error = 0;
   359 					} else {
   360 						SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
   361 					}
   362 				} else {
   363 					SDL_SetError("FLAC__stream_decoder_init_stream() failed");
   364 				}
   365 			} else {
   366 				SDL_SetError("FLAC__stream_decoder_new() failed");
   367 			}
   368 		}
   369 
   370 		if (was_error) {
   371 			switch (init_stage) {
   372 				case 3:
   373 					flac.FLAC__stream_decoder_finish( music->flac_decoder );
   374 				case 2:
   375 					flac.FLAC__stream_decoder_delete( music->flac_decoder );
   376 				case 1:
   377 				case 0:
   378 					free(music);
   379 					if (freerw) {
   380 						SDL_RWclose(rw);
   381 					}
   382 					break;
   383 			}
   384 			return NULL;
   385 		}
   386 	} else {
   387 		SDL_OutOfMemory();
   388 		if (freerw) {
   389 			SDL_RWclose(rw);
   390 		}
   391 		return NULL;
   392 	}
   393 
   394 	return music;
   395 }
   396 
   397 /* Start playback of a given FLAC stream */
   398 void FLAC_play(FLAC_music *music)
   399 {
   400 	music->playing = 1;
   401 }
   402 
   403 /* Return non-zero if a stream is currently playing */
   404 int FLAC_playing(FLAC_music *music)
   405 {
   406 	return(music->playing);
   407 }
   408 
   409 /* Read some FLAC stream data and convert it for output */
   410 static void FLAC_getsome(FLAC_music *music)
   411 {
   412 	SDL_AudioCVT *cvt;
   413 
   414 	/* GET AUDIO wAVE DATA */
   415 	// set the max number of characters to read
   416 	music->flac_data.max_to_read = 8192;
   417 
   418 	// clear out the data buffer if it exists
   419 	if (music->flac_data.data) {
   420 		free (music->flac_data.data);
   421 	}
   422 
   423 	music->flac_data.data_len = music->flac_data.max_to_read;
   424 	music->flac_data.data_read = 0;
   425 	music->flac_data.data = (char *)malloc (music->flac_data.data_len);
   426 
   427 	// we have data to read
   428 	while(music->flac_data.max_to_read > 0) {
   429 		// first check if there is data in the overflow from before
   430 		if (music->flac_data.overflow) {
   431 			size_t overflow_len = music->flac_data.overflow_read;
   432 
   433 			if (overflow_len > music->flac_data.max_to_read) {
   434 				size_t overflow_extra_len = overflow_len -
   435 												music->flac_data.max_to_read;
   436 
   437 				char* new_overflow = (char *)malloc (overflow_extra_len);
   438 				memcpy (music->flac_data.data+music->flac_data.data_read,
   439 					music->flac_data.overflow, music->flac_data.max_to_read);
   440 				music->flac_data.data_read += music->flac_data.max_to_read;
   441 				memcpy (new_overflow,
   442 					music->flac_data.overflow + music->flac_data.max_to_read,
   443 					overflow_extra_len);
   444 				free (music->flac_data.overflow);
   445 				music->flac_data.overflow = new_overflow;
   446 				music->flac_data.overflow_len = overflow_extra_len;
   447 				music->flac_data.overflow_read = 0;
   448 				music->flac_data.max_to_read = 0;
   449 			}
   450 			else {
   451 				memcpy (music->flac_data.data+music->flac_data.data_read,
   452 					music->flac_data.overflow, overflow_len);
   453 				music->flac_data.data_read += overflow_len;
   454 				free (music->flac_data.overflow);
   455 				music->flac_data.overflow = NULL;
   456 				music->flac_data.overflow_len = 0;
   457 				music->flac_data.overflow_read = 0;
   458 				music->flac_data.max_to_read -= overflow_len;
   459 			}
   460 		}
   461 		else {
   462 			if (!flac.FLAC__stream_decoder_process_single (
   463 														music->flac_decoder)) {
   464 				music->flac_data.max_to_read = 0;
   465 			}
   466 
   467 			if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   468 									== FLAC__STREAM_DECODER_END_OF_STREAM) {
   469 				music->flac_data.max_to_read = 0;
   470 			}
   471 		}
   472 	}
   473 
   474 	if (music->flac_data.data_read <= 0) {
   475 		if (music->flac_data.data_read == 0) {
   476 			music->playing = 0;
   477 		}
   478 		return;
   479 	}
   480 	cvt = &music->cvt;
   481 	if (music->section < 0) {
   482 
   483 		SDL_BuildAudioCVT (cvt, AUDIO_S16, (Uint8)music->flac_data.channels,
   484 						(int)music->flac_data.sample_rate, mixer.format,
   485 		                mixer.channels, mixer.freq);
   486 		if (cvt->buf) {
   487 			free (cvt->buf);
   488 		}
   489 		cvt->buf = (Uint8 *)malloc (music->flac_data.data_len * cvt->len_mult);
   490 		music->section = 0;
   491 	}
   492 	if (cvt->buf) {
   493 		memcpy (cvt->buf, music->flac_data.data, music->flac_data.data_read);
   494 		if (cvt->needed) {
   495 			cvt->len = music->flac_data.data_read;
   496 			SDL_ConvertAudio (cvt);
   497 		}
   498 		else {
   499 			cvt->len_cvt = music->flac_data.data_read;
   500 		}
   501 		music->len_available = music->cvt.len_cvt;
   502 		music->snd_available = music->cvt.buf;
   503 	}
   504 	else {
   505 		SDL_SetError ("Out of memory");
   506 		music->playing = 0;
   507 	}
   508 }
   509 
   510 /* Play some of a stream previously started with FLAC_play() */
   511 int FLAC_playAudio(FLAC_music *music, Uint8 *snd, int len)
   512 {
   513 	int mixable;
   514 
   515 	while ((len > 0) && music->playing) {
   516 		if (!music->len_available) {
   517 			FLAC_getsome (music);
   518 		}
   519 		mixable = len;
   520 		if (mixable > music->len_available) {
   521 			mixable = music->len_available;
   522 		}
   523 		if (music->volume == MIX_MAX_VOLUME) {
   524 			memcpy (snd, music->snd_available, mixable);
   525 		}
   526 		else {
   527 			SDL_MixAudio (snd, music->snd_available, mixable, music->volume);
   528 		}
   529 		music->len_available -= mixable;
   530 		music->snd_available += mixable;
   531 		len -= mixable;
   532 		snd += mixable;
   533 	}
   534 
   535 	return len;
   536 }
   537 
   538 /* Stop playback of a stream previously started with FLAC_play() */
   539 void FLAC_stop(FLAC_music *music)
   540 {
   541 	music->playing = 0;
   542 }
   543 
   544 /* Close the given FLAC_music object */
   545 void FLAC_delete(FLAC_music *music)
   546 {
   547 	if (music) {
   548 		if (music->flac_decoder) {
   549 			flac.FLAC__stream_decoder_finish (music->flac_decoder);
   550 			flac.FLAC__stream_decoder_delete (music->flac_decoder);
   551 		}
   552 
   553 		if (music->flac_data.data) {
   554 			free (music->flac_data.data);
   555 		}
   556 
   557 		if (music->flac_data.overflow) {
   558 			free (music->flac_data.overflow);
   559 		}
   560 
   561 		if (music->cvt.buf) {
   562 			free (music->cvt.buf);
   563 		}
   564 
   565 		if (music->freerw) {
   566 			SDL_RWclose(music->rwops);
   567 		}
   568 		free (music);
   569 	}
   570 }
   571 
   572 /* Jump (seek) to a given position (time is in seconds) */
   573 void FLAC_jump_to_time(FLAC_music *music, double time)
   574 {
   575 	if (music) {
   576 		if (music->flac_decoder) {
   577 			double seek_sample = music->flac_data.sample_rate * time;
   578 
   579 			// clear data if it has data
   580 			if (music->flac_data.data) {
   581 				free (music->flac_data.data);
   582 				music->flac_data.data = NULL;
   583 			}
   584 
   585 			// clear overflow if it has data
   586 			if (music->flac_data.overflow) {
   587 				free (music->flac_data.overflow);
   588 				music->flac_data.overflow = NULL;
   589 			}
   590 
   591 			if (!flac.FLAC__stream_decoder_seek_absolute (music->flac_decoder,
   592 												(FLAC__uint64)seek_sample)) {
   593 				if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   594 										== FLAC__STREAM_DECODER_SEEK_ERROR) {
   595 					flac.FLAC__stream_decoder_flush (music->flac_decoder);
   596 				}
   597 
   598 				SDL_SetError
   599 					("Seeking of FLAC stream failed: libFLAC seek failed.");
   600 			}
   601 		}
   602 		else {
   603 			SDL_SetError
   604 				("Seeking of FLAC stream failed: FLAC decoder was NULL.");
   605 		}
   606 	}
   607 	else {
   608 		SDL_SetError ("Seeking of FLAC stream failed: music was NULL.");
   609 	}
   610 }
   611 
   612 #endif /* FLAC_MUSIC */