delphi 多媒体 操作 wave(1)

Wave 文件的文件格式

微软的多媒体文件(wav、avi、tif 等)都有一个 RIFF 头, Wave 文件基本是这个样子:

RIFF 头
  fmt 子块
data 子块



Wave 文件的编码方式有好多, 最常用最简单的就是 PCM 编码.
其他编码会包含更多的"块", 但至少会包含上面的块, PCM 编码只包含上面的块

 

 

2.判断一个文件是否是 Wave 文件

Wave 文件的前 12 个字节可以这样描述:

TRiff = record
  ckId    : DWORD; {'RIFF'}
  ckSize  : DWORD; {文件大小, 不包括前 8 个字节}
  fccType : DWORD; {'WAVE'}
end;

 

3.mmio 系列函数用于 Wave 等多媒体文件的 I/O 操作

mmio 系列函数比一般的 I/O 函数更适合操作 RIFF 格式的多媒体文件, 主要是能更方便地操作 RIFF 的文件块, 官方还说它们更优化.

和其他 I/O 函数一样, 它们也是要 Open 获取句柄, 然后读写, 最后关闭; 但它们文件句柄和其他 I/O 函数的句柄并不兼容, 不过部分函数(上面前 7 个)也可以用于一般文件的操作.

uses MMSystem;

procedure TForm1.FormCreate(Sender: TObject);

const 

   FilePath = 'C:\Temp\mm.txt';

var 

  hFile: HMMIO;  str: RawByteString;

begin

   hFile := mmioOpen(PChar(FilePath),  {要打开的文件} nil{接受 TMMIOInfo 结构信息的指针, 暂时没用到}  

                                        MMIO_CREATE or MMIO_READWRITE {打开选项; 这是建立并以读写权限打开}     ); 

  mmioWrite(hFile, 'Delphi', 6);      {写入 6 个字符} 

   mmioSeek(hFile, 0, SEEK_SET);      {把读写指针移动到文件头}

   SetLength(str, 6);  mmioRead(hFile, PAnsiChar(str), 6); {读出 6 个字符}

  ShowMessage(str);                  {Delphi}

  mmioClose(hFile, 0);                {关闭文件; 第二个参数还可以是 MMIO_FHOPEN, 另有它用}  {最后再删除这个文件, 既然已删除就无需 Close 了}

  mmioOpen(PChar(FilePath), nil, MMIO_DELETE);

end;

 

4.有两个相关的结构体: 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), 此时需要很少的信息就可以找到主块.

 

5.获取 Wave 文件的波形数据

uses MMSystem;

function GetWaveData(FilePath: string; var stream: TMemoryStream): Boolean;
var
  hFile: HMMIO;
  ckiRIFF,ckiData: TMMCKInfo;
begin
  Result := False;
  hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);
  if hFile = 0 then Exit;

  ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));
  ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
  ckiData.ckid := mmioStringToFOURCC('data', 0);

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

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

//调用测试
procedure TForm1.Button1Click(Sender: TObject);
const
  FilePath = 'C:\WINDOWS\Media\Windows XP 启动.wav';
var
  stream: TMemoryStream;
begin
  stream := TMemoryStream.Create;

  if GetWaveData(FilePath, stream) then
    ShowMessageFmt('读出的数据大小是: %d', [stream.Size]); {424600}

  stream.Free;
end;

 6.使用 TMediaPlayer 录制 wav 文件

TMediaPlayer 录音是基于一个已存在的 wav 文件, 上次建立空白 wav 的函数可派上用场了.TMediaPlayer 的功能是基于 MCI 的, 都是该淘汰的东西了, 只是简单了解下.
接下来还要学习用 waveIn...系列函数录音、用 DirectSound 录音.

 

7.多媒体函数库Bass.dll

http://www.cnblogs.com/del/category/150851.html

最近要写个小程序, 用到 mp3 播放; 因为需要非常复杂的控制与功能, 想到了 Bass.dll.

以前我曾以为 Bass.dll 是 Windows 系统自带的库, 后来才知道原来是第三方的:
http://www.un4seen.com/.

Bass.dll 一直在更新, 现在最新版本是 2.411, 下载地址:
http://us2.un4seen.com/files/bass24.zip


在 Delphi 中使用前, 有三步工作要做:
1、复制 Bass.dll 到系统可以识别的文件夹, 譬如: Windows\System32、Windows、Windows\System, 也可以是系统或用户的环境变量 Path 指定的任何目录, 还可以在做程序时放在当前目录, 随便放一个文件夹然后在程序中指定路径也可以.
2、把专为 Delphi 写的头文件 bass.pas 放在某个目录(譬如: C:\Program Files\CodeGear\RAD Studio\6.0\Imports\Bass24).
3、然后从 Delphi 菜单 -> Tools -> Options -> Library-Win32 -> Library path -> 然后 Add 这个目录 (
例子).

 

 

 

 

posted @ 2013-04-14 00:35  javawebsoa  Views(305)  Comments(0Edit  收藏  举报