使用 DirectSound 前應先建立 IDirectSound8 對象(之前的版本是 IDirectSound):
function DirectSoundCreate8(
pcGuidDevice: PGUID; //設備的 GUID; 指定 nil 表示使用默認聲卡
out ppDS8: IDirectSound8; //要返回的 IDirectSound8 對象
pUnkOuter: IUnknown //未使用, 應為 nil
): HResult; stdcall; //返回錯誤碼
//也可使用 GUID 常數指定設備:
DSDEVID_DefaultPlayback //默認設備
DSDEVID_DefaultVoicePlayback //二級默認設備
然後通過 IDirectSound8 對象(它代表著一個播放設備)創建緩沖區, 以寫入聲音信息.
這裡的緩沖區分 "主緩沖區" 和 "次緩沖區". 主緩沖區只有一個; 次緩沖區可以有多個, 以實現多個聲音的同時播放.
DirectSound 會盡量使用硬件(聲卡)提供的緩沖區; 如果硬件不支持則只好使用系統內存做緩沖區, 但這樣效率不及前者.
通過 IDirectSound8.GetCaps() 方法可以獲取指定設備的詳細性能:
function GetCaps(
out pDSCaps: TDSCaps //獲取到的信息將放在 TDSCaps 結構體中
): HResult; stdcall;
//TDSCaps 結構:
TDSCaps = packed record
dwSize : DWord; //結構大小(字節)
dwFlags : DWord; //性能標志
dwMinSecondarySampleRate : DWord; //次緩沖區的最小取樣率
dwMaxSecondarySampleRate : DWord; //次緩沖區的最大取樣率
dwPrimaryBuffers : DWord; //主緩沖區個數
dwMaxHwMixingAllBuffers : DWord; //硬件緩沖區的最大數目
dwMaxHwMixingStaticBuffers : DWord; //靜態硬件緩沖區的最大數目
dwMaxHwMixingStreamingBuffers : DWord; //流式硬件緩沖區的最大數目
dwFreeHwMixingAllBuffers : DWord; //空閒的硬件緩沖區個數
dwFreeHwMixingStaticBuffers : DWord; //空閒的靜態硬件緩沖區個數
dwFreeHwMixingStreamingBuffers : DWord; //空閒的流式硬件緩沖區個數
dwMaxHw3DAllBuffers : DWord; //3D 硬件緩沖區的最大數目
dwMaxHw3DStaticBuffers : DWord; //3D 靜態硬件緩沖區的最大數目
dwMaxHw3DStreamingBuffers : DWord; //3D 流式硬件緩沖區的最大數目
dwFreeHw3DAllBuffers : DWord; //空閒的 3D 硬件緩沖區的最大數目
dwFreeHw3DStaticBuffers : DWord; //空閒的 3D 靜態硬件緩沖區的最大數目
dwFreeHw3DStreamingBuffers : DWord; //空閒的 3D 流式硬件緩沖區的最大數目
dwTotalHwMemBytes : DWord; //硬件內存總量(字節)
dwFreeHwMemBytes : DWord; //空閒的硬件內存總量(字節)
dwMaxContigFreeHwMemBytes : DWord; //空閒的硬件內存最大連續塊大小(字節)
dwUnlockTransferRateHwBuffers : DWord; //硬件緩沖區的數據傳輸速率(千字節/秒)
dwPlayCpuOverheadSwBuffers : DWord; //混合軟件緩沖區占用的 CPU 周期的百分比
dwReserved1 : DWord; //未使用
dwReserved2 : DWord; //未使用
end;
查看默認設備性能的測試程序:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo; //用於顯示信息
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses DirectSound;
procedure TForm1.FormCreate(Sender: TObject);
var
myDSound: IDirectSound8;
capInfo: TDSCaps;
p: PDSCaps;
begin
Memo1.ScrollBars := ssBoth;
Memo1.Align := alLeft;
Memo1.Clear;
FillChar(capInfo, SizeOf(TDSCaps), 0);
capInfo.dwSize := SizeOf(TDSCaps);
DirectSoundCreate8(nil, myDSound, nil);
myDSound.GetCaps(capInfo);
with Memo1.Lines do begin
Add(Format('%d'#9'dwSize', [capInfo.dwSize ]));
Add(Format('%d'#9'dwFlags', [capInfo.dwFlags ]));
Add(Format('%d'#9'dwMinSecondarySampleRate', [capInfo.dwMinSecondarySampleRate ]));
Add(Format('%d'#9'dwMaxSecondarySampleRate', [capInfo.dwMaxSecondarySampleRate ]));
Add(Format('%d'#9'dwPrimaryBuffers', [capInfo.dwPrimaryBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingAllBuffers', [capInfo.dwMaxHwMixingAllBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingStaticBuffers', [capInfo.dwMaxHwMixingStaticBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingStreamingBuffers', [capInfo.dwMaxHwMixingStreamingBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingAllBuffers', [capInfo.dwFreeHwMixingAllBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingStaticBuffers', [capInfo.dwFreeHwMixingStaticBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingStreamingBuffers', [capInfo.dwFreeHwMixingStreamingBuffers]));
Add(Format('%d'#9'dwMaxHw3DAllBuffers', [capInfo.dwMaxHw3DAllBuffers ]));
Add(Format('%d'#9'dwMaxHw3DStaticBuffers', [capInfo.dwMaxHw3DStaticBuffers ]));
Add(Format('%d'#9'dwMaxHw3DStreamingBuffers', [capInfo.dwMaxHw3DStreamingBuffers ]));
Add(Format('%d'#9'dwFreeHw3DAllBuffers', [capInfo.dwFreeHw3DAllBuffers ]));
Add(Format('%d'#9'dwFreeHw3DStaticBuffers', [capInfo.dwFreeHw3DStaticBuffers ]));
Add(Format('%d'#9'dwFreeHw3DStreamingBuffers', [capInfo.dwFreeHw3DStreamingBuffers ]));
Add(Format('%d'#9'dwTotalHwMemBytes', [capInfo.dwTotalHwMemBytes ]));
Add(Format('%d'#9'dwFreeHwMemBytes', [capInfo.dwFreeHwMemBytes ]));
Add(Format('%d'#9'dwMaxContigFreeHwMemBytes', [capInfo.dwMaxContigFreeHwMemBytes ]));
Add(Format('%d'#9'dwUnlockTransferRateHwBuffers', [capInfo.dwUnlockTransferRateHwBuffers ]));
Add(Format('%d'#9'dwPlayCpuOverheadSwBuffers', [capInfo.dwPlayCpuOverheadSwBuffers ]));
end;
end;
end.
查看所有設備性能的測試程序:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
ComboBox1: TComboBox; //用於設備列表
procedure FormCreate(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses DirectSound;
var
guidArr: array of TGUID;
function EnumCallback(lpGuid: PGUID; lpcstrDescription, lpcstrModule: PChar;
lpContext: Pointer): BOOL; stdcall;
begin
if lpGuid <> nil then
begin
TStrings(lpContext).Add(lpcstrDescription);
SetLength(guidArr, Length(guidArr) + 1);
guidArr[Length(guidArr) - 1] := lpGuid^;
end;
Result := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1.Align := alTop;
Memo1.ScrollBars := ssBoth;
Memo1.Align := alClIEnt;
Memo1.Clear;
DirectSoundEnumerate(EnumCallback, ComboBox1.Items);
ComboBox1.ItemIndex := 0;
ComboBox1.OnChange(nil);
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
var
myDSound: IDirectSound8;
capInfo: TDSCaps;
p: PDSCaps;
begin
Memo1.Clear;
ZeroMemory(@capInfo, SizeOf(TDSCaps));
capInfo.dwSize := SizeOf(TDSCaps);
DirectSoundCreate8(@guidArr[ComboBox1.ItemIndex], myDSound, nil);
Caption := GUIDToString(guidArr[ComboBox1.ItemIndex]);
myDSound.GetCaps(capInfo);
with Memo1.Lines do begin
Add(Format('%d'#9'dwSize', [capInfo.dwSize ]));
Add(Format('%d'#9'dwFlags', [capInfo.dwFlags ]));
Add(Format('%d'#9'dwMinSecondarySampleRate', [capInfo.dwMinSecondarySampleRate ]));
Add(Format('%d'#9'dwMaxSecondarySampleRate', [capInfo.dwMaxSecondarySampleRate ]));
Add(Format('%d'#9'dwPrimaryBuffers', [capInfo.dwPrimaryBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingAllBuffers', [capInfo.dwMaxHwMixingAllBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingStaticBuffers', [capInfo.dwMaxHwMixingStaticBuffers ]));
Add(Format('%d'#9'dwMaxHwMixingStreamingBuffers', [capInfo.dwMaxHwMixingStreamingBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingAllBuffers', [capInfo.dwFreeHwMixingAllBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingStaticBuffers', [capInfo.dwFreeHwMixingStaticBuffers ]));
Add(Format('%d'#9'dwFreeHwMixingStreamingBuffers', [capInfo.dwFreeHwMixingStreamingBuffers]));
Add(Format('%d'#9'dwMaxHw3DAllBuffers', [capInfo.dwMaxHw3DAllBuffers ]));
Add(Format('%d'#9'dwMaxHw3DStaticBuffers', [capInfo.dwMaxHw3DStaticBuffers ]));
Add(Format('%d'#9'dwMaxHw3DStreamingBuffers', [capInfo.dwMaxHw3DStreamingBuffers ]));
Add(Format('%d'#9'dwFreeHw3DAllBuffers', [capInfo.dwFreeHw3DAllBuffers ]));
Add(Format('%d'#9'dwFreeHw3DStaticBuffers', [capInfo.dwFreeHw3DStaticBuffers ]));
Add(Format('%d'#9'dwFreeHw3DStreamingBuffers', [capInfo.dwFreeHw3DStreamingBuffers ]));
Add(Format('%d'#9'dwTotalHwMemBytes', [capInfo.dwTotalHwMemBytes ]));
Add(Format('%d'#9'dwFreeHwMemBytes', [capInfo.dwFreeHwMemBytes ]));
Add(Format('%d'#9'dwMaxContigFreeHwMemBytes', [capInfo.dwMaxContigFreeHwMemBytes ]));
Add(Format('%d'#9'dwUnlockTransferRateHwBuffers', [capInfo.dwUnlockTransferRateHwBuffers ]));
Add(Format('%d'#9'dwPlayCpuOverheadSwBuffers', [capInfo.dwPlayCpuOverheadSwBuffers ]));
end;
end;
end.