1 /*
2 mp3tech.c - Functions for handling MP3 files and most MP3 data
3 structure manipulation.
4
5 Copyright (C) 2000-2006 Cedric Tefft <cedric@phreaker.net>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 ***************************************************************************
22
23 This file is based in part on:
24
25 * MP3Info 0.5 by Ricardo Cerqueira <rmc@rccn.net>
26 * MP3Stat 0.9 by Ed Sweetman <safemode@voicenet.com> and
27 Johannes Overmann <overmann@iname.com>
28
29 */
30
31 #include "mp3info.h"
32
33
34 int layer_tab[4]= {0, 3, 2, 1};
35
36 int frequencies[3][4] = {
37 {22050,24000,16000,50000}, /* MPEG 2.0 */
38 {44100,48000,32000,50000}, /* MPEG 1.0 */
39 {11025,12000,8000,50000} /* MPEG 2.5 */
40 };
41
42 int bitrate[2][3][15] = {
43 { /* MPEG 2.0 */
44 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256}, /* layer 1 */
45 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}, /* layer 2 */
46 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160} /* layer 3 */
47
48 },
49
50 { /* MPEG 1.0 */
51 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448}, /* layer 1 */
52 {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384}, /* layer 2 */
53 {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} /* layer 3 */
54 }
55 };
56
57 int frame_size_index[] = {24000, 72000, 72000};
58
59
60 char *mode_text[] = {
61 "stereo", "joint stereo", "dual channel", "mono"
62 };
63
64 char *emphasis_text[] = {
65 "none", "50/15 microsecs", "reserved", "CCITT J 17"
66 };
67
68
get_mp3_info(mp3info * mp3,int scantype,int fullscan_vbr)69 int get_mp3_info(mp3info *mp3,int scantype, int fullscan_vbr)
70 {
71 int had_error = 0;
72 int frame_type[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
73 float seconds=0,total_rate=0;
74 int frames=0,frame_types=0,frames_so_far=0;
75 int l,vbr_median=-1;
76 int bitrate,lastrate;
77 int counter=0;
78 mp3header header;
79 struct stat filestat;
80 off_t sample_pos,data_start=0;
81
82
83 stat(mp3->filename,&filestat);
84 mp3->datasize=filestat.st_size;
85 get_id3(mp3);
86
87 if(scantype == SCAN_QUICK) {
88 if(get_first_header(mp3,0L)) {
89 data_start=ftell(mp3->file);
90 lastrate=15-mp3->header.bitrate;
91 while((counter < NUM_SAMPLES) && lastrate) {
92 sample_pos=(counter*(mp3->datasize/NUM_SAMPLES+1))+data_start;
93 if(get_first_header(mp3,sample_pos)) {
94 bitrate=15-mp3->header.bitrate;
95 } else {
96 bitrate=-1;
97 }
98
99 if(bitrate != lastrate) {
100 mp3->vbr=1;
101 if(fullscan_vbr) {
102 counter=NUM_SAMPLES;
103 scantype=SCAN_FULL;
104 }
105 }
106 lastrate=bitrate;
107 counter++;
108
109 }
110 if(!(scantype == SCAN_FULL)) {
111 mp3->frames=(mp3->datasize-data_start)/(l=frame_length(&mp3->header));
112 mp3->seconds = (int)((float)(frame_length(&mp3->header)*mp3->frames)/
113 (float)(header_bitrate(&mp3->header)*125)+0.5);
114 mp3->vbr_average = (float)header_bitrate(&mp3->header);
115 }
116 }
117
118 }
119
120 if(scantype == SCAN_FULL) {
121 if(get_first_header(mp3,0L)) {
122 data_start=ftell(mp3->file);
123 while((bitrate=get_next_header(mp3))) {
124 frame_type[15-bitrate]++;
125 frames++;
126 }
127 memcpy(&header,&(mp3->header),sizeof(mp3header));
128 for(counter=0;counter<15;counter++) {
129 if(frame_type[counter]) {
130 frame_types++;
131 header.bitrate=counter;
132 frames_so_far += frame_type[counter];
133 seconds += (float)(frame_length(&header)*frame_type[counter])/
134 (float)(header_bitrate(&header)*125);
135 total_rate += (float)((header_bitrate(&header))*frame_type[counter]);
136 if((vbr_median == -1) && (frames_so_far >= frames/2))
137 vbr_median=counter;
138 }
139 }
140 mp3->seconds=(int)(seconds+0.5);
141 mp3->header.bitrate=vbr_median;
142 mp3->vbr_average=total_rate/(float)frames;
143 mp3->frames=frames;
144 if(frame_types > 1) {
145 mp3->vbr=1;
146 }
147 }
148 }
149 return had_error;
150 }
151
152
get_first_header(mp3info * mp3,long startpos)153 int get_first_header(mp3info *mp3, long startpos)
154 {
155 int k, l=0,c;
156 mp3header h, h2;
157 long valid_start=0;
158
159 fseek(mp3->file,startpos,SEEK_SET);
160 while (1) {
161 while((c=fgetc(mp3->file)) != 255 && (c != EOF));
162 if(c == 255) {
163 ungetc(c,mp3->file);
164 valid_start=ftell(mp3->file);
165 if((l=get_header(mp3->file,&h))) {
166 fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
167 for(k=1; (k < MIN_CONSEC_GOOD_FRAMES) && (mp3->datasize-ftell(mp3->file) >= FRAME_HEADER_SIZE); k++) {
168 if(!(l=get_header(mp3->file,&h2))) break;
169 if(!sameConstant(&h,&h2)) break;
170 fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
171 }
172 if(k == MIN_CONSEC_GOOD_FRAMES) {
173 fseek(mp3->file,valid_start,SEEK_SET);
174 memcpy(&(mp3->header),&h2,sizeof(mp3header));
175 mp3->header_isvalid=1;
176 return 1;
177 }
178 }
179 } else {
180 return 0;
181 }
182 }
183
184 return 0;
185 }
186
187 /* get_next_header() - read header at current position or look for
188 the next valid header if there isn't one at the current position
189 */
get_next_header(mp3info * mp3)190 int get_next_header(mp3info *mp3)
191 {
192 int l=0,c,skip_bytes=0;
193 mp3header h;
194
195 while(1) {
196 while((c=fgetc(mp3->file)) != 255 && (ftell(mp3->file) < mp3->datasize)) skip_bytes++;
197 if(c == 255) {
198 ungetc(c,mp3->file);
199 if((l=get_header(mp3->file,&h))) {
200 if(skip_bytes) mp3->badframes++;
201 fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
202 return 15-h.bitrate;
203 } else {
204 skip_bytes += FRAME_HEADER_SIZE;
205 }
206 } else {
207 if(skip_bytes) mp3->badframes++;
208 return 0;
209 }
210 }
211 }
212
213
214 /* Get next MP3 frame header.
215 Return codes:
216 positive value = Frame Length of this header
217 0 = No, we did not retrieve a valid frame header
218 */
219
get_header(FILE * file,mp3header * header)220 int get_header(FILE *file,mp3header *header)
221 {
222 unsigned char buffer[FRAME_HEADER_SIZE];
223 int fl;
224
225 if(fread(&buffer,FRAME_HEADER_SIZE,1,file)<1) {
226 header->sync=0;
227 return 0;
228 }
229 header->sync=(((int)buffer[0]<<4) | ((int)(buffer[1]&0xE0)>>4));
230 if(buffer[1] & 0x10) header->version=(buffer[1] >> 3) & 1;
231 else header->version=2;
232 header->layer=(buffer[1] >> 1) & 3;
233 header->bitrate=(buffer[2] >> 4) & 0x0F;
234 if((header->sync != 0xFFE) || (header->layer != 1) || (header->bitrate == 0xF)) {
235 header->sync=0;
236 return 0;
237 }
238 header->crc=buffer[1] & 1;
239 header->freq=(buffer[2] >> 2) & 0x3;
240 header->padding=(buffer[2] >>1) & 0x1;
241 header->extension=(buffer[2]) & 0x1;
242 header->mode=(buffer[3] >> 6) & 0x3;
243 header->mode_extension=(buffer[3] >> 4) & 0x3;
244 header->copyright=(buffer[3] >> 3) & 0x1;
245 header->original=(buffer[3] >> 2) & 0x1;
246 header->emphasis=(buffer[3]) & 0x3;
247
248 /* Final sanity checks: bitrate 1111b and frequency 11b are reserved (invalid) */
249 if (header->bitrate == 0x0F || header->freq == 0x3) {
250 return 0;
251 }
252
253 return ((fl=frame_length(header)) >= MIN_FRAME_SIZE ? fl : 0);
254 }
255
frame_length(mp3header * header)256 int frame_length(mp3header *header) {
257 return header->sync == 0xFFE ?
258 (frame_size_index[3-header->layer]*((header->version&1)+1)*
259 header_bitrate(header)/header_frequency(header))+
260 header->padding : 1;
261 }
262
header_layer(mp3header * h)263 int header_layer(mp3header *h) {return layer_tab[h->layer];}
264
header_bitrate(mp3header * h)265 int header_bitrate(mp3header *h) {
266 return bitrate[h->version & 1][3-h->layer][h->bitrate];
267 }
268
header_frequency(mp3header * h)269 int header_frequency(mp3header *h) {
270 return frequencies[h->version][h->freq];
271 }
272
header_emphasis(mp3header * h)273 char *header_emphasis(mp3header *h) {
274 return emphasis_text[h->emphasis];
275 }
276
header_mode(mp3header * h)277 char *header_mode(mp3header *h) {
278 return mode_text[h->mode];
279 }
280
sameConstant(mp3header * h1,mp3header * h2)281 int sameConstant(mp3header *h1, mp3header *h2) {
282 if((*(uint*)h1) == (*(uint*)h2)) return 1;
283
284 if((h1->version == h2->version ) &&
285 (h1->layer == h2->layer ) &&
286 (h1->crc == h2->crc ) &&
287 (h1->freq == h2->freq ) &&
288 (h1->mode == h2->mode ) &&
289 (h1->copyright == h2->copyright ) &&
290 (h1->original == h2->original ) &&
291 (h1->emphasis == h2->emphasis ))
292 return 1;
293 else return 0;
294 }
295
296
get_id3(mp3info * mp3)297 int get_id3(mp3info *mp3) {
298 int retcode=0;
299 char fbuf[4];
300
301 if(mp3->datasize >= 128) {
302 if(fseek(mp3->file, -128, SEEK_END )) {
303 fprintf(stderr,"ERROR: Couldn't read last 128 bytes of %s!!\n",mp3->filename);
304 retcode |= 4;
305 } else {
306 fread(fbuf,1,3,mp3->file); fbuf[3] = '\0';
307 mp3->id3.genre[0]=255;
308
309
310 if (!strcmp((const char *)"TAG",(const char *)fbuf)) {
311
312
313 mp3->id3_isvalid=1;
314 mp3->datasize -= 128;
315 fseek(mp3->file, -125, SEEK_END);
316 fread(mp3->id3.title,1,30,mp3->file); mp3->id3.title[30] = '\0';
317 fread(mp3->id3.artist,1,30,mp3->file); mp3->id3.artist[30] = '\0';
318 fread(mp3->id3.album,1,30,mp3->file); mp3->id3.album[30] = '\0';
319 fread(mp3->id3.year,1,4,mp3->file); mp3->id3.year[4] = '\0';
320 fread(mp3->id3.comment,1,30,mp3->file); mp3->id3.comment[30] = '\0';
321 if(mp3->id3.comment[28] == '\0') {
322 mp3->id3.track[0] = mp3->id3.comment[29];
323 }
324 fread(mp3->id3.genre,1,1,mp3->file);
325 unpad(mp3->id3.title);
326 unpad(mp3->id3.artist);
327 unpad(mp3->id3.album);
328 unpad(mp3->id3.year);
329 unpad(mp3->id3.comment);
330 }
331 }
332 }
333 return retcode;
334
335 }
336
pad(char * string,int length)337 char *pad(char *string, int length) {
338 int l;
339
340 l=strlen(string);
341 while(l<length) {
342 string[l] = ' ';
343 l++;
344 }
345
346 string[l]='\0';
347 return string;
348 }
349
350 /* Remove trailing whitespace from the end of a string */
351
unpad(char * string)352 char *unpad(char *string) {
353 char *pos=string+strlen(string)-1;
354 while(isspace(pos[0])) (pos--)[0]=0;
355 return string;
356 }
357
358 /*
359 * Build an ID3 tag and write it to the file
360 * Returns positive int on success, 0 on failure
361 */
362
write_tag(mp3info * mp3)363 int write_tag(mp3info *mp3) {
364
365 char buf[129];
366
367 strcpy(buf,"TAG");
368 pad(mp3->id3.title,TEXT_FIELD_LEN);
369 strncat(buf,mp3->id3.title,TEXT_FIELD_LEN);
370 pad(mp3->id3.artist,TEXT_FIELD_LEN);
371 strncat(buf,mp3->id3.artist,TEXT_FIELD_LEN);
372 pad(mp3->id3.album,TEXT_FIELD_LEN);
373 strncat(buf,mp3->id3.album,TEXT_FIELD_LEN);
374 pad(mp3->id3.year,INT_FIELD_LEN);
375 strncat(buf,mp3->id3.year,INT_FIELD_LEN);
376 pad(mp3->id3.comment,TEXT_FIELD_LEN);
377 strncat(buf,mp3->id3.comment,TEXT_FIELD_LEN);
378 strncat(buf,(char *)&(mp3->id3.genre),1);
379 if (mp3->id3.track[0] != '\0') {
380 buf[125]='\0';
381 buf[126]=mp3->id3.track[0];
382 }
383 fseek(mp3->file,-128*mp3->id3_isvalid,SEEK_END);
384 return (int)fwrite(buf,1,128,mp3->file);
385 }
386