ALSA PCM Timestamping

The ALSA API can provide two different system timestamps:

  • Trigger_tstamp is the system time snapshot taken when the .triggercallback is invoked. This snapshot is taken by the ALSA core in thegeneral case, but specific hardware may have synchronizationcapabilities or conversely may only be able to provide a correctestimate with a delay. In the latter two cases, the low-level driveris responsible for updating the trigger_tstamp at the most appropriateand precise moment. Applications should not rely solely on the firsttrigger_tstamp but update their internal calculations if the driverprovides a refined estimate with a delay.

  • tstamp is the current system timestamp updated during the lastevent or application query.The difference (tstamp - trigger_tstamp) defines the elapsed time.

The ALSA API provides two basic pieces of information, availand delay, which combined with the trigger and current systemtimestamps allow for applications to keep track of the ‘fullness’ ofthe ring buffer and the amount of queued samples.

The use of these different pointers and time information depends onthe application needs:

  • avail reports how much can be written in the ring buffer

  • delay reports the time it will take to hear a new sample after allqueued samples have been played out.

When timestamps are enabled, the avail/delay information is reportedalong with a snapshot of system time. Applications can select fromCLOCK_REALTIME (NTP corrections including going backwards),CLOCK_MONOTONIC (NTP corrections but never going backwards),CLOCK_MONOTIC_RAW (without NTP corrections) and change the modedynamically with sw_params

The ALSA API also provide an audio_tstamp which reflects the passageof time as measured by different components of audio hardware. Inascii-art, this could be represented as follows (for the playbackcase):

--------------------------------------------------------------> time  ^               ^              ^                ^           ^  |               |              |                |           | analog         link            dma              app       FullBuffer time           time           time              time        time  |               |              |                |           |  |< codec delay >|<--hw delay-->|<queued samples>|<---avail->|  |<----------------- delay---------------------->|           |                                 |<----ring buffer length---->|

The analog time is taken at the last stage of the playback, as closeas possible to the actual transducer

The link time is taken at the output of the SoC/chipset as the samplesare pushed on a link. The link time can be directly measured ifsupported in hardware by sample counters or wallclocks (e.g. withHDAudio 24MHz or PTP clock for networked solutions) or indirectlyestimated (e.g. with the frame counter in USB).

The DMA time is measured using counters - typically the least reliableof all measurements due to the bursty nature of DMA transfers.

The app time corresponds to the time tracked by an application afterwriting in the ring buffer.

The application can query the hardware capabilities, define whichaudio time it wants reported by selecting the relevant settings inaudio_tstamp_config fields, thus get an estimate of the timestampaccuracy. It can also request the delay-to-analog be included in themeasurement. Direct access to the link time is very interesting onplatforms that provide an embedded DSP; measuring directly the linktime with dedicated hardware, possibly synchronized with system time,removes the need to keep track of internal DSP processing times andlatency.

In case the application requests an audio tstamp that is not supportedin hardware/low-level driver, the type is overridden as DEFAULT and thetimestamp will report the DMA time based on the hw_pointer value.

For backwards compatibility with previous implementations that did notprovide timestamp selection, with a zero-valued COMPAT timestamp typethe results will default to the HDAudio wall clock for playbackstreams and to the DMA time (hw_ptr) in all other cases.

The audio timestamp accuracy can be returned to user-space, so thatappropriate decisions are made:

  • for dma time (default), the granularity of the transfers can beinferred from the steps between updates and in turn provideinformation on how much the application pointer can be rewoundsafely.

  • the link time can be used to track long-term drifts between audioand system time using the (tstamp-trigger_tstamp)/audio_tstampratio, the precision helps define how much smoothing/low-passfiltering is required. The link time can be either reset on startupor reported as is (the latter being useful to compare progress ofdifferent streams - but may require the wallclock to be alwaysrunning and not wrap-around during idle periods). If supported inhardware, the absolute link time could also be used to define aprecise start time (patches WIP)

  • including the delay in the audio timestamp maycounter-intuitively not increase the precision of timestamps, e.g. if acodec includes variable-latency DSP processing or a chain ofhardware components the delay is typically not known with precision.

The accuracy is reported in nanosecond units (using an unsigned 32-bitword), which gives a max precision of 4.29s, more than enough foraudio applications...

Due to the varied nature of timestamping needs, even for a singleapplication, the audio_tstamp_config can be changed dynamically. IntheSTATUS ioctl, the parameters are read-only and do not allow forany application selection. To work around this limitation withoutimpacting legacy applications, a newSTATUS_EXT ioctl is introducedwith read/write parameters. ALSA-lib will be modified to make use ofSTATUS_EXT and effectively deprecateSTATUS.

