Wave 文件(5): 获取 Wave 文件的格式信息

装载格式信息的结构有:
TWaveFormat = packed record
  wFormatTag: Word;
  nChannels: Word;
  nSamplesPerSec: DWORD;
  nAvgBytesPerSec: DWORD;
  nBlockAlign: Word;
end;

TPCMWaveFormat = record
  wf: TWaveFormat;
  wBitsPerSample: Word;
end;

TWaveFormatEx = packed record
  wFormatTag: Word;       {格式类型; 主要使用的是 WAVE_FORMAT_PCM}
  nChannels: Word;        {声道数; 1 是单声道、2 是立体声}
  nSamplesPerSec: DWORD;  {采样频率}
  nAvgBytesPerSec: DWORD; {传输速率}
  nBlockAlign: Word;      {每次采样的大小}
  wBitsPerSample: Word;   {采样精度}
  cbSize: Word;           {附加数据的大小; PCM 编码的文件没这个字段}
end;


能看出它们是依次递增一个字段, 并且也是 Wave 文件的一个构成部分; 现在要做的就是从 Wave 文件中把它们取出来.

获取函数及测试代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses MMSystem;

//获取 Wave 中格式数据的函数; 常用的是 TWaveFormatEx, 但 PCM 缺它一个字段
function GetWaveFmt(FilePath: string; var fmt: TWaveFormatEx): Boolean;
var
  hFile: HMMIO;
  ckiRIFF,ckiFmt: TMMCKInfo;
begin
  Result := False;
  hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);
  if hFile = 0 then Exit;

  ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));
  ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
  ZeroMemory(@fmt, SizeOf(TWaveFormatEx));     {也先清空准备接受数据的结构体}
  ckiFmt.ckid := mmioStringToFOURCC('fmt', 0); {给查找格式块准备}

  //先获取主块的信息
  mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);

  //再获取 fmt 块的信息后, 指针将自动指向格式数据起点; 然后读出格式数据
  if (ckiRIFF.ckid = FOURCC_RIFF) and
     (ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and
     (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
     Result := (mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize);
end;

//调用测试
procedure TForm1.Button1Click(Sender: TObject);
const
  FilePath = 'C:\WINDOWS\Media\Windows XP 启动.wav';
var
  WaveFormat: TWaveFormatEx;
begin
  if GetWaveFmt(FilePath, WaveFormat) then with Memo1.Lines do
  begin
    Clear;
    Add(Format('wFormatTag: %d', [WaveFormat.wFormatTag]));
    Add(Format('nChannels: %d', [WaveFormat.nChannels]));
    Add(Format('nSamplesPerSec: %d', [WaveFormat.nSamplesPerSec]));
    Add(Format('nAvgBytesPerSec: %d', [WaveFormat.nAvgBytesPerSec]));
    Add(Format('nBlockAlign: %d', [WaveFormat.nBlockAlign]));
    Add(Format('wBitsPerSample: %d', [WaveFormat.wBitsPerSample]));
    Add(Format('cbSize: %d', [WaveFormat.cbSize]));
  end;
{ 显示结果:
  wFormatTag: 1
  nChannels: 2
  nSamplesPerSec: 22050
  nAvgBytesPerSec: 88200
  nBlockAlign: 4
  wBitsPerSample: 16
  cbSize: 0
}
end;

end.

posted @ 2010-01-13 15:06  架构师聊技术  阅读(321)  评论(0编辑  收藏  举报