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

📄 aplay.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 5 页
字号:
				return 1;			}			break;		case 'd':			timelimit = strtol(optarg, NULL, 0);			break;		case 'N':			nonblock = 1;			open_mode |= SND_PCM_NONBLOCK;			break;		case 'F':			period_time = strtol(optarg, NULL, 0);			break;		case 'B':			buffer_time = strtol(optarg, NULL, 0);			break;		case OPT_PERIOD_SIZE:			period_frames = strtol(optarg, NULL, 0);			break;		case OPT_BUFFER_SIZE:			buffer_frames = strtol(optarg, NULL, 0);			break;		case 'A':			avail_min = strtol(optarg, NULL, 0);			break;		case 'R':			start_delay = strtol(optarg, NULL, 0);			break;		case 'T':			stop_delay = strtol(optarg, NULL, 0);			break;		case 'v':			verbose++;			if (verbose > 1 && !vumeter)				vumeter = VUMETER_MONO;			break;		case 'V':			if (*optarg == 's')				vumeter = VUMETER_STEREO;			else if (*optarg == 'm')				vumeter = VUMETER_MONO;			else				vumeter = VUMETER_NONE;			break;		case 'M':			mmap_flag = 1;			break;		case 'I':			interleaved = 0;			break;		case 'P':			stream = SND_PCM_STREAM_PLAYBACK;			command = "aplay";			break;		case 'C':			stream = SND_PCM_STREAM_CAPTURE;			command = "arecord";			start_delay = 1;			if (file_type == FORMAT_DEFAULT)				file_type = FORMAT_WAVE;			break;		case OPT_DISABLE_RESAMPLE:			open_mode |= SND_PCM_NO_AUTO_RESAMPLE;			break;		case OPT_DISABLE_CHANNELS:			open_mode |= SND_PCM_NO_AUTO_CHANNELS;			break;		case OPT_DISABLE_FORMAT:			open_mode |= SND_PCM_NO_AUTO_FORMAT;			break;		case OPT_DISABLE_SOFTVOL:			open_mode |= SND_PCM_NO_SOFTVOL;			break;		case OPT_TEST_POSITION:			test_position = 1;			break;		default:			fprintf(stderr, _("Try `%s --help' for more information.\n"), command);			return 1;		}	}	if (do_device_list) {		if (do_pcm_list) pcm_list();		device_list();		goto __end;	} else if (do_pcm_list) {		pcm_list();		goto __end;	}	err = snd_pcm_open(&handle, pcm_name, stream, open_mode);	if (err < 0) {		error(_("audio open error: %s"), snd_strerror(err));		return 1;	}	if ((err = snd_pcm_info(handle, info)) < 0) {		error(_("info error: %s"), snd_strerror(err));		return 1;	}	if (nonblock) {		err = snd_pcm_nonblock(handle, 1);		if (err < 0) {			error(_("nonblock setting error: %s"), snd_strerror(err));			return 1;		}	}	chunk_size = 1024;	hwparams = rhwparams;	audiobuf = (u_char *)malloc(1024);	if (audiobuf == NULL) {		error(_("not enough memory"));		return 1;	}	if (mmap_flag) {		writei_func = snd_pcm_mmap_writei;		readi_func = snd_pcm_mmap_readi;		writen_func = snd_pcm_mmap_writen;		readn_func = snd_pcm_mmap_readn;	} else {		writei_func = snd_pcm_writei;		readi_func = snd_pcm_readi;		writen_func = snd_pcm_writen;		readn_func = snd_pcm_readn;	}	signal(SIGINT, signal_handler);	signal(SIGTERM, signal_handler);	signal(SIGABRT, signal_handler);	if (interleaved) {		if (optind > argc - 1) {			if (stream == SND_PCM_STREAM_PLAYBACK)				playback(NULL);			else				capture(NULL);		} else {			while (optind <= argc - 1) {				if (stream == SND_PCM_STREAM_PLAYBACK)					playback(argv[optind++]);				else					capture(argv[optind++]);			}		}	} else {		if (stream == SND_PCM_STREAM_PLAYBACK)			playbackv(&argv[optind], argc - optind);		else			capturev(&argv[optind], argc - optind);	}	if (verbose==2)		putchar('\n');	snd_pcm_close(handle);	free(audiobuf);      __end:	snd_output_close(log);	snd_config_update_free_global();	return EXIT_SUCCESS;}/* * Safe read (for pipes) */ static ssize_t safe_read(int fd, void *buf, size_t count){	ssize_t result = 0, res;	while (count > 0) {		if ((res = read(fd, buf, count)) == 0)			break;		if (res < 0)			return result > 0 ? result : res;		count -= res;		result += res;		buf = (char *)buf + res;	}	return result;}/* * Test, if it is a .VOC file and return >=0 if ok (this is the length of rest) *                                       < 0 if not  */static int test_vocfile(void *buffer){	VocHeader *vp = buffer;	if (!memcmp(vp->magic, VOC_MAGIC_STRING, 20)) {		vocminor = LE_SHORT(vp->version) & 0xFF;		vocmajor = LE_SHORT(vp->version) / 256;		if (LE_SHORT(vp->version) != (0x1233 - LE_SHORT(vp->coded_ver)))			return -2;	/* coded version mismatch */		return LE_SHORT(vp->headerlen) - sizeof(VocHeader);	/* 0 mostly */	}	return -1;		/* magic string fail */}/* * helper for test_wavefile */static size_t test_wavefile_read(int fd, u_char *buffer, size_t *size, size_t reqsize, int line){	if (*size >= reqsize)		return *size;	if ((size_t)safe_read(fd, buffer + *size, reqsize - *size) != reqsize - *size) {		error(_("read error (called from line %i)"), line);		exit(EXIT_FAILURE);	}	return *size = reqsize;}#define check_wavefile_space(buffer, len, blimit) \	if (len > blimit) { \		blimit = len; \		if ((buffer = realloc(buffer, blimit)) == NULL) { \			error(_("not enough memory"));		  \			exit(EXIT_FAILURE); \		} \	}/* * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.) *                            == 0 if not * Value returned is bytes to be discarded. */static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size){	WaveHeader *h = (WaveHeader *)_buffer;	u_char *buffer = NULL;	size_t blimit = 0;	WaveFmtBody *f;	WaveChunkHeader *c;	u_int type, len;	if (size < sizeof(WaveHeader))		return -1;	if (h->magic != WAV_RIFF || h->type != WAV_WAVE)		return -1;	if (size > sizeof(WaveHeader)) {		check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);		memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));	}	size -= sizeof(WaveHeader);	while (1) {		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);		c = (WaveChunkHeader*)buffer;		type = c->type;		len = LE_INT(c->length);		len += len % 2;		if (size > sizeof(WaveChunkHeader))			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));		size -= sizeof(WaveChunkHeader);		if (type == WAV_FMT)			break;		check_wavefile_space(buffer, len, blimit);		test_wavefile_read(fd, buffer, &size, len, __LINE__);		if (size > len)			memmove(buffer, buffer + len, size - len);		size -= len;	}	if (len < sizeof(WaveFmtBody)) {		error(_("unknown length of 'fmt ' chunk (read %u, should be %u at least)"),		      len, (u_int)sizeof(WaveFmtBody));		exit(EXIT_FAILURE);	}	check_wavefile_space(buffer, len, blimit);	test_wavefile_read(fd, buffer, &size, len, __LINE__);	f = (WaveFmtBody*) buffer;	if (LE_SHORT(f->format) == WAV_FMT_EXTENSIBLE) {		WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;		if (len < sizeof(WaveFmtExtensibleBody)) {			error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),					len, (u_int)sizeof(WaveFmtExtensibleBody));			exit(EXIT_FAILURE);		}		if (memcmp(fe->guid_tag, WAV_GUID_TAG, 14) != 0) {			error(_("wrong format tag in extensible 'fmt ' chunk"));			exit(EXIT_FAILURE);		}		f->format = fe->guid_format;	}        if (LE_SHORT(f->format) != WAV_FMT_PCM &&            LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) {                error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));		exit(EXIT_FAILURE);	}	if (LE_SHORT(f->channels) < 1) {		error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));		exit(EXIT_FAILURE);	}	hwparams.channels = LE_SHORT(f->channels);	switch (LE_SHORT(f->bit_p_spl)) {	case 8:		if (hwparams.format != DEFAULT_FORMAT &&		    hwparams.format != SND_PCM_FORMAT_U8)			fprintf(stderr, _("Warning: format is changed to U8\n"));		hwparams.format = SND_PCM_FORMAT_U8;		break;	case 16:		if (hwparams.format != DEFAULT_FORMAT &&		    hwparams.format != SND_PCM_FORMAT_S16_LE)			fprintf(stderr, _("Warning: format is changed to S16_LE\n"));		hwparams.format = SND_PCM_FORMAT_S16_LE;		break;	case 24:		switch (LE_SHORT(f->byte_p_spl) / hwparams.channels) {		case 3:			if (hwparams.format != DEFAULT_FORMAT &&			    hwparams.format != SND_PCM_FORMAT_S24_3LE)				fprintf(stderr, _("Warning: format is changed to S24_3LE\n"));			hwparams.format = SND_PCM_FORMAT_S24_3LE;			break;		case 4:			if (hwparams.format != DEFAULT_FORMAT &&			    hwparams.format != SND_PCM_FORMAT_S24_LE)				fprintf(stderr, _("Warning: format is changed to S24_LE\n"));			hwparams.format = SND_PCM_FORMAT_S24_LE;			break;		default:			error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),			      LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);			exit(EXIT_FAILURE);		}		break;	case 32:                if (LE_SHORT(f->format) == WAV_FMT_PCM)                        hwparams.format = SND_PCM_FORMAT_S32_LE;                else if (LE_SHORT(f->format) == WAV_FMT_IEEE_FLOAT)                        hwparams.format = SND_PCM_FORMAT_FLOAT_LE;		break;	default:		error(_(" can't play WAVE-files with sample %d bits wide"),		      LE_SHORT(f->bit_p_spl));		exit(EXIT_FAILURE);	}	hwparams.rate = LE_INT(f->sample_fq);		if (size > len)		memmove(buffer, buffer + len, size - len);	size -= len;		while (1) {		u_int type, len;		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);		c = (WaveChunkHeader*)buffer;		type = c->type;		len = LE_INT(c->length);		if (size > sizeof(WaveChunkHeader))			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));		size -= sizeof(WaveChunkHeader);		if (type == WAV_DATA) {			if (len < pbrec_count && len < 0x7ffffffe)				pbrec_count = len;			if (size > 0)				memcpy(_buffer, buffer, size);			free(buffer);			return size;		}		len += len % 2;		check_wavefile_space(buffer, len, blimit);		test_wavefile_read(fd, buffer, &size, len, __LINE__);		if (size > len)			memmove(buffer, buffer + len, size - len);		size -= len;	}	/* shouldn't be reached */	return -1;}/* */static int test_au(int fd, void *buffer){	AuHeader *ap = buffer;	if (ap->magic != AU_MAGIC)		return -1;	if (BE_INT(ap->hdr_size) > 128 || BE_INT(ap->hdr_size) < 24)		return -1;	pbrec_count = BE_INT(ap->data_size);	switch (BE_INT(ap->encoding)) {	case AU_FMT_ULAW:		if (hwparams.format != DEFAULT_FORMAT &&		    hwparams.format != SND_PCM_FORMAT_MU_LAW)			fprintf(stderr, _("Warning: format is changed to MU_LAW\n"));		hwparams.format = SND_PCM_FORMAT_MU_LAW;		break;	case AU_FMT_LIN8:		if (hwparams.format != DEFAULT_FORMAT &&		    hwparams.format != SND_PCM_FORMAT_U8)			fprintf(stderr, _("Warning: format is changed to U8\n"));		hwparams.format = SND_PCM_FORMAT_U8;		break;	case AU_FMT_LIN16:		if (hwparams.format != DEFAULT_FORMAT &&		    hwparams.format != SND_PCM_FORMAT_S16_BE)			fprintf(stderr, _("Warning: format is changed to S16_BE\n"));		hwparams.format = SND_PCM_FORMAT_S16_BE;		break;	default:		return -1;	}	hwparams.rate = BE_INT(ap->sample_rate);	if (hwparams.rate < 2000 || hwparams.rate > 256000)		return -1;	hwparams.channels = BE_INT(ap->channels);	if (hwparams.channels < 1 || hwparams.channels > 128)		return -1;	if ((size_t)safe_read(fd, buffer + sizeof(AuHeader), BE_INT(ap->hdr_size) - sizeof(AuHeader)) != BE_INT(ap->hdr_size) - sizeof(AuHeader)) {		error(_("read error"));		exit(EXIT_FAILURE);	}	return 0;}static void set_params(void){	snd_pcm_hw_params_t *params;	snd_pcm_sw_params_t *swparams;	snd_pcm_uframes_t buffer_size;	int err;	size_t n;	unsigned int rate;	snd_pcm_uframes_t start_threshold, stop_threshold;	snd_pcm_hw_params_alloca(&params);	snd_pcm_sw_params_alloca(&swparams);	err = snd_pcm_hw_params_any(handle, params);	if (err < 0) {		error(_("Broken configuration for this PCM: no configurations available"));		exit(EXIT_FAILURE);	}	if (mmap_flag) {		snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());		snd_pcm_access_mask_none(mask);		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);		err = snd_pcm_hw_params_set_access_mask(handle, params, mask);	} else if (interleaved)		err = snd_pcm_hw_params_set_access(handle, params,						   SND_PCM_ACCESS_RW_INTERLEAVED);	else		err = snd_pcm_hw_params_set_access(handle, params,						   SND_PCM_ACCESS_RW_NONINTERLEAVED);	if (err < 0) {		error(_("Access type not available"));		exit(EXIT_FAILURE);	}	err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);	if (err < 0) {		error(_("Sample format non available"));		exit(EXIT_FAILURE);	}	err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);	if (err < 0) {		error(_("Channels count non available"));		exit(EXIT_FAILURE);	}#if 0	err = snd_pcm_hw_params_set_periods_min(handle, params, 2);	assert(err >= 0);#endif	rate = hwparams.rate;	err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);	assert(err >= 0);	if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {		if (!quiet_mode) {			char plugex[64];			const char *pcmname = snd_pcm_name(handle);			fprintf(stderr, _("Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"), rate, hwparams.rate);			if (! pcmname || strchr(snd_pcm_name(handle), ':'))				*plugex = 0;			else				snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",					 snd_pcm_name(handle));			fprintf(stderr, _("         please, try the plug plugin %s\n"),				plugex);		}	}	rate = hwparams.rate;	if (buffer_time == 0 && buffer_frames == 0) {

⌨️ 快捷键说明

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