TRiff = ckId : DWORD; ckSize : DWORD; fccType : DWORD; ;
我们读出文件的前 12 个字节进行判断, 就基本可以确认它是不是 Wave 文件.
MMSystem, IOUtils; TForm1.FormCreate(Sender: TObject); riff: ckId, ckSize, fccType: DWORD; ; TFile.OpenRead() Read(riff, SizeOf(riff)); Free; ; (riff.ckId = FOURCC_RIFF) (riff.fccType = mmioStringToFOURCC(,)) ShowMessageFmt(, [riff.ckSize + ]); ;
还是把它写成一个函数吧, 最好也别再引用 MMSystem 单元.
IsWave(FilePath: ): Integer; mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD; Result := DWORD(Chr0) + DWORD(Chr1) + DWORD(Chr2) + DWORD(Chr3) ; ; riff: ckId, ckSize, fccType: DWORD; ; Result := ; TFileStream.Create(FilePath, fmOpenRead) Read(riff, SizeOf(riff)); Free; ; (riff.ckId = mmioFOURCC(, , , )) (riff.fccType = mmioFOURCC(, , , )) Result := riff.ckSize + ; ;
依次道理, 也可以判断一个 RIFF 文件具体是什么格式.
GetRiffType(FilePath: ): String; mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD; Result := DWORD(Chr0) + DWORD(Chr1) + DWORD(Chr2) + DWORD(Chr3) ; ; riff: ckId, ckSize, fccType: DWORD; ; TChars = [..] AnsiChar; Result := ; TFileStream.Create(FilePath, fmOpenRead) Read(riff, SizeOf(riff)); Free; ; (riff.ckId = mmioFOURCC(, , , )) Result := TChars(riff.fccType); ; ShowMessage(GetRiffType()); ShowMessage(GetRiffType()); ShowMessage(GetRiffType()); ;
关于 FOURCC_RIFF、mmioFOURCC、mmioStringToFOURCC:
RIFF 格式的文件都是有若干 "块" 来构成的, 每个块都是有 4 个字符开头(不足4个字符用空格补足);
这连续的 4 个字节刚好是一个 32 位整数的大小, 所以常常把它们当作一个整数读出来判断.
通过 MMSystem.mmioStringToFOURCC 就可以获取这样的整数.
从 C/C++ 代码中经常看到: mmioFOURCC; 它并非 winmm.dll 库中的函数, 是在 C/C++ 中定义的宏.
这里用 Delphi 模拟实现了这个函数. 其功能类似 mmioStringToFOURCC.
MMSystem.FOURCC_RIFF 是个常量, 当需要 "RIFF" 对应的整数时直接用就是了. 举例:
MMSystem; mmioFOURCC(Chr0,Chr1,Chr2,Chr3: AnsiChar): DWORD; Result := DWORD(Chr0) + DWORD(Chr1) + DWORD(Chr2) + DWORD(Chr3) ; ; TForm1.FormCreate(Sender: TObject); f1,f2,f3,f4: FOURCC; f1 := mmioStringToFOURCC(, ); f2 := mmioStringToFOURCC(, MMIO_TOUPPER); f3 := mmioFOURCC(, , , ); f4 := FOURCC_RIFF; ShowMessageFmt(, [f1,f2,f3,f4]); ;