操作 Wave 文件(9): 使用 waveOut... 函数播放 wav 文件


下面是使用低级音频函数播放 wav 的两个方法, 对这个感兴趣的人恐怕很少, 免注释了.

使用窗口接受音频输出设备的消息:


unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls;



type

  TForm1 = class(TForm)

    Button1: TButton;

    procedure Button1Click(Sender: TObject);

  private

  protected

    procedure WndProc(var Message: TMessage); override;

  public

  end;



var

  Form1: TForm1;



implementation



{$R *.dfm}



uses MMSystem;



//获取文件格式和波形数据的函数

function GetWaveFmtData(path: string; var fmt: TWaveFormatEx; var buf: TBytes): Boolean;

var

  hFile: HMMIO;

  ckiRIFF,ckiFmt,ckiData: TMMCKInfo;

begin

  Result := False;

  hFile := mmioOpen(PChar(path), nil, MMIO_READ);

  if hFile = 0 then Exit;



  ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));

  ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));

  ZeroMemory(@ckiData, SizeOf(TMMCKInfo));



  ckiRIFF.fccType := mmioStringToFOURCC('WAVE', 0);

  ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);

  ckiData.ckid := mmioStringToFOURCC('data', 0);



  ZeroMemory(@fmt, SizeOf(TWaveFormatEx));



  mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);



  if (ckiRIFF.ckid = FOURCC_RIFF) and (ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and

     (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) and

     (mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize) and

     (mmioAscend(hFile, @ckiFmt, 0) = MMSYSERR_NOERROR) and

     (mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then

  begin

    SetLength(buf, ckiData.cksize);

    Result := (mmioRead(hFile, PAnsiChar(buf), ckiData.cksize) = ckiData.cksize);

  end;



  mmioClose(hFile, 0);

end;



//------------------------------------------------------------------------------

var

  wh: TWaveHdr;

  hOut: HWAVEOUT;

  fmt: TWaveFormatEx;

  buf: TBytes;



procedure TForm1.Button1Click(Sender: TObject);

const

  path = 'C:\WINDOWS\Media\Windows XP 启动.wav';

begin

  GetWaveFmtData(path, fmt, buf);



  wh.lpData := PAnsiChar(buf);

  wh.dwBufferLength := Length(buf);

  wh.dwBytesRecorded := 0;

  wh.dwUser := 0;

  wh.dwFlags := 0;

  wh.dwLoops := 1;

  wh.lpNext := nil;

  wh.reserved := 0;



  waveOutOpen(@hOut, WAVE_MAPPER, @fmt, Handle, 0, CALLBACK_WINDOW);

  waveOutPrepareHeader(hOut, @wh, SizeOf(TWaveHdr));

  waveOutWrite(hOut, @wh, SizeOf(TWaveHdr));

end;



procedure TForm1.WndProc(var Message: TMessage);

begin

  inherited;

  case Message.Msg of

    MM_WOM_OPEN: ;

    MM_WOM_CLOSE: ;

    MM_WOM_DONE: begin

      waveOutUnprepareHeader(hOut, @wh, SizeOf(TWaveHdr));

      waveOutClose(hOut);

    end;

  end;

end;



end.


 
   

使用回调函数:


unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls;



type

  TForm1 = class(TForm)

    Button1: TButton;

    Button2: TButton;

    Button3: TButton;

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure Button3Click(Sender: TObject);

  end;



var

  Form1: TForm1;



implementation



{$R *.dfm}



uses MMSystem;



function GetWaveFmtData(path: string; var fmt: TWaveFormatEx; var buf: TBytes): Boolean;

var

  hFile: HMMIO;

  ckiRIFF,ckiFmt,ckiData: TMMCKInfo;

begin

  Result := False;

  hFile := mmioOpen(PChar(path), nil, MMIO_READ);

  if hFile = 0 then Exit;



  ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));

  ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));

  ZeroMemory(@ckiData, SizeOf(TMMCKInfo));



  ckiRIFF.fccType := mmioStringToFOURCC('WAVE', 0);

  ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);

  ckiData.ckid := mmioStringToFOURCC('data', 0);



  ZeroMemory(@fmt, SizeOf(TWaveFormatEx));



  mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);



  if (ckiRIFF.ckid = FOURCC_RIFF) and (ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and

     (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) and

     (mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize) and

     (mmioAscend(hFile, @ckiFmt, 0) = MMSYSERR_NOERROR) and

     (mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then

  begin

    SetLength(buf, ckiData.cksize);

    Result := (mmioRead(hFile, PAnsiChar(buf), ckiData.cksize) = ckiData.cksize);

  end;



  mmioClose(hFile, 0);

end;



//------------------------------------------------------------------------------

var

  wh: TWaveHdr;

  hOut: HWAVEOUT;

  fmt: TWaveFormatEx;

  buf: TBytes;



procedure WaveProc(hWave: HWAVE; uMsg, dwInstance, dwParam1, dwParam2: DWORD); stdcall;

begin

  case uMsg of

    MM_WOM_OPEN: ;

    MM_WOM_CLOSE: ;

    MM_WOM_DONE: begin

      waveOutUnprepareHeader(hWave, PWaveHdr(dwParam1), SizeOf(TWaveHdr));

      waveOutClose(hWave);

    end;

  end;

end;



procedure TForm1.Button1Click(Sender: TObject);

const

  path = 'C:\WINDOWS\Media\Windows XP 启动.wav';

begin

  GetWaveFmtData(path, fmt, buf);



  wh.lpData := PAnsiChar(buf);

  wh.dwBufferLength := Length(buf);

  wh.dwBytesRecorded := 0;

  wh.dwUser := 0;

  wh.dwFlags := 0;

  wh.dwLoops := 1;

  wh.lpNext := nil;

  wh.reserved := 0;



  waveOutOpen(@hOut, WAVE_MAPPER, @fmt, DWORD(@WaveProc), 0, CALLBACK_FUNCTION);

  waveOutPrepareHeader(hOut, @wh, SizeOf(TWaveHdr));

  waveOutWrite(hOut, @wh, SizeOf(TWaveHdr));

end;



//暂停

procedure TForm1.Button2Click(Sender: TObject);

begin

  waveOutPause(hOut);

end;



//继续

procedure TForm1.Button3Click(Sender: TObject);

begin

  waveOutRestart(hOut);

end;



end.


 
   

你可能感兴趣的:(out)