mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
Add API extension for overriding frontend audio latency
This commit is contained in:
parent
e195aa3b3d
commit
af6c2d6969
@ -1344,6 +1344,36 @@ enum retro_mod
|
||||
* in the frontend.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63
|
||||
/* const unsigned * --
|
||||
* Sets minimum frontend audio latency in milliseconds.
|
||||
* Resultant audio latency may be larger than set value,
|
||||
* or smaller if a hardware limit is encountered. A frontend
|
||||
* is expected to honour requests up to 512 ms.
|
||||
*
|
||||
* - If value is less than current frontend
|
||||
* audio latency, callback has no effect
|
||||
* - If value is zero, default frontend audio
|
||||
* latency is set
|
||||
*
|
||||
* May be used by a core to increase audio latency and
|
||||
* therefore decrease the probability of buffer under-runs
|
||||
* (crackling) when performing 'intensive' operations.
|
||||
* A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK
|
||||
* to implement audio-buffer-based frame skipping may achieve
|
||||
* optimal results by setting the audio latency to a 'high'
|
||||
* (typically 6x or 8x) integer multiple of the expected
|
||||
* frame time.
|
||||
*
|
||||
* WARNING: This can only be called from within retro_run().
|
||||
* Calling this can require a full reinitialization of audio
|
||||
* drivers in the frontend, so it is important to call it very
|
||||
* sparingly, and usually only with the users explicit consent.
|
||||
* An eventual driver reinitialize will happen so that audio
|
||||
* callbacks happening after this call within the same retro_run()
|
||||
* call will target the newly initialized driver.
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
|
88
retroarch.c
88
retroarch.c
@ -2260,6 +2260,7 @@ struct rarch_state
|
||||
#endif
|
||||
unsigned runloop_pending_windowed_scale;
|
||||
unsigned runloop_max_frames;
|
||||
unsigned runloop_audio_latency;
|
||||
unsigned fastforward_after_frames;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
@ -15884,6 +15885,13 @@ static void retroarch_frame_time_free(struct rarch_state *p_rarch)
|
||||
p_rarch->runloop_max_frames = 0;
|
||||
}
|
||||
|
||||
static void retroarch_audio_buffer_status_free(struct rarch_state *p_rarch)
|
||||
{
|
||||
memset(&p_rarch->runloop_audio_buffer_status, 0,
|
||||
sizeof(struct retro_audio_buffer_status_callback));
|
||||
p_rarch->runloop_audio_latency = 0;
|
||||
}
|
||||
|
||||
static void retroarch_system_info_free(struct rarch_state *p_rarch)
|
||||
{
|
||||
rarch_system_info_t *sys_info = &p_rarch->runloop_system;
|
||||
@ -19907,6 +19915,74 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY:
|
||||
{
|
||||
unsigned audio_latency_default = settings->uints.audio_latency;
|
||||
unsigned audio_latency_current =
|
||||
(p_rarch->runloop_audio_latency > audio_latency_default) ?
|
||||
p_rarch->runloop_audio_latency : audio_latency_default;
|
||||
unsigned audio_latency_new;
|
||||
|
||||
RARCH_LOG("[Environ]: RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY.\n");
|
||||
|
||||
/* Sanitise input latency value */
|
||||
p_rarch->runloop_audio_latency = 0;
|
||||
if (data)
|
||||
p_rarch->runloop_audio_latency = *(const unsigned*)data;
|
||||
if (p_rarch->runloop_audio_latency > 512)
|
||||
{
|
||||
RARCH_WARN("[Environ]: Requested audio latency of %u ms - limiting to maximum of 512 ms.\n",
|
||||
p_rarch->runloop_audio_latency);
|
||||
p_rarch->runloop_audio_latency = 512;
|
||||
}
|
||||
|
||||
/* Determine new set-point latency value */
|
||||
if (p_rarch->runloop_audio_latency >= audio_latency_default)
|
||||
audio_latency_new = p_rarch->runloop_audio_latency;
|
||||
else
|
||||
{
|
||||
if (p_rarch->runloop_audio_latency != 0)
|
||||
RARCH_WARN("[Environ]: Requested audio latency of %u ms is less than frontend default of %u ms."
|
||||
" Using frontend default...\n",
|
||||
p_rarch->runloop_audio_latency, audio_latency_default);
|
||||
|
||||
audio_latency_new = audio_latency_default;
|
||||
}
|
||||
|
||||
/* Check whether audio driver requires reinitialisation
|
||||
* (Identical to RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO,
|
||||
* without video driver initialisation) */
|
||||
if (audio_latency_new != audio_latency_current)
|
||||
{
|
||||
bool video_fullscreen = settings->bools.video_fullscreen;
|
||||
int reinit_flags = DRIVERS_CMD_ALL &
|
||||
~(DRIVER_VIDEO_MASK | DRIVER_INPUT_MASK | DRIVER_MENU_MASK);
|
||||
|
||||
RARCH_LOG("[Environ]: Setting audio latency to %u ms.\n", audio_latency_new);
|
||||
|
||||
command_event(CMD_EVENT_REINIT, &reinit_flags);
|
||||
video_driver_set_aspect_ratio();
|
||||
|
||||
/* Cannot continue recording with different parameters.
|
||||
* Take the easiest route out and just restart the recording. */
|
||||
if (p_rarch->recording_data)
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
msg_hash_to_str(MSG_RESTARTING_RECORDING_DUE_TO_DRIVER_REINIT),
|
||||
2, 180, false,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
command_event(CMD_EVENT_RECORD_DEINIT, NULL);
|
||||
command_event(CMD_EVENT_RECORD_INIT, NULL);
|
||||
}
|
||||
|
||||
/* Hide mouse cursor in fullscreen mode */
|
||||
if (video_fullscreen)
|
||||
video_driver_hide_mouse();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE:
|
||||
{
|
||||
struct retro_rumble_interface *iface =
|
||||
@ -20896,8 +20972,7 @@ static void uninit_libretro_symbols(
|
||||
retroarch_deinit_core_options(p_rarch);
|
||||
retroarch_system_info_free(p_rarch);
|
||||
retroarch_frame_time_free(p_rarch);
|
||||
memset(&p_rarch->runloop_audio_buffer_status, 0,
|
||||
sizeof(struct retro_audio_buffer_status_callback));
|
||||
retroarch_audio_buffer_status_free(p_rarch);
|
||||
p_rarch->camera_driver_active = false;
|
||||
p_rarch->location_driver_active = false;
|
||||
|
||||
@ -30047,6 +30122,8 @@ static bool audio_driver_init_internal(
|
||||
bool audio_sync = settings->bools.audio_sync;
|
||||
bool audio_rate_control = settings->bools.audio_rate_control;
|
||||
float slowmotion_ratio = settings->floats.slowmotion_ratio;
|
||||
unsigned audio_latency = (p_rarch->runloop_audio_latency > settings->uints.audio_latency) ?
|
||||
p_rarch->runloop_audio_latency : settings->uints.audio_latency;
|
||||
#ifdef HAVE_REWIND
|
||||
int16_t *rewind_buf = NULL;
|
||||
#endif
|
||||
@ -30107,7 +30184,7 @@ static bool audio_driver_init_internal(
|
||||
*settings->arrays.audio_device
|
||||
? settings->arrays.audio_device : NULL,
|
||||
settings->uints.audio_out_rate, &new_rate,
|
||||
settings->uints.audio_latency,
|
||||
audio_latency,
|
||||
settings->uints.audio_block_frames,
|
||||
p_rarch->current_audio))
|
||||
{
|
||||
@ -30122,7 +30199,7 @@ static bool audio_driver_init_internal(
|
||||
p_rarch->current_audio->init(*settings->arrays.audio_device ?
|
||||
settings->arrays.audio_device : NULL,
|
||||
settings->uints.audio_out_rate,
|
||||
settings->uints.audio_latency,
|
||||
audio_latency,
|
||||
settings->uints.audio_block_frames,
|
||||
&new_rate);
|
||||
}
|
||||
@ -38067,8 +38144,7 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
|
||||
#endif
|
||||
p_rarch->runloop_autosave = false;
|
||||
retroarch_frame_time_free(p_rarch);
|
||||
memset(&p_rarch->runloop_audio_buffer_status, 0,
|
||||
sizeof(struct retro_audio_buffer_status_callback));
|
||||
retroarch_audio_buffer_status_free(p_rarch);
|
||||
break;
|
||||
case RARCH_CTL_IS_IDLE:
|
||||
return p_rarch->runloop_idle;
|
||||
|
Loading…
Reference in New Issue
Block a user