zoukankan      html  css  js  c++  java
  • 操作 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.
    
  • 相关阅读:
    一个多列组合框
    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
    图结构练习——BFS——从起始点到目标点的最短步数
    图结构练习——BFS——从起始点到目标点的最短步数
    广度优先搜索介绍
    广度优先搜索介绍
    数据结构实验之二叉树一:树的同构
    数据结构实验之二叉树一:树的同构
    对代码不满足,是任何真正有天才的程序员的根本特征。
  • 原文地址:https://www.cnblogs.com/del/p/1597596.html
Copyright © 2011-2022 走看看