ValveSoftware / ValveSoftware/SteamOS

Desktop (non-Steam-Deck) hardware: HDMI audio buffer drains at a constant rate under load, causing repeated dropouts

Open
#2,818 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
2.6k
Forks
83
Avg merge
4m
Merged PRs (30d)
3

Description

Your system information
  • Steam client version: 1788652215
  • SteamOS version: 3.8.16 (BUILD_ID 20260716.1)
  • Opted into Steam client beta?: No (default channel; client reports steamdeck_stable)
  • Opted into SteamOS beta?: No (stable branch)
  • Have you checked for updates in Settings > System?: Yes — steamos-update check reports no update available

Hardware (desktop, not a Steam Deck):

  • Motherboard: Gigabyte B850I AORUS PRO
  • CPU: AMD Ryzen 5 7500X3D (6C/12T)
  • GPU: AMD Navi 48 [Radeon RX 9070 XT] 1002:7550 rev c0, Sapphire 1da2:e491, PCI 03:00.0, amdgpu
  • Kernel: 6.16.12-valve24.5-1-neptune-616-gb2f7cfe85e45
  • Mesa 25.3.0.213835 / vulkan-radeon 26.0.0_devel.214837.steamos
  • PipeWire 1.6.4, WirePlumber 0.5.14-1.4
  • Audio: HDMI to Samsung QN90D — HDA ATI HDMI Digital Stereo (HDMI 4), profile hdmi-stereo-extra3, 2ch/48000 Hz
  • Hardware profile matched: hardware-profiles/default (no Valve Deck profile applies)
  • GPU tuning: 280 W power limit via LACT, no undervolt (so the Overdrive flag is set)
Please describe your issue in as much detail as possible:

Expected: HDMI audio plays continuously without dropouts.

Actual: Repeated audible dropouts that get worse the longer audio runs. Not specific to one title — it happens across most games (Gothic 1 Remake, Steam app 1297900, was used for measurements), and is also reproducible with speaker-test and browser video. Audio does not recover on its own; systemctl --user restart wireplumber clears it until the problem re-accumulates.

The measurement. Sampling /proc/asound/card0/pcm9p/sub0/status once per second during playback shows the ALSA buffer draining at a constant rate and refilling in a sawtooth. Each time it approaches empty, audio drops out.

Healthy (idle desktop, quantum 8192): delay ~10000–12000 frames (~220 ms buffered).

During gameplay at quantum 512 (the SteamOS default):

delay: 984 → 898 → 793 → 691 → 606 → 519 → [refill] → 926 → 832 → 746 ...

During gameplay at quantum 2048 (raised via user config):

delay: 1947 → 1803 → 1698 → 1591 → 1479 → 1376 → 1254 → 1151 → 1043 → [refill]

The drain rate is about 110 frames/second in both cases — roughly a 0.23% rate error against the 48000 Hz clock. Quadrupling the quantum quadrupled the cushion but did not change the drain rate, so the interval between dropouts scaled proportionally while the underlying behaviour stayed identical. That points at a rate mismatch rather than insufficient buffering.

Nothing in the stack reports an error. The stream stays state: RUNNING with no XRUN flag. pw-top shows ERR 0 on every node with WAIT 3.6us / BUSY 8.2us against a multi-millisecond period. No kernel message, no WirePlumber error, no node error state.

Three configuration differences from Deck hardware look relevant:

  1. hardware-profiles/default sets default.clock.quantum = 512 (~10.7 ms), with the filter-chain instance additionally capped at max-quantum = 1024. Reasonable for a Deck; very little margin on this system.
  2. Every Valve profile (valve-jupiter, valve-galileo, valve-fremont) sets session.suspend-timeout-seconds to 3600 or 0. hardware-profiles/default sets no override, so the 5-second default from suspend-node.lua applies. (Worked around locally; did not fix the dropouts.)
  3. The loopback sink that all audio traverses carries resample.disable = "true". With resampling disabled there is no mechanism to correct the rate error above. This could not be overridden: monitor.alsa.rules does not match the loopback for this property (it does match for session.suspend-timeout-seconds), and pw-cli set-param returns an empty Props object, so it is not runtime-settable.

The monitorNodeError patch never engages. SteamOS patches scripts/monitors/alsa.lua (diff against the retained alsa.lua.orig) to set the device profile Off and restore it after one second when a node enters the error state. None of its log lines (Error received on ALSA node, Profile set to Off, Restored profile) ever appear — the node never enters an error state, so this recovery path does not detect this failure mode.

Also observed: ~/.local/share/Steam/logs/steamui_audio.txt shows the sink pair being removed and re-added repeatedly, with a short-lived sink in a separate ID range in between:

12:49:50  SinkRemoved: 236 / 237
12:49:50  SinkAdded: 1048893
12:49:51  SinkAdded: 332 / 333
12:49:51  SinkRemoved: 1048893

Repeats at 12:55:54 and 12:56:46. Caveat: several WirePlumber restarts were done manually while investigating and would produce identical entries, so not every occurrence is spontaneous. Included as an observation, not a conclusion.

Ruled out, with evidence:

  • GPU instability — an unstable undervolt was causing separate hard lockups; removing it eliminated the crashes entirely while the dropouts continued unchanged. No gpu reset, ring timeout, page fault or Oops in any kernel log.
  • HDMI link / renegotiation/proc/asound/card0/eld#* shows monitor_present 1, eld_valid 1, full SAD list for the QN90D. aplay -l shows the endpoint on device 9. No re-probe or reset near any failure.
  • Wrong endpointpcm9p/sub0/status confirms device 9 (the QN90D) is the one RUNNING during playback.
  • Kernel HDA power savingsnd_hda_intel power_save=0 and power_save_controller=N set at runtime; dropouts continued.
  • Realtime schedulingps -Lo shows data-loop.0 running RR at priority 20; rtkit grants priority at service start.
  • Configured sample rate mismatchclock.rate, clock.allowed-rates and both context-properties files all agree on 48000.
  • Node idle suspendsession.suspend-timeout-seconds = 0 applied and verified on both sinks via wpctl inspect; dropouts continued.
  • CPU pressure / underrunpw-top shows ERR 0 and microsecond processing times; no XRUN flag is ever set.
  • Front-panel HD Audio header — the onboard USB-attached codec sits at Active Profile: off with both output ports not available; it is not in the audio path. (It is the source of the unrelated [Mic2] Invalid JackControl index value log spam.)

Workarounds attempted:

Change | Result -- | -- default.clock.quantum = 2048 via ~/.config/pipewire/pipewire.conf.d/ | Partial — roughly doubles the time between dropouts, does not stop them Same for the filter-chain instance | No further change session.suspend-timeout-seconds = 0 on both sinks | Applied and verified; no effect resample.disable = false on the loopback | Not applicable from user config or at runtime; untested as a result wpctl set-default to the hardware sink, bypassing the loopback | Broke game launching and produced duplicate output devices in the Steam UI; reverted systemctl --user restart wireplumber | Reliable temporary recovery

Not tested: whether this reproduces on Steam Deck hardware; whether a non-HDMI output on this machine drifts the same way (no alternative output was available); whether enabling resampling on the loopback would correct the drift; whether the drift rate varies with GPU load specifically or only with elapsed playback time.

Related but distinct: #2627 is an HDMI handshake failure after idle/wake, AV-receiver-specific and not reproducible direct-to-TV. #946 is Deck-docked glitching resolved by disabling WiFi power management. #926 is a 2022 report on a long-superseded build. None describes a constant-rate drain on desktop hardware using the default profile.

Suggested direction: the measured rate error is small and constant, which is what adaptive resampling normally corrects — but the loopback node all audio traverses has resampling disabled and this cannot be changed from user configuration. If that is deliberate for Deck hardware it may be worth revisiting for the default profile, or making the property overridable. Separately, the default profile inherits neither the suspend-timeout overrides nor any quantum tuning suited to desktop hardware; 512 frames leaves very little margin on a system driving 4K output under gaming load.

Steps for reproducing this issue:
  1. Install SteamOS on desktop hardware (so hardware-profiles/default is matched rather than a Valve Deck profile) with audio output over HDMI to a TV.
  2. Start any game — Gothic 1 Remake (app 1297900) was used here, but most titles reproduce it — and let audio play continuously for several minutes. Dropouts become noticeable within a few minutes and progressively worse.
  3. While audio is playing, sample the PCM status once per second and watch delay decay and refill in a sawtooth rather than holding steady:
   while true; do echo "--- $(date +%T)"; cat /proc/asound/card0/pcm9p/sub0/status; sleep 1; done

(Adjust pcm9p to whichever device is RUNNING — check with cat /proc/asound/card0/pcm*p/sub0/status.) 4. systemctl --user restart wireplumber restores normal audio until the drift re-accumulates.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the HDMI dropout on the default profile and sampling /proc/asound/card0/pcm9p/sub0/status during playback. Review hardware-profiles/default, scripts/monitors/alsa.lua, suspend-node.lua, and the monitor.alsa.rules behavior around loopback resampling and quantum settings. Done means sustained HDMI playback no longer shows a constant buffer drain or repeated dropouts under the reported workload.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux
Domain
audio-video-rtc, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.