mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 01:04:02 +02:00
wasapi: implement support for avrt.dll thread characteristics API
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
This commit is contained in:
committed by
David Reid
parent
721863605e
commit
1022e1c08f
+64
@@ -6509,6 +6509,14 @@ typedef enum
|
|||||||
ma_opensl_recording_preset_voice_unprocessed /* SL_ANDROID_RECORDING_PRESET_UNPROCESSED */
|
ma_opensl_recording_preset_voice_unprocessed /* SL_ANDROID_RECORDING_PRESET_UNPROCESSED */
|
||||||
} ma_opensl_recording_preset;
|
} ma_opensl_recording_preset;
|
||||||
|
|
||||||
|
/* WASAPI audio thread priority characteristics. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ma_wasapi_usage_default = 0,
|
||||||
|
ma_wasapi_usage_games,
|
||||||
|
ma_wasapi_usage_pro_audio,
|
||||||
|
} ma_wasapi_usage;
|
||||||
|
|
||||||
/* AAudio usage types. */
|
/* AAudio usage types. */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -6652,6 +6660,7 @@ struct ma_device_config
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
ma_wasapi_usage usage; /* When configured, uses Avrt APIs to set the thread characteristics. */
|
||||||
ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
|
ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
|
||||||
ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
|
ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
|
||||||
ma_bool8 noAutoStreamRouting; /* Disables automatic stream routing. */
|
ma_bool8 noAutoStreamRouting; /* Disables automatic stream routing. */
|
||||||
@@ -6898,6 +6907,9 @@ struct ma_context
|
|||||||
ma_uint32 commandIndex;
|
ma_uint32 commandIndex;
|
||||||
ma_uint32 commandCount;
|
ma_uint32 commandCount;
|
||||||
ma_context_command__wasapi commands[4];
|
ma_context_command__wasapi commands[4];
|
||||||
|
ma_handle hAvrt;
|
||||||
|
ma_proc AvSetMmThreadCharacteristicsW;
|
||||||
|
ma_proc AvRevertMmThreadcharacteristics;
|
||||||
} wasapi;
|
} wasapi;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MA_SUPPORT_DSOUND
|
#ifdef MA_SUPPORT_DSOUND
|
||||||
@@ -7401,6 +7413,8 @@ struct ma_device
|
|||||||
ma_bool8 allowPlaybackAutoStreamRouting;
|
ma_bool8 allowPlaybackAutoStreamRouting;
|
||||||
ma_bool8 isDetachedPlayback;
|
ma_bool8 isDetachedPlayback;
|
||||||
ma_bool8 isDetachedCapture;
|
ma_bool8 isDetachedCapture;
|
||||||
|
ma_wasapi_usage usage;
|
||||||
|
void *hAvrtHandle;
|
||||||
} wasapi;
|
} wasapi;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MA_SUPPORT_DSOUND
|
#ifdef MA_SUPPORT_DSOUND
|
||||||
@@ -19785,6 +19799,10 @@ static MA_INLINE HRESULT ma_IAudioCaptureClient_GetBuffer(ma_IAudioCaptureClient
|
|||||||
static MA_INLINE HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
|
static MA_INLINE HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
|
||||||
static MA_INLINE HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket) { return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
|
static MA_INLINE HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket) { return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
|
||||||
|
|
||||||
|
/* Avrt Functions */
|
||||||
|
typedef HANDLE (WINAPI * MA_PFN_AvSetMmThreadCharacteristicsW)(LPCWSTR TaskName, LPDWORD TaskIndex);
|
||||||
|
typedef BOOL (WINAPI * MA_PFN_AvRevertMmThreadCharacteristics)(HANDLE AvrtHandle);
|
||||||
|
|
||||||
#if !defined(MA_WIN32_DESKTOP) && !defined(MA_WIN32_GDK)
|
#if !defined(MA_WIN32_DESKTOP) && !defined(MA_WIN32_GDK)
|
||||||
#include <mmdeviceapi.h>
|
#include <mmdeviceapi.h>
|
||||||
typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
|
typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
|
||||||
@@ -20137,6 +20155,18 @@ static ma_IMMNotificationClientVtbl g_maNotificationCientVtbl = {
|
|||||||
};
|
};
|
||||||
#endif /* MA_WIN32_DESKTOP */
|
#endif /* MA_WIN32_DESKTOP */
|
||||||
|
|
||||||
|
static LPCWSTR ma_to_usage_string__wasapi(ma_wasapi_usage usage)
|
||||||
|
{
|
||||||
|
switch (usage) {
|
||||||
|
case ma_wasapi_usage_default: return NULL;
|
||||||
|
case ma_wasapi_usage_games: return L"Games";
|
||||||
|
case ma_wasapi_usage_pro_audio: return L"Pro Audio";
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
|
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
|
||||||
typedef ma_IMMDevice ma_WASAPIDeviceInterface;
|
typedef ma_IMMDevice ma_WASAPIDeviceInterface;
|
||||||
#else
|
#else
|
||||||
@@ -21584,6 +21614,7 @@ static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_conf
|
|||||||
MA_ASSERT(pDevice != NULL);
|
MA_ASSERT(pDevice != NULL);
|
||||||
|
|
||||||
MA_ZERO_OBJECT(&pDevice->wasapi);
|
MA_ZERO_OBJECT(&pDevice->wasapi);
|
||||||
|
pDevice->wasapi.usage = pConfig->wasapi.usage;
|
||||||
pDevice->wasapi.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
|
pDevice->wasapi.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
|
||||||
pDevice->wasapi.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
|
pDevice->wasapi.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
|
||||||
pDevice->wasapi.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
|
pDevice->wasapi.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
|
||||||
@@ -21877,6 +21908,14 @@ static ma_result ma_device_start__wasapi(ma_device* pDevice)
|
|||||||
|
|
||||||
MA_ASSERT(pDevice != NULL);
|
MA_ASSERT(pDevice != NULL);
|
||||||
|
|
||||||
|
if (pDevice->pContext->wasapi.hAvrt) {
|
||||||
|
LPCWSTR pTaskName = ma_to_usage_string__wasapi(pDevice->wasapi.usage);
|
||||||
|
if (pTaskName) {
|
||||||
|
DWORD idx = 0;
|
||||||
|
pDevice->wasapi.hAvrtHandle = ((MA_PFN_AvSetMmThreadCharacteristicsW)pDevice->pContext->wasapi.AvSetMmThreadCharacteristicsW)(pTaskName, &idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
|
||||||
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
|
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@@ -21907,6 +21946,11 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice)
|
|||||||
|
|
||||||
MA_ASSERT(pDevice != NULL);
|
MA_ASSERT(pDevice != NULL);
|
||||||
|
|
||||||
|
if (pDevice->wasapi.hAvrtHandle) {
|
||||||
|
((MA_PFN_AvRevertMmThreadCharacteristics)pDevice->pContext->wasapi.AvRevertMmThreadcharacteristics)((HANDLE)pDevice->wasapi.hAvrtHandle);
|
||||||
|
pDevice->wasapi.hAvrtHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
|
||||||
hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
|
hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@@ -22261,6 +22305,11 @@ static ma_result ma_context_uninit__wasapi(ma_context* pContext)
|
|||||||
ma_context_post_command__wasapi(pContext, &cmd);
|
ma_context_post_command__wasapi(pContext, &cmd);
|
||||||
ma_thread_wait(&pContext->wasapi.commandThread);
|
ma_thread_wait(&pContext->wasapi.commandThread);
|
||||||
|
|
||||||
|
if (pContext->wasapi.hAvrt) {
|
||||||
|
ma_dlclose(pContext, pContext->wasapi.hAvrt);
|
||||||
|
pContext->wasapi.hAvrt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only after the thread has been terminated can we uninitialize the sync objects for the command thread. */
|
/* Only after the thread has been terminated can we uninitialize the sync objects for the command thread. */
|
||||||
ma_semaphore_uninit(&pContext->wasapi.commandSem);
|
ma_semaphore_uninit(&pContext->wasapi.commandSem);
|
||||||
ma_mutex_uninit(&pContext->wasapi.commandLock);
|
ma_mutex_uninit(&pContext->wasapi.commandLock);
|
||||||
@@ -22366,6 +22415,21 @@ static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_
|
|||||||
ma_mutex_uninit(&pContext->wasapi.commandLock);
|
ma_mutex_uninit(&pContext->wasapi.commandLock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Optionally use the Avrt API to specify the audio thread's latency sensitivity requirements */
|
||||||
|
pContext->wasapi.hAvrt = ma_dlopen(pContext, "avrt.dll");
|
||||||
|
if (pContext->wasapi.hAvrt) {
|
||||||
|
pContext->wasapi.AvSetMmThreadCharacteristicsW = ma_dlsym(pContext, pContext->wasapi.hAvrt, "AvSetMmThreadCharacteristicsW");
|
||||||
|
pContext->wasapi.AvRevertMmThreadcharacteristics = ma_dlsym(pContext, pContext->wasapi.hAvrt, "AvRevertMmThreadCharacteristics");
|
||||||
|
|
||||||
|
/* If either function could not be found, disable use of avrt entirely. */
|
||||||
|
if (!pContext->wasapi.AvSetMmThreadCharacteristicsW || !pContext->wasapi.AvRevertMmThreadcharacteristics) {
|
||||||
|
pContext->wasapi.AvSetMmThreadCharacteristicsW = NULL;
|
||||||
|
pContext->wasapi.AvRevertMmThreadcharacteristics = NULL;
|
||||||
|
ma_dlclose(pContext, pContext->wasapi.hAvrt);
|
||||||
|
pContext->wasapi.hAvrt = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user