mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
WASAPI: Add support for hardware offloading and low-latency shared mode
This commit is contained in:
@@ -6652,6 +6652,7 @@ mal_result mal_device_init_internal__wasapi(mal_context* pContext, mal_device_ty
|
|||||||
mal_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
|
mal_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
|
||||||
|
|
||||||
// If we're using a default buffer size we need to calculate it based on the efficiency of the system.
|
// If we're using a default buffer size we need to calculate it based on the efficiency of the system.
|
||||||
|
pData->periodsOut = pData->periodsIn;
|
||||||
pData->bufferSizeInFramesOut = pData->bufferSizeInFramesIn;
|
pData->bufferSizeInFramesOut = pData->bufferSizeInFramesIn;
|
||||||
if (pData->bufferSizeInFramesOut == 0) {
|
if (pData->bufferSizeInFramesOut == 0) {
|
||||||
pData->bufferSizeInFramesOut = mal_calculate_buffer_size_in_frames_from_milliseconds(pData->bufferSizeInMillisecondsIn, pData->sampleRateOut);
|
pData->bufferSizeInFramesOut = mal_calculate_buffer_size_in_frames_from_milliseconds(pData->bufferSizeInMillisecondsIn, pData->sampleRateOut);
|
||||||
@@ -6659,6 +6660,9 @@ mal_result mal_device_init_internal__wasapi(mal_context* pContext, mal_device_ty
|
|||||||
|
|
||||||
bufferDurationInMicroseconds = ((mal_uint64)pData->bufferSizeInFramesOut * 1000 * 1000) / pData->sampleRateOut;
|
bufferDurationInMicroseconds = ((mal_uint64)pData->bufferSizeInFramesOut * 1000 * 1000) / pData->sampleRateOut;
|
||||||
|
|
||||||
|
|
||||||
|
mal_bool32 wasInitializedUsingIAudioClient3 = MAL_FALSE;
|
||||||
|
|
||||||
// Slightly different initialization for shared and exclusive modes. We try exclusive mode first, and if it fails, fall back to shared mode.
|
// Slightly different initialization for shared and exclusive modes. We try exclusive mode first, and if it fails, fall back to shared mode.
|
||||||
if (shareMode == MAL_AUDCLNT_SHAREMODE_EXCLUSIVE) {
|
if (shareMode == MAL_AUDCLNT_SHAREMODE_EXCLUSIVE) {
|
||||||
// Exclusive.
|
// Exclusive.
|
||||||
@@ -6714,23 +6718,59 @@ mal_result mal_device_init_internal__wasapi(mal_context* pContext, mal_device_ty
|
|||||||
|
|
||||||
if (shareMode == MAL_AUDCLNT_SHAREMODE_SHARED) {
|
if (shareMode == MAL_AUDCLNT_SHAREMODE_SHARED) {
|
||||||
// Shared.
|
// Shared.
|
||||||
MAL_REFERENCE_TIME bufferDuration = bufferDurationInMicroseconds*10;
|
|
||||||
hr = mal_IAudioClient_Initialize((mal_IAudioClient*)pData->pAudioClient, shareMode, MAL_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, bufferDuration, 0, (WAVEFORMATEX*)&wf, NULL);
|
// Low latency shared mode via IAudioClient3.
|
||||||
if (FAILED(hr)) {
|
mal_IAudioClient3* pAudioClient3 = NULL;
|
||||||
if (hr == E_ACCESSDENIED) {
|
hr = mal_IAudioClient_QueryInterface(pData->pAudioClient, &MAL_IID_IAudioClient3, (void**)&pAudioClient3);
|
||||||
errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MAL_ACCESS_DENIED;
|
if (SUCCEEDED(hr)) {
|
||||||
} else {
|
UINT32 defaultPeriodInFrames;
|
||||||
errorMsg = "[WASAPI] Failed to initialize device.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
UINT32 fundamentalPeriodInFrames;
|
||||||
|
UINT32 minPeriodInFrames;
|
||||||
|
UINT32 maxPeriodInFrames;
|
||||||
|
hr = mal_IAudioClient3_GetSharedModeEnginePeriod(pAudioClient3, (WAVEFORMATEX*)&wf, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
UINT32 desiredPeriodInFrames = pData->bufferSizeInFramesOut / pData->periodsOut;
|
||||||
|
|
||||||
|
// Make sure the period size is a multiple of fundamentalPeriodInFrames.
|
||||||
|
desiredPeriodInFrames = desiredPeriodInFrames / fundamentalPeriodInFrames;
|
||||||
|
desiredPeriodInFrames = desiredPeriodInFrames * fundamentalPeriodInFrames;
|
||||||
|
|
||||||
|
// The period needs to be clamped between minPeriodInFrames and maxPeriodInFrames.
|
||||||
|
desiredPeriodInFrames = mal_clamp(desiredPeriodInFrames, minPeriodInFrames, maxPeriodInFrames);
|
||||||
|
|
||||||
|
hr = mal_IAudioClient3_InitializeSharedAudioStream(pAudioClient3, MAL_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, desiredPeriodInFrames, (WAVEFORMATEX*)&wf, NULL);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
wasInitializedUsingIAudioClient3 = MAL_TRUE;
|
||||||
|
pData->bufferSizeInFramesOut = desiredPeriodInFrames * pData->periodsOut;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goto done;
|
mal_IAudioClient3_Release(pAudioClient3);
|
||||||
|
pAudioClient3 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have an IAudioClient3 then we need to use the normal initialization routine.
|
||||||
|
if (!wasInitializedUsingIAudioClient3) {
|
||||||
|
MAL_REFERENCE_TIME bufferDuration = bufferDurationInMicroseconds*10;
|
||||||
|
hr = mal_IAudioClient_Initialize((mal_IAudioClient*)pData->pAudioClient, shareMode, MAL_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, bufferDuration, 0, (WAVEFORMATEX*)&wf, NULL);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
if (hr == E_ACCESSDENIED) {
|
||||||
|
errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MAL_ACCESS_DENIED;
|
||||||
|
} else {
|
||||||
|
errorMsg = "[WASAPI] Failed to initialize device.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = mal_IAudioClient_GetBufferSize((mal_IAudioClient*)pData->pAudioClient, &pData->bufferSizeInFramesOut);
|
if (!wasInitializedUsingIAudioClient3) {
|
||||||
if (FAILED(hr)) {
|
hr = mal_IAudioClient_GetBufferSize((mal_IAudioClient*)pData->pAudioClient, &pData->bufferSizeInFramesOut);
|
||||||
errorMsg = "[WASAPI] Failed to get audio client's actual buffer size.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
if (FAILED(hr)) {
|
||||||
goto done;
|
errorMsg = "[WASAPI] Failed to get audio client's actual buffer size.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == mal_device_type_playback) {
|
if (type == mal_device_type_playback) {
|
||||||
@@ -28234,6 +28274,8 @@ mal_uint64 mal_sine_wave_read_ex(mal_sine_wave* pSineWave, mal_uint64 frameCount
|
|||||||
// - WASAPI and Core Audio: Add support for stream routing. When the application is using a default device and the
|
// - WASAPI and Core Audio: Add support for stream routing. When the application is using a default device and the
|
||||||
// user switches the default device via the operating system's audio preferences, mini_al will automatically switch
|
// user switches the default device via the operating system's audio preferences, mini_al will automatically switch
|
||||||
// the internal device to the new default.
|
// the internal device to the new default.
|
||||||
|
// - WASAPI: Add support for hardware offloading via IAudioClient2. Only supported on Windows 8 and newer.
|
||||||
|
// - WASAPI: Add support for low-latency shared mode via IAudioClient3. Only supported on Windows 10 and newer.
|
||||||
// - Add support for compiling the UWP build as C.
|
// - Add support for compiling the UWP build as C.
|
||||||
// - mal_device_set_recv_callback() and mal_device_set_send_callback() have been deprecated. You must now set this
|
// - mal_device_set_recv_callback() and mal_device_set_send_callback() have been deprecated. You must now set this
|
||||||
// when the device is initialized with mal_device_init*(). These will be removed in version 0.9.0.
|
// when the device is initialized with mal_device_init*(). These will be removed in version 0.9.0.
|
||||||
|
|||||||
Reference in New Issue
Block a user