函数签名

/**
* @param st 全局context,存储一些上下文用的变量和结构体
* @param X  根据入参in生成的频域数据,其中在训练时,低频部分被全部清零
* @param P  是含有基频(pitch)部分语音信号生成的频域数据
* @param Ex [band](https://blog.csdn.net/mimiduck/article/details/106390000)能量数据
* @param Ep 对应pitch信号数据的band能量
* @param Exp 信号能量与pitch能量的相关(correlation)值
* @param features rnnoise训练定义的feature
* @param in  输入数字信号,即时域信号
* @return gain 如果是训练数据有返回值
* */
int compute_frame_features(DenoiseState *st, kiss_fft_cpx *X,kiss_fft_cpx *P,float *Ex, float *Ep, float *Exp, float *features, const float *in)

该函数主要做以下几件事情:

  1. 降采然后找pitch
    其中几个函数pitch_downsamplepitch_searchremove_doubling都是opus源码里的,作者基本照搬了过来,主要是为了找pitch

  2. 计算pitch信号band能量值,输入信号band能量值,以及根据两者计算出相关系数Exp

  apply_window(p);    // pitch数据应用windowforward_transform(P, p); // 傅里叶变换计算pitch频域数据compute_band_energy(Ep, P); // 计算pitch部分的band能量compute_band_corr(Exp, X, P); // 计算信号频域与pitch频域的相关band能量系数

注意,这里的Bark频率划分为22个区域,所以NB_BANDS=22

Exp做标准化:
Expi=Expi/sqrt(0.001+Exi∗Epi)Exp_i = Exp_i/sqrt(0.001+Ex_i*Ep_i) Expi​=Expi​/sqrt(0.001+Exi​∗Epi​)

然后在做一次dct,实际上就是信号与pitch相关BFCC了

 for (i=0;i<NB_BANDS;i++) Exp[i] = Exp[i]/sqrt(.001+Ex[i]*Ep[i]);dct(tmp, Exp);

然后填充feature的 NB_BANDS+2NB_DELTA_CEPS (22+26=34)到NB_BANDS+3*NB_DELTA_CEPS (40),填充后实际上是做了一些参数调整的。

  for (i=0;i<NB_DELTA_CEPS;i++) features[NB_BANDS+2*NB_DELTA_CEPS+i] = tmp[i];features[NB_BANDS+2*NB_DELTA_CEPS] -= 1.3;features[NB_BANDS+2*NB_DELTA_CEPS+1] -= 0.9;features[NB_BANDS+3*NB_DELTA_CEPS] = .01*(pitch_index-300);

而feature的1-NB_BANDS(22)是由log10(Ex)再做一次DCT后填充的,代码如下,

  logMax = -2;follow = -2;for (i=0;i<NB_BANDS;i++) {Ly[i] = log10(1e-2+Ex[i]);Ly[i] = MAX16(logMax-7, MAX16(follow-1.5, Ly[i]));logMax = MAX16(logMax, Ly[i]);follow = MAX16(follow-1.5, Ly[i]);E += Ex[i];}dct(features, Ly);

这个实际上就是输入信号的BFCC

22~33部分为delta差值,

  features[0] -= 12;features[1] -= 4;ceps_0 = st->cepstral_mem[st->memid];ceps_1 = (st->memid < 1) ? st->cepstral_mem[CEPS_MEM+st->memid-1] : st->cepstral_mem[st->memid-1];ceps_2 = (st->memid < 2) ? st->cepstral_mem[CEPS_MEM+st->memid-2] : st->cepstral_mem[st->memid-2];for (i=0;i<NB_BANDS;i++) ceps_0[i] = features[i];st->memid++;for (i=0;i<NB_DELTA_CEPS;i++) {features[i] = ceps_0[i] + ceps_1[i] + ceps_2[i];features[NB_BANDS+i] = ceps_0[i] - ceps_2[i];features[NB_BANDS+NB_DELTA_CEPS+i] =  ceps_0[i] - 2*ceps_1[i] + ceps_2[i];}/* Spectral variability features. */if (st->memid == CEPS_MEM) st->memid = 0;

cepstral_mem是一个8*22的数组,每一次feature里的值填充到ceps_0,然后这个数组会往下再做一次。

ceps_0是float指针,它指向的是ceptral_mem第一个NB_BANDS数组,然后每次与相邻的band数组相见,做出一个delta差值。


最后一个特性值,

