无外部控件制作多媒体播放器(二)

王朝other·作者佚名  2006-01-09
宽屏版  字体: |||超大  

本来想写点进度控制与音量调整的代码的,后来发现还是太简单了,就是几个MCI命令,来回搬弄,自己都没兴趣写下去。所以我想还是写些独门一点的:音乐信息的读取!

目前常见的主流音乐格式就两种,MP3与WMA,它们都有在文件中保存音乐信息的特定格式,MP3使用的当然是家喻户晓的ID3格式,分为V1与V2两个版本;WMA是MS的宠儿,它只是ASF格式的一个分支,当然遵循ASF的包装规则。

怎么获取它们包含的音乐信息呢?一般是自己读取,当然XP系统开始提供了音乐文件的详细信息资料,利用FSO可以真接从系统那里读取到,这不在本文范围,毕竟不用控件更自由,通用性更好。所以,有必要去深入一下这几种音乐信息格式。还是用代码说话吧,先说说MP3的ID3V1与ID3V2的格式。

ID3V1很简单,共128个字节,写在文件尾部,格式如下:

Private Type Mp3ID3V1

Header As String * 3

Title As String * 30

Artist As String * 30

Album As String * 30

Year As String * 4

Comment As String * 30

Genre As String * 1

End Type

ID3V2是后来出现的,可扩展性很强,写在文件头部,采用标签组格式,分两部分,一是标签组的总头部,一是每个子标签的头部,分别定义如下:

Private Type Mp3ID3V2

Header As String * 3

Ver As Byte

Revision As Byte

Flag As Byte

Size(3) As Byte

End Type

Private Type Mp3ID3V2Tag

Tag As String * 4

Size(3) As Byte

Flag(1) 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

'我习惯于用代码说明问题,所以还是看看代码吧

Private Function GetMusicInfo(udtInfo As MusicInfo) As Boolean

Dim strFileName As String, a() As String, i As Long

With udtInfo

strFileName = Dir(.FileName, vbNormal Or vbHidden Or vbReadOnly Or vbSystem Or vbArchive)

If strFileName = vbNullString Then Exit Function

.MusicType = GetMCIType(strFileName)

If .MusicType And mciMP3 Then

GetMusicInfo = GetMP3Info(udtInfo)

ElseIf .MusicType And mciASF Then

GetMusicInfo = GetASFInfo(udtInfo)

End If

End With

End Function

Private Function GetMCIType(strFileName As String) As MediaType

Dim ext As String

If strFileName <> vbNullString Then

ext = LCase$(Mid$(strFileName, InStrRev(strFileName, ".")))

Select Case ext

Case ".mpg", ".mpeg", ".avi", ".mpe", ".mpa", ".m1v", ".ifo", ".vob"

GetMCIType = mciVIDEO

Case ".mp3"

GetMCIType = mciMP3

Case ".wav", ".snd", ".aif", ".au", ".aifc", ".aiff"

GetMCIType = mciWAVE

Case ".asf", ".wma", ".wm", ".wmd"

GetMCIType = mciASF

Case ".wmv"

GetMCIType = mciASF Or mciVIDEO

Case ".mid", ".midi", ".rmi"

GetMCIType = mciMIDI

End Select

End If

End Function

Private Function GetMP3Info(udtInfo As MusicInfo) As Boolean

Dim FreeNo As Long, n(1) As Byte, b() As Byte, TmpInfo As MusicInfo

Dim Power As Long, v As Long, j As Long, Tagh As Mp3ID3V2Tag

Dim id3 As Mp3ID3V1, s As String, Pos As Long, id32 As Mp3ID3V2

Dim sz As Long, s1 As String

TmpInfo = udtInfo

On Error GoTo exitg

FreeNo = FreeFile

Open TmpInfo.FileName For Binary As #FreeNo

With TmpInfo

Pos = LOF(FreeNo) - 127

If Pos > 0 Then

Get #FreeNo, Pos, id3

If UCase$(id3.Header) = "TAG" Then

s = Trim$(Replace$(id3.Title, vbNullChar, vbNullString))

If Len(s) > 0 Then

s = Replace$(s, "-", vbNullString)

s = Replace$(s, "——", vbNullString)

s = Replace$(s, ".mp3", vbNullString, , , vbTextCompare)

.Title = s

End If

s = Trim$(Replace$(id3.Artist, vbNullChar, vbNullString))

If Len(s) > 0 Then

.Title = Replace$(.Title, s, vbNullString)

.Artist = s

End If

s = Trim$(Replace$(id3.Album, vbNullChar, vbNullString))

If Len(s) > 0 Then .Album = s

s = Trim$(Replace$(id3.Year, vbNullChar, vbNullString))

If Len(s) > 0 Then .Year = s

End If

End If

Get #FreeNo, 1, id32

If id32.Header = "ID3" Then

sz = (id32.Size(1) And &H7F) * &H400 + (id32.Size(2) And &H7F) * &H80 + (id32.Size(3) And &H7F)

Pos = sz + 10

s1 = String(4, vbNullChar)

Get #FreeNo, , Tagh

Do While Not (Tagh.Tag = s1 Or Seek(FreeNo) > sz + 10)

j = Tagh.Size(1) * &H10000 + Tagh.Size(2) * &H100 + Tagh.Size(3)

If j > 0 Then

ReDim b(j - 1)

Get #FreeNo, , b

s = StrConv(b, vbUnicode)

s = Trim$(Replace$(s, vbNullChar, ""))

Select Case Tagh.Tag

Case "TIT2"

.Title = s

Case "TPE1"

.Artist = s

Case "TALB"

.Album = s

Case "TCOM"

.Composer = s

Case "TEXT"

.Writer = s

Case "TYER"

.Year = s

Case "USLT"

s = Replace$(s, " ", " ")

If LCase$(Left$(s, 3)) = "chi" Then

.Lyrics = Mid$(s, 4)

ElseIf LCase$(Left$(s, 3)) = "eng" Then

.Lyrics = Mid$(s, 4)

Else

.Lyrics = s

End If

End Select

End If

Get #FreeNo, , Tagh

Loop

Else

Pos = 1

End If

Get #FreeNo, Pos, n

sz = Pos

If Not (n(0) = &HFF And n(1) >= &HFA And n(1) <= &HFF) Then

Do While Not (n(0) = &HFF And n(1) = &HFB)

Pos = Pos + 1

If Seek(FreeNo) - sz > 8192 Then GoTo exitg

Get #FreeNo, Pos, n

Loop

End If

Get #FreeNo, , n

v = 0

For j = 4 To 7

Power = 2 ^ j

If (n(0) And Power) = Power Then v = v + Power

Next

v = v \ 16

.Bits = Trim$(Mid$("144 320 32 48 56 64 80 96 112 128 160 192 224 256 320 ", v * 4 + 1, 4)) & "Kbps"

v = 0

For j = 2 To 3

Power = 2 ^ j

If (n(0) And Power) = Power Then v = v + Power

Next

v = v \ 4

.Sample = Trim$(Mid$("44 48 32 ?? ", v * 3 + 1, 3)) & "KHz"

End With

udtInfo = TmpInfo

GetMP3Info = True

exitg:

Close #FreeNo

End Function

还有个ASF格式,有点烦,下篇再做说明吧!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有