Cog Audio: Made RetroArch resampler safer
parent
f2656bc7b3
commit
9feaffc92d
|
@ -902,7 +902,7 @@ static float db_to_scale(float db)
|
||||||
}
|
}
|
||||||
if (resampler && resampler_data)
|
if (resampler && resampler_data)
|
||||||
{
|
{
|
||||||
resampler->free(resampler_data);
|
resampler->free(resampler, resampler_data);
|
||||||
resampler = NULL;
|
resampler = NULL;
|
||||||
resampler_data = NULL;
|
resampler_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,9 @@
|
||||||
|
|
||||||
static void resampler_null_process(void *a, struct resampler_data *b) { }
|
static void resampler_null_process(void *a, struct resampler_data *b) { }
|
||||||
static size_t resampler_null_latency(void *a) { return 0; }
|
static size_t resampler_null_latency(void *a) { return 0; }
|
||||||
static void resampler_null_free(void *a) { }
|
static void resampler_null_free(const retro_resampler_t *a, void *b) { }
|
||||||
static void *resampler_null_init(const struct resampler_config *a, double b,
|
static void *resampler_null_init(const struct resampler_config *a, const retro_resampler_t **b,
|
||||||
enum resampler_quality c, size_t d, resampler_simd_mask_t e) { return (void*)0; }
|
double c, enum resampler_quality d, size_t e, resampler_simd_mask_t f) { return (void*)0; }
|
||||||
|
|
||||||
retro_resampler_t null_resampler = {
|
retro_resampler_t null_resampler = {
|
||||||
resampler_null_init,
|
resampler_null_init,
|
||||||
|
@ -189,7 +189,7 @@ static bool resampler_append_plugs(void **re,
|
||||||
resampler_simd_mask_t mask = (resampler_simd_mask_t)cpu_features_get();
|
resampler_simd_mask_t mask = (resampler_simd_mask_t)cpu_features_get();
|
||||||
|
|
||||||
if (*backend)
|
if (*backend)
|
||||||
*re = (*backend)->init(&resampler_config, bw_ratio, quality, channels, mask);
|
*re = (*backend)->init(&resampler_config, backend, bw_ratio, quality, channels, mask);
|
||||||
|
|
||||||
if (!*re)
|
if (!*re)
|
||||||
return false;
|
return false;
|
||||||
|
@ -244,7 +244,7 @@ bool retro_resampler_realloc(void **re, const retro_resampler_t **backend,
|
||||||
double bw_ratio)
|
double bw_ratio)
|
||||||
{
|
{
|
||||||
if (*re && *backend)
|
if (*re && *backend)
|
||||||
(*backend)->free(*re);
|
(*backend)->free(*backend, *re);
|
||||||
|
|
||||||
*re = NULL;
|
*re = NULL;
|
||||||
*backend = find_resampler_driver(ident);
|
*backend = find_resampler_driver(ident);
|
||||||
|
|
|
@ -781,7 +781,7 @@ static size_t resampler_sinc_latency(void *data)
|
||||||
return resamp->taps / 2;
|
return resamp->taps / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resampler_sinc_free(void *data)
|
static void resampler_sinc_free(const retro_resampler_t *resampler, void *data)
|
||||||
{
|
{
|
||||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)data;
|
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)data;
|
||||||
if (resamp) {
|
if (resamp) {
|
||||||
|
@ -789,6 +789,9 @@ static void resampler_sinc_free(void *data)
|
||||||
free(resamp->buffer);
|
free(resamp->buffer);
|
||||||
}
|
}
|
||||||
free(resamp);
|
free(resamp);
|
||||||
|
if (resampler && resampler != &sinc_resampler) {
|
||||||
|
free((void*)resampler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sinc_init_table_kaiser(rarch_sinc_resampler_t *resamp,
|
static void sinc_init_table_kaiser(rarch_sinc_resampler_t *resamp,
|
||||||
|
@ -908,8 +911,8 @@ static void sinc_init_table_lanczos(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *resampler_sinc_new(const struct resampler_config *config,
|
static void *resampler_sinc_new(const struct resampler_config *config,
|
||||||
double bandwidth_mod, enum resampler_quality quality,
|
const retro_resampler_t **_resampler, double bandwidth_mod,
|
||||||
size_t channels, resampler_simd_mask_t mask)
|
enum resampler_quality quality, size_t channels, resampler_simd_mask_t mask)
|
||||||
{
|
{
|
||||||
double cutoff = 0.0;
|
double cutoff = 0.0;
|
||||||
size_t phase_elems = 0;
|
size_t phase_elems = 0;
|
||||||
|
@ -920,10 +923,24 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||||
enum sinc_window window_type = SINC_WINDOW_NONE;
|
enum sinc_window window_type = SINC_WINDOW_NONE;
|
||||||
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)
|
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)
|
||||||
calloc(1, sizeof(*re));
|
calloc(1, sizeof(*re));
|
||||||
|
|
||||||
|
retro_resampler_t *resampler = (retro_resampler_t*)*_resampler;
|
||||||
|
|
||||||
if (!re)
|
if (!re)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (resampler == &sinc_resampler)
|
||||||
|
{
|
||||||
|
resampler = malloc(sizeof(*resampler));
|
||||||
|
if (!resampler)
|
||||||
|
{
|
||||||
|
free(re);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(resampler, *_resampler, sizeof(*resampler));
|
||||||
|
*_resampler = (const retro_resampler_t*)resampler;
|
||||||
|
}
|
||||||
|
|
||||||
switch (quality)
|
switch (quality)
|
||||||
{
|
{
|
||||||
case RESAMPLER_QUALITY_LOWEST:
|
case RESAMPLER_QUALITY_LOWEST:
|
||||||
|
@ -1032,39 +1049,39 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
sinc_resampler.process = resampler_sinc_process_c;
|
resampler->process = resampler_sinc_process_c;
|
||||||
if (window_type == SINC_WINDOW_KAISER)
|
if (window_type == SINC_WINDOW_KAISER)
|
||||||
sinc_resampler.process = resampler_sinc_process_c_kaiser;
|
resampler->process = resampler_sinc_process_c_kaiser;
|
||||||
|
|
||||||
if (mask & RESAMPLER_SIMD_AVX && enable_avx)
|
if (mask & RESAMPLER_SIMD_AVX && enable_avx)
|
||||||
{
|
{
|
||||||
#if defined(__AVX__)
|
#if defined(__AVX__)
|
||||||
sinc_resampler.process = resampler_sinc_process_avx;
|
resampler->process = resampler_sinc_process_avx;
|
||||||
if (window_type == SINC_WINDOW_KAISER)
|
if (window_type == SINC_WINDOW_KAISER)
|
||||||
sinc_resampler.process = resampler_sinc_process_avx_kaiser;
|
resampler->process = resampler_sinc_process_avx_kaiser;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (mask & RESAMPLER_SIMD_SSE)
|
else if (mask & RESAMPLER_SIMD_SSE)
|
||||||
{
|
{
|
||||||
#if defined(__SSE__)
|
#if defined(__SSE__)
|
||||||
sinc_resampler.process = resampler_sinc_process_sse;
|
resampler->process = resampler_sinc_process_sse;
|
||||||
if (window_type == SINC_WINDOW_KAISER)
|
if (window_type == SINC_WINDOW_KAISER)
|
||||||
sinc_resampler.process = resampler_sinc_process_sse_kaiser;
|
resampler->process = resampler_sinc_process_sse_kaiser;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (mask & RESAMPLER_SIMD_NEON)
|
else if (mask & RESAMPLER_SIMD_NEON)
|
||||||
{
|
{
|
||||||
#if (defined(__ARM_NEON__) || defined(HAVE_NEON))
|
#if (defined(__ARM_NEON__) || defined(HAVE_NEON))
|
||||||
sinc_resampler.process = resampler_sinc_process_neon;
|
resampler->process = resampler_sinc_process_neon;
|
||||||
if (window_type == SINC_WINDOW_KAISER)
|
if (window_type == SINC_WINDOW_KAISER)
|
||||||
sinc_resampler.process = resampler_sinc_process_neon_kaiser;
|
resampler->process = resampler_sinc_process_neon_kaiser;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return re;
|
return re;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
resampler_sinc_free(re);
|
resampler_sinc_free(resampler, re);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,21 +115,31 @@ struct resampler_config
|
||||||
resampler_config_free_t free;
|
resampler_config_free_t free;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* NEW: Init takes a pointer to a pointer to a retro_resampler struct, and
|
||||||
|
* fills it out with an altered version of the static structure. This is so
|
||||||
|
* other threads don't clobber the process pointer in each other's instances
|
||||||
|
* when selecting different resampler modes.
|
||||||
|
*
|
||||||
|
* Only the init function needs it on input, and the free function cleans up
|
||||||
|
* after it. The process and latency functions shouldn't need it. */
|
||||||
|
|
||||||
|
typedef struct retro_resampler retro_resampler_t;
|
||||||
|
|
||||||
/* Bandwidth factor. Will be < 1.0 for downsampling, > 1.0 for upsampling.
|
/* Bandwidth factor. Will be < 1.0 for downsampling, > 1.0 for upsampling.
|
||||||
* Corresponds to expected resampling ratio. */
|
* Corresponds to expected resampling ratio. */
|
||||||
typedef void *(*resampler_init_t)(const struct resampler_config *config,
|
typedef void *(*resampler_init_t)(const struct resampler_config *config,
|
||||||
double bandwidth_mod, enum resampler_quality quality,
|
const retro_resampler_t **resampler, double bandwidth_mod,
|
||||||
size_t channels, resampler_simd_mask_t mask);
|
enum resampler_quality quality, size_t channels, resampler_simd_mask_t mask);
|
||||||
|
|
||||||
/* Frees the handle. */
|
/* Frees the handle, and if duped by above, the resampler */
|
||||||
typedef void (*resampler_free_t)(void *data);
|
typedef void (*resampler_free_t)(const retro_resampler_t *resampler, void *data);
|
||||||
|
|
||||||
/* Processes input data. */
|
/* Processes input data. */
|
||||||
typedef void (*resampler_process_t)(void *_data, struct resampler_data *data);
|
typedef void (*resampler_process_t)(void *_data, struct resampler_data *data);
|
||||||
|
|
||||||
typedef size_t (*resampler_latency_t)(void *_data);
|
typedef size_t (*resampler_latency_t)(void *_data);
|
||||||
|
|
||||||
typedef struct retro_resampler
|
struct retro_resampler
|
||||||
{
|
{
|
||||||
resampler_init_t init;
|
resampler_init_t init;
|
||||||
resampler_process_t process;
|
resampler_process_t process;
|
||||||
|
@ -145,7 +155,7 @@ typedef struct retro_resampler
|
||||||
/* Computer-friendly short version of ident.
|
/* Computer-friendly short version of ident.
|
||||||
* Lower case, no spaces and special characters, etc. */
|
* Lower case, no spaces and special characters, etc. */
|
||||||
const char *short_ident;
|
const char *short_ident;
|
||||||
} retro_resampler_t;
|
};
|
||||||
|
|
||||||
typedef struct audio_frame_float
|
typedef struct audio_frame_float
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue