衣带渐宽终不悔,为伊消得人憔悴

想回到过去,试着让故事继续。。。

 
· 所有网志 (75) · 个人日记 (40) · 程序设计 (6) · ACM-ICPC (7) · 读书笔记 (4) · 乱七八糟 (8) · 贴图空间 (7) · 未分类 (3) ·
日历
站内搜索
友情链接
· 我的歪酷
· 喜欢叫我林老师的 Yuer
· “我们家”小樱
· 一粒土豆的天空
· 极光炫影
· 枫之羽
· 渡渡
· 8600
· zl
· Bin-Laden
· RPG
· 月亮公主++
· 阳光不锈
· 农夫三拳

订阅 RSS

0062835

歪酷博客

« 上一篇: 换模版了 下一篇: 关于浮点数的存储 »
linle @ 2006-05-01 13:10

以前的一点研究,公开好了,有什么疑问可以和我讨论

三个多月前的代码,,比较幼稚,大家将就一下吧

文件结构示意图



格式的简单说明:

        如图1,每一个WMA文件,它的头16个字节是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”, 用来标识这个是否为WMA文件。接下来的8个字节为一个整数,表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息,我们在这里就不深入了解了。那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。

       也就是说从文件开始偏移量为31开始,里面存放了很多帧,有我们需要的标准Tag信息,扩展Tag信息,WMA文件控制信息等等。每个帧不是等长的,但是帧头是固定的24个字节,其中前16字节是用来标识这个帧的名字,后8个字节是用来表示这个帧(包括帧头)的大小。这一点和MP3文件的ID3V2信息比较像。

        由于我们只需要读写Tag信息,而Tag信息又分别保存在两个帧里,分别为标准Tag帧和扩展Tag帧,所有我们只需要处理这两个帧,其他帧完全可以根据获得的帧长度来跳过。

       如图2,标准Tag帧只包含歌曲标题,艺术家,版权,备注四个内容。它的帧名是十六进制的“33 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,在24个字节的帧头后紧跟着5个分别为2个字节的整数,前四个分别表示歌曲标题,艺术家,版权,备注的大小,第五个还不清楚是什么用的,大部分情况下是不使用的,即它的大小为0的。

        在这10个字节后,这四个信息的内容就按顺序存放了。记住,在WMA文件里,所有的文字都是按Unicode宽字符的编码方式储存的,而且每个字符串后面都又一个0结束字符的。

        如图3,再看扩展Tag帧,这里就比较麻烦了,里面包含的信息的个数是不确定的,每个信息也是按照像帧一样的方式组织起来的。扩展Tag帧的帧名是十六进制的“40 A4 D0 D2 07 E3 D2 11 97 F0 00 A0 C9 5E A8 50”,在24字节的帧头后先有一个两个字节的整数表示这个帧里一共有的扩展信息个数(ExNo)。

        如图4,每一个扩展信息包含扩展信息名字和对应的值。先有一个两个字节的整数来表示扩展名字信息的大小,接着是扩展信息,然后有一个两个字节的整数标志(Flag),这个后面再讲。然后又是一个两个字节的整数,表示值的大小。接着就是这个值。

       当扩展信息名字为WMFSDKVersion时,这个值表示的是这个WMA文件的版本;当扩展信息名字为WM/AlbumTitle时,这个值代表的就是专辑名;当扩展信息名字为WM/Genre时,这个值代表的就是流派;同理,很容易从扩展信息的名字看出这个值的用途的。这些扩展信息的名字和值几乎都是用Unicode的字符串来存储的,到现在为止只发现对下面两个情况例外。(关于所有扩展信息的名字可以从很多地方查到,比如SDK帮助,MSDN)

       下面再来看看那个标志Flag,这个基本上是为没什么用的(通常值为0),只对WM/TrackNumber和WM/Track这两个扩展信息名字有用,当Flag为3的时候后面的值(也就是曲目信息)是以4个字节的整数的形式表示,当Flag为0的时候,曲目信息是以普通的字符串形式表示的。


