Skip to main content
added 1534 characters in body
Source Link
wangt13
  • 1.2k
  • 11
  • 33

Updated with testing codes and testing results.

#ifdef TEST_APLAY
    frame_size = chan * 2;
    buf = databuf;
    left = data_frames;
    sent = 0;

    while (left > 0) {
        sent = (left > periodsize) ? periodsize : left;
        rc = snd_pcm_writei(hah->pcm_handle, buf, sent);
        if (rc == -EAGAIN || (rc >= 0 && (size_t)rc < sent)) {
            snd_pcm_wait(hah->pcm_handle, 10);
        } else if (rc == -EPIPE) {
            snd_pcm_recover(hah->pcm_handle, rc, 0); 
////            snd_pcm_prepare(hah->pcm_handle);
        } else if (rc < 0) {
            break;
        }
        if (rc > 0) {
            left -= rc; 
            buf += rc * frame_size;
        }
    }   
#endif

And I got the following results (start and stop playing 10 times).

Playing/stoping quickly for times, pid: 3168
Got end of media, breaking
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking

Above is tested in Ubuntu-20.04 X86_64 VM, with AC97 sound card.

Updated with testing codes and testing results.

#ifdef TEST_APLAY
    frame_size = chan * 2;
    buf = databuf;
    left = data_frames;
    sent = 0;

    while (left > 0) {
        sent = (left > periodsize) ? periodsize : left;
        rc = snd_pcm_writei(hah->pcm_handle, buf, sent);
        if (rc == -EAGAIN || (rc >= 0 && (size_t)rc < sent)) {
            snd_pcm_wait(hah->pcm_handle, 10);
        } else if (rc == -EPIPE) {
            snd_pcm_recover(hah->pcm_handle, rc, 0); 
////            snd_pcm_prepare(hah->pcm_handle);
        } else if (rc < 0) {
            break;
        }
        if (rc > 0) {
            left -= rc; 
            buf += rc * frame_size;
        }
    }   
#endif

And I got the following results (start and stop playing 10 times).

Playing/stoping quickly for times, pid: 3168
Got end of media, breaking
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Got end of media, breaking

Above is tested in Ubuntu-20.04 X86_64 VM, with AC97 sound card.

Source Link
wangt13
  • 1.2k
  • 11
  • 33

What is the right way to play audio with ALSA LIB?

I am working on an embedded audio device, it is using kernel-5.10, and ALSA-LIB to play audio.

When I am trying to call snd_pcm_writei() to play audio, I got a little confused on what is the right way to set its input parameters and handle its return value.

Here is my code.

    /* Get periodsize from system */
        snd_pcm_hw_params_get_period_size(hw_params, &periodsize, NULL);

        left = frames;
        sent = 0;
        while (left > 0) {
            sent = (left > periodsize) ? periodsize : left;
            rc = snd_pcm_writei(pcm_handle, buf, sent);
            if (rc < 0) {
                if (rc == -EAGAIN) {
                    usleep(1000);
                }
                rc = snd_pcm_recover(pcm_handle, rc, 0);
                if (rc < 0) {
                    snd_pcm_prepare(pcm_handle);
                }
            } else if (rc == 0) {
/* How to handle this case ?*/
            } else {
/* Samples less than were sent to audio-card */
                left -= rc;
                buf += rc * frame_size;
            }
        }

In my testing, the frames is 820, and periodsize is got from system, now it is 400. I am trying to sent data to audio-card upto the size of periodsize, is it correct?
Should I send data with frames of 820 directly to the audio card to play?

   snd_pcm_writei(pcm_handle, buf, frames);