How to properly handle xrun in ALSA programming when playing audio with snd_pcm_writei()?


Staff member
I've tried multiple example programs that appear to have code to handle xruns under playback:

<a href="" rel="nofollow noreferrer"></a>

<a href="" rel="nofollow noreferrer"></a> (listing 3)

When using snd_pcm_writei(), it appears that when the return value is -EPIPE (which is xrun/underrun), they do:

if (rc == -EPIPE) {
  /* EPIPE means underrun */
  fprintf(stderr, "underrun occurred\n");

I.e. call snd_pcm_prepare() on the handle.

However, I still get stuttering when I attempt to run programs like these. Typically, I will get at least a few, to maybe half a dozen xrun, and then it will play smoothly and continuously without further xruns. However, if I have something else using the sound card, such as Firefox, I will get many more xruns, and sometimes only xruns. But again, even if I kill any other program that uses the sound card, I still experience the issue with some initial xruns and actual stuttering on the speakers.

This is not acceptable for me, how can I modify this type of xrun handling to prevent stuttering?

My own attempt at figuring this out:

From the ALSA API, I see that snd_pcm_prepare() does:

Prepare PCM for use.

This is not very helpful to an ALSA beginner like myself. It is not explained how this can be used to recover xrun issues.

I also note, from: <a href="" rel="nofollow noreferrer"></a>

The PCM device reached overrun (capture) or underrun (playback). You can use the -EPIPE return code from I/O functions
(snd_pcm_writei(), snd_pcm_writen(), snd_pcm_readi(), snd_pcm_readn())
to determine this state without checking the actual state via
snd_pcm_state() call. It is recommended to use the helper function
snd_pcm_recover() to recover from this state, but you can also use
snd_pcm_prepare(), snd_pcm_drop() or snd_pcm_drain() calls.

Again, it is not clear to me. I can use snd_pcm_prepare() OR I can use these other calls? What is the difference? What should I use?