Reading and Writing MP3 ID3v1 and ID3v2 Tags

Two classes to simplify MP3 Tag handling

Tag Reader/Writer Sample Application

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:

  • ID3v2 subversion 2 Frame header
    Private Type ID3V22HDR
       frameName1 As String * 3      ' 3
       frameSize1 As Byte            ' 4
       frameSize2 As Byte            ' 5
       frameSize3 As Byte            ' 6
    End Type
    
  • ID3v2 subversion 3 or 4 Frame header Private Type ID3V23HDR sFrameName As String * 4 ' 4 lSize As Long ' 8 bPad1 As Byte ' 10 bPad2 As Byte ' 12 End Type

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