On Sat Jan 24 08:53:09 2026 +0000, Dzmitry Keremsha wrote:
The game does not underfill, I added a log that shows held_bytes, pa_held and adv_bytes. Note that I added it right after adv_bytes calculation. The point is, held_bytes never dips to zero, and adv_bytes isn't braking. I genuinely do not understand how that makes sense though. I also tested with the commit reversed, also crackles. Attaching both logs. Changing quant used to help (I'd get audio issues only maybe 15-20 minutes in), but it still wouldn't solve all issues. I tested Arc Raiders and Zenless Zone Zero. I think my suspicions about write pointer stepping over read pointer were correct. I attached the Zenless log, there were no underflows at the time of buzz (it is right at the very end, I turned the game off as soon as the buzz ended). Also ignore the first 3 underflows, they happened during launch. Overflow has to do with held_bytes dipping below pa_held_bytes, but I don't fully understand the relationship. The problem is that the server audio consumption is slower than adv_bytes movement. But shouldn't there be a resampler on the server side to maintain an equilibrium? Because right now it looks like a catch-22, you can get steady pointer advancement with write stepping over read, or you can throttle adv_bytes and get mathematecally guaranteed ram buffer overfill. Or, like in my code, inconsistent NtSetEvent. Of course, none of the options sound right. I am not familiar with winealsa's logic, but maybe we can take an inspiration from there, since it's very stable? [pulse-logs.tar.gz](/uploads/35c45ffa35f3e0bc408d4dfb1cd6df80/pulse-logs.tar.gz) Looked at what winealsa does, it seems the logic there is similar to my "safe_bytes" logic. If the audio server is slow - throttle pointer advancement. Since NtSetEvent is consistent, it eventually leads to full buffer RAM and denied refills. I guess this is okay? I don't know where this data goes then, but it never sounds like a part of audio is missing.
It was easy to implement it with 5x timer polling without breaking anything, every tick add +1 to a counter, every 5 ticks (so exactly once per period) fire NtSetEvent. Unless the stream held and pa_held equal 0 (the stream just started), then fire immediately. Passes tests, doesn't crackle, and unless I misunderstand something, looks exactly like winealsa to the game. Attaching a winealsa log with some additional logs from me so it's clear when a refill is missed. [honkai-winealsa.tar.gz](/uploads/c12ab1c11a1c36e7cf3bd784ec5bdf43/honkai-winealsa.tar.gz) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9840#note_127927