现在来分析静音检测
语音通话,基本上是一方听,一方说,采用静音检测可以起到节省一半带宽的作用
网络上有很多静音检测的代码,基本的思路,都是构造一个自适应的能量探测试,
低于阀值时,就认为出现静音
g723的思路基本与此相同
Comp_Vad 这个函数负责静音栽决,看代码吧,
这里笔者只分析算法,不再纠结定点数运算引起的数值缩放的问题了
g723的静音检测,检测了当前帧的180个样点(后60样点由于没有在当前帧里处理)
首先看到ScfTab这个静态数组
因为门限值的计算涉及到log,采用了类似711里的算法,用一系列折线段来近似指数函数
底为0.89 参考门限值公式10^(-0.05)约等于0.89
static Word16 ScfTab[11] = {//lsc 这里是一系列折线的斜率,用于计算近似的指数函数 注意:因为采用的是归一化的位移作自变量,所以这个表是递增的,把0.89的指数函数的第一象限"反"过来看(这里显得很绕,笔者也纠结了很久)
9170 ,
9170 ,
9170 ,
9170 ,//lsc 0.277 * 32768 = 9093 这个点基本吻合 0.277 为 0.89^11
10289 ,//lsc 0.313995361328125=10,
11544 ,//lsc 0.352294921875=9?
12953 ,//lsc 0.395=8?
14533 ,//lsc 0.4435=0.89^7 ?
16306 ,//lsc 6 0.49761962890625=0.89^6
18296 ,//lsc 5 0.558349609375=0.89^5
20529 ,//lsc 0.626=0.89^4
} ;
这个数组里的值为0.89^(n)扩大32768倍, n取值范围(4~11)
从四个子帧里找出基音周基最小的一个,存入Minp
/* Find Minimum pitch period */ //lsc VadStat.Polp 是从Line.Olp中取来的,每一帧保存两个(因为基音周期是每120采样计算一次)
Minp = PitchMax ;
for ( i = 0 ; i < 4 ; i ++ ) {
if ( Minp > VadStat.Polp[i] )
Minp = VadStat.Polp[i] ;
}
判断当前帧是否处理浊音段,依据为,如果所有子帧的基音周期都约为Minp的整数倍,
即认为当前帧是浊音段,代码片段
//lsc itu的中文翻译有误,当tm2=4时,应认为是浊音,见itu的英文版,是voice
Tm2 = 0 ;
for ( i = 0 ; i < 4 ; i ++ ) {
Tm1 = Minp ;
for ( j = 0 ; j < 8 ; j ++ ) {
Tm0 = sub( Tm1, VadStat.Polp[i] ) ;
Tm0 = abs_s( Tm0 ) ;
if ( Tm0 <= 3 )//lsc 如果在倍数附近,差值不大于3,为浊音加分,都在倍数附近,就是浊音了
Tm2 ++ ;
Tm1 = add( Tm1, Minp ) ;//lsc 用减法和加法,循环8次,代替除法
}
}
尾响处理,如果是浊音,之后的6个帧会被认为非静音,这个处理是避免元音段被不正确地截了
代码片段
/* Update adaptation enable counter if not periodic and not sine */
if ( (Tm2 == 4) || (CodStat.SinDet < 0) )//lsc 浊音,要添加尾响
VadStat.Aen += 2 ;
else
VadStat.Aen -- ;
/* Clip it */
if ( VadStat.Aen > 6 )//lsc 尾响限制为6帧
VadStat.Aen = 6 ;
if ( VadStat.Aen < 0 )
VadStat.Aen = 0 ;
与网络上流行的算法不同的是,g723做了滤波,对静音的判断是基于激励的能量
逆向滤波代码片段如下:
//lsc 逆向滤波
/* Inverse filter the data */
Acc1 = 0L ;
for ( i = SubFrLen ; i < Frame ; i ++ ) {
Acc0 = L_mult( Dpnt[i], 0x2000 ) ;
for ( j = 0 ; j < LpcOrder ; j ++ )
Acc0 = L_msu( Acc0, Dpnt[i-j-1], VadStat.NLpc[j] ) ;
Tm0 = round ( Acc0 ) ;
Acc1 = L_mac( Acc1, Tm0, Tm0 ) ;//lsc 计算出能量
}
其中的VadStat.NLpc这个数组,是在计算舒适背景音时,形成的一个平均滤波器,笔者将
在介绍舒适背景音时详细介绍这个lpc系数的生成,这里,只需要知道它是一个滤波器,
可以得到残差信号即可
噪声能量估值
/* Scale the rezidual energy */
Acc1 = L_mls( Acc1, (Word16) 2913 ) ;//lsc 这可能是除11.22(32768/2913=11.24),噪声能量估值 2913 * 11.22 = 32684(32767?) 10^1.05 = 11.220184543019634355910389464779
这里要注意,观察itu g723文档的vad章节的 A-5公式,它把10^1.05这个因子挪过来了,而把80这个因子移给了thrd的计算,绕得很
对噪声能量做个限制
/* Clip noise level in any case */ //lsc 如果噪声能量太大,更新噪声的能量,加前一帧噪声能量估值的3/4,再取1/4,形成当前噪声能量
if ( VadStat.Nlev > VadStat.Penr ) {
Acc0 = L_sub( VadStat.Penr, L_shr( VadStat.Penr, 2 ) ) ;
VadStat.Nlev = L_add( Acc0, L_shr( VadStat.Nlev, 2 ) ) ;
}
根据当前帧是元音还是辅音,做一个适当放大处理,盖因辅音段,在g723的编码模型里,就认为是由一个随机信号激励形成的
/* Update the noise level, if adaptation is enabled */
if ( !VadStat.Aen ) {//lsc 如果是清音
VadStat.Nlev = L_add( VadStat.Nlev, L_shr( VadStat.Nlev, 5 ) ) ;
}
/* Decay Nlev by small amount */
else {//lsc 如果是浊音,或者处于尾响阶段
VadStat.Nlev = L_sub( VadStat.Nlev, L_shr( VadStat.Nlev,11 ) ) ;
}
近一步限制噪声能量的取值范围 最小128 最大16383
/* Update previous energy */
VadStat.Penr = Acc1 ;
/* CLip Noise Level */
if ( VadStat.Nlev < 0x00000080L )
VadStat.Nlev = 0x00000080L ;
if ( VadStat.Nlev > 0x0001ffffL )
VadStat.Nlev = 0x0001ffffL ;
接来计算门限系数,这里涉及到用折线段来模拟指数函数,
知道是这么处理的就可以了.
最后将噪声能量估值与门限系数相乘,然后与激励能量比较,来判断是否为静音帧
代码片段如下:
/* Compute the threshold */ //lsc 这里计算门限,本质而言,还是一个能量探测器
Acc0 = L_shl( VadStat.Nlev, 13 ) ;
Tm0 = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Tm0 ) ;
Acc0 &= 0x3f000000L ;//lsc 笔者认为,itu可能把10这个因子塞在这里了,把10拆成(10^0.005)^20,塞进指数里,做了缩放,纠结的运算啊
Acc0 <<= 1 ;//lsc
Tm1 = extract_h( Acc0 ) ;
Acc0 = L_deposit_h( ScfTab[Tm0] ) ;
Acc0 = L_mac( Acc0, Tm1, ScfTab[Tm0-1] ) ;//lsc 这两行计算斜率,插值
Acc0 = L_msu( Acc0, Tm1, ScfTab[Tm0] ) ;
Tm1 = extract_h( Acc0 ) ;
Tm0 = extract_l( L_shr( VadStat.Nlev, 2 ) ) ;
Acc0 = L_mult( Tm0, Tm1 ) ;
Acc0 >>= 11 ;//lsc 这里隐含着扩大8位, 15+1-2=14 而只右移11位,则扩大了8倍,这样基本算是找到了文档的1/80分之一的因子了
/* Compare with the threshold */ //lsc 0表示为静音 笔者认为文档中的描述有误,应该是thr*nlev与能量比较,至少从代码看,是这样,纠结啊
if ( Acc0 > Acc1 )
VadState = 0 ;
尾响处理,如果是元音,后面的6帧认为非静音,比较简单,笔者就不列出代码了
总结:
g723的能量检测仍然基于能量检测的
林绍川
2012.1.5 于杭州
分享到:
相关推荐
19--[星光小学计算机特长班作品----静音时钟].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码19--[星光小学计算机特长班作品----静音时钟].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码19--...
1、Snort入侵检测系统源码分析,294页全文版; 2、版权所有独孤九贱; 3、注意是基于Snort2.2版本的分析;
笔者在分析g723时产生的注释,希望对语音感兴趣朋友有用 email: lsccsl@tom.com
Ext grid中渲染进度条,超帅 源码-----下载不扣分,回帖加1分,欢迎下载,童叟无欺。Ext grid中渲染进度条,超帅 源码-----下载不扣分,回帖加1分,欢迎下载,童叟无欺。Ext grid中渲染进度条,超帅 源码-----下载不扣分...
逆向易語言源碼 易语言文件分析软件及源码2.0 2014-11-24
ANDROID源码分析实录-高清版-带详细目录书签-可跳转 PDF 本资源转载自网络,供学习研究之用,如用于商业用途,请购买正版,如有侵权,请联系我或CSDN删除。
G.723.1 itu 源码,没有经过优化,纯C
医学影像分析-基于python的3D-CT影像的肺结节检测算法源码+项目说明+LUNA16数据集.zip 医学影像分析-基于python的3D-CT影像的肺结节检测算法源码+项目说明+LUNA16数据集.zip 医学影像分析-基于python的3D-CT影像的肺...
基于 CNN 的疲劳检测源码-Python - 模型: CNN; - drowsiness detection; - blink detection; - yawning detection
Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...
博客<户手势检测-GestureDetector使用详解>对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/39520901
是著名外企公司sun的源代码,包含 g721 g711 g729 g723 g722 音频编码解码及实例分析c代码
VAD - 录音过程中,实时检测当前是否有人在讲话(语音活动检测,或者叫静音检测)。讲话时webRtcVad_Process返回true,不讲话时返回false。直接用android studio打开,编译后“喂喂”两下,看log即可。by tanyaping...
C#源码系列7---一个开源ERP源码(C#)
Android项目源码开源AnyRTC-RTMP全平台直播源码
webrtc的vad静音检测音频处理模块,含源码。VAD 录音过程中,实时检测当前是否有人在讲话(语音活动检测,或者叫静音检测)。讲话时webRtcVad_Process返回true,不讲话时返回false 直接用android studio打开,编译...
微信小程序源码合集1-6.rar
(含源码及报告)本程序分析了自2016年到2021年(外加)每年我国原油加工的产量,并且分析了2020年全国各地区原油加工量等,含饼状图,柱状图,折线图,数据在地图上显示。运行本程序需要requests、bs4、csv、pandas...
webrtc的静音检测(vad)部分单独封装为动态库,附带源码可以编译
OpenStack源码分析,学习nova的好材料