Refactored the comfort noise generation code in the AEC.
This CL will be followed with other CLs that break apart the application of the comfort noise from the comfort noise generation. The changes in the CL are very close to bitexaxt. The bitinexactness is caused by differences in numerical behavior when bundling the spectral band power and the noise scaling based on the NLP gain. BUG=webrtc:5201, webrtc:5298 Review-Url: https://codereview.webrtc.org/1958933002 Cr-Commit-Position: refs/heads/master@{#12713}
This commit is contained in:
@ -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;
|
||||
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);
|
||||
}
|
||||
noise[1][PART_LEN] = 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
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];
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
u[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]);
|
||||
// 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));
|
||||
}
|
||||
noiseAvg /= static_cast<float>(num);
|
||||
upper_bands_noise_power /= (PART_LEN1 - start_avg_band);
|
||||
upper_bands_suppressor_gain /= (PART_LEN1 - start_avg_band);
|
||||
|
||||
// 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));
|
||||
}
|
||||
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];
|
||||
// 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);
|
||||
|
||||
Reference in New Issue
Block a user