[alsa-devel] On non-rewindability of resamplers
Alexander E. Patrakov
patrakov at gmail.com
Sat May 10 15:16:20 CEST 2014
10.05.2014 06:46, Raymond Yau wrote:
> > 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.
> Can this granularity be measured by
> 1) open a playback stream with 2 or more periods
> 2) fill the full buffer and start playback
> 3) check the value returned by snd_pcm_rewindable () is half of period
> at half period time interval
> 4) repeat the test with 1/4 , 1/8,..., period time interval
Yes and no.
Instead of what you are proposing above, I wrote a loop that repeatedly
calls snd_pcm_rewindable() 7000000 times and prints the result if it
differs from the previous one. With snd-hda-intel (PCH), hw plugin,
stereo, S16_LE, 48 kHz, 6 periods, and a period size of 1024, I get this:
Rewindable: 6119, loop iteration: 0
Rewindable: 5119, loop iteration: 5389434
So snd_pcm_rewindable() can return weird values that are updated every
period size or so. As such, I wouldn't believe its return value out of
the box even for hw devices. At loop iteration 5389433, the CPU chewed
enough time for almost one period, but snd_pcm_rewindable() said that
almost 6 periods are rewindable. Probably a missing sync_ptr()
somewhere, or a documentation bug.
With snd_pcm_avail() inserted (which does synchronize the position)
before each call to snd_pcm_rewindable(), I get:
Rewindable: 6119, loop iteration: 0
Rewindable: 6112, loop iteration: 2
Rewindable: 6104, loop iteration: 42
Rewindable: 6096, loop iteration: 76
Rewindable: 6088, loop iteration: 125
Rewindable: 6080, loop iteration: 173
Rewindable: 6072, loop iteration: 222
Rewindable: 6064, loop iteration: 270
(and an underrun in the end).
With 4 channels:
Rewindable: 6112, loop iteration: 0
Rewindable: 6108, loop iteration: 2
Rewindable: 6104, loop iteration: 14
Rewindable: 6100, loop iteration: 36
Rewindable: 6096, loop iteration: 58
Rewindable: 6092, loop iteration: 63
With 8 channels:
Rewindable: 6104, loop iteration: 0
Rewindable: 6098, loop iteration: 1
Rewindable: 6096, loop iteration: 2
Rewindable: 6094, loop iteration: 9
Rewindable: 6092, loop iteration: 24
Rewindable: 6090, loop iteration: 32
Rewindable: 6088, loop iteration: 41
So on my snd-hda-intel, the granularity of the pointer is 32 bytes.
For Haswell HDMI (on another snd-hda-intel), stereo, S16_LE:
Rewindable: 6128, loop iteration: 0
Rewindable: 6112, loop iteration: 129
Rewindable: 6096, loop iteration: 339
Rewindable: 6080, loop iteration: 551
Rewindable: 6064, loop iteration: 753
Rewindable: 6048, loop iteration: 966
Rewindable: 6032, loop iteration: 1180
so the resulting granularity is 64 bytes.
An unfortunate observation is that, without snd_pcm_avail(), even on hw
just after an underrun snd_pcm_rewindable() can return negative numbers
such as -16 or -25 that lead to nonsense error codes (EBUSY or ENOTTY).
> > 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.
> This callback is called when the PCM middle layer inquires the current
> hardware position on the buffer. The position must be returned in
> frames, ranging from 0 to buffer_size - 1.
> This does not implies all drivers must give accurate position at any
> time, some drivers may use timer interrupt and increase the pointer by
> one periods
That's why we have snd_pcm_htimestamp().
> High frequency timer interrupts
> This happens when the hardware doesn't generate interrupts at the period
> boundary but issues timer interrupts at a fixed timer rate (e.g. es1968
> or ymfpci drivers). In this case, you need to check the current hardware
> position and accumulate the processed sample length at each interrupt.
> When the accumulated size exceeds the period size, call
> snd_pcm_period_elapsed() and reset the accumulator.
This clears the confusion.
> I am also confuse about ymfpci really use timer interrupts.
Well, that's easy. According to your own words, the card sends an
interrupt every 256 samples and has no real notion of the user-defined
period size. From ALSA viewpoint, this 256-sample interrupt is just a
timer (but not a timer that is managed through functions that have
"timer" in the name).
<snip information on the OSS DSP_CAP_REALTIME and DSP_CAP_BATCH
Interesting, but does not really clarify anything.
> > hw_ptr granularity is defined only by period_bytes_min (and
> additional constraints if any).
Well, this disagrees with my experiments. For S16_LE stereo,
snd_pcm_hw_params_get_period_size_min() says 32 samples for both PCH and
HDMI, while the measured granularity is different (8 and 16 samples).
> hw.period_bytes_min = 256;
> hw.fifo_size = dma_data->fifo_size;
> Does soc drivers transfer audio in 256 bytes ?
> seem twice the values of snd-hda-Intel (pcie bus)
No comment on this, I am not an expert in this area.
> > 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.
This is something to investigate, I am not ready to provide any useful
comment. Although in comment #2 bluetooth is mentioned, and this is
indeed an example where even somewhat accurate timing information is not
> if you want to hear sound from two snd-hda-intel at the same time using
> combined sink, you may need driver provide the output delay in hda codec
> 220.127.116.11 Audio Function Group Capabilities
> Output Delay is a four bit value representing the number of samples
> between when the sample is received from the Link and when it appears as
> an analog signal at the pin. This may be a “typical” value. If this is
> 0, the widgets along the critical path should be queried, and each
> individual widget must report its individual delay.
> Figure 85. Audio Function Group Capabilities Response Format
> 18.104.22.168 Audio Widget Capabilities
> Delay indicates the number of sample delays through the widget. This may
> be 0 if the delay value in the Audio Function Parameters is supplied to
> represent the entire path.
> some hda codecs report delay in audio output/input widgets and the
> ranges of delay vary from 3 to 13 samples, hda_proc.c did not show
> output/input delay in the audio function group
Interesting, implementable for someone with the skills in this area, but
probably not relevant for the above freedesktop bug. What you are
talking about is just a constant offset in the snd_pcm_delay() return
values. That's bad, but I guess not bad enough for PulseAudio to
stutter. What PulseAudio doesn't tolerate is jitter.
> Does it mean that pulseaudio need to add back the difference of output
> delay of two hda codecs ?
> If yes, this look like combined sink is also not rewindable too when
> difference of output delay is not zero
Indeed, it is not fully rewindable. But what's worse is that the
combined sink contains a variable-rate resampler that is used in order
to compensate adaptively for slightly different sample rates of the two
> for upmix plugin, this mean that snd_pcm_rewindable may need to return
> zero when user specify delay > 0 if you want "glitch free" rewind
> Other pulseaudio modules seen does not support rewind (e.g. jack,
> tunnel, Bluetooth,...
> Other alsa plugins (e.g. Jack, oss,...) seem not support rewind
Jack is interesting here: it is the only ioplug-based plugin which sets
mmap_rw = 1. As such, ALSA treats it as something that has mmapped
buffer with the same semantics as an ordinary hardware sound card, and
performs rewinds using this buffer. There is also a "hardware" position
callback. The actual transfer of samples from that buffer to JACK is
performed in a separate realtime thread which is implicitly created in
jack_activate(). The porition is updated every JACK period.
The whole construction should support rewinds, with the non-rewindable
remainder being one JACK period (which may be different from one ALSA
period). If the JACK period is 256 samples, this plugin should behave
very much like one voice of ymfpci.
However, there is still a bug (possibly fixable). While running my test
program over this plugin does produce silence, it produces a wrong
amount of silence. As if there is something wrong with
snd_pcm_jack_poll_revents() or snd_pcm_jack_pointer(). I have not tested
this patch yet, although I should:
As for ioplug-based plugins with mmap_rw = 0, they are indeed not
rewindable at all.
> How about route and plug plugins ?
Route should in theory support rewind, but there may be bugs. The best
way to test is to run a program that I attached to an earlier message in
this thread and listen - any non-silence indicates a non-rewindable plugin.
Plug is not really a plugin, it just inserts other plugins and then
disappears. It can insert adpcm and rate plugins which are not really
> > 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.
> it does not mean all drivers uses periods_min when applicaition did not
> explicitly set period , period time or period bytes
> Some driver 's period_bytes_max can be less than (buffer_bytes_max /
Please see this code and make your own conclusions.
PulseAudio does try several strategies, among those is "set nothing at
all if everything else failed".
> > 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.
> as long as the application use two periods , no safe rewind is possible
> as the application need to keep at least two periods fill in the buffer
> if the pointer is not accurate.
Correct if we use the viewpoint that the pointer granularity is one
period for such cards. Which is not the case for ymfpci and for USB audio.
> do you mean that pulseaudio still perform rewind when using AC3
> passthrough on Didital playback device ?
I don't know.
> if not , the value of snd_pcm_rewindable() of digital playback device
> depends on whether no audio bit is set or not
While I understand the idea, I would like to see more details. The only
consideration that comes to my mind is that it should not be possible to
rewind into the middle of the currently playing IEC 61937 frame. But
there are also stupid receivers (e.g. JVC TH-A25) that mute their
outputs if a non-IEC-wrapped DTS stream (as found on DTS CDs) is coming
with AES0 = 6.
> >The defaults are:
> > ; default-fragments = 4
> > ; default-fragment-size-msec = 25
> Does this mean that pulseaudio use this values for all sound card
> including hda when user specify this value ?
This is the default for all cards that are autodetected as incompatible
with tsched or where the user configured tsched=0. These defaults can
still be overridden with module-alsa-card parameters.
> Seem the values are comment out and not used by pulseaudio as default ,
> users have to explicitly set these in the following report
The commented-out values are used by default when PulseAudio decides
that it needs a traditional (not tsched based) playback model. They are
in the source:
The key in that comment is the explicit tsched=0. Without tsched=0,
these settings are not used.
Alexander E. Patrakov
More information about the Alsa-devel