Skip to content

Commit a24148e

Browse files
authored
Always use WASAPI's callback mode (#264)
* Hardcodes wasapi GUIDs when compiling as C * Uses the user requested buffer size on wasapi Windows appears to automatically adjust the timer period when you use a small buffer, meaning that using a fraction of a large buffer is unreliable unless you call timeBeginPeriod. Seems simpler to just request the desired size directly. I'll do some further investigations into this, if it seems like the right change to make I'll update the docs as well if needed. * Switches to event driven callbacks on wasapi * Removes some commented out code, moves class variable to local
1 parent 8ab3606 commit a24148e

2 files changed

Lines changed: 19 additions & 42 deletions

File tree

src/wasapi.c

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,9 +1281,10 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
12811281
CoTaskMemFree(mix_format);
12821282
mix_format = NULL;
12831283
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
1284+
flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
12841285
share_mode = AUDCLNT_SHAREMODE_SHARED;
12851286
periodicity = 0;
1286-
buffer_duration = to_reference_time(4.0);
1287+
buffer_duration = to_reference_time(outstream->software_latency);
12871288
}
12881289
to_wave_format_layout(&outstream->layout, &wave_format);
12891290
to_wave_format_format(outstream->format, &wave_format);
@@ -1313,6 +1314,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
13131314
CoTaskMemFree(mix_format);
13141315
mix_format = NULL;
13151316
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
1317+
flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
13161318
to_wave_format_layout(&outstream->layout, &wave_format);
13171319
to_wave_format_format(outstream->format, &wave_format);
13181320
complete_wave_format_data(&wave_format);
@@ -1353,10 +1355,8 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
13531355
}
13541356
outstream->software_latency = osw->buffer_frame_count / (double)outstream->sample_rate;
13551357

1356-
if (osw->is_raw) {
1357-
if (FAILED(hr = IAudioClient_SetEventHandle(osw->audio_client, osw->h_event))) {
1358-
return SoundIoErrorOpeningDevice;
1359-
}
1358+
if (FAILED(hr = IAudioClient_SetEventHandle(osw->audio_client, osw->h_event))) {
1359+
return SoundIoErrorOpeningDevice;
13601360
}
13611361

13621362
if (outstream->name) {
@@ -1408,34 +1408,22 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
14081408
outstream->error_callback(outstream, SoundIoErrorStreaming);
14091409
return;
14101410
}
1411-
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
1412-
if (osw->writable_frame_count <= 0) {
1411+
int writable_frame_count = osw->buffer_frame_count - frames_used;
1412+
if (writable_frame_count <= 0) {
14131413
outstream->error_callback(outstream, SoundIoErrorStreaming);
14141414
return;
14151415
}
14161416
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
1417-
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
1417+
outstream->write_callback(outstream, frame_count_min, writable_frame_count);
14181418

14191419
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
14201420
outstream->error_callback(outstream, SoundIoErrorStreaming);
14211421
return;
14221422
}
14231423

14241424
for (;;) {
1425-
if (FAILED(hr = IAudioClient_GetCurrentPadding(osw->audio_client, &frames_used))) {
1426-
outstream->error_callback(outstream, SoundIoErrorStreaming);
1427-
return;
1428-
}
1429-
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
1430-
double time_until_underrun = frames_used / (double)outstream->sample_rate;
1431-
double wait_time = time_until_underrun / 2.0;
1432-
soundio_os_mutex_lock(osw->mutex);
1433-
soundio_os_cond_timed_wait(osw->cond, osw->mutex, wait_time);
1434-
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag)) {
1435-
soundio_os_mutex_unlock(osw->mutex);
1425+
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag))
14361426
return;
1437-
}
1438-
soundio_os_mutex_unlock(osw->mutex);
14391427
bool reset_buffer = false;
14401428
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->clear_buffer_flag)) {
14411429
if (!osw->is_paused) {
@@ -1473,12 +1461,12 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
14731461
outstream->error_callback(outstream, SoundIoErrorStreaming);
14741462
return;
14751463
}
1476-
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
1477-
if (osw->writable_frame_count > 0) {
1464+
int writable_frame_count = osw->buffer_frame_count - frames_used;
1465+
if (writable_frame_count > 0) {
14781466
if (frames_used == 0 && !reset_buffer)
14791467
outstream->underflow_callback(outstream);
14801468
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
1481-
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
1469+
outstream->write_callback(outstream, frame_count_min, writable_frame_count);
14821470
}
14831471
}
14841472
}
@@ -1598,12 +1586,10 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
15981586
return SoundIoErrorNoMem;
15991587
}
16001588

1601-
if (osw->is_raw) {
1602-
osw->h_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1603-
if (!osw->h_event) {
1604-
outstream_destroy_wasapi(si, os);
1605-
return SoundIoErrorOpeningDevice;
1606-
}
1589+
osw->h_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1590+
if (!osw->h_event) {
1591+
outstream_destroy_wasapi(si, os);
1592+
return SoundIoErrorOpeningDevice;
16071593
}
16081594

16091595
SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag);
@@ -1633,13 +1619,7 @@ static int outstream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoOutSt
16331619

16341620
SOUNDIO_ATOMIC_STORE(osw->desired_pause_state, pause);
16351621
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->pause_resume_flag);
1636-
if (osw->h_event) {
1637-
SetEvent(osw->h_event);
1638-
} else {
1639-
soundio_os_mutex_lock(osw->mutex);
1640-
soundio_os_cond_signal(osw->cond, osw->mutex);
1641-
soundio_os_mutex_unlock(osw->mutex);
1642-
}
1622+
SetEvent(osw->h_event);
16431623

16441624
return 0;
16451625
}
@@ -1694,13 +1674,11 @@ static int outstream_end_write_wasapi(struct SoundIoPrivate *si, struct SoundIoO
16941674
static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
16951675
struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
16961676

1697-
if (osw->h_event) {
1677+
if (osw->is_raw) {
16981678
return SoundIoErrorIncompatibleDevice;
16991679
} else {
17001680
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->clear_buffer_flag);
1701-
soundio_os_mutex_lock(osw->mutex);
1702-
soundio_os_cond_signal(osw->cond, osw->mutex);
1703-
soundio_os_mutex_unlock(osw->mutex);
1681+
SetEvent(osw->h_event);
17041682
}
17051683

17061684
return 0;

src/wasapi.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ struct SoundIoOutStreamWasapi {
7373
struct SoundIoOsCond *start_cond;
7474
struct SoundIoAtomicFlag thread_exit_flag;
7575
bool is_raw;
76-
int writable_frame_count;
7776
UINT32 buffer_frame_count;
7877
int write_frame_count;
7978
HANDLE h_event;

0 commit comments

Comments
 (0)