music_flac.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 04 Jan 2012 00:16:03 -0500
changeset 542 3de4970b36d4
parent 524 0f6aa6179b1d
child 545 32e5ed415a34
permissions -rw-r--r--
Fixed bug 1252 - Added Mix_LoadMUSType_RW() so you can tell SDL_mixer what type the music is

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