[alsa-devel] On non-rewindability of resamplers

Alexander E. Patrakov patrakov at gmail.com
Sat May 3 13:09:01 CEST 2014

02.05.2014 07:39, Raymond Yau wrote:
>  >>  >
>  >>  >
>  >>  > On most sound cards, PulseAudio uses timer-based scheduling and thus
>  >> is not subject to any period-size limitations. As far as I can see,
>  >> snd_ymfpci does not include SNDRV_PCM_INFO_BATCH, and thus will be used
>  >> in this mode.
> http://mailman.alsa-project.org/pipermail/alsa-devel/2014-March/073816.html
> Do you mean sound card which cannot provide sample
> granularity need to use that flag or you want the driver to provide this
> granularity to application ?

I acknowledge that there was some confusion regarding the precise 
meaning of the flag (especially given three possible situations - 
accurate to just one period, accurate to better than one period but 
worse than one sample, accurate to one sample), and I am not the 
authority here.

My own opinion so far is that, if the card cannot provide 
sample-accurate position reports at arbitrary moments in time, then the 
SNDRV_PCM_INFO_BATCH flag needs to be set. Of course, the driver should 
not attempt to provide sample-accurate information if such information 
does not exist in the first place.

In addition, there seems to be some confusion here between the hardware 
periods (which are always 256 samples) and the period size in hw params. 
If I understand the other emails correctly, regardless of what the user 
set in hw_params, the reported position on ymfpci will be accurate to 
within 256 samples.

PulseAudio has the following consideration here: if the card cannot 
report the position accurately, we need to disable the timestamp-based 
scheduling, as this breaks module-combine-sink (or any successor of it), 
because it relies on very accurate estimations of the actual sample rate 
ratio between two non-identical cards.

>  >In addition, it has an implementation of
>  >> snd_ymfpci_playback_pointer that seems to look at the hardware, which is
>  >> good. So effective period times less than 5 ms should work on this card.
>  >>
>  >
>  > Yes (if "cannot disable period wakeups" is the only bad thing about
> the card, which the further text in your e-mail contradicts to). Key
> words: dynamic latency.
>  >
>  > As you surely know, running with low latency has a high chance of
> underruns due to CPU spikes, so this should be avoided if reasonable.
> However, some applications (e.g. VoIP) require low latency. By ignoring
> period wakeups and relying on time-based scheduling, one can effectively
> change the period size on the fly, obtaining low latency only when it is
> needed.
>  >
> Are there any different reqiurment bewteen VOIP and other application in
> addition to low latency ?
> Voip does not really need stereo . The web cam Mic usually capture at
> 16000Hz mono while pulseaudio use same default  rate for playback and
> capture

In practice, only the latency matters here, as PulseAudio will open the 
device at 48 kHz stereo anyway.

>  >
>  >
>  > However, I don't see any code that backs up your claim. Is that fake
> pointer increased in hardware (as opposed to in the kernel) with such
> bad granularity?
>  >
>  > See snd_ymfpci_memalloc(): both chip->voices[voice].bank and
> chip->bank_playback[voice][bank] are assigned a pointer that is based on
> chip->work_ptr.area, which is itself obtained through
> snd_dma_alloc_pages. So all bank pointers definitely point into the
> DMA-able area.
>  >
>  > Also, snd_ymfpci_playback_pointer is based on
> voice->bank[chip->active_bank].start only, and the same construction is
> used in the interrupt handler to obtain the current playback position.
> So it is definitely based on what the hardware wrote into the DMA-able
> area, and that's why I thought that the .pointer function is good. Does
> it write there only just before the interrupt, or every 256 samples
> independently on the period size, or on some other condition?
> http://mailman.alsa-project.org/pipermail/alsa-devel/2011-September/043715.html
> The author of the driver told me that
> The period interrupts are not accurate at all.  The ymfpci hardware
> internally uses fixed periods of 256 frames at 48 kHz. the driver
> reports a period interrupt when the next hardware interrupt at or after
> a period boundary occurs.  The current position reported by the hardware
> is the position at the time of the last hardware interrupt

IMHO, this fits the purpose of the BATCH flag, but is precisely the 
middle case (possibly more accurate than one period, but definitely less 
accurate than one sample) which was disputed at 

>  >
>  > OK, but I don't see why it is relevant. Surely we can set up as many
> periods as we want, if all we are going to do with period interrupts is
> to ignore them in userspace.
>  >

To avoid further misunderstandings: I was speaking above about possible 
changes, not about the current behaviour. The answers below are for the 
current situation, which may be suboptimal.

> Do you mean pulseaudio will use more periods instead of periods_min for
> those sound cards which cannot disable period wake-up ?

For cards that are not batch, it will attempt to set both the period 
size and the buffer size to something large (tsched_size, the default is 
2s) and let the driver adjust that to something more sensible for the 
card. I think that in practice this means periods_min, although it is 
never mentioned explicitly in PulseAudio source.

For batch cards, the desired period (or, in PA speak, "fragment") time 
and the number of periods come from the config, of course subject to 
adjustments made by the ALSA library to fit the hardware requirements. 
The defaults are:

; default-fragments = 4
; default-fragment-size-msec = 25

> Do  dynamic latency mean pulseaudio use 1ms and double the times  until
> the sound card ?

If you are talking about the wakeup latency, the mechanism is indeed as 
you described (start with something small, increase if xruns or 
near-xruns appear, decrease if all runs well for some time), but the 1ms 
number is wrong. See the defines at the top of 
src/modules/alsa/alsa-sink.c for exact numbers.

> It may also be obtained by double the number of periods and restrict
> hwbuf_unused in multiple of samples in a period instead of any arbituary
> number of sample ?

I don't understand here.

>  >
>  > It is a bad idea to rewind into the uncertain area that we don't know
> whether it is already playing or not. If we have 6 periods 5 ms each,
> and always keep 5 of them full by promptly reacting to the interrupt
> notifications, then surely we can rewind one of them without much risk.
> But indeed, a full rewind is impossible for a fake hw_ptr with such bad
> granularity.
>  >
> /* FIXME? True value is 256/48 = 5.33333 ms */
> err = snd_pcm_hw_constraint_minmax(runtime,
>     5334, UINT_MAX);
> if (err < 0)
> return err;
> err = snd_pcm_hw_rule_noresample(runtime, 48000);
> Do you mean when noresample is used, the period byte constraint should
> be used instead of period time to avoid rounding error ?

Yes. And maybe even constrain the period size to be a multiple of 256 
samples in this case.

> To obtain dynamic latency, you can just keep half of them  or at least
> two periods full at any time

Yes if we talk about hardware periods (which are always 256 samples) and 
not about the period size which is settable through calling 
snd_pcm_hw_params_set_period_size_near() or something similar.

Alexander E. Patrakov

More information about the Alsa-devel mailing list