music_flac.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 12 Nov 2018 16:54:24 -0800
changeset 925 5945988b4a41
parent 848 3907db698eb5
child 926 d6c9518fb5ee
permissions -rw-r--r--
Fixed bug 4371 - tvOS Simulator devices not listed

Caleb Cornett

In the Xcode-iOS project, when selecting the libSDL_mixer-tvOS target, no tvOS simulators appear in the available device dropdown.

This is easily fixed with the attached patch.
     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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 */
   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 */
   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 */
   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 */
   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() */
   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) */
   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 */
   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: */