Click here to Skip to main content
Email Password   helpLost your password?

Introduction

There are many other articles at The Code Project describing the audio header and tag information, but none in VB.NET. So it's time to update my very old article (Reading and writing MP3 ID3v1 tags ) with nicer code and extend it to read the MPEG header information.

I don't want to go into detail about the structure of MPEG audio headers, because Konrad Windszus already has a very good article (MPEG Audio Frame Header) about that. If you're interested in the structure of the audio header or the ID3 tag format i recommend to visit the following sites:

Using the code

I wrote two classes to handle the header and tag information, called MP3Info and ID3v1Tag. The following code will show the structure to use the classes:

Dim objMP3Info As New _
 Monotic.Multimedia.MP3.MP3Info
With ListView1
    ''' Set the filename property

    objMP3Info.Filename = "c:\test.mp3"

    ''' Add the header information to a listview

    .Add("Filesize").SubItems.Add(objMP3Info.Filesize & " Byte")
    .Add("SamplingRateFrequency").SubItems.Add _
     (objMP3Info.SamplingRateFrequency & " Hz")
    .Add("Padding").SubItems.Add(objMP3Info.Padding & " Bytes")
    .Add("Private").SubItems.Add(objMP3Info.PrivateBit)
    .Add("Copyright").SubItems.Add(objMP3Info.Copyright)
    .Add("OriginalBit").SubItems.Add(objMP3Info.OriginalBit)
    .Add("Bitrate").SubItems.Add(objMP3Info.Bitrate & " bps")
    .Add("FrameSamples").SubItems.Add(objMP3Info.FrameSamples)
    .Add("FrameSize").SubItems.Add(objMP3Info.FrameSize & " Byte")
    .Add("Length").SubItems.Add(objMP3Info.Length & " s (" 
     & Int(objMP3Info.Length / 60) & ":" & _
      objMP3Info.Length Mod 60 & " m)")
    .Add("HeaderPosition").SubItems.Add(objMP3Info.HeaderPosition)
    .Add("VBRScale").SubItems.Add(objMP3Info.VBRScale)

    Select Case objMP3Info.MPEGVersion
        Case MP3.MPEGVersionEnum.MPEG1
            .Add("MPEGType").SubItems.Add("MPEG 1")
        Case MP3.MPEGVersionEnum.MPEG2
            .Add("MPEGType").SubItems.Add("MPEG 2")
        Case MP3.MPEGVersionEnum.MPEG25
            .Add("MPEGType").SubItems.Add("MPEG 2.5")
    End Select

    Select Case objMP3Info.Layer
        Case MP3.LayerEnum.LayerI
            .Add("Layer").SubItems.Add("Layer I")
        Case MP3.LayerEnum.LayerII
            .Add("Layer").SubItems.Add("Layer II")
        Case MP3.LayerEnum.LayerIII
            .Add("Layer").SubItems.Add("Layer III")
    End Select

    Select Case objMP3Info.Protection
        Case MP3.ProtectionEnum.None
            .Add("Protection").SubItems.Add("None")
        Case MP3.ProtectionEnum.CRC
            .Add("Protection").SubItems.Add("By CRC")
    End Select

    Select Case objMP3Info.ChannelMode
        Case MP3.ChannelModeEnum.DualChannel
            .Add("ChannelMode").SubItems.Add("Dual Channel")
        Case MP3.ChannelModeEnum.JointStereo
            .Add("ChannelMode").SubItems.Add("Joint Stereo")
        Case MP3.ChannelModeEnum.SingleChannel
            .Add("ChannelMode").SubItems.Add("Single Channel")
        Case MP3.ChannelModeEnum.Stereo
            .Add("ChannelMode").SubItems.Add("Stereo")
    End Select

    Select Case objMP3Info.Emphasis
        Case MP3.EmphasisEnum.CCIT
            .Add("Emphasis").SubItems.Add("CCIT")
        Case MP3.EmphasisEnum.MS5015
            .Add("Emphasis").SubItems.Add("50/15 ms")
        Case MP3.EmphasisEnum.None
            .Add("Emphasis").SubItems.Add("None")
    End Select

    Select Case objMP3Info.Encoding
        Case MP3.EncodingEnum.CBR
            .Add("Encoding").SubItems.Add("CBR")
        Case MP3.EncodingEnum.VBR
            .Add("Encoding").SubItems.Add("VBR")
    End Select

    ''' Add the ID3v1 tag information to a listview

    If (objMP3Info.ID3v1Tag.TagAvailable) Then
        .Add("ID3 Title").SubItems.Add _
         (objMP3Info.ID3v1Tag.Title)
        [...]
    End If

    ''' Update the tag

    objMP3Info.ID3v1Tag.Title = "Another title"
    objMP3Info.ID3v1Tag.Update()

