Skip to content

Fixing ALSA underrun death spiral and PulseAudio buffer clamping#239

Draft
f1nalspace wants to merge 1 commit into
duncanthrax:masterfrom
f1nalspace:fix/unix-receiver-underrun-and-pulse-buffer
Draft

Fixing ALSA underrun death spiral and PulseAudio buffer clamping#239
f1nalspace wants to merge 1 commit into
duncanthrax:masterfrom
f1nalspace:fix/unix-receiver-underrun-and-pulse-buffer

Conversation

@f1nalspace

Copy link
Copy Markdown

Issues

  • Breaks sound server playback (PireWire, PulseAudio, ALSA)
  • PipeWire/PulseAudio audio buffer underrun
  • Playing random noises not recovering without a full service restart

Bugfixes

ALSA:

  • After snd_pcm_set_params, override sw_params to set start_threshold to period_size instead of buffer_size. The default causes ~200ms of silence after every underrun recovery, during which PipeWire fires again and triggers another underrun — a death spiral.
  • Set silence_size=buffer_size so ALSA auto-fills silence during brief packet gaps, preventing XRUN before snd_pcm_writei can be called.
  • Add snd_pcm_drop() before snd_pcm_close() to prevent hang on close.
  • Use continue instead of return 0 after snd_pcm_recover so the current packet is retried rather than dropped.

PulseAudio:

  • On format change, recalculate maxlength with the updated sample spec before recalculating tlength. Previously maxlength was set at init with the 44100 S16LE placeholder and never updated; after switching to 48kHz S32LE, tlength > maxlength, so PA silently clamped the effective buffer to ~46ms instead of the requested latency — causing the same underrun spiral.

ALSA:
- After snd_pcm_set_params, override sw_params to set start_threshold
  to period_size instead of buffer_size. The default causes ~200ms of
  silence after every underrun recovery, during which PipeWire fires
  again and triggers another underrun — a death spiral.
- Set silence_size=buffer_size so ALSA auto-fills silence during brief
  packet gaps, preventing XRUN before snd_pcm_writei can be called.
- Add snd_pcm_drop() before snd_pcm_close() to prevent hang on close.
- Use continue instead of return 0 after snd_pcm_recover so the current
  packet is retried rather than dropped.

PulseAudio:
- On format change, recalculate maxlength with the updated sample spec
  before recalculating tlength. Previously maxlength was set at init
  with the 44100 S16LE placeholder and never updated; after switching
  to 48kHz S32LE, tlength > maxlength, so PA silently clamped the
  effective buffer to ~46ms instead of the requested latency — causing
  the same underrun spiral.
@f1nalspace f1nalspace marked this pull request as draft April 28, 2026 17:06
@f1nalspace

Copy link
Copy Markdown
Author

The problem was gone for a while, but now even with all those fixes, the noises are back - especially when i play a video on my host and install stuff in the VM that plays system sounds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant