DirectSound简介
1. DirectSound特性:速度快、可控制性强
(1) 当硬件空闲时自动启用硬件加速
(2) 不受数量限制的声源混音
(3) 声音重现延迟时间短暂
(4) 与Direct3D接口简单的3D声音定位效果
(5) 自动将输入的Wave数据装换成与输出匹配的格式—格式输入为复杂格式
(6) 支持属性设置,利用硬件的新特性而不改变API函数
2. 从声音缓冲区对象:代表一个声源,这个声源既可以是静态的声音对象,也可以是动态的声音对象。静态的声音对象是指声音数据一次性读入内存,它一般适用于较短的声音。动态的声音对象是指声音数据必须隔一段时间传送一部分到缓冲区中,所有缓冲区都含有脉冲编码调制(PCM)格式的声音样本数据
播放从声音缓冲区对象时,DirectSound从每个缓冲区中取出数据,然后在主缓冲区中进行混音(硬件混音和DirectSound软件混音),然后送往输出设备
3. DirectSound只支持(.wav)格式的声音,不支持MIDI的回放
DirectSoundCapture独立与DirectSound,是DirectX中的一个组件,它允许捕获wave声音
4. 声音格式:声道数、采样率、采样点的位数、格式标签——标识采样数据的解释方法(格式信息被包含在WAVEFORMATEX结构中)
5. 设置DirectSound
(1) 步骤:1.为声音设备获得一个“全局唯一标志符(GUID)”(可选)
2.生成DirectSound对象
3.设置协作优先级
4.设置主缓冲区对象的格式(可选)
(2)枚举输出设备:DirectSoundEnumerate函数(一般不用,DirectSound对象通常初始化系统中最好的设备)
(3)生成DirectSound对象:DirectSoundCreate函数
(4)设置协作优先级:SetCooperativeLevel方法——调用该方法后,把DirectSound对象捆绑到一个窗口上,并且决定了应用程序和其它程序间怎样分享声音设备
(5)设置主缓冲区格式:协作优先级至少设置为DSSCL_PRIORITY
(6)改变扬声器配置:GetSpeakerConfig和SetSpeakerConfig
(7)获取设备支持能力:GetCaps方法会提供需要的设备信息(DSCAPS结构)
6. 属性设置:IKsPropertySet接口(QuerySupprot方法、Get方法、Set方法)
7. 一个应用程序应该只生成一个DirectSound对象,为了提高程序执行速度,应该设置主缓冲区声音格式与从缓冲区声音的格式相同
DirectSound回放
8. 进一步了解缓冲区对象(概念上讲,缓冲区是环形的)
(1)播放位置和写入位置(指针)
当前播放位置是下一个即将送入混音器的数据的偏移地址
当前写入位置并不是正在这个位置写入数据,而是缓冲区当前播放位置的前面一点,在这个位置写入数据是安全的。它是当前数据的可写入位置
(2)满足任务要求的最佳缓冲区对象
静态从缓冲区对象:适用于单一、短小、经常重复的声音
动态缓冲区对象:适用于由于声音尺寸限制不能完全放入缓冲区中,而是在播放声音的过程中每隔一段时间传递一部分数据到缓冲区中
CreateSoundBuffer方法缺省时生成的是一个动态缓冲区对象,只有设置了DSBCAPS_STATIC标志后才生成静态缓冲区对象
(3)硬件和软件
硬件缓冲区:DirectSound在声卡内存中生成从缓冲区对象,也就是说在声卡中分配资源(通常生成的是静态缓冲区对象)
软件缓冲区:在系统内存中分配内存(动态缓冲区对象只能保留在系统内存中)
(4)软件混音与硬件混音
(5) Sticky焦点与Global焦点
如果为缓冲区声音对象设置Global焦点,它将一直处于发声状态,直到另一具有exclusiue(独占)协作优先级的应用程序转到前台运行时为止,为缓冲区声音对象设置Sticky焦点意味着它将一直处于发声状态,直到另一个DirectSound的应用程序转到前台运行时为止
(6)控制(属性:3D属性、频率、均衡、音量、位置通告)
(7)避免不必要的CPU开支:不要申请不必要的控制特性、使从缓冲区声音对象具有相同的格式,在可能的情况下将从缓冲区的格式也设置成这个格式、不要生成不必要的3D声音缓冲区对象
9. Windows最常用的声音数据格式:波形声音文件(.wav文件)
波形文件具有资源交换文件格式
(1) 从资源中读入声音:短小的声音可以作为一种资源存储在可执行文件或动态链接库中,而不用存储为一个个独立的声音文件
10. 使用缓冲区对象
(1)设置并播放一个缓冲区对象的步骤:
1. 初始化一个描述声音格式的WAVEFORMATEX结构
2. 用缓冲区的参数——包括WAVEFORMATEX结构的指针,初始化一个DSBUFFERDESC结构
3. 调用CreateSoundBuffer方法生成缓冲区对象
4. 锁定缓冲区的全部或部分
5. 复制数据(通常是从波形文件或资源中)到已锁定的缓冲区部分
6. 对缓冲区解锁
7. 若需要,设置播放位置
8. 播放缓冲区对象
9. 若是动态缓冲区对象,重复4,5,6步
(2)格式描述
设置缓冲区对象的第一步是描述声音格式,大多数情况下,可以简单地从波形文件本身获得该信息
(3)缓冲区对象描述(DSBUFFERDESC结构)
1. 标志设置:告诉DirectSound把缓冲区对象放在哪里,它具有什么能力
2. 缓冲区大小(WAVERORMATEX结构中成员)
3. 指向声音格式的指针
(4)生成缓冲区对象:CreateSoundBuff方法
(5)填充并播放一个静态缓冲区对象
准备缓冲区和数据——锁定缓冲区(LOCK方法)——向缓冲区中写入数据——解除缓冲区锁定(Unlock方法)——播放缓冲区对象(设置播放位置(SetCurrentPosition)——Play方法)——处理缓冲区丢失情况(检测Play方法的返回值是否为DSERR_BUFFERLOST——调用Restore方法)
(7) 复制静态缓冲区对象
DuplicateSoundBuffer方法:使用该方法生成一个LPDIRECTSOUNDBUFFER指针数组,循环调用它们响应游戏的各种事件,每个对象管理自己的播放和写入位置,并能独立地开始和停止播放,不要视图锁定和写入数据到一个复制的复制的缓冲区对象中
(8) 向缓冲区中动态写入数据
设置一个动态缓冲区对象与设置一个静态缓冲区对象十分类似,只有两点不同:
首先是描述缓冲区对象的标识不同,另一个缓冲区对象描述的不同点是没有把缓冲区的大小设为声音文件的数据区大小,而是由SetupStreamBuffer函数设置dwBufferBytes参数为声音数据格式中的每秒字节数的两倍
1. 查询与通告(使数据的传送与当前播放位置同步的方法)
查询:每一消息循环中,定时检查当前播放位置(容易实现但浪费CPU时间)
通告:当播放位置到达感兴趣的点后,DirectSound就发出一个事件信号
2. 调节声音参数:DirectSoundBuffer对象允许控制从缓冲区对象的三个属性:频率、容量和均衡(立体声对象)
(9) 处理DMA:(大多数声卡使用DMA通道将数据送至输出设备)
三维情景中的DirectSound
11. DirectSound在Direct3D中起着重要的作用,它将声音从立体声扩充到了3D声音,由于DirectSound放置声源的空间坐标系就是Direct3D所用的坐标系,所以这两个组件的接口很简单
12. 两种新对象:
DirectSound3DBuffer:控制单个声源的3D属性,即从缓冲区声音对象
DirectSound3DListener:用于放置虚拟的听者,管理3D声音场景的整体属性
13. 声源是如何放置的(表现声源的位置和运动)
(1)随声源距听者的距离边远而逐渐衰减音量
(2)通过衰减一边声道的音量或改变均衡器的值来表现声源的左右方向性
(3)按照听者的耳朵位置,对不在正对听者上的声音加强其衰减,考虑听者头部的声音遮掩效果
(4)通过短暂延迟一个声道的声音来反映声波从头部一边传播到另一边的距离差异
(5)通过增大或减小运动声源的频率来产生多普勒效果
14. 3D空间中的声源
(1) 3D坐标(左手系,X右,Y上,Z远离观察者方向)
(2)位置(相对位置和绝对位置)
(3)方向:声源可能会向某一特定方向发射声音(音锥)
(4)音锥的音量(方向、音锥内角度、音锥外角度、音锥内部音量和音锥外部音量)
(5) Rolloff:音量随着离声源距离的变远按照Rolloff因子逐渐减小
(6)速度与多普勒频移
(7)距离因子
15. 使用3D声音缓冲区对象
(1)步骤:
1. 使用DSBCAPS_CTRL3D属性生成一个从缓冲区声音对象
2. 使用缓冲区对象的QueryInterface方法获取IDirectSound3D接口
这样,一个缓冲区声音对象就有两套方法:一套是标准的IDirectSoundBuffer方法,用于控制从缓冲区对象的通用属性,另一套是IDirectSound3DBuffer方法,用于管理3D效果,每套方法都有自己的接口指针,应用程序为每个3D声音管理两个指针
(2) 生成3D声音缓冲区对象
生成一个具有3D能力的从缓冲区对象只用设置DSBUFFERDESC结构中的DSBCAPS_CTRL3D标志即可
(3) 获取IDirectSound3DBuffer接口
(4) 设置3D缓冲区对象属性
IDirectSound3DBuffer接口的所有方法都将DS3D_DEFERRED或DS3D_IMMEDIATE作为它们最后一个参数,延迟改变模式只有当调用DirectSound3DListener对象的的CommitDeferredSettings方法后才能生效,立即改变模式总是立即生效,为了节约DirectSound进行不必要的计算和混音时间,调用所有方法时都应设置DS3D_DEFERRED标志,只在动画循环体内调用CommitDeferredSettings一次,改变属性
(5) 谨慎使用3D声音(它们很耗费计算时间,在一些情况下,简单的立体声就与3D声音有相同的效果)
(6) 使用Listener对象
获取Listener接口与获取IDirectSound3DBuffer接口的方法一样:由缓冲区对象查询生成,不同的是每个从缓冲区对象都有一个自己的IDirectSound3DBuffer接口指针,而一个应用程序只能有一个听者,另外,应由一个主缓冲区声音对象查询生成IDirectSound3DListener接口,该主缓冲区声音对象还必须设置DSBCAPS_CTRL3D属性
1. 获得Listener接口QueryInterface
2. 设置Listener属性(可以立即执行或CommitDeferredSettings方法后执行)
声音捕获和通告
16. DirectSoundCapture组件:一组用于波形录音的标准的API的一个COM封装。DirectSoundCapture也使用虚拟设备(VxD)驱动程序,它并不提供比Windows API函数更优越的性能,而仅仅是为了与DirectX的其余组件保持一致,然而,使用新的Win32驱动模型(WDM)的驱动程序,它可以使用硬件加速功能
17. 全双工声音操作
(1)制作全双工声音步骤:
1. 生成DirectSound对象,设置协作优先级
2. 枚举音频捕获设备(可选)
3. 生成一个DirectSoundCapture对象
4. 生成一个适合于主缓冲区对象的捕获缓冲区对象,设置通告位置
5. 生成一个从缓冲区声音对象用于输出
6. 开始缓冲区捕获
7. 收到捕获数据准备好的通知后,将数据从捕获缓冲区复制到输出数据流中
8. 空闲时,将数据从输入流中复制到从缓冲区中
(2)设置DirectSound(DirectSoundCapture是独立存在的,不需要DirectSound对象,但是声音回放是需要DirectSound对象的,只有生成DirectSound对象后才能使用它)
(3)设置DirectSoundCapture
传递NULL参数给DirectSoundCaptu reCreate函数,表明DirectSoundCapture将使用用户在控制面板多媒体组件中设置的录音设备,在特殊情况下,可能需要枚举设备,给用户一个选择的机会(DirectSoundCaptureEnumerate函数)
(4)生成捕获缓冲区对象
生成捕获缓冲区对象和生成从缓冲区声音对象的方法几乎一样。设置一个WAVEFORMATEX结构,为它复制一个指针,然后在DSCBUFFERDESC结构中设置一些捕获缓冲区信息,
(5)生成从缓冲区对象
(6)捕获缓冲区的运转(与从缓冲区一样,从概念上讲,捕获缓冲区也是环形的)
开始工作:IDirectSoundCaptureBuffer::Start方法
终止捕获声音:IDirectSoundCaptureBuffer::Stop方法
锁定/解锁:Lock方法/UnLock方法
(7) 通告位置
IDirectSoundNotify接口:该接口只有一种方法—SetNotificationPositions此方法设置了一个缓冲区位置数组,每一个位置将发出一个事件信号,这些通告事件提供了一种摆脱在低层次上的轮询当前读书位置或捕获位置工作的方法,它比重复调用GetCurrentPosition方法有效
18. 生成WAV文件
(1)步骤:
1. 查询捕获设备支持什么格式
2. 生成一个支持格式的捕获缓冲区对象,设置通告位置
3. 调用WaveCreateFile函数,生成文件,写入文件头
4. 调用WaveStartDataWrite函数,生成数据块
5. 运行捕获缓冲区对象
6. 当数据准备好这一通告事件到达时,锁定缓冲区,将数据指针和字节数传递给函数WaveWriteFile,把数据写入数据块中
7. 当缓冲区停止时,调用WaveCloseWriteFile函数,此函数返回到文件头写入数据块长度和采样点数目(可选),然后关闭文件
19. 可以使用IDirectSoundNotify接口为从缓冲区和捕获缓冲区设置通告位置,以及为每个通告位置赋予一个事件,当前播放位置或捕获位置到达通告位置时,对应的事件被激活,在主消息循环中处理通告事件,可以锁定缓冲区,在通告位置之后读出或写入数据