WebRTC AEC快適ノイズアルゴリズムの追加
WebRTCの快適ノイズは、実際には、同じフレームのエコー出力NLPパラメータの重み付け処理によって発生したノイズである.32 K信号であれば、生成された高周波数帯域のランダムノイズに対して統一的に重み付けされ、重み付け値は同じフレームのエコーキャンセル出力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];
}
}
}