小奥的学习笔记

  • Home
  • Learning & Working
    • Speech Enhancement Notes
    • Programming language
    • Computer & DL
    • MOOC
  • Life
    • Life Time
    • Thinking & Comprehension
    • Volunteer
    • Plan
    • Travel
  • Footprints
  • GuestBook
  • About
    • About Me
    • 个人履历
    • 隐私策略
  1. 首页
  2. Study-notes
  3. Computer & DL
  4. 语音处理学习笔记
  5. 正文

AEC个人学习串讲之fullaec.m:非线性处理(下)

2021年8月22日 2209点热度 3人点赞 1条评论

取消大小周了,周末有了更多的时间来自己学习。给自己立个flag,两周内把fullaec.m里面的线性滤波器、NLP等部分弄懂,发博客;再2~3周的时间看webrtc的AEC3的代码,同样发博客整理;然后再2~3周的时间看一下speex里面的AEC算法。

本次继续更新非线性处理部分。在学习过程中,参考了《实时语音处理实践指南》相关内容和网上有关博客的内容,在此对相关作者表示感谢。

非线性处理部分

计算完hnled,接下来开始计算ovrd。
hnlLocalMin是对hnlPrefAvgLow的最小值跟踪,其初始值为1,在满足了下面判断条件下,实际上就是发现了更小的值(并且这个最小值符合条件),就会对其更新,然后将hnlNewMin设置为1,hnlMinCtr重新置0。
设置hnlNewMin为1其实更接近于一个bool值,他其实是指有没有更新hnlLocalMin,hnlMinCtr其实更类似于一个计数器,当hnlNewMin=1(也就是更新了之后),往下走就会更新hnlMinCtr=2,若此时下一个循环过来了没有更新hnlPrefAvg,则实际满足了hnlNewMin=1且计数的hnlMinCtr=2,这个时候就开始更新抑制等级ovrd。
if hnlPrefAvgLow < hnlLocalMin & hnlPrefAvgLow < 0.6
hnlLocalMin = hnlPrefAvgLow;
hnlMin = hnlPrefAvgLow;
hnlNewMin = 1;
hnlMinCtr = 0;
end
if hnlNewMin == 1:
hnlMinCtr = hnlMinCtr + 1;
end
if hnlMinCtr == 2:
hnlNewMin = 0;
hnlMinCtr = 0;
ovrd = max(log(0.00000001)/log(hnlMin +1e-10),3);
end
这里更新的ovrd最小值为3。
除了hnlLocalMin是对hnlPrefAvgLow的最小值跟踪外,cohxdLocalMin是对hnlSort的最小值跟踪。这里为了防止值大于1,对其进行了处理。
hnlLocalMin = min(hnlLocalMin + 0.0008/mult, 1);
cohxdLocalMin = min(cohxdLocalMin + 0.0004/mult, 1);
最后平滑更新ovrdSm。
if ovrd < ovrdSm
ovrdSm = 0.99*ovrdSm + 0.01*ovrd;
else
ovrdSm = 0.9*ovrdSm + 0.1*ovrd;
end

接下来是进行发散处理。
首先对Se和Sd(分别是误差信号的功率谱和近端信号的功率谱)按行求和,得到误差信号的能量ekEn和近端信号的能量dkEn。然后进行发酸处理。如果divergeState为0,期望误差能量大于近端能量,则用df(近端信号频谱)更新ef(误差信号频谱),并将发散处理装divergeState置为1,否则继续往下走。如果divergeState为1,则判断近端信号能量是否大于误差信号能量的1.05倍,若是则将divergeState置为0,否则用df(近端信号频谱)更新ef(误差信号频谱),divergeState仍为1。
ekEn = sum(Se);
dkEn = sum(Sd);
if divergeState == 0
if ekEn > dkEn
ef = df;
divergeState = 1;
end
else
if ekEn*1.05 < dkEn
divergeState = 0;
else
ef = df;
end
end
如果误差信号比近端信号大约13dB(差不多误差能量大于近端能量的19.95倍),则认为此时滤波器已经发散了,就要重新更新滤波器,即将滤波器系数WFb置为全零矩阵。
if ekEn > dkEn*19.95
WFb=zeros(N+1,M); % Block-based FD NLMS
end
如果滤波器系数每发散,或者已经将WFb置零了之后,就需要将相应的能量存放在相应的向量中,将hnlLocalMin/cohxdLocalMin/hnlMin等保存在相应向量中。
ekEnV(kk) = ekEn;
dkEnV(kk) = dkEn;
hnlLocalMinV(kk) = hnlLocalMin;
cohxdLocalMinV(kk) = cohxdLocalMin;
hnlMinV(kk) = hnlMin;

