title
Products            Buy            Support Forum            Professional            About            Codec Central
 

VB.Net Class for reading ID3 And List INFO from WAV Files

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • simonf

    • Sep 2008
    • 3

    VB.Net Class for reading ID3 And List INFO from WAV Files

    Hi all,

    I am new to this forum So hello everyone,

    I have a customer who is using dbpoweramp a lot to rip cds into there music library. He wanted me to write a program to take the data out of thw wave files he produced and update his database with the data. I initialy used a the following code to read the tags.

    Code:
                Dim db As New DMCSCRIPTINGLib.Converter
                For i = 0 To 1000
                    Dim Element As String, Value As String
                    Element = ""
                    Value = ""
                    db.ReadIDTag(Filename, i, Element, Value)
                    If Element = "" Then Exit For
                    Results(i) = Element & "|" & Value
                Next

    But I found this method very slow It took over 1 minuite to read the tags for 10 albums.

    So I decided to write my own managed class to do the same thing (It only works with LIST INFO Items and ID3 Text tags IE T???) But It Is extreamly Quick. I can now read 40000 Tracks a Minute.

    This also has the the advantage of not needing dbpoweramp to be installed on the client machine and also you dont need to worry about which version of dbpoweramp is loaded.

    I thought It may be usefull for some of you, It dosnt write tags but I could modify it to do that if needed.

    This code reads the data from my class as per the example above.

    Code:
                Dim RiffRdr As New RIFFReader(Filename)
                i = 0
                If Not IsNothing(RiffRdr.ID3Items) Then
                    For Each item In RiffRdr.ID3Items
                        Results(i) = item.FriendlyName & "|" & item.Data
                        i += 1
                    Next
                End If
    
                If Not IsNothing(RiffRdr.InfoItems) Then
                    For Each item In RiffRdr.InfoItems
                        Results(i) = item.FriendlyName & "|" & item.Data
                        i += 1
                    Next
                End If
                RiffRdr.Dispose()

    Here is the class

    Code:
    Public Class RIFFReader
    
        Dim RIFFfile As System.IO.FileStream
        Dim RIFFLength As Long
        Dim RIFFType As String
    
        Structure RiffFrame
    
            Dim Name As String
            Dim StartOfData As Long
            Dim Length As Long
    
        End Structure
    
        Structure InfoItem
    
            Dim TAGNAME As String
            Dim FriendlyName As String
            Dim Data As String
    
        End Structure
    
        Structure ID3Item
    
            Dim TAGNAME As String
            Dim FriendlyName As String
            Dim Data As String
    
        End Structure
    
    
        '4.2.1   TALB    [#TALB Album/Movie/Show title]
        '4.2.1   TBPM    [#TBPM BPM (beats per minute)]
        '4.2.1   TCOM    [#TCOM Composer]
        '4.2.1   TCON    [#TCON Content type]
        '4.2.1   TCOP    [#TCOP Copyright message]
        '4.2.1   TDAT    [#TDAT Date]
        '4.2.1   TDLY    [#TDLY Playlist delay]
        '4.2.1   TENC    [#TENC Encoded by]
        '4.2.1   TEXT    [#TEXT Lyricist/Text writer]
        '4.2.1   TFLT    [#TFLT File type]
        '4.2.1   TIME    [#TIME Time]
        '4.2.1   TIT1    [#TIT1 Content group description]
        '4.2.1   TIT2    [#TIT2 Title/songname/content description]
        '4.2.1   TIT3    [#TIT3 Subtitle/Description refinement]
        '4.2.1   TKEY    [#TKEY Initial key]
        '4.2.1   TLAN    [#TLAN Language(s)]
        '4.2.1   TLEN    [#TLEN Length]
        '4.2.1   TMED    [#TMED Media type]
        '4.2.1   TOAL    [#TOAL Original album/movie/show title]
        '4.2.1   TOFN    [#TOFN Original filename]
        '4.2.1   TOLY    [#TOLY Original lyricist(s)/text writer(s)]
        '4.2.1   TOPE    [#TOPE Original artist(s)/performer(s)]
        '4.2.1   TORY    [#TORY Original release year]
        '4.2.1   TOWN    [#TOWN File owner/licensee]
        '4.2.1   TPE1    [#TPE1 Lead performer(s)/Soloist(s)]
        '4.2.1   TPE2    [#TPE2 Band/orchestra/accompaniment]
        '4.2.1   TPE3    [#TPE3 Conductor/performer refinement]
        '4.2.1   TPE4    [#TPE4 Interpreted, remixed, or otherwise modified by]
        '4.2.1   TPOS    [#TPOS Part of a set]
        '4.2.1   TPUB    [#TPUB Publisher]
        '4.2.1   TRCK    [#TRCK Track number/Position in set]
        '4.2.1   TRDA    [#TRDA Recording dates]
        '4.2.1   TRSN    [#TRSN Internet radio station name]
        '4.2.1   TRSO    [#TRSO Internet radio station owner]
        '4.2.1   TSIZ    [#TSIZ Size]
        '4.2.1   TSRC    [#TSRC ISRC (international standard recording code)]
        '4.2.1   TSSE    [#TSEE Software/Hardware and settings used for encoding]
        '4.2.1   TYER    [#TYER Year]
    
        Dim ID3TagName() As String = {"TALB", "TBPM", "TCMP", "TCOM", "TCON", "TCOP", "TDAT", "TDLY", "TENC", "TEXT", "TFLT", "TIME", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", "TOAL", "TOFN", "TOLY", "TOPE", "TORY", "TOWN", "TPE1", "TPE2", "TPE3", "TPE4", "TPOS", "TPUB", "TRCK", "TRDA", "TRSN", "TRSO", "TSIZ", "TSRC", "TSSE", "TYER"}
        Dim ID3TagFriendlyName() As String = {"Album", "BPM", "Compilation", "Composer", "Genre", "Copyright message", "Date", "Playlist delay", "Encoded by", "Lyricist", "File type", "Time", "Style", "Title", "Subtitle/Description", "Initial key", "Language", "Length", "Media type", "Original album", "Original filename", "Original lyricist", "Original artist", "Original release year", "File owner/licensee", "Artist", "Album Artist", "Conductor", "Remixed", "Part of a set", "Label", "Track", "Recording dates", "Internet radio station name", "Internet radio station owner", "Size", "ISRC", "Software/Hardware and settings used for encoding", "Year"}
    
    
        Dim INFOTagName() As String = {"IART", "ICMT", "ICOP", "ICRD", "IGNR", "INAM", "ISRC", "IPRD", "TORG", "LOCA", "TVER", "TURL", "TLEN", "ITCH", "TRCK", "itrk", "ISRF", "ITRK"}
        Dim INFOTagFriendlyName() As String = {"Artist", "Comment", "Copyright", "Year", "Genre", "Title", "ISRC", "Album", "Label", "Location", "Version", "URL", "Length", "Technician", "Track", "Track", "Source", "Track"}
    
        Public RiffFrames() As RiffFrame = Nothing
        Public InfoItems() As InfoItem = Nothing
        Public ID3Items() As ID3Item = Nothing
    
    
        Sub New(ByVal Filename As String)
    
            If My.Computer.FileSystem.FileExists(Filename) Then
    
                RIFFfile = IO.File.Open(Filename, IO.FileMode.Open, IO.FileAccess.ReadWrite)
    
                RIFFfile.Seek(0, IO.SeekOrigin.Begin)
    
                If ReadFourCC() = "RIFF" Then
    
                    'Looks like its a riff 
    
                Else
    
                    Throw New Exception("Not A Riff")
    
                End If
    
                RIFFLength = RIFFfile.ReadByte() + _
                                RIFFfile.ReadByte() * 2 ^ 8 + _
                                    RIFFfile.ReadByte() * 2 ^ 16 + _
                                        RIFFfile.ReadByte() * 2 ^ 24
    
            Else
    
                Throw New Exception("File Not Found")
    
            End If
    
            RIFFType = ReadFourCC()
    
            While RIFFfile.Position < RIFFfile.Length
                ' make space for the frame data
                If IsNothing(RiffFrames) Then
                    ReDim RiffFrames(0)
                Else
                    ReDim Preserve RiffFrames(RiffFrames.Length)
    
                End If
                RiffFrames(RiffFrames.Length - 1).Name = ReadFourCC()
                RiffFrames(RiffFrames.Length - 1).Length = ReadDWord()
                RiffFrames(RiffFrames.Length - 1).StartOfData = RIFFfile.Position
                'seek the begining of the next frame
                'MsgBox(RIFFfile.Position)
                RIFFfile.Seek(RiffFrames(RiffFrames.Length - 1).Length, IO.SeekOrigin.Current)
    
                'MsgBox(RIFFfile.Position)
            End While
    
            For Each item In RiffFrames
                ' Process "LIST" Section 
                If item.Name = "LIST" Then
                    'We Have A List Tag
                    RIFFfile.Seek(item.StartOfData, IO.SeekOrigin.Begin)
                    If ReadFourCC() = "INFO" Then
                        'We Have An Info Tag 
                        While RIFFfile.Position < (item.StartOfData + item.Length)
                            ' make space for the frame data
                            If IsNothing(InfoItems) Then
                                ReDim InfoItems(0)
                            Else
                                ReDim Preserve InfoItems(InfoItems.Length)
                            End If
                            InfoItems(InfoItems.Length - 1).TAGNAME = ReadFourCC()
                            InfoItems(InfoItems.Length - 1).Data = ReadString(ReadDWord)
                            'Set The frendly name to tag name just in case its not found
                            InfoItems(InfoItems.Length - 1).FriendlyName = _
                                     InfoItems(InfoItems.Length - 1).TAGNAME
    
                            For i As Integer = 0 To INFOTagName.Length - 1
    
                                If INFOTagName(i) = InfoItems(InfoItems.Length - 1).TAGNAME Then
    
                                    InfoItems(InfoItems.Length - 1).FriendlyName = INFOTagFriendlyName(i)
                                    Exit For
                                End If
    
    
                            Next
                        End While
                    End If
                End If
    
                If item.Name = "id3 " Then
                    'We Have A List Tag
                    RIFFfile.Seek(item.StartOfData, IO.SeekOrigin.Begin)
                    If ReadFourCC() = "ID3" + Chr(3) Then
                        'We Have An ID3 Tag
                        RIFFfile.Seek(6, IO.SeekOrigin.Current)
                        While RIFFfile.Position < (item.StartOfData + item.Length)
                            ' make space for the frame data
                            Dim Tag As String = ReadFourCC() 'The Tag
                            Dim Length As Long = ReadDWordRevProtected() 'The Length
                            RIFFfile.ReadByte() ' Read Flags
                            RIFFfile.ReadByte() ' Read Flags
                            If Tag(0) = "T" Then
                                'Its a TextTag
                                If IsNothing(ID3Items) Then
                                    ReDim ID3Items(0)
                                Else
                                    ReDim Preserve ID3Items(ID3Items.Length)
                                End If
    
                                ID3Items(ID3Items.Length - 1).TAGNAME = Tag
                                Dim InnerTag As String = ReadStringTag(Length)
    
                                If Tag = "TXXX" Then
    
                                    ID3Items(ID3Items.Length - 1).FriendlyName = _
                                                InnerTag.Substring(0, InnerTag.IndexOf(Chr(0)))
                                    ID3Items(ID3Items.Length - 1).Data = _
                                                InnerTag.Substring(InnerTag.IndexOf(Chr(0)) + 1)
    
                                Else
    
                                    ID3Items(ID3Items.Length - 1).Data = InnerTag
                                    ID3Items(ID3Items.Length - 1).FriendlyName = _
                                            ID3Items(ID3Items.Length - 1).TAGNAME
                                    For i As Integer = 0 To ID3TagName.Length - 1
    
                                        If ID3TagName(i) = ID3Items(ID3Items.Length - 1).TAGNAME Then
    
                                            ID3Items(ID3Items.Length - 1).FriendlyName = ID3TagFriendlyName(i)
                                            Exit For
                                        End If
    
    
                                    Next
    
                                End If
    
    
                            Else
    
                                'Its Not A Text Tag 
                                If Tag = Chr(0) + Chr(0) + Chr(0) + Chr(0) Then Exit While
    
                                'Skip The Tag
                                RIFFfile.Seek(Length, IO.SeekOrigin.Current)
    
                            End If
    
                        End While
                    End If
                End If
            Next
    
        End Sub
    
        Sub Dispose()
    
            RIFFfile.Close()
            RIFFfile.Dispose()
            ID3TagName = Nothing
            ID3TagFriendlyName = Nothing
    
            INFOTagName = Nothing
            INFOTagFriendlyName = Nothing
            RiffFrames = Nothing
            InfoItems = Nothing
            ID3Items = Nothing
    
    
        End Sub
    
        Function ReadStringTag(ByVal I As Long) As String
    
            Dim Tmp As Byte = RIFFfile.ReadByte
            Dim Result As String = ""
            Dim Unicode As Boolean
            Dim LowByteLast As Byte
            I = I - 1
    
            If Tmp = 0 Then
                ' its an ordinary tag
                Unicode = False
            Else
                'its a Unicode String
    
                Tmp = RIFFfile.ReadByte
                Tmp = RIFFfile.ReadByte
    
                Unicode = True
                If Tmp = 254 Then
                    LowByteLast = True
                Else
                    LowByteLast = False
                End If
                I = I - 2
    
            End If
    
    
            While I > 0
                Tmp = RIFFfile.ReadByte
                I -= 1
                If Unicode Then
                    Dim SecondByte As Byte = RIFFfile.ReadByte
                    I -= 1
    
                    If LowByteLast Then
    
                        Result += ChrW(Tmp * 256 + SecondByte)
    
                    Else
    
                        Result += ChrW(Tmp + SecondByte * 256)
    
                    End If
    
                Else
                    Result += Chr(Tmp)
    
                End If
    
    
            End While
            Return Result
    
        End Function
    
        Function ReadString(ByVal I As Long) As String
    
            Dim Tmp As Byte
            Dim Result As String = ""
            While I > 0
                Tmp = RIFFfile.ReadByte
                Result += IIf(Tmp = 0, "", Chr(Tmp))
                I -= 1
            End While
            Return Result
    
        End Function
    
        Function ReadFourCC() As String
    
            'read four bytes into a string 
            Dim Result As String = ""
    
            Result = Chr(RIFFfile.ReadByte()) & Chr(RIFFfile.ReadByte()) & Chr(RIFFfile.ReadByte()) & Chr(RIFFfile.ReadByte())
    
            Return Result
    
        End Function
    
        Function ReadDWord() As Long
    
            'read four bytes into a string 
            Return RIFFfile.ReadByte() + _
                                    RIFFfile.ReadByte() * 2 ^ 8 + _
                                        RIFFfile.ReadByte() * 2 ^ 16 + _
                                            RIFFfile.ReadByte() * 2 ^ 24
    
    
    
        End Function
    
        Function ReadDWordRevProtected() As Long
    
            'read four bytes into a string 
            Return RIFFfile.ReadByte() * 2 ^ 21 + _
                                    RIFFfile.ReadByte() * 2 ^ 14 + _
                                        RIFFfile.ReadByte() * 2 ^ 7 + _
                                            RIFFfile.ReadByte()
    
    
    
        End Function
    
    
    End Class
Working...

]]>