8

I am playing a single channel audio in non-interleaved mode. I am getting underrun when I am writing audio data into speaker : ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred

Here is how I write:

    printf("%d",snd_pcm_avail (spkhandle));  
    ret = snd_pcm_writen(spkhandle, pSpeakerBuf , framesIn18Millisec);
    if(ret < 0)
    {
        snd_pcm_recover(spkhandle, ret, 0);
    }

What are the different ways/parameter configurations to prevent ALSA under run ?

(I am using Linux 3.0, ARM )

Edit: Here is a buffer measurement using snd_pcm_avail() API

      snd_pcm_avail = 2304      << snd_pcm_writen call 1 success
      snd_pcm_avail = 2160      << snd_pcm_writen call 2 success
      snd_pcm_avail = 2016      << snd_pcm_writen call 3 success
      snd_pcm_writen error -32 Broken pipe  << snd_pcm_writen call 4 failure
      ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred  << And displays this message

Here is the output that Marko requested for:

snd_output_t* out;
....
// Do alsa parameters init .... 
....
snd_output_stdio_attach(&out, stderr, 0);
snd_pcm_dump_sw_setup(spkhandle, out);

  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 144
  period_event : 0
  start_threshold  : 288
  stop_threshold   : 2304
  silence_threshold: 0
  silence_size : 0
  boundary     : 1207959552
Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
Lunar Mushrooms
  • 8,358
  • 18
  • 66
  • 88
  • Has your thread got real-time scheduling priority? – marko Jan 30 '13 at 11:01
  • @Marko, Yes, I have given realtime scheduling priority - SCHED_FIFO. – Lunar Mushrooms Jan 30 '13 at 11:09
  • What is your buffer period relative notification period? – marko Jan 30 '13 at 11:14
  • I am new to alsa. I write 18 milliseconds audio into single channel speaker (as my custom embedded system demands 18ms). As you can see in the question, snd_pcm_avail decreases by 144 bytes. How to avoid this ? – Lunar Mushrooms Jan 30 '13 at 13:32
  • You'd expect the available space for samples in the buffer to decrease after writing into it - but by rather more than 144 frames for 18ms. Would you care to put a call to `snd_pcm_dump_sw_setup()` in your code somewhere before audio starts, and share the console output with us? – marko Jan 30 '13 at 14:29
  • @Marko: Updated the question with the output of snd_pcm_dump_sw_setup() – Lunar Mushrooms Jan 30 '13 at 14:50
  • In line with the comment by @Marko, what is your sample rate, and the value of `framesIn18Millisec`. Note that for CD-quality audio (44100 Hz sample rate), there should be 793.8 samples in 18 ms. Although 144 samples would be right for a 8KHz sample rate... – twalberg Jan 30 '13 at 16:30
  • @twalberg Indeed it is. Worth pointing out at this point, that a many of the `alsa_pcm_sw_param_*` and `alsa_pcm_hw_param_*` calls are 'best-effort' - and you don't always get what you want. Setting sample-rate being one of them. After setting parameters, it is always wise to check what you actually got. – marko Jan 30 '13 at 16:51

2 Answers2

6

I assume this code runs in a tight loop and is intended to block on snd_pcm_writen(). The sample-rate isn't given; I assume 48kHz since the numbers all divide nicely.

What I think is going here is as follows:

  • snd_pcm_write() doesn't guarantee to write all frames provided (the return value is only ever checked for error conditions). Judging from the logging of snd_pcm_avail() it's in fact consuming avail_min or 144 frames on each. This is 3ms of audio.
  • Assuming that audio is not running at this point, after two writes, the number of frames in the buffer is equal to start_threshold - at 288 samples; audio output starts
  • calls to printf() block, and I seem to remember that snd_pcm_avail() has to synchronise with the audio output hardware and might also block. Since you are now 6ms ahead of the playback, it's entirely possible that the buffer is running dry during the time of the third call of snd_pcm_writen()

In summary, you shouldn't be calling printf() at this point, and you probably need to compensate for fact that snd_pcm_writen() isn't consuming all of the frames in pSpeakerBuf

Craig McQueen
  • 41,871
  • 30
  • 130
  • 181
marko
  • 9,029
  • 4
  • 30
  • 46
1

It is the buffer underrun,You can try increasing the buffer size by explicitly mentioning it in your ~/.asoundrc file ?

Rahul
  • 171
  • 1
  • 13
    Buffer underrun means the buffer is getting *empty*, not full. A larger buffer would tend to either not affect the symptoms, or maybe even make it worse... – twalberg Jan 30 '13 at 16:31