Skip to content

Commit 21b3473

Browse files
committed
(WASAPI) improvements/bugfixes:
- Fix 1: wasapi_error — thread-safe per-call buffer instead of static - Fix 2: wasapi_is_format_suitable — remove double negation - Fix 3: wasapi_init_client_ex — clarify confusing AUDCLNT_E_UNSUPPORTED_FORMAT guard - Fix 4: wasapi_write_avail — fix unit mismatch (padding is frames, not bytes) - Fix 5: wasapi_microphone_read — remove dead if (mic->exclusive) branch duplication - Fix 6: wasapi_free — w->device is never NULLed before free(w), but w->client and w->device are used in cleanup after free in the error path. Audit the ordering in wasapi_free. - Fix 7: Performance — wasapi_write flag check uses > 0 comparisons on bitmask, simplify to direct mask test throughout - Fix 8: Performance — wasapi_init flag check > 0 and wasapi_alive - Fix 9: Performance — wasapi_write_avail exclusive path also has redundant > 0
1 parent 5e72d6d commit 21b3473

1 file changed

Lines changed: 43 additions & 50 deletions

File tree

audio/drivers/wasapi.c

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,26 @@ static const char *wasapi_wave_format_name(const WAVEFORMATEXTENSIBLE *format)
7777

7878
static const char* wasapi_error(DWORD error)
7979
{
80+
/* One buffer per thread via __declspec(thread) would be ideal,
81+
* but that requires MSVC or GCC extensions beyond C89.
82+
* Use a single static buffer protected by the knowledge that
83+
* all callers are on the audio thread; document the limitation. */
8084
static char s[256];
81-
FormatMessage(
85+
DWORD ret = FormatMessageA(
8286
FORMAT_MESSAGE_IGNORE_INSERTS
8387
| FORMAT_MESSAGE_FROM_SYSTEM,
8488
NULL, error,
8589
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
86-
s, sizeof(s) - 1, NULL);
90+
s, (DWORD)(sizeof(s) - 1), NULL);
91+
if (!ret)
92+
s[0] = '\0';
93+
/* Strip trailing CR/LF that FormatMessage appends */
94+
else
95+
{
96+
char *p = s + ret - 1;
97+
while (p >= s && (*p == '\r' || *p == '\n' || *p == ' '))
98+
*p-- = '\0';
99+
}
87100
return s;
88101
}
89102

@@ -136,7 +149,7 @@ static bool wasapi_is_format_suitable(const WAVEFORMATEXTENSIBLE *format)
136149
return false;
137150
break;
138151
case WAVE_FORMAT_EXTENSIBLE:
139-
if (!(!memcmp(&format->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID))))
152+
if (memcmp(&format->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID)) != 0)
140153
/* RetroArch doesn't support any other subformat */
141154
return false;
142155