读写类的代码:

{请不要删除一下信息}
{          Wma格式文件的Tag(歌曲信息)读写类  V0.9
   这个本应该在05年6月就应该完工的类,由于我高考后贪玩,一直拖到现在,十分抱歉!
   由于时间仓促,此类只包含了十几种常用的属性,如果有任何疑问可以联系我。
   本类可以免费使用,使用时请发一封邮件给我,我只是想知道有多少人用它。
   如果需要用于商业用途,请先与我联系。
   如果你需要修改并重新发布它,请事先与我联系。
   作者:linle
   E_Mail: linle_1987@163.com
   QQ: 150622432
   最后更新日期  2006.2.14
}
{
         Wma Tag Reading and Writing Class V0.9
     You can use it freely.When you use it in your software Please send me a mail.
     If you want to modify it ,contact me;
     Author: linle
     E_mail: linle_1987@163.com
     QQ:150622432
     Last Update 2006.2.14
}
unit TWmaTag;

interface

uses
  Classes, SysUtils;
const
  Wma_head=#48#38#178#117#142#102#207#17#166#217#0#170#0#98#206#108;     //Wma文件头16字节一定要是这个
  Tag_head=#51#38#178#117#142#102#207#17#166#217#0#170#0#98#206#108;     //标签的帧头
  ExTag_head=#64#164#208#210#7#227#210#17#151#240#0#160#201#94#168#80;   //扩展标签的帧头
  ExTagNumber=10;                                                        //本类处理的扩展标签种类总数
var
  Flag:array [1..ExTagNumber] of WideString;                             //用来保存扩展标签的名字

type
  TWma_Tag =class (TObject)
    private
      { Private declarations }
      FVersion: WideString;
      FAllsize: int64;
      FTitle:WideString;
      FArtist: WideString;
      FCopyright:WideString;
      FDescription:WideString;
      FAlbumTitle: WideString;
      FYear: WideString;
      FGenre:WideString;
      FTrackNumber: WideString;
      FTrack:WideString;
      FUserWebURL:WideString;
      FURL: WideString;
      FLyrics:WideString;
      FEncodedBy:WideString;
      procedure FSetTitle(const NewTitle: WideString);
      procedure FSetArtist(const NewArtist: WideString);
      procedure FSetCopyright(const NewCopyright:WideString);
      procedure FSetDescription(const NewDescription:WideString);
      procedure FSetAlbumTitle(const NewAlbum: WideString);
      procedure FSetYear(const NewYear: WideString);
      procedure FSetGenre(const NewGenre:WideString);
      procedure FSetTrackNumber(const NewTrackNo: WideString);
      procedure FSetTrack(const NewTrack:WideString);
      procedure FSetUserWebURL(const NewUWU:WideString);
      procedure FSetURL(const NewURL:WideString);
      procedure FSetLyrics(const NewLyrics:WideString);
      procedure FSetEncodedBy(const NewEncodedby:WideString);
    public
      { Public declarations }
      constructor Create;
      procedure ResetData;                                                   //清空对象中原有数据
      function ReadFromFile(const FileName: String): Boolean;
      function SaveToFile(const FileName: String): Boolean;
      property Version: WideString read FVersion;
      property Title: WideString read FTitle write FSetTitle;
      property Artist: WideString read FArtist write FSetArtist;
      property Copyright:WideString read FCopyright write FSetCopyright;
      property Description:WideString read FDescription write FSetDescription;
      property AlbumTitle: WideString read FAlbumTitle write FSetAlbumTitle;
      property Year: WideString read FYear write FSetYear;
      property TrackNumber: WideString read FTrackNumber write FSetTrackNumber;
      property Genre: WideString read FGenre write FSetGenre;
      property Track: WideString read FTrack write FSetTrack;
      property UserWebURL: WideString read FUserWebURL write FSetUserWebURL;
      property URL: WideString read FURL write FSetURL;
      property Lyrics: WideString read FLyrics write FSetLyrics;
      property EncodedBy: WideString read FEncodedBy write FSetEncodedBy;
  end;

