mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Ported to new API
This commit is contained in:
		
							parent
							
								
									9059d26167
								
							
						
					
					
						commit
						eee70747eb
					
				
					 1 changed files with 80 additions and 163 deletions
				
			
		
							
								
								
									
										243
									
								
								test/latency.c
									
										
									
									
									
								
							
							
						
						
									
										243
									
								
								test/latency.c
									
										
									
									
									
								
							|  | @ -4,17 +4,17 @@ | ||||||
| #include <sched.h> | #include <sched.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include "../include/asoundlib.h" | #include "../include/asoundlib.h" | ||||||
|  | #include <sys/time.h> | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| #define USE_FRAGMENT_MODE	/* latency is twice more than for frame mode!!! */ | #define USE_FRAGMENT_MODE	/* latency is twice more than for frame mode!!! */ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #define USED_RATE	48000 | //#define USED_RATE	48000
 | ||||||
| //#define LATENCY_MIN	8192
 | #define USED_RATE       22050 | ||||||
| #define LATENCY_MIN	32 | #define LATENCY_MIN	32 | ||||||
| #define LATENCY_MAX	8192		/* in bytes */ | #define LATENCY_MAX	2048		/* in frames */ | ||||||
| //#define LOOP_LIMIT	(8192UL * 2)
 | #define LOOP_LIMIT	(30UL * USED_RATE)	/* 30 seconds */ | ||||||
