文档章节

在 Delphi 下使用 DirectSound (2): 查看设备性能

涂孟超
 涂孟超
发布于 2014/09/26 15:37
字数 1101
阅读 13
收藏 0
点赞 0
评论 0

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

© 著作权归作者所有

共有 人打赏支持
涂孟超
粉丝 12
博文 2004
码字总数 14107
作品 0
深圳
程序员
DirectSound入门

文档内容: (费话篇) 关于DirectSound DirectSound是DirectX API的音频(waveaudio)组件之一,它可以提供快速的混音、硬件加速功能,并且可以直接访问相关设备,当然,最主要的是它提供的...

长平狐 ⋅ 2012/08/13 ⋅ 0

C#中使用DirectX编程

我感觉声音的播放比较简单。我们从播放声音开始。为什么我这么觉得?我也不知道。 这里是展示最最最最最简单的DirectX播放声音的例子,我尽量省略了无关的代码。最后的代码只有19行,够简单了...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

Windows上的音频采集技术(转)

转自:http://shanewfx.github.io/blog/2013/08/14/caprure-audio-on-windows/前一段时间接到一个任务,需要采集到声卡的输出信号,以便与麦克风的输入信号进行混音。 之前一直没有研究过音频...

元谷 ⋅ 2013/12/05 ⋅ 0

使用UniDAC在Delphi XE4中开发iOS应用

使用UniDAC在Delphi XE4中开发iOS应用   核心提示:Delphi XE4的发布让很多Delphi开发者欣喜若狂,毫无疑问它使得Delphi开发更简单且更容易被理解,而且让开发无论是iPhone、iPad还是iPod的...

vga ⋅ 2014/06/01 ⋅ 0

SDL2源代码分析1:初始化(SDL_Init())

===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDLInit()) SDL2源代码分析2:窗口(SDLWindow) SDL2源代码分析3:渲染器...

leixiaohua1020 ⋅ 2014/11/01 ⋅ 0

DirectSound学习(二)--流式缓冲区

使用流式缓冲方式播放波形音频文件比较复杂,主要原因是在只有一个缓冲区提供给用户的前提下,这个缓冲区在提供给声卡播放数据的同是还需要用户不断的定时向其中写入数据。要注意从缓冲区这时...

imxiangzi ⋅ 02/11 ⋅ 0

钢琴曲演奏软件--FreePiano

FreePiano是一款使用电脑键盘演奏钢琴音曲的开源软件。 FreePiano的特点: 完全免费的,您不需要购买就可以使用全部的功能。 直接调用VSTi音源,不需要安装虚拟MIDI设备。 支持多种音频输出方...

匿名 ⋅ 2013/05/27 ⋅ 1

Wine 1.3.30 发布

Wine团队日前发布了Wine 1.3.30 开发版本。 Wine 是 X 和 UNIX 之上对 Windows API 的一个开放源代码实现,用来将Windows系统下的软件在类Unix系统下稳定运行,该软件更新频繁,目前已经可以...

小编辑 ⋅ 2011/10/12 ⋅ 2

C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍

原文:C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍 例子主要包括SocketAsyncEventArgs通讯封装、服务端实现日志查看、SCOKET列表、上传、下载、远程文件流、吞吐量协议,用于测试S...

杰克.陈 ⋅ 2017/12/06 ⋅ 0

为什么使用useLegacyV2RuntimeActivationPolicy?

原文:为什么使用useLegacyV2RuntimeActivationPolicy? 参考:https://msdn.microsoft.com/zh-cn/library/bbx34a2h.aspx MSDN的解释是:指定是否启用 .NET Framework 2.0 运行时激活策略,或...

杰克.陈 ⋅ 03/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Boost库编译应用

版本:Boost 1.66.0 Windows库编译 官网指南:直接执行bootstrap.bat处理文件即可,可以我却遇到一堆的问题。 环境:Windows 10 + Visual Studio 2017 Boost编译出来库命名 boost库生成文件命...

水海云 ⋅ 22分钟前 ⋅ 0

解决Eclipse发布到Tomcat丢失依赖jar包的问题

如果jar文件是以外部依赖的形式导入的。Eclipse将web项目发布到Tomcat时,是不会自动发布这些依赖的。 可以通过Eclipse在项目上右击 - Propertics - Deployment Assembly,添加“Java Build ...

ArlenXu ⋅ 22分钟前 ⋅ 0

iview tree组件层级过多时可左右滚动

使用vue+iview的tree组件,iview官网iview的tree树形控件 问题描述:tree层级过多时左右不可滚动 问题解决:修改overflow属性值 .el-tree-node>.el-tree-node_children { overflow: vi...

YXMBetter ⋅ 24分钟前 ⋅ 0

分布式锁

1.通过数据库实现 http://www.weizijun.cn/2016/03/17/%E8%81%8A%E4%B8%80%E8%81%8A%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E8%AE%BE%E8%AE%A1/ 2.ZK实现:curator-recipes分布式锁的......

素雷 ⋅ 32分钟前 ⋅ 0

Sublime Text3 快捷键

选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本。 Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名...

AndyZhouX ⋅ 39分钟前 ⋅ 0

XamarinAndroid组件教程RecylerView自定义适配器动画

XamarinAndroid组件教程RecylerView自定义适配器动画 如果RecyclerViewAnimators.Adapters命名空间中没有所需要的适配器动画,开发者可以自定义动画。此时,需要让自定义的动画继承Animation...

大学霸 ⋅ 39分钟前 ⋅ 0

eureka 基础(二)

使用Eureka服务器进行身份验证 如果其中一个eureka.client.serviceUrl.defaultZone网址中包含一个凭据(如http://user:password@localhost:8761/eureka)),HTTP基本身份验证将自动添加到您...

明理萝 ⋅ 42分钟前 ⋅ 1

Kubernetes(五) - Service

Kubernetes解决的另外一个痛点就是服务发现,服务发现机制和容器开放访问都是通过Service来实现的,把Deployment和Service关联起来只需要Label标签相同就可以关联起来形成负载均衡,基于kuberne...

喵了_个咪 ⋅ 42分钟前 ⋅ 0

更新队友POM文件后报错

打开报错的地方的pom及其引用方法所在文件的pom,观察其版本号是否一致,不一致进行更改

森火 ⋅ 56分钟前 ⋅ 0

IDEA使用sonarLint

一、IDEA如何安装SonarLint插件 1.打开 Idea 2.点击【File】 3.点击【Settings】 4.点击【Plugins】 5.在搜索栏中输入“sonarlint”关键字 6.点击【Install】进行安装 7.重启Idea 二、IDEA如...

开源中国成都区源花 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部