On Sat May 2 00:31:07 2026 +0000, Paul Gofman wrote:
An interesting discovery is that with the default pipewire-pulse quant of 256 (as of the new default in PipeWire 1.6) and PULSE_LATENCY_MSEC=60 the mmdevapi period is 15ms. Pulse latency should be \<10ms for Wine to work correctly, anything \>10ms is de-facto broken now. It is not about crackling in the first place, currently mmdevapi effectively sets minimum period to max(10ms, pulse latency). It can't force lower (unless we are going to implement a separate data feed thread for pulse decoupled from application data consuming thread). On Windows min period is always \~10ms and anything bigger outright breaks some games (make them crash) or may induce audio problems in other. The way is to avoid ever setting pulse latency \>10ms (\~3ms is probably a goo dstarting poin), I think there is no reason to have higher pulse latencies. I know people sometimes try to work around some problems this way but for Wine that is just broken. The pattern looks like this - winepulse timer is mostly in lockstep with the real time (by which I assume PipeWire). Sometimes, however, the audio server would consume less than it received, indicating that winepulse was a bit too fast. Since we don't have a throttling mechanism, we are now permanently ahead of reality. Wait long enough and the pointers would overlap and therefore it will crackle. If there is a slow time drift I'd expect it to lead to starvation or dropping buffer data once in that mentioned 30 minutes and then things to work just fine for another 30 minutes. The current way is supposed to effectively sync-time, possibly with data drop once in a while but that would be hard to notice. If that doesn't happen with the suitable pulse parameters (latency \< 10ms) maybe there is some other issue with implicit time catch up logic and we should be fixing that one. It is also possible that the issue is related to specific games which misbehave on Wine due to some incompatibility not even related to pulse timing. Then, does those affected games use mmdevapi directly even, or the issue might in fact be in, say, xaudio or dinput? \\>So as we can see, with the current winepulse timer implementation and without some sort of a throttling mechanism crackling is inevitable, be it in 10 minutes or 10 hours, at least on the hardware I tested. Well, I don't quite see that from the existing info. Maybe it worth opening Wine bug ticket with detailed repro instructions, which would describe the issue with specific game and reproduced with upstream Wine, along with pulse customization details (and provided latency is \<10ms). If it is reproducible only with official Proton, a proper place for that is Proton github issue tracker (reproducing and attaching PROTON_LOG=+pulse,+mmdevapi,+xaudio2,+dsound , strictly using official Proton and not downstream modifications). To explain things better and as to why my patch is necessary with the timer drift:
1. Timer drift means that wine mmdevapi is slightly faster than pipewire (which is the real time), so the rate of refill is higher than the rate of consumption. 2. pa_held_bytes balloons because on average we, for instance, refill 480 frames and consume 479. Held bytes, as you can see from the log, is consistent, it does not deviate from the margins of it's refill and drain long-term 3. pa_held_bytes grows infinitely -\> held bytes is the same -\> game thinks we have space for 500 frames, we have space for 30. Result - the game would refill it's usual 480 (an example) frames and we have an overlap of 450 frames - sounds like a crackle or static buzz. 4. pa_held_bytes is permanently high now, any overfill = crackle. You can see in that balatro log we have pa_held_bytes that is hovering around 0 and then after some point it stops (just look at the end of the log), as it got higher permanently. Please keep in mind it's happens even proper mmdevapi period so it's not about that. With my patch we never lie to the game - if we only have space for 30 frames, we are telling the game the truth, and hit backpressure which is the correct mechanism for that situation. Now if the wine mmdevapi timer is perfect, we would literally never hit the throttle, gain 480, spend 480, perfect equilibrium. Moreover, this mechanism is in alsa already. Ultimately the incorrect timer is what should be fixed, but the throttle is not harmful in any way. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10792#note_138634