舒适噪声生成算法及其实现

我的书:

购买链接:

京东购买链接

淘宝购买链接

当当购买链接

 

 

舒适生成算法CNG(comfort noise generation)

  舒适噪声应用在实时语音通信(VoIP,电话等)场景中,主要解决两个问题,第一个是减小传输数据量,进而减小传输带宽的要求,这是因为50%的时间是没有语音的,第二个是让人感觉语音通信是持续连接的。

随机数生成

舒适噪声的生成算法中用到了随机数生成算法,随机数将会被填充为语音通信的背景噪声;这里分析乘加同余法实现,该算法由Lehmer于1951年提出,对任意一个初始值$$x_1$$,伪随机数序列由下列递推公式确定:

$$x_{i+1} = a \cdot x_i (modM), \Sigma_{i+1}= \frac{x_{i+1}}{M}, i=1,2,\cdots$$

其中a为常数。

为便于计算机实现,通常取$$M=2^s$$,其中s为计算机中二进制数的最大可能有效位数,$$x_1=奇数$$, $$a=5^{2k+1}$$,其中k使$$5^{2k+1}$$在计算机上所能容纳的最大的整数,

递推公式如下:

RANDU随机数产生器有IBM提出

取69096是为了解决乘同余产生器在三维和三维以上的空间中,所产生的随机数总是聚集在一些超平面上随机数序列是关联的问题。

```

static uint32_t IncreaseSeed(uint32_t* seed)  {
  seed[0] = (seed[0] * ((int32_t)69069) + 1) & (kMaxSeedUsed - 1);
   return seed[0];
 }
 
int16_t WebRtcSpl_RandU(uint32_t* seed) {
  return (int16_t)(IncreaseSeed(seed) >> 16);
}
 
int16_t WebRtcSpl_RandN(uint32_t* seed) {
    return kRandNTable[IncreaseSeed(seed) >> 23];
 }
 
  // Creates an array of uniformly distributed variables.
int16_t WebRtcSpl_RandUArray(int16_t* vector,
                             int16_t vector_length,
                             uint32_t* seed) {
    int i;
    for (i = 0; i < vector_length; i++) {
      vector[i] = WebRtcSpl_RandU(seed);
    }
    return vector_length;
  }

```

舒适噪声生成实现

1.首先生成随机数,调用前面的随机数生成算法,并将其归一化到正负一之间。

```

    // Generate a uniform random array on [0 1]
    WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed);
    for (i = 0; i < PART_LEN; i++) {
      rand[i] = ((float)randW16[i]) / 32768;
    }

```

2.生成噪声

抑制低频噪声,就是将u[0]之后的都赋值为0.为了对频域的信号进行加噪,需要使用欧拉公式,得到实部和虚部分别对应的cos和sin分量值。

```

    // Reject LF noise
    u[0][0] = 0;
    u[0][1] = 0;
    for (i = 1; i < PART_LEN1; i++) {
      tmp = pi2 * rand[i - 1];
 
      noise = sqrtf(noisePow[i]);
      u[i][0] = noise * cosf(tmp);
      u[i][1] = -noise * sinf(tmp);
    }
    u[PART_LEN][1] = 0;

```

3.对分量值进行相乘

为了防止背景噪声过大,使用了限制因子tmp,该值根据lambda值计算,该值的意义见AEC分析。

```

    for (i = 0; i < PART_LEN1; i++) {
      // This is the proper weighting to match the background noise power
      tmp = sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0));
      // tmp = 1 - lambda[i];
      efw[0][i] += tmp * u[i][0];
      efw[1][i] += tmp * u[i][1];
    }

```

如果是宽带的32KHz的信号,还会对高频子带做类似的操作。

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页