[alsa-devel] ALSA PulseAudio plugin: snd_pcm_rewindable() returns >0, but snd_pcm_rewind() is broken

Raymond Yau superquad.vortex2 at gmail.com
Tue Oct 25 01:00:19 CEST 2011

2011/10/25 Nikolay Nikolov <nickysn at gmail.com>:
> On 10/24/2011 06:34 PM, Pierre-Louis Bossart wrote:
>> You want to avoid rewinding completely. Your audio hardware might have
>> prefetched data with the DMA subsystem. Rewinding completely might result in
>> an inconsistent configuration and possibly underflows. If you look at the
>> PulseAudio code, we've introduced some thresholds beyond which we don't
>> rewind (128 bytes or 1ms off the top of my head).

This seem not enough for snd-ymfpci which update hw_ptr on 5.333 ms
intervals using its own timer interrupt (i.e. mininum 256 bytes period
size) at 48000Hz


This seem to be a design fault of alsa-pulse plugin which provide a
latency (minimum period size of 128 bytes) which is less than some of
the alsa sound drivers (e.g. snd-ymfpci, ...) and even PA server probe
those sound cards during initialisation but there is no negotiation
between PA server and client using alsa-pulse plugin

>> You might argue that snd_pcm_rewindable is broken, but it's somewhat
>> difficult to fix as the amount of prefetched data isn't modeled in the
>> driver and it's very much hardware-specific. Using a less aggressive
>> approach works fine on most hardware.
>> -Pierre

> Yes, I figured this out while experimenting with real hw alsa devices
> and that's why I actually rewind snd_pcm_rewindable() minus some
> threshold, that can be configured. However with the alsa pulseaudio
> plugin, rewinding seems to be broken completely, even with a very large
> threshold.

This is quite complicated when some of alsa driver (e.g.snd-ymfpci)
does not provide an accurate hw_ptr

I guess this may be the reason why aplay using 4 periods per buffer

For pulse plugin ,it will need to add two callback into
snd_pcm_ioplug_callback in alsa-lib/include/pcm_ioplug.h

	snd_pcm_sframes_t (*rewindable)(snd_pcm_ioplug_t *io);
	snd_pcm_sframes_t (*forwardwable)(snd_pcm_ioplug_t *io);

and alsa-lib/src/pcm_ioplug.c

static snd_pcm_sframes_t snd_pcm_ioplug_rewindable(snd_pcm_t *pcm)
	ioplug_priv_t *io = pcm->private_data;
+	if (io->data->callback->rewindable) {
+		return io->data->callback->rewindable(io->data);
	return snd_pcm_mmap_hw_avail(pcm);

static snd_pcm_sframes_t snd_pcm_ioplug_forwardable(snd_pcm_t *pcm)
	ioplug_priv_t *io = pcm->private_data;
+	if (io->data->callback->forwardable) {
+		return io->data->callback->forwardable(io->data);
	return snd_pcm_mmap_avail(pcm);

and add pulse_rewindable() and pulse_forwardable() to

More information about the Alsa-devel mailing list