無外部控件製作多媒體播放器(三)

ASF全名爲高級系統格式,是MS大力推寵的一種媒體格式,並已得到廣泛支持。其最主要的分支就是用於音頻的WMA與視頻的WMV,當然還有ASF自身。
在下面地址可下載到ASF格式的說明文檔:
http://www.microsoft.com/windows/windowsmedia/format/asfspec.aspx

ASF格式由一個個不同功能的ASF對象組成,每個對象都有一個GUID做標識,你只需識別對象後,按對象格式讀結構,就能找到你要的信息。
媒體信息內容都在ASF頭部對象ASF_Header_Object中,頭部對象又包含若干子對象,其中與媒體信息有關的對象也就三個:ASF_Codec_List_Object、ASF_Content_Description_Object、ASF_Extended_Content_Description_Object,本文也就是針對這三個對象的讀寫。

'ASF格式的幾個與音樂信息相關的對象
Private Const ASF_Header_Object = "{75B22630-668E-11CF-A6D9-00AA0062CE6C}"
Private Const ASF_Codec_List_Object = "{86D15240-311D-11D0-A3A4-00A0C90348F6}"
Private Const ASF_Content_Description_Object = "{75B22633-668E-11CF-A6D9-00AA0062CE6C}"
Private Const ASF_Extended_Content_Description_Object = "{D2D0A440-E307-11D2-97F0-00A0C95EA850}"
'GUID對象標識
Private Type GUID
    dwData1 As Long
    wData2 As Integer
    wData3 As Integer
    abData4(7) As Byte
End Type
'音樂類型,我自己定義的,不是標準喲
Private Enum MediaType
    mciMIDI = 1
    mciMP3 = 2
    mciASF = 4
    mciVIDEO = 8
    mciWAVE = 16
End Enum
'裝載音樂信息的結構
Private Type MusicInfo
    FileName As String
    MusicType As MediaType
    Title As String
    Artist As String
    Album As String
    Year As String
    Lyrics As String
    Writer As String
    Composer As String
    Bits As String
    Sample As String
    Length As Long
End Type
'ASF對象標識結構
Private Type ObjHeader
  ID As GUID
  Size(1) As Long
End Type
'ASF文件頭對象結構
Private Type ASFHeader
    HeaderInfo As ObjHeader
    NumOfHeader As Long
    Reserved1 As Byte
    Reserved2 As Byte
End Type
'ASF內容描述結構
Private Type ContentDescription
    TitleLength As Integer
    AuthorLength As Integer
    CopyrightLength As Integer
    DescriptionLength As Integer
    RatingLength As Integer
End Type
'ASF描述標籤結構
Private Type DescriptorValue
    Type As Integer
    Length As Integer
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Private Declare Function StringFromCLSID Lib "ole32" (pclsid As GUID, lpsz As Long) As Long

Private Function GUIDToStr(ID As GUID) As String
    Dim s As String, i As Long, j As Long
    s = Space(38)
    j = StringFromCLSID(ID, i)
    If j = 0 Then
        CopyMemory ByVal StrPtr(s), ByVal i, 76
        GUIDToStr = s
    End If
End Function

Private Function GetASFInfo(udtInfo As MusicInfo) As Boolean
    Dim asfh As ASFHeader, bo As ObjHeader, TmpInfo As MusicInfo
    Dim fd As ContentDescription, dv As DescriptorValue, gd As GUID
    Dim a() As String, b() As Byte, Pos As Long, FreeNo As Integer, efl As Integer
    Dim s As String, i As Long, k As Integer, l As Long, j As Long
    Dim en As String, vl As String
   
    On Error GoTo fail
    FreeNo = FreeFile
    Pos = 1
    Open udtInfo.FileName For Binary As #FreeNo
    TmpInfo = udtInfo
    With TmpInfo
        Get #FreeNo, Pos, asfh
        s = GUIDToStr(asfh.HeaderInfo.ID)
        If s <> ASF_Header_Object Then GoTo fail
        Pos = Pos + Len(asfh)
        For l = 1 To asfh.NumOfHeader
            Get #FreeNo, Pos, bo
            s = GUIDToStr(bo.ID)
            Select Case s
                Case ASF_Codec_List_Object
                    Get #FreeNo, , gd
                    Get #FreeNo, , i
                    For j = 1 To i
                        Get #FreeNo, , dv
                        ReDim b(dv.Length * 2 - 1)
                        Get #FreeNo, , b
                        Get #FreeNo, , efl
                        ReDim b(efl * 2 - 1)
                        Get #FreeNo, , b
                        en = b
                        en = Trim$(Replace$(en, vbNullChar, ""))
                        If dv.Type = 2 Then
                            If InStr(1, en, ",") > 0 Then
                                a = Split(en, ",")
                                If InStr(1, a(0), "kbps", vbTextCompare) > 0 Then
                                    .Bits = Val(a(0)) & "Kbps"
                                End If
                                If InStr(1, a(1), "khz", vbTextCompare) > 0 Then
                                    .Sample = Val(a(1)) & "KHz"
                                End If
                            End If
                        ElseIf dv.Type = 1 Then '這裏可以取到視頻格式信息,因爲自己沒這個目的,就沒寫了
                            .MusicType = .MusicType Or mciVIDEO
                        End If
                        Get #FreeNo, , efl
                        ReDim b(efl - 1)
                        Get #FreeNo, , b
                    Next
                Case ASF_Content_Description_Object
                    Get #FreeNo, , fd
                    ReDim b(fd.TitleLength - 1)
                    Get #FreeNo, , b
                    en = b
                    en = Trim$(Replace$(en, vbNullChar, ""))
                    .Title = en
                    ReDim b(fd.AuthorLength - 1)
                    Get #FreeNo, , b
                    en = b
                    en = Trim$(Replace$(en, vbNullChar, ""))
                    .Artist = en
                    If Val(.Year) < 1900 Or Val(.Year) > 2100 Then
                        ReDim b(fd.CopyrightLength - 1)
                        Get #FreeNo, , b
                        en = b
                        en = Trim$(Replace$(en, vbNullChar, ""))
                        a = Split(en, " ")
                        For i = 0 To UBound(a)
                            If Val(a(i)) > 0 Then
                                .Year = Val(a(i))
                                Exit For
                            End If
                        Next
                    End If
                Case ASF_Extended_Content_Description_Object
                    Get #FreeNo, , k
                    For j = 1 To k
                        Get #FreeNo, , efl
                        ReDim b(efl - 1)
                        Get #FreeNo, , b
                        en = b
                        en = LCase$(Trim$(Replace$(en, vbNullChar, "")))
                        Get #FreeNo, , dv
                        Select Case dv.Type
                            Case 0, 1
                                ReDim b(dv.Length - 1)
                                Get #FreeNo, , b
                                vl = b
                                vl = Trim$(Replace$(vl, vbNullChar, ""))
                                Select Case en
                                    Case "title"
                                        .Title = vl
                                    Case "author"
                                        If .Artist = "" Then .Artist = vl
                                    Case "wm/albumartist"
                                        .Artist = vl
                                    Case "wm/writer"
                                        .Writer = vl
                                    Case "wm/composer"
                                        .Composer = vl
                                    Case "wm/albumtitle"
                                        .Album = vl
                                    Case "wm/lyrics"
                                        .Lyrics = Replace$(vl, "  ", " ")
                                    Case "wm/originalreleaseyear"
                                        If .Year = "" Then .Year = Val(vl)
                                    Case "wm/year"
                                        .Year = Val(vl)
                                End Select
                            Case 2, 3
                                ReDim b(3)
                                Get #FreeNo, , b
                            Case 4
                                ReDim b(7)
                                Get #FreeNo, , b
                            Case 5
                                ReDim b(1)
                                Get #FreeNo, , b
                        End Select
                    Next
            End Select
            Pos = Pos + bo.Size(0)
        Next
    End With
    udtInfo = TmpInfo
    GetASFInfo = True
fail:
    Close #FreeNo
End Function

Private Sub Command1_Click()
    Dim i As Long, inf As MusicInfo, s As String
    inf.FileName = Text1.Text
    If GetMusicInfo(inf) Then
        s = "文件:" & inf.FileName & vbCrLf
        s = s & "歌名:" & inf.Title & vbCrLf
        s = s & "唱片:" & inf.Album & vbCrLf
        s = s & "歌手:" & inf.Artist & vbCrLf
        s = s & "作詞:" & inf.Writer & vbCrLf
        s = s & "作曲:" & inf.Composer & vbCrLf
        s = s & "年代:" & inf.Year & vbCrLf
        s = s & "採樣:" & inf.Bits & vbCrLf
        s = s & "位率:" & inf.Sample & vbCrLf
        s = s & "歌詞:" & inf.Lyrics
    Else
        s = "無法取音樂信息"
    End If
    MsgBox s
End Sub

這是一個與上篇相聯繫的代碼,對於一些沒定義的函數,可在前面的文章中找到
http://blog.csdn.net/homezj/archive/2005/04/15/349005.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章