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