博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在 Delphi 下使用 DirectSound (5): 获取或设置缓冲区的格式:
阅读量:6941 次
发布时间:2019-06-27

本文共 4125 字,大约阅读时间需要 13 分钟。

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

转载地址:http://imfnl.baihongyu.com/

你可能感兴趣的文章
同步github工程gitcafe
查看>>
[转]用C#实现的条形码和二维码编码解码器
查看>>
_tcscat在Debug和Release根据问题
查看>>
LinearLayout 垂直滚动条
查看>>
7月19日Docker&Kubernetes技术沙龙总结 - DockOne.io
查看>>
【扩展知识3】一些困难的数组
查看>>
如何在Ubuntu 14.04中安装最新版Eclipse
查看>>
sublime text 3之快捷键操作
查看>>
rest-work-eat-study-rest-work-eat or rest-rest-work-work-eat-eat..
查看>>
Hadoop-2.2.0中国文献—— Web应用代理
查看>>
iOS开发多线程篇—多线程简单介绍
查看>>
c语言的label后面不能直接跟变量申明
查看>>
log4j配置文件的详解
查看>>
struts2于validate要使用
查看>>
C++11实现模板手柄:委托构造函数、defaultkeyword分析
查看>>
Ignatius and the Princess III(母函数)
查看>>
使用setsid替代nohup
查看>>
筛选法求素数
查看>>
Andorid Async-HttpClient阅览
查看>>
http协议格式
查看>>