上篇文章(基于MCRA-OMLSA的语音降噪(一):原理)讲了基于MCRA-OMLSA降噪的原理,本篇讲怎么做软件实现。软件实现有多种方式。单纯看降噪效果可用python,因为python有丰富的库可用,可节省不少时间,把主要精力放在降噪效果提升上。如果要把算法用在产品上就得用其他语言。我们是芯片公司,且我们team偏底层,最常用的语言是C,所以我又用C实现了该算法。本文先讲讲在python下的实现,再讲讲在C下的实现。

一,python下的实现

Python有丰富的库,音频文件读取的librosa/soundfile等,数学库的numpy(里面也包含了信号处理的fft等),连算指数积分的都有了(scipy.special.exp1)。算法原理搞清楚了后先画软件流程图,如下图:

根据流程图并且基于现成的python库很快就能把算法实现了。关键是调优,要有好的降噪效果。算法里参数较多,主要有αp、αs、αd等,其中有些有推荐的经验值,有些需要自己tuning。参数tuning过程中降噪效果评估依旧用权威的PESQ。将干净语音和噪声以指定的SNR(通常有0db/5db/10db/15db等)叠加后得到带噪语音,用降噪算法对这个带噪语音做降噪得到降噪后的语音。用PESQ工具分别将带噪语音和降噪后的语音与原来的干净语音做比较,可以得到MOS分提高了多少。花了一些时间tuning后有了一个相对不错的降噪效果,以叠加的是白噪声为例,降噪后在各种SNR下的MOS分提升如下表:

二,C语言下的实现

C语言下的实现要用在产品中,算法的运算量(即 CPU load)是一个要重点考虑的因素。实现通常分两个阶段。第一阶段是基于C中已有数学库的浮点实现,在参数值一样的情况下降噪效果要和python实现的保持一致。如果运算量较大或者处理器不支持浮点运算,需要进入第二阶段。首先将用到的数学库函数用自己写的函数(函数里只有加减乘除等)代替,然后再将整个算法定点化,使运算量降下来。

1,第一阶段

首先根据算法和流程图定义结构体和API。这里简单把API列一下,如下图:

从上图看出,MCRA和OMLSA各有两个API,相对简洁,一个是初始化,一个是算法处理。实现时遇到的第一个问题是C语言数学库里没有提供指数积分函数,需要自己实现。在网上搜了下,书《常用算法程序集(C语言)第三版》的14.15节讲了怎么算指数积分,这里简单介绍下。令

其中γ为欧拉常数(γ = 0.577215664901532860606512)。

可以通过该书9.7节的勒让德-高斯求积分法来求。对勒让德-高斯求积分法感兴趣的可以找相关资料来看,这里就不详细介绍了。把Ei(x)求出后再取反就是算法中所要的的值。取几个值比较这个实现与python里scipy.special.exp1的结果,如下表,可以看出精度还是挺高的。

算法代码写好后,还需要FFT相关的代码才能调试,FFT相关的选用了CMSIS里浮点实现的代码。调试时带噪语音文件依旧用的是python实现调试的那个,这样结果好对齐,方便比较各个环节的输出,如FFT的输出、噪声估计的输出等。调试时要一级一级的调,在误差允许的范围内,如果上一级的输出一致而本级的输出不一致,则问题就出在这一级里。在这个方法下很快就调试好了,在误差允许的范围内,每帧各个频点降噪后的幅度谱与python里的保持一致。

2,第二阶段

第二阶段可分两个子阶段,一是把数学库的函数用自己写的函数(函数里只有加减乘除等运算)替代,二是把整个算法定点化。目前第一个子阶段已完成,第二个子阶段完成后有机会也会写怎么对算法做定点化的。

算法用到的数学库函数主要是自然指数(exp())和一般指数(pow()),再加上做完FFT后是复数,需要用求平方根(sqrt())算得幅度谱,所以需要写出这几个库函数对应的函数。对于一般的求指数而言,它可以转换成求自然指数和自然对数,具体关系如下:,所以只要实现了自然指数和自然对数就可以了。这样最终实现的函数是3个:自然指数,自然对数,求平方根。至于怎么实现的这3个函数,细节较多,会在后面专门写一篇文章讲。实现完这些函数后与标准库里的做比较,误差在允许的范围内即可。再把这些函数用在算法中,拿降噪后的幅度谱与python里的比较,误差也在允许的范围内。

