/
music_flac.c
744 lines (649 loc) · 24.8 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
int loop;
158
159
FLAC__int64 pcm_pos;
FLAC__int64 full_length;
160
SDL_bool loop_flag;
161
162
163
FLAC__int64 loop_start;
FLAC__int64 loop_end;
FLAC__int64 loop_len;
164
} FLAC_Music;
165
166
167
168
static int FLAC_Seek(void *context, double position);
169
static FLAC__StreamDecoderReadStatus flac_read_music_cb(
170
171
172
173
const FLAC__StreamDecoder *decoder,
FLAC__byte buffer[],
size_t *bytes,
void *client_data)
174
{
175
FLAC_Music *data = (FLAC_Music*)client_data;
176
177
178
(void)decoder;
179
/* make sure there is something to be reading */
180
if (*bytes > 0) {
181
*bytes = SDL_RWread (data->src, buffer, sizeof (FLAC__byte), *bytes);
182
183
if (*bytes == 0) { /* error or no data was read (EOF) */
184
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
185
} else { /* data was read, continue */
186
187
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
188
} else {
189
190
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
191
192
193
}
static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
194
195
196
const FLAC__StreamDecoder *decoder,
FLAC__uint64 absolute_byte_offset,
void *client_data)
197
{
198
FLAC_Music *data = (FLAC_Music*)client_data;
199
200
201
202
(void)decoder;
if (SDL_RWseek(data->src, (Sint64)absolute_byte_offset, RW_SEEK_SET) < 0) {
203
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
204
} else {
205
206
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
207
208
209
}
static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
210
211
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *absolute_byte_offset,
212
void *client_data)
213
{
214
FLAC_Music *data = (FLAC_Music*)client_data;
215
216
Sint64 pos = SDL_RWtell(data->src);
217
218
219
(void)decoder;
220
221
if (pos < 0) {
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
222
} else {
223
224
225
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
226
227
}
228
static FLAC__StreamDecoderLengthStatus flac_length_music_cb(
229
230
231
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *stream_length,
void *client_data)
232
{
233
FLAC_Music *data = (FLAC_Music*)client_data;
234
235
236
Sint64 pos = SDL_RWtell(data->src);
Sint64 length = SDL_RWseek(data->src, 0, RW_SEEK_END);
237
238
239
(void)decoder;
240
if (SDL_RWseek(data->src, pos, RW_SEEK_SET) != pos || length < 0) {
241
242
243
/* 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;
244
} else {
245
246
247
*stream_length = (FLAC__uint64)length;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
248
249
250
}
static FLAC__bool flac_eof_music_cb(
251
const FLAC__StreamDecoder *decoder,
252
void *client_data)
253
{
254
FLAC_Music *data = (FLAC_Music*)client_data;
255
256
257
Sint64 pos = SDL_RWtell(data->src);
Sint64 end = SDL_RWseek(data->src, 0, RW_SEEK_END);
258
259
260
(void)decoder;
261
/* was the original position equal to the end (a.k.a. the seek didn't move)? */
262
if (pos == end) {
263
/* must be EOF */
264
return true;
265
} else {
266
267
/* not EOF, return to the original position */
SDL_RWseek(data->src, pos, RW_SEEK_SET);
268
269
return false;
}
270
271
272
}
static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
273
274
275
276
const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[],
void *client_data)
277
{
278
279
FLAC_Music *music = (FLAC_Music *)client_data;
Sint16 *data;
280
unsigned int i, j, channels;
281
int shift_amount = 0, amount;
282
283
284
(void)decoder;
285
if (!music->stream) {
286
287
288
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
289
290
291
292
293
294
295
296
297
298
299
300
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);
301
302
303
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
304
305
306
307
308
309
if (music->channels == 3) {
/* We'll just drop the center channel for now */
channels = 2;
} else {
channels = music->channels;
}
310
311
312
313
314
315
316
317
318
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) {
319
320
Sint16 FL = (Sint16)(buffer[0][i] >> shift_amount);
Sint16 FR = (Sint16)(buffer[1][i] >> shift_amount);
321
322
323
324
325
326
327
328
329
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 {
330
*dst = (Sint16)sample;
331
332
}
++dst;
333
334
335
336
337
338
339
sample = (FR + FCmix);
if (sample > SDL_MAX_SINT16) {
*dst = SDL_MAX_SINT16;
} else if (sample < SDL_MIN_SINT16) {
*dst = SDL_MIN_SINT16;
} else {
340
*dst = (Sint16)sample;
341
}
342
343
344
345
346
347
++dst;
}
} else {
for (i = 0; i < channels; ++i) {
Sint16 *dst = data + i;
for (j = 0; j < frame->header.blocksize; ++j) {
348
*dst = (Sint16)(buffer[i][j] >> shift_amount);
349
dst += channels;
350
351
352
}
}
}
353
amount = (int)(frame->header.blocksize * channels * sizeof(*data));
354
music->pcm_pos += (FLAC__int64) frame->header.blocksize;
355
if (music->loop && (music->play_count != 1) &&
356
(music->pcm_pos >= music->loop_end)) {
357
amount -= (music->pcm_pos - music->loop_end) * channels * (int)sizeof(*data);
358
359
360
361
music->loop_flag = SDL_TRUE;
}
SDL_AudioStreamPut(music->stream, data, amount);
362
SDL_stack_free(data);
363
364
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
365
366
}
367
368
/* Parse time string of the form HH:MM:SS.mmm and return equivalent sample
* position */
369
static FLAC__int64 parse_time(char *time, unsigned samplerate_hz)
370
371
{
char *num_start, *p;
372
373
FLAC__int64 result = 0;
char c; int val;
374
375
376
/* Time is directly expressed as a sample position */
if (SDL_strchr(time, ':') == NULL) {
377
return SDL_strtoll(time, NULL, 10);
378
379
380
381
382
383
384
385
}
result = 0;
num_start = time;
for (p = time; *p != '\0'; ++p) {
if (*p == '.' || *p == ':') {
c = *p; *p = '\0';
386
387
388
if ((val = SDL_atoi(num_start)) < 0)
return -1;
result = result * 60 + val;
389
390
391
392
393
num_start = p + 1;
*p = c;
}
if (*p == '.') {
394
395
396
double val_f = SDL_atof(p);
if (val_f < 0) return -1;
return result * samplerate_hz + (FLAC__int64) (val_f * samplerate_hz);
397
398
399
}
}
400
401
if ((val = SDL_atoi(num_start)) < 0) return -1;
return (result * 60 + val) * samplerate_hz;
402
403
}
404
static void flac_metadata_music_cb(
405
406
407
const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
408
{
409
FLAC_Music *music = (FLAC_Music *)client_data;
410
const FLAC__StreamMetadata_VorbisComment *vc;
411
int channels;
412
413
414
415
unsigned rate;
char *param, *argument, *value;
SDL_bool is_loop_length = SDL_FALSE;
416
417
(void)decoder;
418
419
420
421
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;
422
/*printf("FLAC: Sample rate = %d, channels = %d, bits_per_sample = %d\n", music->sample_rate, music->channels, music->bits_per_sample);*/
423
424
425
426
427
428
429
/* 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 {
430
channels = (int)music->channels;
431
}
432
433
434
/* We check for NULL stream later when we get data */
SDL_assert(!music->stream);
435
music->stream = SDL_NewAudioStream(AUDIO_S16SYS, (Uint8)channels, (int)music->sample_rate,
436
437
music_spec.format, music_spec.channels, music_spec.freq);
} else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
438
FLAC__uint32 i;
439
440
441
442
vc = &metadata->data.vorbis_comment;
rate = music->sample_rate;
443
for (i = 0; i < vc->num_comments; ++i) {
444
param = SDL_strdup((const char *) vc->comments[i].entry);
445
446
447
448
449
450
451
452
argument = param;
value = SDL_strchr(param, '=');
if (value == NULL) {
value = param + SDL_strlen(param);
} else {
*(value++) = '\0';
}
453
454
455
456
/* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
* string if it is present at position 4. */
if ((argument[4] == '_') || (argument[4] == '-')) {
457
SDL_memmove(argument + 4, argument + 5, SDL_strlen(argument) - 4);
458
459
460
461
462
}
if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
music->loop_start = parse_time(value, rate);
else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
463
music->loop_len = SDL_strtoll(value, NULL, 10);
464
465
466
is_loop_length = SDL_TRUE;
} else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
music->loop_end = parse_time(value, rate);
467
is_loop_length = SDL_FALSE;
468
}
469
470
471
472
473
474
475
if (music->loop_start < 0 || music->loop_len < 0 || music->loop_end < 0) {
music->loop_start = 0;
music->loop_len = 0;
music->loop_end = 0;
SDL_free(param);
break; /* ignore tag. */
}
476
477
478
479
480
481
482
483
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;
}
484
}
485
486
487
}
static void flac_error_music_cb(
488
489
490
const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data)
491
{
492
493
494
(void)decoder;
(void)client_data;
495
/* print an SDL error based on the error status */
496
switch (status) {
497
498
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
499
break;
500
501
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
502
break;
503
504
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
505
break;
506
507
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
508
break;
509
510
default:
SDL_SetError("Error processing the FLAC file [UNKNOWN].");
511
512
break;
}
513
514
515
}
/* Load an FLAC stream from an SDL_RWops object */
516
static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
517
{
518
FLAC_Music *music;
519
520
int init_stage = 0;
int was_error = 1;
521
FLAC__int64 full_length;
522
523
524
525
music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
if (!music) {
SDL_OutOfMemory();
526
527
return NULL;
}
528
529
530
531
532
533
music->src = src;
music->volume = MIX_MAX_VOLUME;
music->flac_decoder = flac.FLAC__stream_decoder_new();
if (music->flac_decoder) {
init_stage++; /* stage 1! */
534
535
flac.FLAC__stream_decoder_set_metadata_respond(music->flac_decoder,
FLAC__METADATA_TYPE_VORBIS_COMMENT);
536
537
538
539
540
541
542
543
544
545
546
547
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;
548
} else {
549
SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
550
551
}
} else {
552
SDL_SetError("FLAC__stream_decoder_init_stream() failed");
553
}
554
555
556
} else {
SDL_SetError("FLAC__stream_decoder_new() failed");
}
557
558
559
560
if (was_error) {
switch (init_stage) {
case 2:
561
flac.FLAC__stream_decoder_finish(music->flac_decoder); /* fallthrough */
562
case 1:
563
flac.FLAC__stream_decoder_delete(music->flac_decoder); /* fallthrough */
564
565
566
case 0:
SDL_free(music);
break;
567
}
568
return NULL;
569
}
570
571
572
573
/* loop_start, loop_end and loop_len get set by metadata callback if tags
* are present in metadata.
*/
574
575
576
full_length = (FLAC__int64) flac.FLAC__stream_decoder_get_total_samples(music->flac_decoder);
if ((music->loop_end > 0) && (music->loop_end <= full_length) &&
(music->loop_start < music->loop_end)) {
577
578
579
music->loop = 1;
}
580
music->full_length = full_length;
581
music->freesrc = freesrc;
582
return music;
583
584
}
585
586
587
/* Set the volume for an FLAC stream */
static void FLAC_SetVolume(void *context, int volume)
{
588
FLAC_Music *music = (FLAC_Music *)context;
589
590
591
music->volume = volume;
}
592
593
594
595
596
597
598
/* Get the volume for an FLAC stream */
static int FLAC_GetVolume(void *context)
{
FLAC_Music *music = (FLAC_Music *)context;
return music->volume;
}
599
/* Start playback of a given FLAC stream */
600
static int FLAC_Play(void *context, int play_count)
601
{
602
603
604
FLAC_Music *music = (FLAC_Music *)context;
music->play_count = play_count;
return FLAC_Seek(music, 0.0);
605
606
607
}
/* Read some FLAC stream data and convert it for output */
608
static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
609
{
610
611
FLAC_Music *music = (FLAC_Music *)context;
int filled;
612
613
614
615
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
616
617
}
618
619
620
621
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
return 0;
622
}
623
624
625
626
if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
SDL_SetError("FLAC__stream_decoder_process_single() failed");
return -1;
627
}
628
629
630
if (music->loop_flag) {
music->pcm_pos = music->loop_start;
631
if (flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, (FLAC__uint64)music->loop_start) ==
632
633
634
635
636
FLAC__STREAM_DECODER_SEEK_ERROR) {
SDL_SetError("FLAC__stream_decoder_seek_absolute() failed");
flac.FLAC__stream_decoder_flush(music->flac_decoder);
return -1;
} else {
637
638
639
640
641
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
music->play_count = play_count;
642
643
644
645
music->loop_flag = SDL_FALSE;
}
}
646
647
648
649
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);
650
} else {
651
652
653
654
655
656
657
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
if (FLAC_Play(music, play_count) < 0) {
return -1;
}
658
659
}
}
660
return 0;
661
662
663
}
/* Play some of a stream previously started with FLAC_play() */
664
static int FLAC_GetAudio(void *context, void *data, int bytes)
665
{
666
667
FLAC_Music *music = (FLAC_Music *)context;
return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
668
669
}
670
671
672
/* Jump (seek) to a given position (position is in seconds) */
static int FLAC_Seek(void *context, double position)
{
673
FLAC_Music *music = (FLAC_Music *)context;
674
FLAC__uint64 seek_sample = (FLAC__uint64) (music->sample_rate * position);
675
676
SDL_AudioStreamClear(music->stream);
677
music->pcm_pos = (FLAC__int64) seek_sample;
678
if (!flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, seek_sample)) {
679
680
if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
flac.FLAC__stream_decoder_flush(music->flac_decoder);
681
682
683
684
685
686
687
688
}
SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
return -1;
}
return 0;
}
689
690
691
692
693
694
695
/* Return music duration in seconds */
static double FLAC_Duration(void *context)
{
FLAC_Music *music = (FLAC_Music *)context;
return (double)music->full_length / music->sample_rate;
}
696
/* Close the given FLAC_Music object */
697
static void FLAC_Delete(void *context)
698
{
699
FLAC_Music *music = (FLAC_Music *)context;
700
701
if (music) {
if (music->flac_decoder) {
702
703
flac.FLAC__stream_decoder_finish(music->flac_decoder);
flac.FLAC__stream_decoder_delete(music->flac_decoder);
704
}
705
706
if (music->stream) {
SDL_FreeAudioStream(music->stream);
707
}
708
709
if (music->freesrc) {
SDL_RWclose(music->src);
710
}
711
SDL_free(music);
712
}
713
714
}
715
Mix_MusicInterface Mix_MusicInterface_FLAC =
716
{
717
718
719
720
721
722
723
724
725
726
727
"FLAC",
MIX_MUSIC_FLAC,
MUS_FLAC,
SDL_FALSE,
SDL_FALSE,
FLAC_Load,
NULL, /* Open */
FLAC_CreateFromRW,
NULL, /* CreateFromFile */
FLAC_SetVolume,
728
FLAC_GetVolume,
729
FLAC_Play,
730
NULL, /* IsPlaying */
731
732
FLAC_GetAudio,
FLAC_Seek,
733
FLAC_Duration,
734
735
NULL, /* Pause */
NULL, /* Resume */
736
NULL, /* Stop */
737
738
FLAC_Delete,
NULL, /* Close */
739
FLAC_Unload
740
741
742
743
744
};
#endif /* MUSIC_FLAC */
/* vi: set ts=4 sw=4 expandtab: */