引言
随着计算机网络的日益普及,人们通过网络进行交流显得越来越重要,于是出现了一系列语音通信的软件,比如NetMeeting、IPPhone、MediaRing以及VoxPhone等等,但这些软件都功能完善、相对独立,不利于集成到自己开发的软件中,有时我们也希望将这种语音通信功能集成到自己的软件中,尤其当一个单位的局域网用户分散在不同的房间时。本文给出一种灵活、简单的实现方法,采用基于对话框的方式编程,硬件上只需要一块双DMA通道的声卡(目前的声卡大多支持双DMA通道)和一支耳麦,其余全部由软件编程实现。程序在 Windows98/2000、Visual C++6.0 下编译通过,在Windows NT 100M 以太网上运行良好。
设计思路
要实现点对点语音通信,原理非常简单,只要针对一个点实现话音的实时采集、处理、播放,同时能进行可靠的传送和接收,这样两点一连便可通话。对于前者,采用Windows MDK的低层音频服务比较合适,因为低层音频服务中的回调机制为我们提供了很大的方便。当应用程序不断向设备驱动程序提供音频数据时,设备驱动程序控制音频设备在后台完成录音和放音的具体操作,通过回调机制,我们又可以检测到什么时候用完一个数据块,并及时传送下一个数据块,从而保证了声音的连续,有了这种单机上的实时采集、回放功能后,接下来的工作就是在网络上传送话音数据。在点对点网络传输方面,选择面向连接的TCP协议,TCP传输协议自动处理分组丢失和交付失序问题,这样我们不用为这些问题操心,只需很好地利用这个连接,在采集话音回放之前一方面将自己的话音传给网络,另一方面接收网络传来的话音,这样便实现了点对点语音通信。其结构框图如下:
具体实现
一、话音的实时采集、处理、回放
首先要介绍一下Windows低层波形音频数据块结构 WAVEHDR,其声明如下:
type struct{
LPSTR lpData; //指向锁定的数据缓冲区的指针
DWORD dwBufferLength; //数据缓冲区的大小
DWORD dwByteRecorded; //录音时指明缓冲区中的数据量
DWORD dwUser; //用户数据
DWORD dwFlag; //提供缓冲区信息的标志
DWORD dwLoops; //循环播放的次数
struct wavehdr_tag * lpNext; //保留
DWORD reserved; //保留
} WAVEHDR;
声音的采集和播放都是在操作这个音频数据块结构,实际上主要用到的就是第一个成员变量lpData, 所以我们只要在分配缓冲区(内存)的同时相应分配WAVEHDR数据块结构,然后将缓冲区的指针赋给对应的数据块结构的成员变量 lpData,这样当一个缓冲区填满后,也就是一个音频数据块填满了,通过消息机制就可以在消息函数中进行处理和播放,播放完后又可通过消息函数把缓冲区再送给音频设备输入驱动程序,继续进行采集并播放,当你一次性分配多个缓冲区和数据块结构并赋给音频设备输入驱动程序后,至于把哪个缓冲区填满,然后再把哪个空缓冲区赋给设备输入驱动程序,不需人为干预,完全由Windows控制,这就是一种用动态循环缓冲区实现话音的实时采集、播放的简单而巧妙的办法。实现步骤: