Trace output with PulseAudio:
``` 0144:trace:mmdevapi:adjust_timing Requested duration 1000000 and period 0 0144:trace:mmdevapi:adjust_timing Device periods: 26666 default and 26666 minimum 0144:trace:mmdevapi:adjust_timing Adjusted duration 1000000 and period 100000 ```
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 0b849e47e3d..bb95e797502 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -47,6 +47,8 @@ extern HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UIN struct audio_session **out); extern struct audio_session_wrapper *session_wrapper_create(struct audio_client *client);
+static const REFERENCE_TIME def_period_cap = 100000; + static HANDLE main_loop_thread;
void main_loop_stop(void) @@ -122,7 +124,7 @@ static HRESULT adjust_timing(struct audio_client *This, TRACE("Device periods: %lu default and %lu minimum\n", (ULONG)def_period, (ULONG)min_period);
if (mode == AUDCLNT_SHAREMODE_SHARED) { - *period = def_period; + *period = max(def_period, def_period_cap); if (*duration < 3 * *period) *duration = 3 * *period; } else { @@ -762,6 +764,9 @@ static HRESULT WINAPI client_GetDevicePeriod(IAudioClient3 *iface, REFERENCE_TIM
wine_unix_call(get_device_period, ¶ms);
+ if (defperiod && *defperiod < def_period_cap) + *defperiod = def_period_cap; + return params.result; }
From: Davide Beatrici git@davidebeatrici.dev
This driver, unlike the others, queries the engine for the actual device period.
The default period cap is not needed anymore because it now lives in mmdevapi. The minimum period cap never mattered because exclusive mode is not supported. --- dlls/winepulse.drv/pulse.c | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index dd8d0b4441d..068245f03b2 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -113,9 +113,6 @@ static pa_mainloop *pulse_ml; static struct list g_phys_speakers = LIST_INIT(g_phys_speakers); static struct list g_phys_sources = LIST_INIT(g_phys_sources);
-static const REFERENCE_TIME MinimumPeriod = 30000; -static const REFERENCE_TIME DefaultPeriod = 100000; - static pthread_mutex_t pulse_mutex; static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
@@ -750,12 +747,6 @@ static void pulse_probe_settings(int render, const char *pulse_name, WAVEFORMATE if (length) *def_period = *min_period = pa_bytes_to_usec(10 * length, &ss);
- if (*min_period < MinimumPeriod) - *min_period = MinimumPeriod; - - if (*def_period < DefaultPeriod) - *def_period = DefaultPeriod; - wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
Does the period cap exist on Windows? If yes, can you add tests for that?
Does the period cap exist on Windows?
https://learn.microsoft.com/en-us/windows-hardware/drivers/audio/low-latency...
It's not exactly what I would call a "cap", `AudioClient::Initialize()` simply ignores the `period` parameter when opening a stream in shared mode. The article states:
Before Windows 10, the buffer was always set to ~10 ms.
Starting with Windows 10, the buffer size is defined by the audio driver (more details on the buffer are described later in this article).
Later on, the article proceeds to describe `IAudioClient3`'s functionality:
Allow an application to discover the range of buffer sizes (that is, periodicity values) that are supported by the audio driver of a given audio device. This makes it possible for an application to choose between the default buffer size (10 ms) or a small buffer (less than 10 ms) when opening a stream in shared mode. If an application doesn't specify a buffer size, then it will use the default buffer size.
I'm assuming they kept 10 ms as the default even for this new interface in fear of potential glitches that could arise with lower latencies, especially when dealing with multiple devices and/or streams.
If yes, can you add tests for that?
https://gitlab.winehq.org/wine/wine/-/blob/7eb72b7bb3d3ea771efddcb5273e8a694...
Huw Davies (@huw) commented about dlls/mmdevapi/client.c:
TRACE("Device periods: %lu default and %lu minimum\n", (ULONG)def_period, (ULONG)min_period); if (mode == AUDCLNT_SHAREMODE_SHARED) {
*period = def_period;
*period = max(def_period, def_period_cap);
Do we not need to do this in the exclusive case?
Also, 'cap' to me implies a maximum value. I'd try `min_def_period` and change the commit msg.