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