1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci * This program only tracks the difference between system time 3d5ac70f0Sopenharmony_ci * and audio time, as reported in snd_pcm_status(). It should be 4d5ac70f0Sopenharmony_ci * helpful to verify the information reported by drivers. 5d5ac70f0Sopenharmony_ci */ 6d5ac70f0Sopenharmony_ci 7d5ac70f0Sopenharmony_ci#include "config.h" 8d5ac70f0Sopenharmony_ci#include <stdio.h> 9d5ac70f0Sopenharmony_ci#if HAVE_MALLOC_H 10d5ac70f0Sopenharmony_ci#include <malloc.h> 11d5ac70f0Sopenharmony_ci#endif 12d5ac70f0Sopenharmony_ci#include <unistd.h> 13d5ac70f0Sopenharmony_ci#include <stdlib.h> 14d5ac70f0Sopenharmony_ci#include <string.h> 15d5ac70f0Sopenharmony_ci#include <getopt.h> 16d5ac70f0Sopenharmony_ci#include <fcntl.h> 17d5ac70f0Sopenharmony_ci#include <ctype.h> 18d5ac70f0Sopenharmony_ci#include <errno.h> 19d5ac70f0Sopenharmony_ci#include <limits.h> 20d5ac70f0Sopenharmony_ci#include <time.h> 21d5ac70f0Sopenharmony_ci#include <locale.h> 22d5ac70f0Sopenharmony_ci#include <math.h> 23d5ac70f0Sopenharmony_ci#include "../include/asoundlib.h" 24d5ac70f0Sopenharmony_ci 25d5ac70f0Sopenharmony_cistatic char *pcm_name = "hw:0"; 26d5ac70f0Sopenharmony_cisnd_output_t *output = NULL; 27d5ac70f0Sopenharmony_ci 28d5ac70f0Sopenharmony_cistatic void usage(char *command) 29d5ac70f0Sopenharmony_ci{ 30d5ac70f0Sopenharmony_ci printf("Usage: %s [OPTION]... \n" 31d5ac70f0Sopenharmony_ci "\n" 32d5ac70f0Sopenharmony_ci "-h, --help help\n" 33d5ac70f0Sopenharmony_ci "-c, --capture capture tstamps \n" 34d5ac70f0Sopenharmony_ci "-d, --delay add delay \n" 35d5ac70f0Sopenharmony_ci "-D, --device=NAME select PCM by name \n" 36d5ac70f0Sopenharmony_ci "-p, --playback playback tstamps \n" 37d5ac70f0Sopenharmony_ci "-t, --ts_type=TYPE Compat(0),default(1),link(2),link_absolute(3),link_estimated(4),link_synchronized(5) \n" 38d5ac70f0Sopenharmony_ci "-r, --report show audio timestamp and accuracy validity\n" 39d5ac70f0Sopenharmony_ci , command); 40d5ac70f0Sopenharmony_ci} 41d5ac70f0Sopenharmony_ci 42d5ac70f0Sopenharmony_ci 43d5ac70f0Sopenharmony_cilong long timestamp2ns(snd_htimestamp_t t) 44d5ac70f0Sopenharmony_ci{ 45d5ac70f0Sopenharmony_ci long long nsec; 46d5ac70f0Sopenharmony_ci 47d5ac70f0Sopenharmony_ci nsec = t.tv_sec * 1000000000ULL; 48d5ac70f0Sopenharmony_ci nsec += t.tv_nsec; 49d5ac70f0Sopenharmony_ci 50d5ac70f0Sopenharmony_ci return nsec; 51d5ac70f0Sopenharmony_ci} 52d5ac70f0Sopenharmony_ci 53d5ac70f0Sopenharmony_cilong long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2) 54d5ac70f0Sopenharmony_ci{ 55d5ac70f0Sopenharmony_ci long long nsec1, nsec2; 56d5ac70f0Sopenharmony_ci 57d5ac70f0Sopenharmony_ci nsec1 = timestamp2ns(t1); 58d5ac70f0Sopenharmony_ci nsec2 = timestamp2ns(t2); 59d5ac70f0Sopenharmony_ci 60d5ac70f0Sopenharmony_ci return nsec1 - nsec2; 61d5ac70f0Sopenharmony_ci} 62d5ac70f0Sopenharmony_ci 63d5ac70f0Sopenharmony_civoid _gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp, 64d5ac70f0Sopenharmony_ci snd_htimestamp_t *trigger_timestamp, 65d5ac70f0Sopenharmony_ci snd_htimestamp_t *audio_timestamp, 66d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_config_t *audio_tstamp_config, 67d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_report_t *audio_tstamp_report, 68d5ac70f0Sopenharmony_ci snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay) 69d5ac70f0Sopenharmony_ci{ 70d5ac70f0Sopenharmony_ci int err; 71d5ac70f0Sopenharmony_ci snd_pcm_status_t *status; 72d5ac70f0Sopenharmony_ci 73d5ac70f0Sopenharmony_ci snd_pcm_status_alloca(&status); 74d5ac70f0Sopenharmony_ci 75d5ac70f0Sopenharmony_ci snd_pcm_status_set_audio_htstamp_config(status, audio_tstamp_config); 76d5ac70f0Sopenharmony_ci 77d5ac70f0Sopenharmony_ci if ((err = snd_pcm_status(handle, status)) < 0) { 78d5ac70f0Sopenharmony_ci printf("Stream status error: %s\n", snd_strerror(err)); 79d5ac70f0Sopenharmony_ci exit(0); 80d5ac70f0Sopenharmony_ci } 81d5ac70f0Sopenharmony_ci snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp); 82d5ac70f0Sopenharmony_ci snd_pcm_status_get_htstamp(status, timestamp); 83d5ac70f0Sopenharmony_ci snd_pcm_status_get_audio_htstamp(status, audio_timestamp); 84d5ac70f0Sopenharmony_ci snd_pcm_status_get_audio_htstamp_report(status, audio_tstamp_report); 85d5ac70f0Sopenharmony_ci *avail = snd_pcm_status_get_avail(status); 86d5ac70f0Sopenharmony_ci *delay = snd_pcm_status_get_delay(status); 87d5ac70f0Sopenharmony_ci} 88d5ac70f0Sopenharmony_ci 89d5ac70f0Sopenharmony_ci#define TIMESTAMP_FREQ 8 /* Hz */ 90d5ac70f0Sopenharmony_ci#define SAMPLE_FREQ 48000 91d5ac70f0Sopenharmony_ci#define PERIOD (SAMPLE_FREQ/TIMESTAMP_FREQ) 92d5ac70f0Sopenharmony_ci#define PCM_LINK /* sync start for playback and capture */ 93d5ac70f0Sopenharmony_ci#define TRACK_CAPTURE /* dump capture timing info */ 94d5ac70f0Sopenharmony_ci#define TRACK_PLAYBACK /* dump playback timing info */ 95d5ac70f0Sopenharmony_ci/*#define TRACK_SAMPLE_COUNTS */ /* show difference between sample counters and audiotimestamps returned by driver */ 96d5ac70f0Sopenharmony_ci#define PLAYBACK_BUFFERS 4 97d5ac70f0Sopenharmony_ci#define TSTAMP_TYPE SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW 98d5ac70f0Sopenharmony_ci 99d5ac70f0Sopenharmony_ci 100d5ac70f0Sopenharmony_ciint main(int argc, char *argv[]) 101d5ac70f0Sopenharmony_ci{ 102d5ac70f0Sopenharmony_ci int c; 103d5ac70f0Sopenharmony_ci int err; 104d5ac70f0Sopenharmony_ci unsigned int i; 105d5ac70f0Sopenharmony_ci snd_pcm_t *handle_p = NULL; 106d5ac70f0Sopenharmony_ci snd_pcm_t *handle_c = NULL; 107d5ac70f0Sopenharmony_ci snd_pcm_sframes_t frames; 108d5ac70f0Sopenharmony_ci snd_htimestamp_t tstamp_c, tstamp_p; 109d5ac70f0Sopenharmony_ci snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p; 110d5ac70f0Sopenharmony_ci snd_htimestamp_t audio_tstamp_c, audio_tstamp_p; 111d5ac70f0Sopenharmony_ci unsigned char buffer_p[PERIOD*4*4]; 112d5ac70f0Sopenharmony_ci unsigned char buffer_c[PERIOD*4*4]; 113d5ac70f0Sopenharmony_ci 114d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *hwparams_p; 115d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *hwparams_c; 116d5ac70f0Sopenharmony_ci 117d5ac70f0Sopenharmony_ci snd_pcm_sw_params_t *swparams_p; 118d5ac70f0Sopenharmony_ci snd_pcm_sw_params_t *swparams_c; 119d5ac70f0Sopenharmony_ci 120d5ac70f0Sopenharmony_ci snd_pcm_uframes_t frame_count_c = 0; 121d5ac70f0Sopenharmony_ci snd_pcm_uframes_t frame_count_p = 0; 122d5ac70f0Sopenharmony_ci 123d5ac70f0Sopenharmony_ci snd_pcm_sframes_t delay_p, delay_c; 124d5ac70f0Sopenharmony_ci snd_pcm_uframes_t avail_p, avail_c; 125d5ac70f0Sopenharmony_ci 126d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_config_t audio_tstamp_config_p; 127d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_config_t audio_tstamp_config_c; 128d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_report_t audio_tstamp_report_p; 129d5ac70f0Sopenharmony_ci snd_pcm_audio_tstamp_report_t audio_tstamp_report_c; 130d5ac70f0Sopenharmony_ci 131d5ac70f0Sopenharmony_ci int option_index; 132d5ac70f0Sopenharmony_ci static const char short_options[] = "hcpdrD:t:"; 133d5ac70f0Sopenharmony_ci 134d5ac70f0Sopenharmony_ci static const struct option long_options[] = { 135d5ac70f0Sopenharmony_ci {"capture", 0, 0, 'c'}, 136d5ac70f0Sopenharmony_ci {"delay", 0, 0, 'd'}, 137d5ac70f0Sopenharmony_ci {"device", required_argument, 0, 'D'}, 138d5ac70f0Sopenharmony_ci {"help", no_argument, 0, 'h'}, 139d5ac70f0Sopenharmony_ci {"playback", 0, 0, 'p'}, 140d5ac70f0Sopenharmony_ci {"ts_type", required_argument, 0, 't'}, 141d5ac70f0Sopenharmony_ci {"report", 0, 0, 'r'}, 142d5ac70f0Sopenharmony_ci {0, 0, 0, 0} 143d5ac70f0Sopenharmony_ci }; 144d5ac70f0Sopenharmony_ci 145d5ac70f0Sopenharmony_ci int do_delay = 0; 146d5ac70f0Sopenharmony_ci int do_playback = 0; 147d5ac70f0Sopenharmony_ci int do_capture = 0; 148d5ac70f0Sopenharmony_ci int type = 0; 149d5ac70f0Sopenharmony_ci int do_report = 0; 150d5ac70f0Sopenharmony_ci 151d5ac70f0Sopenharmony_ci while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { 152d5ac70f0Sopenharmony_ci switch (c) { 153d5ac70f0Sopenharmony_ci case 'h': 154d5ac70f0Sopenharmony_ci usage(argv[0]); 155d5ac70f0Sopenharmony_ci return 0; 156d5ac70f0Sopenharmony_ci case 'p': 157d5ac70f0Sopenharmony_ci do_playback = 1; 158d5ac70f0Sopenharmony_ci break; 159d5ac70f0Sopenharmony_ci case 'c': 160d5ac70f0Sopenharmony_ci do_capture = 1; 161d5ac70f0Sopenharmony_ci break; 162d5ac70f0Sopenharmony_ci case 'd': 163d5ac70f0Sopenharmony_ci do_delay = 1; 164d5ac70f0Sopenharmony_ci break; 165d5ac70f0Sopenharmony_ci case 'D': 166d5ac70f0Sopenharmony_ci pcm_name = optarg; 167d5ac70f0Sopenharmony_ci break; 168d5ac70f0Sopenharmony_ci case 't': 169d5ac70f0Sopenharmony_ci type = atoi(optarg); 170d5ac70f0Sopenharmony_ci break; 171d5ac70f0Sopenharmony_ci case 'r': 172d5ac70f0Sopenharmony_ci do_report = 1; 173d5ac70f0Sopenharmony_ci } 174d5ac70f0Sopenharmony_ci } 175d5ac70f0Sopenharmony_ci 176d5ac70f0Sopenharmony_ci memset(&audio_tstamp_config_p, 0, sizeof(snd_pcm_audio_tstamp_config_t)); 177d5ac70f0Sopenharmony_ci memset(&audio_tstamp_config_c, 0, sizeof(snd_pcm_audio_tstamp_config_t)); 178d5ac70f0Sopenharmony_ci memset(&audio_tstamp_report_p, 0, sizeof(snd_pcm_audio_tstamp_report_t)); 179d5ac70f0Sopenharmony_ci memset(&audio_tstamp_report_c, 0, sizeof(snd_pcm_audio_tstamp_report_t)); 180d5ac70f0Sopenharmony_ci 181d5ac70f0Sopenharmony_ci if (do_playback) { 182d5ac70f0Sopenharmony_ci if ((err = snd_pcm_open(&handle_p, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { 183d5ac70f0Sopenharmony_ci printf("Playback open error: %s\n", snd_strerror(err)); 184d5ac70f0Sopenharmony_ci goto _exit; 185d5ac70f0Sopenharmony_ci } 186d5ac70f0Sopenharmony_ci 187d5ac70f0Sopenharmony_ci if ((err = snd_pcm_set_params(handle_p, 188d5ac70f0Sopenharmony_ci SND_PCM_FORMAT_S16, 189d5ac70f0Sopenharmony_ci SND_PCM_ACCESS_RW_INTERLEAVED, 190d5ac70f0Sopenharmony_ci 2, 191d5ac70f0Sopenharmony_ci SAMPLE_FREQ, 192d5ac70f0Sopenharmony_ci 0, 193d5ac70f0Sopenharmony_ci 4*1000000/TIMESTAMP_FREQ)) < 0) { 194d5ac70f0Sopenharmony_ci printf("Playback open error: %s\n", snd_strerror(err)); 195d5ac70f0Sopenharmony_ci goto _exit; 196d5ac70f0Sopenharmony_ci } 197d5ac70f0Sopenharmony_ci 198d5ac70f0Sopenharmony_ci snd_pcm_hw_params_alloca(&hwparams_p); 199d5ac70f0Sopenharmony_ci/* get the current hwparams */ 200d5ac70f0Sopenharmony_ci err = snd_pcm_hw_params_current(handle_p, hwparams_p); 201d5ac70f0Sopenharmony_ci if (err < 0) { 202d5ac70f0Sopenharmony_ci printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err)); 203d5ac70f0Sopenharmony_ci goto _exit; 204d5ac70f0Sopenharmony_ci } 205d5ac70f0Sopenharmony_ci 206d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT)) 207d5ac70f0Sopenharmony_ci printf("Playback supports audio compat timestamps\n"); 208d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)) 209d5ac70f0Sopenharmony_ci printf("Playback supports audio default timestamps\n"); 210d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK)) 211d5ac70f0Sopenharmony_ci printf("Playback supports audio link timestamps\n"); 212d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE)) 213d5ac70f0Sopenharmony_ci printf("Playback supports audio link absolute timestamps\n"); 214d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED)) 215d5ac70f0Sopenharmony_ci printf("Playback supports audio link estimated timestamps\n"); 216d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_p, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED)) 217d5ac70f0Sopenharmony_ci printf("Playback supports audio link synchronized timestamps\n"); 218d5ac70f0Sopenharmony_ci 219d5ac70f0Sopenharmony_ci snd_pcm_sw_params_alloca(&swparams_p); 220d5ac70f0Sopenharmony_ci /* get the current swparams */ 221d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_current(handle_p, swparams_p); 222d5ac70f0Sopenharmony_ci if (err < 0) { 223d5ac70f0Sopenharmony_ci printf("Unable to determine current swparams_p: %s\n", snd_strerror(err)); 224d5ac70f0Sopenharmony_ci goto _exit; 225d5ac70f0Sopenharmony_ci } 226d5ac70f0Sopenharmony_ci 227d5ac70f0Sopenharmony_ci /* enable tstamp */ 228d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE); 229d5ac70f0Sopenharmony_ci if (err < 0) { 230d5ac70f0Sopenharmony_ci printf("Unable to set tstamp mode : %s\n", snd_strerror(err)); 231d5ac70f0Sopenharmony_ci goto _exit; 232d5ac70f0Sopenharmony_ci } 233d5ac70f0Sopenharmony_ci 234d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_set_tstamp_type(handle_p, swparams_p, TSTAMP_TYPE); 235d5ac70f0Sopenharmony_ci if (err < 0) { 236d5ac70f0Sopenharmony_ci printf("Unable to set tstamp type : %s\n", snd_strerror(err)); 237d5ac70f0Sopenharmony_ci goto _exit; 238d5ac70f0Sopenharmony_ci } 239d5ac70f0Sopenharmony_ci 240d5ac70f0Sopenharmony_ci /* write the sw parameters */ 241d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params(handle_p, swparams_p); 242d5ac70f0Sopenharmony_ci if (err < 0) { 243d5ac70f0Sopenharmony_ci printf("Unable to set swparams_p : %s\n", snd_strerror(err)); 244d5ac70f0Sopenharmony_ci goto _exit; 245d5ac70f0Sopenharmony_ci } 246d5ac70f0Sopenharmony_ci 247d5ac70f0Sopenharmony_ci } 248d5ac70f0Sopenharmony_ci 249d5ac70f0Sopenharmony_ci if (do_capture) { 250d5ac70f0Sopenharmony_ci 251d5ac70f0Sopenharmony_ci if ((err = snd_pcm_open(&handle_c, pcm_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { 252d5ac70f0Sopenharmony_ci printf("Capture open error: %s\n", snd_strerror(err)); 253d5ac70f0Sopenharmony_ci goto _exit; 254d5ac70f0Sopenharmony_ci } 255d5ac70f0Sopenharmony_ci if ((err = snd_pcm_set_params(handle_c, 256d5ac70f0Sopenharmony_ci SND_PCM_FORMAT_S16, 257d5ac70f0Sopenharmony_ci SND_PCM_ACCESS_RW_INTERLEAVED, 258d5ac70f0Sopenharmony_ci 2, 259d5ac70f0Sopenharmony_ci SAMPLE_FREQ, 260d5ac70f0Sopenharmony_ci 0, 261d5ac70f0Sopenharmony_ci 4*1000000/TIMESTAMP_FREQ)) < 0) { 262d5ac70f0Sopenharmony_ci printf("Capture open error: %s\n", snd_strerror(err)); 263d5ac70f0Sopenharmony_ci goto _exit; 264d5ac70f0Sopenharmony_ci } 265d5ac70f0Sopenharmony_ci 266d5ac70f0Sopenharmony_ci snd_pcm_hw_params_alloca(&hwparams_c); 267d5ac70f0Sopenharmony_ci /* get the current hwparams */ 268d5ac70f0Sopenharmony_ci err = snd_pcm_hw_params_current(handle_c, hwparams_c); 269d5ac70f0Sopenharmony_ci if (err < 0) { 270d5ac70f0Sopenharmony_ci printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err)); 271d5ac70f0Sopenharmony_ci goto _exit; 272d5ac70f0Sopenharmony_ci } 273d5ac70f0Sopenharmony_ci 274d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT)) 275d5ac70f0Sopenharmony_ci printf("Capture supports audio compat timestamps\n"); 276d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)) 277d5ac70f0Sopenharmony_ci printf("Capture supports audio default timestamps\n"); 278d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK)) 279d5ac70f0Sopenharmony_ci printf("Capture supports audio link timestamps\n"); 280d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE)) 281d5ac70f0Sopenharmony_ci printf("Capture supports audio link absolute timestamps\n"); 282d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED)) 283d5ac70f0Sopenharmony_ci printf("Capture supports audio link estimated timestamps\n"); 284d5ac70f0Sopenharmony_ci if (snd_pcm_hw_params_supports_audio_ts_type(hwparams_c, SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED)) 285d5ac70f0Sopenharmony_ci printf("Capture supports audio link synchronized timestamps\n"); 286d5ac70f0Sopenharmony_ci 287d5ac70f0Sopenharmony_ci snd_pcm_sw_params_alloca(&swparams_c); 288d5ac70f0Sopenharmony_ci /* get the current swparams */ 289d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_current(handle_c, swparams_c); 290d5ac70f0Sopenharmony_ci if (err < 0) { 291d5ac70f0Sopenharmony_ci printf("Unable to determine current swparams_c: %s\n", snd_strerror(err)); 292d5ac70f0Sopenharmony_ci goto _exit; 293d5ac70f0Sopenharmony_ci } 294d5ac70f0Sopenharmony_ci 295d5ac70f0Sopenharmony_ci /* enable tstamp */ 296d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE); 297d5ac70f0Sopenharmony_ci if (err < 0) { 298d5ac70f0Sopenharmony_ci printf("Unable to set tstamp mode : %s\n", snd_strerror(err)); 299d5ac70f0Sopenharmony_ci goto _exit; 300d5ac70f0Sopenharmony_ci } 301d5ac70f0Sopenharmony_ci 302d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params_set_tstamp_type(handle_c, swparams_c, TSTAMP_TYPE); 303d5ac70f0Sopenharmony_ci if (err < 0) { 304d5ac70f0Sopenharmony_ci printf("Unable to set tstamp type : %s\n", snd_strerror(err)); 305d5ac70f0Sopenharmony_ci goto _exit; 306d5ac70f0Sopenharmony_ci } 307d5ac70f0Sopenharmony_ci 308d5ac70f0Sopenharmony_ci /* write the sw parameters */ 309d5ac70f0Sopenharmony_ci err = snd_pcm_sw_params(handle_c, swparams_c); 310d5ac70f0Sopenharmony_ci if (err < 0) { 311d5ac70f0Sopenharmony_ci printf("Unable to set swparams_c : %s\n", snd_strerror(err)); 312d5ac70f0Sopenharmony_ci goto _exit; 313d5ac70f0Sopenharmony_ci } 314d5ac70f0Sopenharmony_ci } 315d5ac70f0Sopenharmony_ci 316d5ac70f0Sopenharmony_ci if (do_playback && do_capture) { 317d5ac70f0Sopenharmony_ci#ifdef PCM_LINK 318d5ac70f0Sopenharmony_ci if ((err = snd_pcm_link(handle_c, handle_p)) < 0) { 319d5ac70f0Sopenharmony_ci printf("Streams link error: %s\n", snd_strerror(err)); 320d5ac70f0Sopenharmony_ci exit(0); 321d5ac70f0Sopenharmony_ci } 322d5ac70f0Sopenharmony_ci#endif 323d5ac70f0Sopenharmony_ci } 324d5ac70f0Sopenharmony_ci 325d5ac70f0Sopenharmony_ci if (do_playback) { 326d5ac70f0Sopenharmony_ci i = PLAYBACK_BUFFERS; 327d5ac70f0Sopenharmony_ci while (i--) { 328d5ac70f0Sopenharmony_ci frames = snd_pcm_writei(handle_p, buffer_p, PERIOD); 329d5ac70f0Sopenharmony_ci if (frames < 0) { 330d5ac70f0Sopenharmony_ci printf("snd_pcm_writei failed: %s\n", snd_strerror(frames)); 331d5ac70f0Sopenharmony_ci goto _exit; 332d5ac70f0Sopenharmony_ci } 333d5ac70f0Sopenharmony_ci frame_count_p += frames; 334d5ac70f0Sopenharmony_ci } 335d5ac70f0Sopenharmony_ci 336d5ac70f0Sopenharmony_ci if (PLAYBACK_BUFFERS != 4) 337d5ac70f0Sopenharmony_ci snd_pcm_start(handle_p); 338d5ac70f0Sopenharmony_ci } 339d5ac70f0Sopenharmony_ci 340d5ac70f0Sopenharmony_ci if (do_capture) { 341d5ac70f0Sopenharmony_ci#ifndef PCM_LINK 342d5ac70f0Sopenharmony_ci /* need to start capture explicitly */ 343d5ac70f0Sopenharmony_ci snd_pcm_start(handle_c); 344d5ac70f0Sopenharmony_ci#else 345d5ac70f0Sopenharmony_ci if (!do_playback) 346d5ac70f0Sopenharmony_ci /* need to start capture explicitly */ 347d5ac70f0Sopenharmony_ci snd_pcm_start(handle_c); 348d5ac70f0Sopenharmony_ci#endif 349d5ac70f0Sopenharmony_ci } 350d5ac70f0Sopenharmony_ci 351d5ac70f0Sopenharmony_ci while (1) { 352d5ac70f0Sopenharmony_ci 353d5ac70f0Sopenharmony_ci if (do_capture) { 354d5ac70f0Sopenharmony_ci 355d5ac70f0Sopenharmony_ci frames = snd_pcm_wait(handle_c, -1); 356d5ac70f0Sopenharmony_ci if (frames < 0) { 357d5ac70f0Sopenharmony_ci printf("snd_pcm_wait failed: %s\n", snd_strerror(frames)); 358d5ac70f0Sopenharmony_ci goto _exit; 359d5ac70f0Sopenharmony_ci } 360d5ac70f0Sopenharmony_ci 361d5ac70f0Sopenharmony_ci frames = snd_pcm_readi(handle_c, buffer_c, PERIOD); 362d5ac70f0Sopenharmony_ci if (frames < 0) { 363d5ac70f0Sopenharmony_ci printf("snd_pcm_readi failed: %s\n", snd_strerror(frames)); 364d5ac70f0Sopenharmony_ci goto _exit; 365d5ac70f0Sopenharmony_ci } 366d5ac70f0Sopenharmony_ci frame_count_c += frames; 367d5ac70f0Sopenharmony_ci 368d5ac70f0Sopenharmony_ci#if defined(TRACK_CAPTURE) 369d5ac70f0Sopenharmony_ci audio_tstamp_config_c.type_requested = type; 370d5ac70f0Sopenharmony_ci audio_tstamp_config_c.report_delay = do_delay; 371d5ac70f0Sopenharmony_ci _gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, 372d5ac70f0Sopenharmony_ci &audio_tstamp_c, &audio_tstamp_config_c, &audio_tstamp_report_c, 373d5ac70f0Sopenharmony_ci &avail_c, &delay_c); 374d5ac70f0Sopenharmony_ci#if defined(TRACK_SAMPLE_COUNTS) 375d5ac70f0Sopenharmony_ci curr_count_c = frame_count_c + delay_c; /* read plus queued */ 376d5ac70f0Sopenharmony_ci 377d5ac70f0Sopenharmony_ci 378d5ac70f0Sopenharmony_ci printf("capture: curr_count %lli driver count %lli, delta %lli\n", 379d5ac70f0Sopenharmony_ci (long long)curr_count_c * 1000000000LL / SAMPLE_FREQ , 380d5ac70f0Sopenharmony_ci timestamp2ns(audio_tstamp_c), 381d5ac70f0Sopenharmony_ci (long long)curr_count_c * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_c) 382d5ac70f0Sopenharmony_ci ); 383d5ac70f0Sopenharmony_ci#endif 384d5ac70f0Sopenharmony_ci if (do_report) { 385d5ac70f0Sopenharmony_ci if (audio_tstamp_report_c.valid == 0) 386d5ac70f0Sopenharmony_ci printf("Audio capture timestamp report invalid - "); 387d5ac70f0Sopenharmony_ci if (audio_tstamp_report_c.accuracy_report == 0) 388d5ac70f0Sopenharmony_ci printf("Audio capture timestamp accuracy report invalid"); 389d5ac70f0Sopenharmony_ci printf("\n"); 390d5ac70f0Sopenharmony_ci } 391d5ac70f0Sopenharmony_ci 392d5ac70f0Sopenharmony_ci 393d5ac70f0Sopenharmony_ci printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli \t resolution %d ns \n", 394d5ac70f0Sopenharmony_ci timediff(tstamp_c, trigger_tstamp_c), 395d5ac70f0Sopenharmony_ci timestamp2ns(audio_tstamp_c), 396d5ac70f0Sopenharmony_ci timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c), audio_tstamp_report_c.accuracy 397d5ac70f0Sopenharmony_ci ); 398d5ac70f0Sopenharmony_ci#endif 399d5ac70f0Sopenharmony_ci } 400d5ac70f0Sopenharmony_ci 401d5ac70f0Sopenharmony_ci if (do_playback) { 402d5ac70f0Sopenharmony_ci frames = snd_pcm_writei(handle_p, buffer_p, PERIOD); 403d5ac70f0Sopenharmony_ci if (frames < 0) { 404d5ac70f0Sopenharmony_ci printf("snd_pcm_writei failed: %s\n", snd_strerror(frames)); 405d5ac70f0Sopenharmony_ci goto _exit; 406d5ac70f0Sopenharmony_ci } 407d5ac70f0Sopenharmony_ci 408d5ac70f0Sopenharmony_ci frame_count_p += frames; 409d5ac70f0Sopenharmony_ci 410d5ac70f0Sopenharmony_ci#if defined(TRACK_PLAYBACK) 411d5ac70f0Sopenharmony_ci 412d5ac70f0Sopenharmony_ci audio_tstamp_config_p.type_requested = type; 413d5ac70f0Sopenharmony_ci audio_tstamp_config_p.report_delay = do_delay; 414d5ac70f0Sopenharmony_ci _gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, 415d5ac70f0Sopenharmony_ci &audio_tstamp_p, &audio_tstamp_config_p, &audio_tstamp_report_p, 416d5ac70f0Sopenharmony_ci &avail_p, &delay_p); 417d5ac70f0Sopenharmony_ci 418d5ac70f0Sopenharmony_ci#if defined(TRACK_SAMPLE_COUNTS) 419d5ac70f0Sopenharmony_ci curr_count_p = frame_count_p - delay_p; /* written minus queued */ 420d5ac70f0Sopenharmony_ci 421d5ac70f0Sopenharmony_ci printf("playback: curr_count %lli driver count %lli, delta %lli\n", 422d5ac70f0Sopenharmony_ci (long long)curr_count_p * 1000000000LL / SAMPLE_FREQ , 423d5ac70f0Sopenharmony_ci timestamp2ns(audio_tstamp_p), 424d5ac70f0Sopenharmony_ci (long long)curr_count_p * 1000000000LL / SAMPLE_FREQ - timestamp2ns(audio_tstamp_p) 425d5ac70f0Sopenharmony_ci ); 426d5ac70f0Sopenharmony_ci#endif 427d5ac70f0Sopenharmony_ci if (do_report) { 428d5ac70f0Sopenharmony_ci if (audio_tstamp_report_p.valid == 0) 429d5ac70f0Sopenharmony_ci printf("Audio playback timestamp report invalid - "); 430d5ac70f0Sopenharmony_ci if (audio_tstamp_report_p.accuracy_report == 0) 431d5ac70f0Sopenharmony_ci printf("Audio playback timestamp accuracy report invalid"); 432d5ac70f0Sopenharmony_ci printf("\n"); 433d5ac70f0Sopenharmony_ci } 434d5ac70f0Sopenharmony_ci 435d5ac70f0Sopenharmony_ci printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli resolution %d ns\n", 436d5ac70f0Sopenharmony_ci timediff(tstamp_p, trigger_tstamp_p), 437d5ac70f0Sopenharmony_ci timestamp2ns(audio_tstamp_p), 438d5ac70f0Sopenharmony_ci timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p), audio_tstamp_report_p.accuracy 439d5ac70f0Sopenharmony_ci ); 440d5ac70f0Sopenharmony_ci#endif 441d5ac70f0Sopenharmony_ci } 442d5ac70f0Sopenharmony_ci 443d5ac70f0Sopenharmony_ci 444d5ac70f0Sopenharmony_ci } /* while(1) */ 445d5ac70f0Sopenharmony_ci 446d5ac70f0Sopenharmony_ci_exit: 447d5ac70f0Sopenharmony_ci if (handle_p) 448d5ac70f0Sopenharmony_ci snd_pcm_close(handle_p); 449d5ac70f0Sopenharmony_ci if (handle_c) 450d5ac70f0Sopenharmony_ci snd_pcm_close(handle_c); 451d5ac70f0Sopenharmony_ci 452d5ac70f0Sopenharmony_ci return 0; 453d5ac70f0Sopenharmony_ci} 454