speex-DSP 源码分析AEC篇

1. 陷波器去直流

  speex采用数字陷波器去直流。数字陷波器去直流的基本原理就是在单位圆频率为0(即x轴正半轴与单位圆交点)的地方放置一个零点,并在接近零点的单位圆内放置一对共轭极点,这样即实现了去除直流分量的滤波作用;
  公式如下所示:

陷波器系统函数

  极零图如下所示:
极零图

speex所用的系统函数为:
image.png

源码如下

static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride)
{
   int i;
   spx_word16_t den2;
#ifdef FIXED_POINT
   den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius));
#else
   den2 = radius*radius + .7*(1-radius)*(1-radius);
#endif
   /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
   for (i=0;i<len;i++)
   {
      spx_word16_t vin = in[i*stride];
      spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15);  /* out  x(n)-2*x(n - 1) + x(n - 2) + 1.9640*y(n - 1) - 0.964*y(n - 2) */
#ifdef FIXED_POINT
      mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1);
#else
      mem[0] = mem[1] + 2*(-vin + radius*vout);  /* save -2*x(n - 1) + x(n - 2) + 1.9640*y(n - 1) - 0.964*y(n - 2) */
#endif
      mem[1] = SHL32(EXTEND32(vin),15) - MULT16_32_Q15(den2,vout); /* save x(n - 2) - 0.964*y(n - 2) */
      out[i] = SATURATE32(PSHR32(MULT16_32_Q15(radius,vout),15),32767); /*  补偿增益 */
   }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。