#!/usr/bin/perl -w
use strict;
my ($bitrate,$tmp,@tmp);
die "usage: $0 <file.mp3>\n" if($#ARGV);
my $filesize=(-s $ARGV[0]);
sub b2d {my $b=$_[0];my $a=0;while($b =~ s/^(.)//){$a*=2;$a+=1 if($1);}$a}
if(open(FILE,"<$ARGV[0]")) {
   my $data="";
   while(1) {
      die "read: $!" unless(read FILE,$data,10);
      if($data =~ /^ID3/s) {
         printf "ID3v%d",unpack("c",substr($data,3,1));
         $tmp=unpack("c",substr($data,4,1));
         print ".$tmp" if($tmp);
         print " header:";
         $tmp=unpack("B32",substr($data,6,4));
         $tmp =~ s/^(.)(.{7})(.)(.{7})(.)(.{7})(.)(.{7})$/$2$4$6$8/ or die "regex failed";
         unless("$1$3$5$7" eq "0000") {
            print " (invalid size)\n";
            last;
         }
         $tmp=unpack("N",pack("B32","0000$tmp"));
         print " (".(10+$tmp)." bytes)\n";
         die "read: $!" unless(read FILE,$data,$tmp,10);
      } elsif($data =~ /^RIFF/s) {
         die "read: $!" unless(read FILE,$data,30,10);
         $tmp=unpack("c",substr($data,16,1))+256*unpack("c",substr($data,17,1));
         print "RIFF header: (".(40+$tmp)." bytes)\n";
         die "read: $!" unless(read FILE,$data,$tmp,40);
      } else {
         print "MPEG header: ";
         my $data=unpack("B32",substr($data,0,4));
         my $bitrate;
         my $a=b2d(substr($data,0,11));
         unless($a==2047) {
            print "(invalid header)\n";
            last;
         }
         my $b=b2d(substr($data,11,2));
         my $c=b2d(substr($data,13,2));
         my $d=b2d(substr($data,15,1));
         my $e=b2d(substr($data,16,4));
         my $f=b2d(substr($data,20,2));
         my $g=b2d(substr($data,22,1));
         my $h=b2d(substr($data,23,1));
         my $i=b2d(substr($data,24,2));
         my $j=b2d(substr($data,26,2));
         my $k=b2d(substr($data,28,1));
         my $l=b2d(substr($data,29,1));
         my $m=b2d(substr($data,30,2));
         $data="";
         $data.=("MPEG Version 2.5","unknown version","MPEG Version 2","MPEG Version 1")[$b]." ";
         $data.=("unknown layer","Layer III","Layer II","Layer I")[$c]."\n";
         $data.=("CRC present (unverified)","CRC not present")[$d]."\n";
         my @a=(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,-1);
         @a=(0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,-1) if($c==3);
         if($b==3) {
            @a=(0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1) if($c==1);
            @a=(0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,-1) if($c==2);
            @a=(0,32,64,96,128,160,192,224,256,288,320,352,384,416,488,-1) if($c==3);
         }
         $data.=($bitrate=$a[$e])."kbps, ";
         $data.=(11.025,12,8,-1,0,0,0,0,22.05,24,16,-1,44.1,48,32,-1)[4*$b+$f]."kHz\n";
         $data.=("Not frame padded","Frame padded")[$g]."\n";
         $data.=("Private bit not set","Private bit set")[$h]."\n";
         $data.=("Stereo","Joint stereo","Dual channel","Single channel (mono)")[$i];
         if($i==1) {
            if($c==1) {
               $data.=" (intensity stereo)" if($j&2);
               $data.=" (MS stereo)" if($j&1);
            } else {
               $data.=" (bands ".(4,8,12,16)[$j]." to 31)";
            }
         }
         $data.="\n";
         $data.=("Not copyrighted","Copyrighted")[$k]."\n";
         $data.=("Copy of original media","Original media")[$l]."\n";
         $data.=("No","50/15 ms","Unknown","CCIT J.17")[$m]." emphasis\n";
         $tmp=int($filesize*8/($bitrate*1000)+.5);
         $tmp=int($tmp/60).":".substr("0".($tmp%60),-2);
         $data.="Run time: $tmp\n";
         print $data;
         last;
      }
   }
   close(FILE);
} else {
   print "(unopenable)\n";
}

0;
