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