第十七章 舒适噪声生成
舒适噪声应用在实时语音通信(VoIP,电话等)场景中,主要解决两个问题,第一个是减小传输数据量,进而减小传输带宽的要求,这是因为50%的时间是没有语音的,第二个是让人感觉语音通信是持续连接的。
随机数生成
舒适噪声的生成算法中用到了随机数生成算法,随机数将会被填充为语音通信的背景噪声;这里分析乘加同余法实现,该算法由Lehmer于1951年提出,对任意一个初始值,伪随机数序列由下列递推公式确定:
其中a为常数。
为便于计算机实现,通常取,其中s为计算机中二进制数的最大可能有效位数,, ,其中k使在计算机上所能容纳的最大的整数,
递推公式如下:
RANDU随机数产生器有IBM提出
取69096是为了解决乘同余产生器在三维和三维以上的空间中,所产生的随机数总是聚集在一些超平面上随机数序列是关联的问题。
static uint32_t IncreaseSeed(uint32_t* seed) {
seed[0] = (seed[0] * ((int32_t)69069) + 1) & (kMaxSeedUsed - 1);
return seed[0];
}
int16_t WebRtcSpl_RandU(uint32_t* seed) {
return (int16_t)(IncreaseSeed(seed) >> 16);
}
int16_t WebRtcSpl_RandN(uint32_t* seed) {
return kRandNTable[IncreaseSeed(seed) >> 23];
}
// Creates an array of uniformly distributed variables.
int16_t WebRtcSpl_RandUArray(int16_t* vector,
int16_t vector_length,
uint32_t* seed) {
int i;
for (i = 0; i < vector_length; i++) {
vector[i] = WebRtcSpl_RandU(seed);
}
return vector_length;
}
舒适噪声生成实现
1.首先生成随机数,调用前面的随机数生成算法,并将其归一化到正负一之间。
// Generate a uniform random array on [0 1]
WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed);
for (i = 0; i < PART_LEN; i++) {
rand[i] = ((float)randW16[i]) / 32768;
}
2.生成噪声
抑制低频噪声,就是将u[0]之后的都赋值为0.为了对频域的信号进行加噪,需要使用欧拉公式,得到实部和虚部分别对应的cos和sin分量值。
// Reject LF noise
u[0][0] = 0;
u[0][1] = 0;
for (i = 1; i < PART_LEN1; i++) {
tmp = pi2 * rand[i - 1];
noise = sqrtf(noisePow[i]);
u[i][0] = noise * cosf(tmp);
u[i][1] = -noise * sinf(tmp);
}
u[PART_LEN][1] = 0;
3.对分量值进行相乘
为了防止背景噪声过大,使用了限制因子tmp,该值根据lambda值计算,该值的意义见AEC分析。
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[i][0];
efw[1][i] += tmp * u[i][1];
}
如果是宽带的32KHz的信号,还会对高频子带做类似的操作。