注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

面包会有的

php asp 高端网站开发 微信网站开发 视频会议软硬件

 
 
 

日志

 
 

因特网上语音实时传输计划的处理 (重要处理帧间延时罅隙带来的震颤和杂音问题).  

2011-11-13 01:17:11|  分类: 声音播放 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

最近曾经利用ADO和其它COM技巧(诸如Excel、Word之类的)给客户做了一款财务报表实时递交/汇总软件。全副软件是基于C/S(TCP/IP,流式套接字)架构的。本身客户的需求都曾经中意了,即服务器端能动态管教多个客户端链表,并能与客户端举行交互,而客户端也能够在垄断人员填完表格(利用GridCtrl与Excel举行交互,GridCtrl是Chris的杰作)后积极向服务器提交财务数据。

最最近,客户又说要添置语音通信功能。过去,没事的时候“玩过”一两次声卡API不即便一组。本感受waveXXX函数的调用吗,有什么难的,说白了即便良好行音频捉拿,然后将音频数据打包,在穿越一个(自定义的)专用Socket发送出去,交给客户端,客户端举行拆包然后,在包装成款式化的一帧音频输出缓冲。最后,waveOutWrute以下,就能够了。

废话少说,修建一个测验工程,将上述思路很快变成代码后。我就迫不及待的做了实验。我的妈呀,不是不懂得,一试吓一跳!TMD客户端接收到的音频流放出来后比“倩女幽魂”里的黑山老妖的声音都尖厉,真得吓死人。尔后到网上一查,说是许多人都碰上了这种情形,即穿越网络传输后音频数据流在改换成模仿音频信号时会发生:“咯哒~~~吱吱”的杂音和语音的震颤。许多人都提出了对接收到的音频流举行挪动窗滤波。鄙人虽麻木,但还好歹是做过四层板的,向CREATIVE LABS这么的牛叉公司做的声卡举行音频捉拿后的音频数据流还用你来举行什么“滤波”吗? 简直是好笑,人家板子上早做好了硬件滤波,无论是模仿侧滤波的还是数字侧的滤波。这种思路我当即就给抵赖了。当然为了&ldquowww.gexinghua.org;严密的治学-(*^__^*) 嘻嘻……”,我定然要用实验来验证,这种说法hui.huikao.org的悖谬之处。

很容易,我率先在音频捉拿时,开8重缓冲区,这么系统在每当一帧音频数据装满时,就会进去OnMM_WIM_DATA回调函数。在其中,我率先将目前帧迅速拷贝到,另一块Buffer中。尔后,即刻就让目前帧所在的音频捉拿缓冲又加到了音频捉拿缓冲队列中去。然后,又将那块buffer中的数据写到音频输出缓冲区,由扬声器举行功放输出。由于批准了“8重音频输入缓冲”,故而在本地音频实时重放(语音追随)时,能够做到“人耳感受不出延时、且毫无颤音、杂音”。

然后我又谢了一个客户端过程,用来接收服务器发送的音频捉拿数据流。然后在客户端Machine上举行语音播送。呵呵,你猜怎么着?又开始有了“严重的咯哒~~~吱吱声和声音的震颤”。

目前,让我们归纳一下。在本地播送时声音功德良好的音频数据,在客户端Machine上播送时就揭示了杂音、颤音。你感受这可能是滤波问题吗?显明不是,否则的克莱氏谈话。为什么本地播送时声音功德良好。穿越这个实验,其实也不难觉察问题出在哪。你想音频数据流在阅历过打包,网络传输,拆包后能力举行播送。这个过程总会有一些延时,万一在这种情形下(许多人为了容易顺其慷慨的就这么干,其实是大错特错),你却每有一帧数据到来你就播送一帧音频数据,未曾颤音和杂音才怪呢!你想想,这相当于人为地垄断续、滑腻的音频数据的帧与帧之间插入了死区工夫。从Fourier分析的见解来看,这相当于引入了不渴望的谐波,并且构成了基带的频谱频谱混叠。从直观的角度来看,即便,你在帧与帧之间插入了安宁的无须于播送的工夫(并且曾经与采集或播送一帧音频数据的工夫能够比拟),如此一来,就相当于你以很高的频率,说以下话,然后即刻停住,再说一下话,然后又即刻停住。。。如此往复。呵呵,能够遐想,这不正是颤音吗。另外从宏观上来讲,你这引入的超大大死区工夫,定然引入了,以基带音频功率能够比拟的谐波功率。这也就解释了为什么会有相当嘈杂的杂声。

既然觉察了问题,我们即将处理它!用什么措施呢,大约无须多想,其实我在前面曾经指出打听决计划。你想想,我在本地播送时,就有良好的音质那是因为我为音频捉拿开了8重缓冲区,每重缓冲为1024个字节。那么,在客户端我们仍能够用同样的思路。单一的不同点在于,在“本地播送试探”时的8重缓冲区是由系统调动的。而在客户端对我们从服务器接收到的音频数据流的缓冲,必需由我们来安排缓冲区的调动代码。其实,这可能是一个难点,尤其是对于那些,未曾接触过数据构造的人而言。鄙人学过这门课,因而很快就能想到用循环队列来告终音频数据流的缓冲。

翔实思路如下:有于网络传输来的音频数据流可能较慢,且帧与帧之间有延时。因而我们能够,并不是将这些帧间有迟到的数据直接音频输出,而是先让它们入队,然后。另开一个“放音”线程,在按下“语音通信键”后,便开启了“放音”线程,在放音线程中,凡是音频的循环队列缓冲区不为空,就顺次调用waveOutWrite举行逐帧的音频输出。看,这么,我们就在线函数程中将帧间延时肃清了,又还原了本来音频数据在基带内的功率,肃清了失真。在接收数据线程内,我们在循环队列“非满”时,就让数据入队。事实上由于接收的速度小于音频输出的速度,因而,实践验证未曾“丢包”发生。呵呵,全副问题就这么处理了。最后顺心的收获是:客户端缓冲区开30块,每块1024字节,就能够做到音频输出的全面滑腻,并且毫无杂音。语音在因特网上的一种实时传输计划就此提出,然而好像还短点什么?对了,那即便音频流的收缩,接下来就处理这个问题!private Dimension d = new Dimension (0, 0);   public Example (){ } 

  评论这张
 
阅读(1049)| 评论(1)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017