您的位置:首页 > 编程语言

mp3信息解析源代码

2008-05-04 14:57 246 查看

#pragma once




class File




...{


public:


File(void);


public:


~File(void);






BOOL Open(LPCTSTR lpFileName,DWORD dwDesiredAccess/**//*参考CreateFile*/);




DWORD Seek(LONG lDistanceToMove,DWORD dwMoveMethod/**//*参考SetFilePointer*/);


DWORD SeekToBegin( );


DWORD SeekToEnd( );


DWORD GetLength( ) const;


DWORD Read( LPVOID lpBuffer,DWORD nNumberOfBytesToRead);


DWORD Write(LPVOID lpBuffer,DWORD nNumberOfBytesToWrite);


private:


HANDLE m_hFile;


};




#include "StdAfx.h"


#include "File.h"


extern DWORD g_dwLastError;


File::File(void)




...{


m_hFile=INVALID_HANDLE_VALUE;


}




File::~File(void)




...{


if (m_hFile!=INVALID_HANDLE_VALUE)




...{


CloseHandle(m_hFile);


}


}


BOOL File::Open(LPCTSTR lpFileName,DWORD dwDesiredAccess)




...{


m_hFile = CreateFile(lpFileName,dwDesiredAccess,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);


return m_hFile!=INVALID_HANDLE_VALUE ? TRUE:FALSE;


}






DWORD File::Seek(LONG lDistanceToMove,DWORD dwMoveMethod/**//*参考SetFilePointer*/)




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


return SetFilePointer(m_hFile,lDistanceToMove,NULL,dwMoveMethod);


}




DWORD File::SeekToBegin( )




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


return SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);


}


DWORD File::SeekToEnd( )




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


return SetFilePointer(m_hFile,0,NULL,FILE_END);


}




DWORD File::GetLength( ) const




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


return GetFileSize(m_hFile,NULL);


}




DWORD File::Read( LPVOID lpBuffer,DWORD nNumberOfBytesToRead)




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


DWORD dwNumberOfBytesRead;


ReadFile(m_hFile,lpBuffer,nNumberOfBytesToRead,&dwNumberOfBytesRead,NULL);


return dwNumberOfBytesRead;


}




DWORD File::Write(LPVOID lpBuffer,DWORD nNumberOfBytesToWrite)




...{


assert(m_hFile!=INVALID_HANDLE_VALUE);


DWORD dwNumberOfBytesWrite;


WriteFile(m_hFile,lpBuffer,nNumberOfBytesToWrite,&dwNumberOfBytesWrite,NULL);


return dwNumberOfBytesWrite;


}



#ifdef MUSICINFO_EXPORTS
#define MUSICINFO_API __declspec(dllexport)
#else
#define MUSICINFO_API __declspec(dllimport)
#endif
extern DWORD g_dwLastError=0;
typedef struct tagID3V2Head
{
char Header[3]; /*必须为"ID3"否则认为标签不存在*/
char Ver; /*版本号ID3V2.3 就记录3*/
char Revision; /*副版本号此版本记录为0*/
char Flag; /*存放标志的字节,这个版本只定义了三位,稍后详细解说*/
char Size[4]; /*标签大小,包括标签头的10 个字节和所有的标签帧的大小*/
} ID3V2Head,*PID3V2Head;
typedef struct tagID3V2Frame
{
char FrameID[4];
/*
用四个字符标识一个帧,说明一个帧的内容含义,常用的对照如下:
TIT2=标题 表示内容为这首歌的标题,下同
TPE1=作者
TALB=专集
TRCK=音轨 格式:N/M 其中N 为专集中的第N 首,M为专集中共M 首,N和M 为
ASCII 码表示的数字
TYER=年代 是用ASCII 码表示的数字
TCON=类型 直接用字符串表示
COMM=备注 格式:"eng/0备注内容",其中eng 表示备注所使用的自然语言
*/
char Size[4]; /*帧内容的大小,不包括帧头,不得小于1*/
char Flags[2];
/*只定义了6 位,另外的10 位为0,但大部分的情况下16 位都为0 就可以了。
格式如下:
abc00000 ijk00000
a -- 标签保护标志,设置时认为此帧作废
b -- 文件保护标志,设置时认为此帧作废
c -- 只读标志,设置时认为此帧不能修改(但我没有找到一个软件理会这个标志)
i -- 压缩标志,设置时一个字节存放两个BCD 码表示数字
j -- 加密标志(没有见过哪个MP3 文件的标签用了加密)
k -- 组标志,设置时说明此帧和其他的某帧是一组
*/
char data[100];
} ID3V2Frame,*PID3V2Frame;
typedef struct tagID3V1
{
char Header[3]; /*标签头必须是"TAG"否则认为没有标签*/
char Title[30]; /*标题*/
char Artist[30]; /*作者*/
char Album[30]; /*专集*/
char Year[4]; /*出品年代*/
char Comment[28]; /*备注*/
char reserve; /*保留*/
char track;; /*音轨*/
char Genre; /*类型*/
}ID3V1,*PID3V1;

