diff --git a/miniaudio.h b/miniaudio.h index 22b0e4f..49ecd9a 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -23061,6 +23061,26 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice) } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { + ma_uint32 bufferSizeInFrames; + if (pDevice->playback.shareMode == ma_share_mode_exclusive) { + bufferSizeInFrames = pDevice->wasapi.actualBufferSizeInFramesPlayback; + } else { + bufferSizeInFrames = pDevice->wasapi.periodSizeInFramesPlayback; + } + hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, bufferSizeInFrames, (BYTE**)&pDevice->wasapi.pMappedBufferPlayback); + if (FAILED(hr)) { + return ma_result_from_HRESULT(hr); + } + pDevice->wasapi.mappedBufferPlaybackCap = bufferSizeInFrames; + pDevice->wasapi.mappedBufferPlaybackLen = 0; + + ma_device__read_frames_from_client(pDevice, bufferSizeInFrames, pDevice->wasapi.pMappedBufferPlayback); + + ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); + pDevice->wasapi.pMappedBufferPlayback = NULL; + pDevice->wasapi.mappedBufferPlaybackCap = 0; + pDevice->wasapi.mappedBufferPlaybackLen = 0; + hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback); if (FAILED(hr)) { ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device. HRESULT = %d.", (int)hr); @@ -23136,6 +23156,7 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / (pDevice->playback.internalSampleRate / 1000); if (pDevice->playback.shareMode == ma_share_mode_exclusive) { + ResetEvent((HANDLE)pDevice->wasapi.hEventPlayback); WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); } else { ma_uint32 prevFramesAvailablePlayback = (ma_uint32)-1; @@ -23415,7 +23436,23 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames ma_uint32 totalFramesProcessed = 0; /* Keep writing to the device until it's stopped or we've consumed all of our input. */ - while (ma_device_get_state(pDevice) == ma_device_state_started && totalFramesProcessed < frameCount) { + while (totalFramesProcessed < frameCount) { + if (pDevice->playback.shareMode == ma_share_mode_exclusive && pDevice->wasapi.pMappedBufferPlayback == NULL) { + /* + In exclusive mode we need to wait here. Exclusive mode is weird because GetBuffer() never + seems to return AUDCLNT_E_BUFFER_TOO_LARGE, which is what we normally use to determine + whether or not we need to wait for more data. + */ + if (WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) { + result = MA_ERROR; + break; /* Wait failed. Probably timed out. */ + } + } + + if (ma_device_get_state(pDevice) != ma_device_state_started) { + break; + } + ma_uint32 framesRemaining = frameCount - totalFramesProcessed; /* @@ -23448,18 +23485,6 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames pDevice->wasapi.pMappedBufferPlayback = NULL; pDevice->wasapi.mappedBufferPlaybackCap = 0; pDevice->wasapi.mappedBufferPlaybackLen = 0; - - /* - In exclusive mode we need to wait here. Exclusive mode is weird because GetBuffer() never - seems to return AUDCLNT_E_BUFFER_TOO_LARGE, which is what we normally use to determine - whether or not we need to wait for more data. - */ - if (pDevice->playback.shareMode == ma_share_mode_exclusive) { - if (WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) { - result = MA_ERROR; - break; /* Wait failed. Probably timed out. */ - } - } } } else { /* We don't have a mapped data buffer so we'll need to get one. */