程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 操作 Wave 文件(2): 判斷一個文件是否是 Wave 文件

操作 Wave 文件(2): 判斷一個文件是否是 Wave 文件

編輯:Delphi

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; 



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved