1 /*
2 SDL_mixer: An audio mixer library based on the SDL library
3 Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20
21 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 #include "music_flac.h"
31
32 #include <FLAC/stream_decoder.h>
33
34
35 typedef struct {
36 int loaded;
37 void *handle;
38 FLAC__StreamDecoder *(*FLAC__stream_decoder_new)(void);
39 void (*FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
40 FLAC__StreamDecoderInitStatus (*FLAC__stream_decoder_init_stream)(
41 FLAC__StreamDecoder *decoder,
42 FLAC__StreamDecoderReadCallback read_callback,
43 FLAC__StreamDecoderSeekCallback seek_callback,
44 FLAC__StreamDecoderTellCallback tell_callback,
45 FLAC__StreamDecoderLengthCallback length_callback,
46 FLAC__StreamDecoderEofCallback eof_callback,
47 FLAC__StreamDecoderWriteCallback write_callback,
48 FLAC__StreamDecoderMetadataCallback metadata_callback,
49 FLAC__StreamDecoderErrorCallback error_callback,
50 void *client_data);
51 FLAC__bool (*FLAC__stream_decoder_finish)(FLAC__StreamDecoder *decoder);
52 FLAC__bool (*FLAC__stream_decoder_flush)(FLAC__StreamDecoder *decoder);
53 FLAC__bool (*FLAC__stream_decoder_process_single)(
54 FLAC__StreamDecoder *decoder);
55 FLAC__bool (*FLAC__stream_decoder_process_until_end_of_metadata)(
56 FLAC__StreamDecoder *decoder);
57 FLAC__bool (*FLAC__stream_decoder_process_until_end_of_stream)(
58 FLAC__StreamDecoder *decoder);
59 FLAC__bool (*FLAC__stream_decoder_seek_absolute)(
60 FLAC__StreamDecoder *decoder,
61 FLAC__uint64 sample);
62 FLAC__StreamDecoderState (*FLAC__stream_decoder_get_state)(
63 const FLAC__StreamDecoder *decoder);
64 } flac_loader;
65
66 static flac_loader flac = {
67 0, NULL
68 };
69
70 #ifdef FLAC_DYNAMIC
71 #define FUNCTION_LOADER(FUNC, SIG) \
72 flac.FUNC = (SIG) SDL_LoadFunction(flac.handle, #FUNC); \
73 if (flac.FUNC == NULL) { SDL_UnloadObject(flac.handle); return -1; }
74 #else
75 #define FUNCTION_LOADER(FUNC, SIG) \
76 flac.FUNC = FUNC;
77 #endif
78
FLAC_Load(void)79 static int FLAC_Load(void)
80 {
81 if (flac.loaded == 0) {
82 #ifdef FLAC_DYNAMIC
83 flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
84 if (flac.handle == NULL) {
85 return -1;
86 }
87 #elif defined(__MACOSX__)
88 extern FLAC__StreamDecoder *FLAC__stream_decoder_new(void) __attribute__((weak_import));
89 if (FLAC__stream_decoder_new == NULL)
90 {
91 /* Missing weakly linked framework */
92 Mix_SetError("Missing FLAC.framework");
93 return -1;
94 }
95 #endif
96
97 FUNCTION_LOADER(FLAC__stream_decoder_new, FLAC__StreamDecoder *(*)(void))
98 FUNCTION_LOADER(FLAC__stream_decoder_delete, void (*)(FLAC__StreamDecoder *))
99 FUNCTION_LOADER(FLAC__stream_decoder_init_stream, FLAC__StreamDecoderInitStatus (*)(
100 FLAC__StreamDecoder *,
101 FLAC__StreamDecoderReadCallback,
102 FLAC__StreamDecoderSeekCallback,
103 FLAC__StreamDecoderTellCallback,
104 FLAC__StreamDecoderLengthCallback,
105 FLAC__StreamDecoderEofCallback,
106 FLAC__StreamDecoderWriteCallback,
107 FLAC__StreamDecoderMetadataCallback,
108 FLAC__StreamDecoderErrorCallback,
109 void *))
110 FUNCTION_LOADER(FLAC__stream_decoder_finish, FLAC__bool (*)(FLAC__StreamDecoder *))
111 FUNCTION_LOADER(FLAC__stream_decoder_flush, FLAC__bool (*)(FLAC__StreamDecoder *))
112 FUNCTION_LOADER(FLAC__stream_decoder_process_single, FLAC__bool (*)(FLAC__StreamDecoder *))
113 FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_metadata, FLAC__bool (*)(FLAC__StreamDecoder *))
114 FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_stream, FLAC__bool (*)(FLAC__StreamDecoder *))
115 FUNCTION_LOADER(FLAC__stream_decoder_seek_absolute, FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
116 FUNCTION_LOADER(FLAC__stream_decoder_get_state, FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
117 }
118 ++flac.loaded;
119
120 return 0;
121 }
122
FLAC_Unload(void)123 static void FLAC_Unload(void)
124 {
125 if (flac.loaded == 0) {
126 return;
127 }
128 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 int volume;
139 int play_count;
140 FLAC__StreamDecoder *flac_decoder;
141 unsigned sample_rate;
142 unsigned channels;
143 unsigned bits_per_sample;
144 SDL_RWops *src;
145 int freesrc;
146 SDL_AudioStream *stream;
147 } FLAC_Music;
148
149
150 static int FLAC_Seek(void *context, double position);
151
flac_read_music_cb(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * client_data)152 static FLAC__StreamDecoderReadStatus flac_read_music_cb(
153 const FLAC__StreamDecoder *decoder,
154 FLAC__byte buffer[],
155 size_t *bytes,
156 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 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
168 }
169 } else {
170 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
171 }
172 }
173
flac_seek_music_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 absolute_byte_offset,void * client_data)174 static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
175 const FLAC__StreamDecoder *decoder,
176 FLAC__uint64 absolute_byte_offset,
177 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 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
185 }
186 }
187
flac_tell_music_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 * absolute_byte_offset,void * client_data)188 static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
189 const FLAC__StreamDecoder *decoder,
190 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 if (pos < 0) {
198 return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
199 } else {
200 *absolute_byte_offset = (FLAC__uint64)pos;
201 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
202 }
203 }
204
flac_length_music_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 * stream_length,void * client_data)205 static FLAC__StreamDecoderLengthStatus flac_length_music_cb(
206 const FLAC__StreamDecoder *decoder,
207 FLAC__uint64 *stream_length,
208 void *client_data)
209 {
210 FLAC_Music *data = (FLAC_Music*)client_data;
211
212 Sint64 pos = SDL_RWtell(data->src);
213 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 /* there was an error attempting to return the stream to the original
217 * position, or the length was invalid. */
218 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
219 } else {
220 *stream_length = (FLAC__uint64)length;
221 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
222 }
223 }
224
flac_eof_music_cb(const FLAC__StreamDecoder * decoder,void * client_data)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 Sint64 pos = SDL_RWtell(data->src);
232 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 /* not EOF, return to the original position */
240 SDL_RWseek(data->src, pos, RW_SEEK_SET);
241 return false;
242 }
243 }
244
flac_write_music_cb(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)245 static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
246 const FLAC__StreamDecoder *decoder,
247 const FLAC__Frame *frame,
248 const FLAC__int32 *const buffer[],
249 void *client_data)
250 {
251 FLAC_Music *music = (FLAC_Music *)client_data;
252 Sint16 *data;
253 unsigned int i, j, channels;
254 int shift_amount = 0;
255
256 if (!music->stream) {
257 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
258 }
259
260 switch (music->bits_per_sample) {
261 case 16:
262 shift_amount = 0;
263 break;
264 case 20:
265 shift_amount = 4;
266 break;
267 case 24:
268 shift_amount = 8;
269 break;
270 default:
271 SDL_SetError("FLAC decoder doesn't support %d bits_per_sample", music->bits_per_sample);
272 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
273 }
274
275 if (music->channels == 3) {
276 /* We'll just drop the center channel for now */
277 channels = 2;
278 } else {
279 channels = music->channels;
280 }
281
282 data = SDL_stack_alloc(Sint16, (frame->header.blocksize * channels));
283 if (!data) {
284 SDL_SetError("Couldn't allocate %d bytes stack memory", (int)(frame->header.blocksize * channels * sizeof(*data)));
285 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
286 }
287 if (music->channels == 3) {
288 Sint16 *dst = data;
289 for (i = 0; i < frame->header.blocksize; ++i) {
290 Sint16 FL = (buffer[0][i] >> shift_amount);
291 Sint16 FR = (buffer[1][i] >> shift_amount);
292 Sint16 FCmix = (Sint16)((buffer[2][i] >> shift_amount) * 0.5f);
293 int sample;
294
295 sample = (FL + FCmix);
296 if (sample > SDL_MAX_SINT16) {
297 *dst = SDL_MAX_SINT16;
298 } else if (sample < SDL_MIN_SINT16) {
299 *dst = SDL_MIN_SINT16;
300 } else {
301 *dst = sample;
302 }
303 ++dst;
304
305 sample = (FR + FCmix);
306 if (sample > SDL_MAX_SINT16) {
307 *dst = SDL_MAX_SINT16;
308 } else if (sample < SDL_MIN_SINT16) {
309 *dst = SDL_MIN_SINT16;
310 } else {
311 *dst = sample;
312 }
313 ++dst;
314 }
315 } else {
316 for (i = 0; i < channels; ++i) {
317 Sint16 *dst = data + i;
318 for (j = 0; j < frame->header.blocksize; ++j) {
319 *dst = (buffer[i][j] >> shift_amount);
320 dst += channels;
321 }
322 }
323 }
324 SDL_AudioStreamPut(music->stream, data, (frame->header.blocksize * channels * sizeof(*data)));
325 SDL_stack_free(data);
326
327 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
328 }
329
flac_metadata_music_cb(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)330 static void flac_metadata_music_cb(
331 const FLAC__StreamDecoder *decoder,
332 const FLAC__StreamMetadata *metadata,
333 void *client_data)
334 {
335 FLAC_Music *music = (FLAC_Music *)client_data;
336 int channels;
337
338 if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO) {
339 return;
340 }
341
342 music->sample_rate = metadata->data.stream_info.sample_rate;
343 music->channels = metadata->data.stream_info.channels;
344 music->bits_per_sample = metadata->data.stream_info.bits_per_sample;
345 /*printf("FLAC: Sample rate = %d, channels = %d, bits_per_sample = %d\n", music->sample_rate, music->channels, music->bits_per_sample);*/
346
347 /* SDL's channel mapping and FLAC channel mapping are the same,
348 except for 3 channels: SDL is FL FR LFE and FLAC is FL FR FC
349 */
350 if (music->channels == 3) {
351 channels = 2;
352 } else {
353 channels = music->channels;
354 }
355 /* We check for NULL stream later when we get data */
356 SDL_assert(!music->stream);
357 music->stream = SDL_NewAudioStream(AUDIO_S16SYS, channels, music->sample_rate,
358 music_spec.format, music_spec.channels, music_spec.freq);
359 }
360
flac_error_music_cb(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)361 static void flac_error_music_cb(
362 const FLAC__StreamDecoder *decoder,
363 FLAC__StreamDecoderErrorStatus status,
364 void *client_data)
365 {
366 /* print an SDL error based on the error status */
367 switch (status) {
368 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
369 SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
370 break;
371 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
372 SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
373 break;
374 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
375 SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
376 break;
377 case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
378 SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
379 break;
380 default:
381 SDL_SetError("Error processing the FLAC file [UNKNOWN].");
382 break;
383 }
384 }
385
386 /* Load an FLAC stream from an SDL_RWops object */
FLAC_CreateFromRW(SDL_RWops * src,int freesrc)387 static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
388 {
389 FLAC_Music *music;
390 int init_stage = 0;
391 int was_error = 1;
392
393 music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
394 if (!music) {
395 SDL_OutOfMemory();
396 return NULL;
397 }
398 music->src = src;
399 music->volume = MIX_MAX_VOLUME;
400
401 music->flac_decoder = flac.FLAC__stream_decoder_new();
402 if (music->flac_decoder) {
403 init_stage++; /* stage 1! */
404
405 if (flac.FLAC__stream_decoder_init_stream(
406 music->flac_decoder,
407 flac_read_music_cb, flac_seek_music_cb,
408 flac_tell_music_cb, flac_length_music_cb,
409 flac_eof_music_cb, flac_write_music_cb,
410 flac_metadata_music_cb, flac_error_music_cb,
411 music) == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
412 init_stage++; /* stage 2! */
413
414 if (flac.FLAC__stream_decoder_process_until_end_of_metadata(music->flac_decoder)) {
415 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 } else {
423 SDL_SetError("FLAC__stream_decoder_new() failed");
424 }
425
426 if (was_error) {
427 switch (init_stage) {
428 case 2:
429 flac.FLAC__stream_decoder_finish(music->flac_decoder);
430 case 1:
431 flac.FLAC__stream_decoder_delete(music->flac_decoder);
432 case 0:
433 SDL_free(music);
434 break;
435 }
436 return NULL;
437 }
438
439 music->freesrc = freesrc;
440 return music;
441 }
442
443 /* Set the volume for an FLAC stream */
FLAC_SetVolume(void * context,int volume)444 static void FLAC_SetVolume(void *context, int volume)
445 {
446 FLAC_Music *music = (FLAC_Music *)context;
447 music->volume = volume;
448 }
449
450 /* Start playback of a given FLAC stream */
FLAC_Play(void * context,int play_count)451 static int FLAC_Play(void *context, int play_count)
452 {
453 FLAC_Music *music = (FLAC_Music *)context;
454 music->play_count = play_count;
455 return FLAC_Seek(music, 0.0);
456 }
457
458 /* Read some FLAC stream data and convert it for output */
FLAC_GetSome(void * context,void * data,int bytes,SDL_bool * done)459 static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
460 {
461 FLAC_Music *music = (FLAC_Music *)context;
462 int filled;
463
464 filled = SDL_AudioStreamGet(music->stream, data, bytes);
465 if (filled != 0) {
466 return filled;
467 }
468
469 if (!music->play_count) {
470 /* All done */
471 *done = SDL_TRUE;
472 return 0;
473 }
474
475 if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
476 SDL_SetError("FLAC__stream_decoder_process_single() failed");
477 return -1;
478 }
479
480 if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
481 if (music->play_count == 1) {
482 music->play_count = 0;
483 SDL_AudioStreamFlush(music->stream);
484 } else {
485 int play_count = -1;
486 if (music->play_count > 0) {
487 play_count = (music->play_count - 1);
488 }
489 if (FLAC_Play(music, play_count) < 0) {
490 return -1;
491 }
492 }
493 }
494 return 0;
495 }
496
497 /* Play some of a stream previously started with FLAC_play() */
FLAC_GetAudio(void * context,void * data,int bytes)498 static int FLAC_GetAudio(void *context, void *data, int bytes)
499 {
500 FLAC_Music *music = (FLAC_Music *)context;
501 return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
502 }
503
504 /* Jump (seek) to a given position (position is in seconds) */
FLAC_Seek(void * context,double position)505 static int FLAC_Seek(void *context, double position)
506 {
507 FLAC_Music *music = (FLAC_Music *)context;
508 double seek_sample = music->sample_rate * position;
509
510 if (!flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, (FLAC__uint64)seek_sample)) {
511 if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
512 flac.FLAC__stream_decoder_flush(music->flac_decoder);
513 }
514
515 SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
516 return -1;
517 }
518 return 0;
519 }
520
521 /* Close the given FLAC_Music object */
FLAC_Delete(void * context)522 static void FLAC_Delete(void *context)
523 {
524 FLAC_Music *music = (FLAC_Music *)context;
525 if (music) {
526 if (music->flac_decoder) {
527 flac.FLAC__stream_decoder_finish(music->flac_decoder);
528 flac.FLAC__stream_decoder_delete(music->flac_decoder);
529 }
530 if (music->stream) {
531 SDL_FreeAudioStream(music->stream);
532 }
533 if (music->freesrc) {
534 SDL_RWclose(music->src);
535 }
536 SDL_free(music);
537 }
538 }
539
540 Mix_MusicInterface Mix_MusicInterface_FLAC =
541 {
542 "FLAC",
543 MIX_MUSIC_FLAC,
544 MUS_FLAC,
545 SDL_FALSE,
546 SDL_FALSE,
547
548 FLAC_Load,
549 NULL, /* Open */
550 FLAC_CreateFromRW,
551 NULL, /* CreateFromFile */
552 FLAC_SetVolume,
553 FLAC_Play,
554 NULL, /* IsPlaying */
555 FLAC_GetAudio,
556 FLAC_Seek,
557 NULL, /* Pause */
558 NULL, /* Resume */
559 NULL, /* Stop */
560 FLAC_Delete,
561 NULL, /* Close */
562 FLAC_Unload,
563 };
564
565 #endif /* MUSIC_FLAC */
566
567 /* vi: set ts=4 sw=4 expandtab: */
568