mozilla / cubeb-pulse-rs

ISC License
15 stars 17 forks source link

Always uses the quantum limit unless setting PULSE_LATENCY_MSEC=22 or less, even when the minimum quantum is sufficient. Introduces uneccesary latency. #87

Open pallaswept opened 10 months ago

pallaswept commented 10 months ago

By default, if I run firefox, its quantum in pipewire will be the absolute upper limit set in pipewire's config. I can use the environment variable PULSE_LATENCY_MSEC when starting firefox, to set the quantum to the minimum setting in pipewire, and there are no xruns or dropouts whatsoever. Normally, the minimum should be used by default, and increased only to the maximum, to avoid xruns if necessary. In the case of firefox pulse, this is not what happens.

The result of this is an order of magnitude higher latency to and from firefox.

pallaswept commented 8 months ago

I made an interesting discovery regarding this:

I previously set the environment variable PULSE_LATENCY_MSEC=3, in order to avoid this bug and force the buffer/quantum in pipewire which I desired. This got me the 128 quantum I needed.

In an unrelated(? maybe spotify uses cubeb as its backend?) issue, I suggested using this environment variable to avoid this same behaviour in Spotify. Since I was suggesting latencies which were less demanding and more likely to work for the other users I was assisting, I suggested PULSE_LATENCY_MSEC=20 and PULSE_LATENCY_MSEC=10

I tested firefox with PULSE_LATENCY_MSEC=10, just to make sure I was giving correct syntax to the others in that issue, and saw that firefox was following the settings I had made in pipewire's configuration, and did NOT use a 10ms latency at all, rather, it used the 128 sample buffer which was specified in my pipewire configuration.

Just to be sure, I changed the pipewire config to instruct pulseaudio clients to request a 256 sample buffer, set the environment variable to PULSE_LATENCY_MSEC=10 (globally, it's set that way in my environment.d) and sure enough, firefox started and used the correct quantum/buffer size as per my pipewire config.

Just out of pure curiosity, I wondered if any other time for PULSE_LATENCY_MSEC would have the same effect, so I tried with PULSE_LATENCY_MSEC=8 firefox And sure enough, it used the 256 sample buffer as instructed by pipewire.

OK So What if I go higher? I tried 50, and it didn't obey pipewire's settings. 40, doesn't obey. 30, doesn't obey. 20, DOES obey. 25, doesn't, 23, doesn't, 21 DOES, 22 DOES.

So the TL;DR here is that if you set PULSE_LATENCY_MSEC=22 or anything less than 22, then the pipewire settings are adhered to, If you set anything from PULSE_LATENCY_MSEC=23 upwards, or not having it set at all, causes this bug.

I have to make an "illuminti confirmed" joke here

But it is completely bizarre that setting PULSE_LATENCY_MSEC to anything less than 23ms, works as it should and follows pipewire's configuration. Anything 23 or above, or not setting that environment variable at all, ignores pipewire's configuration and pushes the buffer all the way to the quantum limit.

pallaswept commented 7 months ago

Further discovery of this issue:

If you set PULSE_LATENCY, it seems to be ignored entirely, however....

If you set PULSE_LATENCY_MSEC, and also set PULSE_LATENCY, then the nodes will use the value of PULSE_LATENCY, for example, if you set PULSE_LATENCY_MSEC=3 with a sample rate of 48000Hz, and set PULSE_LATENCY=256/48000, then the nodes will request a quantum of 256.

However, this only works if PULSE_LATENCY is greater than the millisecond value of PULSE_LATENCY_MSEC. Using the above example, if you set PULSE_LATENCY_MSEC=3 with a sample rate of 48000Hz, and set PULSE_LATENCY=128/48000, then the nodes will request a quantum of 144 (3 milliseconds). If you set PULSE_LATENCY_MSEC=2 with a sample rate of 48000Hz, and set PULSE_LATENCY=128/48000, then the nodes will request a quantum of 128 (2.6` ms)

This also applies to rules set within pipewire's configuration files - if you have PULSE_LATENCY_MS set lower than the value set by the rules, then it will work, otherwise the rule will be ignored.

Accordingly, it seems that the best (only) way to control the quantum of firefox's cubeb-pulse-rs, is to set PULSE_LATENCY_MS=1 (would 0 work?) and set PULSE_LATENCY or pipewire rules, to the desired value(s)