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)
{
resampler->free(resampler_data);
resampler->free(resampler, resampler_data);
resampler = NULL;
resampler_data = NULL;
}

View File

@ -34,9 +34,9 @@
static void resampler_null_process(void *a, struct resampler_data *b) { }
static size_t resampler_null_latency(void *a) { return 0; }
static void resampler_null_free(void *a) { }
static void *resampler_null_init(const struct resampler_config *a, double b,
enum resampler_quality c, size_t d, resampler_simd_mask_t e) { return (void*)0; }
static void resampler_null_free(const retro_resampler_t *a, void *b) { }
static void *resampler_null_init(const struct resampler_config *a, const retro_resampler_t **b,
double c, enum resampler_quality d, size_t e, resampler_simd_mask_t f) { return (void*)0; }
retro_resampler_t null_resampler = {
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();
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)
return false;
@ -244,7 +244,7 @@ bool retro_resampler_realloc(void **re, const retro_resampler_t **backend,
double bw_ratio)
{
if (*re && *backend)
(*backend)->free(*re);
(*backend)->free(*backend, *re);
*re = NULL;
*backend = find_resampler_driver(ident);

View File

@ -781,7 +781,7 @@ static size_t resampler_sinc_latency(void *data)
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;
if (resamp) {
@ -789,6 +789,9 @@ static void resampler_sinc_free(void *data)
free(resamp->buffer);
}
free(resamp);
if (resampler && resampler != &sinc_resampler) {
free((void*)resampler);
}
}
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,
double bandwidth_mod, enum resampler_quality quality,
size_t channels, resampler_simd_mask_t mask)
const retro_resampler_t **_resampler, double bandwidth_mod,
enum resampler_quality quality, size_t channels, resampler_simd_mask_t mask)
{
double cutoff = 0.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;
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)
calloc(1, sizeof(*re));
retro_resampler_t *resampler = (retro_resampler_t*)*_resampler;
if (!re)
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)
{
case RESAMPLER_QUALITY_LOWEST:
@ -1032,39 +1049,39 @@ static void *resampler_sinc_new(const struct resampler_config *config,
goto error;
}
sinc_resampler.process = resampler_sinc_process_c;
resampler->process = resampler_sinc_process_c;
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 defined(__AVX__)
sinc_resampler.process = resampler_sinc_process_avx;
resampler->process = resampler_sinc_process_avx;
if (window_type == SINC_WINDOW_KAISER)
sinc_resampler.process = resampler_sinc_process_avx_kaiser;
resampler->process = resampler_sinc_process_avx_kaiser;
#endif
}
else if (mask & RESAMPLER_SIMD_SSE)
{
#if defined(__SSE__)
sinc_resampler.process = resampler_sinc_process_sse;
resampler->process = resampler_sinc_process_sse;
if (window_type == SINC_WINDOW_KAISER)
sinc_resampler.process = resampler_sinc_process_sse_kaiser;
resampler->process = resampler_sinc_process_sse_kaiser;
#endif
}
else if (mask & RESAMPLER_SIMD_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)
sinc_resampler.process = resampler_sinc_process_neon_kaiser;
resampler->process = resampler_sinc_process_neon_kaiser;
#endif
}
return re;
error:
resampler_sinc_free(re);
resampler_sinc_free(resampler, re);
return NULL;
}

View File

@ -115,21 +115,31 @@ struct resampler_config
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.
* Corresponds to expected resampling ratio. */
typedef void *(*resampler_init_t)(const struct resampler_config *config,
double bandwidth_mod, enum resampler_quality quality,
size_t channels, resampler_simd_mask_t mask);
const retro_resampler_t **resampler, double bandwidth_mod,
enum resampler_quality quality, size_t channels, resampler_simd_mask_t mask);
/* Frees the handle. */
typedef void (*resampler_free_t)(void *data);
/* Frees the handle, and if duped by above, the resampler */
typedef void (*resampler_free_t)(const retro_resampler_t *resampler, void *data);
/* Processes input data. */
typedef void (*resampler_process_t)(void *_data, struct resampler_data *data);
typedef size_t (*resampler_latency_t)(void *_data);
typedef struct retro_resampler
struct retro_resampler
{
resampler_init_t init;
resampler_process_t process;
@ -145,7 +155,7 @@ typedef struct retro_resampler
/* Computer-friendly short version of ident.
* Lower case, no spaces and special characters, etc. */
const char *short_ident;
} retro_resampler_t;
};
typedef struct audio_frame_float
{