操作 Wave 文件(4): 获取 Wave 文件主块与子块的信息


有两个相关的结构体: TMMIOInfo、TMMCKInfo.

TMMIOInfo 是多媒体文件打开后的状态信息, mmioOpen 函数的第二个参数就是这个结构的指针.
现在先用到了 TMMCKInfo, 这是文件内部 "块" 的信息, 构成如下:

TMMCKInfo = record

  ckid: FOURCC;        {块标识}

  cksize: DWORD;       {块大小}

  fccType: FOURCC;     {格式类型标识}

  dwDataOffset: DWORD; {偏移地址}

  dwFlags: DWORD;      {附加信息}

end;


 
   

查找 "块" 需要通过 mmioDescend、mmioAscend 两个函数.

mmioAscend 是从子块跳出;

mmioDescend 是进入到子块; 进入子块是需要指定子块的 ckid 和父块信息;
mmioDescend 也用来查找主块(RIFF), 此时需要很少的信息就可以找到主块.

测试代码:


unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls;



type

  TForm1 = class(TForm)

    Button1: TButton;

    Button2: TButton;

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

  end;



var

  Form1: TForm1;



implementation



{$R *.dfm}



uses MMSystem;



const FilePath = 'C:\WINDOWS\Media\Windows XP 启动.wav';



//获取 RIFF 块的信息

procedure TForm1.Button1Click(Sender: TObject);

var

  hFile: HMMIO;

  ckiRIFF: TMMCKInfo;

begin

  //清空 ckiRIFF 结构体; 有些函数使用前要求必须清空, 即使不要求也还是清空的好.

  FillChar(ckiRIFF, SizeOf(TMMCKInfo), 0); {局部变量在清空前有垃圾数据}



  //打开文件, 获取句柄

  hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);



  //获取 RIFF 块的信息

  mmioDescend(hFile,        {文件句柄}

              @ckiRIFF,     {块信息结构的指针, 用于获取块的信息}

              nil,          {这父块的结构信息, RIFF 没有父块, 无需指定}

              MMIO_FINDRIFF {如果是查询子块这里的标志是 MMIO_FINDCHUNK}

             );             {返回 0 表示查找成功, 这里忽略了验证}



  //以下是查证获取到的信息

  ShowMessageFmt('%d, %d, %d, %d, %d', [ckiRIFF.ckid, ckiRIFF.cksize, ckiRIFF.fccType,

  ckiRIFF.dwDataOffset, ckiRIFF.dwFlags ]); {1179011410, 424636, 1163280727, 8, 0}



  if ckiRIFF.ckid = FOURCC_RIFF then ShowMessage('是 RIFF');

  if ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0) then ShowMessage('是 WAVE');



  //关闭

  mmioClose(hFile, 0);

end;





//获取子块的信息

procedure TForm1.Button2Click(Sender: TObject);

var

  hFile: HMMIO;

  ckiRIFF,ckiSub: TMMCKInfo;

  n: Integer;

begin

  //清空准备接受信息的结构

  FillChar(ckiRIFF, SizeOf(TMMCKInfo), 0);

  FillChar(ckiSub, SizeOf(TMMCKInfo), 0);



  hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);



  //先获取主块(RIFF)信息

  mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);



  //获取 fmt 子块信息

  ckiSub.ckid := mmioStringToFOURCC('fmt', 0);

  if mmioDescend(hFile, @ckiSub, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR then

  begin

    ShowMessageFmt('%d, %d, %d, %d, %d', [ckiSub.ckid, ckiSub.cksize, ckiSub.fccType,

      ckiSub.dwDataOffset, ckiSub.dwFlags]);

  end;



  //如果继续查找需要跳出子块; 下面将从偏移地址 20 跳到 36 处

  mmioAscend(hFile, @ckiSub, 0); {其第三个参数一直是 0, 是备用参数}



  //获取 data 子块信息

  ckiSub.ckid := mmioStringToFOURCC('data', 0);

  if mmioDescend(hFile, @ckiSub, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR then

  begin

    ShowMessageFmt('%d, %d, %d, %d, %d', [ckiSub.ckid, ckiSub.cksize, ckiSub.fccType,

      ckiSub.dwDataOffset, ckiSub.dwFlags]);

  end;



  mmioClose(hFile, 0);

end;



end.


 
   

你可能感兴趣的:(文件)