mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Added async_direct method
This commit is contained in:
		
							parent
							
								
									2fb0fa541e
								
							
						
					
					
						commit
						3cce88b444
					
				
					 1 changed files with 144 additions and 12 deletions
				
			
		
							
								
								
									
										156
									
								
								test/pcm.c
									
										
									
									
									
								
							
							
						
						
									
										156
									
								
								test/pcm.c
									
										
									
									
									
								
							|  | @ -413,6 +413,138 @@ static int async_loop(snd_pcm_t *handle, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  *   Transfer method - asynchronous notification + direct write | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static void async_direct_callback(snd_async_handler_t *ahandler) | ||||||
|  | { | ||||||
|  | 	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler); | ||||||
|  | 	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler); | ||||||
|  | 	const snd_pcm_channel_area_t *my_areas; | ||||||
|  | 	snd_pcm_uframes_t offset, frames, size; | ||||||
|  | 	snd_pcm_sframes_t avail, commitres; | ||||||
|  | 	snd_pcm_state_t state; | ||||||
|  | 	int first = 0, err; | ||||||
|  | 	 | ||||||
|  | 	while (1) { | ||||||
|  | 		state = snd_pcm_state(handle); | ||||||
|  | 		if (state == SND_PCM_STATE_XRUN) { | ||||||
|  | 			err = xrun_recovery(handle, -EPIPE); | ||||||
|  | 			if (err < 0) { | ||||||
|  | 				printf("XRUN recovery failed: %s\n", snd_strerror(err)); | ||||||
|  | 				exit(EXIT_FAILURE); | ||||||
|  | 			} | ||||||
|  | 			first = 1; | ||||||
|  | 		} else if (state == SND_PCM_STATE_SUSPENDED) { | ||||||
|  | 			err = xrun_recovery(handle, -ESTRPIPE); | ||||||
|  | 			if (err < 0) { | ||||||
|  | 				printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); | ||||||
|  | 				exit(EXIT_FAILURE); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		avail = snd_pcm_avail_update(handle); | ||||||
|  | 		if (avail < 0) { | ||||||
|  | 			err = xrun_recovery(handle, avail); | ||||||
|  | 			if (err < 0) { | ||||||
|  | 				printf("avail update failed: %s\n", snd_strerror(err)); | ||||||
|  | 				exit(EXIT_FAILURE); | ||||||
|  | 			} | ||||||
|  | 			first = 1; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (avail < period_size) { | ||||||
|  | 			if (first) { | ||||||
|  | 				first = 0; | ||||||
|  | 				err = snd_pcm_start(handle); | ||||||
|  | 				if (err < 0) { | ||||||
|  | 					printf("Start error: %s\n", snd_strerror(err)); | ||||||
|  | 					exit(EXIT_FAILURE); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		size = period_size; | ||||||
|  | 		while (size > 0) { | ||||||
|  | 			frames = size; | ||||||
|  | 			err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames); | ||||||
|  | 			if (err < 0) { | ||||||
|  | 				if ((err = xrun_recovery(handle, err)) < 0) { | ||||||
|  | 					printf("MMAP begin avail error: %s\n", snd_strerror(err)); | ||||||
|  | 					exit(EXIT_FAILURE); | ||||||
|  | 				} | ||||||
|  | 				first = 1; | ||||||
|  | 			} | ||||||
|  | 			generate_sine(my_areas, offset, frames, &data->phase); | ||||||
|  | 			commitres = snd_pcm_mmap_commit(handle, offset, frames); | ||||||
|  | 			if (commitres < 0 || commitres != frames) { | ||||||
|  | 				if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) { | ||||||
|  | 					printf("MMAP commit error: %s\n", snd_strerror(err)); | ||||||
|  | 					exit(EXIT_FAILURE); | ||||||
|  | 				} | ||||||
|  | 				first = 1; | ||||||
|  | 			} | ||||||
|  | 			size -= frames; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int async_direct_loop(snd_pcm_t *handle, | ||||||
|  | 			     signed short *samples, | ||||||
|  | 			     snd_pcm_channel_area_t *areas) | ||||||
|  | { | ||||||
|  | 	struct async_private_data data; | ||||||
|  | 	snd_async_handler_t *ahandler; | ||||||
|  | 	const snd_pcm_channel_area_t *my_areas; | ||||||
|  | 	snd_pcm_uframes_t offset, frames, size; | ||||||
|  | 	snd_pcm_sframes_t commitres; | ||||||
|  | 	int err, count; | ||||||
|  | 
 | ||||||
|  | 	data.samples = NULL;	/* we do not require the global sample area for direct write */ | ||||||
|  | 	data.areas = NULL;	/* we do not require the global areas for direct write */ | ||||||
|  | 	data.phase = 0; | ||||||
|  | 	err = snd_async_add_pcm_handler(&ahandler, handle, async_direct_callback, &data); | ||||||
|  | 	if (err < 0) { | ||||||
|  | 		printf("Unable to register async handler\n"); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  | 	for (count = 0; count < 2; count++) { | ||||||
|  | 		size = period_size; | ||||||
|  | 		while (size > 0) { | ||||||
|  | 			frames = size; | ||||||
|  | 			err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames); | ||||||
|  | 			if (err < 0) { | ||||||
|  | 				if ((err = xrun_recovery(handle, err)) < 0) { | ||||||
|  | 					printf("MMAP begin avail error: %s\n", snd_strerror(err)); | ||||||
|  | 					exit(EXIT_FAILURE); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			generate_sine(my_areas, offset, frames, &data.phase); | ||||||
|  | 			commitres = snd_pcm_mmap_commit(handle, offset, frames); | ||||||
|  | 			if (commitres < 0 || commitres != frames) { | ||||||
|  | 				if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) { | ||||||
|  | 					printf("MMAP commit error: %s\n", snd_strerror(err)); | ||||||
|  | 					exit(EXIT_FAILURE); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			size -= frames; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	err = snd_pcm_start(handle); | ||||||
|  | 	if (err < 0) { | ||||||
|  | 		printf("Start error: %s\n", snd_strerror(err)); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* because all other work is done in the signal handler,
 | ||||||
|  | 	   suspend the process */ | ||||||
|  | 	while (1) { | ||||||
|  | 		sleep(1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  *   Transfer method - direct write only |  *   Transfer method - direct write only | ||||||
|  */ |  */ | ||||||
|  | @ -548,6 +680,7 @@ static struct transfer_method transfer_methods[] = { | ||||||
| 	{ "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop }, | 	{ "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop }, | ||||||
| 	{ "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, write_and_poll_loop }, | 	{ "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, write_and_poll_loop }, | ||||||
| 	{ "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop }, | 	{ "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop }, | ||||||
|  | 	{ "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, async_direct_loop }, | ||||||
| 	{ "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_loop }, | 	{ "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_loop }, | ||||||
| 	{ "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, direct_loop }, | 	{ "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, direct_loop }, | ||||||
| 	{ "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_write_loop }, | 	{ "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_write_loop }, | ||||||
|  | @ -557,18 +690,17 @@ static struct transfer_method transfer_methods[] = { | ||||||
| static void help(void) | static void help(void) | ||||||
| { | { | ||||||
| 	int k; | 	int k; | ||||||
| 	printf("\
 | 	printf( | ||||||
| Usage: latency [OPTION]... [FILE]... | "Usage: latency [OPTION]... [FILE]...\n" | ||||||
| -h,--help       help | "-h,--help	help\n" | ||||||
| -D,--device     playback device | "-D,--device	playback device\n" | ||||||
| -r,--rate	stream rate in Hz | "-r,--rate	stream rate in Hz\n" | ||||||
| -c,--channels	count of channels in stream | "-c,--channels	count of channels in stream\n" | ||||||
| -f,--frequency  sine wave frequency in Hz | "-f,--frequency	sine wave frequency in Hz\n" | ||||||
| -b,--buffer     ring buffer size in us | "-b,--buffer	ring buffer size in us\n" | ||||||
| -p,--period     period size in us | "-p,--period	period size in us\n" | ||||||
| -m,--method     transfer method | "-m,--method	transfer method\n" | ||||||
| 
 | "\n"); | ||||||
| "); |  | ||||||
|         printf("Recognized sample formats are:"); |         printf("Recognized sample formats are:"); | ||||||
|         for (k = 0; k < SND_PCM_FORMAT_LAST; ++(unsigned long) k) { |         for (k = 0; k < SND_PCM_FORMAT_LAST; ++(unsigned long) k) { | ||||||
|                 const char *s = snd_pcm_format_name(k); |                 const char *s = snd_pcm_format_name(k); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela