Signed-off-by: Torge Matthies openglfreak@googlemail.com --- These two patches help applications that need very low audio latency. They make sense individually, but are related so I'm sending them as one set.
This first patch does nothing on vanilla Wine, but helps on Wine Staging and other patched Wine versions.
dlls/winepulse.drv/mmdevdrv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 417067f0bf8..4609b2851ed 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -2045,8 +2045,10 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) This->started = TRUE; This->just_started = TRUE;
- if(!This->timer) + if(!This->timer) { This->timer = CreateThread(NULL, 0, pulse_timer_cb, This, 0, NULL); + SetThreadPriority(This->timer, THREAD_PRIORITY_TIME_CRITICAL); + } } pthread_mutex_unlock(&pulse_lock); return hr;
Signed-off-by: Torge Matthies openglfreak@googlemail.com --- This patch makes the pause in the loop of the audio thread more accurate. Sleep() may not be accurate enough for low-latency applications, and may pause execution either for too long or not at all. NtDelayExecution is an internal, undocumented function, but winepulse.drv is a Wine-internal module too so it should be fine imo.
dlls/winepulse.drv/mmdevdrv.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 4609b2851ed..10b01868a9d 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -38,6 +38,7 @@ #include "winbase.h" #include "winnls.h" #include "winreg.h" +#include "winternl.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" @@ -1021,14 +1022,14 @@ static void pulse_read(ACImpl *This)
static DWORD WINAPI pulse_timer_cb(void *user) { - DWORD delay; + LARGE_INTEGER delay; UINT32 adv_bytes; ACImpl *This = user; int success; pa_operation *o;
pthread_mutex_lock(&pulse_lock); - delay = This->mmdev_period_usec / 1000; + delay.QuadPart = -This->mmdev_period_usec * 10; pa_stream_get_time(This->stream, &This->last_time); pthread_mutex_unlock(&pulse_lock);
@@ -1036,11 +1037,11 @@ static DWORD WINAPI pulse_timer_cb(void *user) pa_usec_t now, adv_usec = 0; int err;
- Sleep(delay); + NtDelayExecution(FALSE, &delay);
pthread_mutex_lock(&pulse_lock);
- delay = This->mmdev_period_usec / 1000; + delay.QuadPart = -This->mmdev_period_usec * 10;
o = pa_stream_update_timing_info(This->stream, pulse_op_cb, &success); if (o) @@ -1076,7 +1077,7 @@ static DWORD WINAPI pulse_timer_cb(void *user) else if(adjust < -((INT32)(This->mmdev_period_usec / 2))) adjust = -1 * This->mmdev_period_usec / 2;
- delay = (This->mmdev_period_usec + adjust) / 1000; + delay.QuadPart = -(This->mmdev_period_usec + adjust) * 10;
This->last_time += This->mmdev_period_usec; } @@ -1094,16 +1095,16 @@ static DWORD WINAPI pulse_timer_cb(void *user) } }else{ This->last_time = now; - delay = This->mmdev_period_usec / 1000; + delay.QuadPart = -This->mmdev_period_usec * 10; } }
if (This->event) SetEvent(This->event);
- TRACE("%p after update, adv usec: %d, held: %u, delay: %u\n", + TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n", This, (int)adv_usec, - (int)(This->held_bytes/ pa_frame_size(&This->ss)), delay); + (int)(This->held_bytes/ pa_frame_size(&This->ss)), (unsigned int)(-delay.QuadPart / 10));
pthread_mutex_unlock(&pulse_lock); }
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Sat, Mar 06, 2021 at 02:27:14AM +0100, Torge Matthies wrote:
Signed-off-by: Torge Matthies openglfreak@googlemail.com
This patch makes the pause in the loop of the audio thread more accurate. Sleep() may not be accurate enough for low-latency applications, and may pause execution either for too long or not at all. NtDelayExecution is an internal, undocumented function, but winepulse.drv is a Wine-internal module too so it should be fine imo.
dlls/winepulse.drv/mmdevdrv.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 4609b2851ed..10b01868a9d 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -38,6 +38,7 @@ #include "winbase.h" #include "winnls.h" #include "winreg.h" +#include "winternl.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" @@ -1021,14 +1022,14 @@ static void pulse_read(ACImpl *This)
static DWORD WINAPI pulse_timer_cb(void *user) {
- DWORD delay;
LARGE_INTEGER delay; UINT32 adv_bytes; ACImpl *This = user; int success; pa_operation *o;
pthread_mutex_lock(&pulse_lock);
- delay = This->mmdev_period_usec / 1000;
- delay.QuadPart = -This->mmdev_period_usec * 10; pa_stream_get_time(This->stream, &This->last_time); pthread_mutex_unlock(&pulse_lock);
@@ -1036,11 +1037,11 @@ static DWORD WINAPI pulse_timer_cb(void *user) pa_usec_t now, adv_usec = 0; int err;
Sleep(delay);
NtDelayExecution(FALSE, &delay); pthread_mutex_lock(&pulse_lock);
delay = This->mmdev_period_usec / 1000;
delay.QuadPart = -This->mmdev_period_usec * 10; o = pa_stream_update_timing_info(This->stream, pulse_op_cb, &success); if (o)
@@ -1076,7 +1077,7 @@ static DWORD WINAPI pulse_timer_cb(void *user) else if(adjust < -((INT32)(This->mmdev_period_usec / 2))) adjust = -1 * This->mmdev_period_usec / 2;
delay = (This->mmdev_period_usec + adjust) / 1000;
delay.QuadPart = -(This->mmdev_period_usec + adjust) * 10; This->last_time += This->mmdev_period_usec; }
@@ -1094,16 +1095,16 @@ static DWORD WINAPI pulse_timer_cb(void *user) } }else{ This->last_time = now;
delay = This->mmdev_period_usec / 1000;
delay.QuadPart = -This->mmdev_period_usec * 10; } } if (This->event) SetEvent(This->event);
TRACE("%p after update, adv usec: %d, held: %u, delay: %u\n",
TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n", This, (int)adv_usec,
(int)(This->held_bytes/ pa_frame_size(&This->ss)), delay);
(int)(This->held_bytes/ pa_frame_size(&This->ss)), (unsigned int)(-delay.QuadPart / 10)); pthread_mutex_unlock(&pulse_lock);
}
-- 2.30.1
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Sat, Mar 06, 2021 at 02:27:13AM +0100, Torge Matthies wrote:
Signed-off-by: Torge Matthies openglfreak@googlemail.com
These two patches help applications that need very low audio latency. They make sense individually, but are related so I'm sending them as one set.
This first patch does nothing on vanilla Wine, but helps on Wine Staging and other patched Wine versions.
dlls/winepulse.drv/mmdevdrv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 417067f0bf8..4609b2851ed 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -2045,8 +2045,10 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) This->started = TRUE; This->just_started = TRUE;
if(!This->timer)
if(!This->timer) { This->timer = CreateThread(NULL, 0, pulse_timer_cb, This, 0, NULL);
SetThreadPriority(This->timer, THREAD_PRIORITY_TIME_CRITICAL);
} pthread_mutex_unlock(&pulse_lock); return hr;}
-- 2.30.1