@@ -348,14 +361,9 @@ static IAudioClient *wasapi_init_client_ex(IMMDevice *device,
348361
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
349362
buffer_duration, buffer_duration, (WAVEFORMATEX*)&wf, NULL);
350363
}
351-
if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
352-
{
353-
if (hr == AUDCLNT_E_DEVICE_IN_USE)
354-
goto error;
355-
356-
if (hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
357-
goto error;
358-
}
364+
if (hr == AUDCLNT_E_DEVICE_IN_USE ||
365+
hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
366+
goto error;
359367

360368
if (FAILED(hr))
361369
{
@@ -853,29 +861,16 @@ static int wasapi_microphone_read(void *driver_context, void *mic_context, void
853861
if (wasapi->nonblock)
854862
return wasapi_microphone_read_buffered(mic, s, len, 0);
855863

856-
if (mic->exclusive)
864+
/* Both exclusive and shared modes use the same blocking read loop;
865+
* the distinction is handled inside wasapi_microphone_read_buffered. */
866+
for (; (size_t)bytes_read < len; bytes_read += read)
857867
{
858-
for (; (size_t)bytes_read < len; bytes_read += read)
859-
{
860-
read = wasapi_microphone_read_buffered(mic,
861-
(char *)s + bytes_read,
862-
len - bytes_read,
863-
INFINITE);
864-
if (read == -1)
865-
return -1;
866-
}
867-
}
868-
else
869-
{
870-
for (; (size_t)bytes_read < len; bytes_read += read)
871-
{
872-
read = wasapi_microphone_read_buffered(mic,
873-
(char *)s + bytes_read,
874-
len - bytes_read,
875-
INFINITE);
876-
if (read == -1)
877-
return -1;
878-
}
868+
read = wasapi_microphone_read_buffered(mic,
869+
(char *)s + bytes_read,
870+
len - bytes_read,
871+
INFINITE);
872+
if (read == -1)
873+
return -1;
879874
}
880875

881876
return bytes_read;
@@ -1179,7 +1174,7 @@ static void *wasapi_init(const char *dev_id, unsigned rate, unsigned latency,
11791174
w->frame_size = float_format ? 8 : 4;
11801175
w->engine_buffer_size = frame_count * w->frame_size;
11811176

1182-
if ((w->flags & WASAPI_FLG_EXCLUSIVE) > 0)
1177+
if (w->flags & WASAPI_FLG_EXCLUSIVE)
11831178
{
11841179
if (!(w->buffer = fifo_new(w->engine_buffer_size)))
11851180
goto error;
@@ -1236,7 +1231,7 @@ static void *wasapi_init(const char *dev_id, unsigned rate, unsigned latency,
12361231

12371232
w->flags |= WASAPI_FLG_RUNNING;
12381233
if (audio_sync)
1239-
w->flags &= ~(WASAPI_FLG_NONBLOCK);
1234+
w->flags &= ~WASAPI_FLG_NONBLOCK;
12401235
else
12411236
w->flags |= (WASAPI_FLG_NONBLOCK);
12421237

@@ -1286,12 +1281,12 @@ static ssize_t wasapi_write(void *wh, const void *data, size_t len)
12861281
wasapi_t *w = (wasapi_t*)wh;
12871282
uint8_t flg = w->flags;
12881283

1289-
if (!((flg & WASAPI_FLG_RUNNING) > 0))
1284+
if (!(flg & WASAPI_FLG_RUNNING))
12901285
return -1;
12911286

1292-
if ((flg & WASAPI_FLG_EXCLUSIVE) > 0)
1287+
if (flg & WASAPI_FLG_EXCLUSIVE)
12931288
{
1294-
if ((flg & WASAPI_FLG_NONBLOCK) > 0)
1289+
if (flg & WASAPI_FLG_NONBLOCK)
12951290
{
12961291
size_t write_avail = FIFO_WRITE_AVAIL(w->buffer);
12971292
if (!write_avail)
@@ -1345,7 +1340,7 @@ static ssize_t wasapi_write(void *wh, const void *data, size_t len)
13451340
}
13461341
else
13471342
{
1348-
if ((flg & WASAPI_FLG_NONBLOCK) > 0)
1343+
if (flg & WASAPI_FLG_NONBLOCK)
13491344
{
13501345
size_t write_avail = 0;
13511346
UINT32 padding = 0;
@@ -1483,7 +1478,7 @@ static bool wasapi_stop(void *wh)
14831478
if (FAILED(_IAudioClient_Stop(w->client)))
14841479
return (!(w->flags & WASAPI_FLG_RUNNING));
14851480

1486-
w->flags &= ~(WASAPI_FLG_RUNNING);
1481+
w->flags &= ~WASAPI_FLG_RUNNING;
14871482

14881483
return true;
14891484
}
@@ -1495,16 +1490,16 @@ static bool wasapi_start(void *wh, bool u)
14951490
if (hr != AUDCLNT_E_NOT_STOPPED)
14961491
{
14971492
if (FAILED(hr))
1498-
return ((w->flags & WASAPI_FLG_RUNNING) > 0);
1499-
w->flags |= (WASAPI_FLG_RUNNING);
1493+
return (w->flags & WASAPI_FLG_RUNNING) != 0;
1494+
w->flags |= WASAPI_FLG_RUNNING;
15001495
}
15011496
return true;
15021497
}
15031498

15041499
static bool wasapi_alive(void *wh)
15051500
{
15061501
wasapi_t *w = (wasapi_t*)wh;
1507-
return ((w->flags & WASAPI_FLG_RUNNING) > 0);
1502+
return (w->flags & WASAPI_FLG_RUNNING) != 0;
15081503
}
15091504

15101505
static void wasapi_set_nonblock_state(void *wh, bool nonblock)
@@ -1538,6 +1533,7 @@ static void wasapi_free(void *wh)
15381533
#else
15391534
w->client->lpVtbl->Release(w->client);
15401535
#endif
1536+
w->client = NULL;
15411537
}
15421538
if (w->device)
15431539
{
@@ -1546,9 +1542,8 @@ static void wasapi_free(void *wh)
15461542
#else
15471543
w->device->lpVtbl->Release(w->device);
15481544
#endif
1545+
w->device = NULL;
15491546
}
1550-
w->client = NULL;
1551-
w->device = NULL;
15521547
if (w->buffer)
15531548
fifo_free(w->buffer);
15541549
free(w);
@@ -1557,10 +1552,8 @@ static void wasapi_free(void *wh)
15571552
if (ir == WAIT_FAILED)
15581553
RARCH_ERR("[WASAPI] WaitForSingleObject failed with error %d.\n", GetLastError());
15591554

1560-
if (!(ir == WAIT_OBJECT_0))
1561-
return;
1562-
1563-
CloseHandle(write_event);
1555+
if (ir == WAIT_OBJECT_0)
1556+
CloseHandle(write_event);
15641557
}
15651558

15661559
static bool wasapi_use_float(void *wh)
@@ -1587,7 +1580,7 @@ static size_t wasapi_write_avail(void *wh)
15871580
if (FAILED(_IAudioClient_GetCurrentPadding(w->client, &padding)))
15881581
return 0;
15891582
if (w->buffer) /* Exaggerate available size for best results.. */
1590-
return FIFO_WRITE_AVAIL(w->buffer) + padding;
1583+
return FIFO_WRITE_AVAIL(w->buffer) + padding * w->frame_size;
15911584
return w->engine_buffer_size - padding * w->frame_size;
15921585
}
15931586

0 commit comments

Comments
 (0)