From e00f3ddefac5861d5d124d54da326213f414c243 Mon Sep 17 00:00:00 2001 From: David Reid Date: Sun, 3 Mar 2019 17:18:45 +1000 Subject: [PATCH] DirectSound: Drain the playback buffer when stopping the device. --- mini_al.h | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/mini_al.h b/mini_al.h index 224e85db..dfc94dd2 100644 --- a/mini_al.h +++ b/mini_al.h @@ -9631,9 +9631,44 @@ mal_result mal_device_main_loop__dsound(mal_device* pDevice) /* Getting here means the device is being stopped. */ - /* The playback device should be drained before stopping. */ + /* The playback device should be drained before stopping. All we do is wait until the available bytes is equal to the size of the buffer. */ if (isPlaybackDeviceStarted) { - /* TODO: Drain the playback device. */ + for (;;) { + DWORD availableBytesPlayback = 0; + DWORD physicalPlayCursorInBytes; + DWORD physicalWriteCursorInBytes; + if (FAILED(mal_IDirectSoundBuffer_GetCurrentPosition((mal_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) { + break; + } + + if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) { + physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback; + } + prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes; + + if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) { + /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */ + if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) { + availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback; + availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */ + } else { + break; + } + } else { + /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */ + if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) { + availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback; + } else { + break; + } + } + + if (availableBytesPlayback >= (pDevice->playback.internalBufferSizeInFrames*bpfPlayback)) { + break; + } + + mal_sleep(waitTimeInMilliseconds); + } } if (pDevice->type == mal_device_type_capture || pDevice->type == mal_device_type_duplex) {