/
music_flac.c
711 lines (624 loc) · 23.9 KB
1
/*
2
SDL_mixer: An audio mixer library based on the SDL library
3
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file is used to support SDL_LoadMUS playback of FLAC files.
22
~ Austen Dicken (admin@cvpcs.org)
23
24
*/
25
#ifdef MUSIC_FLAC
26
27
#include "SDL_assert.h"
28
#include "SDL_loadso.h"
29
30
31
#include "music_flac.h"
32
33
34
35
36
37
#include <FLAC/stream_decoder.h>
typedef struct {
int loaded;
void *handle;
38
FLAC__StreamDecoder *(*FLAC__stream_decoder_new)(void);
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
void (*FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
FLAC__StreamDecoderInitStatus (*FLAC__stream_decoder_init_stream)(
FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderReadCallback read_callback,
FLAC__StreamDecoderSeekCallback seek_callback,
FLAC__StreamDecoderTellCallback tell_callback,
FLAC__StreamDecoderLengthCallback length_callback,
FLAC__StreamDecoderEofCallback eof_callback,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data);
FLAC__bool (*FLAC__stream_decoder_finish)(FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_flush)(FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_process_single)(
FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_metadata)(
FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_stream)(
FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_seek_absolute)(
FLAC__StreamDecoder *decoder,
FLAC__uint64 sample);
FLAC__StreamDecoderState (*FLAC__stream_decoder_get_state)(
const FLAC__StreamDecoder *decoder);
64
65
66
67
68
FLAC__uint64 (*FLAC__stream_decoder_get_total_samples)(
const FLAC__StreamDecoder *decoder);
FLAC__bool (*FLAC__stream_decoder_set_metadata_respond)(
FLAC__StreamDecoder *decoder,
FLAC__MetadataType type);
69
70
71
72
73
74
75
} flac_loader;
static flac_loader flac = {
0, NULL
};
#ifdef FLAC_DYNAMIC
76
77
78
79
80
81
82
#define FUNCTION_LOADER(FUNC, SIG) \
flac.FUNC = (SIG) SDL_LoadFunction(flac.handle, #FUNC); \
if (flac.FUNC == NULL) { SDL_UnloadObject(flac.handle); return -1; }
#else
#define FUNCTION_LOADER(FUNC, SIG) \
flac.FUNC = FUNC;
#endif
83
84
static int FLAC_Load(void)
85
86
{
if (flac.loaded == 0) {
87
#ifdef FLAC_DYNAMIC
88
89
90
91
flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
if (flac.handle == NULL) {
return -1;
}
92
93
94
95
96
97
#elif defined(__MACOSX__)
extern FLAC__StreamDecoder *FLAC__stream_decoder_new(void) __attribute__((weak_import));
if (FLAC__stream_decoder_new == NULL)
{
/* Missing weakly linked framework */
Mix_SetError("Missing FLAC.framework");
98
99
return -1;
}
100
101
102
103
104
#endif
FUNCTION_LOADER(FLAC__stream_decoder_new, FLAC__StreamDecoder *(*)(void))
FUNCTION_LOADER(FLAC__stream_decoder_delete, void (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_init_stream, FLAC__StreamDecoderInitStatus (*)(
105
106
107
108
109
110
111
112
113
114
FLAC__StreamDecoder *,
FLAC__StreamDecoderReadCallback,
FLAC__StreamDecoderSeekCallback,
FLAC__StreamDecoderTellCallback,
FLAC__StreamDecoderLengthCallback,
FLAC__StreamDecoderEofCallback,
FLAC__StreamDecoderWriteCallback,
FLAC__StreamDecoderMetadataCallback,
FLAC__StreamDecoderErrorCallback,
void *))
115
116
117
118
119
120
121
FUNCTION_LOADER(FLAC__stream_decoder_finish, FLAC__bool (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_flush, FLAC__bool (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_process_single, FLAC__bool (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_metadata, FLAC__bool (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_stream, FLAC__bool (*)(FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_seek_absolute, FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
FUNCTION_LOADER(FLAC__stream_decoder_get_state, FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
122
123
124
125
126
FUNCTION_LOADER(FLAC__stream_decoder_get_total_samples,
FLAC__uint64 (*)(const FLAC__StreamDecoder *))
FUNCTION_LOADER(FLAC__stream_decoder_set_metadata_respond,
FLAC__bool (*)(FLAC__StreamDecoder *,
FLAC__MetadataType))
127
128
}
++flac.loaded;
129
130
131
132
133
return 0;
}
static void FLAC_Unload(void)
134
{
135
136
137
138
if (flac.loaded == 0) {
return;
}
if (flac.loaded == 1) {
139
#ifdef FLAC_DYNAMIC
140
SDL_UnloadObject(flac.handle);
141
#endif
142
143
}
--flac.loaded;
144
145
}
146
147
typedef struct {
148
149
150
int volume;
int play_count;
FLAC__StreamDecoder *flac_decoder;
151
152
153
154
155
unsigned sample_rate;
unsigned channels;
unsigned bits_per_sample;
SDL_RWops *src;
int freesrc;
156
SDL_AudioStream *stream;
157
158
159
160
161
162
int loop;
FLAC__uint64 pcm_pos;
SDL_bool loop_flag;
FLAC__uint64 loop_start;
FLAC__uint64 loop_end;
FLAC__uint64 loop_len;
163
} FLAC_Music;
164
165
166
167
static int FLAC_Seek(void *context, double position);
168
static FLAC__StreamDecoderReadStatus flac_read_music_cb(
169
170
171
172
const FLAC__StreamDecoder *decoder,
FLAC__byte buffer[],
size_t *bytes,
void *client_data)
173
{
174
FLAC_Music *data = (FLAC_Music*)client_data;
175
176
/* make sure there is something to be reading */
177
if (*bytes > 0) {
178
*bytes = SDL_RWread (data->src, buffer, sizeof (FLAC__byte), *bytes);
179
180
if (*bytes == 0) { /* error or no data was read (EOF) */
181
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
182
} else { /* data was read, continue */
183
184
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
185
} else {
186
187
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
188
189
190
}
static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
191
192
193
const FLAC__StreamDecoder *decoder,
FLAC__uint64 absolute_byte_offset,
void *client_data)
194
{
195
FLAC_Music *data = (FLAC_Music*)client_data;
196
197
if (SDL_RWseek(data->src, absolute_byte_offset, RW_SEEK_SET) < 0) {
198
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
199
} else {
200
201
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
202
203
204
}
static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
205
206
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *absolute_byte_offset,
207
void *client_data)
208
{
209
FLAC_Music *data = (FLAC_Music*)client_data;
210
211
Sint64 pos = SDL_RWtell(data->src);
212
213
214
if (pos < 0) {
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
215
} else {
216
217
218
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
219
220
}
221
static FLAC__StreamDecoderLengthStatus flac_length_music_cb(
222
223
224
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *stream_length,
void *client_data)
225
{
226
FLAC_Music *data = (FLAC_Music*)client_data;
227
228
229
Sint64 pos = SDL_RWtell(data->src);
Sint64 length = SDL_RWseek(data->src, 0, RW_SEEK_END);
230
231
if (SDL_RWseek(data->src, pos, RW_SEEK_SET) != pos || length < 0) {
232
233
234
/* there was an error attempting to return the stream to the original
* position, or the length was invalid. */
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
235
} else {
236
237
238
*stream_length = (FLAC__uint64)length;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
239
240
241
}
static FLAC__bool flac_eof_music_cb(
242
const FLAC__StreamDecoder *decoder,
243
void *client_data)
244
{
245
FLAC_Music *data = (FLAC_Music*)client_data;
246
247
248
Sint64 pos = SDL_RWtell(data->src);
Sint64 end = SDL_RWseek(data->src, 0, RW_SEEK_END);
249
250
/* was the original position equal to the end (a.k.a. the seek didn't move)? */
251
if (pos == end) {
252
/* must be EOF */
253
return true;
254
} else {
255
256
/* not EOF, return to the original position */
SDL_RWseek(data->src, pos, RW_SEEK_SET);
257
258
return false;
}
259
260
261
}
static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
262
263
264
265
const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[],
void *client_data)
266
{
267
268
FLAC_Music *music = (FLAC_Music *)client_data;
Sint16 *data;
269
unsigned int i, j, channels;
270
int shift_amount = 0, amount;
271
272
if (!music->stream) {
273
274
275
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
276
277
278
279
280
281
282
283
284
285
286
287
switch (music->bits_per_sample) {
case 16:
shift_amount = 0;
break;
case 20:
shift_amount = 4;
break;
case 24:
shift_amount = 8;
break;
default:
SDL_SetError("FLAC decoder doesn't support %d bits_per_sample", music->bits_per_sample);
288
289
290
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
291
292
293
294
295
296
if (music->channels == 3) {
/* We'll just drop the center channel for now */
channels = 2;
} else {
channels = music->channels;
}
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
data = SDL_stack_alloc(Sint16, (frame->header.blocksize * channels));
if (!data) {
SDL_SetError("Couldn't allocate %d bytes stack memory", (int)(frame->header.blocksize * channels * sizeof(*data)));
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (music->channels == 3) {
Sint16 *dst = data;
for (i = 0; i < frame->header.blocksize; ++i) {
Sint16 FL = (buffer[0][i] >> shift_amount);
Sint16 FR = (buffer[1][i] >> shift_amount);
Sint16 FCmix = (Sint16)((buffer[2][i] >> shift_amount) * 0.5f);
int sample;
sample = (FL + FCmix);
if (sample > SDL_MAX_SINT16) {
*dst = SDL_MAX_SINT16;
} else if (sample < SDL_MIN_SINT16) {
*dst = SDL_MIN_SINT16;
} else {
*dst = sample;
}
++dst;
320
321
322
323
324
325
326
327
sample = (FR + FCmix);
if (sample > SDL_MAX_SINT16) {
*dst = SDL_MAX_SINT16;
} else if (sample < SDL_MIN_SINT16) {
*dst = SDL_MIN_SINT16;
} else {
*dst = sample;
328
}
329
330
331
332
333
334
335
336
++dst;
}
} else {
for (i = 0; i < channels; ++i) {
Sint16 *dst = data + i;
for (j = 0; j < frame->header.blocksize; ++j) {
*dst = (buffer[i][j] >> shift_amount);
dst += channels;
337
338
339
}
}
}
340
341
amount = frame->header.blocksize * channels * sizeof(*data);
music->pcm_pos += frame->header.blocksize;
342
343
if ((music->loop == 1) && (music->play_count != 1) &&
(music->pcm_pos >= music->loop_end)) {
344
345
346
347
348
amount -= (music->pcm_pos - music->loop_end) * channels * sizeof(*data);
music->loop_flag = SDL_TRUE;
}
SDL_AudioStreamPut(music->stream, data, amount);
349
SDL_stack_free(data);
350
351
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
352
353
}
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/* Parse time string of the form HH:MM:SS.mmm and return equivalent sample
* position */
static FLAC__uint64 parse_time(char *time, unsigned samplerate_hz)
{
char *num_start, *p;
FLAC__uint64 result = 0;
char c;
/* Time is directly expressed as a sample position */
if (SDL_strchr(time, ':') == NULL) {
return SDL_strtoull(time, NULL, 10);
}
result = 0;
num_start = time;
for (p = time; *p != '\0'; ++p) {
if (*p == '.' || *p == ':') {
c = *p; *p = '\0';
result = result * 60 + SDL_atoi(num_start);
num_start = p + 1;
*p = c;
}
if (*p == '.') {
return result * samplerate_hz
+ (FLAC__uint64) (SDL_atof(p) * samplerate_hz);
}
}
return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
}
387
static void flac_metadata_music_cb(
388
389
390
const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
391
{
392
FLAC_Music *music = (FLAC_Music *)client_data;
393
const FLAC__StreamMetadata_VorbisComment *vc;
394
int channels;
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
unsigned rate;
char *param, *argument, *value;
SDL_bool is_loop_length = SDL_FALSE;
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
music->sample_rate = metadata->data.stream_info.sample_rate;
music->channels = metadata->data.stream_info.channels;
music->bits_per_sample = metadata->data.stream_info.bits_per_sample;
/*printf("FLAC: Sample rate = %d, channels = %d, bits_per_sample = %d\n", music->sample_rate, music->channels, music->bits_per_sample);*/
/* SDL's channel mapping and FLAC channel mapping are the same,
except for 3 channels: SDL is FL FR LFE and FLAC is FL FR FC
*/
if (music->channels == 3) {
channels = 2;
} else {
channels = music->channels;
}
413
414
415
416
417
418
/* We check for NULL stream later when we get data */
SDL_assert(!music->stream);
music->stream = SDL_NewAudioStream(AUDIO_S16SYS, channels, music->sample_rate,
music_spec.format, music_spec.channels, music_spec.freq);
} else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
419
420
int i;
421
422
423
vc = &metadata->data.vorbis_comment;
rate = music->sample_rate;
424
for (i = 0; i < vc->num_comments; ++i) {
425
param = SDL_strdup((const char *) vc->comments[i].entry);
426
427
428
429
430
431
432
433
argument = param;
value = SDL_strchr(param, '=');
if (value == NULL) {
value = param + SDL_strlen(param);
} else {
*(value++) = '\0';
}
434
435
436
/* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
* string if it is present at position 4. */
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
if ((argument[4] == '_') || (argument[4] == '-')) {
SDL_memmove(argument + 4, argument + 5,
SDL_strlen(argument) - 4);
}
if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
music->loop_start = parse_time(value, rate);
else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
music->loop_len = SDL_strtoull(value, NULL, 10);
is_loop_length = SDL_TRUE;
} else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
is_loop_length = SDL_FALSE;
music->loop_end = parse_time(value, rate);
}
SDL_free(param);
}
if (is_loop_length) {
music->loop_end = music->loop_start + music->loop_len;
} else {
music->loop_len = music->loop_end - music->loop_start;
}
460
}
461
462
463
}
static void flac_error_music_cb(
464
465
466
const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data)
467
{
468
/* print an SDL error based on the error status */
469
switch (status) {
470
471
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
472
break;
473
474
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
475
break;
476
477
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
478
break;
479
480
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
481
break;
482
483
default:
SDL_SetError("Error processing the FLAC file [UNKNOWN].");
484
485
break;
}
486
487
488
}
/* Load an FLAC stream from an SDL_RWops object */
489
static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
490
{
491
FLAC_Music *music;
492
493
int init_stage = 0;
int was_error = 1;
494
FLAC__uint64 full_length;
495
496
497
498
music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
if (!music) {
SDL_OutOfMemory();
499
500
return NULL;
}
501
502
music->src = src;
music->volume = MIX_MAX_VOLUME;
503
504
505
506
507
508
music->loop = -1;
music->loop_start = -1;
music->loop_end = 0;
music->loop_len = 0;
music->loop_flag = SDL_FALSE;
music->pcm_pos = 0;
509
510
511
512
music->flac_decoder = flac.FLAC__stream_decoder_new();
if (music->flac_decoder) {
init_stage++; /* stage 1! */
513
514
flac.FLAC__stream_decoder_set_metadata_respond(music->flac_decoder,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
515
516
517
518
519
520
521
522
523
524
525
526
if (flac.FLAC__stream_decoder_init_stream(
music->flac_decoder,
flac_read_music_cb, flac_seek_music_cb,
flac_tell_music_cb, flac_length_music_cb,
flac_eof_music_cb, flac_write_music_cb,
flac_metadata_music_cb, flac_error_music_cb,
music) == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
init_stage++; /* stage 2! */
if (flac.FLAC__stream_decoder_process_until_end_of_metadata(music->flac_decoder)) {
was_error = 0;
527
} else {
528
SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
529
530
}
} else {
531
SDL_SetError("FLAC__stream_decoder_init_stream() failed");
532
}
533
534
535
} else {
SDL_SetError("FLAC__stream_decoder_new() failed");
}
536
537
538
539
540
541
542
543
544
545
if (was_error) {
switch (init_stage) {
case 2:
flac.FLAC__stream_decoder_finish(music->flac_decoder);
case 1:
flac.FLAC__stream_decoder_delete(music->flac_decoder);
case 0:
SDL_free(music);
break;
546
}
547
return NULL;
548
}
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
/* loop_start, loop_end and loop_len get set by metadata callback if tags
* are present in metadata.
*/
full_length = flac.FLAC__stream_decoder_get_total_samples(music->flac_decoder);
if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
((music->loop_start < music->loop_end) || (music->loop_end > 0)) &&
(music->loop_start < full_length) &&
(music->loop_end <= full_length)) {
if (music->loop_start < 0) music->loop_start = 0;
if (music->loop_end == 0) music->loop_end = full_length;
music->loop = 1;
}
564
music->freesrc = freesrc;
565
return music;
566
567
}
568
569
570
/* Set the volume for an FLAC stream */
static void FLAC_SetVolume(void *context, int volume)
{
571
FLAC_Music *music = (FLAC_Music *)context;
572
573
574
music->volume = volume;
}
575
/* Start playback of a given FLAC stream */
576
static int FLAC_Play(void *context, int play_count)
577
{
578
579
580
FLAC_Music *music = (FLAC_Music *)context;
music->play_count = play_count;
return FLAC_Seek(music, 0.0);
581
582
583
}
/* Read some FLAC stream data and convert it for output */
584
static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
585
{
586
587
FLAC_Music *music = (FLAC_Music *)context;
int filled;
588
589
590
591
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
592
593
}
594
595
596
597
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
return 0;
598
}
599
600
601
602
if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
SDL_SetError("FLAC__stream_decoder_process_single() failed");
return -1;
603
}
604
605
606
607
608
609
610
611
612
if (music->loop_flag) {
music->pcm_pos = music->loop_start;
if (flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, music->loop_start) ==
FLAC__STREAM_DECODER_SEEK_ERROR) {
SDL_SetError("FLAC__stream_decoder_seek_absolute() failed");
flac.FLAC__stream_decoder_flush(music->flac_decoder);
return -1;
} else {
613
614
615
616
617
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
music->play_count = play_count;
618
619
620
621
music->loop_flag = SDL_FALSE;
}
}
622
623
624
625
if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
if (music->play_count == 1) {
music->play_count = 0;
SDL_AudioStreamFlush(music->stream);
626
} else {
627
628
629
630
631
632
633
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
if (FLAC_Play(music, play_count) < 0) {
return -1;
}
634
635
}
}
636
return 0;
637
638
639
}
/* Play some of a stream previously started with FLAC_play() */
640
static int FLAC_GetAudio(void *context, void *data, int bytes)
641
{
642
643
FLAC_Music *music = (FLAC_Music *)context;
return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
644
645
}
646
647
648
/* Jump (seek) to a given position (position is in seconds) */
static int FLAC_Seek(void *context, double position)
{
649
650
FLAC_Music *music = (FLAC_Music *)context;
double seek_sample = music->sample_rate * position;
651
652
SDL_AudioStreamClear(music->stream);
653
music->pcm_pos = seek_sample;
654
655
656
if (!flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, (FLAC__uint64)seek_sample)) {
if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
flac.FLAC__stream_decoder_flush(music->flac_decoder);
657
658
659
660
661
662
663
664
}
SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
return -1;
}
return 0;
}
665
/* Close the given FLAC_Music object */
666
static void FLAC_Delete(void *context)
667
{
668
FLAC_Music *music = (FLAC_Music *)context;
669
670
if (music) {
if (music->flac_decoder) {
671
672
flac.FLAC__stream_decoder_finish(music->flac_decoder);
flac.FLAC__stream_decoder_delete(music->flac_decoder);
673
}
674
675
if (music->stream) {
SDL_FreeAudioStream(music->stream);
676
}
677
678
if (music->freesrc) {
SDL_RWclose(music->src);
679
}
680
SDL_free(music);
681
}
682
683
}
684
Mix_MusicInterface Mix_MusicInterface_FLAC =
685
{
686
687
688
689
690
691
692
693
694
695
696
697
"FLAC",
MIX_MUSIC_FLAC,
MUS_FLAC,
SDL_FALSE,
SDL_FALSE,
FLAC_Load,
NULL, /* Open */
FLAC_CreateFromRW,
NULL, /* CreateFromFile */
FLAC_SetVolume,
FLAC_Play,
698
NULL, /* IsPlaying */
699
700
701
702
FLAC_GetAudio,
FLAC_Seek,
NULL, /* Pause */
NULL, /* Resume */
703
NULL, /* Stop */
704
705
706
707
708
709
710
711
FLAC_Delete,
NULL, /* Close */
FLAC_Unload,
};
#endif /* MUSIC_FLAC */
/* vi: set ts=4 sw=4 expandtab: */