程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 在 Delphi 下使用 DirectSound (7): 播放資源文件中的 Wave 數據

在 Delphi 下使用 DirectSound (7): 播放資源文件中的 Wave 數據

編輯:Delphi

  首先要修改前面自定義的 ReadWaveFile 單元, 給它增加一個 OpenResource() 方法以直接讀取資源文件中的 "WAVE" 數據;

  為避免混淆, 把單元名 ReadWaveFile 同時改為 ReadWave; 類名 TReadWaveFile 改為 TReadWave.

{修改後的 ReadWave 單元: 從文件或資源讀取 Wave 的格式、數據與數據尺寸}   
unit ReadWave; 
 
interface 
 
uses Windows, Classes, SysUtils, MMSystem; 
 
type 
TReadWave = class 
private 
  FFileHandle: HMMIO; 
  FFormat: TWaveFormatEx; 
  FSize: DWord; 
  function GetFormatAndSize(hFile: HMMIO): Boolean; 
public 
  destructor Destroy; override; 
  function Open(FileName: string): Boolean; 
  function OpenResource(ResName: string): Boolean; 
  function Read(pDest: Pointer; Size: DWord): Boolean; //讀出波形數據 
  property Format: TWaveFormatEx read FFormat;        //讀出格式數據 
  property Size: DWord read FSize;                    //讀出波形數據的大小 
end; 
 
implementation 
 
{ TReadWave } 
 
destructor TReadWave.Destroy; 
begin 
  if FFileHandle > 0 then mmioClose(FFileHandle, 0); 
  inherited; 
end; 
 
function TReadWave.GetFormatAndSize(hFile: HMMIO): Boolean; 
var 
  ckiRIFF,ckiFmt,ckiData: TMMCKInfo; 