for (i=0;i<CEPS_MEM;i++){int j;float mindist = 1e15f;for (j=0;j<CEPS_MEM;j++){int k;float dist=0;for (k=0;k<NB_BANDS;k++){float tmp;tmp = st->cepstral_mem[i][k] - st->cepstral_mem[j][k];dist += tmp*tmp;}if (j!=i)mindist = MIN32(mindist, dist);}spec_variability += mindist;}features[NB_BANDS+3*NB_DELTA_CEPS+1] = spec_variability/CEPS_MEM-2.1;

所以,用于训练的特性值数组整体部署排布如下,

  1. 34-40 输入信号与pitch相关BFCC
  2. 0-21 输入信号BFCC
  3. 0-5 / 22-27/ 28-33 delta BFCC
  4. 41 二阶delta

【rnnoise源码分析】compute_frame_feature函数相关推荐

  1. jQuery源码分析-each函数

    本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...

  2. 【rnnoise源码分析】band能量计算

    rnnoise中有个函数compute_band_energy,用于计算band的能量值.这里有几个概念需要理清楚. 基本概念 在看源码之前,我们要弄懂几个概念,不然还真没法看下去了.讲一下什么是fr ...

  3. 【rnnoise源码分析】biquad滤波器

    rnnoise的主要函数rnnoise_process_frame中首先是对输入的信号做biquad滤波. biquad Filter 双二阶滤波器,wiki介绍在这里 它是一种IIR filter ...

  4. x265源码分析 main函数 x265.cpp

    图片转载于x265源码流程分析_Dillon2015的博客-CSDN博客_x265编码流程 cliopt.prase main ()函数--解析函数参数并进行编码准备工作:x265.cpp (1)Ge ...

  5. GCC源码分析(十) — 函数节点的gimple高端化

    版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...

  6. GCC源码分析(十一) — 函数节点的gimple低端化

    版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...

  7. 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )

    文章目录 一.do_mmap 函数执行流程 二.do_mmap 函数源码 调用 mmap 系统调用 , 先检查 " 偏移 " 是否是 " 内存页大小 " 的 & ...

  8. c++imread 函数_OpenCV学习笔记与源码分析: imread( )函数

    引言 imread()函数在opencv使用比较. imread()函数 声明: Mat imread(const string& filename, int flags); 这很标准的写法, ...

  9. Redis源码分析--lookupKey函数查看value值

    lookupKey函数查看value值 robj *lookupKey(redisDb *db, robj *key) {dictEntry *de = dictFind(db->dict,ke ...

最新文章

  1. OpenLayers辅助函数Util.js(三)
  2. 阿里p8程序员吐槽:新来应届生都开卡宴上班,当时就震惊了!
  3. 视频编解码的理论和实践2:Ffmpeg视频编解码
  4. python下载安装教程图解-一招解决:各种版本的Python下载安装教程
  5. 如何理解Minor/Major/Full GC
  6. matlab 如何hidden,Matlab基本函数-hidden函数
  7. CF888G XOR-MST 最小异或生成树
  8. vim 设置支持鼠标
  9. Ant Design Vue页面数据复制
  10. form提交后台注解拿不到数据_浏览器是如何将用户数据发送到服务器的?
  11. pytorch图像数据增强N大技巧
  12. C++ Vector中size()和capacity()区别
  13. XJOI网上同步训练DAY6 T2
  14. 试试看读一下Zepto源码
  15. 接口中定义的成员变量是( )。_C++:如何正确的定义一个接口类
  16. Kaavi and Magic Spell
  17. u盘克隆服务器系统,只需4步!简单又快速的克隆U盘
  18. Node.js npm 使用介绍
  19. 0x800700c1添加语言,Win10更新失败出现”0x800700C1“错误的解决方法
  20. Docker-容器化应用

热门文章

  1. Nat. Commun. | 多层生物分子网络的鲁棒性研究
  2. 基于张量分解和关系约束的多种类型的MicroRNA-疾病预测
  3. 从复旦博士生到985高校副教授,贫穷使人深知摆脱自卑的艰难
  4. 北京大学现代农业研究院张华伟实验室招聘启示
  5. NAR:测序数据鉴别和去除rRNA序列利器RiboDetector
  6. 生信和植物领域最新资讯合集
  7. Nature子刊:用16S及18S rRNA全长进行微生物多样性研究
  8. JGG:北大陈峰+陈宁揭示维生素A缺陷小鼠中多因素对肠道菌群的调节作用
  9. ARM:钒和铁替代固氮酶的前世今生
  10. Nature Biotechnology封面 | 经济快速:纳米孔宏基因组方案, 6小时准确识别下呼吸道病原体...