implementation
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetTitle(const NewTitle: WideString);
begin
   FTitle:=TrimRight(NewTitle);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetArtist(const NewArtist: WideString);
begin
   FArtist:=TrimRight(NewArtist);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetCopyright(const NewCopyright:WideString);
begin
   FCopyright:=TrimRight(NewCopyright);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetDescription(const NewDescription:WideString);
begin
   FDescription:=TrimRight(NewDescription);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetAlbumTitle(const NewAlbum: WideString);
begin
   FAlbumTitle:=TrimRight(NewAlbum);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetYear(const NewYear: WideString);
begin
   FYear:=TrimRight(NewYear);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetGenre(const NewGenre:WideString);
begin
   FGenre:=TrimRight(NewGenre);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetTrackNumber(const NewTrackNo: WideString);
begin
   FTrackNumber:=TrimRight(NewTrackNo);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetTrack(const NewTrack:WideString);
begin
   FTrack:=TrimRight(NewTrack);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetUserWebURL(const NewUWU:WideString);
begin
   FUserWebURL:=TrimRight(NewUWU);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetURL(const NewURL:WideString);
begin
   FURL:=TrimRight(NewURL);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetLyrics(const NewLyrics:WideString);
begin
   FLyrics:=TrimRight(NewLyrics);
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.FSetEncodedBy(const NewEncodedby:WideString);
begin
   FEncodedBy:=TrimRight(NewEncodedby);
end;
{-------------------------------------------------------------------------------}
constructor TWma_Tag.Create;
begin
  inherited;
  ResetData;
end;
{-------------------------------------------------------------------------------}
procedure TWma_Tag.ResetData;
begin
      FVersion:= '';
      FAllsize:= 0;
      FTitle:= '';
      FArtist:= '';
      FCopyright:= '';
      FDescription:= '';
      FAlbumTitle:= '';
      FYear:= '';
      FGenre:= '';
      FTrackNumber:= '';
      FTrack:= '';
      FUserWebURL:= '';
      FURL:= '';
      FLyrics:= '';
      FEncodedBy:= '';
end;
{-------------------------------------------------------------------------------}
function TWma_Tag.ReadFromFile(const FileName: String): Boolean;
var
  TagStream:TFileStream;                                         //打开WMA文件的流
  head:String;
  size:Int64;
  temps,ExValue:WideString;
  Tagsize:array[1..5] of SmallInt;
  i,TraNo:Integer;
  ExNo,Exsize,Reserve,ExValueSize:SmallInt;
