/
music_flac.c
567 lines (497 loc) · 18.8 KB
1
/*
2
SDL_mixer: An audio mixer library based on the SDL library
3
Copyright (C) 1997-2017 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
64
65
66
67
68
69
70
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);
} flac_loader;
static flac_loader flac = {
0, NULL
};
#ifdef FLAC_DYNAMIC
71
72
73
74
75
76
77
#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
78
79
static int FLAC_Load(void)
80
81
{
if (flac.loaded == 0) {
82
#ifdef FLAC_DYNAMIC
83
84
85
86
flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
if (flac.handle == NULL) {
return -1;
}
87
88
89
90
91
92
#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");
93
94
return -1;
}
95
96
97
98
99
#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 (*)(
100
101
102
103
104
105
106
107
108
109
FLAC__StreamDecoder *,
FLAC__StreamDecoderReadCallback,
FLAC__StreamDecoderSeekCallback,
FLAC__StreamDecoderTellCallback,
FLAC__StreamDecoderLengthCallback,
FLAC__StreamDecoderEofCallback,
FLAC__StreamDecoderWriteCallback,
FLAC__StreamDecoderMetadataCallback,
FLAC__StreamDecoderErrorCallback,
void *))
110
111
112
113
114
115
116
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))
117
118
}
++flac.loaded;
119
120
121
122
123
return 0;
}
static void FLAC_Unload(void)
124
{
125
126
127
128
if (flac.loaded == 0) {
return;
}
if (flac.loaded == 1) {
129
#ifdef FLAC_DYNAMIC
130
SDL_UnloadObject(flac.handle);
131
#endif
132
133
}
--flac.loaded;
134
135
}
136
137
typedef struct {
138
139
140
int volume;
int play_count;
FLAC__StreamDecoder *flac_decoder;
141
142
143
144
145
unsigned sample_rate;
unsigned channels;
unsigned bits_per_sample;
SDL_RWops *src;
int freesrc;
146
147
SDL_AudioStream *stream;
} FLAC_Music;
148
149
150
151
static int FLAC_Seek(void *context, double position);
152
static FLAC__StreamDecoderReadStatus flac_read_music_cb(
153
154
155
156
const FLAC__StreamDecoder *decoder,
FLAC__byte buffer[],
size_t *bytes,
void *client_data)
157
{
158
FLAC_Music *data = (FLAC_Music*)client_data;
159
160
/* make sure there is something to be reading */
161
if (*bytes > 0) {
162
*bytes = SDL_RWread (data->src, buffer, sizeof (FLAC__byte), *bytes);
163
164
if (*bytes == 0) { /* error or no data was read (EOF) */
165
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
166
} else { /* data was read, continue */
167
168
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
169
} else {
170
171
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
172
173
174
}
static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
175
176
177
const FLAC__StreamDecoder *decoder,
FLAC__uint64 absolute_byte_offset,
void *client_data)
178
{
179
FLAC_Music *data = (FLAC_Music*)client_data;
180
181
if (SDL_RWseek(data->src, absolute_byte_offset, RW_SEEK_SET) < 0) {
182
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
183
} else {
184
185
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
186
187
188
}
static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
189
190
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *absolute_byte_offset,
191
void *client_data)
192
{
193
FLAC_Music *data = (FLAC_Music*)client_data;
194
195
Sint64 pos = SDL_RWtell(data->src);
196
197
198
if (pos < 0) {
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
199
} else {
200
201
202
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
203
204
}
205
static FLAC__StreamDecoderLengthStatus flac_length_music_cb(
206
207
208
const FLAC__StreamDecoder *decoder,
FLAC__uint64 *stream_length,
void *client_data)
209
{
210
FLAC_Music *data = (FLAC_Music*)client_data;
211
212
213
Sint64 pos = SDL_RWtell(data->src);
Sint64 length = SDL_RWseek(data->src, 0, RW_SEEK_END);
214
215
if (SDL_RWseek(data->src, pos, RW_SEEK_SET) != pos || length < 0) {
216
217
218
/* 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;
219
} else {
220
221
222
*stream_length = (FLAC__uint64)length;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
223
224
225
}
static FLAC__bool flac_eof_music_cb(
226
const FLAC__StreamDecoder *decoder,
227
void *client_data)
228
{
229
FLAC_Music *data = (FLAC_Music*)client_data;
230
231
232
Sint64 pos = SDL_RWtell(data->src);
Sint64 end = SDL_RWseek(data->src, 0, RW_SEEK_END);
233
234
/* was the original position equal to the end (a.k.a. the seek didn't move)? */
235
if (pos == end) {
236
/* must be EOF */
237
return true;
238
} else {
239
240
/* not EOF, return to the original position */
SDL_RWseek(data->src, pos, RW_SEEK_SET);
241
242
return false;
}
243
244
245
}
static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
246
247
248
249
const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[],
void *client_data)
250
{
251
252
FLAC_Music *music = (FLAC_Music *)client_data;
Sint16 *data;
253
unsigned int i, j, channels;
254
int shift_amount = 0;
255
256
if (!music->stream) {
257
258
259
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
260
261
262
263
264
265
266
267
268
269
270
271
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);
272
273
274
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
275
276
277
278
279
280
if (music->channels == 3) {
/* We'll just drop the center channel for now */
channels = 2;
} else {
channels = music->channels;
}
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
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;
304
305
306
307
308
309
310
311
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;
312
}
313
314
315
316
317
318
319
320
++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;
321
322
323
}
}
}
324
325
SDL_AudioStreamPut(music->stream, data, (frame->header.blocksize * channels * sizeof(*data)));
SDL_stack_free(data);
326
327
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
328
329
330
}
static void flac_metadata_music_cb(
331
332
333
const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
334
{
335
336
337
338
339
FLAC_Music *music = (FLAC_Music *)client_data;
int channels;
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO) {
return;
340
}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
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;
}
/* 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);
359
360
361
}
static void flac_error_music_cb(
362
363
364
const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data)
365
{
366
/* print an SDL error based on the error status */
367
switch (status) {
368
369
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
370
break;
371
372
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
373
break;
374
375
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
376
break;
377
378
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
379
break;
380
381
default:
SDL_SetError("Error processing the FLAC file [UNKNOWN].");
382
383
break;
}
384
385
386
}
/* Load an FLAC stream from an SDL_RWops object */
387
static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
388
{
389
FLAC_Music *music;
390
391
392
int init_stage = 0;
int was_error = 1;
393
394
395
music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
if (!music) {
SDL_OutOfMemory();
396
397
return NULL;
}
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
music->src = src;
music->volume = MIX_MAX_VOLUME;
music->flac_decoder = flac.FLAC__stream_decoder_new();
if (music->flac_decoder) {
init_stage++; /* stage 1! */
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;
416
} else {
417
SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
418
419
}
} else {
420
SDL_SetError("FLAC__stream_decoder_init_stream() failed");
421
}
422
423
424
} else {
SDL_SetError("FLAC__stream_decoder_new() failed");
}
425
426
427
428
429
430
431
432
433
434
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;
435
}
436
return NULL;
437
}
438
439
music->freesrc = freesrc;
440
return music;
441
442
}
443
444
445
/* Set the volume for an FLAC stream */
static void FLAC_SetVolume(void *context, int volume)
{
446
FLAC_Music *music = (FLAC_Music *)context;
447
448
449
music->volume = volume;
}
450
/* Start playback of a given FLAC stream */
451
static int FLAC_Play(void *context, int play_count)
452
{
453
454
455
FLAC_Music *music = (FLAC_Music *)context;
music->play_count = play_count;
return FLAC_Seek(music, 0.0);
456
457
458
}
/* Read some FLAC stream data and convert it for output */
459
static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
460
{
461
462
FLAC_Music *music = (FLAC_Music *)context;
int filled;
463
464
465
466
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
467
468
}
469
470
471
472
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
return 0;
473
}
474
475
476
477
if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
SDL_SetError("FLAC__stream_decoder_process_single() failed");
return -1;
478
}
479
480
481
482
483
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);
484
} else {
485
486
487
488
489
490
491
int play_count = -1;
if (music->play_count > 0) {
play_count = (music->play_count - 1);
}
if (FLAC_Play(music, play_count) < 0) {
return -1;
}
492
493
}
}
494
return 0;
495
496
497
}
/* Play some of a stream previously started with FLAC_play() */
498
static int FLAC_GetAudio(void *context, void *data, int bytes)
499
{
500
501
FLAC_Music *music = (FLAC_Music *)context;
return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
502
503
}
504
505
506
/* Jump (seek) to a given position (position is in seconds) */
static int FLAC_Seek(void *context, double position)
{
507
508
FLAC_Music *music = (FLAC_Music *)context;
double seek_sample = music->sample_rate * position;
509
510
511
512
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);
513
514
515
516
517
518
519
520
}
SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
return -1;
}
return 0;
}
521
/* Close the given FLAC_Music object */
522
static void FLAC_Delete(void *context)
523
{
524
FLAC_Music *music = (FLAC_Music *)context;
525
526
if (music) {
if (music->flac_decoder) {
527
528
flac.FLAC__stream_decoder_finish(music->flac_decoder);
flac.FLAC__stream_decoder_delete(music->flac_decoder);
529
}
530
531
if (music->stream) {
SDL_FreeAudioStream(music->stream);
532
}
533
534
if (music->freesrc) {
SDL_RWclose(music->src);
535
}
536
SDL_free(music);
537
}
538
539
}
540
Mix_MusicInterface Mix_MusicInterface_FLAC =
541
{
542
543
544
545
546
547
548
549
550
551
552
553
"FLAC",
MIX_MUSIC_FLAC,
MUS_FLAC,
SDL_FALSE,
SDL_FALSE,
FLAC_Load,
NULL, /* Open */
FLAC_CreateFromRW,
NULL, /* CreateFromFile */
FLAC_SetVolume,
FLAC_Play,
554
NULL, /* IsPlaying */
555
556
557
558
FLAC_GetAudio,
FLAC_Seek,
NULL, /* Pause */
NULL, /* Resume */
559
NULL, /* Stop */
560
561
562
563
564
565
566
567
FLAC_Delete,
NULL, /* Close */
FLAC_Unload,
};
#endif /* MUSIC_FLAC */
/* vi: set ts=4 sw=4 expandtab: */