Index: webrtc/modules/audio_processing/aec/aec_core.cc |
diff --git a/webrtc/modules/audio_processing/aec/aec_core.cc b/webrtc/modules/audio_processing/aec/aec_core.cc |
index 9ddec59c768f2173e43c46af9918835faac6454e..b463597aba1bbb9799ea36607401ffd7a75cdbab 100644 |
--- a/webrtc/modules/audio_processing/aec/aec_core.cc |
+++ b/webrtc/modules/audio_processing/aec/aec_core.cc |
@@ -518,94 +518,67 @@ static void GetHighbandGain(const float* lambda, float* nlpGainHband) { |
*nlpGainHband /= static_cast<float>(PART_LEN1 - 1 - freqAvgIc); |
} |
-static void ComfortNoise(AecCore* aec, |
- float efw[2][PART_LEN1], |
- float comfortNoiseHband[2][PART_LEN1], |
- const float* noisePow, |
- const float* lambda) { |
- int i, num; |
- float rand[PART_LEN]; |
- float noise, noiseAvg, tmp, tmpAvg; |
+static void GenerateComplexNoise(uint32_t* seed, float noise[2][PART_LEN1]) { |
+ const float kPi2 = 6.28318530717959f; |
int16_t randW16[PART_LEN]; |
- float u[2][PART_LEN1]; |
+ WebRtcSpl_RandUArray(randW16, PART_LEN, seed); |
- const float pi2 = 6.28318530717959f; |
- |
- // Generate a uniform random array on [0 1] |
- WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed); |
- for (i = 0; i < PART_LEN; i++) { |
- rand[i] = static_cast<float>(randW16[i]) / 32768; |
- } |
- |
- // Reject LF noise |
- u[0][0] = 0; |
- u[1][0] = 0; |
- for (i = 1; i < PART_LEN1; i++) { |
- tmp = pi2 * rand[i - 1]; |
- |
- noise = sqrtf(noisePow[i]); |
- u[0][i] = noise * cosf(tmp); |
- u[1][i] = -noise * sinf(tmp); |
+ noise[0][0] = 0; |
+ noise[1][0] = 0; |
+ for (size_t i = 1; i < PART_LEN1; i++) { |
+ float tmp = kPi2 * randW16[i - 1] / 32768.f; |
+ noise[0][i] = cosf(tmp); |
+ noise[1][i] = -sinf(tmp); |
} |
- u[1][PART_LEN] = 0; |
+ noise[1][PART_LEN] = 0; |
+} |
- 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[0][i]; |
- efw[1][i] += tmp * u[1][i]; |
- } |
- |
- // For H band comfort noise |
- // TODO(peah): don't compute noise and "tmp" twice. Use the previous results. |
- noiseAvg = 0.0; |
- tmpAvg = 0.0; |
- num = 0; |
- if (aec->num_bands > 1) { |
- // average noise scale |
- // average over second half of freq spectrum (i.e., 4->8khz) |
- // TODO(peah): we shouldn't need num. We know how many elements we're |
- // summing. |
- for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) { |
- num++; |
- noiseAvg += sqrtf(noisePow[i]); |
- } |
- noiseAvg /= static_cast<float>(num); |
- |
- // average nlp scale |
- // average over second half of freq spectrum (i.e., 4->8khz) |
- // TODO(peah): we shouldn't need num. We know how many elements |
- // we're summing. |
- num = 0; |
- for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) { |
- num++; |
- tmpAvg += sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0)); |
+static void ComfortNoise(bool generate_high_frequency_noise, |
+ uint32_t* seed, |
+ float e_fft[2][PART_LEN1], |
+ float high_frequency_comfort_noise[2][PART_LEN1], |
+ const float* noise_spectrum, |
+ const float* suppressor_gain) { |
+ float complex_noise[2][PART_LEN1]; |
+ |
+ GenerateComplexNoise(seed, complex_noise); |
+ |
+ // Shape, scale and add comfort noise. |
+ for (int i = 1; i < PART_LEN1; ++i) { |
+ float noise_scaling = |
+ sqrtf(WEBRTC_SPL_MAX(1 - suppressor_gain[i] * suppressor_gain[i], 0)) * |
+ sqrtf(noise_spectrum[i]); |
+ e_fft[0][i] += noise_scaling * complex_noise[0][i]; |
+ e_fft[1][i] += noise_scaling * complex_noise[1][i]; |
+ } |
+ |
+ // Form comfort noise for higher frequencies. |
+ if (generate_high_frequency_noise) { |
+ // Compute average noise power and nlp gain over the second half of freq |
+ // spectrum (i.e., 4->8khz). |
+ int start_avg_band = PART_LEN1 / 2; |
+ float upper_bands_noise_power = 0.f; |
+ float upper_bands_suppressor_gain = 0.f; |
+ for (int i = start_avg_band; i < PART_LEN1; ++i) { |
+ upper_bands_noise_power += sqrtf(noise_spectrum[i]); |
+ upper_bands_suppressor_gain += |
+ sqrtf(WEBRTC_SPL_MAX(1 - suppressor_gain[i] * suppressor_gain[i], 0)); |
} |
- tmpAvg /= static_cast<float>(num); |
- |
- // Use average noise for H band |
- // TODO(peah): we should probably have a new random vector here. |
- // Reject LF noise |
- u[0][0] = 0; |
- u[1][0] = 0; |
- for (i = 1; i < PART_LEN1; i++) { |
- tmp = pi2 * rand[i - 1]; |
- |
- // Use average noise for H band |
- u[0][i] = noiseAvg * static_cast<float>(cos(tmp)); |
- u[1][i] = -noiseAvg * static_cast<float>(sin(tmp)); |
- } |
- u[1][PART_LEN] = 0; |
- |
- for (i = 0; i < PART_LEN1; i++) { |
- // Use average NLP weight for H band |
- comfortNoiseHband[0][i] = tmpAvg * u[0][i]; |
- comfortNoiseHband[1][i] = tmpAvg * u[1][i]; |
+ upper_bands_noise_power /= (PART_LEN1 - start_avg_band); |
+ upper_bands_suppressor_gain /= (PART_LEN1 - start_avg_band); |
+ |
+ // Shape, scale and add comfort noise. |
+ float noise_scaling = upper_bands_suppressor_gain * upper_bands_noise_power; |
+ high_frequency_comfort_noise[0][0] = 0; |
+ high_frequency_comfort_noise[1][0] = 0; |
+ for (int i = 1; i < PART_LEN1; ++i) { |
+ high_frequency_comfort_noise[0][i] = noise_scaling * complex_noise[0][i]; |
+ high_frequency_comfort_noise[1][i] = noise_scaling * complex_noise[1][i]; |
} |
+ high_frequency_comfort_noise[1][PART_LEN] = 0; |
} else { |
- memset(comfortNoiseHband, 0, |
- 2 * PART_LEN1 * sizeof(comfortNoiseHband[0][0])); |
+ memset(high_frequency_comfort_noise, 0, |
+ 2 * PART_LEN1 * sizeof(high_frequency_comfort_noise[0][0])); |
} |
} |
@@ -1175,7 +1148,8 @@ static void EchoSuppression(AecCore* aec, |
WebRtcAec_Suppress(hNl, efw); |
// Add comfort noise. |
- ComfortNoise(aec, efw, comfortNoiseHband, aec->noisePow, hNl); |
+ ComfortNoise(aec->num_bands > 1, &aec->seed, efw, comfortNoiseHband, |
+ aec->noisePow, hNl); |
// Inverse error fft. |
ScaledInverseFft(efw, fft, 2.0f, 1); |