DirectSound学习笔记之 创建播放设备

      前面学习了,如何枚举输出设备,其目的也正式为了创建正确的播放设备了,所以这次,学习如何创建一个播放设备。
     创建设备对象,最简单的方法,就是通过DirectSoundCreate8函数来创建,该函数在Dspack的DirectX库中声明样式为:

DelphiCode:
function DirectSoundCreate8(pcGuidDevice: PGUID; out ppDS8: IDirectSound8;
pUnkOuter: IUnknown): HResult; stdcall; external DirectSoundDLL;
可见其第一个参数为PGUID形式,该参数就用来指定咱要创建的设备对象的GUID,前面,咱已经通过枚举获得了各种设备的GUID了并且保存在 Combobox的 Item中,可以随便选择一个GUID,来进行创建,该参数如果传递为nil或DSDEVID_DefaultPlayback,则使用系统默认的输出设备,SDEVID_DefaultVoicePlayback则指定为第二默认设备,通常指USB耳机麦克风等。

    第二个参数,就指定需要得到的设备对象,第三个参数类型是一个未知类型,应该是留待以后使用,这里指定为nil就可以了

具体代码如下: DelphiCode:
hr := DirectSound.DirectSoundCreate8(PGUID(ComboBox1.Items.Objects[0]),lp,nil);
if Failed(hr) then
  ShowMessage('创建设备失败');
该函数一般在没有声音输出设备,或在VXD驱动程序下,声音输出设备正在被某个应用程序通过waveform格式的api函数控制的时候会失败。

自然,可能有人会想要完全通过Com调用来创建设备的,不过比较麻烦一点,具体代码如下: DelphiCode:
Label 1;
begin
  hr := ActiveX.CoInitializeEx(nil,0);//初始化COM库
  if Failed(hr) then
     goto 1;
 //创建一个设备对象,CLSID_DirectSound8为DirectSound设备驱动类的类标识,IID_IDirectSound8为接口标识
  hr := CoCreateInstance(CLSID_DirectSound8,nil,CLSCTX_INPROC_SERVER,IID_IDirectSound8,lp);
  if Failed(hr) then
     goto 1;
  hr = lp.Initialize(nil);//初始化设备对象
  if Fialed(hr) then
    ShowMessage('失败');
1:
  CoUninitialize;
end;
创建设备对象成功之后,首要的第一件事情,我们应该是设置设备对象的协作级别,因为Windows是一个多任务环境,同一时间由多个应用程序去反问设备,通过使用协作级别,DirectX可以确保应用程序不会在别的设备使用时去访问,每个DirectSound应用程序都一个协作级别,这个级别决定着访问硬件的权限。在创建一个设备对象之后,必须使用

IDirectSound8.SetCooperativeLevel来设置协作权限,否则将听不到声音的哦

设置的代码很简单: DelphiCode:
lp.SetCooperativeLevel(self.Handle,DSSCL_NORMAL); //设置协作级别
这里我设置的是一个普通级别,第一个参数为应用程序的窗口句柄.


DirectSound定义了三个协作权限,分别是DSSCL_NORMAL,DSSCL_PRIORITY,DSSCL_WRITEPRIMARY

分别表示普通协作级,优先权协作级,写主缓冲区级


DSSCL_NORMAL(普通协作级)

   在标准协作级别(DSSCL_NORMAL)下,应用程序不能设置主缓冲区的格式,填充主缓冲区,或者压缩设备的On-board内存。所有在这个协作级别的应用程序使用一个22KHz,立体音效,8位采样格式的主缓冲区,这样设备能够在应用程序间顺利地切换。



DSSCL_PRIORITY(优先协作级)

   当使用一个出于优先协作级别(DSSCL_PRIORITY)地DirectSound设备时,应用程序享有对硬件资源的优先权,如硬件混频,设置主缓冲区的格式,以及压缩设备的On-board内存。

  游戏程序在几乎所有环境下都应该使用优先协作级别。这个级别给予了应用程序最强大的行为能力,使它能够控制采样率和位深度。优先协作级别也允许来自其他应用程序(如IP电话)的声音与游戏中的声音一同被听到。


DSSCL_WRITEPRIMARY(写入主缓冲区级)

   最高协作级别是写主缓冲区(DSSCL_WRITEPRIMARY)。当使用这一协作级别的DirectSound设备时,你的应用程序能够直接访问非WDM驱动的主缓冲区。在这种模式下,应用程序必须直接填充主缓冲区。此时,辅助缓冲区无法被播放。
  一个应用程序为了获取对主缓冲区中音频采样的直接写访问,必须被设置为写主缓冲区级别。如果应用程序没有被设置成这一级别,那么所有对主缓冲区上IDirectSoundBuffer::Lock方法的调用都将失败。

另外需要注意的是:主缓冲区只支持IDirectSoundBuffer接口,而不是IDirectSoundBuffer8。

当你的应用程序被设置为写主缓冲区协作级别并出于前台位置时,所有用于其他应用程序的辅助缓冲区将被停止并标记为已丢失。当你的应用程序顺次移动到后台时,它的主缓冲区被标记为已丢失,并且在应用程序再次移动到前台时被恢复。

如果一个DirectSound驱动器不在用户系统中时,你无法设置写主缓冲区协作级别。为判断是否出于这种情形,调用IDirectSound8::GetCaps方法,并检查DSCAPS结构中DSCAPS_EMULDRIVER标识。



设备性能

  DirectSound使你的应用程序可以检查声音设备的硬件性能。许多应用程序不需要这么做,因为DirectSound自动利用任何可用的硬件加速。然而,性能良好的应用程序能够使用这些信息,根据可用的硬件扩展它们的声音需求。比如,如果硬件混频可用,一个应用程序可能选择播放多道声音。在调用 DirectSoundCreate8 函数创建一个设备对象后,你的应用程序能够通过调用IDirectSound8.GetCaps方法获取声音设备的性能。

在Dspack中该函数的声明为:

function GetCaps(out pDSCaps: TDSCaps): HResult; stdcall;

要求传递一个TDsCaps,也就是DSCAPS的结构体

在调用的时候,我们必须先设置DSCAPS的dwsize的大小

具体代码如下: DelphiCode:
var
  hr: HRESULT;
  caps: TDSCaps;
begin
  caps.dwSize := SizeOf(TDscaps);
  hr := lp.GetCaps(caps);
  if failed(hr) then
  begin
    ShowMessage('获取性能失败');
exit;
end;
//这里,我们来查看是否有DSCAPS_EMULDRIVER,也就是测试是否能将协作级设置成DSSCL_WRITEPRIMARY if caps.dwFlags and DSCAPS_EMULDRIVER = 0 then//如果等于0,就说明没有DSCAPS_EMULDRIVER标志 begin ShowMessage('不能设置成写主缓冲区级别模式');
lp.SetCooperativeLevel(self.Handle,DSSCL_NORMAL); //设置协作级别 end else begin ShowMessage('可以设置DSSCL_WRITEPRIMARY模式');
lp.SetCooperativeLevel(self.Handle,DSSCL_WRITEPRIMARY); //设置协作级别 end;
end;

你可能感兴趣的:(游戏,windows,function,server,任务,电话)