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

📄 mp3.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 4 页
字号:
//****************************************************************************//// MP3.C - Codec interface driver for the MP3 decoder.//// Copyright (c) 1999,2000,2001 Cirrus Logic, Inc.////****************************************************************************#include "globals.h"#ifdef SUPPORT_MP3#include "mp3/mpgdata.h"#include "mp3/mpgaudio.h"#include "buffer/buffer.h"#include "src/src.h"//****************************************************************************//// The name of this codec.////****************************************************************************static const unsigned short pusCodecName[] ={    'M', 'P', '3', ' ', 'M', 'P', 'E', 'G', ' ', 'L', 'a', 'y',    'e', 'r', ' ', '3', '\0'};//****************************************************************************//// A structure which defines the persistent state of the MP3 decoder.////****************************************************************************typedef struct{    //    // A pointer to the buffer containing the persistent internal state of the    // MP3 decoder library.    //    tMPEGInstance *pMPEGInstance;    //    // The file from which we read data.    //    tFile *pFile;    //    // A buffer to contain the encoded MP3 audio.    //    char pcEncodedData[2048];    //    // Buffers to contain the decoded MP3 audio.    //    short psLeft[MP3_MAX_PCM_LENGTH + MP3_MAX_PCM_LENGTH + NUMTAPS - 1];    short psRight[MP3_MAX_PCM_LENGTH + MP3_MAX_PCM_LENGTH + NUMTAPS - 1];    //    // The buffer to which we write decoded MP3 data.    //    BufferState *pOutput;    //    // The MP3 bitstream pointer.    //    tMPEGBitstream sBS;    //    // The decoded MP3 header information.    //    tMPEGHeader sHdr;    //    // The number of bytes in pcEncodedData which contain valid encoded MP3    // data.    //    unsigned short usValid;    //    // The sample rate of the decoded PCM stream.    //    unsigned short usSampleRate;    //    // The number of channels in the file.    //    unsigned char ucChannels;    //    // A boolean which is true if this file uses VBR.    //    unsigned char ucIsVBR;    //    // An unused half-word to pad the next member to a word boundary.    //    unsigned short usUnused;    //    // The offset of the first frame of the file.    //    unsigned long ulFirstFrame;    //    // The byte length of the file.    //    unsigned long ulLength;    //    // The time length of the file.    //    unsigned long ulTimeLength;    //    // The bit rate of the MP3 file.    //    unsigned long ulBitRate;    //    // The number of samples which have been decoded.    //    unsigned long ulTimePos;    //    // The seek points for VBR files.    //    unsigned char pucVBRSeek[100];    //    // A buffer to contain the song title, if known.    //    unsigned short pusTitle[64];    //    // A buffer to contain the song author, if known.    //    unsigned short pusArtist[64];} tMP3;//****************************************************************************//// The following is a mapping from the sample rate descriptor in the// tMPEGHeader structure to the integer number of samples per second.////****************************************************************************static const unsigned short usSRMap[] = { 11025, 12000,  8000, 0,                                          22050, 24000, 16000, 0,                                          44100, 48000, 32000, 0 };//****************************************************************************//// The following is a mapping from the bitrate_index and ID bit in the MPEG// sync header to a the bitrate of the frame.  The first 16 entries are for// ID=0 (i.e. MPEG-2 or MPEG-2.5 half sample rate) and the second 16 entries// are for ID=1 (i.e. MPEG-1 full sample rate).////****************************************************************************static const unsigned short usBRMap[] = {   0,   8,  16,  24,                                           32,  40,  48,  56,                                           64,  80,  96, 112,                                          128, 144, 160,   0,                                            0,  32,  40,  48,                                           56,  64,  80,  96,                                          112, 128, 160, 192,                                          224, 256, 320,   0 };//****************************************************************************//// MP3InitBitstream initializes the stream to the given byte offset in the// file.////****************************************************************************static voidMP3InitBitstream(tMP3 *pMP3, unsigned long ulFilePos){    //    // Seek to the correct block of data in the file.    //    FSSeek(pMP3->pFile, ulFilePos & ~511);    //    // Read the first four pages from this position.    //    pMP3->usValid = FSReadBS(pMP3->pFile, pMP3->pcEncodedData, 2048);    //    // Initialize the bitstream pointer structure.    //    pMP3->sBS.bufptr = (unsigned int *)(pMP3->pcEncodedData +                                        (ulFilePos & 508));    pMP3->sBS.bitidx = 8 * (ulFilePos & 3);}//****************************************************************************//// MP3FindNextFrame finds the next frame in the input MP3 bitstream.////****************************************************************************static unsigned longMP3FindNextFrame(tMP3 *pMP3){    unsigned long ulRead;    //    // Make sure the bitstream pointer structure makes sense (i.e. it is    // pointing to a valid bit in a word, not at the bit following the last    // bit of the previous word).    //    if(pMP3->sBS.bitidx == 32)    {        pMP3->sBS.bufptr++;        pMP3->sBS.bitidx = 0;    }    //    // If the bitstream pointer is not at the beginning of the local bitstream    // buffer, then copy the remaining data back to the beginning.    //    if((int)pMP3->sBS.bufptr != (int)pMP3->pcEncodedData)    {        //        // Copy the remainder of the data from the end of the local bitstream        // buffer to the beginning.        //        memcpy(pMP3->pcEncodedData, pMP3->sBS.bufptr,               2048 - ((int)pMP3->sBS.bufptr -                       (int)pMP3->pcEncodedData));        //        // Update the count of valid bytes in the local bitstream buffer.        //        ulRead = (int)pMP3->sBS.bufptr - (int)pMP3->pcEncodedData;        if(ulRead > pMP3->usValid)        {            pMP3->usValid = 0;        }        else        {            pMP3->usValid -= (int)pMP3->sBS.bufptr - (int)pMP3->pcEncodedData;        }        //        // Update the bitstream pointer structure.        //        pMP3->sBS.bufptr = (unsigned int *)pMP3->pcEncodedData;    }    //    // See if there is any additional MP3 data that we can copy into the local    // bitstream buffer.    //    if(pMP3->usValid <= (2048 - 512))    {        //        // Compute the number of bytes to read.        //        ulRead = (2048 - pMP3->usValid) & ~511;        //        // Read MP3 data into the end of the local bitstream buffer.  Since the        // ARM MP3 decoder needs the bytes within each word swapped, perform        // the byte swap as we read.        //        pMP3->usValid += FSReadBS(pMP3->pFile,                                  pMP3->pcEncodedData + pMP3->usValid,                                  ulRead);    }    //    // Find the next sync word.    //    if(MP3SearchForSyncword(pMP3->pMPEGInstance, &(pMP3->sBS),                            pMP3->usValid * 8) != eNoErr)    {        //        // We could not find a sync word, so return an error.        //        return(0);    }    //    // Decode the header.    //    if(MP3DecodeInfo(pMP3->pMPEGInstance, &(pMP3->sBS),                     &(pMP3->sHdr)) != eNoErr)    {        //        // Skip back past the word that was consumed by the attempt to decode        // the header.        //        pMP3->sBS.bufptr--;        //        // We could not decode the header, so return an error.        //        return(0);    }    //    // Success.    //    return(1);}//****************************************************************************//// MP3DecodeVBRHeader determines if the current frame is a Xing VBR header// frame and decodes it if it is.////****************************************************************************static unsigned longMP3DecodeVBRHeader(tMP3 *pMP3){    unsigned char *pucPtr;    unsigned long ulFlags, ulFrames, ulIdx, ulFrameSize;    //    // Get the offset to the beginning of the current frame.    //    pucPtr = (unsigned char *)pMP3->sBS.bufptr + (pMP3->sBS.bitidx >> 3);    //    // Determine the offset of the header.    //    if(pMP3->usSampleRate >= 32000)    {        //        // This is a MPEG-1 file.  Is this a mono or stereo stream?        //        if(pMP3->ucChannels == 1)        {            //            // This is a mono stream, so the header starts at the 17st byte of            // the frame data.            //            pucPtr += 17;        }        else        {            //            // This is a stereo stream, so the header starts at the 32nd byte            // of the frame data.            //            pucPtr += 32;        }        //        // The frame size for MPEG-1 files is 1152.        //        ulFrameSize = 1152;    }    else    {        //        // This is a MPEG-2 file.  Is this a mono or stereo stream?        //        if(pMP3->ucChannels == 1)        {            //            // This is a mono stream, so the header starts at the 9th byte of            // the frame data.            //            pucPtr += 9;        }        else        {            //            // This is a stereo stream, so the header starts at the 17th byte            // of the frame.            //            pucPtr += 17;        }        //        // The frame size for MPEG-2 files is 576.        //        ulFrameSize = 576;    }    //    // See if the "Xing" signature appears in the frame.    //    if((pucPtr[3] != 'X') || (pucPtr[2] != 'i') ||       (pucPtr[1] != 'n') || (pucPtr[0] != 'g'))    {        //        // This is not a Xing VBR header, so return a failure.        //        return(0);    }    //    // Skip past the signature.    //    pucPtr += 4;    //    // Get the header flags from the stream.    //    ulFlags = (pucPtr[3] << 24) | (pucPtr[2] << 16) |              (pucPtr[1] << 8) | pucPtr[0];    pucPtr += 4;    //    // If the number of frames exists in the header, then extract it now.    //    if(ulFlags & 1)    {        ulFrames = (pucPtr[3] << 24) | (pucPtr[2] << 16) |                   (pucPtr[1] << 8) | pucPtr[0];        pucPtr += 4;    }    else    {        //        // The count of frames does not exist, so we will not be able to        // properly support this file.        //        return(0);    }    //    // If the file size exists in the header, then skip it.    //    if(ulFlags & 2)    {        pucPtr += 4;    }    //    // If the seek point table exists in the header, then read it in now.    //    if(ulFlags & 4)    {        //        // There are 100 entries in the table, so copy them one by one.        //        for(ulIdx = 0; ulIdx < 100; ulIdx++)        {            pMP3->pucVBRSeek[ulIdx ^ 3] = *pucPtr++;        }        //        // Since the seek point table exists in the header, indicate that this        // is a VBR file.        //        pMP3->ucIsVBR = 1;    }    else    {        //        // Since there is no seek point table in the header, treat this file as        // a non-VBR file.        //        pMP3->ucIsVBR = 0;    }    //    // Now, compute the bitrate from the file size and the count of frames in    // the file.    //    pMP3->ulBitRate = ((FSLength(pMP3->pFile) / ulFrames) *                       pMP3->usSampleRate) / (ulFrameSize / 8);    //    // Success.    //    return(1);}//****************************************************************************

⌨️ 快捷键说明

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