次缓冲区(或叫辅助缓冲区)尽管使用了波形文件自己的 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;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;typeTForm1 = class(TForm)Button1: TButton;Button2: TButton;procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);end;varForm1: TForm1;implementation{$R *.dfm}uses DirectSound, MMSystem;varmyDSound: IDirectSound8;        //设备对象bufPrimary: IDirectSoundBuffer; //主缓冲buf: IDirectSoundBuffer;        //次缓冲buf8: IDirectSoundBuffer8;      //次缓冲的 IDirectSoundBuffer8 接口{初始化设备}
procedure TForm1.FormCreate(Sender: TObject);
beginDirectSoundCreate8(nil, myDSound, nil);{若手动建立主缓冲, 设备的优先级至少要指定为 DSSCL_PRIORITY}myDSound.SetCooperativeLevel(Handle, DSSCL_PRIORITY);
end;{建立主缓冲, 并修改其格式}
procedure TForm1.Button1Click(Sender: TObject);
varwavFormat,fmt2: TWaveFormatEx;bufDesc: TDSBufferDesc;
beginZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));bufDesc.dwSize := SizeOf(TDSBufferDesc);bufDesc.dwFlags := DSBCAPS_PRIMARYBUFFER; //指明建立的是主缓冲bufDesc.dwBufferBytes := 0; //主缓冲有固定的大小, 无需指定, 须是 0bufDesc.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 beginwFormatTag := 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);
varwavFormat,fmt2: TWaveFormatEx;bufDesc: TDSBufferDesc;
begin{为建立次缓冲准备格式}ZeroMemory(@wavFormat, SizeOf(TWaveFormatEx));with wavFormat do beginwFormatTag := 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);
beginbufPrimary := nil;buf := nil;buf8 := nil;myDSound := nil;
end;end.

在 Delphi 下使用 DirectSound (5): 获取或设置缓冲区的格式:相关推荐

  1. 【转载】Delphi获取与设置系统时间格式(长日期与短日期)

    Delphi获得与设置系统时间格式 在Delphi中,特别是在写管理系统软件时,经常要用到 FormatDateTime 以将 TDateTime 格式的日期时间转换成字符串形式的值显示或保存起来,或 ...

  2. DaHua相机获取与设置相机图片格式列表

    1.获取图片格式列表 2.从图片格式列表选择某种图片格式设置相机图片格式

  3. 在 Delphi 下使用 DirectSound (9): 效果器初步及 IDirectSoundFXGargle8 效果器

    只有使用 IDirectSoundBuffer8 的次缓冲区才能设置"特效", 主缓冲区主要负责的是混音和处理 3D 效果. IDirectSoundBuffer8(非 IDire ...

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

    使用 DirectSound 前应先建立 IDirectSound8 对象(之前的版本是 IDirectSound): function DirectSoundCreate8(pcGuidDevice ...

  5. 在 Delphi 下使用 DirectSound (12): 测试失真效果器 IDirectSoundFXDistortion8

    为什么80%的码农都做不了架构师?>>>    {相关结构:} TDSFXDistortion = packed recordfGain: Sinle; //-60 .. 0 : - ...

  6. 在 Delphi 下使用 DirectSound (4): 设置音量、相位、播放频率和播放位置

    通过 IDirectSoundBuffer 的 SetVolume.SetPan.SetFrequency.SetCurrentPosition 方法可以简单进行这些设置. 同时 IDirectSou ...

  7. 在 Delphi 下使用 DirectSound (14): 测试镶边效果器 IDirectSoundFXFlanger8

    {相关结构:} TDSFXFlanger = packed recordfWetDryMix: Single; // 0 .. 100 : 50 (%)fDepth: Single; // 0 .. ...

  8. 在 Delphi 下使用 DirectSound (6): 按文件自己的格式(TWaveFormatEx)播放

    这必须手动建立主缓冲区. unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Contr ...

  9. Delphi下利用WinIo模拟鼠标键盘详解

    本文最早在编程论坛上发表,文章地址:http://programbbs.com/bbs/view12-17207-1.htm,相关文件可以在上述地址的页面中下载.转载时请注明出处. 前言 一日发现Se ...

最新文章

  1. 和 杠精 聊Redis多线程 :(
  2. MongoDB数据库的下载与Python交互
  3. 共享两个有用的网页布局表格 【有用】
  4. php mvc 通过 htaccess 隐藏 index.php 或 index.php?arg=
  5. 带属性的字符串(NSMutableAttributedString)的使用
  6. C#中 构造函数的执行
  7. cgroup学习(二)——cgroup框架结构
  8. 三阶魔方复原操作方法
  9. 微信永久封禁:从入门到精通
  10. win10内置ubuntu, “指定的网络名不再可用”解决办法
  11. C语言---用筛选法求100以内的素数
  12. 【UOJ#60】【UR #5】怎样提高智商
  13. android app开机启动画面,Android-如何设置APP开机启动(图文)
  14. Linux下安装YASM--编译x264
  15. mac 在连接wifi时出现 无互联网连接 的警告,叹号
  16. 每日算法(四十三)-java为了更改的规划城市,需要统计楼栋数目信息。
  17. Linux管线命令 - cut,grep,sort,uniq,wc,tee,tr,col,join,paste,expand,split,xargs
  18. 视频理解领域小样本学习调研报告
  19. 计算机毕业设计-基于springboot的电影院会员管理系统(项目+文档+ppt)
  20. 基于Simulink的QAM调制解调系统仿真

热门文章

  1. Java数据结构 反转链表
  2. GT Transceiver的复位与初始化(2)CPLL复位以及QPLL复位
  3. 【 Vivado 】UCF到XDC之间的转换
  4. 全过程实现一个最简单的FPGA项目之PWM蜂鸣器控制
  5. FPGA从Xilinx的7系列学起(2)
  6. Tiny4412 Android5.0 定制:编译生成img后如何删除原厂的apk
  7. Spark函数:cogroup
  8. 程序员的量化交易之路(1)----规划开篇
  9. ORA-01081: cannot start already-running ORACLE - shut it down first
  10. Docker Remote API v1.12使用