ALSA snd_pcm_writei() unexpected underrun

I do not know if it is hardware-related, but I am going mad about spurious underrun errors on snd_pcm_writei() calls. The same code runs without issues on my laptop.

I use a blocking setup:

snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);

Here is the snd_pcm_dump_sw_setup() output:

  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1764
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 3528
  silence_threshold: 0
  silence_size : 0
  boundary     : 1849688064

While setting the hardware parameters, I log the results of the snd_pcm_hw_params_set_rate_near(), snd_pcm_hw_params_set_periods_near(), snd_pcm_hw_params_set_period_size_near() calls:

3719.1287 D [AlsaSound] SOUND: setupWithFreq sampling rate: 44100, dir: 0
3719.1288 D [AlsaSound] SOUND: number of periods: 2, dir: 0
3719.1289 D [AlsaSound] SOUND: period size: 1764 frames, dir: 0

Here is the relevant part from the filling loop, what is called repeatedly:

log.debug("play %d samples", n);
while ((ret = snd_pcm_writei(handle, playBuf, n)) != (long)n) {
    if (ret < 0) {
        log.warn("ALSA error: %s\n", snd_strerror(ret));
        if ((ret = snd_pcm_recover(handle, ret, 0)) < 0) {
            log.error("ALSA error after recover: %s\n", snd_strerror(ret));
            checkFatalAlsaError(snd_pcm_prepare(handle), "ALSA irrecoverable error: %s");
        }
    } else {
        log.warn("ALSA short write...?\n");
        break;
    }
}

Here is the log when everything is fine:

3751.3029 D [AlsaSound] Starting square sound, nsamples: 3528, nPeriods: 2, nFrames: 1764
3751.3030 D [AlsaSound] play 1739 samples
3751.3037 D [AlsaSound] play 1739 samples
3751.3046 D [AlsaSound] play 50 samples
3751.3048 D [AlsaSound] Stop sound

And sometimes I get this:

3752.8769 D [AlsaSound] Starting square sound, nsamples: 3528, nPeriods: 2, nFrames: 1764
3752.8770 D [AlsaSound] play 1739 samples
3752.8779 D [AlsaSound] play 1739 samples
3752.8782 W [AlsaSound] ALSA error: Broken pipe
ALSA lib ../../../alsa-lib-1.1.4.1/src/pcm/pcm.c:8323:(snd_pcm_recover) underrun occurred
3752.8792 D [AlsaSound] play 50 samples
3752.8793 D [AlsaSound] Stop sound

From the log timestamps it is visible that the underrun occurs within 2ms of the first write – what writes ~40ms of samples. The two shown examples are identical in any other way, the device is not playing sound and is prepare()'d. The writing thread is renice’d to priority -19.

What can be the problem, and the solution?

Please note that it is intentional that I write fewer samples at once than the period size. Also maybe it counts that I am doing some OpenGL ES work in another thread (running on normal nice value).

OpenEmbedded v2.8b4 - Linux kernel version 4.9.87, libasound2 version 1.1.4.1-r0

Thanks in advance!

You did not state whether or not the OpenGL ES work in another thread has any influence on your audio code underrunning or not.

Sorry for digging this old question. Did you get to realise what caused these unexpected underruns?
I have the same kind of error on an embedded system myself and would be happy to know about any findings you might have.

HI @tonesenna: Thanks for writing to the Toradex Community!

Could you please open a new Question and provide all the details (hardware version, software version, sample code, …) to reproduce the issue?

Thanks and best regards,
Jaski