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

Sander Jansen s.jansen at gmail.com
Mon Feb 17 03:52:39 CET 2014


Ok. Never mind. I was under the false impression that snd_pcm_drain would
be able to handle partially filled periods. Making sure the last write
fills at least a period seemed to have solved the issue.


On Sun, Feb 16, 2014 at 2:26 PM, Sander Jansen <s.jansen at gmail.com> wrote:

> 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