[alsa-devel] Intel HDA + HDMI - snd_pcm_drain buggy behaviour.

Sander Jansen s.jansen at gmail.com
Sun Feb 16 21:26:31 CET 2014


Further investigation on my part I noticed a couple of mistakes I made
myself.

1. snd_pcm_drain() doesn't block in non-blocking mode. I fixed my code to
account for this now.
2. snd_pcm_drain() doesn't block indefinitely in blocking mode. I must have
accidently put in a infinite loop somewhere myself.

That leaves still with one unresolved issue, which is that calling
snd_pcm_drain() does indeed work in both blocking and non-blocking, but I'm
still hearing part of the audio that was already played before. I assume
this is some data in the ringbuffer that hasn't been overwritten by any new
data. I have been able to reproduce this on another PC (Intel G45 chipset)
as well (snd_intel_hda as well, but with analog output) so I don't think
it's HDMI related.


This is my drain code:

    snd_pcm_state_t state = snd_pcm_state(handle);
    if (state==SND_PCM_STATE_RUNNING) {

      /// block while draining
      //if ((result=snd_pcm_nonblock(handle,0))<0) {
      //  printf("[alsa] failed to set blocking mode. Reason:
%s\n",snd_strerror(result));
      //  return;
      //  }

      result=snd_pcm_drain(handle);
      if (result==-EAGAIN) {
        printf("[alsa] waiting for drain\n");
        while(snd_pcm_state(handle)==SND_PCM_STATE_DRAINING){
          FXThread::sleep(500000000); // 50ms
          }
        printf("[alsa] drain complete. State:
%s\n",snd_pcm_state_name(snd_pcm_state(handle)));
        }
      else if (result<0) {
        printf("[alsa] drain failed. Reason: %s\n",snd_strerror(result));
        }
      else {
        printf("[alsa] drain complete\n");
        }
      }

Anything else I'm doing wrong?

Thanks,

Sander


On Sat, Feb 15, 2014 at 6:44 PM, Sander Jansen <s.jansen at gmail.com> wrote:

> All,
>
> When I play regular PCM audio through the HDMI that's connected to my
> amplifier I noticed  buggy behaviour when using the snd_pcm_drain() call.
> From my understanding of ALSA, during playback snd_pcm_drain() normally
> blocks until the playback buffer is empty.
>
> Here's what I'm experiencing:
>
> a. If the PCM handle is in BLOCKING mode, the snd_pcm_drain() function
> will block indefinitely (I've waited 30 seconds, before I gave up).
>
> b. In NON-BLOCKING mode, the first call to snd_pcm_drain results in a
> " Resource temporarily unavailable", subsequent call works but the pcm
> state has changed to DRAINING and takes about 1 sec to change to SETUP.
> Even though the audio has less than 0.5 seconds of actual playback left.
>
> So to make it work, I changed my single snd_pcm_drain() call into the
> following pseudo code:
> while(state==RUNNING && snd_pcm_drain()<0) {
>   state=snd_pcm_state()
>   }
>
> while(state==DRAINING && sleep(100)){
>   state=snd_pcm_state()
>   }
>
> Even though this seem to "sort of work", another problem with this
> approach I've noticed, is that part of the beginning of the playback buffer
> may be replayed at the end of the drain:
>
>   1. start playback at beginning of file
>   2. seek to close to the end of the file (snd_pcm_drop() gets called)
>   3. end of file reached, drain gets called, hear the end of the song +
> part of the beginning again?
>
> So I'm wondering whether this may be related to the drain issue I've
> noticed. I've attached the alsa-info.
>
> Thanks,
>
> Sander
>
>
>


More information about the Alsa-devel mailing list