mp3

/**************************************************************************************  
                    MP3 同步头搜索并检验程序  
**************************************************************************************/   
#include    <stdio.h>   
#include    <string.h>   
#include    <stdlib.h>   
   
#define     MP3_HEADER_MASK     0xFFFE0C00          // 同步头匹配, 忽略比特率   
#define     MIN_MP3_DURATION    4000   
#define     MP3_MIN_LENGTH      1000                // MP3 文件最小长度   
#define     MP3_BUF_LENGTH      1024                // MP3 文件缓冲区大小   
#define     MP3_SEARCH_LEN      0x3FFE              // MP3 搜索同步头最大长度   
#define     MAX_AUDIO_FILE      10   
   
/* audio error code */   
#define     AUDIO_ERR_NONE          0   // 无错误   
#define     AUDIO_ERR_DISK          1   // 磁盘错误(读写)   
#define     AUDIO_ERR_FORMAT        2   // 文件格式错误   
#define     AUDIO_ERR_MEMORY        3   // 内存错误   
#define     AUDIO_ERR_PARAM         4   // 参数错误   
#define     AUDIO_ERR_NOTSUPPORT    5   // 不支持的操作或类型   
#define     AUDIO_ERR_TOOMANYFILE   6   // 打开太多文件   
#define     AUDIO_ERR_NOTFOUND      7   // 文件未找到   
#define     AUDIO_ERR_LOWVOLTAGE    8   // 低电   
#define     AUDIO_ERR_DECODER       9   // 解码器未响应   
#define     AUDIO_ERR_DISKFULL      10  // 磁盘满   
   
// MP3   
typedef struct  tagFRAMEHEADER   
{   
    unsigned emphasis   : 2;    // M ▓   
    unsigned original   : 1;    // L   
    unsigned copyright  : 1;    // K   
    unsigned modeext    : 2;    // J   
    unsigned chanmode   : 2;    // I   
    unsigned privbit    : 1;    // H   
    unsigned padding    : 1;    // G   
    unsigned samplerate : 2;    // F   
    unsigned bitrate    : 4;    // E   
    unsigned hascrc     : 1;    // D   
    unsigned mpeglayer  : 2;    // C   
    unsigned mpegver    : 2;    // B   
    unsigned framesync  : 11;   // A   
} FRAMEHEADER;   
   
typedef struct  tagMEDIAFILEINFO   
{   
    unsigned long   dwFileLength;       // 文件长度   
    unsigned long   dwDuration;         // 播放时间   
    unsigned long   dwBitRate;          // 比特率   
    unsigned long   dwSampleRate;       // 采样率   
    unsigned char   bSampleSize;        // 采样大小   
    unsigned char   bChannels;          // 声道数目   
    unsigned char   bIsVBR;             // 是否为变速   
    unsigned char   bIsProtected;       // 是否受保护   
    unsigned long   dwNumOfFrames;      // 帧数量   
    unsigned long   dwFrameSize;        // 帧大小   
    unsigned long   dwFrameDuration;    // 帧播放时间   
    unsigned long   dwFrameOffset;      // 首帧偏移   
    const char*     szArtist;           // 艺术家   
    const char*     szAlbumTitle;       // 专辑名   
    unsigned short  wYear;              // 年   
    unsigned short  wTrackNumber;       // 音轨号   
    const char*     szGenre;            // 流派   
    const char*     szLyrics;           // 文本歌词   
    const char*     szTitle;            // 名称   
    const char*     szComments;         // 备注   
} MEDIAFILEINFO;   
   
typedef struct  tagMP3_FILE   
{   
    FILE*       fp;   
    MEDIAFILEINFO   mfi;   
   
    unsigned char*  vbr_toc;   
    long            pos;   
   
    unsigned long*  vbri_toc;   
    long            vbri_toc_cnt;   
    long            vbri_toc_frm;   
   
    float           fFrameDuration;   
} MP3_FILE;   
   
///   
   
