[alsa-devel] What does snd_pcm_delay() actually return?

Jaroslav Kysela perex at perex.cz
Mon Jun 16 14:07:24 CEST 2008

Hi all,

	I tried to describe expressions for all values as Lennart proposed 
with current snd_pcm_avail_update() / snd_pcm_delay() functions and add 
some more comments to things noted in this discussion. I do not think that 
we should make internal ring buffer pointers external for applications.

Lennart's proposal (marked with *, my reply marked with -)

* ABSOLUTE_WRITE: the current absolute write counter in samples, since
  the device was opened.
- the application can calculate this value itself without too much pain

* ABSOLUTE_READ:  the current absolute read counter in samples, since
  the device was opened.
- if it's value 'how much samples consumer (driver) read':
  ABSOLUTE_WRITE - (buffer_size - snd_pcm_avail_update())
* ABSOLUTE_HEAR: the current absolute hear counter in samples, since
  the device was opened 
- ABSOLUTE_WRITE - snd_pcm_delay()

* WRITE_TO_READ:  the current fill level of the playback buffer
- buffer_size - snd_pcm_avail_update()

* WRITE_TO_HEAR:  if i write a sample immediately after this call, how
  much time takes it to be played.
- snd_pcm_delay()

* READ_TO_HEAR:   the 'fifo' latency, i.e. the time that passes
  after a sample was read form the playback buffer that it is actually played.
- snd_pcm_delay() - (buffer_size - snd_pcm_avail_update())

* CAN_WRITE:      how much can be written into the buffer right
  now  (buffer_size - WRITE_TO_READ)
- snd_pcm_avail_update()

* LEFT_TO_PLAY:   similar to WRITE_TO_HEAR but callable *after* we
  wrote something, and it will return how much of what we wrote has not
  been heard yet. In contrast to WRITE_TO_HEAR this will return 0
- this accouting can be easily done in app using snd_pcm_delay() - 
  application know how many samples were written

Atomicity of 'avail / delay' values:

It's not actually guaranteed. But I'm not sure if it's required to have
these values "in exact sync". Both values have different meaning. While
avail value should be used for the ring buffer filling / draining,
the purpose of delay value is for sync with other timing source. In time
of call, both functions (snd_pcm_avail_update() and snd_pcm_delay())
return correct value.

Only the READ_TO_HEAD expression uses both delay + avail values. I'm not 
sure for which purpose application will use this value. It seems to me 
only purely informational and we should offer this "internal queue size" 
value using another API.

But I am open to implement atomic call in alsa-lib:

Original functions:

snd_pcm_avail_update()		/* light version - not forced ptr sync */
snd_pcm_delay()			/* already includes hwsync() */
snd_pcm_hwsync()		/* might be osoleted by snd_pcm_avail() ? */


snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *);	/* adds hwsync() */
int snd_pcm_avail_and_delay(snd_pcm_t *,
			    snd_sframes_t *avail, 
			    snd_sframes_t *delay);
	/* hwsync() + avail_update() + delay() - atomic operation */

This extension will allow us to optimize case when both avail and delay 
values are required by application and we can remove "problematic" 
snd_pcm_hwsync() function by snd_pcm_avail() function.

Exposing appl_ptr / hw_ptr / curr_ptr to applications

More complicated buffer state description. Applications must do pointer
wrap calculations itself, including underrun / overrun detection. It's
far more complicated that current avail / delay scheme.


Jaroslav Kysela <perex at perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

More information about the Alsa-devel mailing list