通过 IDirectSoundBuffer 的 SetVolume、SetPan、SetFrequency、SetCurrentPosition 方法可以简单进行这些设置.
同时 IDirectSoundBuffer 也有对应的 GetVolume、GetPan、GetFrequency、GetCurrentPosition 方法.

关键的一点是如果能让缓冲区接受音量、相位和频率的设置, 必须在建立缓冲区时指定相应的标志.

下面的常量说明了它们的取值范围:


DSBVOLUME_MAX = 0;      //音量最大值, 保持在控制面板设置的音量
DSBVOLUME_MIN = -10000; //音量最小值DSBPAN_LEFT   = -10000; //左声道
DSBPAN_CENTER = 0;      //均衡
DSBPAN_RIGHT  = 10000;  //右声道DSBFREQUENCY_ORIGINAL = 0;      //使用默认
DSBFREQUENCY_MIN      = 100;    //频率最小值
DSBFREQUENCY_MAX      = 200000; //频率最大值, 在 DirectSound 9.0 之下的版本, 此值是 100000


在上一个例子中, 最占篇幅的就是那两个函数; 为了更方便使用, 把它们做在了一个 TReadWaveFile 类里:


{实现 TReadWaveFile 类的单元}
unit ReadWaveFile;interfaceuses Windows, Classes, SysUtils, MMSystem;type
TReadWaveFile = class
privateFFileHandle: HMMIO;FFormat: TWaveFormatEx;FSize: DWORD;
publicconstructor Create;destructor Destroy; override;function Open(FileName: string): Boolean;            //打开文件并读取信息function Read(pDest: Pointer; Size: DWORD): Boolean; //读出波形数据property Format: TWaveFormatEx read FFormat;         //读出格式数据property Size: DWORD read FSize;                     //读出波形数据的大小
end;implementation{ TReadWaveFile }constructor TReadWaveFile.Create;
begininherited;end;destructor TReadWaveFile.Destroy;
beginif FFileHandle > 0 then mmioClose(FFileHandle, 0);inherited;
end;function TReadWaveFile.Open(FileName: string): Boolean;
varckiRIFF,ckiFmt,ckiData: TMMCKInfo;
beginResult := False;if not FileExists(FileName) then Exit;FFileHandle := mmioOpen(PChar(FileName), nil, MMIO_READ);if FFileHandle = 0 then Exit;ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));mmioDescend(FFileHandle, @ckiRIFF, nil, MMIO_FINDRIFF);if (ckiRIFF.ckid <> FOURCC_RIFF) or (ckiRIFF.fccType <> mmioStringToFOURCC('WAVE',0)) then Exit;ZeroMemory(@FFormat, SizeOf(TWaveFormatEx));ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);ZeroMemory(@ckiData, SizeOf(TMMCKInfo));ckiData.ckid := mmioStringToFOURCC('data', 0);if (mmioDescend(FFileHandle, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) thenmmioRead(FFileHandle, @FFormat, SizeOf(TWaveFormatEx));mmioAscend(FFileHandle, @ckiFmt, 0);if (mmioDescend(FFileHandle, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) thenFSize := ckiData.cksize;Result := FFormat.wFormatTag = WAVE_FORMAT_PCM;
end;function TReadWaveFile.Read(pDest: Pointer; Size: DWORD): Boolean;
beginResult := mmioRead(FFileHandle, pDest, Size) = Size;
end;end.


测试程序用到了四个 Button 和三个 TrackBar 还有它们的默认事件:


unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ComCtrls;typeTForm1 = class(TForm)Button1: TButton;     //打开并播放Button2: TButton;     //反复播放Button3: TButton;     //暂停Button4: TButton;     //从头播放TrackBar1: TTrackBar; //用于音量调节TrackBar2: TTrackBar; //用于相位调节TrackBar3: TTrackBar; //用于频率调节procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure Button3Click(Sender: TObject);procedure Button4Click(Sender: TObject);procedure TrackBar1Change(Sender: TObject);procedure TrackBar2Change(Sender: TObject);procedure TrackBar3Change(Sender: TObject);end;varForm1: TForm1;implementation{$R *.dfm}uses DirectSound, ReadWaveFile; // ReadWaveFile 是 TReadWaveFile 类所在的单元varmyDSound: IDirectSound8;buf: IDirectSoundBuffer;procedure TForm1.FormCreate(Sender: TObject);
beginTrackBar1.Min := DSBVOLUME_MIN;TrackBar1.Max := DSBVOLUME_MAX;TrackBar2.Min := DSBPAN_LEFT;TrackBar2.Max := DSBPAN_RIGHT;TrackBar3.Min := 100;TrackBar3.Max := 100000;Button1.Caption := '打开并播放';Button2.Caption := '反复播放';Button3.Caption := '暂停';Button4.Caption := '从头播放';System.ReportMemoryLeaksOnShutdown := true;
end;procedure TForm1.Button1Click(Sender: TObject);
varbufDesc: TDSBufferDesc;p1: Pointer;n1: DWORD;wavPath: string;wav: TReadWaveFile; //
beginbuf := nil;myDSound := nil;with TOpenDialog.Create(nil) do beginFilter := 'Wave File(*.wav)|*.wav';if Execute then wavPath := FileName;Free;end;wav := TReadWaveFile.Create;if not wav.Open(wavPath) thenbeginShowMessage('只能是 PCM 格式的 WAVE 文件');wav.Free;Exit;end;DirectSoundCreate8(nil, myDSound, nil);myDSound.SetCooperativeLevel(Self.Handle, DSSCL_NORMAL);ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));bufDesc.dwSize := SizeOf(TDSBufferDesc);{指定缓冲区允许音量、相位和频率调节}bufDesc.dwFlags := DSBCAPS_STATIC or DSBCAPS_CTRLVOLUME or DSBCAPS_CTRLPAN or DSBCAPS_CTRLFREQUENCY;bufDesc.dwBufferBytes := wav.Size;bufDesc.lpwfxFormat := @wav.Format;myDSound.CreateSoundBuffer(bufDesc, buf, nil);buf.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER);wav.Read(p1, n1);buf.Unlock(p1, n1, nil, 0);buf.Play(0, 0, 0);TrackBar1.Position := 0;TrackBar2.Position := 0;TrackBar3.Position := wav.Format.nSamplesPerSec;wav.Free;
end;procedure TForm1.Button2Click(Sender: TObject);
beginif buf <> nil then buf.Play(0, 0, DSBPLAY_LOOPING);
end;procedure TForm1.Button3Click(Sender: TObject);
beginif buf <> nil then buf.Stop;
end;{从头播放}
procedure TForm1.Button4Click(Sender: TObject);
beginif buf = nil then Exit;buf.Stop;buf.SetCurrentPosition(0);buf.Play(0, 0, 0);
end;{音量调节}
procedure TForm1.TrackBar1Change(Sender: TObject);
beginif buf <> nil then buf.SetVolume(TTrackBar(Sender).Position);
end;{相位调节}
procedure TForm1.TrackBar2Change(Sender: TObject);
beginif buf <> nil then buf.SetPan(TTrackBar(Sender).Position);
end;{频率调节}
procedure TForm1.TrackBar3Change(Sender: TObject);
beginif buf <> nil then buf.SetFrequency(TTrackBar(Sender).Position);
end;procedure TForm1.FormDestroy(Sender: TObject);
beginbuf := nil;myDSound := nil;
end;end.

