程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 在 Delphi 下使用 DirectSound (5): 獲取或設置緩沖區的格式

在 Delphi 下使用 DirectSound (5): 獲取或設置緩沖區的格式

編輯:Delphi

次緩沖區(或叫輔助緩沖區)盡管使用了波形文件自己的 TWaveFormatEx, 但最終播放的卻只是 22050HZ 的 8 位立體聲.

  因為次緩沖區最終要混入主緩沖區才播放, 可主緩沖區的缺省格式是 22050HZ 的 8 位立體聲(這利於在不同應用程序之間的平滑切換).

  次緩沖區一旦建立, 其格式就無法修改了(無法使用緩沖區對象的 SetFormat() 方法); 好在主緩沖區可以重置格式.

  也就是說, 播放 44100HZ、16 位的 Wave 時, 如果不通過主緩沖修改格式則無法原聲播放.

  要修改格式只能手動建立主緩沖區(我們無法使 DirectSound 自動建立的主緩沖區, 沒有入口).

  手動建立主緩沖區的注意事項:

  1、SetCoOperativeLevel(Handle, DSSCL_PRIORITY); 因為主緩沖應該是硬緩沖, 這會影響到其它應用程序.

  2、為緩沖區指定 TDSBufferDesc 結構時須 TDSBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER.

  3、同時 TDSBufferDesc.dwBufferBytes = 0; 主緩沖使用的應該是硬緩沖, 其大小是固定的, 不能設置, 指定 0 即可

  4、同時 TDSBufferDesc.lpwfxFormat = nil; 因為主緩沖區的格式已有默認, 重新設置必須使用 SetFormat() 方法.

  另外, 主緩沖不支持 IDirectSoundBuffer8 接口(IDirectSoundBuffer8 比 IDirectSoundBuffer 多出一些功能);

  在次緩沖中可以使用 IDirectSoundBuffer8,但不存在像 CreateSoundBuffer8 這樣的函數, 可通過 IDirectSoundBuffer.QueryInterface() 方法方便獲取.

  測試程序:

unit Unit1; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
 
type 
  TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
  end; 
 
var 
  Form1: TForm1; 
 
implementation 
 
{$R *.dfm} 
 
uses DirectSound, MMSystem; 
 
var 
  myDSound: IDirectSound8;        //設備對象 
  bufPrimary: IDirectSoundBuffer; //主緩沖 
  buf: IDirectSoundBuffer;        //次緩沖 
  buf8: IDirectSoundBuffer8;      //次緩沖的 IDirectSoundBuffer8 接口 
 
{初始化設備} 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
  DirectSoundCreate8(nil, myDSound, nil); 
  {若手動建立主緩沖, 設備的優先級至少要指定為 DSSCL_PRIORITY} 
  myDSound.SetCoOperativeLevel(Handle, DSSCL_PRIORITY); 
end; 
 
{建立主緩沖, 並修改其格式} 
procedure TForm1.Button1Click(Sender: TObject); 
var 
  wavFormat,fmt2: TWaveFormatEx; 
  bufDesc: TDSBufferDesc; 
begin 
  ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc)); 
  bufDesc.dwSize := SizeOf(TDSBufferDesc); 
  bufDesc.dwFlags := DSBCAPS_PRIMARYBUFFER; //指明建立的是主緩沖 
  bufDesc.dwBufferBytes := 0; //主緩沖有固定的大小, 無需指定, 須是 0 
  bufDesc.lpwfxFormat := nil; //主緩沖有自己的格式, 修改它須通過 SetFormat() 方法 
 
  myDSound.CreateSoundBuffer(bufDesc, bufPrimary, nil); 
 
  {顯示修改前主緩沖格式} 
  bufPrimary.GetFormat(@fmt2, SizeOf(TWaveFormatEx), nil); 
  ShowMessageFmt('主緩沖默認: %dHZ %d 位 %d 聲道', [fmt2.nSamplesPerSec, fmt2.wBitsPerSample, fmt2.nChannels]); 
 
  {修改主緩沖的格式} 
  ZeroMemory(@wavFormat, SizeOf(TWaveFormatEx)); 
  with wavFormat do begin 
    wFormatTag := WAVE_FORMAT_PCM; 
    nChannels := 2; 
    nSamplesPerSec := 44100; 
    wBitsPerSample := 16; 
    nBlockAlign := wBitsPerSample * nChannels div 8; 
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; 
  end; 
  bufPrimary.SetFormat(@wavFormat); 
 
  {顯示修改後主緩沖格式} 
  bufPrimary.GetFormat(@fmt2, SizeOf(TWaveFormatEx), nil); 
  ShowMessageFmt('主緩沖改後: %dHZ %d 位 %d 聲道', [fmt2.nSamplesPerSec, fmt2.wBitsPerSample, fmt2.nChannels]); 
end; 
 
{建立次緩沖, 同時獲取個 IDirectSoundBuffer8 接口} 
procedure TForm1.Button2Click(Sender: TObject); 
var 
  wavFormat,fmt2: TWaveFormatEx; 
  bufDesc: TDSBufferDesc; 
begin 
  {為建立次緩沖准備格式} 
  ZeroMemory(@wavFormat, SizeOf(TWaveFormatEx)); 
  with wavFormat do begin 
    wFormatTag := WAVE_FORMAT_PCM; 
    nChannels := 2; 
    nSamplesPerSec := 44100; 
    wBitsPerSample := 16; 
    nBlockAlign := wBitsPerSample * nChannels div 8; 
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; 
  end; 
 
  ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc)); 
  bufDesc.dwSize := SizeOf(TDSBufferDesc); 
  bufDesc.dwFlags := DSBCAPS_STATIC; 
  bufDesc.dwBufferBytes := 3 * wavFormat.nAvgBytesPerSec; //指定容納 3 秒鐘的波形數據 
  bufDesc.lpwfxFormat := @wavFormat; 
 
  {建立 IDirectSoundBuffer, 並查看其格式} 
  myDSound.CreateSoundBuffer(bufDesc, buf, nil); 
  buf.GetFormat(@fmt2, SizeOf(TWaveFormatEx), nil); 
  ShowMessageFmt('buf: %dHZ %d 位 %d 聲道', [fmt2.nSamplesPerSec, fmt2.wBitsPerSample, fmt2.nChannels]); 
 
  {從 IDirectSoundBuffer 獲取 IDirectSoundBuffer8, 並查看其格式} 
  buf.QueryInterface(IID_IDirectSoundBuffer8, buf8); // 
  ZeroMemory(@fmt2, SizeOf(TWaveFormatEx)); 
  buf.GetFormat(@fmt2, SizeOf(TWaveFormatEx), nil); 
  ShowMessageFmt('buf8: %dHZ %d 位 %d 聲道', [fmt2.nSamplesPerSec, fmt2.wBitsPerSample, fmt2.nChannels]); 
end; 
 
procedure TForm1.FormDestroy(Sender: TObject); 
begin 
  bufPrimary := nil; 
  buf := nil; 
  buf8 := nil; 
  myDSound := nil; 
end; 
 
end. 
 
 


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