基于DirectSound的混音与放音实现_第1页
基于DirectSound的混音与放音实现_第2页
基于DirectSound的混音与放音实现_第3页
基于DirectSound的混音与放音实现_第4页
基于DirectSound的混音与放音实现_第5页
已阅读5页,还剩8页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、基于DirectSound的混音与放音实现黎剑兵李永强徐敏 (西安电子科技大学机电工程学院,陕西西安710071摘要文中主要介绍了基于DirectSound的混音与放音的原理与实现的具体步骤,并对实现方法及用到的各A P I函数进行了具体的分析。关键词D i r e c t S o u n d,混音,放音,编程。中图分类号T N912.341引言在进行多媒体软件的设计中,经常会进行混音和放音的程序设计。随着软件对音乐、音效要求的不断提高,对于混音和放音的设计要求也不断提高。作为DirectX的一个组件,DirectSound在混音和回放方面的效率是不可质疑的。MicrosoftDirectSo

2、und应用程序接口是DirectXSDK中的声音组件,是一种比较低级的声音API函数集,主要用于多媒体设计。DirectSound的主要功能有:提供短时间、高效率的声音混合,提供硬件加速,能够直接对声音设备进行操作。此外,新版本的DirectSound可以实现音频捕捉操作,并可以使用设置声卡及其辅助设备所能提供的扩展功能。它还可以实现段时间间隔播放混合声音和三维声音编程。2混音原理利用DirectSound来实现混音与放音,首先从“从声音缓冲区(SecondarySoundBuffer”对象说起。一个从声音缓冲区对象代表一个声源,这个声源既可以是静态的声音对象(StaticSound,也可以是

3、动态的声音对象(StreamingSound。静态的声音对象是指声音数据一次性读入内存,它一般适用于较短的声音。动态声音对象是指声音数据必须隔一段时间传送一部分到缓冲区。所有缓冲区都含有脉冲编码调制(P C M格式的声音样本数据。播放从声音缓冲区对象时,D i r e c t S o u n d从每个缓冲区中取出数据,然后在主缓冲区(PrimaryBuffer中进行混音。混音时,它会执行所有必要的格式转换(例如,将采样率从44kHz转换到22kHz。同时,它会处理所有的特殊效果,例如3D空间中的声源定位等。在主缓冲区中混音后,声音即送往输出设备。当硬件缓冲区和硬件混音设备空闲时,DirectS

4、ound自动将尽可能多的声音对象送入硬件内存中。留在主机系统内存中的声音对象由DirectSound进行软件混音,并以流的方式与硬件缓冲区中的声音对象一起送入硬件混音器。这个过程如图1所示。图1D i r e c t S o u d混音工作过程3实现下面我们说明使用DirectSound进行放音和混电子科技2004年第3期(总第174期56基于DirectSound 的混音与放音实现电子科技/2004年3月15日音的一般步骤:3.1创建D i r e c t S o u n d 对象并设置协作模式DirectSound 对象是所有DirectSound 应用程序的核心。只有通过它才能创建真正与

5、声音操作有关的其他对象。因此在开始进行DirectSound 编程时,首先必须调用DirectSoundCreate 函数创建一个D i r e c t S o u n d 对象,该函数的原型为:H R E S U L T W I N A P I D i r e c t S o u n d C r e a t e (L P G U I D l p G u i d ,L P D I R E C T S O U N D *p p D S ,I U n k n o w n F A R *p U n k O u t e r ;lpGuid 用来指定可用DirectSound 设备GUID 实例指针,通

6、常取NULL ,ppDS 为所创建的DirectSound 对象指针。参数ppDS 为所创建的DirectS o u n d 对象指针。参数p U n k O u t e r 必须取NULL。创建DirectSound 对象后,必须立即调用SetCooperativeLevel 方法设置声音的优先级。该函数的原型如下:H R E S U L T S e t C o o p e r a t i v e L e v e l (H W N D h w n d ,/应用程序窗口句柄D W O R D d w L e v e l /协作优先级;参数hWnd 为应用程序的窗口句柄。如果同时使用Direct

7、Draw ,必须把同样的窗口句柄传递给IDirectDraw 对象的SetCooperativeLevel 函数,否则DirectDraw 的SetCooperativeLevel 调用方法将失败,返回DDERR_HWNDALREADYSET 的错误代码。一般情况下,如果应用程序中所有窗口都派生于同一主窗口,就该把最顶层的窗口句柄传递给DirectSound 和DirectDraw 的SetCooperative-Level 方法。参数dwFlags 用来设置声音设备的优先级,它可取以下4个值之一:DSSCL_NORMAL :与其他应用程序的最佳协作工作方式,该优先级不允许改变主缓冲区声音格式

8、,只能使用D i r e c t S o u n d 缺省输出格式。DSSCL_PRIORITY :允许改变主缓冲区声音格式。DSSCL_EXCLUSIVE :独占声音设备使所有后台应用程序都不发声。DSSCL_WRITEPRIMARY :允许直接存取需要的DirectSound 驱动程序,声音设备不能播放从缓冲区声音对象,其他应用程序将丢失它们的声音对象。大多数应用程序使用DSSCL_NORMALL 或DSSCL_PRIORITY 级别即可满足要求。只有特别要求的应用程序才需要DSSCL WRITEPRIMARY 级别,用以实现用户的混音操作。3.2创建缓冲区设置缓冲区对象首先需要获得描述声

9、音格式的WAVEFOEMATEX 结构。在大多数情况下,可以简单地从波形文件本身获得该信息,例如调用Wave-OpenFile 函数获取该结构。获取WAVEFOEMATEX 后,便可以根据它创建一个描述缓冲区对象的结构D S B U F F E R D E S C ,该结构的定义如下:t y p e d e f s t r u c t D W O R D d w S i z e ;D W O R D d w F l a g s ;D W O R D d w B u f f e r B y t e s ;D W O R D d w R e s e r v e d ;L P W A VEF O R

10、 M A T E X l p w f x F o r m a t ;D S B U F F E R D E S C ,*L P D S B U F F E R D E S C ;typedefconstDSBUFFERDESC*L P C D S B U F F E R D E S C ;成员dwSize 为本结构大小,通常初始化为sizeof(DSBUFFERDESC。dwFlags 缓冲区对象描述标志,它的取值可参阅联机帮助。dwBufferBytes 用来指定缓冲区的大小,缓冲区有静态和动态之分,其中静态缓冲区适用于单一、短小、经常重复的声音,动态缓冲区则适用于由于声音尺寸限制不能完全放

11、入缓冲区中,而是在播故声音的过程中每隔一段时间传递一部分数据到缓冲区中。静态缓冲区尺寸至少应等于将会放到缓冲区中的最长的声音数据基于DirectSound 的混音与放音实现IT Age/Mar. 15, 2004尺寸,动态缓冲区尺寸应大到容纳12s 声音数据的程度。可以通过WAVEFORMATEX 结构中的nAvgBytesPerSec 成员计算出缓冲区所需要的字节数。dwReserved 为保留成员,必须为0。lpwfxFormatDirectSoundBuffer 对象标识一个音频数据缓冲区,通过它可以对音频进行播放、设置属性等操作。使用CreateSoundBuffer 函数可以创建一个

12、D i r e c t S o u n d B u f f e r 对象,其原型为:H R E S U L T C r e a t e S o u n d B u f f e r (L P C D S B U F F E R D E S C l p c D S B u f f e r D e s c ,L P L P D I R E C T S O U N D B U F F E R l p l p D i r e c t S o u n d B u f f e r ,I U n k n o w n F A R *p U n k O u t e r ;lpcDSBufferDes c 为一DS

13、BUFFERDESC 结构指针,它保存了所要创建的音频缓冲区的描述。lplpDirectSoundBuffer 为所创建的DirectSoundB u f f e r ”对象如果系统的音频数据是从网络接收而来,或者音频文件较大而需要多次读取,则属于动态数据,适合使用动态缓冲区来进行播放。使用动态缓冲区进行播放就应该在播放的过程中动态地往缓冲区中传送音频数据。这种动态传送方式引出了一个新的问题,这就是系统应该在什么时候向缓冲区传送数据的问题。为了解决这个问题,可以采用IdrectS o u n d N o t i f y 接口。IDrectSoundNotify 接口只有一种方法:SetNoti

14、ficationPositions 。此方法设置了一个缓冲区位置数组,每一个位置将发出一个事件信号。这些通告事件提供了一种摆脱在低层次上轮询当前读数位置工作的方法。我们利用事件触发向从缓冲区动态地填补音频数据。当缓冲区中数据量少于一定的数量时会发出通知事件。系统可以建立一个线程专门用于接收这种通知事件,在接收到通知事件后线程会将音频数据送入相应的缓冲区,从而解决了动态传送数据的问题。3.3填充并播放一个静态或动态缓冲区对象首先获取音频数据,然后在将准备好的数据送入缓冲区之前通过IdirectSoundBuffer:Lock 锁定缓冲区,以确保它处于稳定状态,锁定的同时获得该缓冲区的地址。L o

15、 c k 函数的原型为:H R E S U L T L o c k (D W O R D d w W r i t e C u r s o r ,D W O R D d w W r i t e B y t e s ,L P V O I D l p l p v A u d i o P t r 1,L P D W O R D l p d w A u d i o B y t e s 1,L P V O I D l p l p v A u d i o P t r 2,L P D W O R D l p d w A u d i o B y t e s 2,D W O R D d w F l a g s ;

16、dwWriteCursor 用于指定锁定的缓冲区开头的偏移量。dwWriteBytes 用于指定锁定的字节数。lplpvAudioPtr1用于返回的锁定区域起始地址。lpdwAudioBytes1返回锁定区域大小,如果锁定区域回绕时返回锁定的第一部分区域大小。lplpvAudioPtr2用于在锁定区域回绕时返回锁定的第二部分区域起始地址。若不回绕,返回NULL 。lpdwAudioBytes2用于在锁定区域回绕时返回锁定的第二部分区域大小,若不回绕,返回NULL 。dwFlags 取DSBLOCK_FROMWRITECURSOR 或DSBLOCK_ENTIREBUFFER 分别表示从当前位置开

17、始锁定和锁定整个缓冲区。基于DirectSound 的混音与放音实现电子科技/2004年3月15日该函数返回两个指针和两个字节数,缓冲区是环形的,但物理上的缓冲区却是线性的,假设缓冲区长100k 字节,想从90k 字节偏移量处写入50k 字节数据,只有10k 字节数据被写入缓冲区的尾部,剩余的数据必须绕回到缓冲区的首部写入。DirectSound 指出了这一点,这是十分有帮助的。Lock 方法返回锁定开始的地址,即第一块锁定区域的大小。同时,也返回了回绕的锁定区域开始地址及回绕锁定区域的大小。如果碰巧知道数据不会回绕就没有必要为DirectSound 提供回绕信息的变量名,可以将参数lplpv

18、AudioPtr2和lpdwAudioB y t e s 2设为N U L L 。下面我们说明播放过程。(1写入数据到缓冲区。从文件读取音频数据到缓冲区的实现非常简单,只要调用一般的文件读取函数设置数据接受缓冲区为前面锁定的缓冲区指针即可。如果被除数处理的音频数据是从网络传来的音频数据包,则可以按照各自的身份标识放到相应的缓冲区内。然后由专门线程(播放声音的线程,循环处理通知事件将缓冲区队列中的数据拷贝到各自对应的SecondB u f f e r 中。(2解除缓冲区锁定。读取数据到缓冲区结束后应该调用IdirectSoundBuffer:Unlock 方法来解除对缓冲区的锁定。该方法的原型为

19、:lpvAudioPtr1用于指定锁定区域的开始地址。dwAudioBytes1用于指定第一块锁定区域字节数。lpvAudioPtr2用于若锁定回绕时指定缓冲区开始地址,若不回绕,设为NULL 。dwAudioBytes2用来指定回绕的锁定区域字节数。它们都是调用Lock 方法后的返回值,若锁定未回绕,则传递NULL 给回绕指针,传递0给回绕字节数参数。(3播放缓冲区对象。首先调用DirectSoundBuffer:SetCurrentP-osition 方法设置当前播放位置为缓冲区开头,然后调用D i r e c t S o u n d B u f f e r :P l a y 方法播放。S

20、etCurrentPosition 方法的原型为:HRESULTSetCurrentPosition(DWORDdwNewPosition。dwNewPosition 用来指定回放开始和继续的缓回区偏移地址,当缓冲区对象生成时或者播放到达缓冲区末尾后,DirectSound 会将播放位置设在缓冲区的开头,只有当出现声音已经在播放或过早地停止播放的情况下,才需要为缓冲区设置播放位置。P l a y 方法的原型为:H R E S U L T P l a y (D W O R D d w R e s e r v e d ,D W O R D d w P r i o r i t y ,D W O R

21、D d w F l a g s ;dwReserved1为保留参数,必须设置为0dwPriority 用于指定声音的级别,这在混音的时候将被用到。dwFlags 用于指定声音播放的方式,它可取0或者DSBLLAY_LOOPING,它们分别表示一般的播放和循环播放。4结束语DirectX 作为一套Windows 程序提供的对系统硬件进行控制的组件,它所包含的许多高层API 使我们对位图和声音的处理工作变得相当简单。这项技术自面世以来就一直被广泛应用于多媒体及游戏等软件的开发中。充分地了解DirectX 可以使我们对编程工作更为得心应手。参考文献1BradleyBargen,PeterDonnelly.DirectX 从入门到精通.北京:北京希望电子出版社,1999.2廖义奎,王志文,韦卫星等.利用Socket 及DirectXSDK 实现视频组播.广西工学院学报2003,14(1:4850.3陈坚,陈伟等.实例解析VisualC+.NET编程.北京:北京希望电子出版社,2002.作者简介黎剑兵(1975,男,西安电子科技大学讲师。研究方向:网络通信及多媒体技术、嵌入式系统。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论