UltraID3Lib

Overview

What is UltraID3Lib?

UltraID3Lib is a fully object-oriented class library for the reading and editing of both ID3v1 and ID3v2 tags in MP3 files.  Reading of MPEG data, such as duration, bitrate, and frequency, is supported as well.  UltraID3Lib was written in Visual Basic .NET and is available as a .NET dll.

Terminology

Tag A section of an MP3 file containing data about the track.
Frame The portion of a ID3v2 Tag which contains a particular element of data (the Field) and its associated metadata.  For example, the Comments Frame not only contains the actual comments, but also contains a description of the comments, the language of the comments, and even the text encoding used to store the comments.
Field Generically refers to the significant values in either an ID3v1 or an ID3v2 tag.  ID3v1 tags only contain Fields, whereas ID3v2 tags contain Frames which contain the Fields and the Frame's metadata.
ID3 Version 1 A tag version which allows for a limited amount of fixed-width text fields.
ID3 Version 2 A tag version which allows for numerous types of data to be stored in an MP3, including text, numeric, and even binary information such as graphics.
ID3 The standard for encoding meta data into mp3 file

UltraID3 Class

The most important class in UltraID3Lib is the UltraID3 class.  This is the class used to read and write tag data.  It has the following properties to store data about a track:  Artist, Title, Album, Track Number, Year, and Genre.  The UltraID3 class also has an ID3v1Tag property and an ID3v23Tag which represents the two ID3 tag versions supported by UltraID3Lib.  The ID3v1Tag property and the ID3v23Tag property are themselves classes which also have Artist, Title, Album, Track Number, Year, and Genre properties.  The fields for each version can be accessed directly using the ID3v1Tag and the ID3v23Tag properties or they can be accessed using the "generic" properties of the UltraID3 class.  The generic properties of the UltraID3 class have different behaviors depending on whether a write or a read is done.  In general, preference is given to ID3v23Tag over ID3v1Tag in both reads and writes.  See charts below for details.

ID3v1 Tag Exists ID3v2 Tag Exists Tag Version From Which Values Are Read Tag Version To Which Values Are Written
No No N/A ID3v23Tag
Yes NoID3v1Tag ID3v1Tag
NoYes ID3v23TagID3v23Tag
Yes Yes ID3v23Tag ID3v1Tag and ID3v23Tag

 

The Read method will open the specified file, search for the ID3 version 1 tag and the ID3 version 2 tag, parse the tags found, and set the appropriate values in the ID3v1Tag and ID3v23Tag class properties.  After a read is performed, the UltraID3.ID3v1.FoundFlag and UltraID3.ID3v2.FoundFlag properties can be checked to verify if the corresponding tag was found in the file which was read.  The UltraID3.ID3v1.WriteFlag and UltraID3.ID3v2.WriteFlag properties control whether the corresponding tag is written when the Write method is called.  When a read is done, the WriteFlag values are defaulted to the corresponding FoundFlag.  For example, if a file has an ID3 version 2 tag, both the ID3v23Tag.FoundFlag and the ID3v23Tag.WriteFlag will initially be set to True after a read of the file.

ID3 v2.3 Frames

There are seventy-four individual frames specified in the ID3 v2.3 standard.  UltraID3Lib has a separate class for each frame with properties specific to the kind of data it stores.  When an ID3v23Tag property, such as Artist or Title, is used to get or set a value, the corresponding underlying Frame is actually used.  The UltraID3.ID3v23Tag.Frames.GetFrame method is used to retrieve Frames which can only have one instance in a Tag, whereas the UltraID3.ID3v23Tag.Frames.GetFrames method is used to retrieve Frames which can have multiple instances in a Tag.

Frame ID Frame Description Frame Class
AENC Audio encryption ID3AudioEncryptionFrame
APIC Attached picture ID3PictureFrame
COMM Comments ID3CommentsFrame
COMR Commercial frame ID3CommercialFrame
ENCR Encryption method registration ID3EncryptionMethodRegistrationFrame
EQUA Equalization ID3EqualizationFrame
ETCO Event timing codes ID3EventTimingCodesFrame
GEOB General encapsulated object ID3GeneralEncapsulatedObjectFrame
GRID Group identification registration ID3GroupIdentificationRegistrationFrame
IPLS Involved people list ID3InvolvedPeopleListFrame
LINK Linked information ID3LinkedInformationFrame
MCDI Music CD identifier ID3CompactDiscIdentifierFrame
MLLT MPEG location lookup table ID3MpegLocationLookupTableFrame
OWNE Ownership frame ID3OwnershipFrame
PRIV Private frame ID3PrivateFrame
PCNT Play counter ID3PlayCounterFrame
POPM Popularimeter ID3PopularimeterFrame
POSS Position synchronisation frame ID3PositionSychronizationFrame
RBUF Recommended buffer size ID3RecommendedBufferSizeFrame
RVAD Relative volume adjustment ID3RelativeVolumnAdjustmentFrame
RVRB Reverb ID3ReverbFrame
SYLT Synchronized lyric/text ID3SynchronizedLyricsFrame
SYTC Synchronized tempo codes ID3SynchronizedTempoCodesFrame
TALB Album/Movie/Show title ID3AlbumFrame
TBPM BPM (beats per minute) ID3BeatsPerMinuteFrame
TCOM Composer ID3ComposersFrame
TCON Content type ID3GenreFrame
TCOP Copyright message ID3CopyrightMessageFrame
TDAT Date ID3RecordingDayMonthFrame
TDLY Playlist delay ID3PlaylistDelayFrame
TENC Encoded by ID3EncodedByFrame
TEXT Lyricist/Text writer ID3LyricistFrame
TFLT File type ID3FileTypeFrame
TIME Time ID3RecordingDurationTimeFrame
TIT1 Content group description ID3ContentGroupDescriptionFrame
TIT2 Title/songname/content description ID3TitleFrame
TIT3 Subtitle/Description refinement ID3SubtitleFrame
TKEY Initial key ID3InitialKeyFrame
TLAN Language(s) ID3LanguagesFrame
TLEN Length ID3RecordingDurationMillisecondsFrame
TMED Media type ID3MediaTypeFrame
TOAL Original album/movie/show title ID3OriginalAlbumFrame
TOFN Original filename ID3OriginalFileNameFrame
TOLY Original lyricist(s)/text writer(s) ID3OriginalLyricistFrame
TOPE Original artist(s)/performer(s) ID3OriginalArtistFrame
TORY Original release year ID3OriginalYearFrame
TOWN File owner/licensee ID3OwnerFrame
TPE1 Lead performer(s)/Soloist(s) ID3ArtistFrame
TPE2 Band/orchestra/accompaniment ID3BandFrame
TPE3 Conductor/performer refinement ID3ConductorFrame
TPE4 Interpreted, remixed, or otherwise modified by ID3InterpretedByFrame
TPOS Part of a set ID3PartOfSetFrame
TPUB Publisher ID3PublisherFrame
TRCK Track number/Position in set ID3TrackNumFrame
TRDA Recording dates ID3RecordingDatesFrame
TRSN Internet radio station name ID3InternetRadioStationNameFrame
TRSO Internet radio station owner ID3InternetRadioStationOwnerFrame
TSIZ Size ID3SizeBytesFrame
TSRC ISRC (international standard recording code) ID3InternationalStandardRecordingCodeFrame
TSSE Software/Hardware and settings used for encoding ID3EncoderSettingsFrame
TYER Year ID3YearFrame
TXXX User defined text information frame ID3UserDefinedTextFrame
UFID Unique file identifier ID3UniqueFileIDFrame
USER Terms of use ID3TermsOfUseFrame
USLT Unsychronized lyric/text transcription ID3UnsynchedLyricsFrame
WCOM Commercial information ID3CommercialInformationWebAddressFrame
WCOP Copyright/Legal information ID3CopyrightInformationWebAddressFrame
WOAF Official audio file webpage ID3OfficialAudioFileWebAddressFrame
WOAR Official artist/performer webpage ID3OfficialArtistWebAddressFrame
WOAS Official audio source webpage ID3OfficialAudioSourceWebAddressFrame
WORS Official internet radio station homepage ID3OfficialInternetRadioStationWebAddressFrame
WPAY Payment ID3PaymentWebAddressFrame
WPUB Publishers official webpage ID3PublisherWebAddressFrame

 

Sample Code (VB.NET)

 Dim TrackFileName As String = "Powderfinger - My Happiness.mp3"

'Create a new instance of the main UltraID3 class
Dim TestUltraID3 As New UltraID3

