webRTC AEC 添加舒适噪声算法

webRTC的舒适噪声实际上就是,一个随机噪声经过同一帧消回声输出NLP参数的加权处理产生的噪声。如果是32K信号,则对产生的高频段随机噪声统一加权,加权值是同一帧消回声输出NLP参数的平均值。

static void ComfortNoise(AecCore* aec,
                         float efw[2][PART_LEN1],
                         complex_t* comfortNoiseHband,
                         const float* noisePow,
                         const float* lambda) {
  int i, num;
  float rand[PART_LEN];
  float noise, noiseAvg, tmp, tmpAvg;
  int16_t randW16[PART_LEN];
  complex_t u[PART_LEN1];

  const float pi2 = 6.28318530717959f;

  // Generate a uniform random array on [0 1]
  // 依据seed产生一个part = 64长度的伪随机数组,存放在randW16的地址处,后面用于计算角频率
  WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed);
  // 将产生的伪随机数组转存到临时数组变量rand中
  for (i = 0; i < PART_LEN; i++) {
    rand[i] = ((float)randW16[i]) / 32768;
  }

  // Reject LF noise
  u[0][0] = 0;
  u[0][1] = 0;
  // 依次根据随机数组中的元素产生噪声的时域信号
  for (i = 1; i < PART_LEN1; i++) {
	  // 2*π*f = w,根据随机数组计算角频率
    tmp = pi2 * rand[i - 1];

	// 根据传入的噪声功率数组,产生相应的噪声幅值
    noise = sqrtf(noisePow[i]);
	// 产生噪声,存放于二维数组u中
    u[i][0] = noise * cosf(tmp);
    u[i][1] = -noise * sinf(tmp);
  }
  u[PART_LEN][1] = 0;

  for (i = 0; i < PART_LEN1; i++) {
    // 根据传入参数lambda数组选取合适的权重,用于非线性的调整噪声幅值u
    tmp = sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0));
    efw[0][i] += tmp * u[i][0];
    efw[1][i] += tmp * u[i][1];
  }

  // 对于高频段的噪声
  // TODO: don't compute noise and "tmp" twice. Use the previous results.
  noiseAvg = 0.0;
  tmpAvg = 0.0;
  num = 0;
  if (aec->sampFreq == 32000 && flagHbandCn == 1) {

    // average noise scale
    // average over second half of freq spectrum (i.e., 4->8khz)
    // TODO: we shouldn't need num. We know how many elements we're summing.
	  // 计算传入的噪声功率noisePow中所有元素的平均功率
    for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) {
      num++;
      noiseAvg += sqrtf(noisePow[i]);
    }
    noiseAvg /= (float)num;

    // average nlp scale
    // average over second half of freq spectrum (i.e., 4->8khz)
    // TODO: we shouldn't need num. We know how many elements we're summing.
	 // 同理计算传入参数lambda中所有元素的平均值
    num = 0;
    for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) {
      num++;
      tmpAvg += sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0));
    }
    tmpAvg /= (float)num;

    // 通过计算出来的平均噪声产生高频段的噪声
    // TODO: we should probably have a new random vector here.
    // Reject LF noise
    u[0][0] = 0;
    u[0][1] = 0;
    for (i = 1; i < PART_LEN1; i++) {
      tmp = pi2 * rand[i - 1];

      // Use average noise for H band
      u[i][0] = noiseAvg * (float)cos(tmp);
      u[i][1] = -noiseAvg * (float)sin(tmp);
    }
    u[PART_LEN][1] = 0;

    for (i = 0; i < PART_LEN1; i++) {
      // 使用非线性参数lambda的平均值对高频噪声进行加权处理
      comfortNoiseHband[i][0] = tmpAvg * u[i][0];
      comfortNoiseHband[i][1] = tmpAvg * u[i][1];
    }
  }
}

猜你喜欢

转载自blog.csdn.net/ljl86400/article/details/81082643
今日推荐