Cog Audio: Made RetroArch resampler safer

CQTexperiment
Christopher Snowhill 2022-01-12 18:45:43 -08:00
parent f2656bc7b3
commit 9feaffc92d
4 changed files with 51 additions and 24 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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
{ {