版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
猎取MP3信息C++源代码C++语言mp3ID3V2mp3信息ID3V1信息。mp3信息,没有别的功能。//1. MP3Info.h//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Copyright (C) 2023, Roman Nurik////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#ifndef#define
MP3INFO_H_ MP3INFO_H_//#include #include<VECTOR>////////////////////////////////////////////////////////////////////////////ID3V2.3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////在文件的首部挨次记录10个字节的ID3V2.3的头部。数据构造如下:/*1〕.标志字节abc00000这个单词不知道是什么意思,字典里也没有找到,一般不设置)bWinamp设置c(99.99%〔2〕.标签大小0。所以格式如下0xxxxxxx0xxxxxxx0xxxxxxx0xxxxxxx28位的二进制数,就是标签大小(不懂为什么要这样做),计算公式如下:inttotal_size;total_size=(Size&0x7F)*0x202300+(Size&0x7F)*0x4000+(Size&0x7F)*0x80+(Size&0x7F)*/typedefstructtagMP3ID3V2HEADER{header;version;revision;flag;
//“ID3“否则认为标签不存在//ID3V2.33//0
charcharcharcharsize;和全部的标签帧的大小
//存放标志的字节,这个版本只定char//标签大小,不包括标签头的10个字节}MP3ID3V2HEADER,*PMP3ID3V2HEADER;/////////////////////////////////////////////////////////////////////////////*每个标签帧都有一个10成。它们也是挨次存放在文件只有从帧头中的到内容大小后才能读出,读取时要留意大小,不要将其他帧的内容或帧头读入。*//*〔1〕.帧标识TIT2TRCKN/MNNMMNMASCIITCON:“engeng表示备注所使用的自然语言〔2〕.大小8位全用,格式如下xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxintFSize;FSize=Size*0x100000000+Size*0x10000+Size*0x100+Size;标志160就可以了。格式如下:abc00000ijk00000abiBCD码表示数字--加密标志(没有见过哪个MP3文件的标签用了加密)个字节计算在帧内容的大小中。*/typedefstructtagMP3ID3V2FRAME{frameID;size;1flags;说frameContent;
char//char//char//存放标志,只定义了6位,稍后具体解char *//标签帧内容}MP3ID3V2FRAME,*PMP3ID3V2FRAME;#defineMP3ID3V2FRAMEHEADERSIZE10//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////mp3// p p p p//AAAAAAAAAAABBCCDEEEEFFGHIIJJKLMM//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////MP3FRAMEHEADER structure 四个字节//留意:c//p=00000000//p=10010000//p=11111011//p=11111111typedefstruct tagMP3FRAMEHEADER{unsignedemphasis :2;//M强调unsignedoriginal :1;//L原创unsignedcopyright :1;//K版权式unsignedunsignedmodeext :chanmode :2;2;////JI扩展模声道unsignedprivbit:1;//H私有bitunsignedpadding :1;//G填充位引unsignedunsignedsamplerate:bitrate 2;4;////FE采样频率位率索位unsignedunsignedhascrc :mpeglayer :1;2;////DC校验Layerunsignedmpegver:2;//BMPEG音IDunsigned framesync : 11;// A 步}MP3FRAMEHEADER,*PMP3FRAMEHEADER;//////////////////////////////////////////////////////////////////////////// ENMPEGVER enumeration B/*MPEGID00-MPEG2.50110-MPEG2〔ISO/IEC13818-3〕11-MPEG1〔ISO/IEC11172-3〕MPEG2.5202.5不支持该版本的应用程序一般认为该比特位置位为帧同步位,也就是说帧同步的长度为12而不是这里规定的11,〕。推举使用该表的方法由于这样允许你可以区分三个版本以获得最高兼容性。*/enum ENMPEGVER{MPEGVER_25,// 2.5// reserved, N/A
MPEGVER_NA,MPEGVER_2,//2.0(ISO/IEC13818-3)MPEGVER_1//1.0(ISO/IEC11172-3)};//////////////////////////////////////////////////////////////////////////// ENCHANNELMODE enumeration I/*声道立体声联合(混合)立体声〔立体声〕双声道〔立体声〕单声道〔单声〕注:双声道文件由二个独立的单声道组成。每一个声道使用整个文件一半的位率。大多数的解码器把它当作立体声来输出,但是它并不总是这种状况。。*/enum ENCHANNELMODE{MP3CM_STEREO,MP3CM_JOINT_STEREO,MP3CM_DUAL_CHANNEL,MP3CM_SINGLE_CHANNEL};//////////////////////////////////////////////////////////////////////////// ENEMPHASIS enumeration M/*0001-50/15ms1011-CCITJ.17*/enum ENEMPHASIS{MP3EM_NONE,MP3EM_50_15_MS,// 50/15 MP3EM_RESERVED,MP3EM_CCIT_J17 // CCIT J.17};//////////////////////////////////////////////////////////////////////////// matrix of bitrates//mp3layer/*索引值MPEGLayer1IMPEG2,2.5(LSF)LayerIILayerIII0000LayerFreeILayerII&III000132323232800106448404816001196564856240100128645664320101160806480400110192968096480111224112961125610002561281121286410012881601281448010103201921601609610113522241921761121100384256224192128110141632025622414411104483843202561601111 Bad*/static int g_nMP3BitRate = {{0, 32,64,96,128,160,192,224,256,288,320,352,384,416,448,-1},{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,-1},{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1},{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,-1},{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,-1},{0,8,16,24,32,64,80,56,64,128,160,112,128,256,320,-1},};////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MP3ID3V1TAG structure/*流派。另外还有额外的注释空间。位于音频文件的最终固定为128字节。构造如下AAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFG*//*符号 长度(bytes) 位置(bytes) 描述A 3 (0-2) 正确的话,必需包含”TAG”。B30(3-32)标题C30(33-62)艺术家D30(63-92)唱片集E4(93-96)年月F30(97-126)注释G1(127)流派*//*该规格要求全部的空间必需以空字符(ASCII0)填充。但是并不是全部的应用程winamp(ASCII32)代替之。号。假设不知道该信息时可以用空字符(ASCII0)代替。*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////MP3ID3V1TAG structuretypedefstruct {char ident; char title; //标题char artist; //艺术家char album; //唱片集char year; //年月char comment;//注释unsignedchar reserved; //保存位unsignedchar tracknum; //音轨unsignedchar genre; //流派}MP3ID3V1TAG,*PMP3ID3V1TAG;//////////////////////////////////////////////////////////////////////////// list of genres 流派使用原码表示 G/*流派。另外还有额外的注释空间。位于音频文件的最终固定为128字节。构造如下AAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFG*/static char* g_arrMP3Genre[] = {//流派使用原码表示,为以下数字之一:0--79“Blues“, Rock“, “Country“, “Disco“,“Metal“,
“Funk“, “Grunge“,“Hip-Hop“, “Jazz“,
“NewAge“, “Oldies“, “Other“,“Pop“, “R&B“,“Rap“, “Reggae“,“Rock“, “Techno“,“Industrial“,“Alternative“, “Ska“,Metal“, “Pranks“, “Soundtrack“,“Euro-Techno“, “Ambient“,
“DeathFunk“,,
“TripHop“, “Vocal“, “Jazz“Fusion“, “Trance“,“Classical“, “Instrumental“, “Acid““House“, “Game“,“SoundClip“, “Gospel“, “Noise“,“Alternative Rock“,“Bass“, “Soul“, “Space“,“Meditative“, Pop“, “InstrumentalRock“,“Ethnic“, “Gothic“,“Darkwave“, “Techno-Industrial“,“Electronic“, “PopFolk“, “Eurodance“,“Dream“, Rock“, “Comedy“, “Gangsta“,“Top40“, “ChristianRap“, “PopFunk“, “Jungle“, “NativeAmerican“,“Cabaret“, Wave“, “Psychadelic“, “ShowTunes“,“Trailer“,“Lo-Fi“,“Tribal“,“AcidPunk“,“AcidJazz“,“Polka“,“Retro“,“Musical“,“Rock&Roll“,“HardRock“,//Winamp:80--125“Folk“, “FolkRock“, “NationalFolk“, “Swing“, “FastFusion“, “Bebob“,“Latin“, “Revival“,“Celtic“, “Bluegrass“,“Avantgarde“, “GothicRock“,“ProgressiveRock“,“PsychedelicRock“,“SymphonicRock“,“SlowRock“, Band“, “Chorus“,Listening“, “Acoustic“, “Speech“, “Chanson“,“Opera“,
“Easy“ChamberMusic“, “Sonata“, “Symphony“,“BootyBass“, “Primus“, Groove“,“Satire“, “SlowJam“, “Club“, “Tango“,“Samba“, “Folklore“,“Ballad“, “PowerBallad“, “RhytmicSoul“, “Freestyle“, “Duet“,“PunkRock“, “DrumSolo“,“ACapella“,“EuroHouse“,“DanceHall“,//其它扩大:126--147“Goa“, “Drum&Bass“, “ClubHouse“, “Hardcore“, “Indie“,“BritPop“, “Negerpunk“,“PolskPunk“, “Beat“, GangstaRap“, “HeavyMetal“,“BlackMetal“, “Crossover“, Christian“, “ChristianRock“, “Merengue“, “Salsa“,“TrashMetal“, “Anime“, “JPop“,“SynthPop“};static constint g_nMP3GenreCount = 148;//流派总数////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bitmask of validity of files#define MP3VLD_INVALID0x0000//#define MP3VLD_ID3V2_VALID0x0001#define MP3VLD_DATA_VALID0x0002#define MP3VLD_ID3V1_VALID0x0004////////////////////////////////////////////////////////////////////////////CMP3Info class//mp3usingstd::string;class CMP3Info{private:
//ID3V2
MP3ID3V2HEADERm_ID3V2Header;m_bHasID3V2;
//ID3V2
//ID3V2
boolm_nID3V2Size;签帧的大小m_bTestID3V2m_nID3V2FrameNum;
unsigned int//10个字节,包含全部的标bool//是否是测试标签unsigned int//标签帧的数目//ID3V1m_ID3V1Tag;//ID3V1m_bHasID3V1;//ID3V1// string m_strFile;
MP3ID3V1TAGbool//mp3mp3名short
//mp3
unsigned// ID3V1 informationstd::string std::string m_strTitle;std::string m_strAlbum;std::string m_strComment;std::string m_strYear;
//艺术家//标题//唱片集//注释int m_nTrack;int m_nGenre;
//年月//音轨//流派索引// MP3 frame informationint m_nFrames;//mp3int m_nMp3Time;//mp3inseconds
unsignedunsignedENMPEGVER int m_nMPEGLayer;bool m_bHasCRC;
//MPEG音频版本//Layer跟帧头后有16位即2个字节用作CRC校验1-没有校验int m_nBitRate;率 average if VBR, 0 if int m_nSampleRate;
//比特ENCHANNELMODE m_enChannelMode;//声道
//采样率ENEMPHASIS bool m_bCopyrighted;bool m_bOriginal;
//强调//版权//原创public:数
CMP3Info;virtual ~CMP3Info;
//默认构造函//析构函数// operations// bool WriteID3V1(string strDestFile = ““, bool bClear = FALSE); // defaults tocurrent filevoidclear;// voidread(std::ifstream&ifs);//mp3信息//boolreadID3V2(std::ifstream&ifs);//读取mp3头:ID3V2const;
//ID3V2
bool isID3V2Available//ID3V2const;
bool isTestID3V2//ID3V2unsigned int getID3V2Sizeconst; //获ID3V2//ID3V2bool readID3V2(std::ifstream&ifs); //读取ID3V2void formatDisplayID3V2(std::ostream& const; //格式化输出ID3V2标签//ID3V1bool readID3V1(std::ifstream&ifs); //读取ID3V1void formatDisplayID3V1(std::ostream& const; //格式化输出ID3V1标签//mp3void readMp3FrameHeader(std::ifstream&ifs); //mp3// void write(std::ostream&os);private://ID3V2bool readID3V2Header(std::ifstream&ifs) //读取ID3V2void formatDisplayID3V2Header(std::ostream&os)const; //ID3V2//ID3V2bool readID3V2Frame(std::ifstream&ifs); //读取ID3v2帧头void formatDisplayID3V2Frame(std::ostream& const; //ID3V2//mp3boolCMP3Info::getNextFrameHeader(std::ifstream&ifs,MP3FRAMEHEADER*pHeader,intnPassBytes); //mp3public:/*voidSetArtist(stringstrArtist){m_strArtist=strArtist;}//设置艺术家voidSetTitle(stringstrTitle){m_strTitle=strTitle;} //设置标题voidSetAlbum(stringstrAlbum){m_strAlbum=strAlbum;} //设置唱片集voidSetComment(stringstrComment){m_strComment = strComment; } //设置注释void SetYear(string strYear){ m_strYear strYear; } //设置年月void SetTrack(int nTrack){ m_nTrack nTrack; } //设置音轨void SetGenreIndex(int nGenre){ m_nGenre= nGenre; } //设置流派索引*/// attributes// string GetFileName const { m_strFile; } //mp3名unsignedshort getValidity const { return }//获得有效性string getArtist const { return trArtist; } //获得艺术家string getTitle const { return m_strTitle; } //获得标题string getAlbum const { return rAlbum; } //获得唱片集string getComment const { return strComment; } //获得注释string getYear const { return Year; } //获得年月int getTrack const { return k; } //获得音轨int getGenreIndex const { return nGenre; } //获得流派索引unsignedint getNumFrames const { return m_nFrames;} //获得帧数unsignedint getLength const { return m_nMp3Time; }//获得播放时间ENMPEGVER getMPEGVersion const { m_enMPEGVersion;}//MPEG音频版本int getMPEGLayer const { return MPEGLayer; } //Layerbool hasCRC const { return C; } //是否有校验int getBitRate const { return tRate; } //获得比特率int getSampleRate const { return nSampleRate; } //获得采样率ENCHANNELMODE getChannelMode const {returnm_enChannelMode;}//获得声道ENEMPHASIS getEmphasis const { m_enEmphasis; } //获得强调bool isCopyrighted const { return m_bCopyrighted; } //是否有版权bool isOriginal const { return riginal; } //是否为原创string getGenreString(int nIndex)const; //获得流派信息string getLengthString(int nSeconds)const; //显示播放时间private:/*// helper functionsbool GetNextFrameHeader(HANDLE hFile,MP3FRAMEHEADER*pHeader, int nPassBytes = 0);void ChangeEndian(void* pBuffer, int nBufSize);// convert frombig-endian tolittle-endian*/char*getBinary(intch,char*binary,size_tsize)const;voidchangeEndian(void* pBuffer, intnBufSize)const; // convert from big-endian o little-endianprivate:};#endif
std::vector<MP3ID3V2FRAME>m_ID3V2Frames;//////////////////////////////////////////////////////////////////////*2. MP3Info.cpp 第一局部*/#include<STDLIB.H>#include<IOSTREAM>#include<FSTREAM>#include<IOMANIP>#include<VECTOR>#include<STRING>#include<VLD.H>//内存泄露检验#include “MP3Info.h“//#defineINVALID_SET_FILE_POINTER0xFFFFFFFFusingnamespacestd;////////////////////////////////////////////////////////////////////////////CMP3Info::CMP3Info{clear;}////////////////////////////////////////////////////////////////////////////CMP3Info::~CMP3Info{for(inti=0;i<m_ID3V2Frames.size;i++){delete[]m_ID3V2Frames.frameContent;}}//void Read(std::ifstream&ifs);信息//mp3信息//bool ReadID3V2(std::ifstream&ifs); //读取mp3头:ID3V2//////////////////////////////////////////////////////////////////////////voidCMP3Info::clear{//m_strFile = ““;//m_dwValidity= MP3VLD_INVALID;//无效
//文件名m_strArtist = ““;m_strTitle = ““;
//艺术家m_strAlbum = ““;m_strComment = ““;m_strYear = ““;m_nTrack = 0;
//标题////注释
//年月m_nGenre =
//音轨//流派索引m_nFrames = 0;m_nMp3Time = 0;
//mp3//播放时间m_enMPEGVersion = MPEGVER_NA;//MPEGm_nMPEGLayer = 0;m_bHasCRC = m_nBitRate = 0;m_nSampleRate = 0;
//layer保存//无校验//比特率//采样率m_enChannelMode = MP3CM_STEREO;//立体声m_enEmphasis = MP3EM_NONE;//无m_bCopyrighted = false;//版权m_bOriginal = //m_bHasID3V2=false;m_bTestID3V2=false;m_nID3V2Size=0;}
//原创////////////////////////////////////////////////////////////////////////////ID3v2//boolCMP3Info::readID3V2Header(ifstream&ifs){ifs.seekg(ios::beg);ifs.read(reinterpret_cast<CHAR*>(&m_ID3V2Header),sizeof(MP3ID3V2HEADER));/*if (((m_ID3V2Header.header==”I”) (m_ID3V2Header.header==”i”))&&((m_ID3V2Header.header==”D”) (m_ID3V2Header.header==”d”))&&(m_ID3V2Header.header==”3”))*/if((m_ID3V2Header.header==”I”)&&(m_ID3V2Header.header==”D”)&&(m_ID3V2Header.header==”3”)){m_bHasID3V2=true;m_dwValidity|=MP3VLD_ID3V2_VALID;if((m_ID3V2Header.flag&0x20)==0x20) //是否为测试标签m_bTestID3V2=true;elsem_bTestID3V2=false;m_nID3V2Size=(m_ID3V2Header.size&0x7F)*0x202300 括所有的标签帧的大小+(m_ID3V2Header.size&0x7F)*0x400+(m_ID3V2Header.size&0x7F)*0x80+(m_ID3V2Header.size&0x7F);}else{m_bHasID3V2=false;}returnm_bHasID3V2;}////////////////////////////////////////////////////////////////////////////推断ID3V2boolCMP3Info::isID3V2Availableconst{returnm_bHasID3V2;}////////////////////////////////////////////////////////////////////////////推断是否为测试ID3V2boolCMP3Info::isTestID3V2const{returnm_bTestID3V2;}////////////////////////////////////////////////////////////////////////////获得ID3V2标签的大小,如果标签头不存在返回0unsignedintCMP3Info::getID3V2Sizeconst{if(m_bHasID3V2)returnm_nID3V2Size;else}
return0;////////////////////////////////////////////////////////////////////////////ID3V2voidCMP3Info::formatDisplayID3V2Header(ostream&os)const{tempBinary;
if(m_bHasID3V2){
char//存放一个字节的二进制编码<<endlos<<“t“<<setw(10)<<“标签:“ <<m_ID3V2Header.header<<m_ID3V2Header.header<<m_ID3V2Header.header<<endl;os<<“t“<<setw(10)<<“版 本 号 :“<<static_cast<INT>(m_ID3V2Header.version)<<endl;os<<“t“<<setw(10)<<“副版本号:“ static_cast<INT>(m_ID3V2Header.revision)<<endl;os<<“t“<<setw(10)<<“getBinary(m_ID3V2Header.flag,tempBinary,8)<<endl;os<<“t“<<setw(10)<<“<<m_nID3V2Size<<endl;os<<endl;}else{}}
<<endl;os<<endl;////////////////////////////////////////////////////////////////////////////ID3v2boolCMP3Info::readID3V2Frame(ifstream&ifs){if(m_bHasID3V2){ifs.seekg(sizeof(MP3ID3V2HEADER),ios::beg); //定位到标签帧MP3ID3V2FRAMEframe;unsignedintnID3V2FrameSize;inti;for(i=0;((unsignedint)ifs.tellg+MP3ID3V2FRAMEHEADERSIZE)<m_nID3V2Size;i++){ifs.read(reinterpret_cast<CHAR*>(&frame),MP3ID3V2FRAMEHEADERSIZE);&&&&1int)(frame.size*0x100000000
//帧标识if(frame.frameID==””&&frame.frameID==””frame.frameID==””frame.frameID==””)break;//帧内容的大小,不包括帧头,不得nID3V2FrameSize=(unsigned+frame.size*0x10000+frame.size*0x100+frame.size);m_ID3V2Frames.push_back(frame);char;nt,nID3V2FrameSize);
//读取帧的内容m_ID3V2Frames.frameContentnewifs.read(m_ID3V2Frames.frameConte}}else{
m_nID3V2FrameNum=i;returntrue;cout<<<<endl;cout<<endl;returnfalse;}}////////////////////////////////////////////////////////////////////////////格式化显示ID3V2void CMP3Info::formatDisplayID3V2Frame(ostream& const{if(m_bHasID3V2){i++)
os<<“标签帧“<<endl;for(inti=0;i<m_ID3V2Frames.size;{os<<m_ID3V2Frames.frameID<<m_ID3V2Frames.frameID<<m_ID3V2Frames.frameID<<m_ID3V2Frames.frameID<<“=“;unsignedintnID3V2FrameSize=(unsignedint)(m_ID3V2Frames.size*0x100000000+m_ID3V2Frames.size*0x10000+m_ID3V2Frames.size*0x100+m_ID3V2Frames.size);nID3V2FrameSize;j++)m_ID3V2Frames.frameContent;
for(intj=0;j<os<<os<<endl;}os<<endl;}else{os<<“标签头不存在“<<endl;os<<endl;}}////////////////////////////////////////////////////////////////////////////ID3V2boolCMP3Info::readID3V2(std::ifstream&ifs){readID3V2Header(ifs);returnreadID3V2Frame(ifs);}////////////////////////////////////////////////////////////////////////////ID3V2voidCMP3Info::formatDisplayID3V2(std::ostream&os)const{formatDisplayID3V2Header(os);formatDisplayID3V2Frame(os);}////////////////////////////////////////////////////////////////////////////ID3V1bool ifs){ifs.seekg(-sizeof(MP3ID3V1TAG),ios::end);ifs.read(reinterpret_cast<CHAR*>(&m_ID3V1Tag),sizeof(MP3ID3V1TAG));==0)
if(ifs.good&&memcmp(m_ID3V1Tag.ident,“TAG“,3){char strTemp;strTemp=””;memcpy(strTemp,m_ID3V1Tag.title,30); m_strTitle = strTemp;memcpy(strTemp,m_ID3V1Tag.artist,30); trArtist = strTemp;memcpy(strTemp,m_ID3V1Tag.album,30); m_strAlbum = strTemp;ear = strTemp;
strTemp = 0;memcpy(strTemp,m_ID3V1Tag.year,4); //now, depending on the reserved byte,//the comment
is 28 bytes or 30 if (m_ID3V1Tag.reserved){m_ID3V1Tag.albumtracknumincluded in,30);
// NOTE: even is of size 28,// the reserved and// are right after,// so they”ll the comment, which is what// we wantmemcpy(strTemp,m_ID3V1Tagmentm_strComment = strTemp;,28);cknum;
}else{}
memcpy(strTemp,m_ID3V1Tagmentm_strComment = strTemp;m_nTrack = m_nGenre = m_ID3V1Tag.genre;m_bHasID3V1=true;m_dwValidity |= MP3VLD_ID3V1_VALID;returntrue;}else{}}
<<endlm_bHasID3V1=false;returnfalse;////////////////////////////////////////////////////////////////////////////ID3V1voidCMP3Info::formatDisplayID3V1(ostream&os)const{if(m_bHasID3V1){os<<“ID3V1<<endl;<<“标题:“ <<m_strTitle <<endl;os<<setw(10)<<“艺术家:“ <<m_strArtist <<endl;os<<setw(10)<<“唱片集:“ <<m_strAlbum <<endl;<<“年代:“ <<m_strYear <<endl;if(m_ID3V1Tag.reserved){os<<setw(10)<<“注释:“ <<m_strComment<<endl;}else{os<<setw(10)<<“注释:“ <<m_strComment<<endl;os<<setw(10)<<“音轨:“ <<m_nTrack <<endl;}<<“流派:“ <<g_arrMP3Genre <<endl;}else{os<<“ID3V1标签不存在“ <<endl;}}//////////////////////////////////////////////////////////////////////////// mp3boolCMP3Info::getNextFrameHeader(ifstream&ifs,MP3FRAMEHEADER*pHeader,intnFrameContentSize){if (nFrameContentSize > 0)ifs.seekg(nFrameContentSize,ios::cur);int n = 0;while (1){//tempBinary;
char//mp3ifs.read(reinterpret_cast<CHAR*>(pHeader),sizeof(*pHeader)); //4////////////////////// cout<<“文件指针的位置“<<ifs.tellg<<endl;////////////////////if(ifs.fail){returnfalse;}unsignedchar*p=reinterpret_cast<UNSIGNEDchar*>(pHeader);//显示mp/*cout<<hex;cout<<(int)p<<“=“<<getBinary(p,tempBinary,8)<<endl;cout<<(int)p<<“=“<<getBinary(p,tempBinary,8)<<endl;cout<<(int)p<<“=“<<getBinary(p,tempBinary,8)<<endl;cout<<(int)p<<“=“<<getBinary(p,tempBinary,8)<<endl;cout<<dec;*/changeEndian(pHeader,4);from big-endian to little-endian
// convert//cout<<getBinary(p,tempBinary,8)<<endl;//cout<<getBinary(p,tempBinary,8)<<endl;//cout<<getBinary(p,tempBinary,8)<<endl;//cout<<getBinary(p,tempBinary,8)<<endl;////cout<<endl;//cout << getBinary(pHeader->emphasis,tempBinary,2)<<endl;//cout << getBinary(pHeader->original,tempBinary,1)<<endl;//cout << getBinary(pHeader->copyright,tempBinary,1)<<endl;//cout << getBinary(pHeader->modeext,tempBinary,2)<<endl;//cout << getBinary(pHeader->chanmode,tempBinary,2)<<endl;//cout << getBinary(pHeader->privbit,tempBinary,1)<<endl;//cout << getBinary(pHeader->padding,tempBinary,1)<<endl;//cout << getBinary(pHeader->samplerate,tempBinary,2)<<endl;//cout << getBinary(pHeader->bitrate,tempBinary,4)<<endl;//cout<<getBinary(pHeader->hascrc,tempBinary,1)<<endl;//cout<<getBinary(pHeader->mpeglayer,tempBinary,2)<<endl;//cout <<getBinary(pHeader->mpegver,tempBinary,2)<<endl;//cout <<getBinary(pHeader->framesync,tempBinary,11)<<endl;// cout<<endl<<endl;// cout <<getBinary(pHeader->framesync,tempBinary,11)<<endl;// cout<<hex<<pHeader->framesync<<endl;// cout<<dec;// only search in 10kbif (pHeader->framesync == F || ++n > 10000)else
returntrue;returnfalse;// SetFilePointer(hFile,-3,NULL,FILE_CURRENT);}}////////////////////////////////////////////////////////////////////////////mp3voidCMP3Info::readMp3FrameHeader(ifstream&ifs){ios::beg);
if(m_bHasID3V2)ifs.seekg(sizeof(MP3ID3V2HEADER)+m_nID3V2Size,elseifs.seekg(ios::beg);MP3FRAMEHEADER int nFrameBitRate;
//mp3unsigned long nTotalBitRate =0; //total frames bit rate (used to calc. age)nFrameConentSizeInBytes = 0;//帧长度(比特)
unsigned longdouble frameTime = 0;// totalength of file// DWORD dwNumBytesRead;// read frame by framewhile(getNextFrameHeader(ifs, nFrameConentSizeInBytes)){//===============================================================mp3帧中保持不变
//MPEGversionlayerif (m_nFrames < 1){MPEG version= MPEGVER_25; break;= MPEGVER_NA; break;= MPEGVER_2; break;= MPEGVER_1; break;MPEG layer description)
// first read theswitch {case 0: m_enMPEGVersioncase 1: m_enMPEGVersioncase 2: m_enMPEGVersioncase 3: m_enMPEGVersion}// next, read theswitch {case 0: m_nMPEGLayer= 0; break;= 3; break;= 2; break;= 1; break;
case 1: m_nMPEGLayercase 2: m_nMPEGLayercase 3: m_nMPEGLayer}or CRC or no ascrc;}
// read the bit m_bHasCRC = //===============================================================//= read the bitrate, based on the layer and versionif (m_nMPEGLayer > 0){MPEGVER_1)yer)
if (m_enMPEGVersion =={switch (m_nMPEGLa{case 1: nFrameBitRate=g_nMP3BitRate;break;eBitRate=g_nMP3BitRate;break;eBitRate=g_nMP3BitRate;break;}else{
case 2: nFramcase 3: nFram}switch (m_nMPEGLayer)eBitRate=g_nMP3BitRate;break;eBitRate=g_nMP3BitRate;break;eBitRate=g_nMP3BitRate;break;}}
{case 1: nFramcase 2: nFramcase 3: nFram}// if nFrameBitRate is 0or -1 then the bitrate is either or badif (nFrameBitRate > 0)nTotalBitRate += nFrameBitRate; //总比特率//===============================================================//=read sample ratee)= 44100;= 48000;= 32023;PEGVER_2)e)= 22050;= 24000;= 16000;PEGVER_25)e)= 11025;
if{break;break;break;}else{break;break;break;}else{break;
(m_enMPEGVersion == MPEGVER_1)switch {case 0: m_nSampleRatecase 1: m_nSampleRatecase 2: m_nSampleRate}if (m_enMPEGVersion == Mswitch (frameHeader.samplerat{case 0: m_nSampleRatecase 1: m_nSampleRatecase 2: m_nSampleRate}if (m_enMPEGVersion == Mswitch (frameHeader.samplerat{case 0: m_nSampleRate= 12023; break;= 8000; break;}
case 1: m_nSampleRatecase 2: m_nSampleRate}if (!m_nSampleRate)break;//===============================================================//=read channel modeswitch {case 0: m_enChannelMode = MP3CM_STEREO; break;case 1: m_enChannelMode = CM_JOINT_STEREO; break;case 2: m_enChannelMode = CM_DUAL_CHANNEL; break;case 3: m_enChannelMode = CM_SINGLE
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年四川阿坝州选调公务员笔试真题
- 2025年广东阜沙镇招聘公办中小学专任教师笔试真题
- 航空基础及推进 2
- 乡村戏曲大赛活动方案策划(3篇)
- 设备监理师《设备监理实务》考前密训题(含解析)
- 打架思想报告(3篇)
- 2026年云南高考(化学)考试真题试卷
- 2026年新疆小升初数学考试真题及答案
- 国家公务员考试时事政治题库参考答案2026年
- 2026年新疆高考(英语)考试试卷(真题)(含答案)
- GA/T 1482-2026机动车驾驶人安全教育内容和方法
- 2026年北京市中考英语试卷真题(含答案及解析)
- 2026 年注塑车间主管上半年述职报告
- 安徽九华山旅游发展股份有限公司招聘笔试真题2025
- 2026年安徽省淮北市辅警考试试题解析及答案
- 【新教材】人教版(2024)八年级下册物理期末检测试卷 3套(含答案)
- 2026上海博物馆公开招聘12名工作人员备考题库及参考答案详解
- 2026年山东定期医师考核题库及答案
- 骨关节炎阶梯治疗专家共识(2026版)
- 小学6年级暑假每日学习打卡表(可直接打印使用)
- 2026年山东聊城市社区工作者考试试题解析及答案
评论
0/150
提交评论