/
music_flac.c
705 lines (618 loc) · 23.7 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
342
343
344
345
346
347
amount = frame->header.blocksize * channels * sizeof(*data);
music->pcm_pos += frame->header.blocksize;
if ((music->loop == 1) && (music->pcm_pos >= music->loop_end)) {
amount -= (music->pcm_pos - music->loop_end) * channels * sizeof(*data);
music->loop_flag = SDL_TRUE;
}
SDL_AudioStreamPut(music->stream, data, amount);
348
SDL_stack_free(data);
349
350
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
351
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
/* 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;
}
386
static void flac_metadata_music_cb(
387
388
389
const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
390
{
391
FLAC_Music *music = (FLAC_Music *)client_data;
392
const FLAC__StreamMetadata_VorbisComment *vc;
393
int channels;
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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;
}
412
413
414
415
416
417
/* 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) {
418
419
int i;
420
421
422
vc = &metadata->data.vorbis_comment;
rate = music->sample_rate;
423
for (i = 0; i < vc->num_comments; ++i) {
424
param = SDL_strdup((const char *) vc->comments[i].entry);
425
426
427
428
429
430
431
432
argument = param;
value = SDL_strchr(param, '=');
if (value == NULL) {
value = param + SDL_strlen(param);
} else {
*(value++) = '\0';
}
433
434
435
/* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
* string if it is present at position 4. */
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
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;
}
459
}
460
461
462
}
static void flac_error_music_cb(
463
464
465
const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data)
466
{
467
/* print an SDL error based on the error status */
468
switch (status) {
469
470
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
471
break;
472
473
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
474
break;
475
476
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
477
break;
478
479
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
480
break;
481
482
default:
SDL_SetError("Error processing the FLAC file [UNKNOWN].");
483
484
break;
}
485
486
487
}
/* Load an FLAC stream from an SDL_RWops object */
488
static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
489
{
490
FLAC_Music *music;
491
492
int init_stage = 0;
int was_error = 1;
493
FLAC__uint64 full_length;
494
495
496
497
music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
if (!music) {
SDL_OutOfMemory();
498
499
return NULL;
}
500
501
music->src = src;
music->volume = MIX_MAX_VOLUME;
502
503
504
505
506
507
music->loop = -1;
music->loop_start = -1;
music->loop_end = 0;
music->loop_len = 0;
music->loop_flag = SDL_FALSE;
music->pcm_pos = 0;
508
509
510
511
music->flac_decoder = flac.FLAC__stream_decoder_new();
if (music->flac_decoder) {
init_stage++; /* stage 1! */
512
513
flac.FLAC__stream_decoder_set_metadata_respond(music->flac_decoder,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
514
515
516
517
518
519
520
521
522
523
524
525
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;
526
} else {
527
SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
528
529
}
} else {
530
SDL_SetError("FLAC__stream_decoder_init_stream() failed");
531
}
532
533
534
} else {
SDL_SetError("FLAC__stream_decoder_new() failed");
}
535
536
537
538
539
540
541
542
543
544
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;
545
}
546
return NULL;
547
}
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/* 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;
}
563
music->freesrc = freesrc;
564
return music;
565
566
}
567
568
569
/* Set the volume for an FLAC stream */
static void FLAC_SetVolume(void *context, int volume)
{
570
FLAC_Music *music = (FLAC_Music *)context;
571
572
573
music->volume = volume;
}
574
/* Start playback of a given FLAC stream */
575
static int FLAC_Play(void *context, int play_count)
576
{
577
578
579
FLAC_Music *music = (FLAC_Music *)context;
music->play_count = play_count;
return FLAC_Seek(music, 0.0);
580
581
582
}
/* Read some FLAC stream data and convert it for output */
583
static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
584
{
585
586
FLAC_Music *music = (FLAC_Music *)context;
int filled;
587
588
589
590
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
591
592
}
593
594
595
596
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
return 0;
597
}
598
599
600
601
if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
SDL_SetError("FLAC__stream_decoder_process_single() failed");
return -1;
602
}
603
604
605
606
607
608
609
610
611
612
613
614
615
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 {
music->loop_flag = SDL_FALSE;
}
}
616
617
618
619
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);
620
} else {
621
622
623
624
625
626
627
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
if (FLAC_Play(music, play_count) < 0) {
return -1;
}
628
629
}
}
630
return 0;
631
632
633
}
/* Play some of a stream previously started with FLAC_play() */
634
static int FLAC_GetAudio(void *context, void *data, int bytes)
635
{
636
637
FLAC_Music *music = (FLAC_Music *)context;
return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
638
639
}
640
641
642
/* Jump (seek) to a given position (position is in seconds) */
static int FLAC_Seek(void *context, double position)
{
643
644
FLAC_Music *music = (FLAC_Music *)context;
double seek_sample = music->sample_rate * position;
645
646
SDL_AudioStreamClear(music->stream);
647
music->pcm_pos = seek_sample;
648
649
650
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);
651
652
653
654
655
656
657
658
}
SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
return -1;
}
return 0;
}
659
/* Close the given FLAC_Music object */
660
static void FLAC_Delete(void *context)
661
{
662
FLAC_Music *music = (FLAC_Music *)context;
663
664
if (music) {
if (music->flac_decoder) {
665
666
flac.FLAC__stream_decoder_finish(music->flac_decoder);
flac.FLAC__stream_decoder_delete(music->flac_decoder);
667
}
668
669
if (music->stream) {
SDL_FreeAudioStream(music->stream);
670
}
671
672
if (music->freesrc) {
SDL_RWclose(music->src);
673
}
674
SDL_free(music);
675
}
676
677
}
678
Mix_MusicInterface Mix_MusicInterface_FLAC =
679
{
680
681
682
683
684
685
686
687
688
689
690
691
"FLAC",
MIX_MUSIC_FLAC,
MUS_FLAC,
SDL_FALSE,
SDL_FALSE,
FLAC_Load,
NULL, /* Open */
FLAC_CreateFromRW,
NULL, /* CreateFromFile */
FLAC_SetVolume,
FLAC_Play,
692
NULL, /* IsPlaying */
693
694
695
696
FLAC_GetAudio,
FLAC_Seek,
NULL, /* Pause */
NULL, /* Resume */
697
NULL, /* Stop */
698
699
700
701
702
703
704
705
FLAC_Delete,
NULL, /* Close */
FLAC_Unload,
};
#endif /* MUSIC_FLAC */
/* vi: set ts=4 sw=4 expandtab: */