begin
  Result:=false;
  if ( not FileExists(Filename) ) then Exit;                      //文件不存在时退出
  Setlength(head,16);
  TagStream:=TFileStream.Create(Filename,fmOpenRead or fmShareDenyNone);
  try
    TagStream.ReadBuffer(head[1],16);                            //读取WMA文件头16字节
    TagStream.ReadBuffer(size,sizeof(size));
  except
    TagStream.Free;
    Exit;
  end;

  if head<>Wma_head then begin TagStream.Free; Exit; end;        //不是WMA文件时退出
  FAllsize:=Size;
  TagStream.Position:=30;                                        //将指针移到第一个帧头
  While TagStream.Position<FAllsize do                           //当指针不在末尾时一直读每一个帧
   begin
    TagStream.ReadBuffer(head[1],16);
    TagStream.ReadBuffer(size,sizeof(size));
    if head=Tag_head then                                         //当为(经典)标签时
        begin
          for i:=1 to 5 do
           TagStream.ReadBuffer(Tagsize[i],2);
          for i:=1 to 5 do
           begin
            if Tagsize[i]>0 then
               begin
                 setlength(temps,(Tagsize[i] div 2)-1);
                 TagStream.ReadBuffer(temps[1],Tagsize[i]);
                 case i of
                   1:FTitle:=temps;
                   2:FArtist:=temps;
                   3:FCopyright:=temps;
                   4:FDescription:=temps;
                 end;
               end;
           end;
        end
    else if head=ExTag_head then                                 //当为扩展标签时
       begin
          TagStream.ReadBuffer(ExNo,2);                          //读出一共有多少个扩展标签
          for i:=1 to ExNo do
            begin
             TagStream.ReadBuffer(Exsize,2);
             SetLength(temps,(Exsize div 2)-1);
             TagStream.Read(temps[1],Exsize);
             TagStream.ReadBuffer(Reserve,2);
             TagStream.ReadBuffer(ExValueSize,2);
             if (Reserve=3) then
               begin
                TagStream.ReadBuffer(TraNo,4);
                if temps=Flag[10] then FTrackNumber:=InttoStr(TraNo)
                else if temps=Flag[5] then FTrack:=InttoStr(TraNo);
              end
             else
               begin
                 if ExValueSize > 2 then SetLength(ExValue,(ExValueSize div 2)-1)
                 else SetLength(ExValue,2);
                 if Exvaluesize>0 then
                 begin
                 TagStream.ReadBuffer(ExValue[1],ExValueSize);
                 if temps=Flag[1] then FAlbumTitle:=ExValue
                 else if temps=Flag[2] then FEncodedBy:=ExValue
                 else if temps=Flag[3] then FGenre:=ExValue
                 else if temps=Flag[4] then FLyrics:=ExValue
                 else if temps=Flag[5] then FTrack:=ExValue
                 else if temps=Flag[6] then FYear:=ExValue
                 else if temps=Flag[7] then FURL:=ExValue
                 else if temps=Flag[8] then FUserWebURL:=ExValue
                 else if temps=Flag[9] then FVersion:=ExValue
                 else if temps=Flag[10] then FTrackNumber:=ExValue;
                 end;
              end;
          end;

       end
    else
    TagStream.Position:=TagStream.Position-24+size;
   end;
  TagStream.Free;
  Result:=true;
end;
{-------------------------------------------------------------------------------}
function TWma_Tag.SaveToFile(const FileName: String): Boolean;
var
  TagStream:TMemoryStream;
  WMAStream:TMemorystream;
  Myfile:TFileStream;
  Size,Tsize:Int64;
  i,j:integer;
  ExCount,ExNo:SmallInt;
  Exsize,Reserve,ExValueSize:SmallInt;
  Tagsize:array[1..5] of SmallInt;
  head:string;
  temps,ExValue:WideString;
  Inflag:boolean;

   procedure WriteExTag(const Name:Widestring;const Re:SmallInt;const Value:Widestring);
    var                                                 //用来写扩展标签的子过程
    tempsize:Smallint;
   begin
    tempsize:=Length(Name)*2+2;                         //计算名字大小
    TagStream.WriteBuffer(tempsize,2);                  //写入名字大小
    TagStream.WriteBuffer(Name[1],tempsize);            // 写入名字
    TagStream.WriteBuffer(Re,2);                        //写入保留字
    tempsize:=Length(Value)*2+2;                        //计算值大小
    TagStream.WriteBuffer(tempsize,2);                  //写入值大小
    TagStream.WriteBuffer(Value[1],tempsize);           //写入值
    ExCount:=ExCount+1;                                 //将写入的扩展标签数目加一
   end;