The ALSA API only allows for a single audio timestamp to be reportedat a time. This is a conscious design decision, reading the audiotimestamps from hardware registers or from IPC takes time, the moretimestamps are read the more imprecise the combined measurementsare. To avoid any interpretation issues, a single (system, audio)timestamp is reported. Applications that need different timestampswill be required to issue multiple queries and perform aninterpolation of the results

In some hardware-specific configuration, the system timestamp islatched by a low-level audio subsystem, and the information providedback to the driver. Due to potential delays in the communication withthe hardware, there is a risk of misalignment with the avail and delayinformation. To make sure applications are not confused, adriver_timestamp field is added in the snd_pcm_status structure; thistimestamp shows when the information is put together by the driverbefore returning from theSTATUS andSTATUS_EXT ioctl. in most casesthis driver_timestamp will be identical to the regular system tstamp.

Examples of timestamping with HDAudio:

1. DMA timestamp, no compensation for DMA+analog delay

$ ./audio_time  -p --ts_type=1playback: systime: 341121338 nsec, audio time 342000000 nsec,         systime delta -878662playback: systime: 426236663 nsec, audio time 427187500 nsec,         systime delta -950837playback: systime: 597080580 nsec, audio time 598000000 nsec,         systime delta -919420playback: systime: 682059782 nsec, audio time 683020833 nsec,         systime delta -961051playback: systime: 852896415 nsec, audio time 853854166 nsec,         systime delta -957751playback: systime: 937903344 nsec, audio time 938854166 nsec,         systime delta -950822

2. DMA timestamp, compensation for DMA+analog delay

$ ./audio_time  -p --ts_type=1 -dplayback: systime: 341053347 nsec, audio time 341062500 nsec,         systime delta -9153playback: systime: 426072447 nsec, audio time 426062500 nsec,         systime delta 9947playback: systime: 596899518 nsec, audio time 596895833 nsec,         systime delta 3685playback: systime: 681915317 nsec, audio time 681916666 nsec,         systime delta -1349playback: systime: 852741306 nsec, audio time 852750000 nsec,         systime delta -8694

3. link timestamp, compensation for DMA+analog delay

$ ./audio_time  -p --ts_type=2 -dplayback: systime: 341060004 nsec, audio time 341062791 nsec,         systime delta -2787playback: systime: 426242074 nsec, audio time 426244875 nsec,         systime delta -2801playback: systime: 597080992 nsec, audio time 597084583 nsec,         systime delta -3591playback: systime: 682084512 nsec, audio time 682088291 nsec,         systime delta -3779playback: systime: 852936229 nsec, audio time 852940916 nsec,         systime delta -4687playback: systime: 938107562 nsec, audio time 938112708 nsec,         systime delta -5146

Example 1 shows that the timestamp at the DMA level is close to 1msahead of the actual playback time (as a side time this sort ofmeasurement can help define rewind safeguards). Compensating for theDMA-link delay in example 2 helps remove the hardware buffering butthe information is still very jittery, with up to one sample oferror. In example 3 where the timestamps are measured with the linkwallclock, the timestamps show a monotonic behavior and a lowerdispersion.

Example 3 and 4 are with USB audio class. Example 3 shows a highoffset between audio time and system time due to buffering. Example 4shows how compensating for the delay exposes a 1ms accuracy (due tothe use of the frame counter by the driver)

Example 3: DMA timestamp, no compensation for delay, delta of ~5ms

$ ./audio_time -p -Dhw:1 -t1playback: systime: 120174019 nsec, audio time 125000000 nsec,         systime delta -4825981playback: systime: 245041136 nsec, audio time 250000000 nsec,         systime delta -4958864playback: systime: 370106088 nsec, audio time 375000000 nsec,         systime delta -4893912playback: systime: 495040065 nsec, audio time 500000000 nsec,         systime delta -4959935playback: systime: 620038179 nsec, audio time 625000000 nsec,         systime delta -4961821playback: systime: 745087741 nsec, audio time 750000000 nsec,         systime delta -4912259playback: systime: 870037336 nsec, audio time 875000000 nsec,         systime delta -4962664

Example 4: DMA timestamp, compensation for delay, delay of ~1ms

$ ./audio_time -p -Dhw:1 -t1 -dplayback: systime: 120190520 nsec, audio time 120000000 nsec,         systime delta 190520playback: systime: 245036740 nsec, audio time 244000000 nsec,         systime delta 1036740playback: systime: 370034081 nsec, audio time 369000000 nsec,         systime delta 1034081playback: systime: 495159907 nsec, audio time 494000000 nsec,         systime delta 1159907playback: systime: 620098824 nsec, audio time 619000000 nsec,         systime delta 1098824playback: systime: 745031847 nsec, audio time 744000000 nsec,         systime delta 1031847