[SOLUTION] ID3 Tags (#136)

$genres = [“Blues”,“Classic Rock”,“Country”,“Dance”,“Disco”,“Funk”,
“Grunge”,“Hip-Hop”,“Jazz”,“Metal”,“New Age”,“Oldies”,
“Other”,“Pop”,“R&B”,“Rap”,“Reggae”,“Rock”,“Techno”,
“Industrial”,“Alternative”,“Ska”,“Death Metal”,“Pranks”,
“Soundtrack”,“Euro-Techno”,“Ambient”,“Trip-Hop”,“Vocal”,
“Jazz+Funk”,“Fusion”,“Trance”,“Classical”,“Instrumental”,
“Acid”,“House”,“Game”,“Sound Clip”,“Gospel”,“Noise”,
“AlternRock”,“Bass”,“Soul”,“Punk”,“Space”,“Meditative”,
“Instrumental Pop”,“Instrumental Rock”,“Ethnic”,“Gothic”,
“Darkwave”,“Techno-Industrial”,“Electronic”,“Pop-Folk”,
“Eurodance”,“Dream”,“Southern Rock”,“Comedy”,“Cult”,“Gangsta”,
“Top 40”,“Christian Rap”,“Pop/Funk”,“Jungle”,
“Native American”,“Cabaret”,“New Wave”,“Psychadelic”,“Rave”,
“Showtunes”,“Trailer”,“Lo-Fi”,“Tribal”,“Acid Punk”,
“Acid Jazz”,“Polka”,“Retro”,“Musical”,“Rock & Roll”,
“Hard Rock”,“Folk”,“Folk-Rock”,“National Folk”,“Swing”,
“Fast Fusion”,“Bebob”,“Latin”,“Revival”,“Celtic”,“Bluegrass”,
“Avantgarde”,“Gothic Rock”,“Progressive Rock”,
“Psychedelic Rock”,“Symphonic Rock”,“Slow Rock”,“Big Band”,
“Chorus”,“Easy Listening”,“Acoustic”,“Humour”,“Speech”,
“Chanson”,“Opera”,“Chamber Music”,“Sonata”,“Symphony”,
“Booty Bass”,“Primus”,“Porn Groove”,“Satire”,“Slow Jam”,
“Club”,“Tango”,“Samba”,“Folklore”,“Ballad”,“Power Ballad”,
“Rhythmic Soul”,“Freestyle”,“Duet”,“Punk Rock”,“Drum Solo”,
“A capella”,“Euro-House”,“Dance Hall”]

file = File.new(ARGV[0].chomp)

tag, song, artist, album, year, comment, genre =
file.read[-128…-1].unpack(“A3A30A30A30A4A30C”)

file.close

track = nil

genre = $genres[genre.to_i]

if comment[28] == 0
track = comment[29]
comment = comment[0…27]
end

if tag == “TAG”
[:song, :artist, :album, :track, :year, :comment, :genre].each do
|sym|
puts sym.to_s.capitalize + ": " + eval(sym.id2name).to_s
end
else
puts “Did not find ID3v1 tags.”
end

----- Original Message ----
From: Ruby Q. [email protected]
To: ruby-talk ML [email protected]
Sent: Friday, August 24, 2007 7:34:47 AM
Subject: [QUIZ] ID3 Tags (#136)

The three rules of Ruby Q.:

  1. Please do not post any solutions or spoiler discussion for this quiz
    until
    48 hours have passed from the time on this message.

  2. Support Ruby Q. by submitting ideas as often as you can:

http://www.rubyquiz.com/

  1. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps
everyone
on Ruby T. follow the discussion. Please reply to the original quiz
message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

The MP3 file format, didn’t provide any means for including metadata
about the
song. ID3 tags were invented to solve this problem.

You can tell if an MP3 file includes ID3 tags by examining the last 128
bytes of
the file. If they begin with the characters TAG, you have found an ID3
tag.
The format of the tag is as follows:

TAG song album artist comment year genre

The spaces above are just for us humans. The actual tags are
fixed-width fields
with no spacing between them. Song, album, artist, and comment are 30
bytes
each. The year is four bytes and the genre just gets one, which is an
index
into a list of predefined genres I’ll include at the end of this quiz.

A minor change was later made to ID3 tags to allow them to include track
numbers, creating ID3v1.1. In that format, if the 29th byte of a
comment is
null and the 30th is not, the 30th byte is an integer representing the
track
number.

Later changes evolved ID3v2 which is a scary beast we won’t worry about.

This week’s Ruby Q. is to write an ID3 tag parser. Using a library is
cheating. Roll up your sleeves and parse it yourself. It’s not hard at
all.

If you don’t have MP3 files to test your solution on, you can find some
free
files at:

http://www.mfiles.co.uk/mp3-files.htm

Here’s the official genre list with some extensions added by Winamp:

Blues
Classic Rock
Country
Dance
Disco
Funk
Grunge
Hip-Hop
Jazz
Metal
New Age
Oldies
Other
Pop
R&B
Rap
Reggae
Rock
Techno
Industrial
Alternative
Ska
Death Metal
Pranks
Soundtrack
Euro-Techno
Ambient
Trip-Hop
Vocal
Jazz+Funk
Fusion
Trance
Classical
Instrumental
Acid
House
Game
Sound Clip
Gospel
Noise
AlternRock
Bass
Soul
Punk
Space
Meditative
Instrumental Pop
Instrumental Rock
Ethnic
Gothic
Darkwave
Techno-Industrial
Electronic
Pop-Folk
Eurodance
Dream
Southern Rock
Comedy
Cult
Gangsta
Top 40
Christian Rap
Pop/Funk
Jungle
Native American
Cabaret
New Wave
Psychadelic
Rave
Showtunes
Trailer
Lo-Fi
Tribal
Acid Punk
Acid Jazz
Polka
Retro
Musical
Rock & Roll
Hard Rock
Folk
Folk-Rock
National Folk
Swing
Fast Fusion
Bebob
Latin
Revival
Celtic
Bluegrass
Avantgarde
Gothic Rock
Progressive Rock
Psychedelic Rock
Symphonic Rock
Slow Rock
Big Band
Chorus
Easy Listening
Acoustic
Humour
Speech
Chanson
Opera
Chamber Music
Sonata
Symphony
Booty Bass
Primus
Porn Groove
Satire
Slow Jam
Club
Tango
Samba
Folklore
Ballad
Power Ballad
Rhythmic Soul
Freestyle
Duet
Punk Rock
Drum Solo
A capella
Euro-House
Dance Hall

def fileTail (file, offset)
f=File.new(file)
f.seek(-offset,IO::SEEK_END)
f.read
end

class ID3Tag
GENRES=[“Blues”,“Classic
Rock”,“Country”,“Dance”,“Disco”,“Funk”,“Grunge”,“Hip-Hop”,
“Jazz”,“Metal”,“New
Age”,“Oldies”,“Other”,“Pop”,“R&B”,“Rap”,“Reggae”,“Rock”,
“Techno”,“Industrial”,“Alternative”,“Ska”,“Death
Metal”,“Pranks”,“Soundtrack”,
“Euro-Techno”,“Ambient”,“Trip-Hop”,“Vocal”,“Jazz+Funk”,“Fusion”,“Trance”,
“Classical”,“Instrumental”,“Acid”,“House”,“Game”,“Sound
Clip”,“Gospel”,
“Noise”,“AlternRock”,“Bass”,“Soul”,“Punk”,“Space”,“Meditative”,
“Instrumental Pop”,“Instrumental
Rock”,“Ethnic”,“Gothic”,“Darkwave”,
“Techno-Industrial”,“Electronic”,“Pop-Folk”,“Eurodance”,“Dream”,
“Southern Rock”,“Comedy”,“Cult”,“Gangsta”,“Top 40”,“Christian
Rap”,“Pop/Funk”,
“Jungle”,“Native American”,“Cabaret”,“New
Wave”,“Psychadelic”,“Rave”,
“Showtunes”,“Trailer”,“Lo-Fi”,“Tribal”,“Acid Punk”,“Acid
Jazz”,“Polka”,
“Retro”,“Musical”,“Rock & Roll”,“Hard
Rock”,“Folk”,“Folk-Rock”,
“National Folk”,“Swing”,“Fast
Fusion”,“Bebob”,“Latin”,“Revival”,“Celtic”,
“Bluegrass”,“Avantgarde”,“Gothic Rock”,“Progressive
Rock”,“Psychedelic Rock”,
“Symphonic Rock”,“Slow Rock”,“Big Band”,“Chorus”,“Easy
Listening”,“Acoustic”,
“Humour”,“Speech”,“Chanson”,“Opera”,“Chamber
Music”,“Sonata”,“Symphony”,
“Booty Bass”,“Primus”,“Porn Groove”,“Satire”,“Slow
Jam”,“Club”,“Tango”,
“Samba”,“Folklore”,“Ballad”,“Power Ballad”,“Rhythmic
Soul”,“Freestyle”,
“Duet”,“Punk Rock”,“Drum Solo”,“A capella”,“Euro-House”,“Dance
Hall”]
attr_reader :title, :artist, :album, :year, :comment, :genre, :track
def initialize fname
tag,@title,@artist,@album,@year,@comment,@genre=fileTail(fname,128).unpack
“A3A30A30A30A4A30C”
raise “No ID3 Info” if tag!=‘TAG’
s_com,flag,[email protected] “A28CC”
if flag==0 and track!=0
@comment=s_com
@track=track
end
@genre=GENRES[@genre]
@genre=“Unknown” if !@genre
end
end

p ID3Tag.new(ARGV[0])

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs