文明
(第七一五研究所,杭州,310023)
基于双缓冲技术的音频数据实时采集与播放
文明
(第七一五研究所,杭州,310023)
为提高声呐模拟演示系统的真实性,并能迅速对目标类型进行初步判断,设计一种实时采集、播放收听声呐数据的实现方法,采用双缓冲技术来避免信号的不连续和延迟,完整的恢复了目标的声音特性,缩短操作员判别目标的时间。
实时采集;播放;声音信号;双缓冲
在声呐模拟显控设计中,设计者往往只关心目标的图形和字符信息,因此,操作员要根据目标的多种信息(如警戒、目标特征谱线等)来判断目标的类型,这就要求操作员对目标进行更多的操作和设置来获得这些信息,这会在某种程度上延误了战机。经验丰富的操作员往往对某些特定目标(如鱼雷)的声音异常敏感。针对以往在设计中只是关心图形和文字信息而无声音信号输出的遗漏,本文提出一种实时采集目标的声音信号并利用双缓冲技术进行播放出来的方法。
双缓冲是图形图像处理编程过程的一种基本技术。窗体在响应WM_PAINT消息时要进行复杂的图形处理,重绘时会因为频繁的刷新而引起闪烁,因此采用了双缓冲技术来避免这种情况的发生。双缓冲技术即在内存中创建一个与屏幕绘图区域一致的对象,先把图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上[1]。在音频数据处理时,如果直接采集数据然后播放出来会明显感觉到声音的卡顿,因此想到能否把双缓冲绘图的方法延伸到双缓冲播放上来。在数据采集时,先把数据在内存中分别用两个数据驱动中保存下来,在播放时采用拨动开关的模式选择播放相应数据驱动上的数据。实践证明,这种想法不但能大大加快数据的处理,并且避免播放声音时会出现卡顿的现象。
要实现对声呐数据的实时采集、处理、播放,我们采用Windows MDK的低层音频服务比较合适,因为低层音频服务中的回调机制为我们提供了很大的方便。当应用程序不断向设备驱动程序提供音频数据时,设备驱动程序控制音频设备在后台完成放音的具体操作,通过回调机制,又可以检测到什么时候用完一个数据块,并及时传送下一个数据块,从而保证了声音的连续。在网络接收声呐数据方面,选择不需连接的UDP协议。在声呐输出的结果中,不仅仅只输出声呐收听数据,如果采用面向连接的TCP协议就可能产生数据堵塞而导致声呐数据播放的时候出现卡顿或者延迟。实时采集和播放声呐收听数据的设计框图如图1。
图1 声呐实时数据处理设计框图
首先要介绍一下Windows低层波形音频数据块结构 WAVEHDR,其声明如下:
声音的采集和播放都是在操作这个音频数据块结构,实际上主要用到的就是第一个成员变量lpData,所以只要在分配缓冲区(内存)的同时相应分配WAVEHDR数据块结构,然后将缓冲区的指针赋给对应的数据块结构的成员变量 lpData。这样当一个缓冲区填满后,即一个音频数据块填满了,通过消息机制可以在消息函数中进行处理和播放,播放完后又可通过消息函数把缓冲区再送给音频设备输入驱动程序,继续进行采集并播放。一次性分配多个缓冲区和数据块结构并赋给音频设备输入驱动程序,这个过程完全由Windows控制(选择缓冲区填满,然后再把哪个空缓冲区赋给设备输入驱动程序),不需人为干预。这是一种用动态循环缓冲区实现话音的实时采集、播放的简单而巧妙的办法。具体实现设计框图如图2。
图2 双缓冲数据播放设计框图
在实现的过程中,通过下面三个消息映射来完成数据接收和播放。
ON_MESSAGE(MM_WOM_OPEN,OnWomOpen)
ON_MESSAGE(MM_WOM_DONE,OnWomDone)
ON_MESSAGE(MM_WOM_CLOSE,OnWomClose)[3]
在waveOutOpen中要指定一个窗口来处理接收波形输出,用消息机制向消息队列发送了MM_WOM_OPEN消息。处理MM_WOM_OPEN消息时,把两个WAVEHDR结构传送给waveOutWrite,此函数将数据传送到波形输出硬件,才真正开始播放声音,当波形硬件播放完waveOutWrite函数传送来的数据后,就向窗口发送MM_WOM_DONE消息。SINEWAVE在处理此消息时,将计算缓冲区的新数据,并调用waveOutWrite来重新提交缓冲区。
从技术设计上来说,这种双缓冲数据播放技术优点有两个。首先,我们不需要关心声卡底层的处理,只需要实时将数据块填满等待调度即可。其次,播放声音连续且不失真。
为了验证这种方法的可行性,我们将这项技术用在和某院校合作的《基于信号级的声呐仿真系统》上来。很明显,模拟演示系统增加了目标收听这个功能后,不但提高了演示系统的真实性,更重要的是,在集中演练的时候,操作员只需根据目标的声音并结合基本的图形输出即可对目标迅速做出反应。如今的联合作战演练中,各作战模块的功能愈来愈多,在错综复杂的功能中迅速做出选择尤为重要。作为一种很直接的表现形式,演示系统中的收听功能必不可少。
[1] 双缓冲技术绘图[EB/OL]. (2014-04-09). m.blog.csdn.net/ article/details? id=23269643.
[2] 林文焕. 基于WaveX低级音频函数的实时语音通信[Z/OL]. (2007-04-03) http://www.wavecn.com/content.php? id=95.
[3] 记忆碎片. VC中实现语音数据的采集[Z/OL]. (2011-11-04). http://yaycici.log.163.com/blog/static/173759063201110 44 4857597/.