当前位置:
文档之家› 基于多缓冲区实时音频采集和传输实现
基于多缓冲区实时音频采集和传输实现
{WAVEHDR* m_WaveHeader; m_WaveHeader. WFormatTag=WAVE_FORMAT_PCM; //设置 wav 格式 m_WaveHeader. nChannels=2;//设置声道个数为 2,双工方式工作 m_WaveHeader. nSamplesPerSec=22050L; //设置采样频率为 22.05kHz m_WaveHeader. nAvgBytesPerSec=22050L; //设置每秒所需字节数 m_WaveHeader. nBlockAlign=1;//设置每个采样点所需总字节数 m_WaveHeader. wBitsPerSample=8; //设置每个采样点所需 Bit 数 }
—272—
(2)低层音频服务 低级音频服务控制不同的音频设备,包括WAVE、MIDI 和辅助音频设备。低级音频服务包括如下内容:1)查询音频 设备;2)打开和关闭设备驱动程序;3)分配和准备音频数据 块;4)管理音频数据块;5)应用 MMTIME 结构;6)处理错误。
(3)音频采集的数据结构 音频的采集存储的数据结构有 3 种:分别是 PCM 波形音 频格式 PCMWAVEFORMAT、波形数据格式 WAVEFORMAT 和波形数据缓冲区格式 WAVEHDR。因为我们采取流媒体方 式来对音频进行处理,所以使用的数据结构是 WAVEHDR。 这种数据结构的音频采集方法可以在极大程度上降低声音延 迟(后面会分析音频的实时传输)。具体的采集方法是通过程 序实现:
if(m_nCurrent>2) m_nCurrent=1; result=waveOutUnprepareHeader(m_WaveOut,m_WaveHeader,siz eof(WAVEHDR) ); if (result!= MMSYSERR_NOERROR) //准备音频头错误,则不再处理;
录音函数;远端的计算机接收到声音信息之后,将此数据填
写到相应的数据结构里,调用回放函数播放。因为视频会议
中的音频传输不同于可视电话。后者使用的线路交换的连接
方式,传输延迟比较小,但是需独占线路资源,网络资源利
用效率太低。而视频会议系统,不仅传送音频数据,还有大
量的视频、数据和一些控制信息,因此不能采用这种方式。
将音频参数设置为 22.05kHz 的采样频率,8 位立体声方 式。采用这种设置的优点是,若使用 44.1kHz 的采样频率, 得到的数据量大;若使用 11.025kHz 的采样频率,采集到的 声音的效果不是很好,因此我们使用上述的音频参数设置。
作者简介:张 兵(1977—),男,硕士、讲师,主研方向:网络数据 库,软件技术 收稿日期:2005-09-19 E-mail:zhangbing@
1 音频采集实现
(1)音频采集、回放模式分析 音频的采集,就是从声卡上获取数据。Windows 通过高 级音频函数、媒体控制接口 (Media Control Interface, MCI) 设备驱动程序、低级音频函数、MIDI Mapper 以及低级音频 设备驱动提供音频服务。 从声卡获取音频流有 3 种方法:1)采用 DirectX 的方法; 2)使用 WaveOut 方法;3)使用媒体控制接口,但是使用 MCI 进行开发时,对于媒体的操作只能在文件级别上,即需对音 频文件进行操作,如音频所对应的 WAV 文件、MIDI 所对应 的 MID 等。上面的几种方法都存在一个问题,就是音频采集 不太适合于音频流的传输需要,从而影响音频的效果,因此 考虑使用低级音频服务功能,与音频设备驱动程序直接通信 的方式。低级音频函数在多媒体计算机中同样为音频硬件提 供了与设备无关的接口。使用低级音频函数时,可以直接控 制声音实时的采集与回放,即不需要把声音形成相应的文件 方式,而是把采集到的声音放到内存中,形成一种类似流的 存储单元。对此内存中的音频数据进行编辑、传输等(在视频 会议系统中,没有实现声音的存储)。视频会议中音频的传送 发送和回放就是基于这种考虑,将内存中的音频数据通过多 播形式发送到各个加入视频会议的终端,终端
(Chengdu NEUSOFT Institute of Information Technology, Chengdu 611844)
【Abstract】Through the introduction of videoconference system designed by software method, the paper applies how to use the sound card as a simple audio device to implement audio real-time collection, play-back, and points out the designing methods and key points in audio implementation, transmission and noise cancellation using multi-buffer technology. 【Key words】Videoconference; Media control interface(MCI); Audio; Multi-buffer; Real-time transmission; Noise cancellation
2.1 定义数据接口以及建立套接字
SOCKET m_sRecv;
//接收套接字
SOCKADDR_IN addrRecv; //接收地址
SOCKET m_sSend;
//发送套接字
SOCKADDR_IN addrSend; //发送地址
WSADATA wsaData;
//缓冲区数据
m_sSend=socket(AF_INET,SOCK_DGRAM,0);
录音缓冲区:lpRecordBuffer[0]、lpRecordBuffer[1]; 播放缓冲区:lpPlayBuffer[0]、lpPlayBuffer[1]。
这里具体介绍一下录音的过程,播放的过程跟录音的实
现方式是基本一样的。通过缓冲区表示 m_currentbuffer 来区 分录制缓冲区是否已满,如果满,则调用发送函数。
打开音频设备进行声音的采集是比较简单的事情,具体可以
参考 MSDN 的帮助文档。
2 音频实时传输的实现和研究
采集到的声音存放在内存数据结构中,当定义的数据缓
冲区满时,通过网络接口函数发将声音数据发送到远端计算
机,处理中将声音数据按照既定的传输和压缩协议,发向指
定的远端计算机,同时释放声音数据缓冲区,然后再次调用
AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
return ; } result = waveOutWrite( m_WaveOut, m_WaveHeader, sizeof (WAVEHDR)); if (result!= MMSYSERR_NOERROR) {
作为多媒体技术和网络技术的集合,视频会议越来越成 为一个研究热点,本文在已进行的课题上,对音频的采集和 传输进行了探讨和研究。视频会议中的音频通信,它不但要 求具有良好的实时性,同时还要求网络具有较高的带宽。虽 然可以租用较高带宽的网络,比如现在的宽带网络或者 DDN,但是这样会增加视频会议的开发成本;同时可以在程 序中使用较好的音频压缩算法来实现一定的数据压缩,也不 影响声音的传输和还原效果。
AfxMessageBox(_T("Sound Output Cannot Write Buffer !")); return ; }}
2.3 音频的实时发送
m_RemoteIP=inet_addr(ip); m_RemoteAddr.sin_addr.S_un.S_addr=m_RemoteIP; m_RemoteAddr.sin_family=AF_INET; m_RemoteAddr.sin_port=htons(SENDPORT); sndIn.SetTestProp(FALSE); sndIn.SetSocketParam(m_sSend,m_RemoteAddr); sndIn.OpenMic(); sndOut.OpenSpk(); sndOut.WriteData((char *)chSndOut,BLOCK);
m_sRecv=socket(AF_INET,SOCK_DGRAM,0);
addrSend.sin_family=AF_INET;
addrSend.sin_addr.S_un.S_addr=INADDR_ANY;
addrSend.sin_port=htons(SENDPORT);
addrRecv.sin_family=AF_INET;
总的声音延迟为
Tdelay=T1a+T2a+T3a+T4a+T5+T1b+T2b+T3b+T4b
其中 T1a 为声卡转换声音的时间,这个由声卡的质量决 定,以及音频的采样算法决定;T2a 为将采集的音频数据写入 缓冲区形成音频流的时间;T3a 为通过 Winsock 编程,调用发 送缓冲区数据的占用时间;T4a 为通过网卡发送数据包的时 间;T5a 为数据包在网络上的传输延迟。从上面的包交换图可 以看出,目前的最大延迟是在 T5a,这主要与网络结点数、网 络介质情况相关。针对以上为问题,为了实时的传输音频数 据,就必须考虑使用双缓冲区。多套接字技术,来分别处理 音频数据的传送和接收,在不同的缓冲区间进行处理。在这 里通过使用 WinSock 套接字的 UDP 数据报协议来进行数据 的传送和接收。
{ return; } //设置音频格式,添加音频信息 int n=(int)m_nBits/8; (*m_WaveHeader).lpData = (LPSTR)(m_pOutputBuffer); (*m_WaveHeader).dwBufferLength = m_nBlock*n*m_nBlock Num; (*m_WaveHeader).dwFlags = 0; result=waveOutPrepareHeader(m_WaveOut,m_WaveHeader, izeof(WAVEHDR) ); if((result!=MMSYSERR_NOERROR)||((*m_WaveHeader).dwFl ags!= HDR_PREPARED)) {