audio: libsamplerate loading now happens once at init time.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 08 Jan 2017 14:18:03 -0500
changeset 1079092726dd20acd
parent 10789 e3eb7a266ec2
child 10791 64c46e09df9d
audio: libsamplerate loading now happens once at init time.
src/audio/SDL_audio.c
src/audio/SDL_audio_c.h
src/audio/SDL_audiocvt.c
     1.1 --- a/src/audio/SDL_audio.c	Sun Jan 08 14:17:09 2017 -0500
     1.2 +++ b/src/audio/SDL_audio.c	Sun Jan 08 14:18:03 2017 -0500
     1.3 @@ -107,6 +107,72 @@
     1.4      NULL
     1.5  };
     1.6  
     1.7 +
     1.8 +#ifdef HAVE_LIBSAMPLERATE_H
     1.9 +#ifdef SDL_LIBSAMPLERATE_DYNAMIC
    1.10 +static void *SRC_lib = NULL;
    1.11 +#endif
    1.12 +SDL_bool SRC_available = SDL_FALSE;
    1.13 +SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error) = NULL;
    1.14 +int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data) = NULL;
    1.15 +int (*SRC_src_reset)(SRC_STATE *state) = NULL;
    1.16 +SRC_STATE* (*SRC_src_delete)(SRC_STATE *state) = NULL;
    1.17 +const char* (*SRC_src_strerror)(int error) = NULL;
    1.18 +
    1.19 +static SDL_bool
    1.20 +LoadLibSampleRate(void)
    1.21 +{
    1.22 +    SRC_available = SDL_FALSE;
    1.23 +
    1.24 +    if (!SDL_GetHintBoolean("SDL_AUDIO_ALLOW_LIBRESAMPLE", SDL_TRUE)) {
    1.25 +        return SDL_FALSE;
    1.26 +    }
    1.27 +
    1.28 +#ifdef SDL_LIBSAMPLERATE_DYNAMIC
    1.29 +    SDL_assert(SRC_lib == NULL);
    1.30 +    SRC_lib = SDL_LoadObject(SDL_LIBSAMPLERATE_DYNAMIC);
    1.31 +    if (!SRC_lib) {
    1.32 +        return SDL_FALSE;
    1.33 +    }
    1.34 +#endif
    1.35 +
    1.36 +    SRC_src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(state->SRC_lib, "src_new");
    1.37 +    SRC_src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(state->SRC_lib, "src_process");
    1.38 +    SRC_src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_reset");
    1.39 +    SRC_src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_delete");
    1.40 +    SRC_src_strerror = (const char* (*)(int error))SDL_LoadFunction(state->SRC_lib, "src_strerror");
    1.41 +
    1.42 +    if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror) {
    1.43 +        #ifdef SDL_LIBSAMPLERATE_DYNAMIC
    1.44 +        SDL_UnloadObject(SRC_lib);
    1.45 +        SRC_lib = NULL;
    1.46 +        #endif
    1.47 +        return SDL_FALSE;
    1.48 +    }
    1.49 +
    1.50 +    SRC_available = SDL_TRUE;
    1.51 +    return SDL_TRUE;
    1.52 +}
    1.53 +
    1.54 +static void
    1.55 +UnloadLibSampleRate(void)
    1.56 +{
    1.57 +#ifdef SDL_LIBSAMPLERATE_DYNAMIC
    1.58 +    if (SRC_lib != NULL) {
    1.59 +        SDL_UnloadObject(SRC_lib);
    1.60 +    }
    1.61 +    SRC_lib = NULL;
    1.62 +#endif
    1.63 +
    1.64 +    SRC_available = SDL_FALSE;
    1.65 +    SRC_src_new = NULL;
    1.66 +    SRC_src_process = NULL;
    1.67 +    SRC_src_reset = NULL;
    1.68 +    SRC_src_delete = NULL;
    1.69 +    SRC_src_strerror = NULL;
    1.70 +}
    1.71 +#endif
    1.72 +
    1.73  static SDL_AudioDevice *
    1.74  get_audio_device(SDL_AudioDeviceID id)
    1.75  {
    1.76 @@ -828,6 +894,10 @@
    1.77      /* Make sure we have a list of devices available at startup. */
    1.78      current_audio.impl.DetectDevices();
    1.79  
    1.80 +#ifdef HAVE_LIBSAMPLERATE_H
    1.81 +    LoadLibSampleRate();
    1.82 +#endif
    1.83 +
    1.84      return 0;
    1.85  }
    1.86  
    1.87 @@ -1427,6 +1497,10 @@
    1.88  
    1.89      SDL_zero(current_audio);
    1.90      SDL_zero(open_devices);
    1.91 +
    1.92 +#ifdef HAVE_LIBSAMPLERATE_H
    1.93 +    UnloadLibSampleRate();
    1.94 +#endif
    1.95  }
    1.96  
    1.97  #define NUM_FORMATS 10
     2.1 --- a/src/audio/SDL_audio_c.h	Sun Jan 08 14:17:09 2017 -0500
     2.2 +++ b/src/audio/SDL_audio_c.h	Sun Jan 08 14:18:03 2017 -0500
     2.3 @@ -36,6 +36,16 @@
     2.4  
     2.5  /* Functions and variables exported from SDL_audio.c for SDL_sysaudio.c */
     2.6  
     2.7 +#ifdef HAVE_LIBSAMPLERATE_H
     2.8 +extern SDL_bool SRC_available;
     2.9 +typedef struct SRC_STATE SRC_STATE;
    2.10 +extern SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error);
    2.11 +extern int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data);
    2.12 +extern int (*SRC_src_reset)(SRC_STATE *state);
    2.13 +extern SRC_STATE* (*SRC_src_delete)(SRC_STATE *state);
    2.14 +extern const char* (*SRC_src_strerror)(int error);
    2.15 +#endif
    2.16 +
    2.17  /* Functions to get a list of "close" audio formats */
    2.18  extern SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format);
    2.19  extern SDL_AudioFormat SDL_NextAudioFormat(void);
     3.1 --- a/src/audio/SDL_audiocvt.c	Sun Jan 08 14:17:09 2017 -0500
     3.2 +++ b/src/audio/SDL_audiocvt.c	Sun Jan 08 14:18:03 2017 -0500
     3.3 @@ -634,45 +634,10 @@
     3.4  };
     3.5  
     3.6  #ifdef HAVE_LIBSAMPLERATE_H
     3.7 -
     3.8 -typedef struct
     3.9 -{
    3.10 -    void *SRC_lib;
    3.11 -
    3.12 -    SRC_STATE* (*src_new)(int converter_type, int channels, int *error);
    3.13 -    int (*src_process)(SRC_STATE *state, SRC_DATA *data);
    3.14 -    int (*src_reset)(SRC_STATE *state);
    3.15 -    SRC_STATE* (*src_delete)(SRC_STATE *state);
    3.16 -    const char* (*src_strerror)(int error);
    3.17 -
    3.18 -    SRC_STATE *SRC_state;
    3.19 -} SDL_AudioStreamResamplerState_SRC;
    3.20 -
    3.21 -static SDL_bool
    3.22 -LoadLibSampleRate(SDL_AudioStreamResamplerState_SRC *state)
    3.23 -{
    3.24 -#ifdef SDL_LIBSAMPLERATE_DYNAMIC
    3.25 -    state->SRC_lib = SDL_LoadObject(SDL_LIBSAMPLERATE_DYNAMIC);
    3.26 -    if (!state->SRC_lib) {
    3.27 -        return SDL_FALSE;
    3.28 -    }
    3.29 -#endif
    3.30 -
    3.31 -    state->src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(state->SRC_lib, "src_new");
    3.32 -    state->src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(state->SRC_lib, "src_process");
    3.33 -    state->src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_reset");
    3.34 -    state->src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_delete");
    3.35 -    state->src_strerror = (const char* (*)(int error))SDL_LoadFunction(state->SRC_lib, "src_strerror");
    3.36 -    if (!state->src_new || !state->src_process || !state->src_reset || !state->src_delete || !state->src_strerror) {
    3.37 -        return SDL_FALSE;
    3.38 -    }
    3.39 -    return SDL_TRUE;
    3.40 -}
    3.41 -
    3.42  static int
    3.43  SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
    3.44  {
    3.45 -    SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
    3.46 +    SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
    3.47      SRC_DATA data;
    3.48      int result;
    3.49  
    3.50 @@ -686,9 +651,9 @@
    3.51      data.end_of_input = 0;
    3.52      data.src_ratio = stream->rate_incr;
    3.53  
    3.54 -    result = state->src_process(state->SRC_state, &data);
    3.55 +    result = SRC_src_process(state, &data);
    3.56      if (result != 0) {
    3.57 -        SDL_SetError("src_process() failed: %s", state->src_strerror(result));
    3.58 +        SDL_SetError("src_process() failed: %s", SRC_src_strerror(result));
    3.59          return 0;
    3.60      }
    3.61  
    3.62 @@ -701,20 +666,15 @@
    3.63  static void
    3.64  SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
    3.65  {
    3.66 -    SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
    3.67 -    state->src_reset(state->SRC_state);
    3.68 +    SRC_src_reset((SRC_STATE *)stream->resampler_state);
    3.69  }
    3.70  
    3.71  static void
    3.72  SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
    3.73  {
    3.74 -    SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
    3.75 +    SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
    3.76      if (state) {
    3.77 -        if (state->SRC_lib) {
    3.78 -            SDL_UnloadObject(state->SRC_lib);
    3.79 -        }
    3.80 -        state->src_delete(state->SRC_state);
    3.81 -        SDL_free(state);
    3.82 +        SRC_src_delete(state);
    3.83      }
    3.84  
    3.85      stream->resampler_state = NULL;
    3.86 @@ -726,15 +686,18 @@
    3.87  static SDL_bool
    3.88  SetupLibSampleRateResampling(SDL_AudioStream *stream)
    3.89  {
    3.90 -    int result;
    3.91 +    int result = 0;
    3.92 +    SRC_STATE *state = NULL;
    3.93  
    3.94 -    SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC *)SDL_calloc(1, sizeof(*state));
    3.95 -    if (!state) {
    3.96 -        return SDL_FALSE;
    3.97 +    if (SRC_available) {
    3.98 +        state = SRC_src_new(SRC_SINC_FASTEST, stream->pre_resample_channels, &result);
    3.99 +        if (!state) {
   3.100 +            SDL_SetError("src_new() failed: %s", SRC_src_strerror(result));
   3.101 +        }
   3.102      }
   3.103  
   3.104 -    if (!LoadLibSampleRate(state)) {
   3.105 -        SDL_free(state);
   3.106 +    if (!state) {
   3.107 +        SDL_CleanupAudioStreamResampler_SRC(stream);
   3.108          return SDL_FALSE;
   3.109      }
   3.110  
   3.111 @@ -743,16 +706,10 @@
   3.112      stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
   3.113      stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
   3.114  
   3.115 -    state->SRC_state = state->src_new(SRC_SINC_FASTEST, stream->pre_resample_channels, &result);
   3.116 -    if (!state->SRC_state) {
   3.117 -        SDL_SetError("src_new() failed: %s", state->src_strerror(result));
   3.118 -        SDL_CleanupAudioStreamResampler_SRC(stream);
   3.119 -        return SDL_FALSE;
   3.120 -    }
   3.121      return SDL_TRUE;
   3.122  }
   3.123 +#endif /* HAVE_LIBSAMPLERATE_H */
   3.124  
   3.125 -#endif /* HAVE_LIBSAMPLERATE_H */
   3.126  
   3.127  typedef struct
   3.128  {