1 #include <stdlib.h>
2 #include <stdio.h>
3 
4 #define error(x)	{puts(x); exit(1);}
5 
6 #define MP3_FRAME_SYNC       0xFFE00000
7 
8 #define MP3_VERSION          0x00180000
9 #define MP3_VERSION_25       0x00000000
10 #define MP3_VERSION_RESERVED 0x00080000
11 #define MP3_VERSION_2        0x00100000
12 #define MP3_VERSION_1        0x00180000
13 
14 #define MP3_LAYER            0x00060000
15 #define MP3_LAYER_RESERVED   0x00000000
16 #define MP3_LAYER_3          0x00020000
17 #define MP3_LAYER_2          0x00040000
18 #define MP3_LAYER_1          0x00060000
19 
20 #define MP3_PROTECT          0x00010000 /* 16-bit CRC after header */
21 
22 #define MP3_BITRATE          0x0000F000
23 #define MP3_BITRATE_SHIFT    12
24 
25 int mp1l1_bitrate_table[] = { 0,   32,   64,  96, 128, 160, 192, 224,
26 			      256, 288, 320, 352, 382, 416, 448 };
27 
28 int mp1l2_bitrate_table[] = { 0,   32,   48,  56,  64,  80,  96, 112,
29 			      128, 160, 192, 224, 256, 320, 384 };
30 
31 int mp1l3_bitrate_table[] = { 0,    32,  40,  48,  56,  64,  80,  96,
32 			      112, 128, 160, 192, 224, 256, 320 };
33 
34 int mp2l1_bitrate_table[] = { 0,    32,  48,  56,  64,  80,  96, 112,
35 			      128, 144, 160, 176, 192, 224, 256 };
36 
37 int mp2l23_bitrate_table[] = { 0,    8,  16,  24,  32,  40,  48,  56,
38 			       64,  80,  96, 112, 128, 144, 160 };
39 
40 #define MP3_SAMPLERATE       0x00000C00
41 #define MP3_SAMPLERATE_SHIFT 10
42 #define MP3_SAMPLERATE_IDX_MAX 2
43 
44 int mp1_samplerate_table[MP3_SAMPLERATE_IDX_MAX + 1] = { 44100, 48000, 32000 };
45 int mp2_samplerate_table[MP3_SAMPLERATE_IDX_MAX + 1] = { 22050, 24000, 16000 }; /* is this right?? */
46 int mp25_samplerate_table[MP3_SAMPLERATE_IDX_MAX + 1] = { 11025, 12000, 8000 }; /* fewer samples?? */
47 
48 #define MP3_PADDING          0x00000200 /* if set, add an extra slot - 4 bytes
49 					   for layer 1, 1 byte for 2+3 */
50 
51 #define MP3_CHANNEL          0x000000C0
52 #define MP3_CHANNEL_STEREO   0x00000000
53 #define MP3_CHANNEL_JOINT    0x00000040
54 #define MP3_CHANNEL_DUAL     0x00000080
55 #define MP3_CHANNEL_MONO     0x000000C0
56 
57 /* rest of the header info doesn't affect frame size.. */
58 
skipBytes(FILE * f,int length)59 void skipBytes(FILE *f, int length)
60 {
61   for(; length>0; --length)
62     if(fgetc(f) == EOF)
63       return;
64 }
65 
printMP3Headers(FILE * f)66 void printMP3Headers(FILE *f)
67 {
68   unsigned long flags;
69   int frameLen, numFrames = 0;
70   int bitrate=0, bitrate_idx, samplerate=0, samplerate_idx;
71   int version, layer, channels, padding;
72   int bitrateSum = 0;
73   int length;
74 
75   for(;;)
76   {
77     int flags_char;
78     int i;
79     /* get 4-byte header, bigendian */
80     if((flags = fgetc(f)) == EOF)
81       break;
82 
83     /* XXX - fix this mad hackery */
84     if(flags == 'I' && fgetc(f) == 'D' && fgetc(f) == '3')
85     {
86       do
87       {
88 	flags = fgetc(f);
89       }
90       while(flags != 0xFF && flags != EOF);
91     }
92 
93     if(flags == EOF)
94       break;
95 
96     flags <<= 24;
97     for (i = 2; i >= 0; --i)
98     {
99       if ((flags_char = fgetc(f)) == EOF)
100       {
101         error("truncated file");
102       }
103       else
104       {
105         flags += flags_char << (i * 8);
106       }
107     }
108 
109     if((flags & MP3_FRAME_SYNC) != MP3_FRAME_SYNC)
110       break;
111     /*      error("bad sync on MP3 block!"); */
112 
113     ++numFrames;
114 
115     bitrate_idx = (flags & MP3_BITRATE) >> MP3_BITRATE_SHIFT;
116     samplerate_idx = (flags & MP3_SAMPLERATE) >> MP3_SAMPLERATE_SHIFT;
117     if (samplerate_idx < 0 || samplerate_idx > MP3_SAMPLERATE_IDX_MAX)
118     {
119       error("invalid samplerate index");
120     }
121 
122     channels = ((flags & MP3_CHANNEL) == MP3_CHANNEL_MONO) ? 1 : 2;
123 
124     switch(flags & MP3_VERSION)
125     {
126       case MP3_VERSION_1:  version = 1; break;
127       case MP3_VERSION_2:  version = 2; break;
128       case MP3_VERSION_25: version = 25; break;
129       default: error("unknown MP3 version!");
130     }
131     switch(flags & MP3_LAYER)
132     {
133       case MP3_LAYER_1: layer = 1; break;
134       case MP3_LAYER_2: layer = 2; break;
135       case MP3_LAYER_3: layer = 3; break;
136       default: error("unknown MP3 layer!");
137     }
138 
139     bitrateSum += bitrate;
140 
141     if(version == 1)
142     {
143       samplerate = mp1_samplerate_table[samplerate_idx];
144 
145       if(layer == 1)
146 	bitrate = mp1l1_bitrate_table[bitrate_idx];
147 
148       else if(layer == 2)
149 	bitrate = mp1l2_bitrate_table[bitrate_idx];
150 
151       else if(layer == 3)
152 	bitrate = mp1l3_bitrate_table[bitrate_idx];
153     }
154     else
155     {
156       if(version == 2)
157 	samplerate = mp2_samplerate_table[samplerate_idx];
158       else
159 	samplerate = mp25_samplerate_table[samplerate_idx];
160 
161       if(layer == 1)
162 	bitrate = mp2l1_bitrate_table[bitrate_idx];
163       else
164 	bitrate = mp2l23_bitrate_table[bitrate_idx];
165     }
166 
167     padding = (flags & MP3_PADDING) ? 1 : 0;
168 
169     if(layer == 1)
170       padding <<= 2;
171 
172     if(version == 1)
173       frameLen = 144 * bitrate * 1000 / samplerate + padding;
174     else
175       frameLen = 72 * bitrate * 1000 / samplerate + padding;
176 
177     printf("frame %i: MP%i layer %i, %i Hz, %ikbps, %s, length=%i, protect %s\n",
178 	   numFrames, version, layer, samplerate, bitrate,
179 	   (channels==2) ? "stereo" : "mono", frameLen,
180 	   (flags&MP3_PROTECT) ? "on" : "off");
181 
182     skipBytes(f, frameLen-4);
183   }
184 
185   if (numFrames == 0)
186     error("no valid frame found");
187 
188   putchar('\n');
189 
190   length = numFrames*(samplerate > 3200 ? 1152 : 576)/samplerate;
191 
192   printf("Number of frames: %i\n", numFrames);
193   printf("Average bitrate: %i\n", bitrateSum/numFrames);
194   printf("Length: %i:%02i\n", length/60, length%60);
195 }
196 
main(int argc,char * argv[])197 int main(int argc, char *argv[])
198 {
199   FILE *f;
200 
201   if(argc<1)
202     error("gimme file name");
203 
204   f = fopen(argv[1],"rb");
205 
206   if(!f)
207     error("couldn't open file");
208 
209   printMP3Headers(f);
210 
211   exit(0);
212 }
213