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?
@filename = filename
@hastag1 = false
@tag1 = {}
@tag1.extend(HashKeys)
@tag2 = ID3v2.new
@file = File.new(filename, "rb")
@file.extend(Mp3FileMethods)
begin
parse_tags
@tag1_orig = @tag1.dup
@tag = {}
if hastag1?
@tag = @tag1.dup
end
if hastag2?
@tag = {}
V1_V2_TAG_MAPPING.each do |key1, key2|
t2 = @tag2[key2]
next unless t2
@tag[key1] = t2.is_a?(Array) ? t2.first : t2
if key1 == "tracknum"
val = @tag2[key2].is_a?(Array) ? @tag2[key2].first : @tag2[key2]
@tag[key1] = val.to_i
end
end
end
@tag.extend(HashKeys)
@tag_orig = @tag.dup
found = false
5.times do
head = find_next_frame()
head.extend(NumericBits)
@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"
puts "Xing header (VBR) detected" if $DEBUG
flags = @file.get32bits
@streamsize = @frames = 0
flags[1] == 1 and @frames = @file.get32bits
flags[2] == 1 and @streamsize = @file.get32bits
puts "#{@frames} frames" if $DEBUG
raise(Mp3InfoError, "bad VBR header") if @frames.zero?
@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
@streamsize = @file.stat.size - (@hastag1 ? TAGSIZE : 0) - (@tag2.valid? ? @tag2.io_position : 0)
@length = ((@streamsize << 3)/1000.0)/@bitrate
if @tag2["TLEN"]
tlen = (@tag2["TLEN"].is_a?(Array) ? @tag2["TLEN"].last : @tag2["TLEN"]).to_i/1000
percent_diff = ((@length.to_i-tlen)/tlen.to_f)
if percent_diff.abs > 0.05
@vbr = true
@length = @tag2["TLEN"].to_i/1000
@bitrate = (@streamsize / @bitrate) >> 10
end
end
end
ensure
@file.close
end
end