Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WASAPI) Shared buffer refactor + cleanup #15929

Merged
merged 1 commit into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
299 changes: 134 additions & 165 deletions audio/common/wasapi.c

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions audio/common/wasapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
#include "../common/mmdevice_common_inline.h"
#include "boolean.h"

/* Get automatic buffer size from client buffer instead of device period */
#define USE_CLIENT_BUFFER
/* Shared buffer size replacement placeholders */
#define WASAPI_SH_BUFFER_AUDIO_LATENCY 0
#define WASAPI_SH_BUFFER_DEVICE_PERIOD 32
#define WASAPI_SH_BUFFER_CLIENT_BUFFER 64

const char *hresult_name(HRESULT hr);
const char* wasapi_error(DWORD error);
Expand Down
58 changes: 26 additions & 32 deletions audio/drivers/wasapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ typedef struct
IMMDevice *device;
IAudioClient *client;
IAudioRenderClient *renderer;
fifo_buffer_t *buffer; /* NULL in unbuffered shared mode */
size_t frame_size; /* 4 or 8 only */
fifo_buffer_t *buffer;
size_t engine_buffer_size;
unsigned char frame_size; /* 4 or 8 only */
bool exclusive;
bool nonblock;
bool running;
Expand All @@ -51,7 +51,7 @@ static void *wasapi_init(const char *dev_id, unsigned rate, unsigned latency,
settings_t *settings = config_get_ptr();
bool float_format = settings->bools.audio_wasapi_float_format;
bool exclusive_mode = settings->bools.audio_wasapi_exclusive_mode;
int sh_buffer_length = settings->ints.audio_wasapi_sh_buffer_length;
unsigned sh_buffer_length = settings->uints.audio_wasapi_sh_buffer_length;
wasapi_t *w = (wasapi_t*)calloc(1, sizeof(wasapi_t));

if (!w)
Expand All @@ -73,43 +73,39 @@ static void *wasapi_init(const char *dev_id, unsigned rate, unsigned latency,
if (FAILED(hr))
goto error;

w->frame_size = float_format ? 8 : 4;
w->engine_buffer_size = frame_count * w->frame_size;
w->frame_size = float_format ? 8 : 4;
w->engine_buffer_size = frame_count * w->frame_size;

if (w->exclusive)
{
w->buffer = fifo_new(w->engine_buffer_size);
if (!w->buffer)
goto error;

RARCH_LOG("[WASAPI]: Intermediate buffer length is %u frames (%.1fms).\n",
frame_count, (double)frame_count * 1000.0 / rate);
}
else if (sh_buffer_length)
else
{
if (sh_buffer_length < 0)
switch (sh_buffer_length)
{
#ifdef USE_CLIENT_BUFFER
sh_buffer_length = frame_count;
#else
hr = _IAudioClient_GetDevicePeriod(w->client, &dev_period, NULL);

if (FAILED(hr))
goto error;

sh_buffer_length = dev_period * rate / 10000000;
#endif
case WASAPI_SH_BUFFER_AUDIO_LATENCY:
case WASAPI_SH_BUFFER_CLIENT_BUFFER:
sh_buffer_length = frame_count;
break;
case WASAPI_SH_BUFFER_DEVICE_PERIOD:
hr = _IAudioClient_GetDevicePeriod(w->client, &dev_period, NULL);

if (FAILED(hr))
goto error;

sh_buffer_length = dev_period * rate / 10000000;
break;
default:
break;
}

w->buffer = fifo_new(sh_buffer_length * w->frame_size);
if (!w->buffer)
goto error;

RARCH_LOG("[WASAPI]: Intermediate buffer length is %u frames (%.1fms).\n",
sh_buffer_length, (double)sh_buffer_length * 1000.0 / rate);
}
else
RARCH_LOG("[WASAPI]: Intermediate buffer is off. \n");

w->write_event = CreateEventA(NULL, FALSE, FALSE, NULL);
if (!w->write_event)
Expand Down Expand Up @@ -203,7 +199,7 @@ static ssize_t wasapi_write_sh_buffer(wasapi_t *w, const void * data, size_t siz

if (!write_avail)
{
size_t read_avail = 0;
size_t read_avail = 0;
if (!(WaitForSingleObject(w->write_event, INFINITE) == WAIT_OBJECT_0))
return -1;

Expand Down Expand Up @@ -252,9 +248,9 @@ static ssize_t wasapi_write_sh(wasapi_t *w, const void * data, size_t size)

static ssize_t wasapi_write_sh_nonblock(wasapi_t *w, const void * data, size_t size)
{
ssize_t written = -1;
size_t write_avail = 0;
UINT32 padding = 0;
ssize_t written = -1;
size_t write_avail = 0;
UINT32 padding = 0;

if (w->buffer)
{
Expand Down Expand Up @@ -320,6 +316,7 @@ static ssize_t wasapi_write_ex(wasapi_t *w, const void * data, size_t size, DWOR
static ssize_t wasapi_write(void *wh, const void *data, size_t size)
{
size_t written = 0;
ssize_t ir = 0;
wasapi_t *w = (wasapi_t*)wh;

if (w->nonblock)
Expand All @@ -331,7 +328,6 @@ static ssize_t wasapi_write(void *wh, const void *data, size_t size)

if (w->exclusive)
{
ssize_t ir;
for (ir = -1; written < size; written += ir)
{
ir = wasapi_write_ex(w, (char*)data + written, size - written, INFINITE);
Expand All @@ -341,7 +337,6 @@ static ssize_t wasapi_write(void *wh, const void *data, size_t size)
}
else
{
ssize_t ir;
if (w->buffer)
{
for (ir = -1; written < size; written += ir)
Expand Down Expand Up @@ -426,7 +421,6 @@ static void wasapi_free(void *wh)
if (ir == WAIT_FAILED)
RARCH_ERR("[WASAPI]: WaitForSingleObject failed with error %d.\n", GetLastError());

/* If event isn't signaled log and leak */
if (!(ir == WAIT_OBJECT_0))
return;

Expand Down
2 changes: 1 addition & 1 deletion config.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,7 @@
#define DEFAULT_WASAPI_EXCLUSIVE_MODE false
#define DEFAULT_WASAPI_FLOAT_FORMAT false
/* Automatic shared mode buffer */
#define DEFAULT_WASAPI_SH_BUFFER_LENGTH -16
#define DEFAULT_WASAPI_SH_BUFFER_LENGTH 0
#endif

/* Automatically mute audio when fast forward
Expand Down
19 changes: 15 additions & 4 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -1783,7 +1783,6 @@ static struct config_bool_setting *populate_settings_bool(

#ifdef HAVE_MICROPHONE
SETTING_BOOL("microphone_enable", &settings->bools.microphone_enable, true, DEFAULT_MICROPHONE_ENABLE, false);

#ifdef HAVE_WASAPI
SETTING_BOOL("microphone_wasapi_exclusive_mode", &settings->bools.microphone_wasapi_exclusive_mode, true, DEFAULT_WASAPI_EXCLUSIVE_MODE, false);
SETTING_BOOL("microphone_wasapi_float_format", &settings->bools.microphone_wasapi_float_format, true, DEFAULT_WASAPI_FLOAT_FORMAT, false);
Expand Down Expand Up @@ -2335,6 +2334,11 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, DEFAULT_AUDIO_RESAMPLER_QUALITY_LEVEL, false);
SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false);
SETTING_UINT("midi_volume", &settings->uints.midi_volume, true, DEFAULT_MIDI_VOLUME, false);

#ifdef HAVE_WASAPI
SETTING_UINT("audio_wasapi_sh_buffer_length", &settings->uints.audio_wasapi_sh_buffer_length, true, DEFAULT_WASAPI_SH_BUFFER_LENGTH, false);
#endif

#ifdef HAVE_MICROPHONE
SETTING_UINT("microphone_latency", &settings->uints.microphone_latency, false, 0 /* TODO */, false);
SETTING_UINT("microphone_resampler_quality", &settings->uints.microphone_resampler_quality, true, DEFAULT_AUDIO_RESAMPLER_QUALITY_LEVEL, false);
Expand Down Expand Up @@ -2549,9 +2553,6 @@ static struct config_int_setting *populate_settings_int(
SETTING_INT("menu_xmb_title_margin_horizontal_offset", &settings->ints.menu_xmb_title_margin_horizontal_offset, true, DEFAULT_XMB_TITLE_MARGIN_HORIZONTAL_OFFSET, false);
#endif

#ifdef HAVE_WASAPI
SETTING_INT("audio_wasapi_sh_buffer_length", &settings->ints.audio_wasapi_sh_buffer_length, true, DEFAULT_WASAPI_SH_BUFFER_LENGTH, false);
#endif
SETTING_INT("crt_switch_center_adjust", &settings->ints.crt_switch_center_adjust, false, DEFAULT_CRT_SWITCH_CENTER_ADJUST, false);
SETTING_INT("crt_switch_porch_adjust", &settings->ints.crt_switch_porch_adjust, false, DEFAULT_CRT_SWITCH_PORCH_ADJUST, false);
#ifdef HAVE_WINDOW_OFFSET
Expand Down Expand Up @@ -3770,6 +3771,16 @@ static bool config_load_file(global_t *global,
audio_set_float(AUDIO_ACTION_MIXER_VOLUME_GAIN, settings->floats.audio_mixer_volume);
#endif

#ifdef HAVE_WASAPI
{
/* Migrate from old deprecated negative value */
int wasapi_sh_buffer_length = settings->uints.audio_wasapi_sh_buffer_length;

if (wasapi_sh_buffer_length < 0)
settings->uints.audio_wasapi_sh_buffer_length = 0;
}
#endif

/* MIDI fallback for old OFF-string */
if (string_is_equal(settings->arrays.midi_input, "Off"))
configuration_set_string(settings,
Expand Down
16 changes: 12 additions & 4 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ typedef struct settings
int location_update_interval_distance;
int state_slot;
int replay_slot;
int audio_wasapi_sh_buffer_length;
int crt_switch_center_adjust;
int crt_switch_porch_adjust;
#ifdef HAVE_VULKAN
Expand Down Expand Up @@ -161,12 +160,18 @@ typedef struct settings
unsigned audio_block_frames;
unsigned audio_latency;

#ifdef HAVE_WASAPI
unsigned audio_wasapi_sh_buffer_length;
#endif

#ifdef HAVE_MICROPHONE
unsigned microphone_sample_rate;
unsigned microphone_block_frames;
unsigned microphone_latency;
unsigned microphone_wasapi_sh_buffer_length;
unsigned microphone_resampler_quality;
#ifdef HAVE_WASAPI
unsigned microphone_wasapi_sh_buffer_length;
#endif
#endif

unsigned fps_update_interval;
Expand Down Expand Up @@ -623,11 +628,14 @@ typedef struct settings
bool audio_enable_menu_scroll;
bool audio_sync;
bool audio_rate_control;
bool audio_wasapi_exclusive_mode;
bool audio_wasapi_float_format;
bool audio_fastforward_mute;
bool audio_fastforward_speedup;

#ifdef HAVE_WASAPI
bool audio_wasapi_exclusive_mode;
bool audio_wasapi_float_format;
#endif

#ifdef HAVE_MICROPHONE
/* Microphone */
bool microphone_enable;
Expand Down
6 changes: 5 additions & 1 deletion menu/menu_displaylist.c
Original file line number Diff line number Diff line change
Expand Up @@ -7184,6 +7184,7 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_AUDIO_BLOCK_FRAMES,
PARSE_ONLY_UINT, false) == 0)
count++;
#ifdef HAVE_WASAPI
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_AUDIO_WASAPI_EXCLUSIVE_MODE,
PARSE_ONLY_BOOL, false) == 0)
Expand All @@ -7194,8 +7195,9 @@ unsigned menu_displaylist_build_list(
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_AUDIO_WASAPI_SH_BUFFER_LENGTH,
PARSE_ONLY_INT, false) == 0)
PARSE_ONLY_UINT, false) == 0)
count++;
#endif
}
break;
#ifdef HAVE_MICROPHONE
Expand Down Expand Up @@ -7235,6 +7237,7 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_MICROPHONE_BLOCK_FRAMES,
PARSE_ONLY_UINT, false) == 0)
count++;
#ifdef HAVE_WASAPI
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_MICROPHONE_WASAPI_EXCLUSIVE_MODE,
PARSE_ONLY_BOOL, false) == 0)
Expand All @@ -7247,6 +7250,7 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_MICROPHONE_WASAPI_SH_BUFFER_LENGTH,
PARSE_ONLY_UINT, false) == 0)
count++;
#endif
break;
#endif
case DISPLAYLIST_AUDIO_SYNCHRONIZATION_SETTINGS_LIST:
Expand Down
Loading
Loading