接下来开始平滑滤波器系数及抑制指数,计算NLP的权重了。
首先使用权重曲线weight平滑hnled。wegiht是一个频率在较低的时候值很低,随着频率点变大值变大的曲线(如下图所示)。我们用hnlPrefAvg和hnled对应频点的较小值来更新这一次的hnled,更新后的值乘上weight,更新之前的值(上一次)乘1-weight的和来作为最终的hnled。结合weight的曲线我们发现,更新的时候存在这样一个现象:频率越高的点,使用本次更新的hnled的值的占比越大;频率越低的点,使用上一次的值平滑的结果占比越大。
aggFact = 0.3;
wCurve = [0; aggrFact*sqrt(linspace(0,1,N))' + 0.1];
weight = wCurve;
hnled = weight.*min(hnlPrefAvg, hnled) + (1 - weight).*hnled;
接下来利用ovrdSm来生成od,实际上是ovrdSm*(1+sqrt(x)),其中x是0~1之间等分65份的线性分布。od用来更新hnld的幂指数。
od = ovrdSm *sqrt(linspace(0,1,N+1))' + 1;
sshift = ones(N+1,1);
hnled = hnled.^(od.*sshift);
最后就是hnl系数与误差信号的频谱点乘,在时域相当于卷积,也就是将误差信号通过这样一个滤波器最后得到NLP处理后的感兴趣信号。最后存储一些有关的变量值。
hnl=hnled;
ef = ef.*(hnl);
ovrdV(kk) = ovrdSm;
hnledAvg(kk) = 1-mean(1-cohed(echoBandRange));
hnlxdAvg(kk) = 1-mean(cohxd(echoBandRange));
hnlSortQV(kk) = hnlPrefAvgLow;
hnlPrefAvgV(kk) = hnlPrefAvg;
至此,整个aec的主要流程已经结束。后面就是舒适噪声的生成和将频域信号经过IFFT和重叠相加变回时域信号,然后切到下一帧进行处理,直到所有音频处理完成。
相关阅读:AEC个人学习串讲:fullaec.m(上) 、AEC个人学习串讲:fullaec.m(中) 

至此,fullaec.m的第一遍阅读笔记就整理结束了。总的来说,经过这次整理我弄明白了AEC里面很多部分的计算和更新的思想是什么,收获颇丰。但是这里并没有DTD模块等其他模块的代码整理,我看在fullaec.m里面也没有这部分代码,我想在后面我在阅读webrtc aec3的时候可以进行进一步的整理。同时我还想提到的是,我阅读的代码只是其中的一个版本,实际上包括od、hnled等多个参数中间都可以有多种方式的特殊处理,以提升AEC的效果,这些我都没要整理在代码串讲里面。接下来我打算趁热打铁,好好看看webrtc 里面aec3代码是如何写的,并且整理出一份代码串讲来,作为下面多期代码串讲的内容。

博客内容排版有些混乱,如需访问原版,请点击这里访问,访问密码请关注个人公众号【小奥的学习笔记】,回复fullaec获取。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: AEC AEC3 WebRTC 语音处理
最后更新:2021年8月22日

davidcheung

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

搜索
欢迎关注我的个人公众号
最新 热点 随机
最新 热点 随机
DEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架 奥地利匈牙利九日游旅程 论文阅读之Study of the General Kalman Filter for Echo Cancellation 小奥看房之鸿荣源珈誉府 杭州往返旅途及西溪喜来登和万怡的体验报告 2022年的第一篇碎碎念
奥地利匈牙利九日游旅程小奥看房之鸿荣源珈誉府论文阅读之Study of the General Kalman Filter for Echo CancellationDEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架
2014.9—2015.1的计划(证书考试)安排 《剑指Offer》题目解析(1) 作品声明 C++面向对象程序设计课程笔记(第四周) AEC个人学习串讲之AEC3:概述及非核心部分 S.V Beijing Travel 6:Very 囧 day
标签聚合
leetcode 鸟哥的linux私房菜 高中 python学习 算法 linux Python 学习 生活 Java
最近评论
davidcheung 发布于 5 个月前(02月09日) The problem has been fixed. May I ask if you can s...
tk88 发布于 5 个月前(02月07日) Hmm is anyone else having problems with the pictur...
cuicui 发布于 8 个月前(10月20日) :wink:
niming 发布于 10 个月前(09月19日) 同级校友,能刷到太巧了
davidcheung 发布于 2 年前(08月16日) 我得找一下我之前整理的word文档看一下,如果找到了我就更新一下这篇文章。
Nolan 发布于 2 年前(07月25日) 您的笔记非常有帮助。贴图不显示了,可以更新一下吗?
davidcheung 发布于 3 年前(06月19日) 到没有看webrtc的代码。现在主要在看我们公司的代码了。。。只是偶尔看一看webrtc的东西。。。
aobai 发布于 3 年前(03月13日) gain_change_hangover_ 应该是每三个block 只能够调整一次,这样保证每帧...
匿名 发布于 5 年前(12月30日) 烫
小奥 发布于 5 年前(12月12日) webRTC里面的NS本身我记得就是在C++里面呀

COPYRIGHT © 2025 小奥的学习笔记. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

陕ICP备19003234号-1

鲁公网安备37120202000100号