Code:
#include<conio.h>
#include<stdio.h>
#define MPEGVersion2_5 0
#define MPEGreserved 1
#define MPEGVersion2 2
#define MPEGVersion1 3
#define LAYER1 3
#define LAYER2 2
#define LAYER3 1
#define LAYERRESERVED 0
//some macros defined by me... you can do what ever you want with these
#define BITRATEFREE 0xfffe
#define BITRATEBAD 0xffff
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
};
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;
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 :32 ; //93-96 4 Year
char comment[30]; //97-126 30 Comment
char genre : 8 ; //127 1 Genre
} MP3ID3TAG1;
#pragma pack(1)
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 MSB
} MP3ID3TAG2;
int unpacktagsize(MP3ID3TAG2 id){
int a, b, c, d;
a = id.size & 0x7f000000,
b = id.size & 0x007f0000,
c = id.size & 0x00007f00,
d = id.size & 0x0000007f;
return a>>3 | b>>2 | c>>1 | d>>0;
}
int readMP3header(FILE *f, MP3HEADER *h){
MP3ID3TAG2 tag;
//push file point to the beginning
rewind(f);
fread(&tag, 1, sizeof(MP3ID3TAG2), f);
//tag id3v2 are located at the beginning of file, id3v1 at the end
if(tag.tagid[0]=='I' && tag.tagid[1]=='D' && tag.tagid[2]=='3'){//is tag id3v2 - jump to end of tag
fseek(f, unpacktagsize(tag), SEEK_CUR);
}else{//isn't tag id3v2 - go back
rewind(f);
}
//I'm currently not interested in the final state of the file pointer
do{//read a frame header
if(fread(h, 1, sizeof(MP3HEADER), f)<1)//returns -1 if eof
return 0;
fseek(f, 1-sizeof(MP3HEADER), SEEK_CUR);
//verifies if the framesync bytes are wellset - if not no frame header was read: go to next file byte
}while(~h->framesync);
return 1;
}
int MP3bitrate(MP3HEADER h){
int index=0;
if( (0x03&h.MPEGID)==MPEGVersion1 ){
index = 3-h.layer;
}else if( (0x03&h.MPEGID)==MPEGVersion2 || (0x03&h.MPEGID)==MPEGVersion2_5 ){
index = (0x03&h.layer) == LAYER1 ? 3 :4 ;
}
return bitrates[ index + (0x0f&h.bitrateindx) * 5];
}
main(){
FILE *f;
MP3HEADER h;
int i;
f = fopen(YOUR_FILE_HERE, "rb");
if(readMP3header(f, &h))
printf("MPEGID: %d\nLAYER: %d\nBITIND: %d\nBITRATE: %d\n",
0x03&h.MPEGID, 0x03&h.layer, 0x0f&h.bitrateindx , MP3bitrate(h));
else
printf("nop, header not found.");
getch();
}
Well, the problem... The first frame header isn't found first. Only after the first iteration, the second time, or not. I think it has something to do with the tag skipping. I get the wrong bitrate, and If I try to read several frames from the same file I get diferent bitrates every time.