Discussion:
[pulseaudio-discuss] [PATCH] Change the default fragment size to 5 ms
Alexander E. Patrakov
2014-10-22 16:21:53 UTC
Permalink
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.

This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!

A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.

This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.

The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.

Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.

Wine wiki recommends 5ms.

On devices that can use tsched, there is no problem.

Signed-off-by: Alexander E. Patrakov <***@gmail.com>
---
man/pulse-daemon.conf.5.xml.in | 4 ++--
src/daemon/daemon-conf.c | 2 +-
src/daemon/daemon.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>

</section>
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b7a85aa..6dc15cf 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -96,7 +96,7 @@ static const pa_daemon_conf default_conf = {
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
- .default_fragment_size_msec = 25,
+ .default_fragment_size_msec = 5,
.deferred_volume_safety_margin_usec = 8000,
.deferred_volume_extra_delay_usec = 0,
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 5b20130..3d758cd 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -85,7 +85,7 @@ ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl
; default-channel-map = front-left,front-right

; default-fragments = 4
-; default-fragment-size-msec = 25
+; default-fragment-size-msec = 5

; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
--
2.1.2
Pierre-Louis Bossart
2014-10-22 20:06:23 UTC
Permalink
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
Maybe it should be made clearer that the actual periods may differ
slightly from the default settings due to hardware constraints or
rounding issues, e.g. with your 5ms setting at 44100 Hz the period of
220.5 samples is going to be rounded....
Post by Alexander E. Patrakov
On devices that can use tsched, there is no problem.
---
man/pulse-daemon.conf.5.xml.in | 4 ++--
src/daemon/daemon-conf.c | 2 +-
src/daemon/daemon.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>
</section>
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b7a85aa..6dc15cf 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -96,7 +96,7 @@ static const pa_daemon_conf default_conf = {
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
- .default_fragment_size_msec = 25,
+ .default_fragment_size_msec = 5,
I've never understood why 4 fragments would be needed. Use 2 fragments
and 10ms periods...
Post by Alexander E. Patrakov
.deferred_volume_safety_margin_usec = 8000,
.deferred_volume_extra_delay_usec = 0,
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 5b20130..3d758cd 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -85,7 +85,7 @@ ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl
; default-channel-map = front-left,front-right
; default-fragments = 4
-; default-fragment-size-msec = 25
+; default-fragment-size-msec = 5
; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
Alexander E. Patrakov
2014-10-22 20:27:52 UTC
Permalink
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
Maybe it should be made clearer that the actual periods may differ
slightly from the default settings due to hardware constraints or
rounding issues, e.g. with your 5ms setting at 44100 Hz the period of
220.5 samples is going to be rounded....
OK, I will clarify the commit message tomorrow.
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
On devices that can use tsched, there is no problem.
---
man/pulse-daemon.conf.5.xml.in | 4 ++--
src/daemon/daemon-conf.c | 2 +-
src/daemon/daemon.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/pulse-daemon.conf.5.xml.in
b/man/pulse-daemon.conf.5.xml.in
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>
</section>
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b7a85aa..6dc15cf 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -96,7 +96,7 @@ static const pa_daemon_conf default_conf = {
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
- .default_fragment_size_msec = 25,
+ .default_fragment_size_msec = 5,
I've never understood why 4 fragments would be needed. Use 2 fragments
and 10ms periods...
This works here, indeed. As for not using 2 periods, I think this may be
related to cards that, according to the ALSA driver, should not work
with just 2 periods (does anyone have a ymfpci?).
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
.deferred_volume_safety_margin_usec = 8000,
.deferred_volume_extra_delay_usec = 0,
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 5b20130..3d758cd 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -85,7 +85,7 @@ ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl
; default-channel-map = front-left,front-right
; default-fragments = 4
-; default-fragment-size-msec = 25
+; default-fragment-size-msec = 5
; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
_______________________________________________
pulseaudio-discuss mailing list
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
--
Alexander E. Patrakov
Raymond Yau
2014-10-23 01:50:09 UTC
Permalink
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
Maybe it should be made clearer that the actual periods may differ
slightly from the default settings due to hardware constraints or rounding
issues, e.g. with your 5ms setting at 44100 Hz the period of 220.5 samples
is going to be rounded....
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
On devices that can use tsched, there is no problem.
---
man/pulse-daemon.conf.5.xml.in | 4 ++--
src/daemon/daemon-conf.c | 2 +-
src/daemon/daemon.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/
pulse-daemon.conf.5.xml.in
Post by Pierre-Louis Bossart
Post by Alexander E. Patrakov
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>
</section>
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b7a85aa..6dc15cf 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -96,7 +96,7 @@ static const pa_daemon_conf default_conf = {
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
- .default_fragment_size_msec = 25,
+ .default_fragment_size_msec = 5,
I've never understood why 4 fragments would be needed. Use 2 fragments
and 10ms periods...

For drivers can report hwptr only on period boundary, you cannot perform
any rewind safely when using two periods

This mean read/write must also in period size too

Even when driver can report hwptr position in every dma brust transfer, the
hwptr position still have an uncertainity of dma brust size
Raymond Yau
2014-10-23 03:05:53 UTC
Permalink
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible"
It is the hardware limitation affect the low latency,
this mean that pulseaudio have to select the maximum of lowest latency of
all the sinks / sources as default latency

viewpoint) would be to
Post by Alexander E. Patrakov
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
On devices that can use tsched, there is no problem.
diff --git a/man/pulse-daemon.conf.5.xml.inb/man/
pulse-daemon.conf.5.xml.in
Post by Alexander E. Patrakov
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>
Is it feasible to add an alternative parameter in fragment size since some
soc driver does not support disable period wakep but dma brust sizes
require 8 frames ?

https://bugs.freedesktop.org/show_bug.cgi?id=84585
Alexander E. Patrakov
2014-10-23 07:15:15 UTC
Permalink
Post by Raymond Yau
Is it feasible to add an alternative parameter in fragment size since
some soc driver does not support disable period wakep but dma brust
sizes require 8 frames ?
https://bugs.freedesktop.org/show_bug.cgi?id=84585
This bug report is so dirty that I cannot make any sense out of it. And
anyway, this would be a different patch.
--
Alexander E. Patrakov
Alexander E. Patrakov
2014-10-23 17:16:15 UTC
Permalink
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
I hereby withdraw the patch, as on IRC I see that Arun said:

"""
I'm not too happy with changing that. It would affect CPU on systems
that don't care about Wine.
and I really really don't want to work around bad clients in PA.
(despite the fact that I am also bitten by this bug)
...
Want to start a BrokenClients page?
"""

(note: due to the "cannot know" reason, I still disagree that it is a
client-side problem)
--
Alexander E. Patrakov
Arun Raghavan
2014-10-23 17:27:18 UTC
Permalink
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
"""
I'm not too happy with changing that. It would affect CPU on systems that
don't care about Wine.
and I really really don't want to work around bad clients in PA. (despite
the fact that I am also bitten by this bug)
...
Want to start a BrokenClients page?
"""
(note: due to the "cannot know" reason, I still disagree that it is a
client-side problem)
I've not looked at the Wine code for this, but I wonder if we can
guess this by looking at the minreq/tlength values that are returned.

-- Arun
Andrew Eikum
2014-10-23 18:08:16 UTC
Permalink
Post by Arun Raghavan
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
"""
I'm not too happy with changing that. It would affect CPU on systems that
don't care about Wine.
and I really really don't want to work around bad clients in PA. (despite
the fact that I am also bitten by this bug)
...
Want to start a BrokenClients page?
"""
It's true that Wine's audio doesn't get much work these days, though
in my defense :) it's a time issue, not a willingness issue.

I have spent literally weeks trying to understand and work around the
timing issues that cause problems with USB devices accessed with the
PulseAudio ALSA plugin. I plan to continue working on it, but business
priorities lay elsewhere at the moment and I've already spent loads of
time on it.
Post by Arun Raghavan
(note: due to the "cannot know" reason, I still disagree that it is a
client-side problem)
I've not looked at the Wine code for this, but I wonder if we can
guess this by looking at the minreq/tlength values that are returned.
I'd love to work with an ALSA/PA expert to come up with a solution,
either by fixing Wine or coming up with a new ALSA API to provide the
info we need.

I have a patch in-hand which improves the current driver
significantly, but it isn't enough to fix the USB devices problem. If
someone wants to review the winealsa driver with the patch applied and
discuss solutions, let me know. I'd love to get this problem solved.

Andrew
Alexander E. Patrakov
2014-10-23 18:38:16 UTC
Permalink
Post by Andrew Eikum
Post by Arun Raghavan
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
"""
I'm not too happy with changing that. It would affect CPU on systems that
don't care about Wine.
and I really really don't want to work around bad clients in PA. (despite
the fact that I am also bitten by this bug)
...
Want to start a BrokenClients page?
"""
It's true that Wine's audio doesn't get much work these days, though
in my defense :) it's a time issue, not a willingness issue.
I have spent literally weeks trying to understand and work around the
timing issues that cause problems with USB devices accessed with the
PulseAudio ALSA plugin. I plan to continue working on it, but business
priorities lay elsewhere at the moment and I've already spent loads of
time on it.
Post by Arun Raghavan
(note: due to the "cannot know" reason, I still disagree that it is a
client-side problem)
I've not looked at the Wine code for this, but I wonder if we can
guess this by looking at the minreq/tlength values that are returned.
I'd love to work with an ALSA/PA expert to come up with a solution,
either by fixing Wine or coming up with a new ALSA API to provide the
info we need.
I have a patch in-hand which improves the current driver
significantly, but it isn't enough to fix the USB devices problem. If
someone wants to review the winealsa driver with the patch applied and
discuss solutions, let me know. I'd love to get this problem solved.
If you send me the patch, I promise to have a look at it. But, see my
other reply why there cannot be a full solution within the ALSA API.
--
Alexander E. Patrakov
Andrew Eikum
2014-10-23 19:44:48 UTC
Permalink
Post by Alexander E. Patrakov
Post by Andrew Eikum
I have a patch in-hand which improves the current driver
significantly, but it isn't enough to fix the USB devices problem. If
someone wants to review the winealsa driver with the patch applied and
discuss solutions, let me know. I'd love to get this problem solved.
If you send me the patch, I promise to have a look at it. But, see
my other reply why there cannot be a full solution within the ALSA
API.
I've attached the patch here. It's been a while since I've worked on
this, so I'm fuzzy on the details. It should apply on any recent Wine
version, including today's.

There's a comment above alsa_write_data() describing how the buffer is
laid out and what the offsets point to. alsa_write_data() is where we
actually send data to ALSA. AudioClient_Stop() and _Start() are where
the stream is rewound and paused. AudioClient_Initialize() is where
the device setup occurs. AudioClock_GetPosition() returns the number
of played frames.

Note that we explicitly toggle handle_underrun to TRUE in
make_handle_underrun_config(). Toggling this off does seem to have an
impact on USB devices. The underruns aren't fixed in either setting,
but it's worth playing with.

If I remember correctly, the problem with USB devices is that
snd_pcm_avail_update() updates too infrequently. To keep low latency,
we set up a buffer size of four ALSA periods (about 40ms, I think).
But, snd_pcm_avail_update() updates less frequently than that, so we
constantly hit underruns. Some Windows applications behave very badly
with large latencies.

I think the issue was more complicated than that, but I've forgotten
the details in the meantime...

I believe disabling BATCH mode on USB devices "fixes" everything with
this patch applied, but I presume there was a reason it was introduced
in the first place (see PA bug 66962). I could be wrong here, I never
totally understood the issue.

There are two important programs that I test with:

-Any well-behaved dsound program (I use the "American McGee's Alice
Demo"; "Marble Arena 1" is another good test program.)

-Microsoft Games's Pinball (This uses winmm very abusively, with lots
of starts and stops. Good at testing latency.)

Once the driver behaves well on those two, I usually run it through
the rest of my audio application gauntlet to look for issues.

Happy for feedback on any part of the driver.

Thanks,
Andrew
Alexander E. Patrakov
2014-10-24 15:57:56 UTC
Permalink
Post by Andrew Eikum
Post by Alexander E. Patrakov
Post by Andrew Eikum
I have a patch in-hand which improves the current driver
significantly, but it isn't enough to fix the USB devices problem. If
someone wants to review the winealsa driver with the patch applied and
discuss solutions, let me know. I'd love to get this problem solved.
If you send me the patch, I promise to have a look at it. But, see
my other reply why there cannot be a full solution within the ALSA
API.
I've attached the patch here. It's been a while since I've worked on
this, so I'm fuzzy on the details. It should apply on any recent Wine
version, including today's.
I have looked at the patch, but have not tested it. I cannot say just by
reading the code whether this is an improvement. I think that the most
important thing here is the removal of the "keep no more than 3 ALSA
periods" logic.

Still, the patch was useful as it forced me to look at the buffering
logic in Wine.
Post by Andrew Eikum
There's a comment above alsa_write_data() describing how the buffer is
laid out and what the offsets point to. alsa_write_data() is where we
actually send data to ALSA. AudioClient_Stop() and _Start() are where
the stream is rewound and paused. AudioClient_Initialize() is where
the device setup occurs. AudioClock_GetPosition() returns the number
of played frames.
Note that we explicitly toggle handle_underrun to TRUE in
make_handle_underrun_config(). Toggling this off does seem to have an
impact on USB devices. The underruns aren't fixed in either setting,
but it's worth playing with.
As I said, the underruns happen because the pulse plugin provides
incorrect information about the actual period size to Wine.
Post by Andrew Eikum
If I remember correctly, the problem with USB devices is that
snd_pcm_avail_update() updates too infrequently. To keep low latency,
we set up a buffer size of four ALSA periods (about 40ms, I think).
But, snd_pcm_avail_update() updates less frequently than that, so we
constantly hit underruns. Some Windows applications behave very badly
with large latencies.
I think the issue was more complicated than that, but I've forgotten
the details in the meantime...
AFAICS we can confirm or disprove this by logging last_period_time.
Post by Andrew Eikum
I believe disabling BATCH mode on USB devices "fixes" everything with
this patch applied, but I presume there was a reason it was introduced
in the first place (see PA bug 66962). I could be wrong here, I never
totally understood the issue.
That bug is exactly what I am talking about.
--
Alexander E. Patrakov
Alexander E. Patrakov
2014-10-23 18:35:54 UTC
Permalink
Post by Arun Raghavan
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
"""
I'm not too happy with changing that. It would affect CPU on systems that
don't care about Wine.
and I really really don't want to work around bad clients in PA. (despite
the fact that I am also bitten by this bug)
...
Want to start a BrokenClients page?
"""
(note: due to the "cannot know" reason, I still disagree that it is a
client-side problem)
I've not looked at the Wine code for this, but I wonder if we can
guess this by looking at the minreq/tlength values that are returned.
Unpatched Wine just uses ALSA, so, your question is more about the ALSA
plugin.

Indeed, for native PulseAudio clients, it is possible to use
pa_stream_get_buffer_attr() once the stream is connected, and winepulse
patches indeed contain such call. The ALSA plugin does not call this
function. So, this is indeed part of the problem.

However, even if it did, I think this wouldn't fully help, for two reasons.

1. The plugin has already lied to the application about the permissible
range of the period sizes. Winepulse uses a test stream to know the
"correct" buffer metrics.

2. The buffer metrics, if I understand correctly, can change at any time
due to the stream being moved. There is no way to propagate the change
to the ALSA application. Winepulse does not reprobe the metrics, either
(well, it only connects the callback that dumps the changed values to
the log), so "please reprobe" does not look like a reasonable
requirement to be imposed on applications.

Due to the need to support dumb wrappers whose APIs do not support
dynamic buffer metrics, I think that, eventually, PulseAudio will just
have to support clients (including Wine) with wakeup frequency
requirements incompatible with those of the sound card.
--
Alexander E. Patrakov
Alexander E. Patrakov
2014-10-23 18:46:23 UTC
Permalink
Post by Alexander E. Patrakov
Post by Arun Raghavan
I've not looked at the Wine code for this, but I wonder if we can
guess this by looking at the minreq/tlength values that are returned.
Unpatched Wine just uses ALSA, so, your question is more about the ALSA
plugin.
Indeed, for native PulseAudio clients, it is possible to use
pa_stream_get_buffer_attr() once the stream is connected, and winepulse
patches indeed contain such call. The ALSA plugin does not call this
function. So, this is indeed part of the problem.
I have to correct myself. The ALSA plugin has no way to call this function.

This is because it needs to communicate the "correct" buffer metrics to
the program when returning from pulse_hw_params(). However, that
function only stores the buffer metrics, and, on return, there is no
stream yet. The stream is connected (and thus the buffer metrics are
known) in pulse_prepare(), i.e. much later than it would be needed to
communicate the actual metrics to the client.
--
Alexander E. Patrakov
David Henningsson
2014-10-24 06:06:15 UTC
Permalink
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
On devices that can use tsched, there is no problem.
On Ubuntu, since before my time, this has been the default:

default-fragments = 8
default-fragment-size-msec = 10

...so 8 x 10 = 80 ms. If you end up with 5 x 4 = 20 ms, I think that's a
bit too short/sensitive, we should then increase the number of periods
to 16 or at least 8 in the same go, so you'll end up with something
above 50 ms in total. I think this could help against underruns caused
by inoptimal scheduling.

I discussed this with Alexander briefly on Linuxcon, and I'm not opposed
to lowering the fragment-size parameter. I have not looked into the wine
DirectSound driver, but if it requires a period size of 10 ms, why does
not 10 ms work?

Also, how well does wine work with non-ALSA sinks, such as bluetooth,
tunnel sinks, etc?
Post by Alexander E. Patrakov
---
man/pulse-daemon.conf.5.xml.in | 4 ++--
src/daemon/daemon-conf.c | 2 +-
src/daemon/daemon.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index 8bd076d..ff54435 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -463,8 +463,8 @@ USA.
</option>
<option>
<p><opt>default-fragment-size-msec=</opt>The duration of a
- single fragment. Defaults to 25ms (i.e. the total buffer is thus
- 100ms long).</p>
+ single fragment. Defaults to 5ms (i.e. the total buffer is thus
+ 20ms long).</p>
</option>
</section>
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b7a85aa..6dc15cf 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -96,7 +96,7 @@ static const pa_daemon_conf default_conf = {
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
- .default_fragment_size_msec = 25,
+ .default_fragment_size_msec = 5,
.deferred_volume_safety_margin_usec = 8000,
.deferred_volume_extra_delay_usec = 0,
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 5b20130..3d758cd 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -85,7 +85,7 @@ ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl
; default-channel-map = front-left,front-right
; default-fragments = 4
-; default-fragment-size-msec = 25
+; default-fragment-size-msec = 5
; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
Alexander E. Patrakov
2014-10-24 06:47:27 UTC
Permalink
Post by David Henningsson
Post by Alexander E. Patrakov
Of course, this only applies to ALSA devices that can't use tsched, as
well as to OSS on more exotic platforms.
This is needed for compatibility with Wine games that use DirectSound8
on distributions such as Arch Linux who don't accept the unofficial
winepulse patch. The reason is that Wine DirectSound8 emulation requests
a period of 10 ms and expects it to work for the purposes of timing. And
in fact, it cannot know (via ALSA API) that it is not going to work!
A known malware-free test application is Foobar2000 version 1.2. Later
versions no longer use DirectSound.
This issue is not going to be fixed on the Wine side, because the audio
subsystem in Wine is not really maintained, and the maintainer has
already privately expressed some negative thoughts about the state of
the linux audio ecosystem in general.
The correct solution (at least from the "isolate the clients from
hardware limitations as thoroughly as possible" viewpoint) would be to
consume audio from sink inputs using a timer if the actual sink does not
provide sufficiently small minreq. In other words, adapt tsched to BATCH
cards and drop non-tsched. But that's a whole project. So, as a stopgap
solution for running Wine games on e.g. USB audio (which is a topic that
pops up regularly on #pulseaudio IRC channel), let's reduce the default
fragment size to a value suitable for unpatched Wine.
Regarding the value: on my system, for mp3 playback through Foobar2000,
8ms fragments work, 9ms fragments result in constant underruns.
Wine wiki recommends 5ms.
On devices that can use tsched, there is no problem.
default-fragments = 8
default-fragment-size-msec = 10
...so 8 x 10 = 80 ms. If you end up with 5 x 4 = 20 ms, I think that's a
bit too short/sensitive, we should then increase the number of periods
to 16 or at least 8 in the same go, so you'll end up with something
above 50 ms in total. I think this could help against underruns caused
by inoptimal scheduling.
I have to test this before accepting or rejecting the proposal. Will do
that later today.
Post by David Henningsson
I discussed this with Alexander briefly on Linuxcon, and I'm not opposed
to lowering the fragment-size parameter. I have not looked into the wine
DirectSound driver, but if it requires a period size of 10 ms, why does
not 10 ms work?
I don't really know, and I now think that the "10 ms fragment" theory is
not the whole story. In fact, two periods 16 ms each work. I need more
experiments.
Post by David Henningsson
Also, how well does wine work with non-ALSA sinks, such as bluetooth,
tunnel sinks, etc?
Bluetooth marginally works (i.e. works acceptably well at small
distances like 2m, but has some dropouts at 4m) right now, but becomes
broken if one applies this patch:

http://permalink.gmane.org/gmane.comp.audio.pulseaudio.general/20763

I have not tested tunnel sinks yet.
--
Alexander E. Patrakov
Raymond Yau
2014-10-24 07:10:35 UTC
Permalink
Post by David Henningsson
default-fragments = 8
default-fragment-size-msec = 10
...so 8 x 10 = 80 ms. If you end up with 5 x 4 = 20 ms, I think that's a
bit too short/sensitive, we should then increase the number of periods to
16 or at least 8 in the same go, so you'll end up with something above 50
ms in total. I think this could help against underruns caused by inoptimal
scheduling.
5ms will be too low for those sound card with .periods_max=2
Alexander E. Patrakov
2014-10-24 08:53:26 UTC
Permalink
Post by David Henningsson
default-fragments = 8
default-fragment-size-msec = 10
...so 8 x 10 = 80 ms. If you end up with 5 x 4 = 20 ms, I think that's a
bit too short/sensitive, we should then increase the number of periods
to 16 or at least 8 in the same go, so you'll end up with something
above 50 ms in total. I think this could help against underruns caused
by inoptimal scheduling.
Unfortunately, what seems to matter (contrary to my initial mail) is the
total buffer size, which needs to be less than 34 ms. I don't know where
this magic number comes from.

4 fragments 5 ms each = works
4 fragments 8 ms each = works
4 fragments 9 ms each = does not work
2 fragments 16 ms each = works
3 fragments 16 ms each = does not work
3 fragments 11 ms each = works
3 fragments 12 ms each = does not work
2 fragments 17 ms each = does not work
6 fragments 5 ms each = works
7 fragments 5 ms each = does not work
--
Alexander E. Patrakov
Raymond Yau
2014-10-25 09:06:41 UTC
Permalink
Post by Alexander E. Patrakov
Post by David Henningsson
default-fragments = 8
default-fragment-size-msec = 10
...so 8 x 10 = 80 ms. If you end up with 5 x 4 = 20 ms, I think that's a
bit too short/sensitive, we should then increase the number of periods
to 16 or at least 8 in the same go, so you'll end up with something
above 50 ms in total. I think this could help against underruns caused
by inoptimal scheduling.
Unfortunately, what seems to matter (contrary to my initial mail) is the
total buffer size, which needs to be less than 34 ms. I don't know where
this magic number comes from.
Post by Alexander E. Patrakov
4 fragments 5 ms each = works
4 fragments 8 ms each = works
4 fragments 9 ms each = does not work
2 fragments 16 ms each = works
3 fragments 16 ms each = does not work
3 fragments 11 ms each = works
3 fragments 12 ms each = does not work
2 fragments 17 ms each = does not work
6 fragments 5 ms each = works
7 fragments 5 ms each = does not work
--
At this exrteme low latency, rewind become un necessary since your ear
won't distinguish this small difference

Loading...