High latency for Canberra notification sounds, poor handling of unset and high latencies
- PipeWire version (
pipewire --version
): >0.3.41, latest dbe61af5 (from modified AUR package), with a wireplumber-git 22fd429 (a few days old) - Distribution and distribution version (
PRETTY_NAME
from/etc/os-release
): Arch Linux - Desktop Environment: KDE Plasma X11
- Kernel version (
uname -r
): 5.15.7-zen1-1-zen
Description of Problem:
When I close an unsaved tab in Sublime Text or run canberra-gtk-play -i dialog-warning
in a terminal (AKA play a sound using Canberra, producing a high-quantum/latency stream), with no other audio playing, there's a long delay before the next sound (eg. closing the tab twice, running canberra-gtk-play
twice) plays. Canberra sets an output quantum of 8192 samples; I measured a latency of up to 600ms.
While the Canberra sound is playing, when I change the speaker volume in plasmashell, the "volume changed" sound (an unset-quantum stream) plays with a long delay. After the Canberra sound ends, the next "volume changed" sound also plays with a long delay. After the delay ends, subsequent sounds have little delay.
While the Canberra sound is playing, or after it ends, trying to start any stream (including a low-quantum or unset-quantum one) produces a long delay before it starts.
How Reproducible:
Always
Steps to Reproduce:
- Open Sublime Text. Type something into a file, and close the tab. This pops up an unsaved changes message, and (on KDE, not Xfce) plays a notification sound using a Canberra stream with quantum 16384 frames.
- Run
canberra-gtk-play -i dialog-warning
in a terminal. This plays a notification sound using a Canberra stream with quantum 8192 frames.phone-incoming-call
is a longer sound, andaudio-volume-change
is a shorter sound which is completely inaudible (#1549 (closed)). - Scroll the mouse wheel on plasmashell's volume icon. This plays a volume-change sound using a Canberra stream with quantum unset. The sound played is
audio-volume-change
, except it's actually audible this time. - Open Audacious (I'm using the ALSA backend with pipewire-alsa), and start/stop/play/pause playback. On my system, it's using a quantum of 3000 frames.
- Mix and match these steps.
Actual Results:
See "Description of Problem" for visible effects. pw-top shows what's going on under the hood.
Sublime Text (quantum 16384) and canberra-gtk-play
(quantum 8192) set the motherboard output device to the maximum default.clock.max-quantum
of 8192 frames. The first sound isn't delayed much, but playing the same sound again has a heavy delay: canberra-gtk-play.txt
-
By recording my room audio in a mic on my phone, and repeatedly closing a Sublime Text tab, I've measured up to 0.6 seconds(!) of latency between clicking X on a Sublime Text tab (or pressing Enter on
canberra-gtk-play -i dialog-warning
), and hearing a sound. At my sampling rate of 48000 Hz, this is over 24000 frames of audio. When I force PipeWire's quantum to 256 samples (by launchingPIPEWIRE_LATENCY=256/48000 audacious
in the background), Sublime Text's notification sound is practically instant (slightly variable but I'd estimate <100ms) after I click the mouse. (In both cases, there's a bit of latency from resampling Canberra's 44100 Hz stream to 48000 Hz system output. In my experience, sinc resamplers add on the order of 48 samples = 1ms of latency.) -
When I run
while true; canberra-gtk-play -i dialog-warning; end
in fish shell, then there's a substantial gap between adjacent sounds. The sounds play more often if I runPIPEWIRE_LATENCY=256/48000 audacious
in the background (Audacious must be set to ALSA -> pipewire-alsa).
plasmashell's volume change sound (quantum unset) sets motherboard output device to 1024 frames, probably taken from default.clock.quantum
: plasmashell_volume_change.txt. But if you play plasmashell sounds while a Sublime Text or canberra-gtk-play
sound is active, plasmashell's sounds also plays at a quantum of 8192 frames: canberra_plus_plasmashell.txt
If the output device's current quantum is high, then starting a stream has delayed sound even if the new stream has a lower quantum, since PipeWire waits for the hardware to finish playing the previous buffer (doesn't rewind the ALSA output).
After a sound finishes playing (even if the stream/node are destroyed), the output device remains at the last active quantum: last_latency_64.txt, last_latency_8192.txt
Expected Results:
I think pipewire's current buffer size system results in undesirable behaviors, and should be improved.
As a user, it's confusing that plasmashell's volume-change sounds can play at an abnormally high quantum/latency, because there's already a stream playing with a high quantum. One solution is to make streams with unset quantum set the output's quantum to default.clock.quantum
, even if other streams are playing at a higher quantum.
Additionally I dislike how a high-quantum notification sound can cause later sounds to take a long time to begin playing. One solution is to decrease default.clock.max-quantum
to match default.clock.quantum
= 1024, or set it to 2048 or so, so the maximum quantum which can be induced this way is around 40ms rather than 170ms (though I've observed audio latencies higher than 2x the quantum). Another solution is to implement rewinding like PulseAudio. Unfortunately, PulseAudio rewinding is incompletely documented (link), and seems to have unresolved bugs which have been open for 9 years (which may even be too complex to reasonably fix, IDK).
Additionally, when all audio streams have finished playing, perhaps PipeWire should reset the output quantum to default.clock.quantum
? Currently it keeps the quantum of the last active stream (which may be below 256, or up to 8192), which results in PipeWire taking an unpredictable time for the next stream to start playing.
Notes on PulseAudio rewinding:
https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Rewinding/
Rewinding is mostly used for making changes in the audio hearable as quickly as possible. For example, if volume changes, the change should be hearable immediately.
I performed some testing in pipewire-pulse:
- Changing plasmashell's volume level is audible immediately, even if the actual "volume changed" sound is delayed. I suspect this is because changes in global volume level actually reconfigure ALSA hardware volume/gain levels, which is instant, unlike changing what gets written to the next buffer and played.
- Opening pavucontrol-qt and changing the volume of "System Sounds" doesn't affect the volume of running sounds at all, even when running
PIPEWIRE_LATENCY=256/48000 audacious
in the background and playing 1-second-long sounds (while true; canberra-gtk-play -i phone-incoming-call; end
). - Pressing Ctrl+C on
canberra-gtk-play
takes a short delay for the sound to stop, quicker than the long audio startup delay. (Audio stopping is instant if you have pavucontrol-qt running, which sets the latency to 1024.)
BUG: That buffer is not currently taken into account when rewinding (https://bugs.freedesktop.org/show_bug.cgi?id=53911).
BUG: Currently this is broken (https://bugs.freedesktop.org/show_bug.cgi?id=53709).
Both of these bugs were moved to GitLab where they remain open. There's 22 "BUG:" occurrences in total, though many point to the same bug.
Additional Info (as attachments):
-
pw-dump > pw-dump.log
: pw-dump.log taken while runningwhile true; canberra-gtk-play -i phone-incoming-call; end
and scrolling my mouse wheel over the plasmashell volume icon (to play theaudio-volume-change
sound rapidly)
Possibly related: #1436 (closed)