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