mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 13:20:30 +00:00
Begin adding rate control.
This commit is contained in:
parent
69a5faaaab
commit
438ac4ca4b
@ -181,6 +181,24 @@ static void rs_free(void *data)
|
||||
free(rsd);
|
||||
}
|
||||
|
||||
static size_t rs_write_avail(void *data)
|
||||
{
|
||||
rsd_t *rsd = data;
|
||||
|
||||
if (rsd->has_error)
|
||||
return 0;
|
||||
rsd_callback_lock(rsd->rd);
|
||||
size_t val = fifo_write_avail(rsd->buffer);
|
||||
rsd_callback_unlock(rsd->rd);
|
||||
return val;
|
||||
}
|
||||
|
||||
static size_t rs_buffer_size(void *data)
|
||||
{
|
||||
(void)data;
|
||||
return 1024 * 4;
|
||||
}
|
||||
|
||||
const audio_driver_t audio_rsound = {
|
||||
rs_init,
|
||||
rs_write,
|
||||
@ -189,6 +207,8 @@ const audio_driver_t audio_rsound = {
|
||||
rs_set_nonblock_state,
|
||||
rs_free,
|
||||
NULL,
|
||||
"rsound"
|
||||
"rsound",
|
||||
rs_write_avail,
|
||||
rs_buffer_size,
|
||||
};
|
||||
|
||||
|
10
config.def.h
10
config.def.h
@ -231,6 +231,16 @@ static const int out_latency = 64;
|
||||
// Will sync audio. (recommended)
|
||||
static const bool audio_sync = true;
|
||||
|
||||
// Experimental rate control
|
||||
static const bool rate_control = false;
|
||||
|
||||
// Rate control delta. Defines how much rate_control is allowed to adjust input rate.
|
||||
static const float rate_control_delta = 0.005;
|
||||
|
||||
//////////////
|
||||
// Misc
|
||||
//////////////
|
||||
|
||||
// Enables use of rewind. This will incur some memory footprint depending on the save state buffer.
|
||||
// This rewind only works when using bSNES core atm.
|
||||
static const bool rewind_enable = false;
|
||||
|
14
driver.c
14
driver.c
@ -335,9 +335,21 @@ void init_audio(void)
|
||||
ssnes_assert(g_settings.audio.out_rate < g_settings.audio.in_rate * AUDIO_MAX_RATIO);
|
||||
ssnes_assert(g_extern.audio_data.outsamples = (float*)malloc(max_bufsamples * sizeof(float) * AUDIO_MAX_RATIO));
|
||||
|
||||
g_extern.audio_data.src_ratio =
|
||||
g_extern.audio_data.orig_src_ratio =
|
||||
g_extern.audio_data.src_ratio =
|
||||
(double)g_settings.audio.out_rate / g_settings.audio.in_rate;
|
||||
|
||||
if (g_settings.audio.rate_control)
|
||||
{
|
||||
if (driver.audio->buffer_size && driver.audio->write_avail)
|
||||
{
|
||||
g_extern.audio_data.driver_buffer_size = driver.audio->buffer_size(driver.audio_data);
|
||||
g_extern.audio_data.rate_control = true;
|
||||
}
|
||||
else
|
||||
SSNES_WARN("Audio rate control was desired, but driver does not support needed features.\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
init_dsp_plugin();
|
||||
#endif
|
||||
|
3
driver.h
3
driver.h
@ -98,6 +98,9 @@ typedef struct audio_driver
|
||||
void (*free)(void *data);
|
||||
bool (*use_float)(void *data); // Defines if driver will take standard floating point samples, or int16_t samples.
|
||||
const char *ident;
|
||||
|
||||
size_t (*write_avail)(void *data); // Optional
|
||||
size_t (*buffer_size)(void *data); // Optional
|
||||
} audio_driver_t;
|
||||
|
||||
#define AXIS_NEG(x) (((uint32_t)(x) << 16) | UINT16_C(0xFFFF))
|
||||
|
@ -138,6 +138,9 @@ struct settings
|
||||
|
||||
char dsp_plugin[PATH_MAX];
|
||||
char external_driver[PATH_MAX];
|
||||
|
||||
bool rate_control;
|
||||
float rate_control_delta;
|
||||
} audio;
|
||||
|
||||
struct
|
||||
@ -299,6 +302,10 @@ struct global
|
||||
dylib_t dsp_lib;
|
||||
const ssnes_dsp_plugin_t *dsp_plugin;
|
||||
void *dsp_handle;
|
||||
|
||||
bool rate_control;
|
||||
double orig_src_ratio;
|
||||
size_t driver_buffer_size;
|
||||
} audio_data;
|
||||
|
||||
struct
|
||||
|
@ -195,6 +195,8 @@ void config_set_defaults(void)
|
||||
strlcpy(g_settings.audio.device, audio_device, sizeof(g_settings.audio.device));
|
||||
g_settings.audio.latency = out_latency;
|
||||
g_settings.audio.sync = audio_sync;
|
||||
g_settings.audio.rate_control = rate_control;
|
||||
g_settings.audio.rate_control_delta = rate_control_delta;
|
||||
|
||||
g_settings.rewind_enable = rewind_enable;
|
||||
g_settings.rewind_buffer_size = rewind_buffer_size;
|
||||
@ -429,6 +431,8 @@ bool config_load_file(const char *path)
|
||||
CONFIG_GET_STRING(audio.device, "audio_device");
|
||||
CONFIG_GET_INT(audio.latency, "audio_latency");
|
||||
CONFIG_GET_BOOL(audio.sync, "audio_sync");
|
||||
CONFIG_GET_BOOL(audio.rate_control, "audio_rate_control");
|
||||
CONFIG_GET_FLOAT(audio.rate_control_delta, "audio_rate_control_delta");
|
||||
|
||||
CONFIG_GET_STRING(video.driver, "video_driver");
|
||||
CONFIG_GET_STRING(audio.driver, "audio_driver");
|
||||
|
22
ssnes.c
22
ssnes.c
@ -246,6 +246,24 @@ void ssnes_render_cached_frame(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void readjust_audio_input_rate(void)
|
||||
{
|
||||
int avail = driver.audio->write_avail(driver.audio_data);
|
||||
//fprintf(stderr, "Audio buffer is %u%% full\n",
|
||||
// (unsigned)(100 - (avail * 100) / g_extern.audio_data.driver_buffer_size));
|
||||
|
||||
int half_size = g_extern.audio_data.driver_buffer_size / 2;
|
||||
int delta_mid = avail - half_size;
|
||||
double direction = (double)delta_mid / half_size;
|
||||
|
||||
double adjust = 1.0 + g_settings.audio.rate_control_delta * direction;
|
||||
|
||||
g_extern.audio_data.src_ratio = g_extern.audio_data.orig_src_ratio * adjust;
|
||||
|
||||
//fprintf(stderr, "New rate: %lf, Orig rate: %lf\n",
|
||||
// g_extern.audio_data.src_ratio, g_extern.audio_data.orig_src_ratio);
|
||||
}
|
||||
|
||||
static bool audio_flush(const int16_t *data, size_t samples)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
@ -284,6 +302,10 @@ static bool audio_flush(const int16_t *data, size_t samples)
|
||||
src_data.data_in = dsp_output.samples ? dsp_output.samples : g_extern.audio_data.data;
|
||||
src_data.data_out = g_extern.audio_data.outsamples;
|
||||
src_data.input_frames = dsp_output.samples ? dsp_output.frames : (samples / 2);
|
||||
|
||||
if (g_extern.audio_data.rate_control)
|
||||
readjust_audio_input_rate();
|
||||
|
||||
src_data.ratio = g_extern.audio_data.src_ratio;
|
||||
|
||||
hermite_process(g_extern.audio_data.source, &src_data);
|
||||
|
@ -146,6 +146,12 @@
|
||||
# Desired audio latency in milliseconds. Might not be honored if driver can't provide given latency.
|
||||
# audio_latency = 64
|
||||
|
||||
# Enable experimental audio rate control.
|
||||
# audio_rate_control = false
|
||||
|
||||
# Controls audio rate control delta. Defines how much input rate can be adjusted dynamically.
|
||||
# Input rate = in_rate * (1.0 +/- audio_rate_control_delta)
|
||||
# audio_rate_control_delta = 0.005
|
||||
|
||||
#### Input
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user