mirror of https://github.com/encounter/SDL.git
audio: libsamplerate loading now happens once at init time.
This commit is contained in:
parent
98cc9d10d3
commit
19e937fc2e
|
@ -107,6 +107,72 @@ static const AudioBootStrap *const bootstrap[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE_H
|
||||||
|
#ifdef SDL_LIBSAMPLERATE_DYNAMIC
|
||||||
|
static void *SRC_lib = NULL;
|
||||||
|
#endif
|
||||||
|
SDL_bool SRC_available = SDL_FALSE;
|
||||||
|
SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error) = NULL;
|
||||||
|
int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data) = NULL;
|
||||||
|
int (*SRC_src_reset)(SRC_STATE *state) = NULL;
|
||||||
|
SRC_STATE* (*SRC_src_delete)(SRC_STATE *state) = NULL;
|
||||||
|
const char* (*SRC_src_strerror)(int error) = NULL;
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
LoadLibSampleRate(void)
|
||||||
|
{
|
||||||
|
SRC_available = SDL_FALSE;
|
||||||
|
|
||||||
|
if (!SDL_GetHintBoolean("SDL_AUDIO_ALLOW_LIBRESAMPLE", SDL_TRUE)) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_LIBSAMPLERATE_DYNAMIC
|
||||||
|
SDL_assert(SRC_lib == NULL);
|
||||||
|
SRC_lib = SDL_LoadObject(SDL_LIBSAMPLERATE_DYNAMIC);
|
||||||
|
if (!SRC_lib) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SRC_src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(state->SRC_lib, "src_new");
|
||||||
|
SRC_src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(state->SRC_lib, "src_process");
|
||||||
|
SRC_src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_reset");
|
||||||
|
SRC_src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_delete");
|
||||||
|
SRC_src_strerror = (const char* (*)(int error))SDL_LoadFunction(state->SRC_lib, "src_strerror");
|
||||||
|
|
||||||
|
if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror) {
|
||||||
|
#ifdef SDL_LIBSAMPLERATE_DYNAMIC
|
||||||
|
SDL_UnloadObject(SRC_lib);
|
||||||
|
SRC_lib = NULL;
|
||||||
|
#endif
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRC_available = SDL_TRUE;
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
UnloadLibSampleRate(void)
|
||||||
|
{
|
||||||
|
#ifdef SDL_LIBSAMPLERATE_DYNAMIC
|
||||||
|
if (SRC_lib != NULL) {
|
||||||
|
SDL_UnloadObject(SRC_lib);
|
||||||
|
}
|
||||||
|
SRC_lib = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SRC_available = SDL_FALSE;
|
||||||
|
SRC_src_new = NULL;
|
||||||
|
SRC_src_process = NULL;
|
||||||
|
SRC_src_reset = NULL;
|
||||||
|
SRC_src_delete = NULL;
|
||||||
|
SRC_src_strerror = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static SDL_AudioDevice *
|
static SDL_AudioDevice *
|
||||||
get_audio_device(SDL_AudioDeviceID id)
|
get_audio_device(SDL_AudioDeviceID id)
|
||||||
{
|
{
|
||||||
|
@ -828,6 +894,10 @@ SDL_AudioInit(const char *driver_name)
|
||||||
/* Make sure we have a list of devices available at startup. */
|
/* Make sure we have a list of devices available at startup. */
|
||||||
current_audio.impl.DetectDevices();
|
current_audio.impl.DetectDevices();
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE_H
|
||||||
|
LoadLibSampleRate();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,6 +1497,10 @@ SDL_AudioQuit(void)
|
||||||
|
|
||||||
SDL_zero(current_audio);
|
SDL_zero(current_audio);
|
||||||
SDL_zero(open_devices);
|
SDL_zero(open_devices);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE_H
|
||||||
|
UnloadLibSampleRate();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUM_FORMATS 10
|
#define NUM_FORMATS 10
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
|
|
||||||
/* Functions and variables exported from SDL_audio.c for SDL_sysaudio.c */
|
/* Functions and variables exported from SDL_audio.c for SDL_sysaudio.c */
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE_H
|
||||||
|
extern SDL_bool SRC_available;
|
||||||
|
typedef struct SRC_STATE SRC_STATE;
|
||||||
|
extern SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error);
|
||||||
|
extern int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data);
|
||||||
|
extern int (*SRC_src_reset)(SRC_STATE *state);
|
||||||
|
extern SRC_STATE* (*SRC_src_delete)(SRC_STATE *state);
|
||||||
|
extern const char* (*SRC_src_strerror)(int error);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Functions to get a list of "close" audio formats */
|
/* Functions to get a list of "close" audio formats */
|
||||||
extern SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format);
|
extern SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format);
|
||||||
extern SDL_AudioFormat SDL_NextAudioFormat(void);
|
extern SDL_AudioFormat SDL_NextAudioFormat(void);
|
||||||
|
|
|
@ -634,45 +634,10 @@ struct SDL_AudioStream
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LIBSAMPLERATE_H
|
#ifdef HAVE_LIBSAMPLERATE_H
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *SRC_lib;
|
|
||||||
|
|
||||||
SRC_STATE* (*src_new)(int converter_type, int channels, int *error);
|
|
||||||
int (*src_process)(SRC_STATE *state, SRC_DATA *data);
|
|
||||||
int (*src_reset)(SRC_STATE *state);
|
|
||||||
SRC_STATE* (*src_delete)(SRC_STATE *state);
|
|
||||||
const char* (*src_strerror)(int error);
|
|
||||||
|
|
||||||
SRC_STATE *SRC_state;
|
|
||||||
} SDL_AudioStreamResamplerState_SRC;
|
|
||||||
|
|
||||||
static SDL_bool
|
|
||||||
LoadLibSampleRate(SDL_AudioStreamResamplerState_SRC *state)
|
|
||||||
{
|
|
||||||
#ifdef SDL_LIBSAMPLERATE_DYNAMIC
|
|
||||||
state->SRC_lib = SDL_LoadObject(SDL_LIBSAMPLERATE_DYNAMIC);
|
|
||||||
if (!state->SRC_lib) {
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state->src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(state->SRC_lib, "src_new");
|
|
||||||
state->src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(state->SRC_lib, "src_process");
|
|
||||||
state->src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_reset");
|
|
||||||
state->src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(state->SRC_lib, "src_delete");
|
|
||||||
state->src_strerror = (const char* (*)(int error))SDL_LoadFunction(state->SRC_lib, "src_strerror");
|
|
||||||
if (!state->src_new || !state->src_process || !state->src_reset || !state->src_delete || !state->src_strerror) {
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
return SDL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
|
SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
|
||||||
{
|
{
|
||||||
SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
|
SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
|
||||||
SRC_DATA data;
|
SRC_DATA data;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
@ -686,9 +651,9 @@ SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const i
|
||||||
data.end_of_input = 0;
|
data.end_of_input = 0;
|
||||||
data.src_ratio = stream->rate_incr;
|
data.src_ratio = stream->rate_incr;
|
||||||
|
|
||||||
result = state->src_process(state->SRC_state, &data);
|
result = SRC_src_process(state, &data);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
SDL_SetError("src_process() failed: %s", state->src_strerror(result));
|
SDL_SetError("src_process() failed: %s", SRC_src_strerror(result));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,20 +666,15 @@ SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const i
|
||||||
static void
|
static void
|
||||||
SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
|
SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
|
||||||
{
|
{
|
||||||
SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
|
SRC_src_reset((SRC_STATE *)stream->resampler_state);
|
||||||
state->src_reset(state->SRC_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
|
SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
|
||||||
{
|
{
|
||||||
SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC*)stream->resampler_state;
|
SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
|
||||||
if (state) {
|
if (state) {
|
||||||
if (state->SRC_lib) {
|
SRC_src_delete(state);
|
||||||
SDL_UnloadObject(state->SRC_lib);
|
|
||||||
}
|
|
||||||
state->src_delete(state->SRC_state);
|
|
||||||
SDL_free(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->resampler_state = NULL;
|
stream->resampler_state = NULL;
|
||||||
|
@ -726,15 +686,18 @@ SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
SetupLibSampleRateResampling(SDL_AudioStream *stream)
|
SetupLibSampleRateResampling(SDL_AudioStream *stream)
|
||||||
{
|
{
|
||||||
int result;
|
int result = 0;
|
||||||
|
SRC_STATE *state = NULL;
|
||||||
|
|
||||||
SDL_AudioStreamResamplerState_SRC *state = (SDL_AudioStreamResamplerState_SRC *)SDL_calloc(1, sizeof(*state));
|
if (SRC_available) {
|
||||||
|
state = SRC_src_new(SRC_SINC_FASTEST, stream->pre_resample_channels, &result);
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return SDL_FALSE;
|
SDL_SetError("src_new() failed: %s", SRC_src_strerror(result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadLibSampleRate(state)) {
|
if (!state) {
|
||||||
SDL_free(state);
|
SDL_CleanupAudioStreamResampler_SRC(stream);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,17 +706,11 @@ SetupLibSampleRateResampling(SDL_AudioStream *stream)
|
||||||
stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
|
stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
|
||||||
stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
|
stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
|
||||||
|
|
||||||
state->SRC_state = state->src_new(SRC_SINC_FASTEST, stream->pre_resample_channels, &result);
|
|
||||||
if (!state->SRC_state) {
|
|
||||||
SDL_SetError("src_new() failed: %s", state->src_strerror(result));
|
|
||||||
SDL_CleanupAudioStreamResampler_SRC(stream);
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_LIBSAMPLERATE_H */
|
#endif /* HAVE_LIBSAMPLERATE_H */
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SDL_bool resampler_seeded;
|
SDL_bool resampler_seeded;
|
||||||
|
|
Loading…
Reference in New Issue