2 * This program only tracks the difference between system time
3 * and audio time, as reported in snd_pcm_status(). It should be
4 * helpful to verify the information reported by drivers.
7 #include "../include/asoundlib.h"
10 static char *device = "hw:0,0";
12 snd_output_t *output = NULL;
14 long long timestamp2ns(snd_htimestamp_t t)
18 nsec = t.tv_sec * 1000000000;
24 long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
26 long long nsec1, nsec2;
28 nsec1 = timestamp2ns(t1);
29 nsec2 = timestamp2ns(t2);
34 void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
35 snd_htimestamp_t *trigger_timestamp,
36 snd_htimestamp_t *audio_timestamp,
37 snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
40 snd_pcm_status_t *status;
42 snd_pcm_status_alloca(&status);
43 if ((err = snd_pcm_status(handle, status)) < 0) {
44 printf("Stream status error: %s\n", snd_strerror(err));
47 snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
48 snd_pcm_status_get_htstamp(status, timestamp);
49 snd_pcm_status_get_audio_htstamp(status, audio_timestamp);
50 *avail = snd_pcm_status_get_avail(status);
51 *delay = snd_pcm_status_get_delay(status);
55 #define PCM_LINK /* sync start for playback and capture */
56 #define TRACK_CAPTURE /* dump capture timing info */
57 #define TRACK_PLAYBACK /* dump playback timing info */
58 #define TRACK_SAMPLE_COUNTS /* show difference between sample counters and audiotimestamps returned by driver */
59 #define PLAYBACK_BUFFERS 4
60 #define TSTAMP_TYPE SND_PCM_TSTAMP_TYPE_MONOTONIC
67 snd_pcm_t *handle_p = NULL;
68 snd_pcm_t *handle_c = NULL;
69 snd_pcm_sframes_t frames;
70 snd_htimestamp_t tstamp_c, tstamp_p;
71 snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
72 snd_htimestamp_t audio_tstamp_c, audio_tstamp_p;
73 unsigned char buffer_p[PERIOD*4*4];
74 unsigned char buffer_c[PERIOD*4*4];
76 snd_pcm_hw_params_t *hwparams_p;
77 snd_pcm_hw_params_t *hwparams_c;
79 snd_pcm_sw_params_t *swparams_p;
80 snd_pcm_sw_params_t *swparams_c;
82 snd_pcm_uframes_t curr_count_c;
83 snd_pcm_uframes_t frame_count_c = 0;
84 snd_pcm_uframes_t curr_count_p;
85 snd_pcm_uframes_t frame_count_p = 0;
87 snd_pcm_sframes_t delay_p, delay_c;
88 snd_pcm_uframes_t avail_p, avail_c;
90 if ((err = snd_pcm_open(&handle_p, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
91 printf("Playback open error: %s\n", snd_strerror(err));
94 if ((err = snd_pcm_set_params(handle_p,
96 SND_PCM_ACCESS_RW_INTERLEAVED,
100 500000)) < 0) { /* 0.5sec */
101 printf("Playback open error: %s\n", snd_strerror(err));
105 snd_pcm_hw_params_alloca(&hwparams_p);
106 /* get the current hwparams */
107 err = snd_pcm_hw_params_current(handle_p, hwparams_p);
109 printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err));
112 if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_p))
113 printf("Playback relies on audio wallclock timestamps\n");
115 printf("Playback relies on audio sample counter timestamps\n");
117 snd_pcm_sw_params_alloca(&swparams_p);
118 /* get the current swparams */
119 err = snd_pcm_sw_params_current(handle_p, swparams_p);
121 printf("Unable to determine current swparams_p: %s\n", snd_strerror(err));
126 err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE);
128 printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
132 err = snd_pcm_sw_params_set_tstamp_type(handle_p, swparams_p, TSTAMP_TYPE);
134 printf("Unable to set tstamp type : %s\n", snd_strerror(err));
138 /* write the sw parameters */
139 err = snd_pcm_sw_params(handle_p, swparams_p);
141 printf("Unable to set swparams_p : %s\n", snd_strerror(err));
145 if ((err = snd_pcm_open(&handle_c, device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
146 printf("Capture open error: %s\n", snd_strerror(err));
149 if ((err = snd_pcm_set_params(handle_c,
151 SND_PCM_ACCESS_RW_INTERLEAVED,
155 500000)) < 0) { /* 0.5sec */
156 printf("Capture open error: %s\n", snd_strerror(err));
160 snd_pcm_hw_params_alloca(&hwparams_c);
161 /* get the current hwparams */
162 err = snd_pcm_hw_params_current(handle_c, hwparams_c);
164 printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err));
167 if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_c))
168 printf("Capture relies on audio wallclock timestamps\n");
170 printf("Capture relies on audio sample counter timestamps\n");
172 snd_pcm_sw_params_alloca(&swparams_c);
173 /* get the current swparams */
174 err = snd_pcm_sw_params_current(handle_c, swparams_c);
176 printf("Unable to determine current swparams_c: %s\n", snd_strerror(err));
181 err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE);
183 printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
187 err = snd_pcm_sw_params_set_tstamp_type(handle_c, swparams_c, TSTAMP_TYPE);
189 printf("Unable to set tstamp type : %s\n", snd_strerror(err));
193 /* write the sw parameters */
194 err = snd_pcm_sw_params(handle_c, swparams_c);
196 printf("Unable to set swparams_c : %s\n", snd_strerror(err));
201 if ((err = snd_pcm_link(handle_c, handle_p)) < 0) {
202 printf("Streams link error: %s\n", snd_strerror(err));
207 i = PLAYBACK_BUFFERS;
209 frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
211 printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
214 frame_count_p += frames;
217 if (PLAYBACK_BUFFERS != 4)
218 snd_pcm_start(handle_p);
221 /* need to start capture explicitly */
222 snd_pcm_start(handle_c);
227 frames = snd_pcm_wait(handle_c, -1);
229 printf("snd_pcm_wait failed: %s\n", snd_strerror(frames));
233 frames = snd_pcm_readi(handle_c, buffer_c, PERIOD);
235 printf("snd_pcm_readi failed: %s\n", snd_strerror(frames));
238 frame_count_c += frames;
240 frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
242 printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
246 frame_count_p += frames;
248 #if defined(TRACK_PLAYBACK)
249 gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &audio_tstamp_p, &avail_p, &delay_p);
251 #if defined(TRACK_SAMPLE_COUNTS)
252 curr_count_p = frame_count_p - delay_p; /* written minus queued */
254 printf("playback: curr_count %lli driver count %lli, delta %lli\n",
255 (long long)curr_count_p * 1000000000LL / 48000 ,
256 timestamp2ns(audio_tstamp_p),
257 (long long)curr_count_p * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_p)
261 printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
262 timediff(tstamp_p, trigger_tstamp_p),
263 timestamp2ns(audio_tstamp_p),
264 timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
268 #if defined(TRACK_CAPTURE)
269 gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &audio_tstamp_c, &avail_c, &delay_c);
271 #if defined(TRACK_SAMPLE_COUNTS)
272 curr_count_c = frame_count_c + delay_c; /* read plus queued */
275 printf("capture: curr_count %lli driver count %lli, delta %lli\n",
276 (long long)curr_count_c * 1000000000LL / 48000 ,
277 timestamp2ns(audio_tstamp_c),
278 (long long)curr_count_c * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_c)
282 printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
283 timediff(tstamp_c, trigger_tstamp_c),
284 timestamp2ns(audio_tstamp_c),
285 timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
293 snd_pcm_close(handle_p);
295 snd_pcm_close(handle_c);