2014-01-05 16:26:32 -08:00
|
|
|
From c70efb35703e991685bf33b2e3faba3a1365a58f Mon Sep 17 00:00:00 2001
|
2013-12-06 12:09:21 -08:00
|
|
|
From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
|
2014-01-05 16:26:32 -08:00
|
|
|
Date: Sat, 4 Jan 2014 07:08:54 +0100
|
2013-12-06 12:09:21 -08:00
|
|
|
Subject: [PATCH 21/42] winepulse v18: Latency and compilation improvements
|
|
|
|
|
|
|
|
Changes since v17:
|
|
|
|
- Remove clock_pulse interpolation
|
|
|
|
* Couldn't work, sadly
|
|
|
|
- Allow 2 * MinimumPeriod for shared buffers
|
|
|
|
- Fix all compiler warnings when compiling with 64-bits
|
|
|
|
- Dynamically select low latency mode if less than 2 default periods are request
|
|
|
|
* This requires the rtkit patch to be useful
|
|
|
|
---
|
|
|
|
dlls/winepulse.drv/mmdevdrv.c | 55 +++++++++++++++++--------------------------
|
|
|
|
1 file changed, 22 insertions(+), 33 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
index 6e75674..8e76826 100644
|
|
|
|
--- a/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
@@ -169,7 +169,6 @@ struct ACImpl {
|
|
|
|
pa_channel_map map;
|
|
|
|
|
|
|
|
INT64 clock_lastpos, clock_written;
|
|
|
|
- pa_usec_t clock_pulse;
|
|
|
|
|
|
|
|
AudioSession *session;
|
|
|
|
AudioSessionWrapper *session_wrapper;
|
|
|
|
@@ -518,7 +517,6 @@ static void pulse_attr_update(pa_stream *s, void *user) {
|
|
|
|
static void pulse_wr_callback(pa_stream *s, size_t bytes, void *userdata)
|
|
|
|
{
|
|
|
|
ACImpl *This = userdata;
|
|
|
|
- pa_usec_t time;
|
|
|
|
UINT32 oldpad = This->pad;
|
|
|
|
|
|
|
|
if (bytes < This->bufsize_bytes)
|
|
|
|
@@ -528,13 +526,8 @@ static void pulse_wr_callback(pa_stream *s, size_t bytes, void *userdata)
|
|
|
|
|
|
|
|
assert(oldpad >= This->pad);
|
|
|
|
|
|
|
|
- if (0 && This->pad && pa_stream_get_time(This->stream, &time) >= 0)
|
|
|
|
- This->clock_pulse = time;
|
|
|
|
- else
|
|
|
|
- This->clock_pulse = PA_USEC_INVALID;
|
|
|
|
-
|
|
|
|
This->clock_written += oldpad - This->pad;
|
|
|
|
- TRACE("New pad: %u (-%u)\n", This->pad / pa_frame_size(&This->ss), (oldpad - This->pad) / pa_frame_size(&This->ss));
|
|
|
|
+ TRACE("New pad: %zu (-%zu)\n", This->pad / pa_frame_size(&This->ss), (oldpad - This->pad) / pa_frame_size(&This->ss));
|
|
|
|
|
|
|
|
if (This->event)
|
|
|
|
SetEvent(This->event);
|
|
|
|
@@ -542,8 +535,6 @@ static void pulse_wr_callback(pa_stream *s, size_t bytes, void *userdata)
|
|
|
|
|
|
|
|
static void pulse_underflow_callback(pa_stream *s, void *userdata)
|
|
|
|
{
|
|
|
|
- ACImpl *This = userdata;
|
|
|
|
- This->clock_pulse = PA_USEC_INVALID;
|
|
|
|
WARN("Underflow\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -562,12 +553,8 @@ static void pulse_latency_callback(pa_stream *s, void *userdata)
|
|
|
|
static void pulse_started_callback(pa_stream *s, void *userdata)
|
|
|
|
{
|
|
|
|
ACImpl *This = userdata;
|
|
|
|
- pa_usec_t time;
|
|
|
|
|
|
|
|
TRACE("(Re)started playing\n");
|
|
|
|
- assert(This->clock_pulse == PA_USEC_INVALID);
|
|
|
|
- if (0 && pa_stream_get_time(This->stream, &time) >= 0)
|
|
|
|
- This->clock_pulse = time;
|
|
|
|
if (This->event)
|
|
|
|
SetEvent(This->event);
|
|
|
|
}
|
|
|
|
@@ -578,7 +565,7 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
|
|
|
ACPacket *p, *next;
|
|
|
|
LARGE_INTEGER stamp, freq;
|
|
|
|
BYTE *dst, *src;
|
|
|
|
- UINT32 src_len, copy, rem = This->capture_period;
|
|
|
|
+ size_t src_len, copy, rem = This->capture_period;
|
|
|
|
if (!(p = (ACPacket*)list_head(&This->packet_free_head))) {
|
|
|
|
p = (ACPacket*)list_head(&This->packet_filled_head);
|
|
|
|
if (!p->discont) {
|
|
|
|
@@ -630,7 +617,7 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
|
|
|
static void pulse_rd_drop(ACImpl *This, size_t bytes)
|
|
|
|
{
|
|
|
|
while (bytes >= This->capture_period) {
|
|
|
|
- UINT32 src_len, copy, rem = This->capture_period;
|
|
|
|
+ size_t src_len, copy, rem = This->capture_period;
|
|
|
|
while (rem) {
|
|
|
|
const void *src;
|
|
|
|
pa_stream_peek(This->stream, &src, &src_len);
|
|
|
|
@@ -660,7 +647,7 @@ static void pulse_rd_callback(pa_stream *s, size_t bytes, void *userdata)
|
|
|
|
{
|
|
|
|
ACImpl *This = userdata;
|
|
|
|
|
|
|
|
- TRACE("Readable total: %u, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(s)->fragsize);
|
|
|
|
+ TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(s)->fragsize);
|
|
|
|
assert(bytes >= This->peek_ofs);
|
|
|
|
bytes -= This->peek_ofs;
|
|
|
|
if (bytes < This->capture_period)
|
|
|
|
@@ -815,7 +802,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(void *key, IMMDevice *dev,
|
|
|
|
This->IAudioStreamVolume_iface.lpVtbl = &AudioStreamVolume_Vtbl;
|
|
|
|
This->dataflow = dataflow;
|
|
|
|
This->parent = dev;
|
|
|
|
- This->clock_pulse = PA_USEC_INVALID;
|
|
|
|
for (i = 0; i < PA_CHANNELS_MAX; ++i)
|
|
|
|
This->vol[i] = 1.f;
|
|
|
|
IMMDevice_AddRef(This->parent);
|
|
|
|
@@ -1199,7 +1185,19 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (mode == AUDCLNT_SHAREMODE_SHARED) {
|
|
|
|
- period = pulse_def_period[This->dataflow == eCapture];
|
|
|
|
+ REFERENCE_TIME def = pulse_def_period[This->dataflow == eCapture];
|
|
|
|
+ REFERENCE_TIME min = pulse_min_period[This->dataflow == eCapture];
|
|
|
|
+
|
|
|
|
+ /* Switch to low latency mode if below 2 default periods,
|
|
|
|
+ * which is 20 ms by default, this will increase the amount
|
|
|
|
+ * of interrupts but allows very low latency. In dsound I
|
|
|
|
+ * managed to get a total latency of ~8ms, which is well below
|
|
|
|
+ * default
|
|
|
|
+ */
|
|
|
|
+ if (duration < 2 * def)
|
|
|
|
+ period = min;
|
|
|
|
+ else
|
|
|
|
+ period = def;
|
|
|
|
if (duration < 2 * period)
|
|
|
|
duration = 2 * period;
|
|
|
|
}
|
|
|
|
@@ -1510,7 +1508,6 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
|
|
|
pthread_mutex_unlock(&pulse_lock);
|
|
|
|
return AUDCLNT_E_NOT_STOPPED;
|
|
|
|
}
|
|
|
|
- This->clock_pulse = PA_USEC_INVALID;
|
|
|
|
|
|
|
|
if (pa_stream_is_corked(This->stream)) {
|
|
|
|
o = pa_stream_cork(This->stream, 0, pulse_op_cb, &success);
|
|
|
|
@@ -1566,7 +1563,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
This->started = FALSE;
|
|
|
|
- This->clock_pulse = PA_USEC_INVALID;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&pulse_lock);
|
|
|
|
return hr;
|
|
|
|
@@ -1764,7 +1760,8 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
|
|
|
UINT32 frames, BYTE **data)
|
|
|
|
{
|
|
|
|
ACImpl *This = impl_from_IAudioRenderClient(iface);
|
|
|
|
- UINT32 avail, pad, req, bytes = frames * pa_frame_size(&This->ss);
|
|
|
|
+ size_t avail, req, bytes = frames * pa_frame_size(&This->ss);
|
|
|
|
+ UINT32 pad;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
@@ -1789,7 +1786,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
|
|
|
avail = This->bufsize_frames - pad;
|
|
|
|
if (avail < frames || bytes > This->bufsize_bytes) {
|
|
|
|
pthread_mutex_unlock(&pulse_lock);
|
|
|
|
- WARN("Wanted to write %u, but only %u available\n", frames, avail);
|
|
|
|
+ WARN("Wanted to write %u, but only %zu available\n", frames, avail);
|
|
|
|
return AUDCLNT_E_BUFFER_TOO_LARGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1797,7 +1794,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
|
|
|
req = bytes;
|
|
|
|
ret = pa_stream_begin_write(This->stream, &This->locked_ptr, &req);
|
|
|
|
if (ret < 0 || req < bytes) {
|
|
|
|
- FIXME("%p Not using pulse locked data: %i %u/%u %u/%u\n", This, ret, req/pa_frame_size(&This->ss), frames, pad, This->bufsize_frames);
|
|
|
|
+ FIXME("%p Not using pulse locked data: %i %zu/%u %u/%u\n", This, ret, req/pa_frame_size(&This->ss), frames, pad, This->bufsize_frames);
|
|
|
|
if (ret >= 0)
|
|
|
|
pa_stream_cancel_write(This->stream);
|
|
|
|
*data = This->tmp_buffer;
|
|
|
|
@@ -1845,7 +1842,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
|
|
|
|
pa_stream_write(This->stream, This->tmp_buffer, written_bytes, NULL, 0, PA_SEEK_RELATIVE);
|
|
|
|
This->pad += written_bytes;
|
|
|
|
This->locked_ptr = NULL;
|
|
|
|
- TRACE("Released %u, pad %u\n", written_frames, This->pad / pa_frame_size(&This->ss));
|
|
|
|
+ TRACE("Released %u, pad %zu\n", written_frames, This->pad / pa_frame_size(&This->ss));
|
|
|
|
assert(This->pad <= This->bufsize_bytes);
|
|
|
|
pthread_mutex_unlock(&pulse_lock);
|
|
|
|
return S_OK;
|
|
|
|
@@ -2053,7 +2050,6 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
|
|
|
|
UINT64 *qpctime)
|
|
|
|
{
|
|
|
|
ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
- pa_usec_t time;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
|
|
|
|
@@ -2069,13 +2065,6 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
|
|
|
|
}
|
|
|
|
|
|
|
|
*pos = This->clock_written;
|
|
|
|
- if (This->clock_pulse != PA_USEC_INVALID && pa_stream_get_time(This->stream, &time) >= 0) {
|
|
|
|
- UINT32 delta = pa_usec_to_bytes(time - This->clock_pulse, &This->ss);
|
|
|
|
- if (delta < This->pad)
|
|
|
|
- *pos += delta;
|
|
|
|
- else
|
|
|
|
- *pos += This->pad;
|
|
|
|
- }
|
|
|
|
|
|
|
|
/* Make time never go backwards */
|
|
|
|
if (*pos < This->clock_lastpos)
|
|
|
|
--
|
2014-01-05 16:26:32 -08:00
|
|
|
1.8.5.2
|
2013-12-06 12:09:21 -08:00
|
|
|
|