I've tried multiple example programs that appear to have code to handle xruns under playback:
<a href="https://albertlockett.wordpress.com/2013/11/06/creating-digital-audio-with-alsa/" rel="nofollow noreferrer">https://albertlockett.wordpress.com/2013/11/06/creating-digital-audio-with-alsa/</a>
<a href="https://www.linuxjournal.com/article/6735" rel="nofollow noreferrer">https://www.linuxjournal.com/article/6735</a> (listing 3)
When using snd_pcm_writei(), it appears that when the return value is -EPIPE (which is xrun/underrun), they do:
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:
<blockquote>
Prepare PCM for use.
</blockquote>
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="https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html" rel="nofollow noreferrer">https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html</a>
<blockquote>
SND_PCM_STATE_XRUN
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.
</blockquote>
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?
<a href="https://albertlockett.wordpress.com/2013/11/06/creating-digital-audio-with-alsa/" rel="nofollow noreferrer">https://albertlockett.wordpress.com/2013/11/06/creating-digital-audio-with-alsa/</a>
<a href="https://www.linuxjournal.com/article/6735" rel="nofollow noreferrer">https://www.linuxjournal.com/article/6735</a> (listing 3)
When using snd_pcm_writei(), it appears that when the return value is -EPIPE (which is xrun/underrun), they do:
Code:
if (rc == -EPIPE) {
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
}
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:
<blockquote>
Prepare PCM for use.
</blockquote>
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="https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html" rel="nofollow noreferrer">https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html</a>
<blockquote>
SND_PCM_STATE_XRUN
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.
</blockquote>
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?