rendered paste body#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<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#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;
}