Reading and Writing MP3 ID3v1 and ID3v2 Tags
Two classes to simplify MP3 Tag handling
This article describes the MP3 ID3v1 and ID3v2 tags and provides a sample application which can
read and write both types from MP3 files, along with two reusable classes wrapping up the
tag functionality.
About MP3 Tags
The MP3 file standard includes specifications for tags, known as ID3 tags, which
allow you to store information within the MP3 file about the track's title, artist and so on.
If you're running Windows XP, you will see that there is a Shell Extension to
read these tags, which allows you to read the tags in the Properties dialog for the file,
or to see them in Explorer.
There are two types of MP3 tags: the v1 original version, which is rather limited, and
the v2 tags, which are much more sophisticated.
ID3v1 Tags
The ID3v1 tag is found at the end of an MP3 file and has a fixed number of fields and size.
The structure of the tag is as follows:
Private Type MP3ID3V1Tag
Tag As String * 3 '-- 03 = "TAG"
Title As String * 30 '-- 33
Artist As String * 30 '-- 63
Album As String * 30 '-- 93
Year As String * 4 '-- 97
Comment As String * 30 '-- 127
Genre As Byte '-- 128
End Type
Note that v1.1 of the ID3v1 specification allows the last two bytes of the Comment tag
to be used to store the track number. Byte 29 is always set to 0 in this case, and Byte 30
stores the track number itself.
Checking if an MP3 file contains an ID3v1 tag is a simple matter of rewinding 128 bytes from the
end and checking if the bytes read "TAG". If they do, then the rest of the bytes are the tag
itself. Reading and writing the tag is simple: if its already there, then you just fill in the
structure and then write it over the last 128 bytes of the file. If the tag isn't there, then
just append a structure to the end of the file.
For information, a list of known Genre bytes is given at the end of this article.
The cMP3ID3v1 class provided with the download provides a wrapper for reading and
writing this tag. Properties and methods are:
-
MP3File - Gets/sets the MP3 file to work on.
-
HasID3v1Tag - True if the MP3 file has an ID3v1 Tag, False otherwise.
-
Title - Gets/sets the title. Use Update to save to the file.
-
Album - Gets/sets the album. Use Update to save to the file.
-
Year - Gets/sets the year. Use Update to save to the file.
-
Genre - Gets/sets the genre. Use Update to save to the file.
-
GenreName(genre As Byte) - Gets the genre name for the specified byte.
-
Comments - Gets/sets the comment. Use Update to save to the file.
-
Track - Gets/sets the track number. Use Update to save to the file.
-
Update - Updates the MP3 file with the current values.
All fields will be truncated so they are no longer than the length allowed in
the structure prior to saving.
ID3v2 Tags
The ID3v2 tag is more flexible and hence more difficult to work with. An ID3v2 tag has
a signature code of "ID3x" where x is the sub-version number of the tag. Typically ID3v2
tags are found at the beginning of an MP3 file but this is not an absolute restriction.
What happens next depends on the subversion of the ID3v2 tag. As far as I can tell, there
have been three versions so far: 2,3 and 4.
Following the ID3v2 signature there are two reserved bytes and then 4 bytes containing the
size of the ID3v2 tag. Note that all sizes appear in the opposite byte-order to Win32, so
to read the actual length you need to swap the byte order. Once the size has been determined
then anywhere after the header until the end of the tag there can be an ID3v2 tag Frame. The
structure of a Frame header depends on the sub-version of ID3v2, but always encodes the
name of the frame followed by its length in bytes and optionally some padding:
Typical frame names used in the more modern ID3v2 tags are as follows (with the
subversion 2 equivalent in brackets afterwards where I've found details):
-
PCNT - Play counter
-
TRCK - Track (ID3v2.2: TRK)
-
TENC - Encoded by (ID3v2.2: TEN)
-
WXXX - Link to
-
TCOP - Copyright
-
TOPE - Original artist
-
TCOM - Composer
-
TCON - Genre (ID3v2.2: TCO)
-
COMM - Comment (ID3v2.2: COM)
-
TYER - Year (ID3v2.2: TYE)
-
TIT2 - Title (ID3v2.2: TT2)
-
TRCK - Track number (ID3v2.2: TRK)
-
TPE1 - Artist (ID3v2.2: TP1)
-
TALB - Album (ID3v2.2: TAL)
-
WOAF - Audio URL
-
WOAR - Artist URL
-
WCOM - Buy URL
-
USLT - Lyrics
It is possible to have more than one of each tag. For example, the COMM frame
is used in MusicMatch to allow you tag Preferences, Notes, Bios, Moods, Tempos and other such
trivial information. A different COMM frame is written out for each of these with
the data within the COMM frames divided into a header (such as MusicMatch_Bio) followed
by a null character and then the data.
Clearly it is more difficult to read and write this member. If the file doesn't contain
an ID3v2 tag, or the ID3v2 is too short for the new data, then the MP3 data has to be shifted
up until it can be read in the result. I also noted that when writing some text frames,
an additional null character is needed prior to the text otherwise the data isn't read
correctly. The frames affected are Lyrics (USLT), Comments (COMM) and LinkTo (WXXX).
The cMP3ID3v2 class provided with the download wraps up reading and writing this tag.
There are two ways of using the class. For access to any of the standard frames given above,
there are corresponding Property Gets/Lets. This does not allow you to create multiple COMM
frames, though, so you can also work directly with the collection of frames.
File Properties and Methods
-
MP3File - Gets/sets the MP3 file to work on.
-
HasID3v2Tag - True if the MP3 file has an ID3v2 Tag, False otherwise.
-
Update - Updates the MP3 file with the current values.
Standard Tag Properties and Methods
Setting any of these properties will mean there will be only one occurrence of
the relevant frame. For example, if you set the Comments property on
an MP3 file that had multiple COMM frames, the old COMM frames
are cleared and replaced with the new comment.
-
Title - Gets/sets the title.
-
Album - Gets/sets the album.
-
Year - Gets/sets the year.
-
Comments - Gets/sets the comment. Use Update to save to the file.
-
Genre - Gets/sets the genre byte.
-
GenreName(genre As Byte) - Gets the genre name for the specified byte.
-
OtherGenreName - Gets sets the genre name.
-
Track - Gets/sets the track number.
-
Copyright - Gets/sets the copyright.
-
OriginalArtist - Gets/sets the original artist.
-
LinkTo - Gets/sets the LinkTo URL.
-
Lyrics - Gets/sets the lyrics.
-
EncodedBy - Gets/sets the encoder.
-
ArtistURL - Gets/sets the artist URL.
-
BuyURL - Gets/sets the Buy URL.
-
AudioURL - Gets/sets the Audio URL.
Frame Collection Properties and Methods
-
FrameCount - Number of frames in the tag.
-
Frame(index) - Gets the frame name (e.g. "COMM") for the specified frame index.
-
RemoveFrame(frame) - Removes all the frames with the specified name (e.g. "COMM") or frame index.
-
TagsInFrame(frame) - Returns the number of actual occurrences of the specified frame.
-
AddTag(frame, tag) - Adds a new instance of the specified frame.
-
RemoveTag(frame, tagIndex) - Removes the specified instance of a frame.
Genre Bytes
-
34: Acid
-
74: Acid Jazz
-
73: Acid Punk
-
99: Acoustic
-
40: Alt.Rock
-
20: Alternative
-
26: Ambient
-
145: Anime
-
90: Avant Garde
-
116: Ballad
-
41: Bass
-
135: Beat
-
85: Bebob
-
96: Big Band
-
138: Black Metal
-
89: Blue Grass
-
0: Blues
-
107: Booty Bass
-
132: Brit Pop
-
65: Cabaret
-
88: Celtic
-
104: Chamber Music
-
102: Chanson
-
97: Chorus
-
136: Christian Gangsta Rap
-
61: Christian Rap
-
141: Christian Rock
-
1: Classic Rock
-
32: Classical
-
112: Club
-
128: Club - House
-
57: Comedy
-
140: Contemporary Christian
-
2: Country
-
139: Crossover
-
58: Cult
-
3: Dance
-
125: Dance Hall
-
50: Darkwave
-
22: Death Metal
-
4: Disco
-
55: Dream
-
127: Drum & Bass
-
122: Drum Solo
-
120: Duet
-
98: Easy Listening
-
52: Electronic
-
48: Ethnic
-
54: Eurodance
-
124: Euro - House
-
25: Euro - Techno
-
84: Fast Fusion
-
80: Folk
-
81: Folk / Rock
-
115: Folklore
-
119: Freestyle
-
5: Funk
-
30: Fusion
-
36: Game
-
59: Gangsta Rap
-
126: Goa
-
38: Gospel
-
49: Gothic
-
91: Gothic Rock
-
6: Grunge
-
79: Hard Rock
-
129: Hardcore
-
137: Heavy Metal
-
7: Hip Hop
-
35: House
-
100: Humour
-
131: Indie
-
19: Industrial
-
33: Instrumental
-
46: Instrumental Pop
-
47: Instrumental Rock
-
8: Jazz
-
29: Jazz - Funk
-
146: JPop
-
63: Jungle
-
86: Latin
-
71: Lo - fi
-
45: Meditative
-
142: Merengue
-
9: Metal
-
77: Musical
-
82: National Folk
-
64: Native American
-
133: Negerpunk
-
10: New Age
-
66: New Wave
-
39: Noise
-
11: Oldies
-
103: Opera
-
12: Other
-
75: Polka
-
134: Polsk Punk
-
13: Pop
-
62: Pop / Funk
-
53: Pop / Folk
-
109: Pr0n Groove
-
117: Power Ballad
-
23: Pranks
-
108: Primus
-
92: Progressive Rock
-
67: Psychedelic
-
93: Psychedelic Rock
-
43: Punk
-
121: Punk Rock
-
14: R&B
-
15: Rap
-
68: Rave
-
16: Reggae
-
76: Retro
-
87: Revival
-
118: Rhythmic Soul
-
17: Rock
-
78: Rock 'n'Roll
-
143: Salsa
-
114: Samba
-
110: Satire
-
69: Showtunes
-
21: Ska
-
111: Slow Jam
-
95: Slow Rock
-
105: Sonata
-
42: Soul
-
37: Sound Clip
-
24: Soundtrack
-
56: Southern Rock
-
44: Space
-
101: Speech
-
83: Swing
-
94: Symphonic Rock
-
106: Symphony
-
147: Synth Pop
-
113: Tango
-
18: Techno
-
51: Techno - Industrial
-
130: Terror
-
144: Thrash Metal
-
60: Top 40
-
70: Trailer
-
31: Trance
-
72: Tribal
-
27: Trip Hop
-
28: Vocal
|