>non-continous transfers. The right loop, based on the period_size
>transfers, should be like this:
>
>       poll();
>       if ((pfd->revents & POLLIN) {
>               while (1) {
>                       if (snd_pcm_avail_update(pcm) < period_size)
>                               break;
>                       count = period_size;
>                       // transfer whole period (can be composed from more
>                       // non-continuous parts)

right, i understand that on some hardware, this is true. but there is
no reason i know of for the trident h/w (perhaps for any hardware) to
have a whole period composed of 2 non-continuous parts of size 1 and 
(period_size-1) frames. i can't believe that its an honest reflection
of the state of the hardware.

the one complication that i can see that might cause this is the
extent to which capture+playback hw pointers are in sync. what might
be happening is that there really is a continuous period_size's worth
of frames available on one stream, but in the other stream, the
pointer doesn't quite reflect this, so we end up with the silly
situation of having (period_size-1) + 1 frames. you'll note that in the
code below, i poll only one descriptor. 

do you think this is possible/likely? if it is, do you think that its
the job of the low level driver(s) to handle this? otherwise, its hard
for me to see how an application (or library) can handle this
efficiently in any full-duplex situations. 

i say this because even if we poll on both stream descriptors, if one
of them is out-of-step by 1 (or lets just say some very small number
of frames), we have to go back into poll immediately, which will
return immediately, and we end up busy waiting, which is not good at all.
i don't see any other way to handle that situation. do you?

i'm going to add some debugging to check on the "pointers-not-in-sync
theory", and i'll let you know what i find. since very few programs do
full duplex operation, this may be a rather hidden problem.

>                       while (avail > 0) {
>                               frames = count;
>                               snd_pcm_mmap_begin(pcm, areas, &offset, &frames
>);
>                               ....
>                               snd_pcm_mmap_commit(pcm, offset, frames);
>                               count -= frames;
>                       }
>               }
>       }

is there any difference between that and the actual loop (a few
non-essentials removed to make it clearer):

        if (poll (&driver->pfd, 1, 1000) < 0) {
                .... error ...
        }

        if (driver->pfd.revents & POLLERR) {
                .... error ....
        }
        
        if (driver->pfd.revents == 0) {
                ... timeout ....
        }
        
        if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) {
              ... detect xruns ...
        }

        if ((playback_avail = snd_pcm_avail_update (driver->playback_handle)) < 0) {
               ... detect xruns ...
        }

        ... handle xruns ...
        
        avail = capture_avail < playback_avail ? 
                   capture_avail : playback_avail;

        while (avail) {
                
                /* driver->frames_per_cycle === period_size */

                capture_avail = (avail > driver->frames_per_cycle) ? 
                                  driver->frames_per_cycle : avail;
                playback_avail = (avail > driver->frames_per_cycle) ? 
                                  driver->frames_per_cycle : avail;
                
                /* THIS CALLS snd_pcm_mmap_begin() FOR BOTH STREAMS */

                if (alsa_driver_get_channel_addresses 
                       (driver, 
                       (snd_pcm_uframes_t *) &capture_avail, 
                       (snd_pcm_uframes_t *) &playback_avail,
                       &capture_offset, &playback_offset) < 0) {
                        return -1;
                }

                contiguous = capture_avail < playback_avail ? 
                                  capture_avail : playback_avail;

                .... do interesting stuff with `contiguous' frames ...

                snd_pcm_mmap_commit (driver->capture_handle, 
                                     capture_offset, contiguous);
                snd_pcm_mmap_commit (driver->playback_handle, 
                                     playback_offset, contiguous);
                
                avail -= contiguous;
        }





_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to