zoukankan      html  css  js  c++  java
  • 操作 Wave 文件(2): 判断一个文件是否是 Wave 文件


    Wave 文件的前 12 个字节可以这样描述:
    TRiff = record
      ckId    : DWORD; {'RIFF'}
      ckSize  : DWORD; {文件大小, 不包括前 8 个字节}
      fccType : DWORD; {'WAVE'}
    end;
    

    我们读出文件的前 12 个字节进行判断, 就基本可以确认它是不是 Wave 文件.

    uses MMSystem, IOUtils; {这里准备用 IOUtils.TFile.OpenRead 方便地建立文件流}
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      riff: record ckId, ckSize, fccType: DWORD; end; {可以同时定义结构并声明结构变量}
    begin
      with TFile.OpenRead('C:\WINDOWS\Media\Windows XP 启动.wav') do
      begin
        Read(riff, SizeOf(riff));
        Free;
      end;
    
      if (riff.ckId = FOURCC_RIFF) and (riff.fccType = mmioStringToFOURCC('WAVE',0)) then
        ShowMessageFmt('这是个 Wave 文件, 其大小是 %d 字节', [riff.ckSize + 8]);
    end;
    

    还是把它写成一个函数吧, 最好也别再引用 MMSystem 单元.

    {如果是 Wave 文件则返回文件大小, 不是则返回 0}
    function IsWave(FilePath: string): Integer;
      function mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD;
      begin
        Result := DWORD(Chr0) + DWORD(Chr1) shl 8 + DWORD(Chr2) shl 16 + DWORD(Chr3) shl 24;
      end;
    var
      riff: record ckId, ckSize, fccType: DWORD; end;
    begin
      Result := 0;
      with TFileStream.Create(FilePath, fmOpenRead) do begin
        Read(riff, SizeOf(riff));
        Free;
      end;
      if (riff.ckId = mmioFOURCC('R', 'I', 'F', 'F')) and
         (riff.fccType = mmioFOURCC('W', 'A', 'V', 'E')) then
        Result := riff.ckSize + 8;
    end;
    

    依次道理, 也可以判断一个 RIFF 文件具体是什么格式.

    {返回 RIFF 文件格式的函数, 如果不是 RIFF 文件, 则返回 'noneRIFF'}
    function GetRiffType(FilePath: string): String;
      function mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD;
      begin
        Result := DWORD(Chr0) + DWORD(Chr1) shl 8 + DWORD(Chr2) shl 16 + DWORD(Chr3) shl 24;
      end;
    var
      riff: record ckId, ckSize, fccType: DWORD; end;
    type
      TChars = array[0..3] of AnsiChar; {用于类型转换}
    begin
      Result := 'noneRIFF';
      with TFileStream.Create(FilePath, fmOpenRead) do begin
        Read(riff, SizeOf(riff));
        Free;
      end;
      if (riff.ckId = mmioFOURCC('R', 'I', 'F', 'F')) then Result := TChars(riff.fccType);
    end;
    
    //测试:
    begin
      ShowMessage(GetRiffType('C:\WINDOWS\Media\Windows XP 启动.wav')); {WAVE}
      ShowMessage(GetRiffType('C:\WINDOWS\clock.avi'));                 {AVI }
      ShowMessage(GetRiffType('C:\WINDOWS\notepad.exe'));               {noneRIFF}
    end;
    

    关于 FOURCC_RIFF、mmioFOURCC、mmioStringToFOURCC:

    RIFF 格式的文件都是有若干 "块" 来构成的, 每个块都是有 4 个字符开头(不足4个字符用空格补足);
    这连续的 4 个字节刚好是一个 32 位整数的大小, 所以常常把它们当作一个整数读出来判断.

    通过 MMSystem.mmioStringToFOURCC 就可以获取这样的整数.

    从 C/C++ 代码中经常看到: mmioFOURCC; 它并非 winmm.dll 库中的函数, 是在 C/C++ 中定义的宏.
    这里用 Delphi 模拟实现了这个函数. 其功能类似 mmioStringToFOURCC.

    MMSystem.FOURCC_RIFF 是个常量, 当需要 "RIFF" 对应的整数时直接用就是了. 举例:

    uses MMSystem;
    
    {自定义的 mmioFOURCC 函数}
    function mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD;
    begin
      Result := DWORD(Chr0) + DWORD(Chr1) shl 8 + DWORD(Chr2) shl 16 + DWORD(Chr3) shl 24;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      f1,f2,f3,f4: FOURCC; {FOURCC = DWORD;}
    begin
      f1 := mmioStringToFOURCC('RIFF', 0);
      f2 := mmioStringToFOURCC('Riff', MMIO_TOUPPER); {第二个参数可以把字符串转大写}
    
      f3 := mmioFOURCC('R', 'I', 'F', 'F');
    
      f4 := FOURCC_RIFF;
    
      ShowMessageFmt('%d, %d, %d, %d', [f1,f2,f3,f4]);
      {1179011410, 1179011410, 1179011410, 1179011410}
    end;
    
  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/del/p/1597315.html
Copyright © 2011-2022 走看看