基于MCRA-OMLSA的语音降噪(二):实现的更多相关文章

  1. 基于MCRA-OMLSA的语音降噪(三):实现(续)

    上篇文章(基于MCRA-OMLSA的语音降噪(二):实现)讲了基于MCRA-OMLSA的语音降噪的软件实现.本篇继续讲,主要讲C语言下怎么对数学库里的求平方根(sqrt()).求自然指数(exp()) ...

  2. webRTC中语音降噪模块ANS细节详解(一)

    ANS(adaptive noise suppression) 是webRTC中音频相关的核心模块之一,为众多公司所使用.从2015年开始,我在几个产品中使用了webRTC的3A(AEC/ANS/AG ...

  3. 基于MCRA-OMLSA的语音降噪(一):原理

    前面的几篇文章讲了webRTC中的语音降噪.最近又用到了基于MCRA-OMLSA的语音降噪,就学习了原理并且软件实现了它.MCRA主要用于噪声估计,OMLSA是基于估计出来的噪声去做降噪.类比于web ...

  4. webRTC中语音降噪模块ANS细节详解(二)

    上篇(webRTC中语音降噪模块ANS细节详解(一))讲了维纳滤波的基本原理.本篇先给出webRTC中ANS的基本处理过程,然后讲其中两步(即时域转频域和频域转时域)中的一些处理细节. ANS的基本处 ...

  5. webRTC中语音降噪模块ANS细节详解(三)

    上篇(webRTC中语音降噪模块ANS细节详解(二))讲了ANS的处理流程和语音在时域和频域的相互转换.本篇开始讲语音降噪的核心部分,首先讲噪声的初始估计以及基于估计出来的噪声算先验信噪比和后验信噪比 ...

  6. webRTC中语音降噪模块ANS细节详解(四)

    上篇(webRTC中语音降噪模块ANS细节详解(三))讲了噪声的初始估计方法以及怎么算先验SNR和后验SNR. 本篇开始讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降 ...

  7. Java基于opencv实现图像数字识别(二)—基本流程

    Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...

  8. 语音降噪论文“A Hybrid Approach for Speech Enhancement Using MoG Model and Neural Network Phoneme Classifier”的研读

    最近认真的研读了这篇关于降噪的论文.它是一种利用混合模型降噪的方法,即既利用了生成模型(MoG高斯模型),也利用了判别模型(神经网络NN模型).本文根据自己的理解对原理做了梳理. 论文是基于" ...

  9. Android RecyclerView单击、长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类

     Android RecyclerView单击.长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类 我写的附录文章2,介绍了 ...

随机推荐

  1. Prometheus概述

    Prometheus是什么 首先, Prometheus 是一款时序(time series) 数据库, 但他的功能却并非支部与 TSDB , 而是一款设计用于进行目标 (Target) 监控的关键组 ...

  2. 零基础学习java------day11------常用API---Object、Scanner、String、StringBufer/StringBuilder

    API概述 API(application Programming Interface, 应用程序编程接口),是一些预先定义的函数.目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力, ...

  3. windows Notepad++ 上配置 vs 编译器 , 编译并运行

    windows 中 配置 vs编译器 在Linux下,Kris是倾向于在终端中使用gcc和g++来编译C/C++的,在Windows下相信很多人都是选择臃肿的Visual Studio,我亦不免如此. ...

  4. Java实现单链表的增删查改及逆置打印

    //所提供的接口 LinkList.java package Struct; public interface LinkList {//判断链表为空public boolean linkListIsE ...

  5. jvm的优化

    a) 设置参数,设置jvm的最大内存数 b) 垃圾回收器的选择

  6. Cocoapods 版本更新与更新到指定版本

    1.本地现有的Cocoapods的版本号是1.1.0.rc.2,想升级到最新版本 1.先切换gem源 gem sources --remove https://rubygems.org/ gem so ...

  7. RunLoop基础知识以及GCD

    - 1.1 字面意思   a 运行循环   b 跑圈   - 1.2 基本作用(作用重大)   a 保持程序的持续运行(ios程序因而能一直活着不会死)    b 处理app中的各种事件(比如触摸事件 ...

  8. 错误: 找不到或无法加载主类(IDEA中启动spring boot项目)

    版权声明:本文为博主原创文章,如果转载请给出原文链接:http://www.jufanshare.com/content/142.html 提示:需要对IDEA编辑工具使用熟悉 出现一个问题,就是sp ...

  9. String直接赋值与使用new String的区别

    在研究String直接赋值与new String的区别之前我们需要先了解java中的字符串常量池的概念 字符串常量池 String类是我们平常项目中使用频率非常高的一种对象类型,jvm为了提升性能和减 ...

  10. spring Profile 为不同环境提供不同的配置支持

    说明 Profile为在不同环境下使用不同的配置提供了支持(开发环境下的配置和生产环境下的配置肯定是不同的, 例如, 数据库的配置) . 在spring开发中用@Profile 注解使用来选择行配置系 ...