diff --git a/CMakeLists.txt b/CMakeLists.txt index ee0356cf0c..5cc9680a11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1044,6 +1044,11 @@ if(WIN32) set(HAVE_WASAPI 1) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) + + find_library(AVRT_LIBRARY NAMES avrt DOC "The AVRT library") + if(AVRT_LIBRARY) + set(EXTRA_LIBS ${AVRT_LIBRARY} ${EXTRA_LIBS}) + endif() endif() endif() diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 0e51996b7c..bccecacfd0 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -319,6 +320,13 @@ struct DeviceListLock : public std::unique_lock { DeviceList gDeviceList; +#ifdef AVRTAPI +struct AvrtHandleCloser { + void operator()(HANDLE handle) { AvRevertMmThreadCharacteristics(handle); } +}; +using AvrtHandlePtr = std::unique_ptr,AvrtHandleCloser>; +#endif + #if defined(ALSOFT_UWP) enum EDataFlow { eRender = 0, @@ -968,6 +976,7 @@ struct WasapiProxy { static inline std::deque mMsgQueue; static inline std::mutex mMsgQueueLock; static inline std::condition_variable mMsgQueueCond; + static inline DWORD sAvIndex{}; static inline std::optional sDeviceHelper; @@ -1169,6 +1178,15 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() const UINT32 buffer_len{mOrigBufferSize}; const void *resbufferptr{}; +#ifdef AVRTAPI + /* TODO: "Audio" or "Pro Audio"? The suggestion is to use "Pro Audio" for + * device periods less than 10ms, and "Audio" for greater than or equal to + * 10ms. + */ + auto taskname = (update_size < mFormat.Format.nSamplesPerSec/100) ? L"Pro Audio" : L"Audio"; + auto avhandle = AvrtHandlePtr{AvSetMmThreadCharacteristicsW(taskname, &sAvIndex)}; +#endif + mBufferFilled = 0; while(!mKillNow.load(std::memory_order_relaxed)) { @@ -1257,6 +1275,11 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() std::vector resbuffers; std::vector tmpbuffers; +#ifdef AVRTAPI + auto taskname = (mOrigUpdateSize