begin 
  Result := False; 
  if hFile = 0 then Exit; 
  ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo)); 
  mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF); 
  if (ckiRIFF.ckid <> FOURCC_RIFF) or (ckiRIFF.fccType <> mmiOStringToFOURCC('WAVE',0)) then Exit; 
 
  ZeroMemory(@FFormat, SizeOf(TWaveFormatEx)); 
  ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo)); 
  ckiFmt.ckid := mmiOStringToFOURCC('fmt', 0); 
 
  ZeroMemory(@ckiData, SizeOf(TMMCKInfo)); 
  ckiData.ckid := mmiOStringToFOURCC('data', 0); 
 
  if (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then mmioRead(hFile, @FFormat, SizeOf(TWaveFormatEx)); 
  mmioAscend(hFile, @ckiFmt, 0); 
  if (mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then FSize := ckiData.cksize; 
 
  Result := FFormat.wFormatTag = WAVE_FORMAT_PCM; 
end; 
 
function TReadWave.Open(FileName: string): Boolean; 
begin 
  Result := False; 
  if not FileExists(FileName) then Exit; 
  if FFileHandle > 0 then mmioClose(FFileHandle, 0); 
  FFileHandle := mmioOpen(PChar(FileName), nil, MMIO_READ); 
  Result := GetFormatAndSize(FFileHandle); 
end; 
 
function TReadWave.OpenResource(ResName: string): Boolean; 
var 
  res: TResourceStream; 
  mmioInfo: TMMIOInfo; 
begin 
  Result := False; 
  res := TResourceStream.Create(HInstance, ResName, 'WAVE'); 
  ZeroMemory(@mmioInfo, SizeOf(TMMIOInfo)); 
  mmioInfo.fccIOProc := FOURCC_MEM; 
  mmioInfo.cchBuffer := res.Size; 
  mmioInfo.pchBuffer := res.Memory; 
  if FFileHandle > 0 then mmioClose(FFileHandle, 0); 
  FFileHandle := mmioOpen(nil, @mmioInfo, MMIO_ALLOCBUF or MMIO_READ); 
  Result := GetFormatAndSize(FFileHandle); 
  res.Free; 
end; 
 
function TReadWave.Read(pDest: Pointer; Size: DWord): Boolean; 
begin 
  Result := mmioRead(FFileHandle, pDest, Size) = Size; 
end; 
 
end. 

下面的例子如圖載入了三個 Wave 文件到資源:

在 Delphi 下使用 DirectSound (7): 播放資源文件中的 Wave 數據

  本例可充分體現 DirectSound 可同時播放多個聲音的特點; 實現代碼:

unit Unit1; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
 
type 
  TForm1 = class(TForm) 
    Button1: TButton;    //播放第一個資源 
    Button2: TButton;    //播放第二個資源 
    Button3: TButton;    //播放第三個資源 
    Button4: TButton;    //全部停止 
    CheckBox1: TCheckBox; //控制是否循環播放 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button4Click(Sender: TObject); 
  end; 
 
var 
  Form1: TForm1; 
 
implementation 
 
{$R *.dfm} 
 
uses DirectSound, MMSystem, ReadWave; //ReadWave 是上面重新定義的單元 
 
var 
  myDSound: IDirectSound8; 
  bufs: array[0..2] of IDirectSoundBuffer; //緩沖區數組, 用於裝載資源文件中的三個 WAVE 文件 
 
{使用資源文件建立緩沖區並播放} 
procedure PlayResourceWave(ResName: string; var buf: IDirectSoundBuffer; loop: Boolean=false); 
var 
  wavFormat: TWaveFormatEx; 
  bufDesc: TDSBufferDesc; 
  wav: TReadWave; 
  p1: Pointer; 
  n1: DWord; 
begin 
  buf := nil; 
  wav := TReadWave.Create; 
  if not wav.OpenResource(ResName) then 
  begin 
    ShowMessage('打開失敗'); 
    wav.Free; 
    Exit; 
  end; 
  ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc)); 
  bufDesc.dwSize := SizeOf(TDSBufferDesc); 
  bufDesc.dwFlags := DSBCAPS_STATIC; 
  bufDesc.dwBufferBytes := wav.Size; 
  bufDesc.lpwfxFormat := @wav.Format; 
 
  myDSound.CreateSoundBuffer(bufDesc, buf, nil); 
 
  buf.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER); 
  wav.Read(p1, n1); 
  buf.Unlock(p1, n1, nil, 0); 
  if loop then buf.Play(0, 0, DSBPLAY_LOOPING) else buf.Play(0, 0, 0); 
  wav.Free; 
end; 
 
{初始化設備} 
procedure TForm1.FormCreate(Sender: TObject); 
var 
  wavFormat: TWaveFormatEx; 
  bufDesc: TDSBufferDesc; 
begin 
  DirectSoundCreate8(nil, myDSound, nil); 
  myDSound.SetCoOperativeLevel(Handle, DSSCL_NORMAL); 
end; 
 
{播放第一個資源} 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
  PlayResourceWave('wav_1', bufs[0], CheckBox1.Checked); 
end; 
 
{播放第二個資源} 
procedure TForm1.Button2Click(Sender: TObject); 
begin 
  PlayResourceWave('wav_2', bufs[1], CheckBox1.Checked); 
end; 
 
{播放第三個資源} 
procedure TForm1.Button3Click(Sender: TObject); 
begin 
  PlayResourceWave('wav_3', bufs[2], CheckBox1.Checked); 
end; 
 
{全部停止} 
procedure TForm1.Button4Click(Sender: TObject); 
var 
  i: Integer; 
begin 
  for i := Low(bufs) to High(bufs) do 
    if bufs[i] <> nil then bufs[i].Stop; 
end; 
 
procedure TForm1.FormDestroy(Sender: TObject); 
var 
  i: Integer; 
begin 
  for i := Low(bufs) to High(bufs) do bufs[i] := nil; 
  myDSound := nil; 
end; 
 
end. 



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