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