Below you'll find the source for the Visual Basic 6 function get_audio_tag.
Attribute VB_Name = "modGetAudioTag"
' These functions are downloaded from:
' http://www.stefanthoolen.nl/archive/vb6-functions/
'
' You may freely distribute this file but please leave all comments, including this one, in it.
'
' @Author Stefan Thoolen <mail@stefanthoolen.nl>
Option Explicit
Public Type audio_tag
type As String
has_track As Boolean
track As Integer
artist As String
title As String
album As String
year As String
genre As String
comment As String
End Type
' Public type, will contain all fetched information
Public Type asf_tag
FP_Playtime As Long
FP_Filesize As Long
FP_Bitrate As Long
CD_Found As Boolean
CD_Title As String
CD_Author As String
CD_Copyright As String
CD_Description As String
CD_Rating As String
ECD_Found As Boolean
ECD_Genre As String
ECD_AlbumTitle As String
ECD_Track As Integer
ECD_TrackNumber As Integer
ECD_Year As String
ECD_Composer As String
End Type
' Used to send back the ID3 tag to the application
' This is different from id3v2_header and id3v2_tag_frame since this type does not have string lengths defined
' Also some reformatting has been done so usage will be more user friendly
Public Type id3v2_tag
has_tag As Boolean
tag_version As String
artist As String
title As String
album As String
year As String
comment As String
comment_language As String
genre As String
track As String
other_tags() As String
other_tags_cnt As Integer
End Type
' Used to send back the ID3 tag to the application
' This is different from id3v1_file_footer since this type does not have string lengths defined
' Also some reformatting has been done so usage will be more user friendly
Public Type id3v1_tag
has_tag As Boolean
artist As String
title As String
album As String
year As String
has_trackno As Boolean
trackno As Byte
comment As String
genre_id As Byte
genre_text As String
speed As Byte
End Type
' For internal use, a structure to read the ASF_File_Properties_Object
Private Type ASF_File_Properties
fileid_guid As String * 16
filesize1 As Long ' QuadWORD
filesize2 As Long ' ^^^^^^^^
creation_date1 As Long ' QuadWORD
creation_date2 As Long ' ^^^^^^^^
data_packets1 As Long ' QuadWORD
data_packets2 As Long ' ^^^^^^^^
play_duration1 As Long ' QuadWORD
play_duration2 As Long ' ^^^^^^^^
send_duration1 As Long ' QuadWORD
send_duration2 As Long ' ^^^^^^^^
preroll1 As Long ' QuadWORD
preroll2 As Long ' ^^^^^^^^
flags_raw As Long ' DoubleWORD
min_packet_size As Long ' DoubleWORD
max_packet_size As Long ' DoubleWORD
max_bitrate As Long ' DoubleWORD
End Type
' For internal use, a structure to read ContentDescription sizes
Private Type ASF_CD_Lengths
title_len As Integer
author_len As Integer
copyright_len As Integer
description_len As Integer
rating_len As Integer
End Type
' ID3v2 tag frame
Private Type id3v2_tag_frame
frame_id As String * 4
framesize As String * 4
flag_byte1 As Byte
flag_byte2 As Byte
End Type
' ID3v2 file header
Private Type id3v2_header
identifier As String * 3
'major_ver is always 2 and therefor not in the header
minor_ver As Byte
revision As Byte
flags As Byte
tagsize_byte1 As Byte
tagsize_byte2 As Byte
tagsize_byte3 As Byte
tagsize_byte4 As Byte
End Type
' Used to read the ID3 tag from the file
Private Type id3v1_file_footer
Ext_Header As String * 4
Ext_Title As String * 60
Ext_Artist As String * 60
Ext_Album As String * 60
Ext_Speed As Byte
Ext_Genre As String * 30
Ext_StartTime As String * 6
Ext_EndTime As String * 6
header As String * 3
SongTitle As String * 30
artist As String * 30
album As String * 30
year As String * 4
comment As String * 28
ZeroByte As Byte
trackno As Byte
genre As Byte
End Type
''
' Combines two Long values to one variant (for QuadWORDs)
' @param long long1 The first value
' @param long long2 The second value
' @return Variant Both values combined
' @author Steven Don <www.shdon.com>
Public Function two_longs_to_variant(long1 As Long, long2 As Long) As Double
Dim ret As Double
Dim bit31 As Double, bit63 As Double
bit31 = &H8000
bit31 = bit31 * &H10000
bit63 = bit31 * bit31
bit63 = bit63 * 2
'Move long2 into upper 32 bits, excluding sign bit
ret = (long2 And &H7FFFFFFF)
ret = ret * &H10000
ret = ret * &H10000
'Move long1 into lower 31 bits
ret = ret + (long1 And &H7FFFFFFF)
'Take care of sign bits
If (long1 < 0) Then ret = ret + bit31
If (long2 < 0) Then ret = ret + bit63
two_longs_to_variant = ret
End Function
''
' Converts a heximal string to a decimal integer
' Same syntax as the PHP function 'hexdec'
' See also: http://www.php.net/manual/en/function.hexdec.php
' @param String hex_string The heximal string
' @return Integer An integer value
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function hexdec(hex_string As String) As Integer
hexdec = Val("&h" & hex_string)
End Function
''
' Converts a String to a binary GUID
' @param string GUID The GUID, for example "{01234567-89AB-CDEF-0123-456789ABCDEF}"
' @return string A binary string, always 16 bytes
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function GUIDFromString(ByVal GUID As String) As String
' The return value will be built in here
Dim ret As String
' Multiple used variables
Dim s As String, i As Integer
' Removes some formatting characters
GUID = Replace(GUID, "-", "")
If Left(GUID, 1) = "{" And Right(GUID, 1) = "}" Then GUID = Mid(GUID, 2, Len(GUID) - 2)
' The first part
s = Left(GUID, 8)
For i = 7 To 1 Step -2
ret = ret & Chr(hexdec(Mid(s, i, 2)))
Next i
' The second part
s = Mid(GUID, 9, 4)
For i = 3 To 1 Step -2
ret = ret & Chr(hexdec(Mid(s, i, 2)))
Next i
' The third part
s = Mid(GUID, 13, 4)
For i = 3 To 1 Step -2
ret = ret & Chr(hexdec(Mid(s, i, 2)))
Next i
' The forth part
s = Right(GUID, 16)
For i = 1 To 15 Step 2
ret = ret & Chr(hexdec(Mid(s, i, 2)))
Next i
GUIDFromString = ret
End Function
''
' Reads an ASF (WMA) tag
' @param String FileName The filename of which we need the tags
' @return asf_tag The tag elements
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function asf_get_tag(filename As String) As asf_tag
' Variables with multiple uses
Dim s As String, gs As String * 16, i As Integer
' The return value
Dim ret As asf_tag
' AFS works with different GUIDs. I wrote them down like this:
Dim ASF_Header_Object As String * 16
Dim ASF_Content_Description_Object As String * 16
Dim ASF_Extended_Content_Description_Object As String * 16
Dim ASF_File_Properties_Object As String * 16
ASF_Header_Object = GUIDFromString("75B22630-668E-11CF-A6D9-00AA0062CE6C")
ASF_Content_Description_Object = GUIDFromString("75B22633-668E-11CF-A6D9-00AA0062CE6C")
ASF_Extended_Content_Description_Object = GUIDFromString("D2D0A440-E307-11D2-97F0-00A0C95EA850")
ASF_File_Properties_Object = GUIDFromString("8CABDCA1-A947-11CF-8EE4-00C00C205365")
Dim ff As Integer
ff = FreeFile
Open filename For Binary Access Read As #ff
Get #ff, 1, gs
If gs = ASF_Header_Object Then
Dim header_len As Long, header_objects As Long, object_len As Long
s = String(8, 0): Get #ff, , s: header_len = change_endian(s) ' Length of the header
s = String(4, 0): Get #ff, , s: header_objects = change_endian(s) ' Amount of objects
s = String(2, 0): Get #ff, , s ' Reserved1 & Reserved 2
' Loops through all header objects
Dim ho_i As Integer
For ho_i = 1 To header_objects
' Fetching next GUID
Get #ff, , gs
' Length of the object
s = String(8, 0): Get #ff, , s: object_len = change_endian(s)
If gs = ASF_Content_Description_Object Then
Dim cd_len As ASF_CD_Lengths
ret.CD_Found = True
Get #ff, , cd_len
s = String(cd_len.title_len, 0): Get #ff, , s: ret.CD_Title = Replace(s, Chr(0), "")
s = String(cd_len.author_len, 0): Get #ff, , s: ret.CD_Author = Replace(s, Chr(0), "")
s = String(cd_len.copyright_len, 0): Get #ff, , s: ret.CD_Copyright = Replace(s, Chr(0), "")
s = String(cd_len.description_len, 0): Get #ff, , s: ret.CD_Description = Replace(s, Chr(0), "")
s = String(cd_len.rating_len, 0): Get #ff, , s: ret.CD_Rating = Replace(s, Chr(0), "")
ElseIf gs = ASF_Extended_Content_Description_Object Then
Dim ecd_item_count As Integer
ret.ECD_Found = True
Get #ff, , ecd_item_count
For i = 1 To ecd_item_count
Dim ecd_namelen As Integer, ecd_name As String
Get #ff, , ecd_namelen
ecd_name = String(ecd_namelen, 0): Get #ff, , ecd_name
Dim ecd_valtype As Integer, ecd_vallen As Integer, ecd_value As String
Get #ff, , ecd_valtype
Get #ff, , ecd_vallen
ecd_value = String(ecd_vallen, 0): Get #ff, , ecd_value
ecd_name = Replace(ecd_name, Chr(0), "")
If ecd_valtype = 0 Or ecd_valtype = 1 Then
ecd_value = Replace(ecd_value, Chr(0), "")
Select Case LCase(ecd_name)
Case "wm/genre": ret.ECD_Genre = ecd_value
Case "wm/albumtitle": ret.ECD_AlbumTitle = ecd_value
Case "wm/year": ret.ECD_Year = ecd_value
Case "wm/composer": ret.ECD_Composer = ecd_value
Case Else: Rem MsgBox ecd_name & ": " & ecd_value
End Select
ElseIf ecd_valtype = 3 Then
Select Case LCase(ecd_name)
Case "wm/track": ret.ECD_Track = Asc(ecd_value)
Case "wm/tracknumber": ret.ECD_TrackNumber = Asc(ecd_value)
Case Else: Rem MsgBox ecd_name & ": " & Asc(ecd_value)
End Select
Else
Rem MsgBox ecd_valtype & ":" & ecd_name & ": " & Replace(ecd_value, Chr(0), "")
End If
Next i
ElseIf gs = ASF_File_Properties_Object Then
Dim fp As ASF_File_Properties, pt As Long
Get #ff, , fp
pt = (two_longs_to_variant(fp.play_duration1, fp.play_duration2) / 10000000) - (two_longs_to_variant(fp.preroll1, fp.preroll2) / 1000)
ret.FP_Playtime = pt
ret.FP_Filesize = two_longs_to_variant(fp.filesize1, fp.filesize2)
ret.FP_Bitrate = (ret.FP_Filesize * 8) / ret.FP_Playtime
Else
' Skips the data of this unknown block
' The length is minus 24, since the guid and length itself are also counted
s = String(object_len - 24, 0): Get #ff, , s
End If
Next ho_i
End If
Close #ff
asf_get_tag = ret
End Function
''
' When reading a binary file in another endian, this function can convert multiple bytes to a valid number
' @param string inp The bytes as string
' @return variant The actual number
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function change_endian(ByVal inp As String, Optional ByVal reverse As Boolean = False) As Variant
If Len(inp) = 0 Then change_endian = 0: Exit Function
Dim i As Integer, s As String
If reverse Then
For i = 1 To Len(inp)
s = s & zerofill(decbin(Asc(Mid(inp, i, 1))), 8)
Next i
Else
For i = Len(inp) To 1 Step -1
s = s & zerofill(decbin(Asc(Mid(inp, i, 1))), 8)
Next i
End If
change_endian = bindec(s)
End Function
''
' Trims all kind of whitespaces
' The VB6 trim() function only removes spaces, this function also removes null-chars, tabs, returns and linefeeds
' @param String txt The input text
' @return String The trimmed output text
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function RealTrim(ByVal txt As String) As String
Do
If Len(txt) = 0 Then
Exit Do
ElseIf Left(txt, 1) = Chr(0) Or _
Left(txt, 1) = vbTab Or _
Left(txt, 1) = " " Or _
Left(txt, 1) = vbCr Or _
Left(txt, 1) = vbLf Then
txt = Right(txt, Len(txt) - 1)
ElseIf Right(txt, 1) = Chr(0) Or _
Right(txt, 1) = vbTab Or _
Right(txt, 1) = " " Or _
Right(txt, 1) = vbCr Or _
Right(txt, 1) = vbLf Then
txt = Left(txt, Len(txt) - 1)
Else
Exit Do
End If
Loop
RealTrim = txt
End Function
''
' Makes a binary string from an integer number
' Same syntax as the PHP function 'decbin'
' See also: http://www.php.net/manual/en/function.decbin.php
' @param Integer number The decimal value
' @return String A binary presentation of the number (ex.: 00100111)
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function decbin(ByVal number As Integer) As String
Dim retval As String
Do Until number = 0
If (number Mod 2) Then retval = "1" & retval Else retval = "0" & retval
number = number \ 2
Loop
decbin = retval
End Function
''
' Makes an integer number from a binary string
' Same syntax as the PHP function 'bindec'
' See also: http://www.php.net/manual/en/function.bindec.php
' @param String binary_string The binary string (ex.: 00100111)
' @return Integer A decimal presentation of the binary value
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function bindec(binary_string As String) As Long
Dim i As Integer, pos As Integer, ret As Long
For i = 1 To Len(binary_string)
pos = Len(binary_string) - i
If Mid(binary_string, pos + 1, 1) = "1" Then ret = ret + (2 ^ (i - 1))
Next i
bindec = ret
End Function
''
' Completes a string by adding zero characters to the front
' @param string value The input string
' @param integer length The length the return value must be
' @param string character Optional, the character that should be used for filling, default: "0"
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function zerofill(ByVal value As String, ByVal length As Integer, Optional ByVal character = "0") As String
If Len(value) >= length Then zerofill = value: Exit Function
Dim i As Integer
Do
value = character & value
Loop While Len(value) < length
zerofill = value
End Function
''
' Reads an ID3v2-tag (to up to 2.3) from a file and returns it
' @param String FileName The filename of which we need the tags
' @return id3v2_tag The tag elements
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function id3v2_get_tag(ByVal filename As String) As id3v2_tag
' Some temporal reusable variables
Dim ff As Long, s As String
' Some internal values
Dim id3hdr As id3v2_header, retval As id3v2_tag, tagframe As id3v2_tag_frame
Dim tagsize As Long, unsynchronisation As Boolean, extended_header As Boolean, experimental_indicator As Boolean
ff = FreeFile
Open filename For Binary Access Read As #ff
Get #ff, 1, id3hdr
If id3hdr.identifier = "ID3" And id3hdr.minor_ver < 4 Then
' Some basic tag information
retval.has_tag = True
retval.tag_version = "2." & id3hdr.minor_ver & "." & id3hdr.revision
' Reading the flags
s = decbin(Val(id3hdr.flags))
If Mid(s, 8, 1) = "1" Then unsynchronisation = True
If Mid(s, 7, 1) = "1" Then extended_header = True
If Mid(s, 6, 1) = "1" Then experimental_indicator = True
' Reading the tag size
s = Left(zerofill(decbin(Val(id3hdr.tagsize_byte1)), 8), 7) ' The ID3v2 tag size is encoded with four bytes where the most
s = s & Left(zerofill(decbin(Val(id3hdr.tagsize_byte2)), 8), 7) ' significant bit (bit 7) is set to zero in every byte, making a total
s = s & Left(zerofill(decbin(Val(id3hdr.tagsize_byte3)), 8), 7) ' of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is
s = s & Left(zerofill(decbin(Val(id3hdr.tagsize_byte4)), 8), 7) ' represented as $00 00 02 01.
tagsize = bindec(s)
If extended_header Then
' Unsupported so far
retval.has_tag = False
id3v2_get_tag = retval
Close #ff
Exit Function
End If
' The ID3v2 tag size is the size of the complete tag after unsychronisation, including padding,
' excluding the header but not excluding the extended header (total tag size - 10).
Do While Seek(ff) < (tagsize + 10)
Get #ff, , tagframe
' Reading the actual value
s = String(change_endian(tagframe.framesize, True), 0): Get #ff, , s
Select Case UCase(tagframe.frame_id)
Case "TPE1": retval.artist = RealTrim(s)
Case "TIT2": retval.title = RealTrim(s)
Case "TALB": retval.album = RealTrim(s)
Case "TYER": retval.year = RealTrim(s)
Case "TCON": retval.genre = RealTrim(s)
Case "TRCK": retval.track = RealTrim(s)
Case "COMM"
' First byte: character encoding
' Three bytes: language
' Rest: Zero-byte with the actual value
retval.comment_language = Mid(s, 2, 3)
retval.comment = RealTrim(Mid(s, 5))
Case String(4, 0)
Exit Do
Case Else
ReDim Preserve retval.other_tags(0 To retval.other_tags_cnt)
retval.other_tags(retval.other_tags_cnt) = tagframe.frame_id & s
retval.other_tags_cnt = retval.other_tags_cnt + 1
End Select
Loop
End If
Close #ff
id3v2_get_tag = retval
End Function
''
' Returns the name of a genre number
' @param Byte id The number of the genre
' @return String The name of the genre
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function id3_genre_name(id As Byte) As String
Dim genre As String
Select Case id
Case 0: genre = "Blues"
Case 1: genre = "Classic Rock"
Case 2: genre = "Country"
Case 3: genre = "Dance"
Case 4: genre = "Disco"
Case 5: genre = "Funk"
Case 6: genre = "Grunge"
Case 7: genre = "Hip-Hop"
Case 8: genre = "Jazz"
Case 9: genre = "Metal"
Case 10: genre = "New Age"
Case 11: genre = "Oldies"
Case 12: genre = "Other"
Case 13: genre = "Pop"
Case 14: genre = "R&B"
Case 15: genre = "Rap"
Case 16: genre = "Reggae"
Case 17: genre = "Rock"
Case 18: genre = "Techno"
Case 19: genre = "Industrial"
Case 20: genre = "Alternative"
Case 21: genre = "Ska"
Case 22: genre = "Death Metal"
Case 23: genre = "Pranks"
Case 24: genre = "Soundtrack"
Case 25: genre = "Euro-Techno"
Case 26: genre = "Ambient"
Case 27: genre = "Trip-Hop"
Case 28: genre = "Vocal"
Case 29: genre = "Jazz+Funk"
Case 30: genre = "Fusion"
Case 31: genre = "Trance"
Case 32: genre = "Classical"
Case 33: genre = "Instrumental"
Case 34: genre = "Acid"
Case 35: genre = "House"
Case 36: genre = "Game"
Case 37: genre = "Sound Clip"
Case 38: genre = "Gospel"
Case 39: genre = "Noise"
Case 40: genre = "AlternRock"
Case 41: genre = "Bass"
Case 42: genre = "Soul"
Case 43: genre = "Punk"
Case 44: genre = "Space"
Case 45: genre = "Meditative"
Case 46: genre = "Instrumental Pop"
Case 47: genre = "Instrumental Rock"
Case 48: genre = "Ethnic"
Case 49: genre = "Gothic"
Case 50: genre = "Darkwave"
Case 51: genre = "Techno-Industrial"
Case 52: genre = "Electronic"
Case 53: genre = "Pop-Folk"
Case 54: genre = "Eurodance"
Case 55: genre = "Dream"
Case 56: genre = "Southern Rock"
Case 57: genre = "Comedy"
Case 58: genre = "Cult"
Case 59: genre = "Gangsta"
Case 60: genre = "Top 40"
Case 61: genre = "Christian Rap"
Case 62: genre = "Pop/Funk"
Case 63: genre = "Jungle"
Case 64: genre = "Native American"
Case 65: genre = "Cabaret"
Case 66: genre = "New Wave"
Case 67: genre = "Psychadelic"
Case 68: genre = "Rave"
Case 69: genre = "Showtunes"
Case 70: genre = "Trailer"
Case 71: genre = "Lo-Fi"
Case 72: genre = "Tribal"
Case 73: genre = "Acid Punk"
Case 74: genre = "Acid Jazz"
Case 75: genre = "Polka"
Case 76: genre = "Retro"
Case 77: genre = "Musical"
Case 78: genre = "Rock & Roll"
Case 79: genre = "Hard Rock"
Case 80: genre = "Folk"
Case 81: genre = "Folk-Rock"
Case 82: genre = "National Folk"
Case 83: genre = "Swing"
Case 84: genre = "Fast Fusion"
Case 85: genre = "Bebob"
Case 86: genre = "Latin"
Case 87: genre = "Revival"
Case 88: genre = "Celtic"
Case 89: genre = "Bluegrass"
Case 90: genre = "Avantgarde"
Case 91: genre = "Gothic Rock"
Case 92: genre = "Progressive Rock"
Case 93: genre = "Psychedelic Rock"
Case 94: genre = "Symphonic Rock"
Case 95: genre = "Slow Rock"
Case 96: genre = "Big Band"
Case 97: genre = "Chorus"
Case 98: genre = "Easy Listening"
Case 99: genre = "Acoustic"
Case 100: genre = "Humour"
Case 101: genre = "Speech"
Case 102: genre = "Chanson"
Case 103: genre = "Opera"
Case 104: genre = "Chamber Music"
Case 105: genre = "Sonata"
Case 106: genre = "Symphony"
Case 107: genre = "Booty Bass"
Case 108: genre = "Primus"
Case 109: genre = "Porn Groove"
Case 110: genre = "Satire"
Case 111: genre = "Slow Jam"
Case 112: genre = "Club"
Case 113: genre = "Tango"
Case 114: genre = "Samba"
Case 115: genre = "Folklore"
Case 116: genre = "Ballad"
Case 117: genre = "Power Ballad"
Case 118: genre = "Rhythmic Soul"
Case 119: genre = "Freestyle"
Case 120: genre = "Duet"
Case 121: genre = "Punk Rock"
Case 122: genre = "Drum Solo"
Case 123: genre = "A capella"
Case 124: genre = "Euro-House"
Case 125: genre = "Dance Hall"
Case Else: genre = "Unknown"
End Select
id3_genre_name = genre
End Function
''
' Reads an ID3v1-tag from a file and returns it
' Supports ID3 version 1 with TAG+
' @param String FileName The filename of which we need the tags
' @return id3v1_tag The tag elements
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function id3v1_get_tag(ByVal filename As String) As id3v1_tag
On Error GoTo id3v1_get_tag_error
' At default we don't have a tag
id3v1_get_tag.has_tag = False
Dim file_footer As id3v1_file_footer
Dim ff As Long
ff = FreeFile
Open filename For Binary Access Read As #ff
Get #ff, LOF(ff) - (Len(file_footer) - 1), file_footer
Close #ff
' Not a valid ID3v1-tag
If file_footer.header <> "TAG" Then Exit Function
With id3v1_get_tag
.has_tag = True
.artist = Trim(Replace(file_footer.artist, Chr(0), ""))
.title = Trim(Replace(file_footer.SongTitle, Chr(0), ""))
.album = Trim(Replace(file_footer.album, Chr(0), ""))
.year = Trim(Replace(file_footer.year, Chr(0), ""))
.genre_id = file_footer.genre
If file_footer.ZeroByte = 0 Then
' Track number is specified, comment can only contain 28 characters
.has_trackno = True
.trackno = file_footer.trackno
.comment = Trim(Replace(file_footer.comment, Chr(0), ""))
Else
' Comment is 30 characters long and no track number is specified
.has_trackno = False
.comment = Trim(Replace(file_footer.comment & Chr(file_footer.ZeroByte) & Chr(file_footer.trackno), Chr(0), ""))
End If
' The tag can be extended according to the specifications
If file_footer.Ext_Header = "TAG+" Then
.artist = .artist & Trim(Replace(file_footer.Ext_Artist, Chr(0), ""))
.title = .title & Trim(Replace(file_footer.Ext_Title, Chr(0), ""))
.album = .album & Trim(Replace(file_footer.Ext_Artist, Chr(0), ""))
.genre_text = Trim(Replace(file_footer.Ext_Genre, Chr(0), ""))
.speed = file_footer.Ext_Speed
Else
.genre_text = id3_genre_name(.genre_id)
End If
End With
Exit Function
id3v1_get_tag_error:
Close #ff
End Function
''
' Reads the id3 or asf tags from an audio file
' @param String filename The audio file
' @return audio_tag A generic type with a few entries that exist in most tags
' @author Stefan Thoolen <mail@stefanthoolen.nl>
Public Function get_audio_tag(filename As String) As audio_tag
Dim id3v1 As id3v1_tag, id3v2 As id3v2_tag, asf As asf_tag
id3v1 = id3v1_get_tag(filename)
If id3v1.has_tag Then
With get_audio_tag
.type = "ID3v1.1.0"
.album = id3v1.album
.artist = id3v1.artist
.comment = id3v1.comment
.genre = id3v1.genre_text
.title = id3v1.title
.has_track = id3v1.has_trackno
.track = id3v1.trackno
.year = id3v1.year
End With
Exit Function
End If
id3v2 = id3v2_get_tag(filename)
If id3v2.has_tag Then
With get_audio_tag
.type = "ID3v" & id3v2.tag_version
.album = id3v2.album
.artist = id3v2.artist
.comment = id3v2.comment
.genre = id3v2.genre
.title = id3v2.title
If id3v2.track <> "" Then .has_track = True
.track = Val(id3v2.track)
.year = id3v2.year
End With
Exit Function
End If
asf = asf_get_tag(filename)
If asf.CD_Found Then
With get_audio_tag
.type = "ASF"
.album = asf.ECD_AlbumTitle
.artist = asf.CD_Author
.comment = asf.CD_Description
.genre = asf.ECD_Genre
.title = asf.CD_Title
If asf.ECD_Track > 0 Then .has_track = True: .track = asf.ECD_Track
If asf.ECD_TrackNumber > 0 Then .has_track = True: .track = asf.ECD_TrackNumber
.year = asf.ECD_Year
End With
Exit Function
End If
End Function