From addba80c3b1e1781f0278188355b59dd9db56418 Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 20 May 2014 12:28:33 +0200 Subject: [PATCH] Rewrite DSP plugin interface. --- Makefile | 1 + Makefile.win | 1 + audio/dsp_filter.c | 363 ++++++++++++++++++++ audio/dsp_filter.h | 38 ++ audio/filters/rarch_dsp.h | 74 ++-- command.c | 1 - config.def.h | 3 - driver.c | 140 +------- driver.h | 1 - frontend/menu/backend/menu_common_backend.c | 31 +- general.h | 11 +- input/input_common.c | 1 - retroarch.c | 35 +- settings.c | 3 +- 14 files changed, 471 insertions(+), 232 deletions(-) create mode 100644 audio/dsp_filter.c create mode 100644 audio/dsp_filter.h diff --git a/Makefile b/Makefile index 239d6c3037..03ecf686b5 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ OBJ = frontend/frontend.o \ gfx/fonts/fonts.o \ gfx/fonts/bitmapfont.o \ audio/resampler.o \ + audio/dsp_filter.o \ audio/sinc.o \ audio/cc_resampler.o \ performance.o diff --git a/Makefile.win b/Makefile.win index 8acea301c7..cd6af8730a 100644 --- a/Makefile.win +++ b/Makefile.win @@ -46,6 +46,7 @@ OBJ = frontend/frontend.o \ gfx/image/image_rpng.o \ gfx/image_context.o \ audio/resampler.o \ + audio/dsp_filter.o \ audio/sinc.o \ audio/cc_resampler.o \ performance.o diff --git a/audio/dsp_filter.c b/audio/dsp_filter.c new file mode 100644 index 0000000000..4e5c12a26a --- /dev/null +++ b/audio/dsp_filter.c @@ -0,0 +1,363 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "../general.h" + +#include "dsp_filter.h" +#include "../dynamic.h" +#include "../conf/config_file.h" +#include "filters/rarch_dsp.h" +#include "../file_path.h" +#include "../file_ext.h" +#include "../compat/posix_string.h" + +#include + +struct rarch_dsp_plug +{ +#ifdef HAVE_DYLIB + dylib_t lib; +#endif + const struct dspfilter_implementation *impl; +}; + +struct rarch_dsp_instance +{ + const struct dspfilter_implementation *impl; + void *impl_data; +}; + +struct rarch_dsp_filter +{ + config_file_t *conf; + + struct rarch_dsp_plug *plugs; + unsigned num_plugs; + + struct rarch_dsp_instance *instances; + unsigned num_instances; +}; + +const struct dspfilter_implementation *find_implementation(rarch_dsp_filter_t *dsp, const char *ident) +{ + unsigned i; + for (i = 0; i < dsp->num_plugs; i++) + { + if (!strcmp(dsp->plugs[i].impl->short_ident, ident)) + return dsp->plugs[i].impl; + } + + return NULL; +} + +struct dsp_userdata +{ + config_file_t *conf; + const char *prefix[2]; +}; + +static int get_float(void *userdata, const char *key_str, float *value, float default_value) +{ + struct dsp_userdata *dsp = (struct dsp_userdata*)userdata; + + char key[2][256]; + snprintf(key[0], sizeof(key[0]), "%s_%s", dsp->prefix[0], key_str); + snprintf(key[1], sizeof(key[1]), "%s_%s", dsp->prefix[1], key_str); + + bool got = config_get_float(dsp->conf, key[0], value); + got = got || config_get_float(dsp->conf, key[1], value); + + if (!got) + *value = default_value; + return got; +} + +static int get_int(void *userdata, const char *key_str, int *value, int default_value) +{ + struct dsp_userdata *dsp = (struct dsp_userdata*)userdata; + + char key[2][256]; + snprintf(key[0], sizeof(key[0]), "%s_%s", dsp->prefix[0], key_str); + snprintf(key[1], sizeof(key[1]), "%s_%s", dsp->prefix[1], key_str); + + bool got = config_get_int(dsp->conf, key[0], value); + got = got || config_get_int(dsp->conf, key[1], value); + + if (!got) + *value = default_value; + return got; +} + +// Yup, still C >__< +#define get_array_setup() \ + struct dsp_userdata *dsp = (struct dsp_userdata*)userdata; \ + \ + char key[2][256]; \ + snprintf(key[0], sizeof(key[0]), "%s_%s", dsp->prefix[0], key_str); \ + snprintf(key[1], sizeof(key[1]), "%s_%s", dsp->prefix[1], key_str); \ + \ + char *str = NULL; \ + bool got = config_get_string(dsp->conf, key[0], &str); \ + got = got || config_get_string(dsp->conf, key[1], &str); + +#define get_array_body(T) \ + if (got) \ + { \ + unsigned i; \ + struct string_list *list = string_split(str, " "); \ + *values = (T*)calloc(list->size, sizeof(T)); \ + for (i = 0; i < list->size; i++) \ + (*values)[i] = (T)strtod(list->elems[i].data, NULL); \ + *out_num_values = list->size; \ + string_list_free(list); \ + return true; \ + } \ + else \ + { \ + *values = (T*)calloc(num_default_values, sizeof(T)); \ + memcpy(*values, default_values, sizeof(T) * num_default_values); \ + return false; \ + } + +static int get_float_array(void *userdata, const char *key_str, + float **values, unsigned *out_num_values, + const float *default_values, unsigned num_default_values) +{ + get_array_setup() + get_array_body(float) +} + +static int get_int_array(void *userdata, const char *key_str, + int **values, unsigned *out_num_values, + const int *default_values, unsigned num_default_values) +{ + get_array_setup() + get_array_body(int) +} + +static int get_string(void *userdata, const char *key_str, + char **output, const char *default_output) +{ + get_array_setup() + + if (got) + { + *output = str; + return true; + } + else + { + *output = strdup(default_output); + return false; + } +} + +static void dspfilter_free(void *userdata, void *ptr) +{ + free(ptr); +} + +static const struct dspfilter_config dspfilter_config = { + get_float, + get_int, + get_float_array, + get_int_array, + get_string, + dspfilter_free, +}; + +static bool create_filter_graph(rarch_dsp_filter_t *dsp, float sample_rate) +{ + unsigned i; + + unsigned filters = 0; + if (!config_get_uint(dsp->conf, "filters", &filters)) + return false; + + dsp->instances = (struct rarch_dsp_instance*)calloc(filters, sizeof(*dsp->instances)); + if (!dsp->instances) + return false; + + dsp->num_instances = filters; + + for (i = 0; i < filters; i++) + { + char key[64]; + snprintf(key, sizeof(key), "filter%u", i); + + char name[64]; + if (!config_get_array(dsp->conf, key, name, sizeof(name))) + return false; + + dsp->instances[i].impl = find_implementation(dsp, name); + if (!dsp->instances[i].impl) + return false; + + struct dsp_userdata userdata; + userdata.conf = dsp->conf; + userdata.prefix[0] = key; // Index-specific configs take priority over ident-specific. + userdata.prefix[1] = dsp->instances[i].impl->short_ident; + + struct dspfilter_info info = { sample_rate }; + dsp->instances[i].impl_data = dsp->instances[i].impl->init(&info, &dspfilter_config, &userdata); + if (!dsp->instances[i].impl_data) + return false; + } + + return true; +} + +#ifdef HAVE_DYLIB +static bool append_plugs(rarch_dsp_filter_t *dsp, struct string_list *list) +{ + unsigned i; + dspfilter_simd_mask_t mask = rarch_get_cpu_features(); + + for (unsigned i = 0; i < dsp->num_plugs; i++) + { + dylib_t lib = dylib_load(list->elems[i].data); + if (!lib) + continue; + + dspfilter_get_implementation_t cb = (dspfilter_get_implementation_t)dylib_proc(lib, "dspfilter_get_implementation"); + if (!cb) + { + dylib_close(lib); + continue; + } + + const struct dspfilter_implementation *impl = cb(mask); + if (!impl) + { + dylib_close(lib); + continue; + } + + if (impl->api_version != DSPFILTER_API_VERSION) + { + dylib_close(lib); + continue; + } + + struct rarch_dsp_plug *new_plugs = (struct rarch_dsp_plug*)realloc(dsp->plugs, sizeof(*dsp->plugs) * (dsp->num_plugs + 1)); + if (!new_plugs) + { + dylib_close(lib); + return false; + } + + RARCH_LOG("[DSP]: Found plug: %s (%s).\n", impl->ident, impl->short_ident); + + dsp->plugs = new_plugs; + dsp->plugs[dsp->num_plugs].lib = lib; + dsp->plugs[dsp->num_plugs].impl = impl; + dsp->num_plugs++; + } + + return true; +} +#else +// Append from built-in filters. +#endif + +rarch_dsp_filter_t *rarch_dsp_filter_new(const char *filter_config, float sample_rate) +{ + char basedir[PATH_MAX]; + struct string_list *plugs = NULL; + + rarch_dsp_filter_t *dsp = (rarch_dsp_filter_t*)calloc(1, sizeof(*dsp)); + if (!dsp) + return NULL; + + dsp->conf = config_file_new(filter_config); + if (!dsp->conf) + { + RARCH_ERR("[DSP]: Did not find config: %s\n", filter_config); + goto error; + } + +#ifdef HAVE_DYLIB + fill_pathname_basedir(basedir, filter_config, sizeof(basedir)); + + plugs = dir_list_new(basedir, EXT_EXECUTABLES, false); + if (!plugs) + goto error; + + if (!append_plugs(dsp, plugs)) + goto error; + + string_list_free(plugs); + plugs = NULL; +#else + if (!append_plugs(dsp)) + goto error; +#endif + + if (!create_filter_graph(dsp, sample_rate)) + goto error; + + return dsp; + +error: + string_list_free(plugs); + rarch_dsp_filter_free(dsp); + return NULL; +} + +void rarch_dsp_filter_free(rarch_dsp_filter_t *dsp) +{ + unsigned i; + if (!dsp) + return; + + for (i = 0; i < dsp->num_instances; i++) + { + if (dsp->instances[i].impl_data && dsp->instances[i].impl) + dsp->instances[i].impl->free(dsp->instances[i].impl_data); + } + free(dsp->instances); + +#ifdef HAVE_DYLIB + for (i = 0; i < dsp->num_plugs; i++) + dylib_close(dsp->plugs[i].lib); + free(dsp->plugs); +#endif + + if (dsp->conf) + config_file_free(dsp->conf); + + free(dsp); +} + +void rarch_dsp_filter_process(rarch_dsp_filter_t *dsp, struct rarch_dsp_data *data) +{ + unsigned i; + struct dspfilter_output output = {0}; + struct dspfilter_input input = {0}; + + output.samples = data->input; + output.frames = data->input_frames; + + for (i = 0; i < dsp->num_instances; i++) + { + input.samples = output.samples; + input.frames = output.frames; + dsp->instances[i].impl->process(dsp->instances[i].impl_data, &output, &input); + } + + data->output = output.samples; + data->output_frames = output.frames; +} + diff --git a/audio/dsp_filter.h b/audio/dsp_filter.h new file mode 100644 index 0000000000..7ae95a5367 --- /dev/null +++ b/audio/dsp_filter.h @@ -0,0 +1,38 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef RARCH_DSP_FILTER_H__ +#define RARCH_DSP_FILTER_H__ + +typedef struct rarch_dsp_filter rarch_dsp_filter_t; + +rarch_dsp_filter_t *rarch_dsp_filter_new(const char *filter_config, float sample_rate); + +void rarch_dsp_filter_free(rarch_dsp_filter_t *dsp); + +struct rarch_dsp_data +{ + const float *input; + unsigned input_frames; + + // Set by rarch_dsp_filter_process(). + const float *output; + unsigned output_frames; +}; + +void rarch_dsp_filter_process(rarch_dsp_filter_t *dsp, struct rarch_dsp_data *data); + +#endif + diff --git a/audio/filters/rarch_dsp.h b/audio/filters/rarch_dsp.h index ba7ae9ef8c..a28c42252f 100644 --- a/audio/filters/rarch_dsp.h +++ b/audio/filters/rarch_dsp.h @@ -43,19 +43,19 @@ extern "C" { typedef unsigned dspfilter_simd_mask_t; // Dynamic library endpoint. -typedef const struct dspfilter_implementation *(*dspfilter_get_implementation_t)(dspfilter_simd_mask_t); +typedef const struct dspfilter_implementation *(*dspfilter_get_implementation_t)(dspfilter_simd_mask_t mask); // The same SIMD mask argument is forwarded to create() callback as well to avoid having to keep lots of state around. -const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t); +const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask); -#define RARCH_DSP_API_VERSION 6 +#define DSPFILTER_API_VERSION 1 -typedef struct rarch_dsp_info +struct dspfilter_info { // Input sample rate that the DSP plugin receives. float input_rate; -} rarch_dsp_info_t; +}; -typedef struct rarch_dsp_output +struct dspfilter_output { // The DSP plugin has to provide the buffering for the output samples. // This is for performance reasons to avoid redundant copying of data. @@ -70,9 +70,9 @@ typedef struct rarch_dsp_output // (I.e. 44.1kHz, 16bit stereo will have // 88.2k samples/sec and 44.1k frames/sec.) unsigned frames; -} rarch_dsp_output_t; +}; -typedef struct rarch_dsp_input +struct dspfilter_input { // Input data for the DSP. The samples are interleaved in order: LRLRLRLR const float *samples; @@ -83,41 +83,59 @@ typedef struct rarch_dsp_input // (I.e. 44.1kHz, 16bit stereo will have // 88.2k samples/sec and 44.1k frames/sec.) unsigned frames; -} rarch_dsp_input_t; +}; + +// Returns true if config key was found. Otherwise, returns false, and sets value to default value. +typedef int (*dspfilter_config_get_float_t)(void *userdata, const char *key, float *value, float default_value); +typedef int (*dspfilter_config_get_int_t)(void *userdata, const char *key, int *value, int default_value); + +// Allocates an array with values. free() with dspfilter_config_free_t. +typedef int (*dspfilter_config_get_float_array_t)(void *userdata, const char *key, + float **values, unsigned *out_num_values, + const float *default_values, unsigned num_default_values); + +typedef int (*dspfilter_config_get_int_array_t)(void *userdata, const char *key, + int **values, unsigned *out_num_values, + const int *default_values, unsigned num_default_values); + +typedef int (*dspfilter_config_get_string_t)(void *userdata, const char *key, char **output, const char *default_output); + +// Calls free() in host runtime. Sometimes needed on Windows. free() on NULL is fine. +typedef void (*dspfilter_config_free_t)(void *userdata, void *ptr); + +struct dspfilter_config +{ + dspfilter_config_get_float_t get_float; + dspfilter_config_get_int_t get_int; + + dspfilter_config_get_float_array_t get_float_array; + dspfilter_config_get_int_array_t get_int_array; + + dspfilter_config_get_string_t get_string; + dspfilter_config_free_t free; // Avoid problems where DSP plug and host are linked against different C runtimes. +}; // Creates a handle of the plugin. Returns NULL if failed. -typedef void *(*dspfilter_init_t)(const rarch_dsp_info_t *info); +typedef void *(*dspfilter_init_t)(const struct dspfilter_info *info, const struct dspfilter_config *config, void *userdata); // Frees the handle. typedef void (*dspfilter_free_t)(void *data); // Processes input data. // The plugin is allowed to return variable sizes for output data. -typedef void (*dspfilter_process_t)(void *data, rarch_dsp_output_t *output, - const rarch_dsp_input_t *input); - -// Signal plugin that it may open a configuring window or -// something similar. The behavior of this function -// is thus plugin dependent. Implementing this is optional, -// and can be set to NULL. -typedef void (*dspfilter_config_t)(void *data); - -// Called every frame, allows creating a GUI main loop in the main thread. -// GUI events can be processed here in a non-blocking fashion. -// Can be set to NULL to ignore it. -typedef void (*dspfilter_events_t)(void *data); +typedef void (*dspfilter_process_t)(void *data, struct dspfilter_output *output, + const struct dspfilter_input *input); struct dspfilter_implementation { dspfilter_init_t init; dspfilter_process_t process; dspfilter_free_t free; - int api_version; // Must be RARCH_DSP_API_VERSION - dspfilter_config_t config; - const char *ident; // Human readable identifier of implementation. - dspfilter_events_t events; -}; + unsigned api_version; // Must be DSPFILTER_API_VERSION + const char *ident; // Human readable identifier of implementation. + const char *short_ident; // Computer-friendly short version of ident. Lower case, no spaces and special characters, etc. +}; #ifdef __cplusplus } diff --git a/command.c b/command.c index 473482e5de..f913cb3695 100644 --- a/command.c +++ b/command.c @@ -195,7 +195,6 @@ static const struct cmd_map map[] = { { "CHEAT_INDEX_MINUS", RARCH_CHEAT_INDEX_MINUS }, { "CHEAT_TOGGLE", RARCH_CHEAT_TOGGLE }, { "SCREENSHOT", RARCH_SCREENSHOT }, - { "DSP_CONFIG", RARCH_DSP_CONFIG }, { "MUTE", RARCH_MUTE }, { "NETPLAY_FLIP", RARCH_NETPLAY_FLIP }, { "SLOWMOTION", RARCH_SLOWMOTION }, diff --git a/config.def.h b/config.def.h index a2a12ad0f4..70a4daa0fc 100644 --- a/config.def.h +++ b/config.def.h @@ -674,7 +674,6 @@ static const bool input_autodetect_enable = true; #define RETRO_LBL_CHEAT_INDEX_MINUS "Cheat Index Minus" #define RETRO_LBL_CHEAT_TOGGLE "Cheat Toggle" #define RETRO_LBL_SCREENSHOT "Screenshot" -#define RETRO_LBL_DSP_CONFIG "DSP Config" #define RETRO_LBL_MUTE "Mute Audio" #define RETRO_LBL_NETPLAY_FLIP "Netplay Flip Players" #define RETRO_LBL_SLOWMOTION "Slowmotion" @@ -736,7 +735,6 @@ static const struct retro_keybind retro_keybinds_1[] = { { true, RARCH_CHEAT_INDEX_MINUS, RETRO_LBL_CHEAT_INDEX_MINUS, RETROK_t, NO_BTN, 0, AXIS_NONE }, { true, RARCH_CHEAT_TOGGLE, RETRO_LBL_CHEAT_TOGGLE, RETROK_u, NO_BTN, 0, AXIS_NONE }, { true, RARCH_SCREENSHOT, RETRO_LBL_SCREENSHOT, RETROK_F8, NO_BTN, 0, AXIS_NONE }, - { true, RARCH_DSP_CONFIG, RETRO_LBL_DSP_CONFIG, RETROK_c, NO_BTN, 0, AXIS_NONE }, { true, RARCH_MUTE, RETRO_LBL_MUTE, RETROK_F9, NO_BTN, 0, AXIS_NONE }, { true, RARCH_NETPLAY_FLIP, RETRO_LBL_NETPLAY_FLIP, RETROK_i, NO_BTN, 0, AXIS_NONE }, { true, RARCH_SLOWMOTION, RETRO_LBL_SLOWMOTION, RETROK_e, NO_BTN, 0, AXIS_NONE }, @@ -799,7 +797,6 @@ static const struct retro_keybind retro_keybinds_menu[] = { { true, RARCH_CHEAT_INDEX_MINUS, RETRO_LBL_CHEAT_INDEX_MINUS, RETROK_t, NO_BTN, 0, AXIS_NONE }, { true, RARCH_CHEAT_TOGGLE, RETRO_LBL_CHEAT_TOGGLE, RETROK_u, NO_BTN, 0, AXIS_NONE }, { true, RARCH_SCREENSHOT, RETRO_LBL_SCREENSHOT, RETROK_F8, NO_BTN, 0, AXIS_NONE }, - { true, RARCH_DSP_CONFIG, RETRO_LBL_DSP_CONFIG, RETROK_c, NO_BTN, 0, AXIS_NONE }, { true, RARCH_MUTE, RETRO_LBL_MUTE, RETROK_F9, NO_BTN, 0, AXIS_NONE }, { true, RARCH_NETPLAY_FLIP, RETRO_LBL_NETPLAY_FLIP, RETROK_i, NO_BTN, 0, AXIS_NONE }, { true, RARCH_SLOWMOTION, RETRO_LBL_SLOWMOTION, RETROK_e, NO_BTN, 0, AXIS_NONE }, diff --git a/driver.c b/driver.c index 6f77a40011..e7892f2098 100644 --- a/driver.c +++ b/driver.c @@ -26,7 +26,7 @@ #include "audio/resampler.h" #include "gfx/thread_wrapper.h" #include "audio/thread_wrapper.h" -#include "audio/filters/rarch_dsp.h" +#include "audio/dsp_filter.h" #include "gfx/gfx_common.h" #ifdef HAVE_X11 @@ -970,144 +970,22 @@ void uninit_drivers(void) driver.input_data_own = false; } -#ifdef HAVE_FILTERS_BUILTIN -static const struct dspfilter_implementation *(*dspfilter_drivers[]) (dspfilter_simd_mask_t) = -{ - NULL, - &echo_dsp_plugin_init, -#ifndef _WIN32 -#ifndef ANDROID - &eq_dsp_plugin_init, -#endif -#endif - &iir_dsp_plugin_init, - &phaser_dsp_plugin_init, - &reverb_dsp_plugin_init, - &volume_dsp_plugin_init, - &wah_dsp_plugin_init, -}; - -unsigned dspfilter_get_last_idx(void) -{ - return sizeof(dspfilter_drivers) / sizeof(dspfilter_drivers[0]); -} - -static dspfilter_get_implementation_t dspfilter_get_implementation_from_idx(unsigned i) -{ - if (i < dspfilter_get_last_idx()) - return dspfilter_drivers[i]; - return NULL; -} - -#endif - - -const char *rarch_dspfilter_get_name(void *data) -{ - const struct dspfilter_implementation *impl; - (void)data; -#ifdef HAVE_FILTERS_BUILTIN - unsigned cpu_features; - dspfilter_get_implementation_t cb = (dspfilter_get_implementation_t)dspfilter_get_implementation_from_idx(g_settings.audio.filter_idx); - if (cb) - { - cpu_features = rarch_get_cpu_features(); - impl = (const struct dspfilter_implementation *)cb(cpu_features); - if (impl) - return impl->ident; - } - - return NULL; -#else - impl = (const struct dspfilter_implementation*)data; - if (!impl || !impl->ident) - return NULL; - - return impl->ident; -#endif -} - void rarch_init_dsp_filter(void) { - unsigned cpu_features; - dspfilter_get_implementation_t cb; - rarch_dsp_info_t info = {0}; - -#ifdef HAVE_FILTERS_BUILTIN - if (!g_settings.audio.filter_idx) -#else - if (!(*g_settings.audio.dsp_plugin)) -#endif + rarch_deinit_dsp_filter(); + if (!*g_settings.audio.dsp_plugin) return; - cb = NULL; - -#if defined(HAVE_FILTERS_BUILTIN) - cb = (dspfilter_get_implementation_t)dspfilter_get_implementation_from_idx(g_settings.audio.filter_idx); -#elif defined(HAVE_DYLIB) - g_extern.audio_data.dsp_lib = dylib_load(g_settings.audio.dsp_plugin); - if (!g_extern.audio_data.dsp_lib) - { - RARCH_ERR("Failed to open DSP plugin: \"%s\" ...\n", g_settings.audio.dsp_plugin); - return; - } - - cb = (dspfilter_get_implementation_t)dylib_proc(g_extern.audio_data.dsp_lib, "rarch_dsp_plugin_init"); -#endif - - if (!cb) - { - RARCH_ERR("Failed to find symbol \"rarch_dsp_plugin_init\" in DSP plugin.\n"); - goto error; - } - - cpu_features = rarch_get_cpu_features(); - g_extern.audio_data.dsp_plugin = cb(cpu_features); - - if (!g_extern.audio_data.dsp_plugin) - { - RARCH_ERR("Failed to get a valid DSP plugin.\n"); - goto error; - } - - if (g_extern.audio_data.dsp_plugin->api_version != RARCH_DSP_API_VERSION) - { - RARCH_ERR("DSP plugin API mismatch. RetroArch: %d, Plugin: %d\n", RARCH_DSP_API_VERSION, g_extern.audio_data.dsp_plugin->api_version); - goto error; - } - - RARCH_LOG("Loaded DSP plugin: \"%s\"\n", g_extern.audio_data.dsp_plugin->ident ? g_extern.audio_data.dsp_plugin->ident : "Unknown"); - - info.input_rate = g_settings.audio.in_rate; - - g_extern.audio_data.dsp_handle = g_extern.audio_data.dsp_plugin->init(&info); - if (!g_extern.audio_data.dsp_handle) - { - RARCH_ERR("Failed to init DSP plugin.\n"); - goto error; - } - - return; - -error: -#ifdef HAVE_DYLIB - if (g_extern.audio_data.dsp_lib) - dylib_close(g_extern.audio_data.dsp_lib); - g_extern.audio_data.dsp_lib = NULL; -#endif - g_extern.audio_data.dsp_plugin = NULL; + g_extern.audio_data.dsp = rarch_dsp_filter_new(g_settings.audio.dsp_plugin, g_settings.audio.in_rate); + if (!g_extern.audio_data.dsp) + RARCH_ERR("[DSP]: Failed to init DSP filter \"%s\".\n", g_settings.audio.dsp_plugin); } void rarch_deinit_dsp_filter(void) { - if (g_extern.audio_data.dsp_plugin && g_extern.audio_data.dsp_plugin->free) - g_extern.audio_data.dsp_plugin->free(g_extern.audio_data.dsp_handle); -#ifdef HAVE_DYLIB - if (g_extern.audio_data.dsp_lib) - dylib_close(g_extern.audio_data.dsp_lib); -#endif - g_extern.audio_data.dsp_handle = NULL; - g_extern.audio_data.dsp_plugin = NULL; + if (g_extern.audio_data.dsp) + rarch_dsp_filter_free(g_extern.audio_data.dsp); + g_extern.audio_data.dsp = NULL; } void init_audio(void) diff --git a/driver.h b/driver.h index d4e8cee1cc..96460eb3d2 100644 --- a/driver.h +++ b/driver.h @@ -96,7 +96,6 @@ enum // RetroArch specific bind IDs. RARCH_CHEAT_INDEX_MINUS, RARCH_CHEAT_TOGGLE, RARCH_SCREENSHOT, - RARCH_DSP_CONFIG, RARCH_MUTE, RARCH_NETPLAY_FLIP, RARCH_SLOWMOTION, diff --git a/frontend/menu/backend/menu_common_backend.c b/frontend/menu/backend/menu_common_backend.c index 93f4bc82a8..d8933e0136 100644 --- a/frontend/menu/backend/menu_common_backend.c +++ b/frontend/menu/backend/menu_common_backend.c @@ -1008,7 +1008,7 @@ static void menu_parse_and_resolve(void *data, unsigned menu_type) else if (menu_type == RGUI_SETTINGS_VIDEO_SOFTFILTER) exts = EXT_EXECUTABLES; else if (menu_type == RGUI_SETTINGS_AUDIO_DSP_FILTER) - exts = EXT_EXECUTABLES; + exts = "dsp"; else if (menu_type == RGUI_SETTINGS_OVERLAY_PRESET) exts = "cfg"; else if (menu_common_type_is(menu_type) == RGUI_FILE_DIRECTORY) @@ -2539,34 +2539,14 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action case RGUI_SETTINGS_AUDIO_DSP_FILTER: switch (action) { -#ifdef HAVE_FILTERS_BUILTIN - case RGUI_ACTION_LEFT: - if (g_settings.audio.filter_idx > 0) - g_settings.audio.filter_idx--; - break; - case RGUI_ACTION_RIGHT: - if ((g_settings.audio.filter_idx + 1) != dspfilter_get_last_idx()) - g_settings.audio.filter_idx++; - break; -#endif case RGUI_ACTION_OK: -#if defined(HAVE_FILTERS_BUILTIN) - rarch_deinit_dsp_filter(); - rarch_init_dsp_filter(); -#elif defined(HAVE_DYLIB) file_list_push(rgui->menu_stack, g_settings.audio.filter_dir, setting, rgui->selection_ptr); menu_clear_navigation(rgui); -#endif rgui->need_refresh = true; break; case RGUI_ACTION_START: -#if defined(HAVE_FILTERS_BUILTIN) - g_settings.audio.filter_idx = 0; -#elif defined(HAVE_DYLIB) - strlcpy(g_settings.audio.dsp_plugin, "", sizeof(g_settings.audio.dsp_plugin)); -#endif + *g_settings.audio.dsp_plugin = '\0'; rarch_deinit_dsp_filter(); - rarch_init_dsp_filter(); break; } break; @@ -2902,7 +2882,6 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action case RGUI_SETTINGS_BIND_CHEAT_INDEX_MINUS: case RGUI_SETTINGS_BIND_CHEAT_TOGGLE: case RGUI_SETTINGS_BIND_SCREENSHOT: - case RGUI_SETTINGS_BIND_DSP_CONFIG: case RGUI_SETTINGS_BIND_MUTE: case RGUI_SETTINGS_BIND_NETPLAY_FLIP: case RGUI_SETTINGS_BIND_SLOWMOTION: @@ -4082,10 +4061,7 @@ static void menu_common_setting_set_label(char *type_str, size_t type_str_size, } break; case RGUI_SETTINGS_AUDIO_DSP_FILTER: - { - const char *filter_name = rarch_dspfilter_get_name((void*)g_extern.audio_data.dsp_plugin); - strlcpy(type_str, filter_name ? filter_name : "N/A", type_str_size); - } + strlcpy(type_str, g_settings.audio.dsp_plugin, type_str_size); break; #ifdef HAVE_OVERLAY case RGUI_SETTINGS_OVERLAY_PRESET: @@ -4214,7 +4190,6 @@ static void menu_common_setting_set_label(char *type_str, size_t type_str_size, case RGUI_SETTINGS_BIND_CHEAT_INDEX_MINUS: case RGUI_SETTINGS_BIND_CHEAT_TOGGLE: case RGUI_SETTINGS_BIND_SCREENSHOT: - case RGUI_SETTINGS_BIND_DSP_CONFIG: case RGUI_SETTINGS_BIND_MUTE: case RGUI_SETTINGS_BIND_NETPLAY_FLIP: case RGUI_SETTINGS_BIND_SLOWMOTION: diff --git a/general.h b/general.h index a4798c3bd2..de52333cdc 100644 --- a/general.h +++ b/general.h @@ -29,7 +29,7 @@ #include "autosave.h" #include "dynamic.h" #include "cheats.h" -#include "audio/filters/rarch_dsp.h" +#include "audio/dsp_filter.h" #include "compat/strl.h" #include "performance.h" #include "core_options.h" @@ -239,9 +239,6 @@ struct settings char dsp_plugin[PATH_MAX]; char filter_dir[PATH_MAX]; -#ifdef HAVE_FILTERS_BUILTIN - unsigned filter_idx; -#endif bool rate_control; float rate_control_delta; @@ -496,11 +493,7 @@ struct global size_t rewind_ptr; size_t rewind_size; -#ifdef HAVE_DYLIB - dylib_t dsp_lib; -#endif - const struct dspfilter_implementation *dsp_plugin; - void *dsp_handle; + rarch_dsp_filter_t *dsp; bool rate_control; double orig_src_ratio; diff --git a/input/input_common.c b/input/input_common.c index 973077d8d9..5c0d243f4e 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -851,7 +851,6 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { DECLARE_META_BIND(2, cheat_index_minus, RARCH_CHEAT_INDEX_MINUS, "Cheat index -"), DECLARE_META_BIND(2, cheat_toggle, RARCH_CHEAT_TOGGLE, "Cheat toggle"), DECLARE_META_BIND(2, screenshot, RARCH_SCREENSHOT, "Take screenshot"), - DECLARE_META_BIND(2, dsp_config, RARCH_DSP_CONFIG, "DSP config"), DECLARE_META_BIND(2, audio_mute, RARCH_MUTE, "Audio mute toggle"), DECLARE_META_BIND(2, netplay_flip_players, RARCH_NETPLAY_FLIP, "Netplay flip players"), DECLARE_META_BIND(2, slowmotion, RARCH_SLOWMOTION, "Slow motion"), diff --git a/retroarch.c b/retroarch.c index 7256ead358..32f7101267 100644 --- a/retroarch.c +++ b/retroarch.c @@ -388,16 +388,15 @@ static bool audio_flush(const int16_t *data, size_t samples) g_extern.audio_data.volume_gain); RARCH_PERFORMANCE_STOP(audio_convert_s16); - rarch_dsp_output_t dsp_output = {0}; - rarch_dsp_input_t dsp_input = {0}; - dsp_input.samples = g_extern.audio_data.data; - dsp_input.frames = samples >> 1; + struct rarch_dsp_data dsp_data = {0}; + dsp_data.input = g_extern.audio_data.data; + dsp_data.input_frames = samples >> 1; - if (g_extern.audio_data.dsp_plugin) - g_extern.audio_data.dsp_plugin->process(g_extern.audio_data.dsp_handle, &dsp_output, &dsp_input); + if (g_extern.audio_data.dsp) + rarch_dsp_filter_process(g_extern.audio_data.dsp, &dsp_data); - src_data.data_in = dsp_output.samples ? dsp_output.samples : g_extern.audio_data.data; - src_data.input_frames = dsp_output.samples ? dsp_output.frames : (samples >> 1); + src_data.data_in = dsp_data.output ? dsp_data.output : g_extern.audio_data.data; + src_data.input_frames = dsp_data.output ? dsp_data.output_frames : (samples >> 1); src_data.data_out = g_extern.audio_data.outsamples; @@ -2575,19 +2574,6 @@ static void check_screenshot(void) } #endif -static void check_dsp_config(void) -{ - if (!g_extern.audio_data.dsp_plugin || !g_extern.audio_data.dsp_plugin->config) - return; - - static bool old_pressed; - bool pressed = input_key_pressed_func(RARCH_DSP_CONFIG); - if (pressed && !old_pressed) - g_extern.audio_data.dsp_plugin->config(g_extern.audio_data.dsp_handle); - - old_pressed = pressed; -} - static void check_mute(void) { if (!g_extern.audio_active) @@ -2765,7 +2751,6 @@ static void do_state_checks(void) check_cheats(); check_disk(); - check_dsp_config(); check_reset(); #ifdef HAVE_NETPLAY } @@ -3063,12 +3048,6 @@ bool rarch_main_iterate(void) { unsigned i; -#ifdef HAVE_DYLIB - // DSP plugin GUI events. - if (g_extern.audio_data.dsp_handle && g_extern.audio_data.dsp_plugin && g_extern.audio_data.dsp_plugin->events) - g_extern.audio_data.dsp_plugin->events(g_extern.audio_data.dsp_handle); -#endif - // SHUTDOWN on consoles should exit RetroArch completely. if (g_extern.system.shutdown) return false; diff --git a/settings.c b/settings.c index fe812b3ea7..6a691e813a 100644 --- a/settings.c +++ b/settings.c @@ -831,8 +831,8 @@ bool config_load_file(const char *path, bool set_defaults) * setting the filter later doesn't cause a problem meanwhile */ CONFIG_GET_INT(video.filter_idx, "filter_index"); #endif - CONFIG_GET_INT(audio.filter_idx, "audio_filter_index"); #endif + #ifdef RARCH_CONSOLE /* TODO - will be refactored later to make it more clean - it's more * important that it works for consoles right now */ @@ -1327,7 +1327,6 @@ bool config_save_file(const char *path) config_set_bool(conf, "rewind_enable", g_settings.rewind_enable); #ifdef HAVE_FILTERS_BUILTIN config_set_int(conf, "filter_index", g_settings.video.filter_idx); - config_set_int(conf, "audio_filter_index", g_settings.audio.filter_idx); #endif config_set_int(conf, "audio_latency", g_settings.audio.latency); config_set_bool(conf, "audio_sync", g_settings.audio.sync);