begin
  Result:=false;
  Setlength(head,16);
  if ( not FileExists(Filename) ) then Exit;                 //文件不存在时退出
  Myfile:=TFileStream.Create(Filename,fmOpenRead or fmShareDenyNone );
  try
    Myfile.ReadBuffer(head[1],16);
    Myfile.ReadBuffer(size,sizeof(size));
    FAllSize:=size;
  except
    Myfile.Free;
    Exit;
  end;
  if head<>Wma_head then begin Myfile.Free; Exit; end;        //当不是WMA文件时退出
  Myfile.Position:=0;

  WMAStream:=TMemorystream.Create;                            //一个用来保存新的标签信息的流
  WMAStream.CopyFrom(Myfile,30);
    TagStream:=TMemoryStream.Create;                          //以下代码生产(经典)标签,并复制到WMAStream后
    TagStream.WriteBuffer(Tag_head[1],16);
    TagStream.WriteBuffer(Tsize,8);
    for i:=1 to 5 do Tagsize[i]:=0;
    if(FTitle<>'') then Tagsize[1]:=length(FTitle)*2+2;
    if(FArtist<>'') then Tagsize[2]:=length(FArtist)*2+2;
    if(FCopyright<>'') then Tagsize[3]:=length(FCopyright)*2+2;
    if(FDescription<>'') then Tagsize[4]:=length(FDescription)*2+2;
    for i:=1 to 5 do TagStream.WriteBuffer(Tagsize[i],2);
    if(FTitle<>'') then TagStream.WriteBuffer(FTitle[1],Tagsize[1]);
    if(FArtist<>'') then TagStream.WriteBuffer(FArtist[1],Tagsize[2]);
    if(FCopyright<>'') then TagStream.WriteBuffer(FCopyright[1],Tagsize[3]);
    if(FDescription<>'') then TagStream.WriteBuffer(FDescription[1],Tagsize[4]);
    Tsize:=Tagstream.Size;
    Tagstream.Position:=16;
    Tagstream.WriteBuffer(Tsize,8);
    Tagstream.Position:=0;
    WMAStream.CopyFrom(Tagstream,Tsize);
    Tagstream.Free;
  Myfile.Position:=30;
  While Myfile.Position<FAllsize do
    begin
     Myfile.ReadBuffer(head[1],16);
     Myfile.ReadBuffer(size,8);
     if head=Tag_head then Myfile.Position:=Myfile.Position-24+size   //当读到原来的(经典)标签时,直接跳过
     else if head=ExTag_head then                                     //当读到扩展标签时
       begin
        ExCount:=0;
        Tagstream:=TMemorystream.Create;
        Tagstream.WriteBuffer(ExTag_head[1],16);
        TagStream.WriteBuffer(Tsize,8);
        TagStream.WriteBuffer(ExCount,2);
        if FAlbumTitle<>'' then WriteExTag(Flag[1],0,FAlbumTitle);      //先写入本类有处理的一些扩展标签
        if FEncodedBy<>'' then  WriteExTag(Flag[2],0,FEncodedBy);
        if FGenre<>'' then  WriteExTag(Flag[3],0,FGenre);
        if FLyrics<>'' then WriteExTag(Flag[4],0,FLyrics);
        if FTrack<>'' then WriteExTag(Flag[5],0,FTrack);
        if FYear<>'' then WriteExTag(Flag[6],0,FYear);
        if FURL<>'' then WriteExTag(Flag[7],0,FURL);
        if FUserWebURL<>'' then WriteExTag(Flag[8],0,FUserWebURL);
        if FVersion<>'' then WriteExTag(Flag[9],0,FVersion);
        if FTrackNumber<>'' then WriteExTag(Flag[10],0,FTrackNumber);

        Myfile.ReadBuffer(ExNo,2);
        for i:=1 to ExNo do
          begin                                                          //读出文件中原有的扩展标签
           Myfile.ReadBuffer(ExSize,2);
           SetLength(temps,(Exsize div 2) -1);
           Myfile.ReadBuffer(temps[1],ExSize);
           Myfile.ReadBuffer(Reserve,2);
           Myfile.ReadBuffer(ExValueSize,2);
           if ExValueSize > 2 then SetLength(ExValue,(ExValueSize div 2)-1)
           else SetLength(ExValue,2);
           if ExValueSize>0 then
             begin
             Myfile.ReadBuffer(ExValue[1],ExValueSize);
             Inflag:=False;
             for j:=1 to ExTagNumber do
               if temps=Flag[j] then Inflag:=True;
             if (not Inflag) then WriteExTag(temps,Reserve,ExValue);     //当不属于本类处理的扩展标签范围时,直接原样写入
             end;
          end;
         Tsize:=TagStream.Size;
         Tagstream.Position:=16;                                       
         Tagstream.WriteBuffer(Tsize,8);                                  //写入扩展标签实际大小
         Tagstream.Position:=24;
         Tagstream.WriteBuffer(ExCount,2);
         Tagstream.Position:=0;                                           //写入扩展标签实际数目
         WMAStream.CopyFrom(Tagstream,Tsize);                             //将扩展标签帧复制到WMAStream末尾
         Tagstream.Free;
       end
     else                                                                //当读到其他帧时,直接复制整个帧
       begin
       Myfile.Position:=Myfile.Position-24;
       WMAStream.CopyFrom(Myfile,size);
       end;
     end;
   
    Tsize:=WMAStream.Size;
    WMAStream.Position:=16;
    WMAStream.WriteBuffer(TSize,8);                                        //写入整个标签的实际大小
    WMAStream.Position:=TSize;                                             //指针移到末尾
    Myfile.Position:=FAllsize;                                             //将Myfile指针也移到标签末尾
    WMAStream.CopyFrom(Myfile,Myfile.Size-FAllsize);                       //将Myfile中的其他数据复制到WMAStream后
    Myfile.Free;
     try
      WMAStream.SaveToFile(Filename);                                       //将WMAStream保存
     except
      WMAStream.Free;
      Exit;
      end;
    WMAStream.Free;
    Result:=True;
