ALSA unexpected underrun with seemingly correct timings

1.6k Views Asked by At

I am going mad about spurious underrun errors on snd_pcm_writei() calls.

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.8764 D [AlsaSound] Setup square sound, time: 800, nsamples: 3528
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.

What can be the problem, and the solution?

Please note that it is intentional that I write fewer samples than the period size.

Linux kernel version 4.9.87, libasound2 version 1.1.4.1-r0, ARM (Colibri iMX6) platform

0

There are 0 best solutions below