1. 原理
人耳在对能量较低的频率上的噪声比较敏感! 所以能量高的共峰处允许误差较大,能量低的共峰处误差允许较小...
上面的 r 为加权系数
2. 自适应....加权系数计算...
double LarOld[2] = {0, 0};
int smooth = 1;
void perc_var (double *gamma1, double *gamma2, double *LsfInt, double *LsfNew, double *r_c )
{
double Lar[4]; /* Q11 */
int k=0;
printf("\n perc_var");
for (k=0; k<M; k++)
{
// LsfInt[k] = shl(LsfInt[k], 1);
// LsfNew[k] = shl(LsfNew[k], 1);
printf("\n %8.4f %8.4f ", LsfInt[k], LsfInt[k]);
}
double *LarNew = &Lar[2];
double rc_cur = 0.0;
// -------> 快速算法 用来计算 对数比面积 log10( (1-rc) /(1+rc))
int i=0;
for(i=0; i<2;i++)
{
if(r_c[i]>0)
rc_cur = r_c[i];
else
rc_cur = -r_c[i];
if(rc_cur <= 0.6314)
{
LarNew[i] = rc_cur;
}
else
{
if(rc_cur <= 0.8864)
{
LarNew[i] = rc_cur * 2.23 - 0.78;
}
else
{
if(rc_cur <= 0.9490)
{
LarNew[i] = rc_cur * 5.57 - 3.90;
}
else
{
LarNew[i] = rc_cur * 13.40 - 11.16;
}
}
}
}
////////////////////////////////////////////////////
Lar[0] = (LarNew[0] + LarOld[0])/2;
Lar[1] = (LarNew[1] + LarOld[1])/2;
LarOld[0] = LarNew[0];
LarOld[1] = LarNew[1];
// 自适应计算增益
for (k=0; k<2; k++)
{
double CritLar0 = Lar[2*k];
double CritLar1 = Lar[2*k+1];
if(smooth != 0)
{
if( (CritLar0 < -1.74) && (CritLar1>0.65))
smooth = 0;
}
else
{
if( (CritLar0 > 1.52) && (CritLar1<0.43))
smooth = 1;
}
if(smooth == 0)
{
double *pLsf = NULL;
gamma1[k] = 0.98;
if(k==0)
pLsf = LsfInt;
else
pLsf = LsfNew;
double min = pLsf[1] - pLsf[0];
for(i=1; i<(M-1); i++)
{
double tmp = pLsf[i+1] - pLsf[i];
if(tmp<min) min = tmp;
}
// 不是平滑的情况下....用最小间隙计算
gamma2[k] = -6*PI*min+1.0;
if(gamma2[k]>0.70) gamma2[k] = 0.70;
if(gamma2[k]<0.40) gamma2[k] = 0.40;
}
else
{
gamma1[k] = 0.94;
gamma2[k] = 0.60;
}
}
}
3. 进行加权计算....也就是实现下面的公式---> 这里有个问题 s(n) 应该是不用的..但不知道为什么论文中有这个东西....
// 计算 上图中的.. a(i)*r^i 放到 Ap 中去
Weight_Az(&A_t[0], gamma1[0], M, Ap1);
Weight_Az(&A_t[0], gamma2[0], M, Ap2);
wsp = old_wsp + PIT_MAX;
// 实现 上图的第二部分 第一张图的分子
Residu(Ap1, &speech[0], &wsp[0], L_SUBFR); //
// 实现 上图的第三部分 第一张图的分母
Syn_filt(Ap2, &wsp[0], &wsp[0], L_SUBFR, mem_w, 1); // 线性预测
// 第二子帧
Weight_Az(&A_t[MP1], gamma1[1], M, Ap1);
Weight_Az(&A_t[MP1], gamma2[1], M, Ap2);
Residu(Ap1, &speech[L_SUBFR], &wsp[L_SUBFR], L_SUBFR); //
Syn_filt(Ap2, &wsp[L_SUBFR], &wsp[L_SUBFR], L_SUBFR, mem_w, 1);
..输出放到 wsp 中去.....