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)
|
||||
{
|
||||
resampler->free(resampler_data);
|
||||
resampler->free(resampler, resampler_data);
|
||||
resampler = NULL;
|
||||
resampler_data = NULL;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue