-
Notifications
You must be signed in to change notification settings - Fork 233
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
Add a code path for better shared mode wasapi on windows #231
base: master
Are you sure you want to change the base?
Conversation
It seems that on my device, windows updates only on a 10ms basis with 48000Hz floating point (480 frames, max and min are the same, increment also the same), and minimum buffer created has a size of 1056. It seems that the audio system on my device always asks for some padding for re-sampling and does some buffering at the same time with the new code path. It may be that the buffer size is the total software latency on windows on my device, and buffers are only sent to engine after filled completely in shared mode (and the few seconds of sound after a breakpoint has been hit can be explained). EDIT: |
Something has changed since Windows 10 v2004, does this patch solve those issues too? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the extra +
.
src/wasapi.c
Outdated
+static const IID IID_IAudioEndpointVolume = { | ||
+ //MIDL_INTERFACE("5CDF2C82-841E-4546-9722-0CF74078229A") | ||
+0x5cdf2c82, 0x841e, 0x4546, {0x97, 0x22, 0x0c, 0xf7, 0x40, 0x78, 0x22, 0x9a} | ||
+}; | ||
+static const IID IID_IAudioEndpointVolumeCallback = { | ||
+ //MIDL_INTERFACE("657804FA-D6AD-4496-8A60-352752AF4F89") | ||
+0x657804fa, 0xd6ad, 0x4496, {0x8a, 0x60, 0x35, 0x27, 0x52, 0xaf, 0x4f, 0x89} | ||
+}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have extra +
in front of these lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
You mostly changed for outstream only. How about instream? |
This is mainly meant for better implementing a buffer size negotiation and callback based buffer submission. The main code path is no different from the original, only that the buffer can better accommodate the shared mode engine period, thus reducing the buffer size while not making audio dropouts. I doubt if audio input will benefit from this as long as it is using a callback based implementation, since the available buffer size is determined by the os at wakeup time. It is possible to change the os audio engine period to something much less than the default 10ms, but I did not have the hardware to test it (mine reports 480 to 480 samples working on native 48kHz float), thus currently only the current period is used. Also when using smaller frames, like the raw mode on my device, there is a constant flow of dropouts. It seems that the thread scheduler cannot work on that much granularity, and must use the realtime work queue API for scheduling if such precision is needed. The |
WIP |
See also https://chromium.googlesource.com/chromium/src/media/+/refs/heads/master/audio/win/core_audio_util_win.cc for things like |
Preparing for merge
Same as title.
Thanks again for pointing to a working implementation, I'm adding a bit of non-WAVEFORMATEXTENSIBLE (8 bit and 16 bit pcm support, others may not work and should return invalid) in the WIP pull. |
It seems that can be used when audio3 is not available, will put this into the WIP. |
Also fix pausing logic that wwnt wrong some time ago.
@@ -0,0 +1,163 @@ | |||
#ifndef __MSVC_STDATOMIC_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This atomic implementation is for msvc to build with c compiler, since windows sdk does not include a C atomic implementation (mingw should be configured to exclude this).
Code from github repo:
https://github.com/zenny-chen/simple-stdatomic-for-VS-Clang
under apache 2.0 license.
(maybe add a license note?)
src/config.h
Outdated
/* | ||
* Copyright (c) 2015 Andrew Kelley | ||
* | ||
* This file is part of libsoundio, which is MIT licensed. | ||
* See http://opensource.org/licenses/MIT | ||
*/ | ||
|
||
#ifndef SOUNDIO_CONFIG_H | ||
#define SOUNDIO_CONFIG_H | ||
|
||
#define SOUNDIO_VERSION_MAJOR 2 | ||
#define SOUNDIO_VERSION_MINOR 0 | ||
#define SOUNDIO_VERSION_PATCH 0 | ||
#define SOUNDIO_VERSION_STRING "2.0.0" | ||
|
||
/* #undef SOUNDIO_HAVE_JACK */ | ||
/* #undef SOUNDIO_HAVE_PULSEAUDIO */ | ||
/* #undef SOUNDIO_HAVE_ALSA */ | ||
/* #undef SOUNDIO_HAVE_COREAUDIO */ | ||
#define SOUNDIO_HAVE_WASAPI | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config.h
is not meant to be checked in, is it?
if (wave_format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { | ||
from_channel_mask_layout(wave_format->dwChannelMask, layout); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreachable due to assert()
above.
src/wasapi.c
Outdated
dev_w_raw->iaudio3_available=true; | ||
dev_w_shared->iaudio3_available = true; | ||
dev_w_raw->iaudio3_available = false; | ||
dev_w_shared->iaudio3_available = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true
or false
?
Remove code added to test shared mode without iaudioclient3 and the assertion added when the extensible problem is first known
Fixed problems listed. They are mainly code for testing and initial waveformatex support. Sorry that I forgot to look at the diffs and made such mistake. Also fixed pausing the original shared mode (It seems only stopping the stream, and then supplying buffers to it will somehow restart it on my PC (sdk 1903) currently, may be because of the smaller buffer size from GetPeroid exposed this problem or because of driver change (the original 4 second buffer may be much larger than the time from pause to unpause).) |
It works on v2004. Will test on v1909 soon. |
This is mainly a sanity check, since paused stream should not be calling callbacks
@shangjiaxuan Sorry for bumping an old issue but is event mode exclusive to newer versions of |
Newer versions of windows exposes a event callback based shared mode, which has much smaller latency (up to less than 10ms) and min max frame counts and os mixing engine frame size can be queried through the new interface.
The added test in refresh device tests for the existence and sets a flag of availability in the device (I normally use c++, I don't know if there's bool type in pure c, if not, may need to change the bool to int), and the stream_do_open will open the new interface if detected earlier, and sets the smallest buffer size. The shared run code also added the path for this event based shared mode.
Since the queried size is in frame count, the path was changed to use frame count instead of reference time for better precision.
Tested on my device, before using this setup, the program continues to beep after a breakpoint is hit for a few seconds, corresponding to the default 4 second buffer size (a really large latency for anything, even multimedia playback is not allowed to have this lag). After using the new one, the time shortens to something acceptable (I cannot estimate with my ears).
Of course, setting the buffer size to something like 20ms in original code has similar effect, but that often ends up with lots of overhead. (It seems typically windows updates sound on a 10ms time frame, incompatible buffer sizes will impose overhead and dropouts.)