const int nMpegVer  [] = { 3, 0, 2, 1 };   
const int nMpegLayer[] = { 0, 3, 2, 1 };   
const int nBitrateTable[3][3][16] =   
{   
    // V1 L1   
    0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1,   
    // V1 L2   
    0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1,   
    // V1 L3   
    0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1,   
    // V2 L1   
    0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1,   
    // V2 L2   
    0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1,   
    // V2 L3   
//  0,  8, 16, 24,  32,  64,  80,  56,  64, 128, 160, 112, 128, 256, 320, -1,   
    0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1,   
    // V2.5 L1   
    0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1,   
    // V2.5 L2   
    0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1,   
    // V2.5 L3   
//  0,  8, 16, 24,  32,  64,  80,  56,  64, 128, 160, 112, 128, 256, 320, -1 
    0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1   
};   
   
const int nSamplingRateTable[3][4] =   
{   
    // MPEG1                // MPEG 2               // MPEG 2.5   
    44100, 48000, 32000, 0, 22050, 24000, 16000, 0, 11025, 12000,  8000, 0   
};   
   
// Samples per Frame: 1. index = LSF, 2. index = Layer   
const int dwSamplesPerFrames[][3] =   
{   
    {   // MPEG 1   
        384,    // Layer1   
        1152,   // Layer2      
        1152    // Layer3   
    },   
    {   // MPEG 2   
        384,    // Layer1   
        1152,   // Layer2   
        576     // Layer3   
    },   
    {   // MPEG 2.5   
        384,    // Layer1   
        1152,   // Layer2   
        576     // Layer3   
    }   
};   
   
///   
   
static MP3_FILE*    mp3HandleTable[10];   
   
int         gAudioErrCode;      // 错误代码   
int         gWaittingMemory;   
   
///   
   
static void REV_DWORD(void* p);   
int IsValidFrameHeader(FRAMEHEADER* pfh);   
   
///   
   
// reverse dword(32 bit)   
static   
void REV_DWORD(void* p)   
{   
    unsigned char   b0, b1, b2, b3;   
   
    b0 = *((unsigned char*)p + 0);   
    b1 = *((unsigned char*)p + 1);   
    b2 = *((unsigned char*)p + 2);   
    b3 = *((unsigned char*)p + 3);   
   
    *((unsigned char*)p + 0) = b3;   
    *((unsigned char*)p + 1) = b2;   
    *((unsigned char*)p + 2) = b1;   
    *((unsigned char*)p + 3) = b0;   
}   
   
static   
unsigned short RevShort(unsigned short data)   
{   
    unsigned char   b0, b1 ;   
    short *p = &data ;   
   
    b0 = *((unsigned char*)p + 0);   
    b1 = *((unsigned char*)p + 1);   
       
    *((unsigned char*)p + 0) = b1;   
    *((unsigned char*)p + 1) = b0;   
       
    return data ;   
}      
   
// 验证是否为有效帧头   
int IsValidFrameHeader(FRAMEHEADER* pfh)   
{   
    // 11 bit   
    if (0x7FF != pfh->framesync) return 0;   
    // 2bit   
    if (0x01 == pfh->mpegver) return 0;   
    // 2bit   
    if (0x00 == pfh->mpeglayer) return 0;   
    // 4bit   
    if (0x00 == pfh->bitrate || 0x0F == pfh->bitrate) return 0;   
    // 2bit   
    if (0x03 == pfh->samplerate) return 0;   
   
    return 1;   
}   
   
// calc frame size   
long calc_mp3_frm_size(FRAMEHEADER* pfh)   
{   
    int     ver   = nMpegVer[pfh->mpegver];   
    int     layer = nMpegLayer[pfh->mpeglayer];   
    long    frame_size;   
    int     bit_rate;   
    int     sample_rate;   
   
    bit_rate    = nBitrateTable[ver - 1][layer - 1][pfh->bitrate];   
    sample_rate = nSamplingRateTable[ver - 1][pfh->samplerate];   
   
    if (1 == ver)   // MPEG 1   
        frame_size = 144 * 1000 * bit_rate / sample_rate + pfh->padding; 
    else   
        frame_size = 72 * 1000 * bit_rate / sample_rate + pfh->padding;   
   
    return frame_size;   
}   
   
///   
   
int MP3_Init(void)   
{   
    memset(mp3HandleTable, 0x00, MAX_AUDIO_FILE * sizeof(MP3_FILE*));   
    return 0;   
}   
   