end;
{-------------------------------------------------------------------------------}
initialization
  begin
  Flag[1]:='WM/AlbumTitle';
  Flag[2]:='WM/EncodedBy';
  Flag[3]:='WM/Genre';
  Flag[4]:='WM/Lyrics';
  Flag[5]:='WM/Track';
  Flag[6]:='WM/Year';
  Flag[7]:='WM/URL';
  Flag[8]:='WM/UserWebURL';
  Flag[9]:='WMFSDKVersion';
  Flag[10]:='WM/TrackNumber';
  end;


end.

使用该类时的范例代码:

procedure TForm1.Button1Click(Sender: TObject);
var
 wma:TWma_Tag;
begin
 if opendialog1.Execute then
   begin
   label15.Caption:=opendialog1.FileName;
   wma:=TWma_Tag.Create;
   if wma.ReadFromFile(opendialog1.FileName) then
    begin
     edit1.Text:=wma.Title;
     edit2.Text:=wma.Artist;
     edit3.Text:=wma.Copyright;
     edit4.Text:=wma.Description;
     edit5.Text:=wma.AlbumTitle;
     edit6.Text:=wma.EncodedBy;
     edit7.Text:=wma.Genre;
     edit8.Text:=wma.Lyrics;
     edit9.Text:=wma.TrackNumber;
     edit10.Text:=wma.Year;
     edit11.Text:=wma.URL;
     edit12.Text:=wma.UserWebURL;
     edit13.Text:=wma.Version;
    end;
   wma.Free;
 end;

end;

procedure TForm1.Button2Click(Sender: TObject);
var
 wma:TWma_Tag;
begin
 wma:=TWma_Tag.Create;
 wma.ReadFromFile(label15.Caption);
 wma.Title:=Edit1.Text;
 wma.Artist:=edit2.Text;
 wma.Copyright:=Edit3.Text;
 wma.Description:=Edit4.Text;
 wma.AlbumTitle:=Edit5.Text;
 wma.EncodedBy:=Edit6.Text;
 wma.Genre:=Edit7.Text;
 wma.Lyrics:=Edit8.Text;
 wma.TrackNumber:=Edit9.Text;
 wma.Year:=Edit10.Text;
 wma.URL:=Edit11.Text;
 wma.UserWebURL:=Edit12.Text;
 if wma.SaveToFile(label15.Caption)then Showmessage('Success in Saving to File ')
 else showmessage('Fail in Saving to File');
 wma.Free;
end;