| #define LOOP_LIMIT	(30 * 176400UL)	/* 30 seconds */ |  | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| static char *xitoa(int aaa) | static char *xitoa(int aaa) | ||||||
|  | @ -26,39 +26,6 @@ static char *xitoa(int aaa) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| static int syncro(snd_pcm_t *phandle, snd_pcm_t *chandle) |  | ||||||
| { |  | ||||||
| 	snd_pcm_stream_info_t pinfo, cinfo; |  | ||||||
| 	int err; |  | ||||||
| 	 |  | ||||||
| 	bzero(&pinfo, sizeof(pinfo)); |  | ||||||
| 	bzero(&cinfo, sizeof(cinfo)); |  | ||||||
| 	pinfo.stream = SND_PCM_STREAM_PLAYBACK; |  | ||||||
| 	cinfo.stream = SND_PCM_STREAM_CAPTURE; |  | ||||||
| 	if ((err = snd_pcm_stream_info(phandle, &pinfo)) < 0) { |  | ||||||
| 		printf("Playback info error: %s\n", snd_strerror(err)); |  | ||||||
| 		exit(0); |  | ||||||
| 	} |  | ||||||
| 	if ((err = snd_pcm_stream_info(chandle, &cinfo)) < 0) { |  | ||||||
| 		printf("Capture info error: %s\n", snd_strerror(err)); |  | ||||||
| 		exit(0); |  | ||||||
| 	} |  | ||||||
| 	if (pinfo.sync.id32[0] == 0 && pinfo.sync.id32[1] == 0 && |  | ||||||
| 	    pinfo.sync.id32[2] == 0 && pinfo.sync.id32[3] == 0) |  | ||||||
| 		return 0; |  | ||||||
| 	if (memcmp(&pinfo.sync, &cinfo.sync, sizeof(pinfo.sync))) |  | ||||||
| 		return 0; |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void syncro_id(snd_pcm_sync_t *sync) |  | ||||||
| { |  | ||||||
| 	sync->id32[0] = 0;	/* application */ |  | ||||||
| 	sync->id32[1] = getpid(); |  | ||||||
| 	sync->id32[2] = 0x89abcdef; |  | ||||||
| 	sync->id32[3] = 0xaaaaaaaa; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  *  This small demo program can be used for measuring latency between |  *  This small demo program can be used for measuring latency between | ||||||
|  *  capture and playback. This latency is measured from driver (diff when |  *  capture and playback. This latency is measured from driver (diff when | ||||||
|  | @ -67,15 +34,14 @@ static void syncro_id(snd_pcm_sync_t *sync) | ||||||
|  *  Used format is 44100Hz, Signed Little Endian 16-bit, Stereo. |  *  Used format is 44100Hz, Signed Little Endian 16-bit, Stereo. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int sync, int *queue) | int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int sync, int *bufsize) | ||||||
| { | { | ||||||
| 	int err, again; | 	int err; | ||||||
| 	snd_pcm_stream_params_t params; | 	snd_pcm_params_t params; | ||||||
| 	snd_pcm_stream_setup_t psetup, csetup; | 	snd_pcm_setup_t psetup, csetup; | ||||||
| 
 | 
 | ||||||
| 	bzero(¶ms, sizeof(params)); | 	bzero(¶ms, sizeof(params)); | ||||||
| 	params.stream = SND_PCM_STREAM_PLAYBACK; | #ifdef USE_FRAGMENT_MODE | ||||||
| #ifdef USE_BLOCK_MODE |  | ||||||
| 	params.mode = SND_PCM_MODE_FRAGMENT; | 	params.mode = SND_PCM_MODE_FRAGMENT; | ||||||
| #else | #else | ||||||
| 	params.mode = SND_PCM_MODE_FRAME; | 	params.mode = SND_PCM_MODE_FRAME; | ||||||
|  | @ -87,107 +53,68 @@ int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int sync, int *queue) | ||||||
| 	params.start_mode = SND_PCM_START_GO; | 	params.start_mode = SND_PCM_START_GO; | ||||||
| 	params.xrun_mode = SND_PCM_XRUN_DRAIN; | 	params.xrun_mode = SND_PCM_XRUN_DRAIN; | ||||||
| 	params.time = 1; | 	params.time = 1; | ||||||
| 	*queue += 16; | 	*bufsize += 4; | ||||||
| #if 0 | 
 | ||||||
| 	params.buf.stream.fill = SND_PCM_FILL_SILENCE; |  | ||||||
| 	params.buf.stream.max_fill = 1024; |  | ||||||
| #else |  | ||||||
| 	params.buf.stream.fill = SND_PCM_FILL_NONE; |  | ||||||
| #endif |  | ||||||
| 	if (sync) |  | ||||||
| 		syncro_id(¶ms.sync); |  | ||||||
|       __again: |       __again: | ||||||
| 	if (*queue > LATENCY_MAX) | 	if (*bufsize > LATENCY_MAX) | ||||||
| 		return -1; | 		return -1; | ||||||
|       	again = 0; | 	params.frag_size = *bufsize / 2; | ||||||
|       	params.stream = SND_PCM_STREAM_PLAYBACK; | 	params.frames_min = 1; | ||||||
| 	params.frag_size = *queue; | 	params.buffer_size = *bufsize; | ||||||
| #ifdef USE_BLOCK_MODE | 
 | ||||||
| 	params.buffer_size = *queue * 2; | 	if ((err = snd_pcm_params(phandle, ¶ms)) < 0) { | ||||||
| 	params.buf.block.frags_min = 1; |  | ||||||
| #else |  | ||||||
| 	params.buffer_size = *queue; |  | ||||||
| 	params.buf.stream.bytes_min = 2; |  | ||||||
| #endif |  | ||||||
| 	if ((err = snd_pcm_stream_params(phandle, ¶ms)) < 0) { |  | ||||||
| 		printf("Playback params error: %s\n", snd_strerror(err)); | 		printf("Playback params error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| 	params.stream = SND_PCM_STREAM_CAPTURE; | 	if ((err = snd_pcm_params(chandle, ¶ms)) < 0) { | ||||||
| 	if ((err = snd_pcm_stream_params(chandle, ¶ms)) < 0) { |  | ||||||
| 		printf("Capture params error: %s\n", snd_strerror(err)); | 		printf("Capture params error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| 	bzero(&psetup, sizeof(psetup)); | 	bzero(&psetup, sizeof(psetup)); | ||||||
| 	psetup.stream = SND_PCM_STREAM_PLAYBACK; | 	if ((err = snd_pcm_setup(phandle, &psetup)) < 0) { | ||||||
| 	if ((err = snd_pcm_stream_setup(phandle, &psetup)) < 0) { |  | ||||||
| 		printf("Playback setup error: %s\n", snd_strerror(err)); | 		printf("Playback setup error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| 	bzero(&csetup, sizeof(csetup)); | 	bzero(&csetup, sizeof(csetup)); | ||||||
| 	csetup.stream = SND_PCM_STREAM_CAPTURE; | 	if ((err = snd_pcm_setup(chandle, &csetup)) < 0) { | ||||||
| 	if ((err = snd_pcm_stream_setup(chandle, &csetup)) < 0) { |  | ||||||
| 		printf("Capture setup error: %s\n", snd_strerror(err)); | 		printf("Capture setup error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| #ifdef USE_BLOCK_MODE | 	if (psetup.buffer_size > *bufsize) { | ||||||
| 	if (psetup.buffer_size / 2 > *queue) { | 		*bufsize = psetup.buffer_size; | ||||||
| 		*queue = psetup.buffer_size / 2; |  | ||||||
| 		again++; |  | ||||||
| 	} |  | ||||||
| #else |  | ||||||
| 	if (psetup.buffer_size > *queue) { |  | ||||||
| 		*queue = psetup.buffer_size; |  | ||||||
| 		again++; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 	if (again) |  | ||||||
| 		goto __again; | 		goto __again; | ||||||
| 	if ((err = snd_pcm_playback_prepare(phandle)) < 0) { | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((err = snd_pcm_prepare(phandle)) < 0) { | ||||||
| 		printf("Playback prepare error: %s\n", snd_strerror(err)); | 		printf("Playback prepare error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| 	if ((err = snd_pcm_capture_prepare(chandle)) < 0) { | 	if ((err = snd_pcm_prepare(chandle)) < 0) { | ||||||
| 		printf("Capture prepare error: %s\n", snd_strerror(err)); | 		printf("Capture prepare error: %s\n", snd_strerror(err)); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	}	 | 	} | ||||||
| 	printf("Trying latency %i (playback rate = %iHz, capture rate = %iHz)...\n", | 	snd_pcm_dump(phandle, stdout); | ||||||
| #ifdef USE_BLOCK_MODE | 	snd_pcm_dump(chandle, stdout); | ||||||
| 		*queue * 2,  | 	printf("Trying latency %i...\n", *bufsize); | ||||||
| #else |  | ||||||
| 		*queue,  |  | ||||||
| #endif |  | ||||||
| 		psetup.format.rate, csetup.format.rate); |  | ||||||
| 	printf("Fragment boundary = %li/%li, Position boundary = %li/%li\n", (long)psetup.frag_boundary, (long)csetup.frag_boundary, (long)psetup.pos_boundary, (long)psetup.pos_boundary); |  | ||||||
| 	printf("Frags = %li/%li, Buffer size = %li/%li\n", (long)psetup.frags, (long)csetup.frags, (long)psetup.buffer_size, (long)csetup.buffer_size); |  | ||||||
| 	fflush(stdout); | 	fflush(stdout); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void showstat(snd_pcm_t *handle, int stream, snd_pcm_stream_status_t *rstatus, size_t bytes) | void showstat(snd_pcm_t *handle, snd_pcm_status_t *rstatus, size_t frames) | ||||||
| { | { | ||||||
| 	int err; | 	int err; | ||||||
| 	snd_pcm_stream_status_t status; | 	snd_pcm_status_t status; | ||||||
| 	char *str; |  | ||||||
| 
 | 
 | ||||||
| 	str = stream == SND_PCM_STREAM_CAPTURE ? "Capture" : "Playback"; |  | ||||||
| 	bzero(&status, sizeof(status)); | 	bzero(&status, sizeof(status)); | ||||||
| 	status.stream = stream; | 	if ((err = snd_pcm_status(handle, &status)) < 0) { | ||||||
| 	if ((err = snd_pcm_stream_status(handle, &status)) < 0) { | 		printf("Stream status error: %s\n", snd_strerror(err)); | ||||||
| 		printf("Stream %s status error: %s\n", str, snd_strerror(err)); |  | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	} | 	} | ||||||
| 	printf("%s:\n", str); | 	printf("  state = %i\n", status.state); | ||||||
| 	printf("  status = %i\n", status.status); | 	printf("  frames = %i\n", frames); | ||||||
| 	printf("  bytes = %i\n", bytes); | 	printf("  frame_io = %li\n", (long)status.frame_io); | ||||||
| 	printf("  frag_io = %li\n", (long)status.frag_io); | 	printf("  frame_data = %li\n", (long)status.frame_data); | ||||||
| 	printf("  frag_data = %li\n", (long)status.frag_data); | 	printf("  frames_avail = %li\n", (long)status.frames_avail); | ||||||
| 	printf("  frag_used = %li\n", (long)status.frags_used); |  | ||||||
| 	printf("  frag_free = %li\n", (long)status.frags_free); |  | ||||||
| 	printf("  pos_io = %li\n", (long)status.pos_io); |  | ||||||
| 	printf("  pos_data = %li\n", (long)status.pos_data); |  | ||||||
| 	printf("  bytes_used = %li\n", (long)status.bytes_used); |  | ||||||
| 	printf("  bytes_free = %li\n", (long)status.bytes_free); |  | ||||||
| 	if (rstatus) | 	if (rstatus) | ||||||
| 		*rstatus = status; | 		*rstatus = status; | ||||||
| } | } | ||||||
|  | @ -223,7 +150,7 @@ long timediff(struct timeval t1, struct timeval t2) | ||||||
| 	return (t1.tv_sec * 1000000) + l; | 	return (t1.tv_sec * 1000000) + l; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *bytes) | long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames) | ||||||
| { | { | ||||||
| 	long r; | 	long r; | ||||||
| 	 | 	 | ||||||
|  | @ -231,29 +158,27 @@ long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *bytes) | ||||||
| 		r = snd_pcm_read(handle, buf, len); | 		r = snd_pcm_read(handle, buf, len); | ||||||
| 	} while (r == -EAGAIN); | 	} while (r == -EAGAIN); | ||||||
| 	if (r > 0) | 	if (r > 0) | ||||||
| 		*bytes += r; | 		*frames += r; | ||||||
| 	// printf("read = %li\n", r);
 | 	// printf("read = %li\n", r);
 | ||||||
| 	// showstat(handle, SND_PCM_STREAM_CAPTURE, NULL);
 | 	// showstat(handle, NULL);
 | ||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *bytes) | long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames) | ||||||
| { | { | ||||||
| 	long r; | 	long r; | ||||||
| 
 | 
 | ||||||
| 	while (len > 0) { | 	while (len > 0) { | ||||||
| 		r = snd_pcm_write(handle, buf, len); | 		r = snd_pcm_write(handle, buf, len); | ||||||
| #ifndef USE_BLOCK_MODE |  | ||||||
| 		if (r == -EAGAIN) | 		if (r == -EAGAIN) | ||||||
| 			continue; | 			continue; | ||||||
| #endif |  | ||||||
| 		// printf("write = %li\n", r);
 | 		// printf("write = %li\n", r);
 | ||||||
| 		if (r < 0) | 		if (r < 0) | ||||||
| 			return r; | 			return r; | ||||||
| 		// showstat(handle, SND_PCM_STREAM_PLAYBACK, NULL);
 | 		// showstat(handle, NULL);
 | ||||||
| 		buf += r; | 		buf += r * 4; | ||||||
| 		len -= r; | 		len -= r; | ||||||
| 		*bytes += r; | 		*frames += r; | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -261,79 +186,71 @@ long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *bytes) | ||||||
| int main(void) | int main(void) | ||||||
| { | { | ||||||
| 	snd_pcm_t *phandle, *chandle; | 	snd_pcm_t *phandle, *chandle; | ||||||
| 	char buffer[LATENCY_MAX];	/* max two fragments by 4096 bytes */ | 	char buffer[LATENCY_MAX*4]; | ||||||
| 	int pcard = 0, pdevice = 0; | 	int pcard = 0, pdevice = 0; | ||||||
| 	int ccard = 0, cdevice = 0; | 	int ccard = 0, cdevice = 0; | ||||||
| 	int err, latency = LATENCY_MIN - 16; | 	int err, latency = LATENCY_MIN - 4; | ||||||
| 	int size, ok; | 	int size, ok; | ||||||
| 	int sync; | 	int sync; | ||||||
| 	snd_pcm_sync_t ssync; | 	snd_pcm_status_t pstatus, cstatus; | ||||||
| 	snd_pcm_stream_status_t pstatus, cstatus; |  | ||||||
| 	ssize_t r; | 	ssize_t r; | ||||||
| 	size_t bytes_in, bytes_out; | 	size_t frames_in, frames_out; | ||||||
|  | 	snd_pcm_synchro_request_t sync_req[2]; | ||||||
| 
 | 
 | ||||||
| 	setscheduler(); | 	setscheduler(); | ||||||
| 	if ((err = snd_pcm_plug_open(&phandle, pcard, pdevice, SND_PCM_OPEN_PLAYBACK|SND_PCM_NONBLOCK_PLAYBACK)) < 0) { | 	if ((err = snd_pcm_plug_open(&phandle, pcard, pdevice, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { | ||||||
| 		printf("Playback open error: %s\n", snd_strerror(err)); | 		printf("Playback open error: %s\n", snd_strerror(err)); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 	if ((err = snd_pcm_plug_open(&chandle, ccard, cdevice, SND_PCM_OPEN_CAPTURE|SND_PCM_NONBLOCK_CAPTURE)) < 0) { | 	if ((err = snd_pcm_plug_open(&chandle, ccard, cdevice, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { | ||||||
| 		printf("Record open error: %s\n", snd_strerror(err)); | 		printf("Record open error: %s\n", snd_strerror(err)); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| #ifdef USE_BLOCK_MODE | 	memset(sync_req, 0, sizeof(sync_req)); | ||||||
|  | 	sync_req[0].handle = phandle; | ||||||
|  | 	sync_req[0].result = -3; | ||||||
|  | 	sync_req[1].handle = chandle; | ||||||
|  | #ifdef USE_FRAGMENT_MODE | ||||||
| 	printf("Using fragment mode...\n"); | 	printf("Using fragment mode...\n"); | ||||||
| #else | #else | ||||||
| 	printf("Using frame mode...\n"); | 	printf("Using frame mode...\n"); | ||||||
| #endif | #endif | ||||||
| 	sync = syncro(phandle, chandle); | 	printf("Loop limit is %li frames\n", LOOP_LIMIT); | ||||||
| 	if (sync) |  | ||||||
| 		printf("Using hardware synchronization mode\n"); |  | ||||||
| 	printf("Loop limit is %li bytes\n", LOOP_LIMIT); |  | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		bytes_in = bytes_out = 0; | 		frames_in = frames_out = 0; | ||||||
| 		if (setparams(phandle, chandle, sync, &latency) < 0) | 		if (setparams(phandle, chandle, sync, &latency) < 0) | ||||||
| 			break; | 			break; | ||||||
| 		if (snd_pcm_format_set_silence(SND_PCM_SFMT_S16_LE, buffer, latency) < 0) { | 		if (snd_pcm_format_set_silence(SND_PCM_SFMT_S16_LE, buffer, latency*2) < 0) { | ||||||
| 			fprintf(stderr, "silence error\n"); | 			fprintf(stderr, "silence error\n"); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		if (writebuf(phandle, buffer, latency, &bytes_out) < 0) { | 		if (writebuf(phandle, buffer, latency, &frames_out) < 0) { | ||||||
| 			fprintf(stderr, "write error\n"); | 			fprintf(stderr, "write error\n"); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| #ifdef USE_BLOCK_MODE	/* at least two fragments MUST BE filled !!! */ | 
 | ||||||
| 		if (writebuf(phandle, buffer, latency, &bytes_out) < 0) | 		if ((err = snd_pcm_synchro(SND_PCM_SYNCHRO_GO, 2, sync_req, SND_PCM_SYNC_MODE_NORMAL)) < 0) { | ||||||
| 			break; | 			printf("Sync go error: %s\n", snd_strerror(err)); | ||||||
| #endif | 			exit(0); | ||||||
| 		if (sync) { | 		} | ||||||
| 			syncro_id(&ssync); | 		if (sync_req[0].tstamp.tv_sec == sync_req[1].tstamp.tv_sec && | ||||||
| 			if ((err = snd_pcm_sync_go(phandle, &ssync)) < 0) { | 		    sync_req[0].tstamp.tv_usec == sync_req[1].tstamp.tv_usec) { | ||||||
| 				printf("Sync go error: %s\n", snd_strerror(err)); | 			printf("Hardware sync\n"); | ||||||
| 				exit(0); |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			if ((err = snd_pcm_capture_go(chandle)) < 0) { |  | ||||||
| 				printf("Capture go error: %s\n", snd_strerror(err)); |  | ||||||
| 				exit(0); |  | ||||||
| 			} |  | ||||||
| 			if ((err = snd_pcm_playback_go(phandle)) < 0) { |  | ||||||
| 				printf("Playback go error: %s\n", snd_strerror(err)); |  | ||||||
| 				exit(0); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		ok = 1; | 		ok = 1; | ||||||
| 		size = 0; | 		size = 0; | ||||||
| 		while (ok && bytes_in < LOOP_LIMIT) { | 		while (ok && frames_in < LOOP_LIMIT) { | ||||||
| 			if ((r = readbuf(chandle, buffer, latency, &bytes_in)) < 0) | 			if ((r = readbuf(chandle, buffer, latency, &frames_in)) < 0) | ||||||
| 				ok = 0; | 				ok = 0; | ||||||
| 			if (r > 0 && writebuf(phandle, buffer, r, &bytes_out) < 0) | 			else if (writebuf(phandle, buffer, r, &frames_out) < 0) | ||||||
| 				ok = 0; | 				ok = 0; | ||||||
| 		} | 		} | ||||||
| 		showstat(phandle, SND_PCM_STREAM_PLAYBACK, &pstatus, bytes_out); | 		printf("Playback:\n"); | ||||||
| 		showstat(chandle, SND_PCM_STREAM_CAPTURE, &cstatus, bytes_in); | 		showstat(phandle, &pstatus, frames_out); | ||||||
| 		snd_pcm_capture_flush(chandle); | 		printf("Capture:\n"); | ||||||
| 		snd_pcm_playback_flush(phandle); | 		showstat(chandle, &cstatus, frames_in); | ||||||
|  | 		snd_pcm_flush(chandle); | ||||||
|  | 		snd_pcm_flush(phandle); | ||||||
| 		if (ok) { | 		if (ok) { | ||||||
| 			printf("Playback time = %li.%i, Record time = %li.%i, diff = %li\n", | 			printf("Playback time = %li.%i, Record time = %li.%i, diff = %li\n", | ||||||
| 			       pstatus.stime.tv_sec, | 			       pstatus.stime.tv_sec, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Abramo Bagnara
						Abramo Bagnara