转载于:https://www.cnblogs.com/del/archive/2011/01/16/1936942.html

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

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

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

  2. 在 Delphi 下使用 DirectSound (5): 获取或设置缓冲区的格式:

    次缓冲区(或叫辅助缓冲区)尽管使用了波形文件自己的 TWaveFormatEx, 但最终播放的却只是 22050HZ 的 8 位立体声. 因为次缓冲区最终要混入主缓冲区才播放, 可主缓冲区的缺省格式是 ...

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

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

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

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

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

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

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

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

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

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

  8. Delphi下的COM编程

    Delphi通过向导可以非常迅速和方便的直接建立实现COM对象的代码,但是整个COM实现的过程被完全的封装,甚至没有VCL那么结构清晰可见. 一个没有C++下COM开发经验甚至没有接触过COM开发的D ...

  9. DELPHI下的SOCK编程(转)

    DELPHI下的SOCK编程       本文是写给公司新来的程序员的,算是一点培训的教材.本文不会涉及太多的编程细节,只是简单讲解在DELPHI下进行Winsock编程最好了解的知识. 题外话:我认 ...

最新文章

  1. mysql获取有哪几种状态_Mysql进阶垫脚石 -- Sql命令的执行状态有哪几种
  2. FS,FT,DFT,DFS和DTFT的关系
  3. Steps to configure Oracle 11g Data Guard Physical Standby – Active Data Guard Part-I
  4. RWCString 定义 memeroy leak
  5. @EnableDiscoveryClient和@EnableEurekaClient的区别
  6. css居中无效的解决办法
  7. python附件发送到邮箱_python – 如何发送电子邮件附件?
  8. 钣金编程软件Radan无人值守,自动排版功能
  9. 怎么利用计算机辅助评标,计算机辅助评标系统及其的应用.doc
  10. 故障:PDF 文件打印失败
  11. 纯干货,用好PPT中的异形,提高页面的设计感,建议收藏!
  12. LAV Filter 源代码分析 4: LAV Video (2)
  13. 门户通专访蓝色理想曾沐阳:用户需慢慢沉淀
  14. 专业课课本复习(数电,通原,数信,信号与系统,数据结构)
  15. 山东专升本-计算机课堂笔记之第一章 信息技术与计算机文化(一)
  16. Quartus II使用说明(Verilog HDL二选一数据选择器 )
  17. Hook DirectX 在War3 魔兽争霸界面写屏
  18. 渗透测试常见漏洞描述及修复建议
  19. DP线和HDMI线区别,优缺点,传输显示器图像速率
  20. 【Tanzu 社区版=TCE】 Mac 笔记本快速部署安装体验-(一)

热门文章

  1. android 百度悬浮搜索框,百度的搜索框效果如何实现的???
  2. list vue 删除后页面渲染_浅谈Vue项目实战(页面渲染+事件绑定)
  3. java手机号归属地查询_【原创】Java实现手机号码归属地查询
  4. php mysql 随机字符串函数是,mysql生成随机字符串函数分享
  5. bash、dash(/bin/bash和/bin/sh)
  6. KVM Vhost-net 和 Virtio-net代码详解(十八)
  7. KVM中virtio-user工作思路(十二)
  8. linux虚拟网络设备之tun/tap(一)
  9. dec++如何查看机器指令_机器指令到汇编再到高级编程语言!
  10. 怎么给电脑设密码_怎么给电脑中重要的文件夹设置密码?