1 #include "mp3_check.h"
2 
3 #include <stdio.h>
4 
5 static inline int move_to_next_frame(char *possible_mp3_tag,
6 				     frame_info * mp3_i, gen_info * file_info,
7 				     command_flags * flags, FILE *);
8 static int get_char_from_file(FILE *fp, unsigned int *header_value,
9 			      gen_info *file_info, command_flags *flags,
10 			      char *possible_mp3_tag);
11 static int check_vbr_and_time(frame_info *mp3_i, vbr_data *vbr_info,
12 			      gen_info *file_info);
13 static int rotate_char_array(char *byte_list, int *new_byte,
14 			     gen_info * info_file);
15 static int scan_file(FILE *fp, char *filename, meta_options *flag_options,
16 		     command_flags *flags);
17 
18 
rotate_char_array(char * byte_list,int * new_byte,gen_info * file_info)19 static int rotate_char_array(char *byte_list, int *new_byte,
20 			     gen_info *file_info)
21 {
22 	int place_holder = 0;
23 
24 	/* I don't think it'll get any faster than this. */
25 	place_holder = file_info->byte_count % 128;
26 
27 	*(byte_list + place_holder) = *new_byte;
28 
29 	return (TRUE);
30 }
31 
scan_file(FILE * fp,char * filename,meta_options * flag_options,command_flags * flags)32 static int scan_file(FILE *fp, char *filename, meta_options *flag_options,
33 		     command_flags *flags)
34 {
35 	int counter = 0;
36 	int END_OF_FILE = FALSE;
37 	int found_first_frame = FALSE;
38 	char possible_mp3_tag[BUFFER_LENGTH];
39 	unsigned int header_value = 0;
40 
41 	/*
42 	 * This is set to 'YES' so that I will always get the first 4 bytes
43 	 * off the stream no matter what.
44 	 */
45 	char found_valid_header = YES;
46 	char found_weak_header = NO;
47 
48 	/* Keep all the structures centralized. */
49 	frame_info mp3_i;
50 	vbr_data vbr_info;
51 	mp3_time song_time;
52 	frame_info first_mp3_frame;
53 	id3_tag_info id3_tag;
54 	gen_info file_info;
55 
56 	/* Zero these structures out. */
57 	init_frame_struct(&first_mp3_frame);
58 	init_vbr_tag_struct(&vbr_info);
59 	init_gen_info_struct(&file_info);
60 
61 
62 	while (!END_OF_FILE) {
63 		if (flags->bflag || flags->aflag) {
64 			/*
65 			 * This is the part where if the current byte count is
66 			 * greater than the upper limit on the commandline,
67 			 * it will break out.
68 			 */
69 			if (flags->bflag
70 			    && (file_info.byte_count >
71 				flag_options->byte_limit)) break;
72 		}
73 
74 		/*
75 		 * The fist run defaults to 'YES', so the 'else' section runs
76 		 * first
77 		 *
78 		 * The logic below is what travels through the mp3 file, and
79 		 * then quickly does a sync checksum to see if it is a
80 		 * candidate.
81 		 */
82 		if (!found_valid_header) {
83 			/*
84 			 * Just add one character to the end and keep the
85 			 * rest. I do not want to grab another 4 bytes unless
86 			 * I got a success.
87 			 *
88 			 * Putting the below action in a function slows it
89 			 * down quite a bit, but, it makes the code more
90 			 * readable.
91 			 */
92 			if (get_char_from_file
93 			    (fp, &header_value, &file_info, flags,
94 			     possible_mp3_tag)) {
95 				if (!flags->ssflag && flags->sflag
96 				    && !flags->fflag) {
97 					printf("%c", (header_value & 0xff));
98 				}
99 			} else
100 				break;
101 		} else {
102 			/* Clear it out of old values. */
103 			header_value = 0;
104 
105 			/* Grab the complete 4-byte header (if it is one). */
106 			for (counter = 0; counter < 4; counter++) {
107 				if (get_char_from_file
108 				    (fp, &header_value, &file_info, flags,
109 				     possible_mp3_tag)) {
110 					if (!flags->ssflag && flags->sflag
111 					    && !flags->fflag) {
112 						printf("%c",
113 						       (header_value & 0xff));
114 					}
115 				} else
116 					break;
117 			}
118 		}
119 
120 
121 		/* Check if this is a valid frame sync. */
122 		if (((header_value >> 21) & 0x7ff) == 0x7ff) {
123 			found_weak_header = YES;
124 
125 			init_frame_struct(&mp3_i);
126 
127 			if (check_header_value
128 			    (&header_value, filename, &mp3_i)) {
129 				found_valid_header = YES;
130 
131 				/*
132 				 * Was the offset of this current frame known
133 				 * by the previous frame? It better have...
134 				 *
135 				 * This also defines junk at the beginning as
136 				 * being a bad frame.
137 				 */
138 				if ((file_info.good_frame_count > 0)
139 				    && (file_info.next_expected_frame !=
140 					file_info.byte_count)) {
141 					file_info.bad_frame_count++;
142 
143 					/*
144 					 * I guess if I get to this section,
145 					 * I have found an mp3 with some bad
146 					 * stuff in it, so I will return a
147 					 * fail when the program exits.
148 					 */
149 					fprintf(stderr,
150 						"\nAn expected frame was not found. Expected it at offset 0x%x (BYTE %d), now at offset 0x%x (BYTE %d).",
151 						file_info.next_expected_frame,
152 						file_info.next_expected_frame,
153 						file_info.byte_count,
154 						file_info.byte_count);
155 
156 					/*
157 					 * Checking to see if a continuous
158 					 * amount of frames were found. This
159 					 * check only occurs when a bad frame
160 					 * was found.
161 					 */
162 					if (flags->qflag
163 					    && (file_info.
164 						frame_sequence_count > 0)
165 					    && (flag_options->min_frame_seq >
166 						file_info.
167 						frame_sequence_count)) {
168 						fprintf(stderr,
169 							"\nMininum contiguous number of frames wasn't reached. Got to %d, needed %d at offset 0x%x (BYTE %d).",
170 							file_info.
171 							frame_sequence_count,
172 							flag_options->
173 							min_frame_seq,
174 							file_info.
175 							next_expected_frame,
176 							file_info.
177 							next_expected_frame);
178 
179 						file_info.
180 						    frame_sequence_count = 0;
181 					}
182 
183 				} else if (file_info.next_expected_frame ==
184 					   file_info.byte_count) {
185 					file_info.good_frame_count++;
186 					file_info.frame_sequence_count++;
187 				} else
188 					printf
189 					    ("\nSomething happened at byte %d. Next expected frame: %d.\n",
190 					     file_info.byte_count,
191 					     file_info.next_expected_frame);
192 
193 
194 				/*
195 				 * The fflag is only good to use when there
196 				 * is *no* valid data, and not when there is
197 				 * good data (it should be implied). !sflag
198 				 * is set up this way because the data is
199 				 * already being shown above.
200 				 *
201 				 * There are two parts to this header printing.
202 				 */
203 				if (!flags->ssflag &&
204 				    (flags->sflag && flags->fflag))
205 					printf("%c%c%c%c",
206 					       ((header_value >> 24) & 0xff),
207 					       ((header_value >> 16) & 0xff),
208 					       ((header_value >> 8) & 0xff),
209 					       (header_value & 0xff));
210 
211 				/*
212 				 * I'm currently in a known good frame, so I
213 				 * can safely move forward two characters and
214 				 * still be in the frame. I will have to
215 				 * compensate when I move to the next frame.
216 				 * That is taken care of in move_to_next_frame.
217 				 */
218 				if (mp3_i.PROT_BIT) {
219 					/*
220 					 * Now, to grab the 2 bytes for the
221 					 * CRC value.
222 					 */
223 					for (counter = 0; counter < 2;
224 					     counter++) {
225 						if (get_char_from_file
226 						    (fp, &header_value,
227 						     &file_info, flags,
228 						     possible_mp3_tag)) {
229 							if (!flags->ssflag
230 							    && flags->sflag
231 							    && !flags->fflag) {
232 								printf("%c",
233 								       (header_value
234 									&
235 									0xff));
236 							}
237 						} else {
238 							break;
239 						}
240 					}
241 
242 					/* Now, extract it from the header. */
243 					mp3_i.CRC16_VALUE =
244 					    header_value & 0xffff;
245 
246 					/*
247 					 * The fflag is only good to use when
248 					 * there is *no* valid data, and not
249 					 * when there is good data (it should
250 					 * be implied). !sflag is set up this
251 					 * way because the data is already
252 					 * being shown above.
253 					 */
254 					if (!flags->ssflag
255 					    && (flags->sflag && flags-> fflag))
256 						printf("%c%c",
257 						       ((header_value >> 8) & 0xff),
258 						       (header_value & 0xff));
259 				}
260 
261 				/*
262 				 * If the header is valid, but has bad data,
263 				 * it will still store this information.
264 				 * Perhaps it would be better to make sure it
265 				 * _really_ is a good frame before storing
266 				 * any VBR data...
267 				 */
268 				check_vbr_and_time(&mp3_i, &vbr_info,
269 						   &file_info);
270 
271 				/*
272 				 * I always want to keep the first frame so I
273 				 * can print it out at the end consistently.
274 				 *
275 				 * I am going to disable the 'if' statement
276 				 * because for some reason if there's an
277 				 * anomaly in the frame, it keeps the data,
278 				 * so I guess for now I'll just have this
279 				 * information updated at every frame.
280 				 */
281 				if (file_info.good_frame_count > 0) {
282 					first_mp3_frame = mp3_i;
283 					found_first_frame = TRUE;
284 				}
285 
286 				/* Print out per-frame stats. */
287 				if (!flags->sflag && flags->vvflag
288 				    && (file_info.good_frame_count > 0))
289 					print_frame_info(&mp3_i, &file_info);
290 
291 				/*
292 				 * This will checkety-check to see if I get
293 				 * the next frame when I am supposed to.
294 				 */
295 				if (mp3_i.PROT_BIT)
296 					file_info.next_expected_frame =
297 					    file_info.byte_count +
298 					    mp3_i.FRAME_LENGTH - 2;
299 				else
300 					file_info.next_expected_frame =
301 					    file_info.byte_count +
302 					    mp3_i.FRAME_LENGTH;
303 
304 				/*
305 				 * Keep on searching the whole mp3? Ok, lemme
306 				 * skip though the data to get to the next
307 				 * header.
308 				 */
309 				if (flags->aflag
310 				    || (flags->bflag
311 					&& (flag_options->byte_limit > 0))) {
312 					if (!move_to_next_frame
313 					    (possible_mp3_tag, &mp3_i,
314 					     &file_info, flags, fp))
315 						break;
316 				} else
317 					/*
318 					 * I found my first valid header, so
319 					 * I can quit now.
320 					 */
321 					break;
322 
323 			} else {
324 				/*
325 				 * I guess if I get to this section, I have
326 				 * found an mp3 with some bad stuff in it, so
327 				 * I will return a fail when the program exits.
328 				 */
329 				file_info.bad_frame_count++;
330 
331 				if (flags->vflag)
332 					fprintf(stderr,
333 						"\nA possible header 0x%x passed the weak sieve, but failed the strong one at offset 0x%x (BYTE %d).",
334 						header_value,
335 						file_info.byte_count,
336 						file_info.byte_count);
337 
338 
339 				if (flags->qflag
340 				    && (file_info.frame_sequence_count > 0)
341 				    && (flag_options->min_frame_seq >
342 					file_info.frame_sequence_count)) {
343 					fprintf(stderr,
344 						"\nMininum contiguous number of frames wasn't reached. Got to %d, needed %d at offset 0x%x (BYTE %d).",
345 						file_info.frame_sequence_count,
346 						flag_options->min_frame_seq,
347 						file_info.next_expected_frame,
348 						file_info.next_expected_frame);
349 
350 					file_info.frame_sequence_count = 0;
351 				}
352 			}
353 
354 		} else if (file_info.file_pos == 4
355 			   && (header_value & 0xffffff00) == 0x49443300) {
356 
357 
358 			/*
359 			 * Getting to this section means we may have an
360 			 * ID3V2.x.x header
361 			 */
362 			fprintf(stderr,
363 				"Possible ID3v2 frame found, skipping\n");
364 
365 			/*
366 			 * Since this section is going to be under serious
367 			 * development, the flag 'eflag' will allow mp3_check
368 			 * to record a bad frame when an id3v2 tag is found.
369 			 * This will allow the user to weed out troublesome
370 			 * id3v2 mp3s.
371 			 */
372 			mp3_i.ID3V2 = TRUE;
373 
374 			if (flags->eflag) {
375 				if (flags->qflag
376 				    && (file_info.frame_sequence_count > 0)
377 				    && (flag_options->min_frame_seq >
378 					file_info.frame_sequence_count)) {
379 					fprintf(stderr,
380 						"\nMininum contiguous number of frames wasn't reached. Got to %d, needed %d at offset 0x%x (BYTE %d).",
381 						file_info.frame_sequence_count,
382 						flag_options->min_frame_seq,
383 						file_info.next_expected_frame,
384 						file_info.next_expected_frame);
385 
386 					file_info.frame_sequence_count = 0;
387 				}
388 
389 				file_info.bad_frame_count++;
390 			}
391 
392 			/*
393 			 * TODO: Full ID3V2 checking & processing instead of
394 			 * skipping.
395 			 *
396 			 * Throw away the next two bytes - the first one
397 			 * should always be > 0xff
398 			 * The next 4 bytes represent the len encoded to
399 			 * avoid 0x80 bits set
400 			 */
401 			for (counter = 0; counter < 6; counter++) {
402 				if (get_char_from_file
403 				    (fp, &header_value, &file_info, flags,
404 				     possible_mp3_tag)) {
405 					if (!flags->ssflag && flags->sflag
406 					    && !flags->fflag) {
407 						printf("%c",
408 						       (header_value & 0xff));
409 					}
410 				} else {
411 					break;
412 				}
413 			}
414 
415 			/* calculate the proper length */
416 			counter = ((header_value >> 3) & 0xfe00000)
417 			    | ((header_value >> 2) & 0x1fc000)
418 			    | ((header_value >> 1) & 0x3f80)
419 			    | (header_value & 0x7f);
420 
421 			/*
422 			 * TODO: account for Unsynchronization!
423 			 * we may won't skip all of it if Unsynchroized is
424 			 * set (0x80 in byte 5 of file) account for the 10
425 			 * byte header and the next header this is to avoide
426 			 * excess messages during sync
427 			 */
428 			file_info.next_expected_frame = counter + 14;
429 
430 			/* skip the ID3V2 frame */
431 			while (counter-- > 0) {
432 				if (get_char_from_file
433 				    (fp, &header_value, &file_info, flags,
434 				     possible_mp3_tag)) {
435 					if (!flags->ssflag && flags->sflag
436 					    && !flags->fflag) {
437 						printf("%c",
438 						       (header_value & 0xff));
439 					}
440 				} else {
441 					break;
442 				}
443 			}
444 
445 			/* and mark as not currently synchronized - force it */
446 			found_valid_header = YES;
447 			found_weak_header = NO;
448 		} else {
449 			/*
450 			 * Getting to this section does not mean we got an
451 			 * invalid mp3 file...
452 			 */
453 			found_valid_header = NO;
454 			found_weak_header = NO;
455 		}
456 	}
457 
458 
459 	if (!flags->sflag) {
460 		if (flags->pflag) {
461 			printf("%s %s\t%s %d\t%s %d\t%s %d", "FILE_NAME",
462 			       filename, "GOOD_FRAMES",
463 			       file_info.good_frame_count, "BAD_FRAMES",
464 			       file_info.bad_frame_count, "LAST_BYTE_CHECKED",
465 			       file_info.byte_count);
466 		} else {
467 			printf("\n");
468 			printf("%-20s%s\n", "FILE_NAME", filename);
469 			printf("%-20s%d\n", "GOOD_FRAMES",
470 			       file_info.good_frame_count);
471 			printf("%-20s%d\n", "BAD_FRAMES",
472 			       file_info.bad_frame_count);
473 			printf("%-20s%d", "LAST_BYTE_CHECKED",
474 			       file_info.byte_count);
475 		}
476 
477 		if ((vbr_info.high_rate != vbr_info.low_rate)
478 		    && (file_info.good_frame_count > 0)) {
479 			/*
480 			 * I do not want floating values in ave_rate. Seems
481 			 * silly to have a decimal point for that.
482 			 */
483 			vbr_info.ave_rate =
484 			    vbr_info.sum_rate / file_info.good_frame_count;
485 
486 			if (flags->pflag) {
487 				/*
488 				 * I don't want any newlines for the below
489 				 * line because the pflag option is to print
490 				 * it out all one one line
491 				 */
492 				printf("\t%s %d\t%s %d\t%s %d", "VBR_HIGH",
493 				       vbr_info.high_rate, "VBR_LOW",
494 				       vbr_info.low_rate, "VBR_AVERAGE",
495 				       vbr_info.ave_rate);
496 			} else {
497 				printf("\n");
498 				printf("%-20s%d\n", "VBR_HIGH",
499 				       vbr_info.high_rate);
500 				printf("%-20s%d\n", "VBR_LOW",
501 				       vbr_info.low_rate);
502 				printf("%-20s%d", "VBR_AVERAGE",
503 				       vbr_info.ave_rate);
504 			}
505 		}
506 
507 		if (found_first_frame) {
508 			if (flags->vflag && !flags->pflag) {
509 				print_summary(&first_mp3_frame, filename);
510 			}
511 
512 			translate_time(&file_info, &song_time);
513 
514 			if (flags->pflag)
515 				printf("\t%-20s%02u:%02u.%02u\n",
516 				       "SONG_LENGTH", song_time.minutes,
517 				       song_time.seconds,
518 				       song_time.frac_second);
519 			else
520 				printf("\n%-20s%02u:%02u.%02u\n",
521 				       "SONG_LENGTH", song_time.minutes,
522 				       song_time.seconds,
523 				       song_time.frac_second);
524 
525 		} else {
526 			/*
527 			 * This line below closes the strings above. notice
528 			 * that at the end of the last string, there is no
529 			 * newline...
530 			 */
531 			printf("\n");
532 		}
533 	}
534 
535 
536 	init_id3_tag_struct(&id3_tag);
537 	transform_char_array(possible_mp3_tag, &file_info);
538 
539 
540 	if (flags->iflag && validate_id3_tag(possible_mp3_tag, &id3_tag)) {
541 		if (flags->iflag && flags->fflag && flags->sflag)
542 			dump_id3_tag(&id3_tag);
543 
544 		if (!flags->sflag && flags->vflag) {
545 			printf("\n%-20s%d\n", "MP3_TAG", 1);
546 
547 			printf("%-20s%s\n", "TITLE", id3_tag.TITLE);
548 			printf("%-20s%s\n", "ARTIST", id3_tag.ARTIST);
549 			printf("%-20s%s\n", "ALBUM", id3_tag.ALBUM);
550 			printf("%-20s%s\n", "YEAR", id3_tag.YEAR);
551 			printf("%-20s%s\n", "COMMENT", id3_tag.COMMENT);
552 			printf("%-20s%d\n", "GENRE", id3_tag.GENRE);
553 			printf("%-20s%d\n", "TRACK", id3_tag.TRACK_NUMBER);
554 			printf("%-20s%d\n", "ID3.11", id3_tag.ID3_311_VERSION);
555 		}
556 	} else if (!flags->sflag && flags->iflag) {
557 		printf("\n%-20s%d\n", "MP3_TAG", 0);
558 	}
559 
560 	if (ferror(fp)) {
561 		fprintf(stderr, _("%s: %s %s\n"), PACKAGE, filename,
562 			strerror(errno));
563 		clearerr(fp);
564 	}
565 
566 	if (ferror(stdout)) {
567 		fprintf(stderr, _("%s: stdout %s\n"), PACKAGE,
568 			strerror(errno));
569 		exit(1);
570 	}
571 
572 	/*
573 	 * The 'file_info.bad_frame_count' seems the best way to find errors,
574 	 * so I will use it.
575 	 */
576 	if (file_info.bad_frame_count > 0)
577 		return (FAIL);
578 	else
579 		return (PASS);
580 }
581 
parse_args(char * argv[],meta_options * flag_options,command_flags * flags)582 int parse_args(char *argv[], meta_options *flag_options, command_flags *flags)
583 {
584 	FILE *fp;
585 	char *filename;
586 	int error_count = 0;
587 
588 	fp = stdin;
589 	filename = "stdin";
590 
591 	do {
592 		if (*argv) {
593 			if (strcmp(*argv, "-") == 0) {
594 				fp = stdin;
595 			} else if ((fp = fopen(*argv, "r")) == NULL) {
596 				fprintf(stderr, "mp3_check: %s %s\n", *argv,
597 					strerror(errno));
598 				++argv;
599 				filename = *argv++;
600 				continue;
601 			}
602 			filename = *argv++;
603 		}
604 
605 		if (!scan_file(fp, filename, flag_options, flags))
606 			error_count++;
607 
608 		if (fp != stdin)
609 			fclose(fp);
610 
611 	} while (*argv);
612 
613 	if (error_count > 0)
614 		return (FAIL);
615 	else
616 		return (PASS);
617 }
618 
move_to_next_frame(char * possible_mp3_tag,frame_info * mp3_i,gen_info * file_info,command_flags * flags,FILE * fp)619 static inline int move_to_next_frame(char *possible_mp3_tag,
620 				     frame_info *mp3_i, gen_info *file_info,
621 				     command_flags *flags, FILE *fp)
622 {
623 	int counter = 0;
624 	int unk_char = 0;
625 
626 	const int print_to_stdout = !flags->ssflag && (flags->sflag
627 						       || flags->fflag);
628 	int bytes_to_read = 0;
629 
630 	/* Here, mp3_check adjusts for the CRC checksum */
631 	if (mp3_i->PROT_BIT)
632 		/* move past the header (4 bytes) and CRC (2 bytes) = 6 */
633 		bytes_to_read = mp3_i->FRAME_LENGTH - 6;
634 	else
635 		/* move past the header (4 bytes) since no CRC */
636 		bytes_to_read = mp3_i->FRAME_LENGTH - 4;
637 
638 	/*
639 	 * This for loop cycles though the frame data. All I want to know is
640 	 * if the frame header is valid or not... basically, I know I got a
641 	 * good frame, I just want to hurry to the next one.
642 	 */
643 	if (fp != stdin && !print_to_stdout && !flags->iflag) {
644 
645 		if (!fseek(fp, bytes_to_read, SEEK_CUR)) {
646 			file_info->file_pos += bytes_to_read;
647 			file_info->byte_count += bytes_to_read;
648 
649 			return (PASS);
650 		}
651 	}
652 
653 	/*
654 	 * Walk though the contents by hand if we've got to print the
655 	 * contents, or if we're reading from stdin, or if something went
656 	 * wrong with fseek().
657 	 */
658 	for (counter = 0; counter < bytes_to_read; counter++) {
659 		if ((unk_char = getc(fp)) != EOF) {
660 
661 			++file_info->file_pos;
662 			++file_info->byte_count;
663 
664 			/*
665 			 * This is to keep track of the id3 tag that is at
666 			 * the end of mp3s.
667 			 */
668 			if (flags->iflag)
669 				rotate_char_array(possible_mp3_tag, &unk_char,
670 						  file_info);
671 
672 			/*
673 			 * Since I know I am in a good frame, print out the
674 			 * data. When I am in this function, it doesnt matter
675 			 * if the fflag is set.
676 			 */
677 			if (print_to_stdout)
678 				printf("%c", unk_char);
679 
680 
681 		} else {
682 			return (FAIL);
683 			break;
684 		}
685 	}
686 
687 	return (PASS);
688 }
689 
get_char_from_file(FILE * fp,unsigned int * header_value,gen_info * file_info,command_flags * flags,char * possible_mp3_tag)690 static int get_char_from_file(FILE *fp, unsigned int *header_value,
691 			      gen_info *file_info, command_flags *flags,
692 			      char *possible_mp3_tag)
693 {
694 	int step_char = 0;
695 
696 	if ((step_char = getc(fp)) != EOF) {
697 		/*
698 		 * This keeps the 32 bit header, and rotates out the oldest,
699 		 * and adds a new one.
700 		 */
701 		*header_value = (*header_value << 8) + step_char;
702 
703 		++file_info->file_pos;
704 		++file_info->byte_count;
705 
706 		/*
707 		 * This section keeps track of the last 128 Bytes of the stream
708 		 * to later check for mp3 tags.
709 		 */
710 		if (flags->iflag)
711 			rotate_char_array(possible_mp3_tag, &step_char,
712 					  file_info);
713 
714 		return (PASS);
715 	} else
716 		return (FAIL);
717 }
718 
check_vbr_and_time(frame_info * mp3_i,vbr_data * vbr_info,gen_info * file_info)719 static int check_vbr_and_time(frame_info *mp3_i, vbr_data *vbr_info,
720 			      gen_info *file_info)
721 {
722 	/*
723 	 * Lets get the time of this frame, and add it to the total length of
724 	 * the mp3 file
725 	 */
726 	file_info->time_in_seconds +=
727 	    (mp3_i->SAMPLES_PER_FRAME * 1.0) / (mp3_i->SAMPLE_FREQ * 1.0);
728 
729 	/* Time to do some nifty VBR checking. */
730 	if (vbr_info->high_rate < mp3_i->BIT_RATE)
731 		vbr_info->high_rate = mp3_i->BIT_RATE;
732 
733 	if ((mp3_i->BIT_RATE < vbr_info->low_rate)
734 	    || (vbr_info->low_rate == 0)) vbr_info->low_rate = mp3_i->BIT_RATE;
735 
736 
737 	/* Get a running total for division at the end. */
738 	vbr_info->sum_rate += mp3_i->BIT_RATE;
739 
740 	return (TRUE);
741 }
742