End With

Please have a look at the sample and the class code to see all the features.

Points of Interest

Unlike other articles, this class will handle CBR and VBR encoded files, so the playtime is calculated correctly.

The class is well-commented with XML comments made by AxTools CodeSmart 2005 and NDoc . I included the generated HTML help file in the download.

I'm working on reading and writing the much more complex ID3v2.x tags at the moment (80% done, just compressed frames are a little bit tricky). If you are interested in this, i will update this article in the future.

History

27.02.2004 Release of version 1

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionWie kann ich Änderungen speichern? MP3
michaelroswitha1
9:25 3 Jan '10  
With MP3Info.ID3v1Tag
.Title = DataGridViewMp3.Rows(e.RowIndex).Cells(4).Value
.Artist = DataGridViewMp3.Rows(e.RowIndex).Cells(3).Value
.Album = DataGridViewMp3.Rows(e.RowIndex).Cells(5).Value
.Year = DataGridViewMp3.Rows(e.RowIndex).Cells(6).Value
.Genre = 9
End With
MP3Info.Update()--> Funktioniert nicht
QuestionHow to read the actual genre string when it is "other"
a1penguin
18:05 18 Jun '09  
I have an application where all of the mp3 files will have made up genres which are not in the list of enums. In all cases I get 12 when I read the genre or "other" when I read the string. Is there a way to read back the actual genre string in these cases.
GeneralVBR File
nitesh gaba
22:30 19 Mar '09  
It doesnot give correct file duration of VBR file. Whereas this library gives http://www.codeproject.com/KB/audio-video/mpegaudioinfo.aspx[^] correct length after reading complete file.

Could you please help me.
QuestionWhat i write to the tag doesn't show up when viewing the property details in the file system.
MattRoy10
15:11 18 Mar '09  
Reading works fine. When i write to the tag, the value doesn't appear to change if it already contained a value. However, if i proceed to read the same information it returns what i previously wrote.

Example:
The MP3 ID tag already contains the album name "Original Album" as seen in the file system. I write the new album info like this:

objMP3Info.ID3v1Tag.Album = "New Album"
objMP3Info.Update()

If i read the tag again, i will see "New Album", but if i view the file properties i don't see the change. If i clear the tag using the file system (Windows Vista) and re-run the code i will get the results i expect. The new album name will be written and viewed correctly in the file system.

Basically, i need to manually clear out all the tag info if i want this sample code to write values that i will see with my OS.

Please help!
Generalhip hop songs and dance
Jigga Hov
6:58 12 Dec '08  
I am looking for a fresh version of the ID with words of the songs. It is extremely useful in hip hop songs.

Also while looking at website about hip hop dance moves I have found that the old tags might do the job because there are less words at the songs. Blush
GeneralGNU OpenSource Tag Library for .NET
someonestupid1969
5:55 10 Dec '08  
http://developer.novell.com/wiki/index.php/TagLib_Sharp

by the way, not by me... I am just using it... Cool
GeneralSet mp3-Tag with objMP3Info
squirrel91
0:45 28 Jul '07  
this sample code for the mp3-tags is excellent for reading the tags, but how can i write some informations??

objMP3Info.ID3v1Tag.Title = "Another title"
objMP3Info.ID3v1Tag.update()

error: update isnt a member of monotonic.multimedia.mp3.ID3v1Tag...

it doesnt work ;-(

anybody can help me?


QuestionIs it?
Rola /anglian/
1:03 12 Jun '07  
_
GeneralRemote MP3
ohadioe2
6:33 30 Apr '07  
Is it possible to read the tags for remote MP3's with this class?
GeneralOverFlow searching Genres
ricsamma
18:25 15 Nov '06  
Hi,
I'm using this powerfull code and I think that is very well done.

I think that the form to obtain the genre is a little archaic, and i'm gona implement the search whit a XML file that can be editable in the future.. i don't now what you think..

For now I think that the GetGenreString function must end like this:

Public Function GetGenreString(ByVal bytGenre As Byte) As String

Dim strGenres() As String = {"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", "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 Cappella", "Euro - House", _
"Dance Hall", "Goa", "Drum & Bass", "Club - House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", _
"Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", _
"Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop"}
If bytGenre > 147 Then
Return "Unknown"
Else
Return strGenres(bytGenre)
End If
End Function

Thanks again for the class man..Laugh



Ricsamma
AnswerRe: OverFlow searching Genres
Thommy Mewes
21:39 15 Nov '06  
ricsamma wrote:
I think that the form to obtain the genre is a little archaic, and i'm gona implement the search whit a XML file that can be editable in the future.. i don't now what you think..

Yes, it is, but i think there is no need for an extra xml file, because the genres don't will change.
GeneralAdding Info to a listbox
John Dovey
3:36 7 Sep '06  
Hi,
This is a really nifty little class. Thanx a million for it. There was no project or anything in the download though, so I created a project, added a form to it and on the form put a ListBox1 and a "test" button called btn_test.
Then I changed the code from this page and added it to the btn_test.
Hope this helps others.

John
Private Sub btn_Test_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_Test.Click
            Dim objMP3Info As New Monotic.Multimedia.MP3.MP3Info
            With ListBox1.Items
                  ' Set the filename property
                  objMP3Info.Filename = "test.mp3"

                  ' Add the header information to a listview
                  .Add("Filesize= " & objMP3Info.Filesize & " Byte")
                  .Add("SamplingRateFrequency= " & objMP3Info.SamplingRateFrequency & " Hz")
                  .Add("Padding= " & objMP3Info.Padding & " Bytes")
                  .Add("Private= " & objMP3Info.PrivateBit)
                  .Add("Copyright=" & objMP3Info.Copyright)
                  .Add("OriginalBit= " & objMP3Info.OriginalBit)
                  .Add("Bitrate= " & objMP3Info.Bitrate & " bps")
                  .Add("FrameSamples= " & objMP3Info.FrameSamples)
                  .Add("FrameSize= " & objMP3Info.FrameSize & " Byte")
                  .Add("Length= " & objMP3Info.Length & " s (" & Int(objMP3Info.Length / 60) & ":" & objMP3Info.Length Mod 60 & " m)")
                  .Add("HeaderPosition= " & objMP3Info.HeaderPosition)
                  .Add("VBRScale= " & objMP3Info.VBRScale)

                  Select Case objMP3Info.MPEGVersion
                        Case MP3Info.Monotic.Multimedia.MP3.MPEGVersionEnum.MPEG1
                              .Add("MPEGType= " & "MPEG 1")
                        Case MP3Info.Monotic.Multimedia.MP3.MPEGVersionEnum.MPEG2
                              .Add("MPEGType= " & "MPEG 2")
                        Case MP3Info.Monotic.Multimedia.MP3.MPEGVersionEnum.MPEG25
                              .Add("MPEGType= " & "MPEG 2.5")
                  End Select

                  Select Case objMP3Info.Layer
                        Case MP3Info.Monotic.Multimedia.MP3.LayerEnum.LayerI
                              .Add("Layer= " & "Layer I")
                        Case MP3Info.Monotic.Multimedia.MP3.LayerEnum.LayerII
                              .Add("Layer= " & "Layer II")
                        Case MP3Info.Monotic.Multimedia.MP3.LayerEnum.LayerIII
                              .Add("Layer= " & "Layer III")
                  End Select

                  Select Case objMP3Info.Protection
                        Case MP3Info.Monotic.Multimedia.MP3.ProtectionEnum.None
                              .Add("Protection= " & "None")
                        Case MP3Info.Monotic.Multimedia.MP3.ProtectionEnum.CRC
                              .Add("Protection= " & "By CRC")
                  End Select

                  Select Case objMP3Info.ChannelMode
                        Case MP3Info.Monotic.Multimedia.MP3.ChannelModeEnum.DualChannel
                              .Add("ChannelMode= " & "Dual Channel")
                        Case MP3Info.Monotic.Multimedia.MP3.ChannelModeEnum.JointStereo
                              .Add("ChannelMode= " & "Joint Stereo")
                        Case MP3Info.Monotic.Multimedia.MP3.ChannelModeEnum.SingleChannel
                              .Add("ChannelMode= " & "Single Channel")
                        Case MP3Info.Monotic.Multimedia.MP3.ChannelModeEnum.Stereo
                              .Add("ChannelMode= " & "Stereo")
                  End Select

                  Select Case objMP3Info.Emphasis
                        Case MP3Info.Monotic.Multimedia.MP3.EmphasisEnum.CCIT
                              .Add("Emphasis= " & "CCIT")
                        Case MP3Info.Monotic.Multimedia.MP3.EmphasisEnum.MS5015
                              .Add("Emphasis= " & "50/15 ms")
                        Case MP3Info.Monotic.Multimedia.MP3.EmphasisEnum.None
                              .Add("Emphasis= " & "None")
                  End Select

                  Select Case objMP3Info.Encoding
                        Case MP3Info.Monotic.Multimedia.MP3.EncodingEnum.CBR
                              .Add("Encoding= " & "CBR")
                        Case MP3Info.Monotic.Multimedia.MP3.EncodingEnum.VBR
                              .Add("Encoding= " & "VBR")
                  End Select

                  ' Add the ID3v1 tag information to a listview
                  If (objMP3Info.ID3v1Tag.TagAvailable) Then
                        .Add("ID3 Title= " & objMP3Info.ID3v1Tag.Title)
                        '[...]()
                  End If

                  ' Update the tag
                  'objMP3Info.ID3v1Tag.Title = "Another title"
                  'objMP3Info.ID3v1Tag.Update()

            End With
      End Sub

GeneralHow to use this dll in Exel Macro?
strangerland
19:16 26 May '06  
Hi I need some very basic instruction in how to use this dll in an Excel macro. For instance where do I place the dll to begin with (that is which directory?) I'm using excel 2002. Let's say I want to get the bitrate, size, and encoding(stereo or joint stereo etc) for a single file.

Thanks,
Steve
AnswerRe: How to use this dll in Exel Macro? [modified]
bill-tor
18:50 4 Jan '07  
You'll need ta compile the DLL with a STRONG NAME and den will need to smack a COM wrapper on it and den register it on your machine using REGSRV23.EXE, a Windows provided executable.

After ya dun all that, the DLL will be available in the VBE as an add-able reference.

GeneralBitrate problem
Alberto Venditti
10:12 15 Feb '06  
I got a problem with the Property Bitrate() As Integer.
On some MP3 files I have an issue in computing the Bitrate. Stepping with the debugger, I found for those files: Encoding=CBR, MPEGVersion=MPEG25, Layer=Reserved, and then no IF branch inside the block:

If (Me.Encoding = EncodingEnum.CBR) Then
...
Else

is executed, resulting in a Bitrate set to 0 and consequently an overflow error while computing the track length (in seconds) as:

Return Math.Round(f_intAudioSize / Me.Bitrate * 8, 0)

I read somewhere that computing the track length may be difficult for VBR files, but this one is CBR. I read also that ID3 tags should expose the "duration" of the track (solving also inaccuracies eventually coming in this computation on VBR files), but ID3v1Tag property of your class doesn't expose such "duration" (maybe a ID3 v2 feature...).

Can you help me, please?

Thank you in advance,
AV

GeneralRe: Bitrate problem
AndyLang
16:17 15 Jul '07  
I got the same problem, for some mp3 file, it cann't get the correct Layer information.
but the article he referenced http://www.codeproject.com/audio/MPEGAudioInfo.asp[^] can do that.


GeneralRe: Bitrate problem
LegoMindstorms
11:44 5 Apr '08  
I had the same problem, but solved it by changing the length property like this:
Public ReadOnly Property Length() As Integer
Get
If Me.Bitrate = 0 Or Me.Bitrate = -1 Then
Return 0 Else
Return Math.Round(f_intAudioSize / Me.Bitrate * 8, 0)
End If
End Get
End Property
Then I made an errorhandling wehn length = 0.
QuestionUpdate Missing
Iftikhar Ali
0:54 17 Jan '06  
objMP3Info.ID3v1Tag.Update() is missing. How can I write tags to mp3 file from my program?
AnswerRe: Update Missing
Thommy Mewes
9:44 17 Jan '06  
Above sample is working on my machine, please post the code to find the error.
GeneralRe: Update Missing
Iftikhar Ali
21:33 17 Jan '06  
I use the same code as you provide in this page (above), but objMP3Info.ID3v1Tag.Update() is missing in your dll. Infact I checked ID3v1Tag and it doesn't contain any Update(), how can it works?
Please upload the correct version of these downloads (files). This will correct this problem.
GeneralPassword???
Godz1lla
13:44 1 Jan '06  
Why is the Zip file passworded?
GeneralRe: Password???
Thommy Mewes
9:45 17 Jan '06  
There is no password.
GeneralException by reading header info from CD
Ronny Foerster
21:03 29 May '05  
Hi Thommy,
great class it works very fine. I've written a small mp3Manager wich scans for my mp3 files and stores them, with path and header info to a database.
If I scan my HDD it works very well, but if I scan an CD then I got an exception in your class at Opening the File.

The CD's files aren't damaged, I've already checked this and in Winamp it's also possible to read all the information. I don't know why this execption is fired.

Greetz
RF
GeneralRe: Exception by reading header info from CD
Thommy Mewes
13:21 16 Jun '05  
Good question. Can you send me a piece of code where i can have a look (thommy@hotmail.de)?
GeneralRe: Exception by reading header info from CD
Jef Lagueux
13:59 21 Mar '06  
I think I have an answer for you. It looks like the file is being opened for read/write access, but when they are on a CD this is not possible. I was having the same issue, but through code I copied the file to the hard drive, changed the file attributes from readonly to normal and I was able to access it with no problems. I then deleted the "temp" file once i was done with it.

It's not the best solution, but it works.

Just thought I would throw my 2 cents in.

Thanks!


Last Updated 1 Mar 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010