music_flac.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 27 Feb 2008 07:31:03 +0000
changeset 382 50501e45c57b
child 386 695494546b3c
permissions -rw-r--r--
Austen Dicken - Tue Feb 26 23:28:27 PST 2008

Ok, here is the patch I made for FLAC support.

I have tested it relatively thoroughly and currently the patch allows:
1. Pre-loading FLAC files and playing them via LoadWAV
2. The patch allows for FLAC support in the LoadMUS setting as well as:
* Pause / Resume
* Volume control
* Seeking

I also did a little benchmarking by comparing memory/cpu usage of playmus to
that of mplayer, and the results were very good. playmus typically took about
half the RAM as mplayer, though that may be attributed to mplayer being a more
"bulky" program. As such I would say that the two are probably about equal in
efficiency.

Also, it is important to note that, similar to the OGG support currently
built-in, my FLAC patch only supports 16 bit stereo-encoded sound. Also, it
is only for Native FLAC (standard) and not the derivative, Ogg-FLAC.

I have tried to find a simple way to detect Ogg-FLAC files, as the only
difference between Ogg-FLAC and Native FLAC support is changing the init_
function call, but after digging a little deeper it seems that Ogg-FLAC is
basically FLAC wrapped in an Ogg transport layer, so it would be better to have
a way to read the Ogg transport layer which then reads the inner audio files
according to the proper codec.

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