MP3文件解析

目前解析了 MP3的头,帧头。接下来要做的就是 哈夫曼解码了。。。无力了囧

MP3文件的整体数据解析不过也算是个成长的见证,从去年怎么也弄不明白。到今天。:)好好学习天天向上


#ifndef __FRAME__INFO__H__

#define __FRAME__INFO__H__


const int SamplingRateTable[][4] =
{
{ 44100, 22050, 11025 }, // 00
{ 48000, 24000, 12000 }, // 01
{ 32000, 16000, 8000 }, // 10
{ 0,     0,     0} // 11
};

const int SamplingSizeTable[3][3] = 
{
{ 384, 384, 384 },
{ 1152, 1152, 1152 },
{ 1152, 576, 576 }
};

const short int BitrateTable[2][3][15] =
{
    {
        {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
        {0,32,48,56,64 ,80 ,96 ,112,128,160,192,224,256,320,384},
        {0,32,40,48,56 ,64 ,80 ,96 ,112,128,160,192,224,256,320}
    },
    {
        {0,32,48,56,64 ,80 ,96 ,112,128,144,160,176,192,224,256},
        {0,8 ,16,24,32 ,40 ,48 ,56 ,64 ,80 ,96 ,112,128,144,160},
        {0,8 ,16,24,32 ,40 ,48 ,56 ,64 ,80 ,96 ,112,128,144,160}
    }
};

#ifndef BYTE
typedef unsigned char BYTE;
#endif


struct XINGInfo{
unsigned char VBRID[4];
unsigned int Flags ;
unsigned int FramesNumber;
unsigned int BytesNumber;
char TOC[100];
int Quality ;
};

class FrameInfo
{
public:
// 同步标识
unsigned short mSycnFlag;
// MPEG版本
BYTE mMPEGVersion;
// 
BYTE mLayerIndex;
// Protection bit
BYTE mProtection;
// 比特率索引
BYTE mBps;
// 采样索引
BYTE mSamplingIndex;
// Padding bit
BYTE mPadding;
// 保护
BYTE mPrivate;
// Channel
BYTE mChannelMode;
// 扩展模式
BYTE mModeExtension;

BYTE mCopyright;

BYTE mOriginal;

BYTE mEmphasis;

public:
bool init(int fixFrameHeard);

// 获取比特率
short int getBitrate();

// 获取采样大小
int getSamplingSize();

// 获取采样率
int  getSamplingRate();

int getFrameSize();

// 获取边信息大小
int getEdgeSize();
};



struct ID3V2_HEADER{
char Header[3];
char Ver;      
char Revision;
char Flag;    
char Size[4];
};

struct ID3V2_FRAME_HEADER{
char FrameID[4];
char Size[4];
char Flag[2];
};


struct ID3V1{
char Header[3];    
char Title[30];    
char Artist[30];  
char Album[30];    
char Year[4];      
char Comment[28];
char reserve;      
char track;;      
char Genre;        
};

#include "cocos2d.h"

class MP3File
{
private:

// 初始化IDV3头
bool initID3V2Header();
// 初始化第一帧的数据 
bool initFirstFrame();

// 是否拥有IDV3头
bool m_bHaveID3V2;

private: // 
// IDV3
ID3V2_HEADER mID3V2Header;
// 数据缓存
unsigned char* m_pDataBuffer;
// 缓存数据长度
unsigned long m_lDataLength;
public:

// 获取第一帧开始位置
int getFrameOffset();

// 获取标签头
int getFrameSize();
// 初始化到文件
bool initFile(const char* pszFilepath);

// 解析文件
static MP3File* parse(const char* pszFilepath);



};


#endif





#include "FrameInfo.h"

bool FrameInfo::init(int fixFrameHeard){

// 同步头
this->mSycnFlag = (fixFrameHeard & 0xFFE00000) >> 16;
if(this->mSycnFlag != 0xFFE0){
return false;
}

// 2  0000 0000 0001 1000 0000 0000 0000 0000
this->mMPEGVersion = (fixFrameHeard & 0x180000) >> 19;

// 2  0000 0000 0000 0110 0000 0000 0000 0000
this->mLayerIndex = (fixFrameHeard & 0x60000) >> 17;
    
// 1  0000 0000 0000 0001 0000 0000 0000 0000
this->mProtection = (fixFrameHeard & 0x10000) >> 16;
// 4  0000 0000 0000 0000 1111 0000 0000 0000
this->mBps = (fixFrameHeard & 0xF000) >> 12;
// 2  0000 0000 0000 0000 0000 2200 0000 0000
this->mSamplingIndex = (fixFrameHeard & 0xC00) >> 10;

// 1  0000 0000 0000 0000 0000 0010 0000 0000
this->mPadding = (fixFrameHeard & 0x200) >> 9;
// 1  0000 0000 0000 0000 0000 0001 0000 0000
this->mPrivate = (fixFrameHeard & 0x100) >> 8;
// 2  0000 0000 0000 0000 0000 0000 1100 0000
this->mChannelMode = (fixFrameHeard & 0xC0) >> 6;
// 2  0000 0000 0000 0000 0000 0000 0011 0000
this->mModeExtension = (fixFrameHeard & 0x30) >> 4;
// 1  0000 0000 0000 0000 0000 0000 00000 1000
this->mCopyright = (fixFrameHeard & 0x8) >> 3;
// 1  0000 0000 0000 0000 0000 0000 0000 0100
this->mOriginal = (fixFrameHeard & 0x4) >> 2;
// 2  0000 0000 0000 0000 0000 0000 0000 0011
this->mEmphasis = (fixFrameHeard & 0x3);

//=============一些修正=================================================
switch(this->mMPEGVersion){
case 0: this->mMPEGVersion = 3; break;
case 2: this->mMPEGVersion = 2; break;
case 3: this->mMPEGVersion = 0; break;
}

switch(this->mLayerIndex){
    case 1: this->mLayerIndex = 3; break;
    case 2: this->mLayerIndex = 2; break;
    case 3: this->mLayerIndex = 1; break;
    };
if(this->mPadding){
        this->mPadding = ( this->mLayerIndex == 1 ? 4 : 1 );
    }

return true;
}

short int FrameInfo::getBitrate(){
int index_I = this->mMPEGVersion == 0 ? 0 : 1;
int index_II = this->mLayerIndex - 1;



return BitrateTable[index_I][index_II][this->mBps];
}

int FrameInfo::getSamplingRate(){

return SamplingRateTable[this->mSamplingIndex][this->mMPEGVersion];
} 

int FrameInfo::getFrameSize(){

return ((this->mMPEGVersion == 0 ? 144 : 77) * (getBitrate()*1000) / getSamplingRate()) + this->mPadding;
}

int FrameInfo::getSamplingSize(){
int index = 0;
switch(this->mMPEGVersion){
case 0: // MPEG 1
index = 0;
case 2: // MPEG 2
index = 1;
case 3: // MPEG 3
index = 2;
}

return SamplingSizeTable[this->mLayerIndex - 1][index];
}

int FrameInfo::getEdgeSize(){
switch(this->mMPEGVersion){
case 0: // MPEG 1
if(mChannelMode == 1) return 32; else return 17;
case 2: // MPEG 2
if(mChannelMode == 1) return 17; else return 9;
case 3: // MPEG 3
if(mChannelMode == 1) return 17; else return 9;
}
return 0;
}

#include "MP3File.h"
#include "FrameInfo.h"

int MP3File::getFrameOffset(){

return getFrameSize() + 0;
}

int MP3File::getFrameSize(){
return (int)(mID3V2Header.Size[0]&0x7F)*0x200000 +
(mID3V2Header.Size[1]&0x7F)*0x400 + 
(mID3V2Header.Size[2]&0x7F)*0x80 + 
(mID3V2Header.Size[3]&0x7F) + 10; 
}

bool MP3File::initID3V2Header(){

memcpy(&mID3V2Header, m_pDataBuffer, sizeof(ID3V2_HEADER));
char headr[4];
memcpy(headr, mID3V2Header.Header, 3);
headr[3] = '\000';

return strcmp(headr, "ID3") == 0;
}

unsigned int fixData(int data){
unsigned int res = 0;
res |= (data & 0x000000ff) << 24;
res |= (data >> 8 & 0x000000ff) << 16; 
res |= (data >> 16 & 0x000000ff) << 8; 
res |= (data >> 24 & 0x000000ff); 
return res;
}


#include "cocos2d.h"
bool MP3File::initFirstFrame(){
int framePos = getFrameOffset();

int frameHeard;
memcpy(&frameHeard, m_pDataBuffer + framePos, 4);
FrameInfo* frameInfo = new FrameInfo();
frameInfo->init(fixData(frameHeard));
int size = frameInfo->getFrameSize();

int i = frameInfo->mMPEGVersion;

// 得到XING头
framePos += frameInfo->getEdgeSize() + 4;
XINGInfo xing;
memset(&xing, 0, sizeof(XINGInfo));
memcpy(&xing, m_pDataBuffer + framePos, sizeof(XINGInfo));
xing.Flags = fixData(xing.Flags);
xing.FramesNumber = fixData(xing.FramesNumber);
xing.BytesNumber = fixData(xing.BytesNumber);
xing.Quality = fixData(xing.Quality);


// 开始遍历帧
framePos = getFrameOffset();
for(int i = 0 ; i < xing.FramesNumber ; i++){

memcpy(&frameHeard, m_pDataBuffer + framePos, 4);
frameInfo->init(fixData(frameHeard));

size = frameInfo->getFrameSize();

unsigned char* data_pos = m_pDataBuffer + framePos;

unsigned char* frameData = new unsigned char[size];
memcpy(frameData, data_pos, size);
for(int i = 0 ; i < size ; i++){
//cocos2d::CCLog("%i", frameData[i]);
}

framePos += size;
}

return true;
}

bool MP3File::initFile(const char* pszFilepath){
// 载入数据
m_pDataBuffer = cocos2d::CCFileUtils::sharedFileUtils()->getFileData(pszFilepath, "rb", &m_lDataLength);

// 初始化头
m_bHaveID3V2 = initID3V2Header();

// 如果是标准IDV3
if(m_bHaveID3V2){
// 初始化第一帧
initFirstFrame();

}
return true;
}

MP3File* MP3File::parse(const char* pszFilepath){
MP3File* mp3File = new MP3File();

if(mp3File->initFile(pszFilepath)){
return mp3File;
}

delete mp3File;

return mp3File;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值