mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
WASAPI: Add some overrun detection for ma_device_type_capture.
This is derived from the ma_device_type_duplex case. It basically detects a possible overrun and drops some periods. The idea is to prevent the buffer from indefinitely straddling the end of the buffer and causing persistent glitching. Public issue https://github.com/dr-soft/miniaudio/issues/81
This commit is contained in:
+53
-1
@@ -12884,7 +12884,58 @@ static ma_result ma_device_main_loop__wasapi(ma_device* pDevice)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should have a buffer at this point. */
|
/* Overrun detection. */
|
||||||
|
if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
|
||||||
|
/* Glitched. Probably due to an overrun. */
|
||||||
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
|
printf("[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Exeriment: If we get an overrun it probably means we're straddling the end of the buffer. In order to prevent a never-ending sequence of glitches let's experiment
|
||||||
|
by dropping every frame until we're left with only a single period. To do this we just keep retrieving and immediately releasing buffers until we're down to the
|
||||||
|
last period.
|
||||||
|
*/
|
||||||
|
if (framesAvailableCapture >= pDevice->wasapi.actualPeriodSizeInFramesCapture) {
|
||||||
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
|
printf("[WASAPI] Synchronizing capture stream. ");
|
||||||
|
#endif
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
framesAvailableCapture -= mappedDeviceBufferSizeInFramesCapture;
|
||||||
|
|
||||||
|
if (framesAvailableCapture > 0) {
|
||||||
|
mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
|
||||||
|
hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
|
||||||
|
exitLoop = MA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pMappedDeviceBufferCapture = NULL;
|
||||||
|
mappedDeviceBufferSizeInFramesCapture = 0;
|
||||||
|
}
|
||||||
|
} while (framesAvailableCapture > periodSizeInFramesCapture);
|
||||||
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
|
printf("framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
|
if (flagsCapture != 0) {
|
||||||
|
printf("[WASAPI] Capture Flags: %d\n", flagsCapture);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should have a buffer at this point, but let's just do a sanity check anyway. */
|
||||||
|
if (mappedDeviceBufferSizeInFramesCapture > 0 && pMappedDeviceBufferCapture != NULL) {
|
||||||
ma_device__send_frames_to_client(pDevice, mappedDeviceBufferSizeInFramesCapture, pMappedDeviceBufferCapture);
|
ma_device__send_frames_to_client(pDevice, mappedDeviceBufferSizeInFramesCapture, pMappedDeviceBufferCapture);
|
||||||
|
|
||||||
/* At this point we're done with the buffer. */
|
/* At this point we're done with the buffer. */
|
||||||
@@ -12896,6 +12947,7 @@ static ma_result ma_device_main_loop__wasapi(ma_device* pDevice)
|
|||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user