int MP3_Open(char* mp3_filename)   
{   
    FRAMEHEADER     fh;   
    int             valid_frame = 0;   
    long            id;   
    int             i;   
   
    FILE*       fp;   
    long            file_length;            // 文件长度   
// MP3 frame info   
    long            frame_num;              // 帧总数   
    long            frame_size;             // 帧大小   
    long            frame_offset;           // 第一个帧在文件内偏移   
// MP3 format info   
    unsigned char*  vbr_toc;                // VBR索引 (Xing)   
    unsigned long*  vbri_toc;               // (VBRI)   
    long            vbri_toc_cnt;           // (VBRI)   
    long            vbri_toc_frm;           // (VBRI)   
    unsigned char   is_vbr_format;          // 是否为VBR格式   
    unsigned char   channels;   
    int             bit_rate;               // 比特率   
    int             sample_rate;            // 采样率   
    int             duration;               // 总播放时间   
    long            search_start;           // 开始搜索帧头的位置   
    float           fFrameDuration;   
   
    fp = fopen(mp3_filename, "rb");   
    if (0 == fp)   
    {   
        gAudioErrCode = AUDIO_ERR_NOTFOUND;   
        return -1;   
    }   
   
    fseek(fp, 0, SEEK_END);   
    file_length = ftell(fp);   
   
    if (file_length  MP3_MIN_LENGTH)   
    {   
        gAudioErrCode = AUDIO_ERR_FORMAT;   
        fclose(fp);   
        return -1;   
    }   
   
   
    // ID3 tag   
    fseek(fp, -128, SEEK_END);   
    fread(&id, 4, 1, fp);   
   
    if ('GAT' == id)        // "TAG\0"   
        file_length -= 128;   
   
   
    fseek(fp, 0, SEEK_SET);   
   
    if (!fread(&id, 4, 1, fp))   
    {   
        gAudioErrCode = AUDIO_ERR_FORMAT;   
        fclose(fp);   
        return -1;   
    }   
   
    // 存在ID3标签   
    id &= 0xFFFFFF;         // remove version field   
   
    if (0x334449 == id)     // 'ID3'   
    {   
        char    buf[4];   
   
        fseek(fp, 2, SEEK_CUR);   
        if (!fread(buf, 4, 1, fp))   
        {   
            gAudioErrCode = AUDIO_ERR_FORMAT;   
            fclose(fp);   
            return -1;   
        }   
        else   
        {   
            frame_offset = (buf[0] & 0x7F) * 0x200000L   
                         + (buf[1] & 0x7F) * 0x004000L   
                         + (buf[2] & 0x7F) * 0x000080L   
                         + (buf[3] & 0x7F)   
                         + 10;          // ID3 header   
   
            // ID3 length error   
            if (frame_offset  file_length)   
            {   
                // read 1st frame header   
                fseek(fp, frame_offset, SEEK_SET);   
                if (!fread(&fh, 4, 1, fp))   
                {   
                    gAudioErrCode = AUDIO_ERR_DISK;   
                    fclose(fp);   
                    return -1;   
                }   
                // big endian -> little endian   
                REV_DWORD(&fh);   
                valid_frame = IsValidFrameHeader(&fh);   
            }   
        }   
    }   
    else   
    {   
        fseek(fp, 0, SEEK_SET);   
    }   
   
    // search sync   
    if (!valid_frame)   
    {   
        search_start = ftell(fp);   
        while (1)   
        {   
            // read frame header   
            if (4 != fread(&fh, 1, 4, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_FORMAT;   
                fclose(fp);   
                return -1;   
            }   
   
            // big endian -> little endian   
            REV_DWORD(&fh);   
            if (IsValidFrameHeader(&fh)) break;   
   
            if (ftell(fp) - search_start > MP3_SEARCH_LEN)   
            {   
                gAudioErrCode = AUDIO_ERR_FORMAT;   
                fclose(fp);   
                return -1;   
            }   
   
            fseek(fp, -3, SEEK_CUR);   
        }   
    }   
    else   
    {   
        search_start = 0;   
    }   
   
    // 1st frame header found   
    frame_offset = ftell(fp) - 4;   
    frame_size   = calc_mp3_frm_size(&fh);   
   
//-------------------------------------------------------------------------------------   
   
    // check for VBR format   
    if (3 == fh.mpegver)        // MPEG 1   
    {   
        if (3 == fh.chanmode)   // mono   
            fseek(fp, 21 - 4, SEEK_CUR);   
        else                    // stereo   
            fseek(fp, 36 - 4, SEEK_CUR);   
    }   
    else if (2 == fh.mpegver)   // MPEG 2   
    {   
        if (3 == fh.chanmode)   // mono   
            fseek(fp, 13 - 4, SEEK_CUR);   
        else                    // stereo   
            fseek(fp, 21 - 4, SEEK_CUR);   
    }   
   
    if (4 != fread(&id, 1, 4, fp))   
    {   
        gAudioErrCode = AUDIO_ERR_DISK;   
        fclose(fp);   
        return -1;   
    }   
   
    vbr_toc       = (unsigned char*)0;   
    vbri_toc      = 0;   
    vbri_toc_cnt  = 0;   
    frame_num     = 0;   
    is_vbr_format = ('gniX' == id) ||   // Xing   
                    ('ofnI' == id) ||   // Info   
                    ('IRBV' == id);     // VBRI   
//                  0;                  // none   
   
    if (is_vbr_format)   
    {   
        if ('IRBV' == id)   // 'VBRI'   
        {   
            unsigned short toc_cnt;   
            unsigned short toc_scale;   
            unsigned short toc_size;   
            unsigned short toc_frames;   
   
            fseek(fp, 6, SEEK_CUR);   
   
            // Number of Bytes as Big-Endian DWORD   
            if (0 == fread(&file_length, 4, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            REV_DWORD(&file_length);   
   
            // Number of Frames as Big-Endian DWORD    
            if (0 == fread(&frame_num, 4, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            REV_DWORD(&frame_num);   
   
            // Number of entries within TOC table as Big-Endian WORD   
            if (0 == fread(&toc_cnt, 2, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            toc_cnt = RevShort(toc_cnt);   
   
            vbri_toc_cnt = toc_cnt + 1; // !!!   
   
            // Scale factor of TOC table entries as Big-Endian WORD   
            if (0 == fread(&toc_scale, 2, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            toc_scale = RevShort(toc_scale);   
   
            // Size per table entry in bytes (max 4) as Big-Endian WORD   
            if (0 == fread(&toc_size, 2, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            toc_size = RevShort(toc_size);   
   
            if (toc_size > 4 || toc_size  1)   
            {   
                gAudioErrCode = AUDIO_ERR_FORMAT;   
                fclose(fp);   
                return -1;   
            }   
   
            // Frames per table entry as Big-Endian WORD   
            if (0 == fread(&toc_frames, 2, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            toc_frames = RevShort(toc_frames);   
            vbri_toc_frm = toc_frames;   
   
            vbri_toc = (unsigned long*)malloc(vbri_toc_cnt * sizeof(unsigned long));   
            if (!vbri_toc)   
            {   
                gAudioErrCode = AUDIO_ERR_MEMORY;   
                fclose(fp);   
                return -1;   
            }   
   
            // read toc   
            {   
                int             j = vbri_toc_cnt + 1;   
                unsigned long*  p = vbri_toc;   
                unsigned long   pos = 0;            // must be unsigned   
                float           fscale;   
   
                while (--j)   
                {   
                    unsigned long toc_entry = 0;    // must be unsigned   
                    if (0 == fread(&toc_entry, toc_size, 1, fp))   
                    {   
                        free(vbri_toc);   
                        gAudioErrCode = AUDIO_ERR_FORMAT;   
                        fclose(fp);   
                        return -1;   
                    }   
                    REV_DWORD(&toc_entry);   
                    toc_entry >>= 8 * (4 - toc_size);   
                    pos += toc_entry * toc_scale;   
                    *p++ = pos;   
                }   
   
                j = vbri_toc_cnt + 1;   
                p = vbri_toc;   
                fscale = (float)((double)file_length / (double)pos);   
                while (--j)   
                {   
                    *p *= (unsigned long)fscale;   
                    p++;   
                }   
            }   
        }   
        else        // 'Xing'   
        {   
            long    flag;   
            if (0 == fread(&flag, 4, 1, fp))   
            {   
                gAudioErrCode = AUDIO_ERR_DISK;   
                fclose(fp);   
                return -1;   
            }   
            REV_DWORD(&flag);   
   
            if (flag & 1)       // Frames Flag   
            {   
                if (0 == fread(&frame_num, 4, 1, fp))   
                {   
                    gAudioErrCode = AUDIO_ERR_DISK;   
                    fclose(fp);   
                    return -1;   
                }   
                REV_DWORD(&frame_num);   
            }   
   
            if (flag & 2)       // Bytes Flag   
            {   
                if (0 == fread(&file_length, 4, 1, fp))   
                {   
                    gAudioErrCode = AUDIO_ERR_DISK;   
                    fclose(fp);   
                    return -1;   
                }   
                REV_DWORD(&file_length);   
            }   
   
            vbr_toc = malloc(100);   
            if (0 == vbr_toc)   
            {   
                gAudioErrCode = AUDIO_ERR_MEMORY;   
                fclose(fp);   
                return -1;   
            }   
   
            if (flag & 4)       // TOC Flag   
            {   
                if (0 == fread(vbr_toc, 100, 1, fp))   
                {   
                    gAudioErrCode = AUDIO_ERR_DISK;   
                    free(vbr_toc);   
                    fclose(fp);   
                    return -1;   
                }   
            }   
            else            // TOC Flag does not exist, create it   
            {   
                for (i = 0; i  100; i++)   
                    vbr_toc[i] = i * 256 / 100;   
            }   
        }   
    }   
//-------------------------------------------------------------------------------------   
    else   
    {   
        long    last_header;   
   
        // check next frame...   
        fseek(fp, frame_offset + frame_size, SEEK_SET);   
   
        while (1)   
        {   
            last_header = *(long*)&fh;   
   
            // search sync   
            while (1)   
            {   
                // read frame header   
                if (4 != fread(&fh, 1, 4, fp))   
                {   
                    gAudioErrCode = AUDIO_ERR_FORMAT;   
                    fclose(fp);   
                    return -1;   
                }   
   
                // big endian -> little endian   
                REV_DWORD(&fh);   
                if (IsValidFrameHeader(&fh)) break;   
   
                if (ftell(fp) - search_start > MP3_SEARCH_LEN)   
                {   
                    gAudioErrCode = AUDIO_ERR_FORMAT;   
                    fclose(fp);   
                    return -1;   
                }   
   
                fseek(fp, -3, SEEK_CUR);   
            }   
   
            // found it   
            if ((*(long*)&fh & MP3_HEADER_MASK) == (last_header & MP3_HEADER_MASK))   
            {   
                frame_size += calc_mp3_frm_size(&fh);   
                break;   
            }   
   
// BUG文档编号: DW/BUG/200511/0203   
            frame_offset = ftell(fp) - 4;   
            frame_size = calc_mp3_frm_size(&fh);   
            fseek(fp, frame_size - 4, SEEK_CUR);   
        }   
    }   
   
   
//-------------------------------------------------------------------------------------   
   
    {   
        int ver   = nMpegVer[fh.mpegver];   
        int layer = nMpegLayer[fh.mpeglayer];   
   
        // only layer 3 is supportted   
        if (3 != layer)   
        {   
            gAudioErrCode = AUDIO_ERR_NOTSUPPORT;   
            if (vbr_toc) free(vbr_toc);   
            if (vbri_toc) free(vbri_toc);   
            fclose(fp);   
            return -1;   
        }   
   
        bit_rate    = nBitrateTable[ver - 1][layer - 1][fh.bitrate];   
        sample_rate = nSamplingRateTable[ver - 1][fh.samplerate];   
   
   
        if (is_vbr_format)   
            fFrameDuration = (float)((double)dwSamplesPerFrames[ver - 1][layer - 1] * 1000.0 / (double)sample_rate);   
        else   
            fFrameDuration = (float)((double)frame_size * 8.0 / (double)bit_rate);   
    }   
   
    if (3 != fh.chanmode)   
        channels = 2;   
    else   
        channels = 1;   
   
   
//-------------------------------------------------------------------------------------   
   
    if (0 == frame_num)   
        frame_num = (file_length - frame_offset) / frame_size;   
   
    duration = (int)((double)frame_num * (double)fFrameDuration);   
   
   
//-------------------------------------------------------------------------------------   
   
    fseek(fp, frame_offset, SEEK_SET);   
   
    // find free handle   
    for (i = 0; i  MAX_AUDIO_FILE; i++)   
    {   
        if (0 == mp3HandleTable[i])   
            break;   
    }   
   
    if (MAX_AUDIO_FILE == i)   
    {   
        gAudioErrCode = AUDIO_ERR_TOOMANYFILE;   
        if (vbr_toc) free(vbr_toc);   
        if (vbri_toc) free(vbri_toc);   
        fclose(fp);   
        return -1;   
    }   
   
    mp3HandleTable[i] = (MP3_FILE*)malloc(sizeof(MP3_FILE));   
    if (0 == mp3HandleTable[i])   
    {   
        gAudioErrCode = AUDIO_ERR_MEMORY;   
        if (vbr_toc) free(vbr_toc);   
        if (vbri_toc) free(vbri_toc);   
        fclose(fp);   
        return -1;   
    }   
   
    memset(mp3HandleTable[i], 0x00, sizeof(MP3_FILE));   
   
    mp3HandleTable[i]->fp                  = fp;   
    mp3HandleTable[i]->vbr_toc             = vbr_toc;   
    mp3HandleTable[i]->vbri_toc            = vbri_toc;   
    mp3HandleTable[i]->vbri_toc_cnt        = vbri_toc_cnt;   
    mp3HandleTable[i]->vbri_toc_frm        = vbri_toc_frm;   
    mp3HandleTable[i]->pos                 = frame_offset;   
    mp3HandleTable[i]->fFrameDuration      = fFrameDuration;   
   
    // media file infomation   
    mp3HandleTable[i]->mfi.dwFileLength    = file_length;   
    mp3HandleTable[i]->mfi.dwDuration      = duration;   
    mp3HandleTable[i]->mfi.dwBitRate       = bit_rate;   
    mp3HandleTable[i]->mfi.dwSampleRate    = sample_rate;   
    mp3HandleTable[i]->mfi.bSampleSize     = 16;         // 16 bit   
    mp3HandleTable[i]->mfi.bChannels       = channels;   
   
    mp3HandleTable[i]->mfi.bIsVBR          = is_vbr_format;   
    mp3HandleTable[i]->mfi.bIsProtected    = 1;   
   
    mp3HandleTable[i]->mfi.dwNumOfFrames   = frame_num;   
    mp3HandleTable[i]->mfi.dwFrameSize     = frame_size;   
    mp3HandleTable[i]->mfi.dwFrameDuration = (long)fFrameDuration; 
    mp3HandleTable[i]->mfi.dwFrameOffset   = frame_offset;   
   
    mp3HandleTable[i]->mfi.szArtist        = 0;   
    mp3HandleTable[i]->mfi.szAlbumTitle    = 0;   
    mp3HandleTable[i]->mfi.wYear           = 0;   
    mp3HandleTable[i]->mfi.wTrackNumber    = 1;   
    mp3HandleTable[i]->mfi.szGenre         = 0;   
    mp3HandleTable[i]->mfi.szLyrics        = 0;   
    mp3HandleTable[i]->mfi.szTitle         = 0;   
    mp3HandleTable[i]->mfi.szComments      = 0;   
   
    gAudioErrCode = AUDIO_ERR_NONE;   
    return i;   
}   
   
int MP3_Close(int handle)   
{   
    if (handle >= MAX_AUDIO_FILE)   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    if (0 == mp3HandleTable[handle])   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    if (mp3HandleTable[handle]->vbr_toc)   
        free(mp3HandleTable[handle]->vbr_toc);   
    if (mp3HandleTable[handle]->vbri_toc)   
        free(mp3HandleTable[handle]->vbri_toc);   
   
    fclose(mp3HandleTable[handle]->fp);   
       
    free(mp3HandleTable[handle]);   
   
    mp3HandleTable[handle] = 0;   
   
    return 0;   
}   
   
int MP3_Seek(int handle, unsigned long time)   
{   
    MEDIAFILEINFO*  pmfi;   
    long            pos;   
   
    if (handle >= MAX_AUDIO_FILE)   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    if (0 == mp3HandleTable[handle])   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    pmfi = &mp3HandleTable[handle]->mfi;   
   
    if (time  0)   
        time = 0;   
    if (time > pmfi->dwDuration)   
        time = pmfi->dwDuration;   
   
#ifdef      MP3_SUPPORT_FAV   
    fav_mp3_time = time;   
#endif   
   
    // 计算文件偏移   
    if (pmfi->bIsVBR)   
    {   
        if (mp3HandleTable[handle]->vbr_toc) // Xing   
        {   
            long ratio = mp3HandleTable[handle]->vbr_toc[time * 99 / pmfi->dwDuration];   
            pos = ratio * pmfi->dwFileLength / 256;   
        }   
        else    // VBRI   
        {   
            float   fidx = time / mp3HandleTable[handle]->fFrameDuration / mp3HandleTable[handle]->vbri_toc_frm;   
            int     iidx = (int)fidx;   
   
            fidx -= iidx;   
   
            if (iidx)   
            {   
                if (iidx > mp3HandleTable[handle]->vbri_toc_cnt)   
                    iidx = mp3HandleTable[handle]->vbri_toc_cnt;   
                iidx--;   
                pos = mp3HandleTable[handle]->vbri_toc[iidx] + pmfi->dwFrameOffset;   
            }   
            else   
            {   
                pos = 0;   
            }   
   
            if (iidx  mp3HandleTable[handle]->vbri_toc_cnt - 1)   
                pos += (long)((mp3HandleTable[handle]->vbri_toc[iidx + 1] - mp3HandleTable[handle]->vbri_toc[iidx]) * fidx);   
        }   
    }   
    else   
    {   
        pos = (long)((double)time * (double)pmfi->dwFrameSize / (double)mp3HandleTable[handle]->fFrameDuration   
                + pmfi->dwFrameOffset);   
    }   
   
    mp3HandleTable[handle]->pos = pos;   
    return 0;   
}   
   
   
size_t MP3_Read(int handle, void* buf, size_t length)   
{   
    size_t      ret;   
   
    if (handle >= MAX_AUDIO_FILE)   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return 0;   
    }   
   
    if (0 == mp3HandleTable[handle])   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    ret = fread(buf, mp3HandleTable[handle]->pos, length, mp3HandleTable[handle]->fp);   
    mp3HandleTable[handle]->pos += ret;   
   
    return ret;   
}   
   
size_t MP3_Write(int handle, const void* buf, size_t length)   
{   
    return 0;   
}   
   
size_t MP3_ReadBuffer(int handle, void* buf, size_t length)   
{   
    return 0;   
}   
   
size_t MP3_WriteBuffer(int handle, const void* buf, size_t length)   
{   
    return 0;   
   
}   
   
int MP3_GetInfo(int handle, MEDIAFILEINFO* pmfi)   
{   
    if (handle >= MAX_AUDIO_FILE)   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    if (0 == mp3HandleTable[handle])   
    {   
        gAudioErrCode = AUDIO_ERR_PARAM;   
        return -1;   
    }   
   
    memcpy(pmfi, &mp3HandleTable[handle]->mfi, sizeof(MEDIAFILEINFO));   
    return 0;   
}   
   
   
int main()   
{   
    int i ;   
    MP3_Init();   
    i = MP3_Open("d:\\1.mp3") ;   
   
    if (i)   
    {   
        printf("mp3 open err!!!\r\n");   
    }   
    else   
    {   
        printf("===========MP3 Infomation==================\r\n");   
        printf("Channel ,  BitRate  , SampleRate , Duration \r\n");   
        printf("  %d    ,    %dKbps ,  %dHZ   , %dMS \r\n" , mp3HandleTable[0]->mfi.bChannels ,  mp3HandleTable[0]->mfi.dwBitRate ,   mp3HandleTable[0]->mfi.dwSampleRate ,    mp3HandleTable[0]->mfi.dwDuration );   
        printf("=====================================\r\n");   
    }   
    return 0 ;   
}   
/**************************************************************************************/  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值