5 #include <alsa/asoundlib.h>
7 static uint64_t timespec_us(const struct timespec
*ts
) {
9 ts
->tv_sec
* 1000000LLU +
10 ts
->tv_nsec
/ 1000LLU;
13 int main(int argc
, char *argv
[]) {
16 snd_pcm_hw_params_t
*hwparams
;
17 snd_pcm_sw_params_t
*swparams
;
18 snd_pcm_status_t
*status
;
20 unsigned rate
= 44100;
22 snd_pcm_uframes_t boundary
, buffer_size
= 44100/10; /* 100s */
24 struct timespec start
, last_timestamp
= { 0, 0 };
26 snd_pcm_sframes_t last_avail
, last_delay
;
27 struct pollfd
*pollfds
;
29 int64_t sample_count
= 0;
31 snd_pcm_hw_params_alloca(&hwparams
);
32 snd_pcm_sw_params_alloca(&swparams
);
33 snd_pcm_status_alloca(&status
);
35 r
= clock_gettime(CLOCK_MONOTONIC
, &start
);
38 start_us
= timespec_us(&start
);
40 dev
= argc
> 1 ? argv
[1] : "front:AudioPCI";
42 r
= snd_pcm_open(&pcm
, dev
, SND_PCM_STREAM_PLAYBACK
, 0);
45 r
= snd_pcm_hw_params_any(pcm
, hwparams
);
48 r
= snd_pcm_hw_params_set_rate_resample(pcm
, hwparams
, 0);
51 r
= snd_pcm_hw_params_set_access(pcm
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
);
54 r
= snd_pcm_hw_params_set_format(pcm
, hwparams
, SND_PCM_FORMAT_S16_LE
);
57 r
= snd_pcm_hw_params_set_rate_near(pcm
, hwparams
, &rate
, NULL
);
60 r
= snd_pcm_hw_params_set_channels(pcm
, hwparams
, 2);
63 r
= snd_pcm_hw_params_set_periods_integer(pcm
, hwparams
);
66 r
= snd_pcm_hw_params_set_periods_near(pcm
, hwparams
, &periods
, &dir
);
69 r
= snd_pcm_hw_params_set_buffer_size_near(pcm
, hwparams
, &buffer_size
);
72 r
= snd_pcm_hw_params(pcm
, hwparams
);
75 r
= snd_pcm_hw_params_current(pcm
, hwparams
);
78 r
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, 1);
81 r
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 1);
84 r
= snd_pcm_hw_params_get_buffer_size(hwparams
, &buffer_size
);
86 r
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, buffer_size
);
89 r
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
);
91 r
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
);
94 r
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
);
97 r
= snd_pcm_sw_params(pcm
, swparams
);
100 r
= snd_pcm_prepare(pcm
);
103 r
= snd_pcm_sw_params_current(pcm
, swparams
);
106 /* assert(snd_pcm_hw_params_is_monotonic(hwparams) > 0); */
108 n_pollfd
= snd_pcm_poll_descriptors_count(pcm
);
109 assert(n_pollfd
> 0);
111 pollfds
= malloc(sizeof(struct pollfd
) * n_pollfd
);
114 r
= snd_pcm_poll_descriptors(pcm
, pollfds
, n_pollfd
);
115 assert(r
== n_pollfd
);
118 snd_pcm_sframes_t avail
, delay
;
119 /* snd_pcm_uframes_t avail2; */
120 struct timespec now
, timestamp
;
121 unsigned short revents
;
123 uint64_t now_us
, timestamp_us
;
124 snd_pcm_state_t state
;
126 r
= poll(pollfds
, n_pollfd
, 0);
129 r
= snd_pcm_poll_descriptors_revents(pcm
, pollfds
, n_pollfd
, &revents
);
132 assert((revents
& ~POLLOUT
) == 0);
134 /* state = snd_pcm_get_state(pcm); */
136 avail
= snd_pcm_avail(pcm
);
139 r
= snd_pcm_status(pcm
, status
);
142 printf("%lu %lu\n", (unsigned long) avail
, (unsigned long) snd_pcm_status_get_avail(status
));
144 assert(avail
== (snd_pcm_sframes_t
) snd_pcm_status_get_avail(status
));
145 snd_pcm_status_get_htstamp(status
, ×tamp
);
146 delay
= snd_pcm_status_get_delay(status
);
147 state
= snd_pcm_status_get_state(status
);
149 /* r = snd_pcm_avail_delay(pcm, &avail, &delay); */
150 /* assert(r == 0); */
152 /* r = snd_pcm_htimestamp(pcm, &avail2, ×tamp); */
153 /* assert(r == 0); */
155 /* assert(avail == (snd_pcm_sframes_t) avail2); */
157 r
= clock_gettime(CLOCK_MONOTONIC
, &now
);
160 assert(!revents
|| avail
> 0);
163 snd_pcm_sframes_t sframes
;
164 static const uint16_t samples
[2] = { 0, 0 };
166 sframes
= snd_pcm_writei(pcm
, samples
, 1);
167 assert(sframes
== 1);
174 memcmp(×tamp
, &last_timestamp
, sizeof(timestamp
)) == 0 &&
175 avail
== last_avail
&&
176 delay
== last_delay
) {
181 now_us
= timespec_us(&now
);
182 timestamp_us
= timespec_us(×tamp
);
184 printf("%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
185 (unsigned long long) (now_us
- start_us
),
186 (unsigned long long) (timestamp_us
? timestamp_us
- start_us
: 0),
187 (unsigned long long) ((sample_count
- 1 - delay
) * 1000000LU / 44100),
196 last_timestamp
= timestamp
;