最新评论 (点击这里查看更早的所有评论...)


netwudoo

2006-10-10 17:51

作者分析的很透彻,而且无私分享,在下佩服,严重支持你!  

呵呵,兄台过奖了。。


wowo

2006-11-09 17:27

搜破了baidu&google只有你这篇文章对我的帮助最大,
不过仍有疑问
修改tag的时候是不是一定要把整个文件重写一篇,我用过一些软件修改tag,输入了一些较长的歌名字符,但大小没有任何改变,如果每次重写文件是不是存在效率问题呢?请赐教.

这个问题我也想过。我在研究wma格式的时候发现,它有一个帧是全都是 0 的,相当于缓冲区。如果写入的歌名比原来长的话,就减少缓冲区大小,歌名短就增加缓冲区。这样就可以保持文件头的大小不变,每次更新的话只需要重写文件头,不需要重写音频数据。
不过这个功能在我这个代码里还没实现。


myf

2006-12-12 19:17

真是高人啊



Andy

2007-06-08 10:53 匿名 123.112.*.*

倒挺佩服你这种精神的,通过分析文件能得到结果也是很不容易的,不过微软对于wma的文件结构有详细的文档,在网站上可以下载,感觉你这是一种非标准做法。最前面那16个字节是固定的,但他是用来标识Wma的,其实是一个guid。我是用C#的,对delphi不太熟。



Jin

2007-07-27 11:44 匿名 203.69.*.* 网址: http://jin.tw

最近在研究分析檔案dataset, 無意間來到這裡
最近在研究如何讓程式辨識wmv跟wma的差別, 33 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C 這段header,在wmv以及asf上也都是一模一樣, 所以無法透過這種判斷來分析檔案, 按照msdn上的說法, wmv,asf,wma這三種檔案只有副檔名上的差異..不知道您是否有注意到這個



小帆

2007-11-21 10:13 匿名 125.93.*.*

您好:
我想知道如何读取WMA文件里面包含的专辑封面图片,我在使用你的这个类了,确实比较好,但是缺少的就是读取专辑封面图片。



BaoShixian

2007-12-10 22:22 匿名 221.0.*.* 网址: http://baolongtu.ys168.com/

Public Function ReadTagInfo_wma(FileName As String, typInfo As InfoTag) As Boolean

'Dim TagStream As TFileStream '打开WMA文件的流
Dim sHead As String
Dim i As Integer
Dim Reserve As Long
Dim TraNo As Long
Dim ExtValue As String, ExtValueSize As Long
Dim ExtNo As Long, ExtSize As Long

Dim Tagsize(1 To 5) As Long
Dim sTemp As String
Dim mLenB As Long
Dim fTextB As String
Dim iPosn As Long, iSize As Long
'Dim iLen As Long, sTagB As String
Dim virErase As InfoTag

On Error Resume Next
'信息:***************************************************


2008-04-17 15:44

感觉自己以前都白学了,
高手!!


2008-06-27 17:28 网址: http://abin_00@163.com

感谢linle
以下是我使用后的一个发现,希望有点用^^
[那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。]



这6个字节其中前面4个字节应该为总标签帧数。(猜测)

理由如下:  个人写了个更改WMA头文件的程序,为WMA增加了一个自定义帧,插入后的结果是该文件无法播放,遍查不得其果,想到这6个BYTE可能有所相关,就对比了两个WMA文件,发现这6个BYTE中头一个BYTE不一样,猜测这个数据应该为帧数,于是更改该数据,发现更改后WMA文件解码正常。后经对比,证实这个数据确实为帧数,但唯一不能确定的是这个数据究竟是否是int型、short型、又或者是BYTE型。 从文件上看个人认为是int型的。



yedeerzi

2010-01-29 19:40 匿名 219.136.*.*

ASF 1.0 文档
http://avifile.sourceforge.net/asf-1.0.htm


评论 / 个人网页 / 扔小纸条
*昵称

已经注册过? 请登录

Email
网址
*评论