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

📄 aplay.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		if (r > 0) {			if (vumeter) {				for (channel = 0; channel < channels; channel++)					compute_max_peak(data[channel], r);			}			result += r;			count -= r;		}	}	return result;}/* *  read function */static ssize_t pcm_read(u_char *data, size_t rcount){	ssize_t r;	size_t result = 0;	size_t count = rcount;	if (count != chunk_size) {		count = chunk_size;	}	while (count > 0) {		if (test_position)			do_test_position();		r = readi_func(handle, data, count);		if (test_position)			do_test_position();		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {			snd_pcm_wait(handle, 1000);		} else if (r == -EPIPE) {			xrun();		} else if (r == -ESTRPIPE) {			suspend();		} else if (r < 0) {			error(_("read error: %s"), snd_strerror(r));			exit(EXIT_FAILURE);		}		if (r > 0) {			if (vumeter)				compute_max_peak(data, r * hwparams.channels);			result += r;			count -= r;			data += r * bits_per_frame / 8;		}	}	return rcount;}static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount){	ssize_t r;	size_t result = 0;	size_t count = rcount;	if (count != chunk_size) {		count = chunk_size;	}	while (count > 0) {		unsigned int channel;		void *bufs[channels];		size_t offset = result;		for (channel = 0; channel < channels; channel++)			bufs[channel] = data[channel] + offset * bits_per_sample / 8;		if (test_position)			do_test_position();		r = readn_func(handle, bufs, count);		if (test_position)			do_test_position();		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {			snd_pcm_wait(handle, 1000);		} else if (r == -EPIPE) {			xrun();		} else if (r == -ESTRPIPE) {			suspend();		} else if (r < 0) {			error(_("readv error: %s"), snd_strerror(r));			exit(EXIT_FAILURE);		}		if (r > 0) {			if (vumeter) {				for (channel = 0; channel < channels; channel++)					compute_max_peak(data[channel], r);			}			result += r;			count -= r;		}	}	return rcount;}/* *  ok, let's play a .voc file */static ssize_t voc_pcm_write(u_char *data, size_t count){	ssize_t result = count, r;	size_t size;	while (count > 0) {		size = count;		if (size > chunk_bytes - buffer_pos)			size = chunk_bytes - buffer_pos;		memcpy(audiobuf + buffer_pos, data, size);		data += size;		count -= size;		buffer_pos += size;		if ((size_t)buffer_pos == chunk_bytes) {			if ((size_t)(r = pcm_write(audiobuf, chunk_size)) != chunk_size)				return r;			buffer_pos = 0;		}	}	return result;}static void voc_write_silence(unsigned x){	unsigned l;	u_char *buf;	buf = (u_char *) malloc(chunk_bytes);	if (buf == NULL) {		error(_("can't allocate buffer for silence"));		return;		/* not fatal error */	}	snd_pcm_format_set_silence(hwparams.format, buf, chunk_size * hwparams.channels);	while (x > 0) {		l = x;		if (l > chunk_size)			l = chunk_size;		if (voc_pcm_write(buf, l) != (ssize_t)l) {			error(_("write error"));			exit(EXIT_FAILURE);		}		x -= l;	}	free(buf);}static void voc_pcm_flush(void){	if (buffer_pos > 0) {		size_t b;		if (snd_pcm_format_set_silence(hwparams.format, audiobuf + buffer_pos, chunk_bytes - buffer_pos * 8 / bits_per_sample) < 0)			fprintf(stderr, _("voc_pcm_flush - silence error"));		b = chunk_size;		if (pcm_write(audiobuf, b) != (ssize_t)b)			error(_("voc_pcm_flush error"));	}	snd_pcm_nonblock(handle, 0);	snd_pcm_drain(handle);	snd_pcm_nonblock(handle, nonblock);}static void voc_play(int fd, int ofs, char *name){	int l;	VocBlockType *bp;	VocVoiceData *vd;	VocExtBlock *eb;	size_t nextblock, in_buffer;	u_char *data, *buf;	char was_extended = 0, output = 0;	u_short *sp, repeat = 0;	size_t silence;	off64_t filepos = 0;#define COUNT(x)	nextblock -= x; in_buffer -= x; data += x#define COUNT1(x)	in_buffer -= x; data += x	data = buf = (u_char *)malloc(64 * 1024);	buffer_pos = 0;	if (data == NULL) {		error(_("malloc error"));		exit(EXIT_FAILURE);	}	if (!quiet_mode) {		fprintf(stderr, _("Playing Creative Labs Channel file '%s'...\n"), name);	}	/* first we waste the rest of header, ugly but we don't need seek */	while (ofs > (ssize_t)chunk_bytes) {		if ((size_t)safe_read(fd, buf, chunk_bytes) != chunk_bytes) {			error(_("read error"));			exit(EXIT_FAILURE);		}		ofs -= chunk_bytes;	}	if (ofs) {		if (safe_read(fd, buf, ofs) != ofs) {			error(_("read error"));			exit(EXIT_FAILURE);		}	}	hwparams.format = DEFAULT_FORMAT;	hwparams.channels = 1;	hwparams.rate = DEFAULT_SPEED;	set_params();	in_buffer = nextblock = 0;	while (1) {	      Fill_the_buffer:	/* need this for repeat */		if (in_buffer < 32) {			/* move the rest of buffer to pos 0 and fill the buf up */			if (in_buffer)				memcpy(buf, data, in_buffer);			data = buf;			if ((l = safe_read(fd, buf + in_buffer, chunk_bytes - in_buffer)) > 0)				in_buffer += l;			else if (!in_buffer) {				/* the file is truncated, so simulate 'Terminator' 				   and reduce the datablock for safe landing */				nextblock = buf[0] = 0;				if (l == -1) {					perror(name);					exit(EXIT_FAILURE);				}			}		}		while (!nextblock) {	/* this is a new block */			if (in_buffer < sizeof(VocBlockType))				goto __end;			bp = (VocBlockType *) data;			COUNT1(sizeof(VocBlockType));			nextblock = VOC_DATALEN(bp);			if (output && !quiet_mode)				fprintf(stderr, "\n");	/* write /n after ASCII-out */			output = 0;			switch (bp->type) {			case 0:#if 0				d_printf("Terminator\n");#endif				return;		/* VOC-file stop */			case 1:				vd = (VocVoiceData *) data;				COUNT1(sizeof(VocVoiceData));				/* we need a SYNC, before we can set new SPEED, STEREO ... */				if (!was_extended) {					hwparams.rate = (int) (vd->tc);					hwparams.rate = 1000000 / (256 - hwparams.rate);#if 0					d_printf("Channel data %d Hz\n", dsp_speed);#endif					if (vd->pack) {		/* /dev/dsp can't it */						error(_("can't play packed .voc files"));						return;					}					if (hwparams.channels == 2)		/* if we are in Stereo-Mode, switch back */						hwparams.channels = 1;				} else {	/* there was extended block */					hwparams.channels = 2;					was_extended = 0;				}				set_params();				break;			case 2:	/* nothing to do, pure data */#if 0				d_printf("Channel continuation\n");#endif				break;			case 3:	/* a silence block, no data, only a count */				sp = (u_short *) data;				COUNT1(sizeof(u_short));				hwparams.rate = (int) (*data);				COUNT1(1);				hwparams.rate = 1000000 / (256 - hwparams.rate);				set_params();				silence = (((size_t) * sp) * 1000) / hwparams.rate;#if 0				d_printf("Silence for %d ms\n", (int) silence);#endif				voc_write_silence(*sp);				break;			case 4:	/* a marker for syncronisation, no effect */				sp = (u_short *) data;				COUNT1(sizeof(u_short));#if 0				d_printf("Marker %d\n", *sp);#endif				break;			case 5:	/* ASCII text, we copy to stderr */				output = 1;#if 0				d_printf("ASCII - text :\n");#endif				break;			case 6:	/* repeat marker, says repeatcount */				/* my specs don't say it: maybe this can be recursive, but				   I don't think somebody use it */				repeat = *(u_short *) data;				COUNT1(sizeof(u_short));#if 0				d_printf("Repeat loop %d times\n", repeat);#endif				if (filepos >= 0) {	/* if < 0, one seek fails, why test another */					if ((filepos = lseek64(fd, 0, 1)) < 0) {						error(_("can't play loops; %s isn't seekable\n"), name);						repeat = 0;					} else {						filepos -= in_buffer;	/* set filepos after repeat */					}				} else {					repeat = 0;				}				break;			case 7:	/* ok, lets repeat that be rewinding tape */				if (repeat) {					if (repeat != 0xFFFF) {#if 0						d_printf("Repeat loop %d\n", repeat);#endif						--repeat;					}#if 0					else						d_printf("Neverending loop\n");#endif					lseek64(fd, filepos, 0);					in_buffer = 0;	/* clear the buffer */					goto Fill_the_buffer;				}#if 0				else					d_printf("End repeat loop\n");#endif				break;			case 8:	/* the extension to play Stereo, I have SB 1.0 :-( */				was_extended = 1;				eb = (VocExtBlock *) data;				COUNT1(sizeof(VocExtBlock));				hwparams.rate = (int) (eb->tc);				hwparams.rate = 256000000L / (65536 - hwparams.rate);				hwparams.channels = eb->mode == VOC_MODE_STEREO ? 2 : 1;				if (hwparams.channels == 2)					hwparams.rate = hwparams.rate >> 1;				if (eb->pack) {		/* /dev/dsp can't it */					error(_("can't play packed .voc files"));					return;				}#if 0				d_printf("Extended block %s %d Hz\n",					 (eb->mode ? "Stereo" : "Mono"), dsp_speed);#endif				break;			default:				error(_("unknown blocktype %d. terminate."), bp->type);				return;			}	/* switch (bp->type) */		}		/* while (! nextblock)  */		/* put nextblock data bytes to dsp */		l = in_buffer;		if (nextblock < (size_t)l)			l = nextblock;		if (l) {			if (output && !quiet_mode) {				if (write(2, data, l) != l) {	/* to stderr */					error(_("write error"));					exit(EXIT_FAILURE);				}			} else {				if (voc_pcm_write(data, l) != l) {					error(_("write error"));					exit(EXIT_FAILURE);				}			}			COUNT(l);		}	}			/* while(1) */      __end:        voc_pcm_flush();        free(buf);}/* that was a big one, perhaps somebody split it :-) *//* setting the globals for playing raw data */static void init_raw_data(void){	hwparams = rhwparams;}/* calculate the data count to read from/to dsp */static off64_t calc_count(void){	off64_t count;	if (timelimit == 0) {		count = pbrec_count;	} else {		count = snd_pcm_format_size(hwparams.format, hwparams.rate * hwparams.channels);		count *= (off64_t)timelimit;	}	return count < pbrec_count ? count : pbrec_count;}/* write a .VOC-header */static void begin_voc(int fd, size_t cnt){	VocHeader vh;	VocBlockType bt;	VocVoiceData vd;	VocExtBlock eb;	memcpy(vh.magic, VOC_MAGIC_STRING, 20);	vh.headerlen = LE_SHORT(sizeof(VocHeader));	vh.version = LE_SHORT(VOC_ACTUAL_VERSION);	vh.coded_ver = LE_SHORT(0x1233 - VOC_ACTUAL_VERSION);	if (write(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {		error(_("write error"));		exit(EXIT_FAILURE);	}	if (hwparams.channels > 1) {		/* write an extended block */		bt.type = 8;		bt.datalen = 4;		bt.datalen_m = bt.datalen_h = 0;		if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {			error(_("write error"));			exit(EXIT_FAILURE);		}		eb.tc = LE_SHORT(65536 - 256000000L / (hwparams.rate << 1));		eb.pack = 0;		eb.mode = 1;		if (write(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {			error(_("write error"));			exit(EXIT_FAILURE);		}	}	bt.type = 1;	cnt += sizeof(VocVoiceData);	/* Channel_data block follows */	bt.datalen = (u_char) (cnt & 0xFF);	bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);	bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);	if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {		error(_("write error"));		exit(EXIT_FAILURE);	}	vd.tc = (u_char) (256 - (1000000 / hwparams.rate));	vd.pack = 0;	if (write(fd, &vd, sizeof(VocVoiceData)) != sizeof(VocVoiceData)) {		error(_("write error"));		exit(EXIT_FAILURE);	}}/* write a WAVE-header */static void begin_wave(int fd, size_t cnt){	WaveHeader h;	WaveFmtBody f;	WaveChunkHeader cf, cd;	int bits;	u_int tmp;	u_short tmp2;	/* WAVE cannot handle greater than 32bit (signed?) int */	if (cnt == (size_t)-2)		cnt = 0x7fffff00;	bits = 8;	switch ((unsigned long) hwparams.format) {	case SND_PCM_FORMAT_U8:		bits = 8;		break;	case SND_PCM_FORMAT_S16_LE:		bits = 16;		break;	case SND_PCM_FORMAT_S32_LE:        case SND_PCM_FORMAT_FLOAT_LE:		bits = 32;		break;	case SND_PCM_FORMAT_S24_LE:	case SND_PCM_FORMAT_S24_3LE:		bits = 24;		break;	default:		error(_("Wave doesn't support %s format..."), snd_pcm_format_name(hwparams.format));		exit(EXIT_FAILURE);	}	h.magic = WAV_RIFF;	tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;	h.length = LE_INT(tmp);	h.type = WAV_WAVE;	cf.type = WAV_FMT;	cf.length = LE_INT(16);

⌨️ 快捷键说明

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