-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmp3.rb
More file actions
109 lines (85 loc) · 1.92 KB
/
mp3.rb
File metadata and controls
109 lines (85 loc) · 1.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#mp3 id3 tag reader
require './mp3_frame_ids.rb'
class ID3
attr_accessor :mp3_file, :song_title, :album_title, :artist, :track, :year, :song_length, :version, :flags, :path
def initialize(file)
@file = file
header = get_tag_header
tag_size = parse_header(header)
tag = get_tag(tag_size)
get_frames(tag)
set_file
set_flag(header[5])
end
def get_tag_header
header = Array.new
File.open(@file, "r") do |f|
f.each_byte.with_index do |ch, index|
case index
when 0..4
header << ch.chr
when 5
header << ch.to_s(2)[0..2]
when 6..9
if ch > 128
raise "Header error: reported tag size too large"
end
header << ch.to_s(2).rjust(7,"0")
end
return header if index > 10
end
end
end
def get_tag(size)
tag = ""
File.open(@file, "r") do |f|
f.each_byte.with_index do |ch,index|
tag << ch
return tag if index > size
end
end
end
def parse_header(header)
check_ID3(header)
check_ver(header)
return tag_size(header[6..9])
end
def check_ID3(header)
unless header[0..2].join == "ID3"
raise "No ID3 tag on the file"
end
end
def check_ver(header)
if header[3..4].join(' ') == "\x03 \x00"
@version = "2.3"
else
raise "Incorrect ID3 version - require v2.3"
end
end
def tag_size(header6_9)
header6_9.join.to_i(2)
end
def get_frames(tag)
FRAMES.keys.each do |type|
if loc = (/#{type}/ =~ tag)
fr_size_arr = tag[loc+4,4].bytes
fr_size_str=""
fr_size_arr.each do |ch|
fr_size_str<<ch.to_s(2).rjust(8,"0")
end
fr_size = fr_size_str.to_i(2)
frm = tag[loc+10,fr_size].gsub(/\u0000/,"")
eval("self.#{FRAMES[type]} = frm")
else
eval("self.#{FRAMES[type]} = nil")
end
end
end
def set_file
@path = File.dirname(@file)
@mp3_file = File.basename(@file)
end
def set_flag(flags)
@flags = flags
end
end