📄 test2.c
字号:
#include "test2.h"
/****************************************************************************/
/*
* Get stream size (just file size).
*/
static int getstreamsize(void)
{
struct stat st;
if (stat(mp3_filename, &st) < 0)
return(0);
return(st.st_size);
}
/****************************************************************************/
/****************************************************************************/
/*
* Get another chunk of data into RAM.
*/
static UINT32 getnextbuffer()
{
int rc;
printf("%s mp3_buffer_next_block:%p\n", __FUNCTION__, mp3_buffer_next_block);
lseek(mp3_fd, mp3_buffer_next_block, SEEK_SET);
rc = read(mp3_fd, mp3_buffer, MP3_BUF_SIZE);
mp3_buffer_size = (rc < 0) ? 0 : rc;
mp3_buffer_next_block += mp3_buffer_size;
return(mp3_buffer_size);
}
/****************************************************************************/
/*
* Start our own bitstream access routines.
*/
INT32 bs_open(char *stream_name, INT32 buffer_size, INT32 *stream_size)
{
#if 0
printf("bs_open: '%s'\n", stream_name);
#endif
if (!mp3_buffer)
return(0);
mp3_buffer_offset = 0;
/* We know total size, we can set it */
*stream_size = mp3_stream_size;
/* Just return a dummy handle (not NULL) */
return(1);
}
/****************************************************************************/
void bs_close(INT32 handle)
{
#if 0
printf("bs_close\n");
#endif
/* Don't need to do anything... */
}
/****************************************************************************/
INT32 bs_read(INT32 handle, void *buffer, INT32 num_bytes)
{
INT32 read_size;
// printf("bs_read\n");
if (!handle )
return(-1);
tryagain:
read_size = mp3_buffer_size - mp3_buffer_offset;
if (read_size > num_bytes)
read_size = num_bytes;
if (read_size > 0) {
if(!buffer)
return(-1);
memcpy(buffer, &mp3_buffer[mp3_buffer_offset], read_size);
mp3_buffer_offset += read_size;
} else {
if (getnextbuffer() > 0) {
mp3_buffer_offset = 0;
goto tryagain;
}
read_size = -1; /* End of stream */
}
return(read_size);
}
/****************************************************************************/
int bs_seek(INT32 handle, INT32 abs_byte_seek_pos)
{
// printf("bs_seek\n");
if (!handle)
return(-1);
if (abs_byte_seek_pos <= 0)
mp3_buffer_offset = 0;
else if (abs_byte_seek_pos >= mp3_buffer_size)
return(-1);
else
mp3_buffer_offset = abs_byte_seek_pos;
return(0);
}
MPEGDEC_ACCESS bs_access = { bs_open, bs_close, bs_read, bs_seek };
/****************************************************************************/
/*
* Configure DSP engine settings for playing this track.
*/
void setdsp(int fd, int playstereo, int playbits)
{
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);
}
//ioctl(fd, SNDCTL_DSP_CHANNELS, &(mps->channels));
#if __BYTE_ORDER == __LITTLE_ENDIAN
bits = (playbits == 16) ? AFMT_S16_LE : AFMT_U8;
#elif __BYTE_ORDER == __BIG_ENDIAN
bits = (playbits == 16) ? AFMT_S16_BE : AFMT_U8;
#else
#error "I don't know what endian your machine is??"
#endif
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);
}
}
/****************************************************************************/
/*
* 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);
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 close_all()
{
close(mp3_fd);
MPEGDEC_close(mps);
mps = NULL;
close(dspfd);
ready = 0;
}
/****************************************************************************/
int ready_play( const char *fn )
//int main(int argc, char *argv[])
{
int playbits, playstereo;
char *device;
int c, i, j;
playstereo = 1;
playbits = 16;
quality = 2;
prebuflimit = 64000;
device = "/dev/dsp";
mp3_buffer = (INT8 *) fmalloc(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] = fmalloc(MPEGDEC_PCM_SIZE * sizeof(INT16));
if (!pcm[i]) {
fprintf(stderr, "ERROR: Can't allocate PCM buffers\n");
exit(1);
}
}
if ((rawbuf = fmalloc(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);
}
}
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);
}
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[1];
mp3_filename = (char *)fn;
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);
close_all();
exit(0);
}
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);
close_all();
exit(0);
}
setdsp(dspfd, playstereo, playbits);
/* Restart pre-buffering for next track */
prebufnow = prebuflimit;
prebufcnt = 0;
ready = 1;
}
void play_frame( unsigned char *ply )
{
if ( ready ) {
*ply = 1;
if((pcmcount = MPEGDEC_decode_frame(mps, pcm))<0) {
printf("pcmcount =%d.\n", pcmcount);
if(pcmcount==MPEGDEC_ERR_EOF) {
/* Flush out any remaining buffer PCM data */
flushpcm(dspfd);
close_all();
exit(0);
}
}
writepcm(dspfd, pcm, pcmcount);
*ply = 0;
}
}
void play_forward( int f )
{
if ( ( mp3_buffer_next_block + f*1024 ) < mp3_stream_size )
mp3_buffer_next_block += f*1024;
}
void play_backward( int b )
{
mp3_buffer_next_block -= b*1024;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -