VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "clsMP3"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'The purpose of this class is to read information about MP3's. It was written to do the dirty
'work in an ASP MP3 streamer.
'
'1. ReadMP3() - Reads ID3v1, ID3v2, bitrate, variable bitrate, freq, and duration of a specified
'MP3. If the MP3 has v1 and v2 tags, then v2 will override v1.
'
'example usage
'Private Sub Command1_Click()
'    'declare variables to be passed to ReadMP3 function
'    Dim Artist As String
'    Dim Album As String
'    Dim SongName As String
'    Dim Track As String
'    Dim BitRate As String
'    Dim Frequency As String
'    Dim Duration As String
'
'    'Create instance of clsMP3
'    Dim objMP3 As clsMP3
'    Set objMP3 = New clsMP3
'        'call function
'        If objMP3.ReadMP3("d:\Faith No More - 10 - A Small Victory.mp3", Artist, Album, SongName, Track, BitRate, Frequency, Duration) Then
'            'display results
'            MsgBox Artist & vbCrLf & _
'                Album & vbCrLf & _
'                SongName & vbCrLf & _
'                Track & vbCrLf & _
'                BitRate & vbCrLf & _
'                Frequency & vbCrLf & _
'                Duration
'        End If
'    'destroy object
'    Set objMP3 = Nothing
'End Sub
'
'
'
'2. SearchDir() - Give this function a dir, and a file type to look for,
'and it will return the subdirs (pipe delimited), and the files (pipe delimited)
'
'example usage
'Private Sub Command2_Click()
'    'declare strings to be passed to SearchDir function
'    Dim SubDirs As String
'    Dim MP3Files As String
'
'    'Create instance of clsMP3
'    Dim objMP3 As clsMP3
'    Set objMP3 = New clsMP3
'        'display results
'        If objMP3.SearchDir("d:\", "*.mp3", SubDirs, MP3Files) Then
'            MsgBox "Subdirs = " & SubDirs
'            MsgBox "MP3Files = " & MP3Files
'        End If
'    'destroy object
'    Set objMP3 = Nothing
'End Sub

Private Const INVALID_HANDLE_VALUE = -1
Private Const DDL_DIRECTORY = &H10
Private Const MAX_PATH = 260

Private Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
    dwFileAttributes As Long
    ftCreationTime As FILETIME
    ftLastAccessTime As FILETIME
    ftLastWriteTime As FILETIME
    nFileSizeHigh As Long
    nFileSizeLow As Long
    dwReserved0 As Long
    dwReserved1 As Long
    cFileName As String * MAX_PATH
    cAlternate As String * 14
End Type

Private Type MP3Info
    BitRate As String
    Frequency As String
    Duration As String
    SongName As String
    Artist As String
    Album As String
    Year As String
    Comment As String
    Genre As String
    Track As String
    
    VBR As Boolean
    Mode As String
    Emphasis As String
    MpegVersion As String
    MpegLayer As String
    Padding As String
    CRC As String
    CopyRight As String
    Original As String
    PrivateBit As String
    HasTag As Boolean
    Tag As String
    Frames As String
End Type



Private GetMP3Info As MP3Info

Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long




Public Function SearchDir(ByVal RootDir As String, ByVal FileType As String, ByRef rSubDirs As Variant, ByRef rFiles As Variant) As Boolean
    On Error GoTo ErrHand
    
    DoEvents
    Dim Dir_Names() As String
    Dim Num_Dirs As Integer
    Dim I As Integer
    Dim fName As String
    Dim Search_Handle As Long
    Dim File_Data As WIN32_FIND_DATA
    Dim TempInt As Integer
    
    'clear vars because they are passed by ref and could contain data
    rSubDirs = ""
    rFiles = ""

    ' Get the matching files in this directory.
    Search_Handle = FindFirstFile(RootDir & FileType, File_Data)
    If Search_Handle <> INVALID_HANDLE_VALUE Then
        Do
            fName = File_Data.cFileName
            fName = RootDir & Left$(fName, InStr(fName, Chr$(0)) - 1)
            
            'add the file to the string
            rFiles = rFiles & fName & "|"
            
            'find the next file
            If FindNextFile(Search_Handle, File_Data) = 0 Then Exit Do
        Loop
        FindClose Search_Handle
    End If

    ' Get the list of subdirectories.
    Search_Handle = FindFirstFile(RootDir & "*.*", File_Data)
    If Search_Handle <> INVALID_HANDLE_VALUE Then
        Do
            If File_Data.dwFileAttributes And DDL_DIRECTORY Then
                fName = File_Data.cFileName
                fName = Left$(fName, InStr(fName, Chr$(0)) - 1)
                If fName <> "." And fName <> ".." Then
                    rSubDirs = rSubDirs & fName & "|"
                End If
            End If
            DoEvents
            If FindNextFile(Search_Handle, File_Data) = 0 Then Exit Do
        Loop
        FindClose Search_Handle
    End If
    
    SearchDir = True
    Exit Function
    
ErrHand:
    SearchDir = False

End Function

Private Function ReadFile(ByVal strFilename As String) As Boolean
    
    ReadFile = False
    
    On Error GoTo ErrHand
    
    Dim I As Integer                'holds temp int bytes
    Dim B As Byte                   'holds temp byte values
    Dim S As String                 'holds temp strings
    Dim R As Double
    Dim Version As Byte
    Dim lngHeaderPosition As Long
    Dim TagString As String         'holds the string read from the mp3
    
    
    'vars that hold ID3v2 attibutes
    Dim TitleField As String
    Dim ArtistField As String
    Dim AlbumField As String
    Dim YearField As String
    Dim GenreField As String
    Dim FieldSize As Long
    Dim SizeOffset As Long
    Dim FieldOffset As Long
    Dim TrackNbr As String
    Dim strStrip As String
    
    'fixed length vars for reading ID3v1 tags
    Dim ID As String * 3
    Dim tTitle As String * 30
    Dim tArtist As String * 30
    Dim tAlbum As String * 30
    Dim tYear As String * 4
    Dim tComment As String * 30
    Dim tGenre As Byte
    Dim Genre As Byte

    'Open the file so we can read it
    Open strFilename For Binary As #2
        

        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' Check for a Header
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            
        Get #2, 1, B
            
        If B <> 255 Then '(255 is where an ID3v2 header should start)
            If B <> 73 Then
                'Exit Function
            End If
        End If
         
        lngHeaderPosition = 1
        Get #2, 2, B
        If (B < 250 Or B > 251) Then
            'We have an ID3v2 tag
            If B = 68 Then
                Get #2, 3, B
                If B = 51 Then
                    
                    Get #2, 4, Version
                    Get #2, 7, B
                    R = B * 20917152
                    Get #2, 8, B
                    R = R + (B * 16384)
                    Get #2, 9, B
                    R = R + (B * 128)
                    Get #2, 10, B
                    R = R + B
                    If R > LOF(2) Or R > 2147483647 Then
                        Exit Function
                    End If
                    TagString = Space$(R)
                    Get #2, 11, TagString
                    lngHeaderPosition = R + 11
                End If
            End If
        Else
            'ID3v2 tag is missing
        End If

        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' Check for an ID3v1 tag
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
        'ID3v1 tag
        Get #2, LOF(2) - 127, ID
        
        
        
        
        
        If ID = "TAG" Then 'If "TAG" is present, then we have a valid ID3v1 tag and will extract all available ID3v1 info from the file
            Get #2, , tTitle    'Always limited to 30 characters
            Get #2, , tArtist   'Always limited to 30 characters
            Get #2, , tAlbum    'Always limited to 30 characters
            Get #2, , tYear     'Always limited to 4 characters
            Get #2, , tComment  'Always limited to 30 characters
            Get #2, , tGenre    'Always limited to 1 byte (?)
            
            
            GetMP3Info.SongName = tTitle
            GetMP3Info.Artist = tArtist
            GetMP3Info.Album = tAlbum
            GetMP3Info.Year = tYear
            GetMP3Info.Comment = tComment
            Genre = tGenre
            
            'get rid of " " on the right side of the string
            Do Until Right(GetMP3Info.SongName, 1) <> " "
                GetMP3Info.SongName = Left(GetMP3Info.SongName, Len(GetMP3Info.SongName) - 1)
            Loop
            Do Until Right(GetMP3Info.Artist, 1) <> " "
                GetMP3Info.Artist = Left(GetMP3Info.Artist, Len(GetMP3Info.Artist) - 1)
            Loop
            Do Until Right(GetMP3Info.Album, 1) <> " "
                GetMP3Info.Album = Left(GetMP3Info.Album, Len(GetMP3Info.Album) - 1)
            Loop
            Do Until Right(GetMP3Info.Year, 1) <> " "
                GetMP3Info.Year = Left(GetMP3Info.Year, Len(GetMP3Info.Year) - 1)
            Loop
            Do Until Right(GetMP3Info.Comment, 1) <> " "
                GetMP3Info.Comment = Left(GetMP3Info.Comment, Len(GetMP3Info.Comment) - 1)
            Loop
            Do Until Right(Genre, 1) <> " "
                Genre = Left(Genre, Len(Genre) - 1)
            Loop
      
            'get rid of null characters
            GetMP3Info.SongName = Replace(GetMP3Info.SongName, vbNullChar, "")
            GetMP3Info.Artist = Replace(GetMP3Info.Artist, vbNullChar, "")
            GetMP3Info.Album = Replace(GetMP3Info.Album, vbNullChar, "")
            GetMP3Info.Year = Replace(GetMP3Info.Year, vbNullChar, "")
            GetMP3Info.Comment = Replace(GetMP3Info.Comment, vbNullChar, "")
            Genre = Replace(Genre, vbNullChar, "")
        End If
        
        
        
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' Proceed to extract the ID3v2 tag info if any exists
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     
        If TagString <> "" Then
            'GET ID3V2 TAG
               
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Determine if the ID3v2 tag is ID3v2.2 or ID3v2.3
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            
            'Notes: I haven't tested reading an MP3 file that has a ID3v2.2 tag
               
            Select Case Version
            
                Case 2 'ID3v2.2
                    'Set the fieldnames for version 2.0
                    TitleField = "TT2"
                    ArtistField = "TOA"
                    AlbumField = "TAL"
                    YearField = "TYE"
                    GenreField = "TCO"
                    FieldOffset = 7
                    SizeOffset = 5
                    TrackNbr = "TRCK"
               
                Case 3 'ID3v2.3
                    'Set the fieldnames for version 3.0
                    TitleField = "TIT2"
                    ArtistField = "TPE1"
                    AlbumField = "TALB"
                    YearField = "TYER"
                    GenreField = "TCON"
                    TrackNbr = "TRCK"
               
                    FieldOffset = 11
                    SizeOffset = 7
                Case Else
                    'We don't have a valid ID3v2 tag, so bail
                    Exit Function
                    
            End Select
                
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract track title
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                
            I = InStr(TagString, TitleField)
            If I > 0 Then
                'read the title
                FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
                If Version = 3 Then
                   'check for compressed or encrypted field
                   B = Asc(Mid$(TagString, I + 9))
                   If (B And 128) = True Or (B And 64) = True Then GoTo ReadAlbum
                End If
                If GetMP3Info.SongName = "" Then
                    GetMP3Info.SongName = Mid$(TagString, I + FieldOffset, FieldSize)
                End If
            End If
                   
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract album title
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ReadAlbum:
            I = InStr(TagString, AlbumField)
            If I > 0 Then
                FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
                If Version = 3 Then
                   'check for compressed or encrypted field
                   B = Asc(Mid$(TagString, I + 9))
                   If (B And 128) = 128 Or (B And 64) = 64 Then GoTo ReadArtist
                End If
                If GetMP3Info.Album = "" Then
                    GetMP3Info.Album = Mid$(TagString, I + FieldOffset, FieldSize)
                End If
               
            End If
                
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract artist name
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ReadArtist:
            I = InStr(TagString, ArtistField)
            If I > 0 Then
                FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
                If Version = 3 Then
                    'check for compressed or encrypted field
                    B = Asc(Mid$(TagString, I + 9))
                    If (B And 128) = 128 Or (B And 64) = 64 Then GoTo ReadYear
                End If
                If GetMP3Info.Artist = "" Then
                    GetMP3Info.Artist = Mid$(TagString, I + FieldOffset, FieldSize)
                End If
            End If
               
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract year title
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ReadYear:
            I = InStr(TagString, YearField)
            If I > 0 Then
                FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
                If Version = 3 Then
                    'check for compressed or encrypted field
                    B = Asc(Mid$(TagString, I + 9))
                    If (B And 128) = 128 Or (B And 64) = 64 Then GoTo ReadGenre
                End If
                If GetMP3Info.Year = "" Then
                    GetMP3Info.Year = Mid$(TagString, I + FieldOffset, FieldSize)
                End If
            End If
               
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract genre
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ReadGenre:
            I = InStr(TagString, GenreField)
            If I > 0 Then
               FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
               
               If Version = 3 Then
                  'check for compressed or encrypted field
                  B = Asc(Mid$(TagString, I + 9))
                  If (B And 128) = 128 Or (B And 64) = 64 Then GoTo ReadTrackNbr
               End If
               
               S = Mid$(TagString, I + FieldOffset, FieldSize)
               
               If Left$(S, 1) = "(" Then
               
                    'we have an ID3v2 genre that's in the format of:
                    '(0) Blues
                    '(12) Rock
                    '(125) Dance Hall
                    If Genre = 0 Then
                        Genre = Trim(Right(S, (Len(S) - InStr(1, S, ")", 0))))
                    End If
                 
               Else
                    'no genre in tag
               End If
               
            End If
               
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' Extract track number
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ReadTrackNbr:
            I = InStr(TagString, TrackNbr)
            If I > 0 Then
                FieldSize = Asc(Mid$(TagString, I + SizeOffset)) - 1
                If Version = 3 Then
                   'check for compressed or encrypted field
                   B = Asc(Mid$(TagString, I + 9))
                   If (B And 128) = 128 Or (B And 64) = 64 Then GoTo Done
                End If
                If GetMP3Info.Track = "" Then
                    GetMP3Info.Track = Mid$(TagString, I + FieldOffset, FieldSize)
                End If
            End If
               
Done:
        End If
        
    Close #2
    
    'look up the genre
    GetMP3Info.Genre = GetGenreFromID(Genre)

    Exit Function
        
ErrHand:
    MsgBox Err.Number & " " & Err.Description
    Close #1
    Close #2
    
End Function

Public Function ReadMP3(ByVal FileName As Variant, _
    Optional ByRef rArtist As Variant, Optional ByRef rAlbum As Variant, _
    Optional ByRef rSongname As Variant, Optional ByRef rTrack As Variant, _
    Optional ByRef rBitRate As Variant, Optional ByRef rFrequency As Variant, _
    Optional ByRef rDuration As Variant, Optional ByRef rYear As Variant, _
    Optional ByRef rComment As Variant, Optional ByRef rGenre As Variant) As Boolean
    
    'set function to false
    ReadMP3 = False
    
    'clear out mp3 info
    GetMP3Info.BitRate = ""
    GetMP3Info.Frequency = ""
    GetMP3Info.Duration = ""
    GetMP3Info.SongName = ""
    GetMP3Info.Artist = ""
    GetMP3Info.Album = ""
    GetMP3Info.Year = ""
    GetMP3Info.Comment = ""
    GetMP3Info.Genre = ""
    GetMP3Info.Track = ""
    GetMP3Info.Mode = ""
    GetMP3Info.Emphasis = ""
    GetMP3Info.MpegVersion = ""
    GetMP3Info.MpegLayer = ""
    GetMP3Info.Padding = ""
    GetMP3Info.CRC = ""
    GetMP3Info.CopyRight = ""
    GetMP3Info.Original = ""
    GetMP3Info.PrivateBit = ""
    GetMP3Info.Tag = ""
    GetMP3Info.Frames = ""
    GetMP3Info.VBR = False
    GetMP3Info.HasTag = False


    'extract all 32 bits
    bin = BinaryHeader(FileName, True, True)
    
    
    
    'Mpegversion table
    Version = Array(25, 0, 2, 1)
    'get mpegversion from table
    MpegVersion = Version(BinToDec(Mid(bin, 12, 2)))
    'layer table
    layer = Array(0, 3, 2, 1)
    'get layer from table
    MpegLayer = layer(BinToDec(Mid(bin, 14, 2)))
    'mode table
    SMode = Array("stereo", "joint stereo", "dual channel", "single channel")
    'get mode from table
    Mode = SMode(BinToDec(Mid(bin, 25, 2)))
    'empasis table
    Emph = Array("no", "50/15", "reserved", "CCITT J 17")
    'get empasis from table
    Emphasis = Emph(BinToDec(Mid(bin, 31, 2)))
    
    'look for version to create right table
    Select Case MpegVersion
        Case 1
            'for version 1
            Freq = Array(44100, 48000, 32000)
        Case 2 Or 25
            'for version 2 or 2.5
            Freq = Array(22050, 24000, 16000)
        Case Else
            Frequency = 0
            Exit Function
    End Select
    
    'look for frequency in table
    Frequency = Freq(BinToDec(Mid(bin, 21, 2)))
    
    'check if variable bitrate
    If GetMP3Info.VBR = True Then
        'define to calculate correct bitrate
        Temp = Array(, 12, 144, 144)
        
        BitRate = (FileLen(FileName) * Frequency) / (Int(GetMP3Info.Frames)) / 1000 / Temp(MpegLayer)
    Else    'if not variable bitrate
    
        Dim LayerVersion As String
        
        'combine version and layer to string
        LayerVersion = MpegVersion & MpegLayer
        
        'look for the right bitrate table
        Select Case Val(LayerVersion)
            Case 11
                'Version 1, Layer 1
                Brate = Array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448)
            Case 12
                'V1 L1
                Brate = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384)
            Case 13
                'V1 L3
                Brate = Array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)
            Case 21 Or 251
                'V2 L1 and 'V2.5 L1
                Brate = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256)
            Case 22 Or 252 Or 23 Or 253
                'V2 L2 and 'V2.5 L2 etc...
                Brate = Array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160)
            Case Else
                'if variable bitrate
                BitRate = 1
            Exit Function
        End Select
        
        BitRate = Brate(BinToDec(Mid(bin, 17, 4)))
    End If
    
    'if there is a decimal place, then parse it off
    If InStr(1, BitRate, ".") Then
        BitRate = Left(BitRate, InStr(1, BitRate, ".") - 1)
    End If
    
    
    NoYes = Array("no", "yes")
    
    'Set original bit
    Original = NoYes(Mid(bin, 30, 1))
    'Set copyright bit
    CopyRight = NoYes(Mid(bin, 29, 1))
    'get padding bit
    Padding = NoYes(Mid(bin, 23, 1))
    'get private bit
    PrivateBit = NoYes(Mid(bin, 24, 1))
    'CRC table
    YesNo = Array("yes", "no")
    'Get CRC
    CRC = YesNo(Mid(bin, 16, 1))
    'calculate duration
    ms = (FileLen(FileName) * 8) / BitRate
    Duration = Int(ms / 1000)
    Duration = Duration \ 60 & "m " & Duration - (Duration \ 60) * 60 & "s"
    
    'populate type with info
    With GetMP3Info
        .BitRate = BitRate
        .CRC = CRC
        .Duration = Duration
        .Emphasis = Emphasis
        .Frequency = Frequency
        .Mode = Mode
        .MpegLayer = MpegLayer
        .MpegVersion = MpegVersion
        .Padding = Padding
        .Original = Original
        .CopyRight = CopyRight
        .PrivateBit = PrivateBit
    End With
    
    
    'if var are empty then populate them with "n/a"
    With GetMP3Info
        If .Artist = "" Then
            .Artist = "n/a"
        End If
        If .Album = "" Then
            .Album = "n/a"
        End If
        If .SongName = "" Then
            .SongName = "n/a"
        End If
        If .Track = "" Then
            .Track = "n/a"
        End If
        If .BitRate = "" Then
            .BitRate = "n/a"
        End If
        If .Frequency = "" Then
            .Frequency = "n/a"
        End If
        If .Duration = "" Then
            .Duration = "n/a"
        End If
        If .Year = "" Then
            .Year = "n/a"
        End If
        If .Comment = "" Then
            .Comment = "n/a"
        End If
        If .Genre = "" Then
            .Genre = "n/a"
        End If
    End With
    
    'place info in byref vars
    With GetMP3Info
        rArtist = .Artist
        rAlbum = .Album
        rSongname = .SongName
        rTrack = .Track
        rBitRate = .BitRate
        rFrequency = .Frequency
        rDuration = .Duration
        rYear = .Year
        rComment = .Comment
        rGenre = .Genre
    End With

    ReadMP3 = True
    Exit Function
    
ErrHand:
    MsgBox Err.Number & " " & Err.Description
    Close #1
    Close #2
    
    
End Function


Private Function BinToDec(BinValue As String) As Long
    BinToDec = 0
    For I = 1 To Len(BinValue)
        If Mid(BinValue, I, 1) = 1 Then
            BinToDec = BinToDec + 2 ^ (Len(BinValue) - I)
        End If
    Next I
End Function
Private Function ByteToBit(ByteArray) As String
    'convert 4*1 byte array to 4*8 bits'''''
    ByteToBit = ""
    For Z = 1 To 4
        For I = 7 To 0 Step -1
            If Int(ByteArray(Z) / (2 ^ I)) = 1 Then
                ByteToBit = ByteToBit & "1"
                ByteArray(Z) = ByteArray(Z) - (2 ^ I)
            ElseIf ByteToBit <> "" Then
                ByteToBit = ByteToBit & "0"
            End If
        Next
    Next Z
End Function
Private Function BinaryHeader(ByVal FileName As String, ReadTag As Boolean, ReadHeader As Boolean) As String
    On Error GoTo ErrHand
    
    Dim ByteArray(4) As Byte
    Dim XingH As String * 4
    Dim LenMP3 As Long
    
    
    FIO% = FreeFile
    
    Open FileName For Binary Access Read As FIO%
        LenMP3 = LOF(FIO%)
        If LOF(FIO%) < 256 Then
            Close FIO%
            Exit Function
        End If
        
        If ReadHeader = True Then
            Dim x As Byte
            '''''start check startposition for header''''''''''''
            '''''if start position <>1 then id3v2 tag exists'''''
            For I = 1 To 5000            'check up to 5000 bytes for the header
                Get #FIO%, I, x
                If x = 255 Then             'header always start with 255 followed by 250 or 251
                    Get #FIO%, I + 1, x
                    If x > 249 And x < 252 Then
                        Headstart = I       'set header start position
                        Exit For
                    End If
                End If
            Next I
            '''end check start position for header'''''''''''''
        
            ''start check for XingHeader'''
            Get #1, Headstart + 36, XingH
            If XingH = "Xing" Then
                GetMP3Info.VBR = True
                For Z = 1 To 4 '
                    Get #1, Headstart + 43 + Z, ByteArray(Z)  'get framelength to array
                Next Z
                Frames = BinToDec(ByteToBit(ByteArray))   'calculate # of frames
                GetMP3Info.Frames = Frames                'set frames
            Else: GetMP3Info.VBR = False
            End If
            '''end check for XingHeader
        
            '''start extract the first 4 bytes (32 bits) to an array
            For Z = 1 To 4 '
                Get #1, Headstart + Z - 1, ByteArray(Z)
            Next Z
            '''stop extract the first 4 bytes (32 bits) to an array
        End If
        
        If ReadTag = True Then
            ReadFile FileName
        End If
        
    Close FIO%
    BinaryHeader = ByteToBit(ByteArray)
    
    Exit Function
    
    
ErrHand:
    Close FIO%
    
    
End Function
Private Function GetGenreFromID(ByVal strListGenre As Integer) As String
    Dim GenreArray() As String
    Const sGenreMatrix = " |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|Alt. Rock|Bass|Soul|Punk|Space|Meditative|" & _
    "Instrumental Pop|Instrumental Rock|Ethnic|Gothic|Darkwave|Techno-Industrial|Electronic|" & _
    "Pop-Folk|Eurodance|Dream|Southern Rock|Comedy|Cult|Gangsta Rap|Top 40|Christian Rap|" & _
    "Pop/Punk|Jungle|Native American|Cabaret|New Wave|Phychedelic|Rave|Showtunes|Trailer|" & _
    "Lo-Fi|Tribal|Acid Punk|Acid Jazz|Polka|Retro|Musical|Rock & Roll|Hard Rock|Folk|" & _
    "Folk/Rock|National Folk|Swing|Fast-Fusion|Bebob|Latin|Revival|Celtic|Blue Grass|" & _
    "Avantegarde|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|Brit Pop|Negerpunk|Polsk Punk|" & _
    "Beat|Christian Gangsta Rap|Heavy Metal|Black Metal|Crossover|Comteporary Christian|" & _
    "Christian Rock|Merengue|Salsa|Trash Metal|Anime|JPop|Synth Pop"
    
    'Populate the array
    GenreArray = Split(sGenreMatrix, "|")
    
    If strListGenre = 0 Then
        GetGenreFromID = "Blues"
    ElseIf strListGenre = 1 Then
        GetGenreFromID = "Classic Rock"
    ElseIf strListGenre = 2 Then
        GetGenreFromID = "Country"
    ElseIf strListGenre = 3 Then
        GetGenreFromID = "Dance"
    ElseIf strListGenre = 4 Then
        GetGenreFromID = "Disco"
    ElseIf strListGenre = 5 Then
        GetGenreFromID = "Funk"
    ElseIf strListGenre = 6 Then
        GetGenreFromID = "Grunge"
    ElseIf strListGenre = 7 Then
        GetGenreFromID = "Hip-Hop"
    ElseIf strListGenre = 8 Then
        GetGenreFromID = "Jazz"
    ElseIf strListGenre = 9 Then
        GetGenreFromID = "Metal"
    ElseIf strListGenre = 10 Then
        GetGenreFromID = "New Age"
    ElseIf strListGenre = 11 Then
        GetGenreFromID = "Oldies"
    ElseIf strListGenre = 12 Then
        GetGenreFromID = "Other"
    ElseIf strListGenre = 13 Then
        GetGenreFromID = "Pop"
    ElseIf strListGenre = 14 Then
        GetGenreFromID = "R&B"
    ElseIf strListGenre = 15 Then
        GetGenreFromID = "Rap"
    ElseIf strListGenre = 16 Then
        GetGenreFromID = "Reggae"
    ElseIf strListGenre = 17 Then
        GetGenreFromID = "Rock"
    ElseIf strListGenre = 18 Then
        GetGenreFromID = "Techno"
    ElseIf strListGenre = 19 Then
        GetGenreFromID = "Industrial"
    ElseIf strListGenre = 20 Then
        GetGenreFromID = "Alternative"
    ElseIf strListGenre = 21 Then
        GetGenreFromID = "Ska"
    ElseIf strListGenre = 22 Then
        GetGenreFromID = "Death Metal"
    ElseIf strListGenre = 23 Then
        GetGenreFromID = "Pranks"
    ElseIf strListGenre = 24 Then
        GetGenreFromID = "Soundtrack"
    ElseIf strListGenre = 25 Then
        GetGenreFromID = "Euro-Techno"
    ElseIf strListGenre = 26 Then
        GetGenreFromID = "Ambient"
    ElseIf strListGenre = 27 Then
        GetGenreFromID = "Trip-Hop"
    ElseIf strListGenre = 28 Then
        GetGenreFromID = "Vocal"
    ElseIf strListGenre = 29 Then
        GetGenreFromID = "Jazz+Funk"
    ElseIf strListGenre = 30 Then
        GetGenreFromID = "Fusion"
    ElseIf strListGenre = 31 Then
        GetGenreFromID = "Trance"
    ElseIf strListGenre = 32 Then
        GetGenreFromID = "Classical"
    ElseIf strListGenre = 33 Then
        GetGenreFromID = "Instrumental"
    ElseIf strListGenre = 34 Then
        GetGenreFromID = "Acid"
    ElseIf strListGenre = 35 Then
        GetGenreFromID = "House"
    ElseIf strListGenre = 36 Then
        GetGenreFromID = "Game"
    ElseIf strListGenre = 37 Then
        GetGenreFromID = "Sound Clip"
    ElseIf strListGenre = 38 Then
        GetGenreFromID = "Gospel"
    ElseIf strListGenre = 39 Then
        GetGenreFromID = "Noise"
    ElseIf strListGenre = 40 Then
        GetGenreFromID = "AlternRock"
    ElseIf strListGenre = 41 Then
        GetGenreFromID = "Bass"
    ElseIf strListGenre = 42 Then
        GetGenreFromID = "Soul"
    ElseIf strListGenre = 43 Then
        GetGenreFromID = "Punk"
    ElseIf strListGenre = 44 Then
        GetGenreFromID = "Space"
    ElseIf strListGenre = 45 Then
        GetGenreFromID = "Meditative"
    ElseIf strListGenre = 46 Then
        GetGenreFromID = "Instrumental Pop"
    ElseIf strListGenre = 47 Then
        GetGenreFromID = "Instrumental Rock"
    ElseIf strListGenre = 48 Then
        GetGenreFromID = "Ethnic"
    ElseIf strListGenre = 49 Then
        GetGenreFromID = "Gothic"
    ElseIf strListGenre = 50 Then
        GetGenreFromID = "Darkwave"
    ElseIf strListGenre = 51 Then
        GetGenreFromID = "Techno-Indistrial"
    ElseIf strListGenre = 52 Then
        GetGenreFromID = "Electronic"
    ElseIf strListGenre = 53 Then
        GetGenreFromID = "Pop-Folk"
    ElseIf strListGenre = 54 Then
        GetGenreFromID = "Eurodance"
    ElseIf strListGenre = 55 Then
        GetGenreFromID = "Dream"
    ElseIf strListGenre = 56 Then
        GetGenreFromID = "Southern Rock"
    ElseIf strListGenre = 57 Then
        GetGenreFromID = "Comedy"
    ElseIf strListGenre = 58 Then
        GetGenreFromID = "Cult"
    ElseIf strListGenre = 59 Then
        GetGenreFromID = "Gansta"
    ElseIf strListGenre = 60 Then
        GetGenreFromID = "Top 40"
    ElseIf strListGenre = 61 Then
        GetGenreFromID = "Christian Rap"
    ElseIf strListGenre = 62 Then
        GetGenreFromID = "Pop/Funk"
    ElseIf strListGenre = 63 Then
        GetGenreFromID = "Jungle"
    ElseIf strListGenre = 64 Then
        GetGenreFromID = "Native American"
    ElseIf strListGenre = 65 Then
        GetGenreFromID = "Cabaret"
    ElseIf strListGenre = 66 Then
        GetGenreFromID = "New Wave"
    ElseIf strListGenre = 67 Then
        GetGenreFromID = "Psychaledic"
    ElseIf strListGenre = 68 Then
        GetGenreFromID = "Rave"
    ElseIf strListGenre = 69 Then
        GetGenreFromID = "Showtunes"
    ElseIf strListGenre = 70 Then
        GetGenreFromID = "Trailer"
    ElseIf strListGenre = 71 Then
        GetGenreFromID = "Lo-Fi"
    ElseIf strListGenre = 72 Then
        GetGenreFromID = "Tribal"
    ElseIf strListGenre = 73 Then
        GetGenreFromID = "Acid Punk"
    ElseIf strListGenre = 74 Then
        GetGenreFromID = "Acid Jazz"
    ElseIf strListGenre = 75 Then
        GetGenreFromID = "Polka"
    ElseIf strListGenre = 76 Then
        GetGenreFromID = "Retro"
    ElseIf strListGenre = 77 Then
        GetGenreFromID = "Musical"
    ElseIf strListGenre = 78 Then
        GetGenreFromID = "Rock & Roll"
    ElseIf strListGenre = 79 Then
        GetGenreFromID = "Hard Rock"
    ElseIf strListGenre = 80 Then
        GetGenreFromID = "Folk"
    ElseIf strListGenre = 81 Then
        GetGenreFromID = "Folk-Rock"
    ElseIf strListGenre = 82 Then
        GetGenreFromID = "National Folk"
    ElseIf strListGenre = 83 Then
        GetGenreFromID = "Swing"
    ElseIf strListGenre = 84 Then
        GetGenreFromID = "Fast Fusion"
    ElseIf strListGenre = 85 Then
        GetGenreFromID = "Bebop"
    ElseIf strListGenre = 86 Then
        GetGenreFromID = "Latin"
    ElseIf strListGenre = 87 Then
        GetGenreFromID = "Revival"
    ElseIf strListGenre = 88 Then
        GetGenreFromID = "Celtic"
    ElseIf strListGenre = 89 Then
        GetGenreFromID = "Bluegrass"
    ElseIf strListGenre = 90 Then
        GetGenreFromID = "Avantgarde"
    ElseIf strListGenre = 91 Then
        GetGenreFromID = "Gothic Rock"
    ElseIf strListGenre = 92 Then
        GetGenreFromID = "Progressive Rock"
    ElseIf strListGenre = 93 Then
        GetGenreFromID = "Psychadelic Rock"
    ElseIf strListGenre = 94 Then
        GetGenreFromID = "Symphonic Rock"
    ElseIf strListGenre = 95 Then
        GetGenreFromID = "Slow Rock"
    ElseIf strListGenre = 96 Then
        GetGenreFromID = "Big Band"
    ElseIf strListGenre = 97 Then
        GetGenreFromID = "Chorus"
    ElseIf strListGenre = 98 Then
        GetGenreFromID = "Easy Listening"
    ElseIf strListGenre = 99 Then
        GetGenreFromID = "Acoustic"
    ElseIf strListGenre = 100 Then
        GetGenreFromID = "Humour"
    ElseIf strListGenre = 101 Then
        GetGenreFromID = "Speech"
    ElseIf strListGenre = 102 Then
        GetGenreFromID = "Chanson"
    ElseIf strListGenre = 103 Then
        GetGenreFromID = "Opera"
    ElseIf strListGenre = 104 Then
        GetGenreFromID = "Chamber Music"
    ElseIf strListGenre = 105 Then
        GetGenreFromID = "Sonata"
    ElseIf strListGenre = 106 Then
        GetGenreFromID = "Symphony"
    ElseIf strListGenre = 107 Then
        GetGenreFromID = "Booty Bass"
    ElseIf strListGenre = 108 Then
        GetGenreFromID = "Primus"
    ElseIf strListGenre = 109 Then
        GetGenreFromID = "Porn Groove"
    ElseIf strListGenre = 110 Then
        GetGenreFromID = "Satire"
    ElseIf strListGenre = 111 Then
        GetGenreFromID = "Slow Jam"
    ElseIf strListGenre = 112 Then
        GetGenreFromID = "Club"
    ElseIf strListGenre = 113 Then
        GetGenreFromID = "Tango"
    ElseIf strListGenre = 114 Then
        GetGenreFromID = "Samba"
    ElseIf strListGenre = 115 Then
        GetGenreFromID = "Folklore"
    ElseIf strListGenre = 116 Then
        GetGenreFromID = "Ballad"
    ElseIf strListGenre = 117 Then
        GetGenreFromID = "Power Ballad"
    ElseIf strListGenre = 118 Then
        GetGenreFromID = "Rhythmic Soul"
    ElseIf strListGenre = 119 Then
        GetGenreFromID = "Freestyle"
    ElseIf strListGenre = 120 Then
        GetGenreFromID = "Duet"
    ElseIf strListGenre = 121 Then
        GetGenreFromID = "Punk Rock"
    ElseIf strListGenre = 122 Then
        GetGenreFromID = "Drum Solo"
    ElseIf strListGenre = 123 Then
        GetGenreFromID = "A Capella"
    ElseIf strListGenre = 124 Then
        GetGenreFromID = "Euro-House"
    ElseIf strListGenre = 125 Then
        GetGenreFromID = "Dance Hall"
    End If

End Function