typedef struct tagFrameHeader
{
unsigned char sync1:8; //同步信息1 0xFF
unsigned char crc:1; //CRC校验 0x01/0x00
unsigned char layer:2; //层 0x01
unsigned char version:2; //版本 0x03
unsigned char sync2:3; //同步信息2 0x07
unsigned char privatebit:1; //私有bit,可以用来做特殊应用 0x00
unsigned char padding:1; //填充空白字 0x00/0x01
unsigned char sample_rate_index:2; //采样率索引 0x00
unsigned char bit_rate_index:4; //位率索引 0x0A
unsigned char emphasis:2; //强调方式 0x00
unsigned char original:1; //原始媒体 0x01
unsigned char copyright:1; //版权标志 0x00
unsigned char mode_extension:2; //扩展模式,仅用于联合立体声 0x00
unsigned char channel_mode:2; //声道模式 0x00
}FHEADER, *PFHEADER;

MUSICINFO_API int miGetMp3ID3V1Info(LPTSTR pFileName,PID3V1 pData);
MUSICINFO_API int miGetMp3ID3V2Head(LPTSTR pFileName,PID3V2Head ptagHead);
MUSICINFO_API int miGetMp3ID3V2Size(LPTSTR pFileName);//包括标签头大小
MUSICINFO_API int miEnumMp3ID3V2TagFrame(LPTSTR pFileName,PID3V2Frame pTagFrame);
MUSICINFO_API int miGetMp3FirstFrameHeadInfo(LPTSTR pFileName,PFHEADER pFrameHead);//不用
MUSICINFO_API int miEnumMp3FrameHeadInfo(LPTSTR pFileName,PFHEADER pTagFrame);
MUSICINFO_API int miGetMp3FrameSize(PFHEADER pTagFrame);

MUSICINFO_API double miGetMp3Duration(LPTSTR pFileName);




#include "stdafx.h"
#include "MusicInfo.h"
#include "File.h"
#include <malloc.h>
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
MUSICINFO_API int miGetMp3ID3V1Info(LPTSTR pFileName,PID3V1 pData)
{
assert(pData&&sizeof(ID3V1)==128);
File file;
if(file.Open(pFileName,FILE_READ_DATA))
{
file.Seek(-128,FILE_END);
file.Read((LPVOID)pData,128);
}
return 0;
}
MUSICINFO_API int miGetMp3ID3V2Head(LPTSTR pFileName,PID3V2Head ptagHead)
{
assert(ptagHead);
File file;
if(file.Open(pFileName,FILE_READ_DATA))
{
file.SeekToBegin();
file.Read((LPVOID)ptagHead,sizeof(ID3V2Head));
}
return 0;
}
MUSICINFO_API int miGetMp3ID3V2Size(LPTSTR pFileName)
{
ID3V2Head tagHead;
miGetMp3ID3V2Head(pFileName,&tagHead);
if (memcmp(tagHead.Header,"ID3",3)!=0)
{
return 0;
}
return sizeof(ID3V2Head)+(tagHead.Size[0]&0x7F)*0x200000 +(tagHead.Size[1]&0x7F)*0x400+(tagHead.Size[2]&0x7F)*0x80+(tagHead.Size[3]&0x7F) ;
}
MUSICINFO_API int miEnumMp3ID3V2TagFrame(LPTSTR pFileName,PID3V2Frame pTagFrame)
{
const int TAG_HEAD_SIZE = 10;
static int sizecount = 0;
ID3V2Head head;
File file;
if(file.Open(pFileName,FILE_READ_DATA))
{
file.SeekToBegin();
file.Read((LPVOID)&head,sizeof(ID3V2Head));
/*必须为"ID3"否则认为标签不存在*/
if (memcmp(head.Header,"ID3",3)!=0)
{
return 0;
}
int tagsize = (head.Size[0]&0x7F)*0x200000 +(head.Size[1]&0x7F)*0x400+(head.Size[2]&0x7F)*0x80 +(head.Size[3]&0x7F) ;
if (sizecount>=tagsize)
{
sizecount = 0;
return 0;
}
file.Seek(sizecount+sizeof(ID3V2Head),FILE_BEGIN);
ID3V2Frame frame;
file.Read((LPVOID)&frame,sizeof(ID3V2Frame));
int FSize = frame.Size[0]*0x100000000+frame.Size[1]*0x10000+frame.Size[2]*0x100+frame.Size[3];
if (FSize==0)
{
sizecount = 0;
return 0;
}
file.Seek(sizecount+sizeof(ID3V2Head),FILE_BEGIN);
file.Read((LPVOID)pTagFrame,TAG_HEAD_SIZE+FSize);
sizecount+=TAG_HEAD_SIZE+FSize;
return 1;
}
return 0;
}
MUSICINFO_API int miGetMp3FirstFrameHeadInfo(LPTSTR pFileName,PFHEADER pFrameHead)
{
int tagSize = miGetMp3ID3V2Size(pFileName);
File file;
if(file.Open(pFileName,FILE_READ_DATA))
{
file.Seek(tagSize,FILE_BEGIN);
file.Read(pFrameHead,sizeof(FHEADER));
return 1;
}
return 0;
}
MUSICINFO_API int miEnumMp3FrameHeadInfo(LPTSTR pFileName,PFHEADER pFrameHead)
{
static int nSeekTo = 0;
int tagSize = miGetMp3ID3V2Size(pFileName);

File file;
if(file.Open(pFileName,FILE_READ_DATA))
{
if (tagSize+nSeekTo+128 >=file.GetLength())
{
nSeekTo = 0;
return 0;
}
file.Seek(tagSize+nSeekTo,FILE_BEGIN);
file.Read(pFrameHead,sizeof(FHEADER));
// int tmp = tagSize+nSeekTo;
// while (pFrameHead->sync1!=0xFF || pFrameHead->sync2!=0x07 )
// {
// tmp++;
// file.Seek(tmp,FILE_BEGIN);
// file.Read(pFrameHead,sizeof(FHEADER));
// }
int fsize = miGetMp3FrameSize(pFrameHead);
if (fsize==0)
{
nSeekTo = 0;
return 0;
}
nSeekTo += fsize;
return 1;
}
return 0;
}
//帧长度(字节)= (( 每帧采样数(1152) / 8 * 比特率 ) / 采样频率 ) + 填充
MUSICINFO_API int miGetMp3FrameSize(PFHEADER pFrameHead)
{

int samplenum = 0;
int bitrate=0;
int samplerate=0;
// MPEG 1 MPEG 2 MPEG 2.5
// Layer I 384 384 384
// Layer II 1152 1152 1152
// Layer III 1152 576 576

switch(pFrameHead->layer)
{
case 0x01://Layer III
switch(pFrameHead->version)
{
case 0x00://MPEG 2.5
samplenum = 576;
break;
case 0x02://MPEG 2
samplenum = 576;
break;
case 0x03://MPEG 1
samplenum = 1152;
break;
}
break;
case 0x02://Layer II
switch(pFrameHead->version)
{
case 0x00://MPEG 2.5
samplenum = 1152;
break;
case 0x02://MPEG 2
samplenum = 1152;
break;
case 0x03://MPEG 1
samplenum = 1152;
break;
}
break;
case 0x03://Layer I
switch(pFrameHead->version)
{
case 0x00://MPEG 2.5
samplenum = 384;
break;
case 0x02://MPEG 2
samplenum = 384;
break;
case 0x03://MPEG 1
samplenum = 384;
break;
}
break;
default:
return 0;
}
switch(pFrameHead->bit_rate_index)
{
case 0x01:
bitrate = 32;
break;
case 0x02:
bitrate = 40;
break;
case 0x03:
bitrate = 48;
break;
case 0x04:
bitrate = 56;
break;
case 0x05:
bitrate = 64;
break;
case 0x06:
bitrate = 80;
break;
case 0x07:
bitrate = 96;
break;
case 0x08:
bitrate = 112;//注意:测试多首音乐发现它设置的实际值是128而不是112
break;
case 0x09:
bitrate = 128;
break;
case 0x0a:
bitrate = 160;
break;
case 0x0b:
bitrate = 192;
break;
case 0x0c:
bitrate = 224;
break;
case 0x0d:
bitrate = 256;
break;
case 0x0e:
bitrate = 320;
break;
default:
return 0;
}
switch(pFrameHead->sample_rate_index)
{
case 0x00:
switch(pFrameHead->version)
{
case 0x00:
samplerate = 11025;
break;
case 0x02:
samplerate = 22050;
break;
case 0x03:
samplerate = 44100;
break;
}
break;
case 0x01:
switch(pFrameHead->version)
{
case 0x00:
samplerate = 12000;
break;
case 0x02:
samplerate = 24000;
break;
case 0x03:
samplerate = 48000;
break;
}
break;
case 0x02:
switch(pFrameHead->version)
{
case 0x00:
samplerate = 8000;
break;
case 0x02:
samplerate = 16000;
break;
case 0x03:
samplerate = 32000;
break;
}
break;
default:
return 0;
}
assert(samplenum!=0&&samplerate!=0&&bitrate!=0);
return (( samplenum/8*bitrate*1000 )/samplerate ) + (pFrameHead->padding?1:0);
}
MUSICINFO_API double miGetMp3Duration(LPTSTR pFileName)
{
FHEADER fh;
int framenum = 0;
double spf = 0.0f;
while(miEnumMp3FrameHeadInfo(pFileName,&fh))
{
if (framenum==0)
{
int samplenum = 0;
int samplerate=0;

switch(fh.layer)
{
case 1://Layer III
switch(fh.version)
{
case 0://MPEG 2.5
samplenum = 576;
break;
case 2://MPEG 2
samplenum = 576;
break;
case 3://MPEG 1
samplenum = 1152;
break;
}
break;
case 2://Layer II
switch(fh.version)
{
case 0://MPEG 2.5
samplenum = 1152;
break;
case 2://MPEG 2
samplenum = 1152;
break;
case 3://MPEG 1
samplenum = 1152;
break;
}
break;
case 3://Layer I
switch(fh.version)
{
case 0://MPEG 2.5
samplenum = 384;
break;
case 2://MPEG 2
samplenum = 384;
break;
case 3://MPEG 1
samplenum = 384;
break;
}
break;
}

switch(fh.sample_rate_index)
{
case 0x00:
switch(fh.version)
{
case 0x00:
samplerate = 11025;
break;
case 0x02:
samplerate = 22050;
break;
case 0x03:
samplerate = 44100;
break;
}
break;
case 0x01:
switch(fh.version)
{
case 0x00:
samplerate = 12000;
break;
case 0x02:
samplerate = 24000;
break;
case 0x03:
samplerate = 48000;
break;
}
break;
case 0x02:
switch(fh.version)
{
case 0x00:
samplerate = 8000;
break;
case 0x02:
samplerate = 16000;
break;
case 0x03:
samplerate = 32000;
break;
}
break;
}
assert(samplenum&&samplerate);
spf = (double)samplenum/(double)samplerate;
}
framenum++;

}
return spf*(double)framenum;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: