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 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