目前解析了 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;
}