#ifdef __cplusplus extern "C"{ #endif //typedef enum bool_t{false = 0, true} bool;//C... #ifndef __cplusplus typedef int bool; #define true 1 #define false 0 #endif #include #include #include #include #define FRAMESYNC 0x03ff #define MPEGVersion2_5 0x00 #define MPEGreserved 0x01 #define MPEGVersion2 0x02 #define MPEGVersion1 0x03 #define LAYER1 0x03 #define LAYER2 0x02 #define LAYER3 0x01 #define LAYERreserved 0x00 #define BITRATEFREE 0xfffe #define BITRATEBAD 0xffff #define SAMPLINGFREQreserved 0x3 #define EMPHASYSreserved 0x10 #ifndef byte typedef unsigned char byte; #endif /* typedef struct{ unsigned framesync :11; //Frame synchronizer unsigned MPEGID : 2; //MPEG version ID unsigned layer : 2; //Layer unsigned protectbit : 1; //CRC Protection //---- unsigned bitrateindx: 4; //Bitrate index unsigned samplefreq : 2; //Samplig rate frequency index unsigned paddingbit : 1; //Padding unsigned privatebit : 1; //Private bit //---- unsigned channel : 2; //Channel unsigned modeext : 2; //Mode extension (only if Joint Stereo is set) unsigned copyright : 1; //Copyright unsigned original : 1; //Original unsigned emphasis : 2; //Emphasis } MP3HEADER; */ #pragma pack( push, 1 ) enum { MP3H_FRAMESYNC, MP3H_MPEGID, MP3H_LAYER, MP3H_PROTECTBIT, MP3H_BITRATEINDX, MP3H_SAMPLEFREQ, MP3H_PADDINGBIT, MP3H_PRIVATEBIT, MP3H_CHANNEL, MP3H_MODEEXT, MP3H_COPYRIGHT, MP3H_ORIGINAL, MP3H_EMPHASIS }; short int masks[]; char shifts[]; #define getHAtr(h, m) (masks[m] & ((h)>>shifts[m])) typedef struct{ short framesync ; //Frame synchronizer char MPEGID ; //MPEG version ID char layer ; //Layer char protectbit ; //CRC Protection //---- char bitrateindx; //Bitrate index char samplefreq ; //Samplig rate frequency index char paddingbit ; //Padding char privatebit ; //Private bit //---- char channel ; //Channel char modeext ; //Mode extension (only if Joint Stereo is set) char copyright ; //Copyright char original ; //Original char emphasis ; //Emphasis } MP3HEADER; typedef struct{ char tagid [ 3]; //0-2 3 Tag identifier. Must contain "TAG" string if Tag is valid. char name [30]; //3-32 30 Song Name char artist [30]; //33-62 30 Artist char album [30]; //63-92 30 Album int year ; //93-96 4 Year char comment[30]; //97-126 30 Comment char genre ; //127 1 Genre } MP3ID3TAG1; typedef struct{ char tagid[3];//0-2 TAG identifier. It contains of string "ID3" short tagverm ;//3-4 TAG version char flags ;//5 Flags long size ;//6-9 Size of TAG } MP3ID3TAG2; int MP3bitrate(const MP3HEADER *h); int MP3SamplingFreq(const MP3HEADER *h); bool readMP3header(FILE *f, MP3HEADER *h); bool skipMP3Frame(FILE *f, const MP3HEADER *h); bool skipMP3Tag(FILE *f);//ID3 bool isMP3CBR(FILE *f); bool isMP3VBR(FILE *f); int GetMP3FileBitrate(const char* fname); #pragma pack( pop ) #ifdef __cplusplus } #endif /*---------------------------------------------- bits V1,L1 V1,L2 V1,L3 V2,L1 V2, L2 & L3 0000 free free free free free 0001 32 32 32 32 8 0010 64 48 40 48 16 0011 96 56 48 56 24 0100 128 64 56 64 32 0101 160 80 64 80 40 0110 192 96 80 96 48 0111 224 112 96 112 56 1000 256 128 112 128 64 1001 288 160 128 144 80 1010 320 192 160 160 96 1011 352 224 192 176 112 1100 384 256 224 192 128 1101 416 320 256 224 144 1110 448 384 320 256 160 1111 bad bad bad bad bad -----------------------------------------------*/ int bitrates[] = { BITRATEFREE, BITRATEFREE, BITRATEFREE, BITRATEFREE, BITRATEFREE, 32, 32, 32, 32, 8, 64, 48, 40, 48, 16, 96, 56, 48, 56, 24, 128, 64, 56, 64, 32, 160, 80, 64, 80, 40, 192, 96, 80, 96, 48, 224, 112, 96, 112, 56, 256, 128, 112, 128, 64, 288, 160, 128, 144, 80, 320, 192, 160, 160, 96, 352, 224, 192, 176, 112, 384, 256, 224, 192, 128, 416, 320, 256, 224, 144, 448, 384, 320, 256, 160, BITRATEBAD, BITRATEBAD, BITRATEBAD, BITRATEBAD, BITRATEBAD }; /*----------------------------------- Sampling rate frequency index (values are in Hz) bits MPEG1 MPEG2 MPEG2.5 00 44100 22050 11025 01 48000 24000 12000 10 32000 16000 8000 11 reserv. reserv. reserv. ---------------------------------------*/ int samplingfreqs[] = { 44100, 22050, 11025, 48000, 24000, 12000, 32000, 16000, 8000, SAMPLINGFREQreserved,SAMPLINGFREQreserved, SAMPLINGFREQreserved }; short int masks[] = { 0x03FF, 0x03, 0x03, 0x01, 0x0f, 0x03, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03}; char shifts[] = { 21, 19, 17, 16, 12, 10, 9, 8, 6, 4, 3, 2, 0 }; int unpacktagsize(MP3ID3TAG2 id){ int a, b, c, d; a = ( id.size >> 3 ) & 0x0fe00000; b = ( id.size >> 2 ) & 0x001fc000; c = ( id.size >> 1 ) & 0x00003f80; d = ( id.size >> 0 ) & 0x0000007f; return a>>21 | b>>7 | c<<7 | d<<21; } int MP3SamplingFreq(const MP3HEADER *h){ int idx; switch(h->MPEGID){ case MPEGVersion2_5:idx = 2;break; case MPEGVersion2: idx = 1;break; case MPEGVersion1: idx = 0;break; case MPEGreserved: return SAMPLINGFREQreserved; } return samplingfreqs[(h->samplefreq * 3) + idx]; } int MP3bitrate(const MP3HEADER *h){ int index=0; if( h->MPEGID == MPEGVersion1 ){ index = 3-h->layer; }else if( h->MPEGID == MPEGVersion2 || h->MPEGID == MPEGVersion2_5 ){ index = (h->layer == LAYER1 ? 3 :4 ); } return bitrates[ index + h->bitrateindx * 5 ]; } bool skipMP3Frame(FILE *f, const MP3HEADER *h){ int frsz; if(h->layer == LAYER1){ frsz = (12 * MP3bitrate(h) * 1000 / MP3SamplingFreq(h) + h->paddingbit) * 4; }else if( (h->layer == LAYER2) || (h->layer == LAYER3) ){ frsz = 144 * MP3bitrate(h) * 1000 / MP3SamplingFreq(h) + h->paddingbit; }else{ frsz = 0; } //printf("framesz: %d\n\n", frsz); return fseek(f, frsz, SEEK_CUR) == 0; } bool skipMP3Tag(FILE *f){ MP3ID3TAG2 tag; rewind(f); if(fread(&tag, 1, sizeof(MP3ID3TAG2), f)<1) return false; if(!memcmp(tag.tagid, "ID3", 3)){//é tag id3v2 - saltar para fim da tag return fseek(f, unpacktagsize(tag), SEEK_CUR) == 0; }else{//não é tag id3v2 - inicio do ficheiro rewind(f); } return true; } bool readMP3header(FILE *f, MP3HEADER *h){ int t, b; do{ if(fread(&t, 1, 4, f)<1) return false; fseek(f, -3, SEEK_CUR); /*troca...*/ b = (t & 0x000000ff); t = (t & 0xffffff00) | ((t>>24) & 0x000000ff); t = (t & 0x00ffffff) | ((b<<24) & 0xff000000); b = (t & 0x0000ff00); t = (t & 0xffff00ff) | ( (t>>8) & 0x0000ff00); t = (t & 0xff00ffff) | ( (b<<8) & 0x00ff0000); /*-----*/ h->framesync = getHAtr(t, MP3H_FRAMESYNC); h->MPEGID = getHAtr(t, MP3H_MPEGID); h->layer = getHAtr(t, MP3H_LAYER); h->bitrateindx = getHAtr(t, MP3H_BITRATEINDX); h->samplefreq = getHAtr(t, MP3H_SAMPLEFREQ); h->emphasis = getHAtr(t, MP3H_EMPHASIS); }while( (h->framesync != FRAMESYNC) ||(h->bitrateindx == 0x0f) ||(h->bitrateindx == 0x00) ||(h->MPEGID == MPEGreserved) ||(h->layer == LAYERreserved) ||(h->samplefreq == SAMPLINGFREQreserved) ||(h->emphasis == EMPHASYSreserved)); fseek(f, 3, SEEK_CUR); // h->framesync = getHAtr(t, MP3H_FRAMESYNC); //Frame synchronizer // h->MPEGID = getHAtr(t, MP3H_MPEGID); //MPEG version ID // h->layer = getHAtr(t, MP3H_LAYER); //Layer h->protectbit = getHAtr(t, MP3H_PROTECTBIT); //CRC Protection // h->bitrateindx = getHAtr(t, MP3H_BITRATEINDX); //Bitrate index // h->samplefreq = getHAtr(t, MP3H_SAMPLEFREQ); //Samplig rate frequency index h->paddingbit = getHAtr(t, MP3H_PADDINGBIT); //Padding h->privatebit = getHAtr(t, MP3H_PRIVATEBIT); //Private bit h->channel = getHAtr(t, MP3H_CHANNEL); //Channel h->modeext = getHAtr(t, MP3H_MODEEXT); //Mode extension (only if Joint Stereo is set) h->copyright = getHAtr(t, MP3H_COPYRIGHT); //Copyright h->original = getHAtr(t, MP3H_ORIGINAL); //Original // h->emphasis = getHAtr(t, MP3H_EMPHASIS); //Emphasis return true; } bool isMP3CBR(FILE *f){ return true; } bool isMP3VBR(FILE *f){ return false; } int GetMP3FileBitrate(const char* fname){ FILE *f; MP3HEADER h; int brate; f = fopen(fname, "rb"); if(!f) return -1; if(isMP3CBR(f)){ skipMP3Tag(f); readMP3header(f, &h); brate = MP3bitrate(&h); }else if(isMP3VBR(f)){ // brate = 0; }else brate = -1; fclose(f); return brate; }