📄 mp3play.c
字号:
{ 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 + -