[alsa-devel] Problems with safe API and snd-cs46xx

Takashi Iwai tiwai at suse.de
Tue Sep 8 16:42:35 CEST 2009


At Tue, 8 Sep 2009 15:38:25 +0200,
Lennart Poettering wrote:
> 
> On Tue, 08.09.09 08:29, Takashi Iwai (tiwai at suse.de) wrote:
> 
> > > This turned out to cause a couple of issues with some drivers (i think
> > > CS46xx is one of them, ice1712 another, I lack the hw in question, so
> > > i never tried to track this down further). Basically on those drivers
> > > both _set_buffer_size_near() and _set_periods_near() would fail with
> > > EINVAL for some reason and then causing snd_pcm_hw_params() to return
> > > ENOENT. Removing the two calls and calling snd_pcm_hw_params() would
> > > however work. Changing the order of the first two calls, i.e. doing
> > > first _set_periods_near() and then _set_buffer_size_near() would make
> > > both calls succeed and the snd_pcm_hw_params(), too.
> > 
> > The general problem in the hw_params setup is that the multiple
> > parameters depending with each other are allowed almost freely.
> > And, yet another problematic constraint is like cs46xx's one, the
> > power-of-two rule.  This limits strongly the value range.
> > 
> > Also, another issue is the presence of three units to specify the same
> > thing.  There are units, frame, bytes and time for period and buffer
> > sizes.  Especially the former two and the time units can be
> > inconsistent due to the integer rounding.
> 
> I always use 'frames' as unit for the actual calls, even if I said
> bytes.

It's not about what unit you use.  It's the fact that three units
exist in the hw_params space parallel and they have to be aligned with
each other.  See ens1371 example below.


> > > It would be good if the ALSA docs would actually mention in which
> > > order those functions need to be called, if the order matters, which
> > > it apparently does.
> > 
> > There is no golden rule, unfortunately, AFAIK.  There can be pretty
> > weird hardware, e.g. the buffer size depending on rate.  But, as a
> > rule of thumb:
> > 1. set access, format, channels and rate first,
> > 2. if you need larger buffers than shorter periods, set the buffer
> >   size first,
> > 3. set the period size only when you must specify it
> 
> This breaks on ice1712 at least...

Might be.

> > But, this can also fail when a hardware has a strong dependency
> > between period and buffer sizes together with a strong constraint
> > in period size.  In that case, you may need to try another way,
> > set period and hw_params.
> 
> For me the large buffers matter most. And large periods are the second
> most important thing. Would something like the following make sense?
> 
> <snip>
> snd_pcm_hw_params_any(pcm, hw);
> snd_pcm_hw_params_set_access(pcm, hw, ...);
> snd_pcm_hw_params_set_format(pcm, hw, ...);
> snd_pcm_hw_params_set_rate_near(pcm, hw, ...);
> snd_pcm_hw_params_set_channels_near(pcm, hw, ...);
> 
> snd_pcm_hw_params_copy(hw2, hw);
> 
> /* We care more about buffer size than the period size, so try setting
> things in this order first */
> snd_pcm_hw_params_set_buffer_size_near(hw, ...);
> snd_pcm_hw_params_set_periods_near(hw, ...);
> 
> if (snd_pcm_hw_params(pcm, hw) < 0) {
>    /* This order didn't work, so let's try it the other way round */
>    snd_pcm_hw_params_set_periods_near(hw2, ...);
>    snd_pcm_hw_params_set_buffer_size_near(hw2, ...);
> 
>    if (snd_pcm_hw_params(pcm, hw2) < 0) {
>        /* fail fatally */
>        ....
>    }
> }
> </snip>

I think yes.  But needs more testing of course :)


> > > ens1371 has some issues with the buffer size: if you ask it for 65536
> > > bytes in the playback buffer it will only agree to 65532. If the next
> > > time you ask for 65532 right-away it will only agree to 65528, and so on...)
> > 
> > The byte size can depend on the sample format and channels.
> > This might be the case.  Otherwise I don't see any strong restriction
> > of buffer/period size in ens1371 code.  It has the restriction of
> > sample rates, though.
> 
> I only actually manipulate samples here, not bytes. So the prob is
> that if you ask for a buffer size of n samples it will only agree to
> n-1 samples, for every possible n. Other drivers don't do that.

Then the problem is likely the sample rate setup.  ens1371 can't give
you always the integer sample rate.  Now the problem of multiple units
appears here like a ghost.  Almost every parameter is associated with
other parameters in the end due to the constraints below:
  buffer_time = buffer_size / sample_rate
  buffer_size = buffer_bytes / (channels * format_width)

When you get a non-integer rate value, even buffer_size can be
affected, rounded down to the next integer value.

All for one, one for all -- what a perfect world.


thanks,

Takashi


More information about the Alsa-devel mailing list