# File lib/mp3info.rb, line 330
  def initialize(filename)
    $stderr.puts("#{self.class}::new() does not take block; use #{self.class}::open() instead") if block_given?
    raise(Mp3InfoError, "empty file") unless File.stat(filename).size? #FIXME
    @filename = filename
    @hastag1, @hastag2 = false
    @tag = Hash.new
    @tag1 = Hash.new
    @tag2 = Hash.new

    @file = File.new(filename, "rb")
    parse_tags
    @tag_orig = @tag1.dup

    #creation of a sort of "universal" tag, regardless of the tag version
    if hastag2?
      h = { 
        "title"    => "TIT2",
        "artist"   => "TPE1", 
        "album"    => "TALB",
        "year"     => "TYER",
        "tracknum" => "TRCK",
        "comments" => "COMM",
        "genre"    => 255,
        "genre_s"  => "TCON"
      }

      h.each { |k, v| @tag[k] = @tag2[v] }

    elsif hastag1?
      @tag = @tag1.dup
    end


    ### extracts MPEG info from MPEG header and stores it in the hash @mpeg
    ###  head (fixnum) = valid 4 byte MPEG header
    
    found = false

    5.times do
      head = find_next_frame() 
      @mpeg_version = [2, 1][head[19]]
      @layer = LAYER[head.bits(18,17)]
      next if @layer.nil?
      @bitrate = BITRATE[@mpeg_version-1][@layer-1][head.bits(15,12)-1]
      @error_protection = head[16] == 0 ? true : false
      @samplerate = SAMPLERATE[@mpeg_version-1][head.bits(11,10)]
      @padding = (head[9] == 1 ? true : false)
      @channel_mode = CHANNEL_MODE[@channel_num = head.bits(7,6)]
      @copyright = (head[3] == 1 ? true : false)
      @original = (head[2] == 1 ? true : false)
      @vbr = false
      found = true
      break
    end

    raise(Mp3InfoError, "Cannot find good frame") unless found


    seek = @mpeg_version == 1 ? 
      (@channel_num == 3 ? 17 : 32) :       
      (@channel_num == 3 ?  9 : 17)

    @file.seek(seek, IO::SEEK_CUR)
    
    vbr_head = @file.read(4)
    if vbr_head == "Xing"
      flags = @file.get32bits
      @streamsize = @frames = 0
      flags[1] == 1 and @frames = @file.get32bits
      flags[2] == 1 and @streamsize = @file.get32bits 
      # currently this just skips the TOC entries if they're found
      @file.seek(100, IO::SEEK_CUR) if flags[0] == 1
      @vbr_quality = @file.get32bits if flags[3] == 1
      @length = (26/1000.0)*@frames
      @bitrate = (((@streamsize/@frames)*@samplerate)/144) >> 10
      @vbr = true
    else
      # for cbr, calculate duration with the given bitrate
      @streamsize = @file.stat.size - (@hastag1 ? TAGSIZE : 0) - (@hastag2 ? @tag2["length"] : 0)
      @length = ((@streamsize << 3)/1000.0)/@bitrate
      if @tag2["TLEN"]
        # but if another duration is given and it isn't close (within 5%)
        #  assume the mp3 is vbr and go with the given duration
        tlen = (@tag2["TLEN"].to_i)/1000
        percent_diff = ((@length.to_i-tlen)/tlen.to_f)
        if percent_diff.abs > 0.05
          # without the xing header, this is the best guess without reading
          #  every single frame
          @vbr = true
          @length = @tag2["TLEN"].to_i/1000
          @bitrate = (@streamsize / @bitrate) >> 10
        end
      end
    end
  end