Try

   'Read the track file
   TestUltraID3.Read(TrackFileName)

   'Display a single string representation of the common ID3 fields
   MsgBox(TestUltraID3.ToString)

   'Display the Title, letting UltraID3 determine the appropriate tag source
   MsgBox(TestUltraID3.Title)

   'Check to see if the ID3v1 tag was found
   If TestUltraID3.ID3v1Tag.FoundFlag Then

      'Display the Title property of the ID3v1Tag directly
      MsgBox(TestUltraID3.ID3v1Tag.Title)

   End If

   'Check to see if the ID3v23 tag was found
   If TestUltraID3.ID3v23Tag.FoundFlag Then

      'Display the Title property of the ID3v23Tag directly
      MsgBox(TestUltraID3.ID3v23Tag.Title)

      'Retrieve the ID3TitleFrame, if any
      Dim MyID3TitleFrame As ID3TitleFrame = CType(TestUltraID3.ID3v23Tag.Frames.GetFrame(SingleInstanceFrameTypes.Title), ID3TitleFrame)

      'Check to see if the ID3TitleFrame exists
      If Not MyID3TitleFrame Is Nothing Then

         'Display the Title property of the ID3TitleFrame
         MsgBox(MyID3TitleFrame.Title)

      End If

   End If

   'Retrieve any non-fatal exceptions which might have occurred
   Dim UltraID3TagExceptions As UltraID3ContextMetaDataException() = TestUltraID3.GetExceptions()

   If UltraID3TagExceptions.Length > 0 Then

      Dim IndexUltraID3TagException As UltraID3TagException

      'Iterate through each found non-fatal exception
      For Each UltraID3ContextMetaDataException As UltraID3ContextMetaDataException In UltraID3TagExceptions

         'Display the Message of the non-fatal exception
         MsgBox(IndexUltraID3TagException.Message)

      Next

   End If

'Catch any fatal exceptions
Catch exc As Exception

   MsgBox(exc.Message)

End Try

 

 

Exceptions

 

There are three types of Exceptions that can occur during the UltraID3.Read method...

  1. Tag exceptions
    Thrown during a Read
    Prevents a Tag from being read

  2. Frame Errors
    Prevents a Frame from being read
    Not thrown, but retrieved by the GetExceptions method after a Read

  3. Frame Warnings
    Does not prevent a Frame from being read, but just records a non-standard format to the Frame

  4. Not thrown, but retrieved by the GetExceptions method after a Read

So, why are there exceptions that have to be retrieved using a function instead of being caught in a Try/Catch block?  Well, many of the exceptions that would be returned by the GetExceptions can also be thrown in other situations.  In other words, in the context of a Read, an exception may just give a warning that particular Frame field value is out of bounds or is not in the correct format.  But if you were to try a an invalid value to Frame field, the same exception would be thrown.

 

 

 

MPEG Metadata

 

While the primary purpose of UltraID3Lib is to read and write ID3 metadata in MP3's, reading of MPEG data is also supported.  Probably the most commonly referenced MPEG metadata values are the duration and the bit rate.  However, because MP3 files are constructed from an independent set of audio frames, determining the overall duration and bit rate of a track is not a straight forward matter. There are essentially four ways that one can get the duration and/or bit rate of an MP3 using UltraID3Lib, each one having their own pros and cons.

 

A) UltraID3.GetMPEGTrackInfo.Duration, UltraID3.GetMPEGTrackInfo.AverageBitRate

This is the most accurate method, but because it has to read each individual audio frame, it is also the most expensive.  Each audio frame is read sequentially in order to determine the total duration and average bit rate of the overall track.  Because of the sequential nature of the read, if any of the frames are corrupt, the location of the next frame cannot be determined and the function will fail.

 

B) UltraID3.FirstMPEGFrameInfo.Duration, UltraID3.FirstMPEGFrameInfo.Bitrate

This method is a good estimate of the duration and bit rate of a track, but because it only uses the first audio frame found, the results are not guaranteed 100% accurate.  In particular, the duration is calculated using the overall file length and the bit rate recorded in the first MPEG frame found.  But the bit rate can change from frame to frame, so the calculated duration and the bit rate can only ever be an estimate, albeit a most likely very good estimate.

 

C) UltraID3.FirstMPEGFrameInfo.VBRInfo.Duration

Using the Variable Bit Rate header, encoders have the ability to store information about the VBR parameters used to encode the track.  If this optional information exists, the VBRInfo.Duration will return the recorded value.  Please note, however, that this information is only as good as the encoder which stored the data and applies only to when the file was first encoded.  If the file was edited after the initial encoding, this duration will be incorrect unless it was updated by the editing program.

 

D) UltraID3.Duration.

This method uses the Variable Bit Rate header (if it exists) to calculate the duration.  As long as the Frame Count field is accurate, the duration will be accurate as well.  If the VBR header doesn't exist or if it doesn't contain a Frame Count field, then the method will return the UltraID3.FirstMPEGFrameInfo.Duration.