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

📄 mp3play.c

📁 Application (fix point) for playing MP3 data on embedded systems. mp3play is designed to be able to
💻 C
📖 第 1 页 / 共 2 页
字号:
{	if (ioctl(fd, SNDCTL_DSP_SPEED, &mps->dec_frequency) < 0) {		fprintf(stderr, "ERROR: Unable to set frequency to %d, "			"errno=%d\n", mps->dec_frequency, errno);		exit(1);	}	/* Check if data stream is stereo, otherwise must play mono. */	stereo = (mps->channels == 1) ? 0 : playstereo;	if (ioctl(fd, SNDCTL_DSP_STEREO, &stereo) < 0) {		fprintf(stderr, "ERROR: Unable to set stereo to %d, "			"errno=%d\n", stereo, errno);		exit(1);	}	bits = (playbits == 16) ? AFMT_S16_BE : AFMT_U8;	if (ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &bits) < 0) {		fprintf(stderr, "ERROR: Unable to set sample size to "			"%d, errno=%d\n", bits, errno);		exit(1);	}}/****************************************************************************//* *	Generate a tone instead of PCM output. This is purely for *	testing purposes. */int writetone(int fd, INT16 *pcm[2], int count){	static int	ramp = 0;	unsigned char	*pbufbp;	unsigned short	*pbufwp;	int		i;	if (count <= 0)		return(count);	if (stereo) {		if (bits == 8) {			/* 8bit stereo */			pbufbp = (unsigned char *) rawbuf;			for (i = 0; (i < count); i++) {				*pbufbp++ = ramp;				*pbufbp++ = ramp;				ramp = (ramp + 0x80) & 0x7ff;			}			i = count * 2 * sizeof(unsigned char);		} else {			/* 16bit stereo */			pbufwp = (unsigned short *) rawbuf;			for (i = 0; (i < count); i++) {				*pbufwp++ = ramp;				*pbufwp++ = ramp;				ramp = (ramp + 0x80) & 0x7ff;			}			i = count * 2 * sizeof(unsigned short);		}	} else {		if (bits == 8) {			/* 8bit mono */			pbufbp = (unsigned char *) rawbuf;			for (i = 0; (i < count); i++) {				*pbufbp++ = ramp;				ramp = (ramp + 0x80) & 0x7ff;			}			i = count * sizeof(unsigned char);		} else {			/* 16bit mono */			pbufwp = (unsigned short *) rawbuf;			for (i = 0; (i < count); i++) {				*pbufwp++ = ramp;				ramp = (ramp + 0x80) & 0x7ff;			}			i = count * sizeof(unsigned short);		}	}	write(fd, rawbuf, i);	return(i);}/****************************************************************************//* *	Write out the PCM data to the file descriptor, translating to *	the specified data format. */int writepcm(int fd, INT16 *pcm[2], int count){	unsigned short	*pcm0, *pcm1;	unsigned char	*pbufbp;	unsigned short	*pbufwp;	char		*buf;	int		i;	if (count <= 0)		return(count);	if (testtone)		return(writetone(fd, pcm, count));	buf = rawbuf;	if (stereo) {		if (bits == 8) {			/* 8bit stereo */			pcm0 = pcm[0];			pcm1 = pcm[1];			pbufbp = (unsigned char *) buf;			for (i = 0; (i < count); i++) {				*pbufbp++ = (*pcm0++ ^ 0x8000) >> 8;				*pbufbp++ = (*pcm1++ ^ 0x8000) >> 8;			}			i = count * 2 * sizeof(unsigned char);		} else {			/* 16bit stereo */			pcm0 = pcm[0];			pcm1 = pcm[1];			pbufwp = (unsigned short *) buf;			for (i = 0; (i < count); i++) {				*pbufwp++ = *pcm0++;				*pbufwp++ = *pcm1++;			}			i = count * 2 * sizeof(unsigned short);		}	} else {		if (bits == 8) {			/* 8bit mono */			pcm0 = pcm[0];			pbufbp = (unsigned char *) buf;			for (i = 0; (i < count); i++)				*pbufbp++ = (*pcm0++ ^ 0x8000) >> 8;			i = count * sizeof(unsigned char);		} else {			/* 16bit mono, no translation required! */			i = count * sizeof(unsigned short);			buf = (char *) pcm[0];		}	}	if (prebufnow) {		memcpy(&prebuffer[prebufcnt], buf, i);		prebufcnt += i;		if (prebufcnt > prebufnow) {			write(fd, &prebuffer[0], prebufcnt);			prebufnow = prebufcnt = 0;		}	} else {		write(fd, buf, i);	}	return(i);}/****************************************************************************//* *	Flush out any remaining buffered PCM data. This is really to allow *	for prebuffing of files smaller than the prebuffer. */void flushpcm(int fd){	if (prebufnow) {		write(fd, &prebuffer[0], prebufcnt);		prebufnow = prebufcnt = 0;	}}/****************************************************************************/void usage(int rc){	printf("usage: mp3play [-hmvqz8RPTZ] [-g <quality>] [-s <time>] "		"[-d <device>] [-w <filename>] [-B <prebuf>] "		"[-l <line> [-t]] mp3-files...\n\n"		"\t\t-h            this help\n"		"\t\t-v            verbose stdout output\n"		"\t\t-q            quiet (don't print title)\n"		"\t\t-m            mix both channels (mono)\n"		"\t\t-8            play 8 bit samples\n"		"\t\t-R            repeat tracks forever\n"		"\t\t-z            shuffle tracks\n"		"\t\t-Z            psuedo-random tracks (implicit -R)\n"		"\t\t-P            print time to decode/play\n"		"\t\t-T            do decode, but output test tone\n"		"\t\t-g <quality>  decode quality (0,1,2)\n"		"\t\t-s <time>     sleep between playing tracks\n"		"\t\t-d <device>   audio device for playback\n"		"\t\t-w <filename> write output to file\n"		"\t\t-l <line>     display title on LCD line (0,1,2) (0 = no title)\n"		"\t\t-t <line>     display time on LCD line (1,2)\n"		"\t\t-B <prebuf>   size of pre-buffer\n");	exit(rc);}/****************************************************************************/int main(int argc, char *argv[]){	unsigned long	us;	INT16		*pcm[MPEGDEC_MAX_CHANNELS];	int		pcmcount, rawcount;	int		c, i, j, dspfd, dsphw, slptime;	int		playbits, playstereo, repeat, printtime; 	int		argnr, startargnr, rand, shuffle;	char		*device, *argvtmp;	time_t		sttime;	verbose = 0;	quiet = 0;	playstereo = 1;	playbits = 16;	quality = 2;	shuffle = 0;	rand = 0;	repeat = 0;	printtime = 0;	slptime = 0;	prebuflimit = 64000;	device = "/dev/dsp";	dsphw = 1;	while ((c = getopt(argc, argv, "?hmvqzt:8RZPTg:s:d:w:l:B:")) >= 0) {		switch (c) {		case 'v':			verbose++;			break;		case 'q':			verbose = 0;			quiet++;			break;		case 'm':			playstereo = 0;			break;		case '8':			playbits = 8;			break;		case 'R':			repeat++;			break;		case 'z':			shuffle++;			break;		case 'Z':			rand++;			repeat++;			break;		case 'P':			printtime++;			break;		case 'T':			testtone++;			break;		case 'g':			quality = atoi(optarg);			if ((quality < 0) || (quality > 2)) {				fprintf(stderr, "ERROR: valid quality 0, 1 "					"and 2\n");				exit(1);			}			break;		case 's':			slptime = atoi(optarg);			break;		case 'd':			device = optarg;			break;		case 'w':			device = optarg;			dsphw = 0;			break;		case 'l':			lcd_line = atoi(optarg);			break;		case 't':			lcd_time = atoi(optarg);			break;		case 'B':			prebuflimit = atoi(optarg);			if ((prebuflimit < 0) || (prebuflimit > (1*1024*1024))){				fprintf(stderr, "ERROR: valid pre-buffer range "					"0 to 1000000 bytes\n");				exit(1);			}			break;		case 'h':		case '?':			usage(0);			break;		}	}	argnr = optind;	if (argnr >= argc)		usage(1);	startargnr = argnr;	mp3_buffer = (INT8 *) malloc(MP3_BUF_SIZE);	if (!mp3_buffer) {		fprintf(stderr, "ERROR: Can't allocate MPEG buffer\n");		exit(0);	}	for (i = 0; (i < MPEGDEC_MAX_CHANNELS); i++) {		pcm[i] = malloc(MPEGDEC_PCM_SIZE * sizeof(INT16));		if (!pcm[i]) {			fprintf(stderr, "ERROR: Can't allocate PCM buffers\n");			exit(1);		}	}	if ((rawbuf = malloc(MPEGDEC_PCM_SIZE * sizeof(short) * 2)) == NULL) {		fprintf(stderr, "ERROR: Can't allocate raw buffers\n");		exit(1);	}	if (prebuflimit) {		prebufsize = prebuflimit + (MPEGDEC_PCM_SIZE*sizeof(short)*2);		if ((prebuffer = malloc(prebufsize)) == NULL) {			fprintf(stderr, "ERROR: Can't allocate pre-buffer\n");			exit(1);		}	}	/* Make ourselves the top priority process! */	setpriority(PRIO_PROCESS, 0, -20);	srandom(time(NULL));	/* Open the audio playback device */	if ((dspfd = open(device, (O_WRONLY | O_CREAT | O_TRUNC), 0660)) < 0) {		fprintf(stderr, "ERROR: Can't open output device '%s', "			"errno=%d\n", device, errno);		exit(0);	}	/* Open LCD device if we are going to use it */	if ((lcd_line > 0) || (lcd_time > 0)) {		lcdfd = open("/dev/lcdtxt", O_WRONLY);		if (lcdfd < 0) {			lcd_time = 0;			lcd_line = 0;		}	}nextall:	/* Shuffle tracks if slected */	if (shuffle) {		for (c = 0; (c < 10000); c++) {			i = (((unsigned int) random()) % (argc - startargnr)) +				startargnr;			j = (((unsigned int) random()) % (argc - startargnr)) +				startargnr;			argvtmp = argv[i];			argv[i] = argv[j];			argv[j] = argvtmp;		}	}nextfile:	if (rand) {		argnr = (((unsigned int) random()) % (argc - startargnr)) +			startargnr;	}	mpa_ctrl = mpa_defctrl;	mpa_ctrl.bs_access = &bs_access;	if (playstereo == 0)		mpa_ctrl.layer_3.force_mono = 1;	mpa_ctrl.layer_3.mono.quality = quality;	mpa_ctrl.layer_3.stereo.quality = quality;	mp3_buffer_offset = 0;	mp3_buffer_next_block = 0;	mp3_filename = argv[argnr];	/* Open file or stream to mp3 data */	if (strncmp(mp3_filename, "http://", 7) == 0) {		mp3_stream_size = 0; /*HACK*/		mp3_fd = openhttp(mp3_filename);	} else {		mp3_stream_size = getstreamsize();		mp3_fd = open(mp3_filename, O_RDONLY);	}	if (mp3_fd < 0) {		fprintf(stderr, "ERROR: Unable to open '%s', errno=%d\n",			mp3_filename, errno);		http_streaming = 0;		goto badfile;	}	getmp3taginfo();	/* Get first part of the stream into a ram buffer */	getnextbuffer();mp3_restream:	mps = MPEGDEC_open(mp3_filename, &mpa_ctrl);	if (!mps) {		fprintf(stderr, "ERROR: Unable to open MP3 Audio "			"stream '%s'\n", mp3_filename);		http_streaming = 0;		goto badfile;	}#ifdef CONFIG_KEY	if ((i = getdriverkey(&key, sizeof(key))) > 0)		MPEGDEC_setkey(mps, &key, i);#endif	printmp3info();	if (dsphw)		setdsp(dspfd, playstereo, playbits);	if (lcd_line)		lcdtitle();	gettimeofday(&tvstart, NULL);	sttime = time(NULL);	/* Restart pre-buffering for next track */	prebufnow = prebuflimit;	prebufcnt = 0;	/* We are all set, decode the file and play it */	while ((pcmcount = MPEGDEC_decode_frame(mps, pcm)) >= 0) {		writepcm(dspfd, pcm, pcmcount);		if (gotsigusr1) {			gotsigusr1 = 0;			if (lcd_line)				lcdtitle();		}		if (lcd_time)			lcdtime(sttime);	}	/* Flush out any remaining buffer PCM data */	flushpcm(dspfd); 	gettimeofday(&tvend, NULL);	if (printtime) {		us = ((tvend.tv_sec - tvstart.tv_sec) * 1000000) +		    (tvend.tv_usec - tvstart.tv_usec);		printf("Total time = %d.%06d seconds\n",			(us / 1000000), (us % 1000000));	}badfile:	if (slptime)		sleep(slptime);	close(mp3_fd);	MPEGDEC_close(mps);	mps = NULL;	if (++argnr < argc)		goto nextfile;	if (repeat) {		argnr = startargnr;		goto nextall;	}	close(dspfd);	if (lcdfd >= 0)		close(lcdfd);	exit(0);}/****************************************************************************/

⌨️ 快捷键说明

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