mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
(Audio) The latency floor is a setting
The eight-millisecond minimum was a constant in audio_driver.c, applied once before any driver saw the value - which is why it showed up identically on WASAPI, ASIO and WDM-KS, none of which was involved. The reasoning behind it, in its own comment, is about drivers mishandling zero rather than about hardware: the setting's range starts at zero, zero reached the drivers, and they each did something different with it. That argument is much weaker for the drivers that negotiate a period with the device directly, and those already floor themselves at whatever their hardware states. So it is audio_latency_floor now: advanced, one to sixteen milliseconds, eight by default, which is what it has always been. The constant stays as an absolute floor of one, because zero is the value the original trouble was about and "let the driver decide" is not something the interface can express. It is a frontend floor rather than a Windows one, so ALSA, CoreAudio and the rest are equally free of it. Every link of the chain was walked rather than assumed - field, binding, default, menu row, label enum, label string, menu listing, and the clamp that reads it - because a settings change that compiles while doing nothing is a thing I have already shipped once this week.
This commit is contained in:
1 parent
f5e186e555
commit
25b6bd1fbd
8 files changed
+52
-7
No files matched your search
+21
-7
@@ -129,8 +129,15 @@
|
||||
* once here before any driver sees it. The setting's range starts at
|
||||
* zero, and zero reached the drivers: some floored it themselves, each
|
||||
* at its own value, one refused to open, one fell back to a fixed
|
||||
* fifo. A driver keeps only a floor of its hardware's own. */
|
||||
#define AUDIO_LATENCY_MIN_MS 8
|
||||
* fifo. A driver keeps only a floor of its hardware's own.
|
||||
*
|
||||
* Eight is the default and was for a long time the only value. It is a
|
||||
* setting now - audio_latency_floor - because the reasoning above is
|
||||
* about drivers mishandling zero rather than about hardware, and an
|
||||
* exclusive-mode driver that negotiates its period with the device can
|
||||
* go below it where the device allows. Never below one: zero is the
|
||||
* value that caused the trouble this floor exists for. */
|
||||
#define AUDIO_LATENCY_MIN_MS 1
|
||||
|
||||
/* Region spacing inside the two scratch arenas, in elements: 64 bytes
|
||||
* for either type. Every region starts on a 64-byte boundary for the
|
||||
@@ -3128,12 +3135,19 @@ bool audio_driver_init_internal(void *settings_data, bool audio_cb_inited)
|
||||
convert_float_to_s16_init_simd();
|
||||
audio_driver_clamp_init_simd();
|
||||
|
||||
if (audio_latency < AUDIO_LATENCY_MIN_MS)
|
||||
{
|
||||
RARCH_WARN("[Audio] Latency setting of %u ms is below the %u ms minimum; using %u ms.\n",
|
||||
audio_latency, AUDIO_LATENCY_MIN_MS, AUDIO_LATENCY_MIN_MS);
|
||||
latency_floored = true;
|
||||
audio_latency = AUDIO_LATENCY_MIN_MS;
|
||||
unsigned floor_ms = settings->uints.audio_latency_floor;
|
||||
if (floor_ms < AUDIO_LATENCY_MIN_MS)
|
||||
floor_ms = AUDIO_LATENCY_MIN_MS;
|
||||
|
||||
if (audio_latency < floor_ms)
|
||||
{
|
||||
RARCH_WARN("[Audio] Latency setting of %u ms is below the %u ms"
|
||||
" floor; using %u ms.\n",
|
||||
audio_latency, floor_ms, floor_ms);
|
||||
latency_floored = true;
|
||||
audio_latency = floor_ms;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arena_int16 || !arena_float)
|
||||
|
||||
@@ -1315,6 +1315,15 @@
|
||||
#endif
|
||||
|
||||
/* Audio device (e.g. hw:0,0 or /dev/audio). If NULL, will use defaults. */
|
||||
/* The floor applied to the audio latency setting before any driver
|
||||
* sees it, in milliseconds. Eight is what it was fixed at, and the
|
||||
* reason it existed: zero used to reach the drivers and each handled
|
||||
* it differently. Lower it and an exclusive-mode driver - WASAPI,
|
||||
* ASIO, WDM-KS - will negotiate a shorter period with the device
|
||||
* where the device allows one; a driver that cannot goes no lower
|
||||
* than its own hardware floor either way. */
|
||||
#define DEFAULT_AUDIO_LATENCY_FLOOR 8
|
||||
|
||||
#define DEFAULT_AUDIO_DEVICE NULL
|
||||
|
||||
/* Desired audio latency in milliseconds. Might not be honored
|
||||
|
||||
@@ -3351,6 +3351,7 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
|
||||
SETTING_UINT("audio_out_rate", &settings->uints.audio_output_sample_rate, true, DEFAULT_OUTPUT_RATE, false);
|
||||
SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false);
|
||||
SETTING_UINT("audio_latency_floor", &settings->uints.audio_latency_floor, true, DEFAULT_AUDIO_LATENCY_FLOOR, false);
|
||||
|
||||
|
||||
#ifdef HAVE_MICROPHONE
|
||||
@@ -5567,6 +5568,7 @@ void config_set_defaults(void *data)
|
||||
g_defaults.settings_out_latency = DEFAULT_OUT_LATENCY;
|
||||
|
||||
settings->uints.audio_latency = g_defaults.settings_out_latency;
|
||||
settings->uints.audio_latency_floor = DEFAULT_AUDIO_LATENCY_FLOOR;
|
||||
|
||||
if (!g_defaults.settings_in_latency)
|
||||
g_defaults.settings_in_latency = DEFAULT_IN_LATENCY;
|
||||
|
||||
@@ -164,6 +164,13 @@ typedef struct settings
|
||||
unsigned audio_output_sample_rate;
|
||||
unsigned audio_output_layout;
|
||||
unsigned audio_latency;
|
||||
/* The floor applied to audio_latency before any driver sees it,
|
||||
* in milliseconds. Eight by default, which is what it was fixed
|
||||
* at; lower it and an exclusive-mode driver that can negotiate a
|
||||
* shorter period with the device will. Never zero - zero is the
|
||||
* value that reached the drivers before this floor existed, and
|
||||
* each did something different with it. */
|
||||
unsigned audio_latency_floor;
|
||||
unsigned audio_format_negotiation;
|
||||
|
||||
#ifdef HAVE_WASAPI
|
||||
|
||||
@@ -208,6 +208,10 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_AUDIO_LATENCY,
|
||||
MENU_ENUM_LABEL_AUDIO_LATENCY_STR
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_AUDIO_LATENCY_FLOOR,
|
||||
"audio_latency_floor"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_AUDIO_MUTE,
|
||||
MENU_ENUM_LABEL_AUDIO_MUTE_STR
|
||||
|
||||
@@ -9140,6 +9140,7 @@ unsigned menu_displaylist_build_list(
|
||||
{ MENU_ENUM_LABEL_AUDIO_DEVICE, PARSE_ONLY_STRING, false },
|
||||
{ MENU_ENUM_LABEL_AUDIO_OUTPUT_RATE, PARSE_ONLY_UINT, false },
|
||||
{ MENU_ENUM_LABEL_AUDIO_LATENCY, PARSE_ONLY_UINT, false },
|
||||
{ MENU_ENUM_LABEL_AUDIO_LATENCY_FLOOR, PARSE_ONLY_UINT, false },
|
||||
{ MENU_ENUM_LABEL_AUDIO_RESAMPLER_DRIVER, PARSE_ONLY_STRING_OPTIONS, false },
|
||||
};
|
||||
count += menu_displaylist_parse_settings_rows(list, settings,
|
||||
@@ -12075,6 +12076,7 @@ unsigned menu_displaylist_build_list(
|
||||
{MENU_ENUM_LABEL_RUN_AHEAD_HIDE_WARNINGS, PARSE_ONLY_BOOL, false },
|
||||
#endif
|
||||
{MENU_ENUM_LABEL_AUDIO_LATENCY, PARSE_ONLY_UINT, true },
|
||||
{MENU_ENUM_LABEL_AUDIO_LATENCY_FLOOR, PARSE_ONLY_UINT, false },
|
||||
#ifdef HAVE_MICROPHONE
|
||||
{MENU_ENUM_LABEL_MICROPHONE_LATENCY, PARSE_ONLY_UINT, true },
|
||||
#endif
|
||||
|
||||
@@ -20757,6 +20757,7 @@ enum msg_hash_enums
|
||||
MENU_LABEL(AUDIO_MIXER_VOLUME),
|
||||
MENU_LBL_H(AUDIO_RATE_CONTROL_DELTA),
|
||||
MENU_LABEL(AUDIO_LATENCY),
|
||||
MENU_LABEL(AUDIO_LATENCY_FLOOR),
|
||||
/* GENERATED REGION: resampler quality group enum rows (see settings/settings_def_audio_resampler_quality.h). */
|
||||
#define SETTINGS_DEF_ENUM_PASS
|
||||
#define SETTINGS_DEF_STRINGS_PASS
|
||||
|
||||
@@ -12,6 +12,12 @@ S_UINT_DF(audio_latency, AUDIO_LATENCY,
|
||||
SD_FLAG_LAKKA_ADVANCED, SDESC_RANGE_MINMAX, 0, 0, 512, 1, 0, setting_action_ok_uint, NULL, 0,
|
||||
"Audio Latency (ms)",
|
||||
"Desired audio latency in milliseconds. Might not be honored if the audio driver can't provide it.")
|
||||
S_UINT(audio_latency_floor, AUDIO_LATENCY_FLOOR,
|
||||
"audio_latency_floor",
|
||||
DEFAULT_AUDIO_LATENCY_FLOOR, SD_FLAG_ADVANCED, SDESC_RANGE_MINMAX, 0, 1, 16, 1, 0,
|
||||
setting_action_ok_uint, NULL,
|
||||
"Minimum Audio Latency (ms)",
|
||||
"The lowest audio latency RetroArch will ask a driver for. Eight milliseconds by default, which is where this was fixed for a long time: a setting of zero used to reach the drivers and they handled it inconsistently. Drivers that talk to the device directly - WASAPI in exclusive mode, ASIO, WDM-KS - can often negotiate a shorter period than that, so lowering this lets them. A driver that cannot go lower will not; it keeps its own hardware floor either way.")
|
||||
#ifdef HAVE_MICROPHONE
|
||||
S_UINT_DF(microphone_latency, MICROPHONE_LATENCY,
|
||||
"microphone_latency",
|
||||
|
||||
Reference in new issue
Block a user