使用 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.