⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aplay.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  aplay.c - plays and records * *      CREATIVE LABS CHANNEL-files *      Microsoft WAVE-files *      SPARC AUDIO .AU-files *      Raw Data * *  Copyright (c) by Jaroslav Kysela <perex@perex.cz> *  Based on vplay program by Michael Beck * * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#define _GNU_SOURCE#include <stdio.h>#include <malloc.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <fcntl.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <time.h>#include <locale.h>#include <alsa/asoundlib.h>#include <assert.h>#include <sys/poll.h>#include <sys/uio.h>#include <sys/time.h>#include <sys/signal.h>#include <asm/byteorder.h>#include "aconfig.h"#include "gettext.h"#include "formats.h"#include "version.h"#ifndef LLONG_MAX#define LLONG_MAX    9223372036854775807LL#endif#define DEFAULT_FORMAT		SND_PCM_FORMAT_U8#define DEFAULT_SPEED 		8000#define FORMAT_DEFAULT		-1#define FORMAT_RAW		0#define FORMAT_VOC		1#define FORMAT_WAVE		2#define FORMAT_AU		3/* global data */static snd_pcm_sframes_t (*readi_func)(snd_pcm_t *handle, void *buffer, snd_pcm_uframes_t size);static snd_pcm_sframes_t (*writei_func)(snd_pcm_t *handle, const void *buffer, snd_pcm_uframes_t size);static snd_pcm_sframes_t (*readn_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);static snd_pcm_sframes_t (*writen_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);enum {	VUMETER_NONE,	VUMETER_MONO,	VUMETER_STEREO};static char *command;static snd_pcm_t *handle;static struct {	snd_pcm_format_t format;	unsigned int channels;	unsigned int rate;} hwparams, rhwparams;static int timelimit = 0;static int quiet_mode = 0;static int file_type = FORMAT_DEFAULT;static int open_mode = 0;static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;static int mmap_flag = 0;static int interleaved = 1;static int nonblock = 0;static u_char *audiobuf = NULL;static snd_pcm_uframes_t chunk_size = 0;static unsigned period_time = 0;static unsigned buffer_time = 0;static snd_pcm_uframes_t period_frames = 0;static snd_pcm_uframes_t buffer_frames = 0;static int avail_min = -1;static int start_delay = 0;static int stop_delay = 0;static int verbose = 0;static int vumeter = VUMETER_NONE;static int buffer_pos = 0;static size_t bits_per_sample, bits_per_frame;static size_t chunk_bytes;static int test_position = 0;static snd_output_t *log;static int fd = -1;static off64_t pbrec_count = LLONG_MAX, fdcount;static int vocmajor, vocminor;/* needed prototypes */static void playback(char *filename);static void capture(char *filename);static void playbackv(char **filenames, unsigned int count);static void capturev(char **filenames, unsigned int count);static void begin_voc(int fd, size_t count);static void end_voc(int fd);static void begin_wave(int fd, size_t count);static void end_wave(int fd);static void begin_au(int fd, size_t count);static void end_au(int fd);static const struct fmt_capture {	void (*start) (int fd, size_t count);	void (*end) (int fd);	char *what;	long long max_filesize;} fmt_rec_table[] = {	{	NULL,		NULL,		N_("raw data"),		LLONG_MAX },	{	begin_voc,	end_voc,	N_("VOC"),		16000000LL },	/* FIXME: can WAV handle exactly 2GB or less than it? */	{	begin_wave,	end_wave,	N_("WAVE"),		2147483648LL },	{	begin_au,	end_au,		N_("Sparc Audio"),	LLONG_MAX }};#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)#define error(...) do {\	fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \	fprintf(stderr, __VA_ARGS__); \	putc('\n', stderr); \} while (0)#else#define error(args...) do {\	fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \	fprintf(stderr, ##args); \	putc('\n', stderr); \} while (0)#endif	static void usage(char *command){	snd_pcm_format_t k;	printf(_("Usage: %s [OPTION]... [FILE]...\n""\n""-h, --help              help\n""    --version           print current version\n""-l, --list-devices      list all soundcards and digital audio devices\n""-L, --list-pcms         list device names\n""-D, --device=NAME       select PCM by name\n""-q, --quiet             quiet mode\n""-t, --file-type TYPE    file type (voc, wav, raw or au)\n""-c, --channels=#        channels\n""-f, --format=FORMAT     sample format (case insensitive)\n""-r, --rate=#            sample rate\n""-d, --duration=#        interrupt after # seconds\n""-M, --mmap              mmap stream\n""-N, --nonblock          nonblocking mode\n""-F, --period-time=#     distance between interrupts is # microseconds\n""-B, --buffer-time=#     buffer duration is # microseconds\n""    --period-size=#     distance between interrupts is # frames\n""    --buffer-size=#     buffer duration is # frames\n""-A, --avail-min=#       min available space for wakeup is # microseconds\n""-R, --start-delay=#     delay for automatic PCM start is # microseconds \n""                        (relative to buffer size if <= 0)\n""-T, --stop-delay=#      delay for automatic PCM stop is # microseconds from xrun\n""-v, --verbose           show PCM structure and setup (accumulative)\n""-V, --vumeter=TYPE      enable VU meter (TYPE: mono or stereo)\n""-I, --separate-channels one file for each channel\n""    --disable-resample  disable automatic rate resample\n""    --disable-channels  disable automatic channel conversions\n""    --disable-format    disable automatic format conversions\n""    --disable-softvol   disable software volume control (softvol)\n""    --test-position     test ring buffer position\n")		, command);	printf(_("Recognized sample formats are:"));	for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {		const char *s = snd_pcm_format_name(k);		if (s)			printf(" %s", s);	}	printf(_("\nSome of these may not be available on selected hardware\n"));	printf(_("The availabled format shortcuts are:\n"));	printf(_("-f cd (16 bit little endian, 44100, stereo)\n"));	printf(_("-f cdr (16 bit big endian, 44100, stereo)\n"));	printf(_("-f dat (16 bit little endian, 48000, stereo)\n"));}static void device_list(void){	snd_ctl_t *handle;	int card, err, dev, idx;	snd_ctl_card_info_t *info;	snd_pcm_info_t *pcminfo;	snd_ctl_card_info_alloca(&info);	snd_pcm_info_alloca(&pcminfo);	card = -1;	if (snd_card_next(&card) < 0 || card < 0) {		error(_("no soundcards found..."));		return;	}	printf(_("**** List of %s Hardware Devices ****\n"),	       snd_pcm_stream_name(stream));	while (card >= 0) {		char name[32];		sprintf(name, "hw:%d", card);		if ((err = snd_ctl_open(&handle, name, 0)) < 0) {			error("control open (%i): %s", card, snd_strerror(err));			goto next_card;		}		if ((err = snd_ctl_card_info(handle, info)) < 0) {			error("control hardware info (%i): %s", card, snd_strerror(err));			snd_ctl_close(handle);			goto next_card;		}		dev = -1;		while (1) {			unsigned int count;			if (snd_ctl_pcm_next_device(handle, &dev)<0)				error("snd_ctl_pcm_next_device");			if (dev < 0)				break;			snd_pcm_info_set_device(pcminfo, dev);			snd_pcm_info_set_subdevice(pcminfo, 0);			snd_pcm_info_set_stream(pcminfo, stream);			if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {				if (err != -ENOENT)					error("control digital audio info (%i): %s", card, snd_strerror(err));				continue;			}			printf(_("card %i: %s [%s], device %i: %s [%s]\n"),				card, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info),				dev,				snd_pcm_info_get_id(pcminfo),				snd_pcm_info_get_name(pcminfo));			count = snd_pcm_info_get_subdevices_count(pcminfo);			printf( _("  Subdevices: %i/%i\n"),				snd_pcm_info_get_subdevices_avail(pcminfo), count);			for (idx = 0; idx < (int)count; idx++) {				snd_pcm_info_set_subdevice(pcminfo, idx);				if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {					error("control digital audio playback info (%i): %s", card, snd_strerror(err));				} else {					printf(_("  Subdevice #%i: %s\n"),						idx, snd_pcm_info_get_subdevice_name(pcminfo));				}			}		}		snd_ctl_close(handle);	next_card:		if (snd_card_next(&card) < 0) {			error("snd_card_next");			break;		}	}}static void pcm_list(void){	void **hints, **n;	char *name, *descr, *descr1, *io;	const char *filter;	if (snd_device_name_hint(-1, "pcm", &hints) < 0)		return;	n = hints;	filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";	while (*n != NULL) {		name = snd_device_name_get_hint(*n, "NAME");		descr = snd_device_name_get_hint(*n, "DESC");		io = snd_device_name_get_hint(*n, "IOID");		if (io != NULL && strcmp(io, filter) != 0)			goto __end;		printf("%s\n", name);		if ((descr1 = descr) != NULL) {			printf("    ");			while (*descr1) {				if (*descr1 == '\n')					printf("\n    ");				else					putchar(*descr1);				descr1++;			}			putchar('\n');		}	      __end:	      	if (name != NULL)	      		free(name);		if (descr != NULL)			free(descr);		if (io != NULL)			free(io);		n++;	}	snd_device_name_free_hint(hints);}static void version(void){	printf("%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex@perex.cz>\n", command);}static void signal_handler(int sig){	if (verbose==2)		putchar('\n');	if (!quiet_mode)		fprintf(stderr, _("Aborted by signal %s...\n"), strsignal(sig));	if (stream == SND_PCM_STREAM_CAPTURE) {		if (fmt_rec_table[file_type].end) {			fmt_rec_table[file_type].end(fd);			fd = -1;		}		stream = -1;	}	if (fd > 1) {		close(fd);		fd = -1;	}	if (handle && sig != SIGABRT) {		snd_pcm_close(handle);		handle = NULL;	}	exit(EXIT_FAILURE);}enum {	OPT_VERSION = 1,	OPT_PERIOD_SIZE,	OPT_BUFFER_SIZE,	OPT_DISABLE_RESAMPLE,	OPT_DISABLE_CHANNELS,	OPT_DISABLE_FORMAT,	OPT_DISABLE_SOFTVOL,	OPT_TEST_POSITION};int main(int argc, char *argv[]){	int option_index;	static const char short_options[] = "hnlLD:qt:c:f:r:d:MNF:A:R:T:B:vV:IPC";	static const struct option long_options[] = {		{"help", 0, 0, 'h'},		{"version", 0, 0, OPT_VERSION},		{"list-devnames", 0, 0, 'n'},		{"list-devices", 0, 0, 'l'},		{"list-pcms", 0, 0, 'L'},		{"device", 1, 0, 'D'},		{"quiet", 0, 0, 'q'},		{"file-type", 1, 0, 't'},		{"channels", 1, 0, 'c'},		{"format", 1, 0, 'f'},		{"rate", 1, 0, 'r'},		{"duration", 1, 0 ,'d'},		{"mmap", 0, 0, 'M'},		{"nonblock", 0, 0, 'N'},		{"period-time", 1, 0, 'F'},		{"period-size", 1, 0, OPT_PERIOD_SIZE},		{"avail-min", 1, 0, 'A'},		{"start-delay", 1, 0, 'R'},		{"stop-delay", 1, 0, 'T'},		{"buffer-time", 1, 0, 'B'},		{"buffer-size", 1, 0, OPT_BUFFER_SIZE},		{"verbose", 0, 0, 'v'},		{"vumeter", 1, 0, 'V'},		{"separate-channels", 0, 0, 'I'},		{"playback", 0, 0, 'P'},		{"capture", 0, 0, 'C'},		{"disable-resample", 0, 0, OPT_DISABLE_RESAMPLE},		{"disable-channels", 0, 0, OPT_DISABLE_CHANNELS},		{"disable-format", 0, 0, OPT_DISABLE_FORMAT},		{"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},		{"test-position", 0, 0, OPT_TEST_POSITION},		{0, 0, 0, 0}	};	char *pcm_name = "default";	int tmp, err, c;	int do_device_list = 0, do_pcm_list = 0;	snd_pcm_info_t *info;#ifdef ENABLE_NLS	setlocale(LC_ALL, "");	textdomain(PACKAGE);#endif	snd_pcm_info_alloca(&info);	err = snd_output_stdio_attach(&log, stderr, 0);	assert(err >= 0);	command = argv[0];	file_type = FORMAT_DEFAULT;	if (strstr(argv[0], "arecord")) {		stream = SND_PCM_STREAM_CAPTURE;		file_type = FORMAT_WAVE;		command = "arecord";		start_delay = 1;	} else if (strstr(argv[0], "aplay")) {		stream = SND_PCM_STREAM_PLAYBACK;		command = "aplay";	} else {		error(_("command should be named either arecord or aplay"));		return 1;	}	chunk_size = -1;	rhwparams.format = DEFAULT_FORMAT;	rhwparams.rate = DEFAULT_SPEED;	rhwparams.channels = 1;	while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {		switch (c) {		case 'h':			usage(command);			return 0;		case OPT_VERSION:			version();			return 0;		case 'l':			do_device_list = 1;			break;		case 'L':			do_pcm_list = 1;			break;		case 'D':			pcm_name = optarg;			break;		case 'q':			quiet_mode = 1;			break;		case 't':			if (strcasecmp(optarg, "raw") == 0)				file_type = FORMAT_RAW;			else if (strcasecmp(optarg, "voc") == 0)				file_type = FORMAT_VOC;			else if (strcasecmp(optarg, "wav") == 0)				file_type = FORMAT_WAVE;			else if (strcasecmp(optarg, "au") == 0 || strcasecmp(optarg, "sparc") == 0)				file_type = FORMAT_AU;			else {				error(_("unrecognized file format %s"), optarg);				return 1;			}			break;		case 'c':			rhwparams.channels = strtol(optarg, NULL, 0);			if (rhwparams.channels < 1 || rhwparams.channels > 32) {				error(_("value %i for channels is invalid"), rhwparams.channels);				return 1;			}			break;		case 'f':			if (strcasecmp(optarg, "cd") == 0 || strcasecmp(optarg, "cdr") == 0) {				if (strcasecmp(optarg, "cdr") == 0)					rhwparams.format = SND_PCM_FORMAT_S16_BE;				else					rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;				rhwparams.rate = 44100;				rhwparams.channels = 2;			} else if (strcasecmp(optarg, "dat") == 0) {				rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;				rhwparams.rate = 48000;				rhwparams.channels = 2;			} else {				rhwparams.format = snd_pcm_format_value(optarg);				if (rhwparams.format == SND_PCM_FORMAT_UNKNOWN) {					error(_("wrong extended format '%s'"), optarg);					exit(EXIT_FAILURE);				}			}			break;		case 'r':			tmp = strtol(optarg, NULL, 0);			if (tmp < 300)				tmp *= 1000;			rhwparams.rate = tmp;			if (tmp < 2000 || tmp > 192000) {				error(_("bad speed value %i"), tmp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -