mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-23 00:55:29 +00:00
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
This commit is contained in:
parent
8ab3606912
commit
a24148e15f
60
src/wasapi.c
60
src/wasapi.c
|
@ -1281,9 +1281,10 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
||||||
CoTaskMemFree(mix_format);
|
CoTaskMemFree(mix_format);
|
||||||
mix_format = NULL;
|
mix_format = NULL;
|
||||||
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
|
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
|
||||||
|
flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||||
share_mode = AUDCLNT_SHAREMODE_SHARED;
|
share_mode = AUDCLNT_SHAREMODE_SHARED;
|
||||||
periodicity = 0;
|
periodicity = 0;
|
||||||
buffer_duration = to_reference_time(4.0);
|
buffer_duration = to_reference_time(outstream->software_latency);
|
||||||
}
|
}
|
||||||
to_wave_format_layout(&outstream->layout, &wave_format);
|
to_wave_format_layout(&outstream->layout, &wave_format);
|
||||||
to_wave_format_format(outstream->format, &wave_format);
|
to_wave_format_format(outstream->format, &wave_format);
|
||||||
|
@ -1313,6 +1314,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
||||||
CoTaskMemFree(mix_format);
|
CoTaskMemFree(mix_format);
|
||||||
mix_format = NULL;
|
mix_format = NULL;
|
||||||
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
|
flags = osw->need_resample ? AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY : 0;
|
||||||
|
flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||||
to_wave_format_layout(&outstream->layout, &wave_format);
|
to_wave_format_layout(&outstream->layout, &wave_format);
|
||||||
to_wave_format_format(outstream->format, &wave_format);
|
to_wave_format_format(outstream->format, &wave_format);
|
||||||
complete_wave_format_data(&wave_format);
|
complete_wave_format_data(&wave_format);
|
||||||
|
@ -1353,10 +1355,8 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
||||||
}
|
}
|
||||||
outstream->software_latency = osw->buffer_frame_count / (double)outstream->sample_rate;
|
outstream->software_latency = osw->buffer_frame_count / (double)outstream->sample_rate;
|
||||||
|
|
||||||
if (osw->is_raw) {
|
if (FAILED(hr = IAudioClient_SetEventHandle(osw->audio_client, osw->h_event))) {
|
||||||
if (FAILED(hr = IAudioClient_SetEventHandle(osw->audio_client, osw->h_event))) {
|
return SoundIoErrorOpeningDevice;
|
||||||
return SoundIoErrorOpeningDevice;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outstream->name) {
|
if (outstream->name) {
|
||||||
|
@ -1408,13 +1408,13 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
|
||||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
|
int writable_frame_count = osw->buffer_frame_count - frames_used;
|
||||||
if (osw->writable_frame_count <= 0) {
|
if (writable_frame_count <= 0) {
|
||||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||||
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
|
outstream->write_callback(outstream, frame_count_min, writable_frame_count);
|
||||||
|
|
||||||
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
|
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
|
||||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||||
|
@ -1422,20 +1422,8 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (FAILED(hr = IAudioClient_GetCurrentPadding(osw->audio_client, &frames_used))) {
|
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag))
|
||||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
|
|
||||||
double time_until_underrun = frames_used / (double)outstream->sample_rate;
|
|
||||||
double wait_time = time_until_underrun / 2.0;
|
|
||||||
soundio_os_mutex_lock(osw->mutex);
|
|
||||||
soundio_os_cond_timed_wait(osw->cond, osw->mutex, wait_time);
|
|
||||||
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag)) {
|
|
||||||
soundio_os_mutex_unlock(osw->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
soundio_os_mutex_unlock(osw->mutex);
|
|
||||||
bool reset_buffer = false;
|
bool reset_buffer = false;
|
||||||
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->clear_buffer_flag)) {
|
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->clear_buffer_flag)) {
|
||||||
if (!osw->is_paused) {
|
if (!osw->is_paused) {
|
||||||
|
@ -1473,12 +1461,12 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
|
||||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
|
int writable_frame_count = osw->buffer_frame_count - frames_used;
|
||||||
if (osw->writable_frame_count > 0) {
|
if (writable_frame_count > 0) {
|
||||||
if (frames_used == 0 && !reset_buffer)
|
if (frames_used == 0 && !reset_buffer)
|
||||||
outstream->underflow_callback(outstream);
|
outstream->underflow_callback(outstream);
|
||||||
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||||
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
|
outstream->write_callback(outstream, frame_count_min, writable_frame_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1598,12 +1586,10 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (osw->is_raw) {
|
osw->h_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
osw->h_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
if (!osw->h_event) {
|
||||||
if (!osw->h_event) {
|
outstream_destroy_wasapi(si, os);
|
||||||
outstream_destroy_wasapi(si, os);
|
return SoundIoErrorOpeningDevice;
|
||||||
return SoundIoErrorOpeningDevice;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag);
|
SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag);
|
||||||
|
@ -1633,13 +1619,7 @@ static int outstream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoOutSt
|
||||||
|
|
||||||
SOUNDIO_ATOMIC_STORE(osw->desired_pause_state, pause);
|
SOUNDIO_ATOMIC_STORE(osw->desired_pause_state, pause);
|
||||||
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->pause_resume_flag);
|
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->pause_resume_flag);
|
||||||
if (osw->h_event) {
|
SetEvent(osw->h_event);
|
||||||
SetEvent(osw->h_event);
|
|
||||||
} else {
|
|
||||||
soundio_os_mutex_lock(osw->mutex);
|
|
||||||
soundio_os_cond_signal(osw->cond, osw->mutex);
|
|
||||||
soundio_os_mutex_unlock(osw->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1694,13 +1674,11 @@ static int outstream_end_write_wasapi(struct SoundIoPrivate *si, struct SoundIoO
|
||||||
static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||||
struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
||||||
|
|
||||||
if (osw->h_event) {
|
if (osw->is_raw) {
|
||||||
return SoundIoErrorIncompatibleDevice;
|
return SoundIoErrorIncompatibleDevice;
|
||||||
} else {
|
} else {
|
||||||
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->clear_buffer_flag);
|
SOUNDIO_ATOMIC_FLAG_CLEAR(osw->clear_buffer_flag);
|
||||||
soundio_os_mutex_lock(osw->mutex);
|
SetEvent(osw->h_event);
|
||||||
soundio_os_cond_signal(osw->cond, osw->mutex);
|
|
||||||
soundio_os_mutex_unlock(osw->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -73,7 +73,6 @@ struct SoundIoOutStreamWasapi {
|
||||||
struct SoundIoOsCond *start_cond;
|
struct SoundIoOsCond *start_cond;
|
||||||
struct SoundIoAtomicFlag thread_exit_flag;
|
struct SoundIoAtomicFlag thread_exit_flag;
|
||||||
bool is_raw;
|
bool is_raw;
|
||||||
int writable_frame_count;
|
|
||||||
UINT32 buffer_frame_count;
|
UINT32 buffer_frame_count;
|
||||||
int write_frame_count;
|
int write_frame_count;
|
||||||
HANDLE h_event;
|
HANDLE h_event;
|
||||||
|
|
Loading…
Reference in a new issue