music_flac.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 10:27:48 -0500
changeset 518 8bc9b5fd2aae
parent 487 485a29de2b2d
child 521 565549e046b0
permissions -rw-r--r--
Happy New Year!
     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);
    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)
   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->flac_data.max_to_read = 0;
   331 		music->flac_data.overflow = NULL;
   332 		music->flac_data.overflow_len = 0;
   333 		music->flac_data.overflow_read = 0;
   334 		music->flac_data.data = NULL;
   335 		music->flac_data.data_len = 0;
   336 		music->flac_data.data_read = 0;
   337 
   338 		if (Mix_Init(MIX_INIT_FLAC)) {
   339 			init_stage++; // stage 1!
   340 
   341 			music->flac_decoder = flac.FLAC__stream_decoder_new ();
   342 
   343 			if (music->flac_decoder != NULL) {
   344 				init_stage++; // stage 2!
   345 
   346 				if (flac.FLAC__stream_decoder_init_stream(
   347 							music->flac_decoder,
   348 							flac_read_music_cb, flac_seek_music_cb,
   349 							flac_tell_music_cb, flac_length_music_cb,
   350 							flac_eof_music_cb, flac_write_music_cb,
   351 							flac_metadata_music_cb, flac_error_music_cb,
   352 							music) == FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
   353 					init_stage++; // stage 3!
   354 
   355 					if (flac.FLAC__stream_decoder_process_until_end_of_metadata
   356 											(music->flac_decoder)) {
   357 						was_error = 0;
   358 					} else {
   359 						SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
   360 					}
   361 				} else {
   362 					SDL_SetError("FLAC__stream_decoder_init_stream() failed");
   363 				}
   364 			} else {
   365 				SDL_SetError("FLAC__stream_decoder_new() failed");
   366 			}
   367 		}
   368 
   369 		if (was_error) {
   370 			switch (init_stage) {
   371 				case 3:
   372 					flac.FLAC__stream_decoder_finish( music->flac_decoder );
   373 				case 2:
   374 					flac.FLAC__stream_decoder_delete( music->flac_decoder );
   375 				case 1:
   376 				case 0:
   377 					free(music);
   378 					SDL_RWclose(rw);
   379 					break;
   380 			}
   381 			return NULL;
   382 		}
   383 	}
   384 	else {
   385 		SDL_OutOfMemory();
   386 	}
   387 
   388 	return music;
   389 }
   390 
   391 /* Start playback of a given FLAC stream */
   392 void FLAC_play(FLAC_music *music)
   393 {
   394 	music->playing = 1;
   395 }
   396 
   397 /* Return non-zero if a stream is currently playing */
   398 int FLAC_playing(FLAC_music *music)
   399 {
   400 	return(music->playing);
   401 }
   402 
   403 /* Read some FLAC stream data and convert it for output */
   404 static void FLAC_getsome(FLAC_music *music)
   405 {
   406 	SDL_AudioCVT *cvt;
   407 
   408 	/* GET AUDIO wAVE DATA */
   409 	// set the max number of characters to read
   410 	music->flac_data.max_to_read = 8192;
   411 
   412 	// clear out the data buffer if it exists
   413 	if (music->flac_data.data) {
   414 		free (music->flac_data.data);
   415 	}
   416 
   417 	music->flac_data.data_len = music->flac_data.max_to_read;
   418 	music->flac_data.data_read = 0;
   419 	music->flac_data.data = (char *)malloc (music->flac_data.data_len);
   420 
   421 	// we have data to read
   422 	while(music->flac_data.max_to_read > 0) {
   423 		// first check if there is data in the overflow from before
   424 		if (music->flac_data.overflow) {
   425 			size_t overflow_len = music->flac_data.overflow_read;
   426 
   427 			if (overflow_len > music->flac_data.max_to_read) {
   428 				size_t overflow_extra_len = overflow_len -
   429 												music->flac_data.max_to_read;
   430 
   431 				char* new_overflow = (char *)malloc (overflow_extra_len);
   432 				memcpy (music->flac_data.data+music->flac_data.data_read,
   433 					music->flac_data.overflow, music->flac_data.max_to_read);
   434 				music->flac_data.data_read += music->flac_data.max_to_read;
   435 				memcpy (new_overflow,
   436 					music->flac_data.overflow + music->flac_data.max_to_read,
   437 					overflow_extra_len);
   438 				free (music->flac_data.overflow);
   439 				music->flac_data.overflow = new_overflow;
   440 				music->flac_data.overflow_len = overflow_extra_len;
   441 				music->flac_data.overflow_read = 0;
   442 				music->flac_data.max_to_read = 0;
   443 			}
   444 			else {
   445 				memcpy (music->flac_data.data+music->flac_data.data_read,
   446 					music->flac_data.overflow, overflow_len);
   447 				music->flac_data.data_read += overflow_len;
   448 				free (music->flac_data.overflow);
   449 				music->flac_data.overflow = NULL;
   450 				music->flac_data.overflow_len = 0;
   451 				music->flac_data.overflow_read = 0;
   452 				music->flac_data.max_to_read -= overflow_len;
   453 			}
   454 		}
   455 		else {
   456 			if (!flac.FLAC__stream_decoder_process_single (
   457 														music->flac_decoder)) {
   458 				music->flac_data.max_to_read = 0;
   459 			}
   460 
   461 			if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   462 									== FLAC__STREAM_DECODER_END_OF_STREAM) {
   463 				music->flac_data.max_to_read = 0;
   464 			}
   465 		}
   466 	}
   467 
   468 	if (music->flac_data.data_read <= 0) {
   469 		if (music->flac_data.data_read == 0) {
   470 			music->playing = 0;
   471 		}
   472 		return;
   473 	}
   474 	cvt = &music->cvt;
   475 	if (music->section < 0) {
   476 
   477 		SDL_BuildAudioCVT (cvt, AUDIO_S16, (Uint8)music->flac_data.channels,
   478 						(int)music->flac_data.sample_rate, mixer.format,
   479 		                mixer.channels, mixer.freq);
   480 		if (cvt->buf) {
   481 			free (cvt->buf);
   482 		}
   483 		cvt->buf = (Uint8 *)malloc (music->flac_data.data_len * cvt->len_mult);
   484 		music->section = 0;
   485 	}
   486 	if (cvt->buf) {
   487 		memcpy (cvt->buf, music->flac_data.data, music->flac_data.data_read);
   488 		if (cvt->needed) {
   489 			cvt->len = music->flac_data.data_read;
   490 			SDL_ConvertAudio (cvt);
   491 		}
   492 		else {
   493 			cvt->len_cvt = music->flac_data.data_read;
   494 		}
   495 		music->len_available = music->cvt.len_cvt;
   496 		music->snd_available = music->cvt.buf;
   497 	}
   498 	else {
   499 		SDL_SetError ("Out of memory");
   500 		music->playing = 0;
   501 	}
   502 }
   503 
   504 /* Play some of a stream previously started with FLAC_play() */
   505 int FLAC_playAudio(FLAC_music *music, Uint8 *snd, int len)
   506 {
   507 	int mixable;
   508 
   509 	while ((len > 0) && music->playing) {
   510 		if (!music->len_available) {
   511 			FLAC_getsome (music);
   512 		}
   513 		mixable = len;
   514 		if (mixable > music->len_available) {
   515 			mixable = music->len_available;
   516 		}
   517 		if (music->volume == MIX_MAX_VOLUME) {
   518 			memcpy (snd, music->snd_available, mixable);
   519 		}
   520 		else {
   521 			SDL_MixAudio (snd, music->snd_available, mixable, music->volume);
   522 		}
   523 		music->len_available -= mixable;
   524 		music->snd_available += mixable;
   525 		len -= mixable;
   526 		snd += mixable;
   527 	}
   528 
   529 	return len;
   530 }
   531 
   532 /* Stop playback of a stream previously started with FLAC_play() */
   533 void FLAC_stop(FLAC_music *music)
   534 {
   535 	music->playing = 0;
   536 }
   537 
   538 /* Close the given FLAC_music object */
   539 void FLAC_delete(FLAC_music *music)
   540 {
   541 	if (music) {
   542 		if (music->flac_decoder) {
   543 			flac.FLAC__stream_decoder_finish (music->flac_decoder);
   544 			flac.FLAC__stream_decoder_delete (music->flac_decoder);
   545 		}
   546 
   547 		if (music->flac_data.data) {
   548 			free (music->flac_data.data);
   549 		}
   550 
   551 		if (music->flac_data.overflow) {
   552 			free (music->flac_data.overflow);
   553 		}
   554 
   555 		if (music->cvt.buf) {
   556 			free (music->cvt.buf);
   557 		}
   558 
   559 		free (music);
   560 	}
   561 }
   562 
   563 /* Jump (seek) to a given position (time is in seconds) */
   564 void FLAC_jump_to_time(FLAC_music *music, double time)
   565 {
   566 	if (music) {
   567 		if (music->flac_decoder) {
   568 			double seek_sample = music->flac_data.sample_rate * time;
   569 
   570 			// clear data if it has data
   571 			if (music->flac_data.data) {
   572 				free (music->flac_data.data);
   573 				music->flac_data.data = NULL;
   574 			}
   575 
   576 			// clear overflow if it has data
   577 			if (music->flac_data.overflow) {
   578 				free (music->flac_data.overflow);
   579 				music->flac_data.overflow = NULL;
   580 			}
   581 
   582 			if (!flac.FLAC__stream_decoder_seek_absolute (music->flac_decoder,
   583 												(FLAC__uint64)seek_sample)) {
   584 				if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   585 										== FLAC__STREAM_DECODER_SEEK_ERROR) {
   586 					flac.FLAC__stream_decoder_flush (music->flac_decoder);
   587 				}
   588 
   589 				SDL_SetError
   590 					("Seeking of FLAC stream failed: libFLAC seek failed.");
   591 			}
   592 		}
   593 		else {
   594 			SDL_SetError
   595 				("Seeking of FLAC stream failed: FLAC decoder was NULL.");
   596 		}
   597 	}
   598 	else {
   599 		SDL_SetError ("Seeking of FLAC stream failed: music was NULL.");
   600 	}
   601 }
   602 
   603 #endif /* FLAC_MUSIC */