天天看點

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];
    }
  }
}
           

繼續閱讀