增益量化
寻找xn、y1、y2之间的相关性,并记录相关结果的量化Q值。
/*-----------------------------------------------------*
* - Quantization of gains. *
*-----------------------------------------------------*/
g_coeff_cs[0] = g_coeff[0]; /* <y1,y1> */
exp_g_coeff_cs[0] = negate(g_coeff[1]); /* Q-Format:XXX -> JPN */
g_coeff_cs[1] = negate(g_coeff[2]); /* (xn,y1) -> -2<xn,y1> */
exp_g_coeff_cs[1] = negate(add(g_coeff[3], 1)); /* Q-Format:XXX -> JPN */
// xn:基音搜索目标向量
// y1: 滤波后自适应码书激励
// y2:滤波后固定码书激励
Corr_xy2( xn, y1, y2, g_coeff_cs, exp_g_coeff_cs ); /* Q0 Q0 Q12 ^Qx ^Q0 */
/* g_coeff_cs[3]:exp_g_coeff_cs[3] = <y2,y2> */
/* g_coeff_cs[4]:exp_g_coeff_cs[4] = -2<xn,y2> */
/* g_coeff_cs[5]:exp_g_coeff_cs[5] = 2<y1,y2> */
*ana++ = Qua_gain(code, g_coeff_cs, exp_g_coeff_cs,
L_SUBFR, &gain_pit, &gain_code, temp);
搜索下式均方误差的最小值
|(x-g_p y-g_c z)|^2=(x-g_p y-g_c z)^T*(x-g_p y-g_c z)
增益预测
计算固定码书的增益,预测能量和增益
因为已经两输入除以2,这里$\bar{E}$
从36修改为30。
27为$E_{sum}$
的$E_{fix}$
形式表示的定点,即$E_{sum}=\tfrac{E_{fix}}{2^{27}}$
。
T=\bar{E}-E
=\bar{E}-10\lg{\tfrac{E_{sum}}{40}}
= 30 - \left[10\lg{{E_{fix}}} - 10\lg{2^{27}} - 10\lg{40} \right]
= 30 - 10\lg{{E_{fix}}} + 10\lg{40} + 10\lg{2^{27}}
= 30 - 10\lg{{E_{fix}}} + 16.02 + 81.278
= 127.298 - 10\lg{{E_{fix}}}
= 127.298 - 3.0103*10\log_2{{E_{fix}}}
log_{10}{x}=\lg{x}=\lg2*\log_{2}{x}=0.30103*\log_{2}{x}
/* MA gain prediction coeff ={0.68, 0.58, 0.34, 0.19} in Q13 */
Word16 pred[4] = { 5571, 4751, 2785, 1556 };
P=\bar{E}-E+E^{m}=T+E^{m}=T+\sum_{i=0}^{3}b_iU^{m-i}
g_c=10^{\tfrac{\bar{E}-E+E^{m}}{20}}
=2^{3.3219*\tfrac{\bar{E}-E+E^{m}}{20}}
=2^{0.166*P}
// gainpred.c->Gain_predict
/*-------------------------------*
* Energy coming from code *
*-------------------------------*/
L_tmp = 0;
for(i=0; i<L_subfr; i++) // 固定码书能量
L_tmp = L_mac(L_tmp, code[i], code[i]);
/*-----------------------------------------------------------------*
* Compute: means_ener - 10log10(ener_code/ L_sufr) *
* Note: mean_ener change from 36 dB to 30 dB because input/2 *
* *
* = 30.0 - 10 log10( ener_code / lcode) + 10log10(2^27) *
* !!ener_code in Q27!! *
* = 30.0 - 3.0103 * log2(ener_code) + 10log10(40) + 10log10(2^27) *
* = 30.0 - 3.0103 * log2(ener_code) + 16.02 + 81.278 *
* = 127.298 - 3.0103 * log2(ener_code) *
*-----------------------------------------------------------------*/
// exp包含求log结果的整数部分,frac包含小数部分。
Log2(L_tmp, &exp, &frac); /* Q27->Q0 ^Q0 ^Q15 */
L_tmp = Mpy_32_16(exp, frac, -24660); /* Q0 Q15 Q13 -> ^Q14 */
/* hi:Q0+Q13+1 */
/* lo:Q15+Q13-15+1 */
/* -24660[Q13]=-3.0103 */
L_tmp = L_mac(L_tmp, 32588, 32); /* 32588*32[Q14]=127.298 */
/*-----------------------------------------------------------------*
* Compute gcode0. *
* = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
*-----------------------------------------------------------------*/
L_tmp = L_shl(L_tmp, 10); /* From Q14 to Q24 */
for(i=0; i<4; i++)
L_tmp = L_mac(L_tmp, pred[i], past_qua_en[i]); /* Q13*Q10 ->Q24 */
*gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */
/*-----------------------------------------------------------------*
* gcode0 = pow(10.0, gcode0/20) *
* = pow(2, 3.3219*gcode0/20) *
* = pow(2, 0.166*gcode0) *
*-----------------------------------------------------------------*/
L_tmp = L_mult(*gcode0, 5439); /* *0.166 in Q15, result in Q24*/
L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */
L_Extract(L_tmp, &exp, &frac); /* Extract exponent of gcode0 */
*gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16768 < Pow2() <= 32767 */
*exp_gcode0 = sub(14,exp);
/*------------------------------------------------------------*
* - Update pitch sharpening "sharp" with quantized gain_pit *
*------------------------------------------------------------*/
sharp = gain_pit;
if (sub(sharp, SHARPMAX) > 0) { sharp = SHARPMAX; }
if (sub(sharp, SHARPMIN) < 0) { sharp = SHARPMIN; }
/*------------------------------------------------------*
* - Find the total excitation *
* - find synthesis speech corresponding to exc[] *
* - update filters memories for finding the target *
* vector in the next subframe *
* (update error[-m..-1] and mem_w_err[]) *
* update error function for taming process *
*------------------------------------------------------*/
for (i = 0; i < L_SUBFR; i++)
{
/* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */
/* exc[i] in Q0 gain_pit in Q14 */
/* code[i] in Q13 gain_cod in Q1 */
L_temp = L_mult(exc[i+i_subfr], gain_pit);
L_temp = L_mac(L_temp, code[i], gain_code);
L_temp = L_shl(L_temp, 1);
exc[i+i_subfr] = round(L_temp);
}
update_exc_err(gain_pit, T0);
Syn_filt(Aq, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem_syn, 1);
for (i = L_SUBFR-M, j = 0; i < L_SUBFR; i++, j++)
{
mem_err[j] = sub(speech[i_subfr+i], synth[i_subfr+i]);
temp = extract_h(L_shl( L_mult(y1[i], gain_pit), 1) );
k = extract_h(L_shl( L_mult(y2[i], gain_code), 2) );
mem_w0[j] = sub(xn[i], add(temp, k));
}
A += MP1; /* interpolated LPC parameters for next subframe */
Aq += MP1;
预筛选
一个定点数保存为了两部分,二进制表示和小数位的bit数,即16Qx中的x。
计算自适应码书基音增益,未量化。
/*-----------------------------------------------------------------*
* pre-selection *
*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*
* calculate best gain *
* *
* tmp = -1./(4.*coeff[0]*coeff[2]-coeff[4]*coeff[4]) ; *
* best_gain[0] = (2.*coeff[2]*coeff[1]-coeff[3]*coeff[4])*tmp ; *
* best_gain[1] = (2.*coeff[0]*coeff[3]-coeff[1]*coeff[4])*tmp ; *
* gbk_presel(best_gain,&cand1,&cand2,gcode0) ; *
* *
*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*
* tmp = -1./(4.*coeff[0]*coeff[2]-coeff[4]*coeff[4]) ; *
*-----------------------------------------------------------------*/
L_tmp1 = L_mult( g_coeff[0], g_coeff[2] );
exp1 = add( add( exp_coeff[0], exp_coeff[2] ), 1-2 ); // 相当于乘以 4
L_tmp2 = L_mult( g_coeff[4], g_coeff[4] );
exp2 = add( add( exp_coeff[4], exp_coeff[4] ), 1 );
if( sub(exp1, exp2)>0 ){ // Q(L_tmp1) < Q(L_tmp2),将L_tmp1化成和L_tmp2同定点后做减法
L_tmp = L_sub( L_shr( L_tmp1, sub(exp1,exp2) ), L_tmp2 ); // L_tmp1>>(exp1-exp2) - L_tmp2
exp = exp2;
}
else{
L_tmp = L_sub( L_tmp1, L_shr( L_tmp2, sub(exp2,exp1) ) ); // Q(L_tmp1) > Q(L_tmp2),将L_tmp2化成和L_tmp1同定点后做减法
exp = exp1;
}
sft = norm_l( L_tmp );
denom = extract_h( L_shl(L_tmp, sft) ); // 归一化
exp_denom = sub( add( exp, sft ), 16 ); // 重新计算Q值
inv_denom = div_s(16384,denom);
inv_denom = negate( inv_denom ); // -1 / denom
exp_inv_denom = sub( 14+15, exp_denom ); // 计算Q值
/*-----------------------------------------------------------------*
* best_gain[0] = (2.*coeff[2]*coeff[1]-coeff[3]*coeff[4])*tmp ; *
*-----------------------------------------------------------------*/
L_tmp1 = L_mult( g_coeff[2], g_coeff[1] );
exp1 = add( exp_coeff[2], exp_coeff[1] );
L_tmp2 = L_mult( g_coeff[3], g_coeff[4] );
exp2 = add( add( exp_coeff[3], exp_coeff[4] ), 1 );
if( sub(exp1, exp2)>0 ){
L_tmp = L_sub( L_shr( L_tmp1, add(sub(exp1,exp2),1 )), L_shr( L_tmp2,1 ) );
exp = sub(exp2,1);
}
else{
L_tmp = L_sub( L_shr( L_tmp1,1 ), L_shr( L_tmp2, add(sub(exp2,exp1),1 )) );
exp = sub(exp1,1);
}
sft = norm_l( L_tmp );
nume = extract_h( L_shl(L_tmp, sft) );
exp_nume = sub( add( exp, sft ), 16 );
sft = sub( add( exp_nume, exp_inv_denom ), (9+16-1) );
L_acc = L_shr( L_mult( nume,inv_denom ), sft ); // 乘以 tmp
best_gain[0] = extract_h( L_acc ); /*-- best_gain[0]:Q9 --*/
if (tameflag == 1){ // 需要柔和,即自适应搜索基音延迟误差较大
if(sub(best_gain[0], GPCLIP2) > 0)
best_gain[0] = GPCLIP2; // 如果需要柔和,设置基音增益最大值
}
/*-----------------------------------------------------------------*
* best_gain[1] = (2.*coeff[0]*coeff[3]-coeff[1]*coeff[4])*tmp ; *
*-----------------------------------------------------------------*/
L_tmp1 = L_mult( g_coeff[0], g_coeff[3] );
exp1 = add( exp_coeff[0], exp_coeff[3] ) ;
L_tmp2 = L_mult( g_coeff[1], g_coeff[4] );
exp2 = add( add( exp_coeff[1], exp_coeff[4] ), 1 );
if( sub(exp1, exp2)>0 ){
L_tmp = L_sub( L_shr( L_tmp1, add(sub(exp1,exp2),1) ), L_shr( L_tmp2,1 ) );
exp = sub(exp2,1);
}
else{
L_tmp = L_sub( L_shr( L_tmp1,1 ), L_shr( L_tmp2, add(sub(exp2,exp1),1) ) );
exp = sub(exp1,1);
}
sft = norm_l( L_tmp );
nume = extract_h( L_shl(L_tmp, sft) );
exp_nume = sub( add( exp, sft ), 16 );
sft = sub( add( exp_nume, exp_inv_denom ), (2+16-1) );
L_acc = L_shr( L_mult( nume,inv_denom ), sft ); // // 乘以 tmp
best_gain[1] = extract_h( L_acc ); /*-- best_gain[1]:Q2 --*/
/*--- Change Q-format of gcode0 ( Q[exp_gcode0] -> Q4 ) ---*/
if( sub(exp_gcode0,4) >= 0 ){
gcode0_org = shr( gcode0, sub(exp_gcode0,4) );
}
else{
L_acc = L_deposit_l( gcode0 ); // 16->32位扩展,扩展符号位
L_acc = L_shl( L_acc, sub( (4+16), exp_gcode0 ) ); // 20 - exp_gcode0
gcode0_org = extract_h( L_acc ); /*-- gcode0_org:Q4 --*/
}
预筛选共轭码书,得到搜索起始位置。
// Gbk_presel,返回后续搜索的起始位置
/*--------------------------------------------------------------------------*
x = (best_gain[1] - (coef[0][0]*best_gain[0] + coef[1][1])*gcode0) * inv_coef;
*--------------------------------------------------------------------------*/
L_cfbg = L_mult( coef[0][0], best_gain[0] ); /* L_cfbg:Q20 -> !!y */
L_acc = L_shr( L_coef[1][1], 15 ); /* L_acc:Q20 */
L_acc = L_add( L_cfbg , L_acc );
acc_h = extract_h( L_acc ); /* acc_h:Q4 */
L_preg = L_mult( acc_h, gcode0 ); /* L_preg:Q9 */
L_acc = L_shl( L_deposit_l( best_gain[1] ), 7 ); /* L_acc:Q9 */
L_acc = L_sub( L_acc, L_preg );
acc_h = extract_h( L_shl( L_acc,2 ) ); /* L_acc_h:Q[-5] */
L_tmp_x = L_mult( acc_h, INV_COEF ); /* L_tmp_x:Q15 */
/*--------------------------------------------------------------------------*
y = (coef[1][0]*(-coef[0][1]+best_gain[0]*coef[0][0])*gcode0
-coef[0][0]*best_gain[1]) * inv_coef;
*--------------------------------------------------------------------------*/
L_acc = L_shr( L_coef[0][1], 10 ); /* L_acc:Q20 */
L_acc = L_sub( L_cfbg, L_acc ); /* !!x -> L_cfbg:Q20 */
acc_h = extract_h( L_acc ); /* acc_h:Q4 */
acc_h = mult( acc_h, gcode0 ); /* acc_h:Q[-7] */
L_tmp = L_mult( acc_h, coef[1][0] ); /* L_tmp:Q10 */
L_preg = L_mult( coef[0][0], best_gain[1] ); /* L_preg:Q13 */
L_acc = L_sub( L_tmp, L_shr(L_preg,3) ); /* L_acc:Q10 */
acc_h = extract_h( L_shl( L_acc,2 ) ); /* acc_h:Q[-4] */
L_tmp_y = L_mult( acc_h, INV_COEF ); /* L_tmp_y:Q16 */
// 搜索
sft_y = (14+4+1)-16; /* (Q[thr1]+Q[gcode0]+1)-Q[L_tmp_y] */
sft_x = (15+4+1)-15; /* (Q[thr2]+Q[gcode0]+1)-Q[L_tmp_x] */
if(gcode0 > 0){
/*-- pre select codebook #1 --*/
*cand1 = 0 ;
do{ // thr1,门限,递增,共(NCODE1-NCAN1=4)个
L_temp = L_sub( L_tmp_y, L_shr(L_mult(thr1[*cand1],gcode0),sft_y)); // L_tmp_y - [(thr1[*cand1]*gcode0) >> sft_y]
if(L_temp >0L ) // 大于0,则继续
(*cand1) =add(*cand1,1);
else
break ; // 从这里退出表示符合要求的个数大于要求个数,但也只取前面的
} while(sub((*cand1),(NCODE1-NCAN1))<0) ; // NCODE1码字总个数,NCAN1选择的码字个数,保证候选码字个数足够
/*-- pre select codebook #2 --*/
*cand2 = 0 ;
do{ // thr2,门限,递增,共(NCODE2-NCAN2=8)个
L_temp = L_sub( L_tmp_x , L_shr(L_mult(thr2[*cand2],gcode0),sft_x)); // L_tmp_x - [(thr2[*cand2]*gcode0) >> sft_x]
if( L_temp >0L) // 大于0,则继续
(*cand2) =add(*cand2,1);
else
break ; // 从这里退出表示符合要求的个数大于要求个数,但也只取前面的
} while(sub((*cand2),(NCODE2-NCAN2))<0); // NCODE2码字总个数,NCAN2选择的码字个数,保证候选码字个数足够
}else{
/*-- pre select codebook #1 --*/
*cand1 = 0 ;
do{ // thr1,门限,递增,共(NCODE1-NCAN1=4)个
L_temp = L_sub(L_tmp_y ,L_shr(L_mult(thr1[*cand1],gcode0),sft_y)); // L_tmp_y - [(thr1[*cand1]*gcode0) >> sft_y]
if( L_temp <0L) // 小于0,则继续搜索
(*cand1) =add(*cand1,1);
else
break ; // 从这里退出表示符合要求的个数大于要求个数,但也只取前面的
} while(sub((*cand1),(NCODE1-NCAN1))) ;
/*-- pre select codebook #2 --*/
*cand2 = 0 ;
do{ // thr2,门限,递增,共(NCODE2-NCAN2=8)个
L_temp =L_sub(L_tmp_x ,L_shr(L_mult(thr2[*cand2],gcode0),sft_x)); // L_tmp_x - [(thr2[*cand2]*gcode0) >> sft_x]
if( L_temp <0L) // 小于0,则继续搜索
(*cand2) =add(*cand2,1);
else
break ; // 从这里退出表示符合要求的个数大于要求个数,但也只取前面的
} while(sub( (*cand2),(NCODE2-NCAN2))) ;
}
执行搜索过程
/*---------------------------------------------------------------------------*
* *
* Find the best quantizer. *
* *
* dist_min = MAX_32; *
* for ( i=0 ; i<NCAN1 ; i++ ){ *
* for ( j=0 ; j<NCAN2 ; j++ ){ *
* g_pitch = gbk1[cand1+i][0] + gbk2[cand2+j][0]; *
* g_code = gcode0 * (gbk1[cand1+i][1] + gbk2[cand2+j][1]); *
* dist = g_pitch*g_pitch * coeff[0] *
* + g_pitch * coeff[1] *
* + g_code*g_code * coeff[2] *
* + g_code * coeff[3] *
* + g_pitch*g_code * coeff[4] ; *
* *
* if (dist < dist_min){ *
* dist_min = dist; *
* indice1 = cand1 + i ; *
* indice2 = cand2 + j ; *
* } *
* } *
* } *
* *
* g_pitch = Q13 *
* g_pitch*g_pitch = Q11:(13+13+1-16) *
* g_code = Q[exp_gcode0-3]:(exp_gcode0+(13-1)+1-16) *
* g_code*g_code = Q[2*exp_gcode0-21]:(exp_gcode0-3+exp_gcode0-3+1-16) *
* g_pitch*g_code = Q[exp_gcode0-5]:(13+exp_gcode0-3+1-16) *
* *
* term 0: g_pitch*g_pitch*coeff[0] ;exp_min0 = 13 +exp_coeff[0] *
* term 1: g_pitch *coeff[1] ;exp_min1 = 14 +exp_coeff[1] *
* term 2: g_code*g_code *coeff[2] ;exp_min2 = 2*exp_gcode0-21+exp_coeff[2] *
* term 3: g_code *coeff[3] ;exp_min3 = exp_gcode0 - 3+exp_coeff[3] *
* term 4: g_pitch*g_code *coeff[4] ;exp_min4 = exp_gcode0 - 4+exp_coeff[4] *
* *
*---------------------------------------------------------------------------*/
exp_min[0] = add( exp_coeff[0], 13 );
exp_min[1] = add( exp_coeff[1], 14 );
exp_min[2] = add( exp_coeff[2], sub( shl( exp_gcode0, 1 ), 21 ) );
exp_min[3] = add( exp_coeff[3], sub( exp_gcode0, 3 ) );
exp_min[4] = add( exp_coeff[4], sub( exp_gcode0, 4 ) );
e_min = exp_min[0];
for(i=1; i<5; i++){
if( sub(exp_min[i], e_min) < 0 ){
e_min = exp_min[i];
}
}
/* align coeff[] and save in special 32 bit double precision */
for(i=0; i<5; i++){
j = sub( exp_min[i], e_min );
L_tmp = L_deposit_h( g_coeff[i] );
L_tmp = L_shr( L_tmp, j ); /* L_tmp:Q[exp_g_coeff[i]+16-j] */
L_Extract( L_tmp, &coeff[i], &coeff_lsf[i] ); /* DPF */
}
/* Codebook search */
L_dist_min = MAX_32;
/* initialization used only to suppress Microsoft Visual C++ warnings */
index1 = cand1;
index2 = cand2;
if(tameflag == 1){
for(i=0; i<NCAN1; i++){
for(j=0; j<NCAN2; j++){
g_pitch = add( gbk1[cand1+i][0], gbk2[cand2+j][0] ); /* Q14 */
if(g_pitch < GP0999) {
L_acc = L_deposit_l( gbk1[cand1+i][1] );
L_accb = L_deposit_l( gbk2[cand2+j][1] ); /* Q13 */
L_tmp = L_add( L_acc,L_accb );
tmp = extract_l( L_shr( L_tmp,1 ) ); /* Q12 */
g_code = mult( gcode0, tmp ); /* Q[exp_gcode0+12-15] */
g2_pitch = mult(g_pitch, g_pitch); /* Q13 */
g2_code = mult(g_code, g_code); /* Q[2*exp_gcode0-6-15] */
g_pit_cod= mult(g_code, g_pitch); /* Q[exp_gcode0-3+14-15] */
L_tmp = Mpy_32_16(coeff[0], coeff_lsf[0], g2_pitch);
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[1], coeff_lsf[1], g_pitch) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[2], coeff_lsf[2], g2_code) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[3], coeff_lsf[3], g_code) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[4], coeff_lsf[4], g_pit_cod) );
L_temp = L_sub(L_tmp, L_dist_min);
if( L_temp < 0L ){
L_dist_min = L_tmp;
index1 = add(cand1,i);
index2 = add(cand2,j);
}
}
}
}
}
else{
for(i=0; i<NCAN1; i++){
for(j=0; j<NCAN2; j++){
g_pitch = add( gbk1[cand1+i][0], gbk2[cand2+j][0] ); /* Q14 */
L_acc = L_deposit_l( gbk1[cand1+i][1] );
L_accb = L_deposit_l( gbk2[cand2+j][1] ); /* Q13 */
L_tmp = L_add( L_acc,L_accb );
tmp = extract_l( L_shr( L_tmp,1 ) ); /* Q12 */
g_code = mult( gcode0, tmp ); /* Q[exp_gcode0+12-15] */
g2_pitch = mult(g_pitch, g_pitch); /* Q13 */
g2_code = mult(g_code, g_code); /* Q[2*exp_gcode0-6-15] */
g_pit_cod= mult(g_code, g_pitch); /* Q[exp_gcode0-3+14-15] */
L_tmp = Mpy_32_16(coeff[0], coeff_lsf[0], g2_pitch);
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[1], coeff_lsf[1], g_pitch) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[2], coeff_lsf[2], g2_code) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[3], coeff_lsf[3], g_code) );
L_tmp = L_add(L_tmp, Mpy_32_16(coeff[4], coeff_lsf[4], g_pit_cod) );
L_temp = L_sub(L_tmp, L_dist_min);
if( L_temp < 0L ){
L_dist_min = L_tmp;
index1 = add(cand1,i);
index2 = add(cand2,j);
}
}
}
}
得到搜索结果
//
/* Read the quantized gain */
/*-----------------------------------------------------------------*
* *gain_pit = gbk1[indice1][0] + gbk2[indice2][0]; *
*-----------------------------------------------------------------*/
*gain_pit = add( gbk1[index1][0], gbk2[index2][0] ); /* Q14 */
/*-----------------------------------------------------------------*
* *gain_code = (gbk1[indice1][1]+gbk2[indice2][1]) * gcode0; *
*-----------------------------------------------------------------*/
L_acc = L_deposit_l( gbk1[index1][1] );
L_accb = L_deposit_l( gbk2[index2][1] );
L_gbk12 = L_add( L_acc, L_accb ); /* Q13 */
tmp = extract_l( L_shr( L_gbk12,1 ) ); /* Q12 */
L_acc = L_mult(tmp, gcode0); /* Q[exp_gcode0+12+1] */
L_acc = L_shl(L_acc, add( negate(exp_gcode0),(-12-1+1+16) ));
*gain_cod = extract_h( L_acc );
更新量化器参数
U^{(m)}=E^{(m)}-\tilde{E}^{(m)}=20\log{(\gamma)}
\gamma=L\_gbk12=gbk1[index1][1]+gbk2[index2][1]
// gainpred.c->Gain_update()
for(i=3; i>0; i--){ // 更新量化能量误差记录
past_qua_en[i] = past_qua_en[i-1]; /* Q10 */
}
/*----------------------------------------------------------------------*
* -- past_qua_en[0] = 20*log10(gbk1[index1][1]+gbk2[index2][1]); -- *
* 2 * 10 log10( gbk1[index1][1]+gbk2[index2][1] ) *
* = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] ) *
* = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] ) *
* 24660:Q12(6.0205) *
*----------------------------------------------------------------------*/
Log2( L_gbk12, &exp, &frac ); /* L_gbk12:Q13 */
L_acc = L_Comp( sub(exp,13), frac); /* L_acc:Q16 */ // DPF->WORD32
tmp = extract_h( L_shl( L_acc,13 ) ); /* tmp:Q13 */
past_qua_en[0] = mult( tmp, 24660 ); /* past_qua_en[]:Q10 */
更新sharp
/*------------------------------------------------------------*
* - Update pitch sharpening "sharp" with quantized gain_pit *
*------------------------------------------------------------*/
sharp = gain_pit;
if (sub(sharp, SHARPMAX) > 0) { sharp = SHARPMAX; }
if (sub(sharp, SHARPMIN) < 0) { sharp = SHARPMIN; }
子帧搜索后处理
为下一子帧处理做准备。
//--
/*------------------------------------------------------*
* - Find the total excitation *
* - find synthesis speech corresponding to exc[] *
* - update filters memories for finding the target *
* vector in the next subframe *
* (update error[-m..-1] and mem_w_err[]) *
* update error function for taming process *
*------------------------------------------------------*/
for (i = 0; i < L_SUBFR; i++)
{
/* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */
/* exc[i] in Q0 gain_pit in Q14 */
/* code[i] in Q13 gain_cod in Q1 */
L_temp = L_mult(exc[i+i_subfr], gain_pit);
L_temp = L_mac(L_temp, code[i], gain_code);
L_temp = L_shl(L_temp, 1);
exc[i+i_subfr] = round(L_temp);
}
update_exc_err(gain_pit, T0);
Syn_filt(Aq, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem_syn, 1);
for (i = L_SUBFR-M, j = 0; i < L_SUBFR; i++, j++)
{
mem_err[j] = sub(speech[i_subfr+i], synth[i_subfr+i]);
temp = extract_h(L_shl( L_mult(y1[i], gain_pit), 1) );
k = extract_h(L_shl( L_mult(y2[i], gain_code), 2) );
mem_w0[j] = sub(xn[i], add(temp, k));
}
// MP1=M+1,M为LP滤波器阶数
A += MP1; /* interpolated LPC parameters for next subframe */
Aq += MP1;
计算总的激励
计算自适应码字误差
计算编码端和解码段自适应码字的误差。
L_worst = -1L;
n = sub(T0, L_SUBFR);
if(n < 0) { // 基音延迟小于子帧长度
L_Extract(L_exc_err[0], &hi, &lo);
L_temp = Mpy_32_16(hi, lo, gain_pit); // L_exc_err[0]*gain_pit(基音增益)
L_temp = L_shl(L_temp, 1);
L_temp = L_add(0x00004000L, L_temp); // L_exc_err[0]*gain_pit*2 - L_worst
L_acc = L_sub(L_temp, L_worst);
if(L_acc > 0L) {
L_worst = L_temp;
}
L_Extract(L_temp, &hi, &lo);
L_temp = Mpy_32_16(hi, lo, gain_pit);
L_temp = L_shl(L_temp, 1);
L_temp = L_add(0x00004000L, L_temp); // L_temp[0]*gain_pit*2 - L_worst
L_acc = L_sub(L_temp, L_worst);
if(L_acc > 0L) {
L_worst = L_temp;
}
} else { // 基音延迟大于子帧长度
zone1 = tab_zone[n]; // Table for taming procedure test_err.
i = sub(T0, 1);
zone2 = tab_zone[i];
for(i = zone1; i <= zone2; i++) {
L_Extract(L_exc_err[i], &hi, &lo);
L_temp = Mpy_32_16(hi, lo, gain_pit);
L_temp = L_shl(L_temp, 1);
L_temp = L_add(0x00004000L, L_temp);
L_acc = L_sub(L_temp, L_worst);
if(L_acc > 0L) {
L_worst = L_temp;
}
}
}
for(i=3; i>=1; i--) {
L_exc_err[i] = L_exc_err[i-1];
}
L_exc_err[0] = L_worst;
更新滤波器状态
//
// 得到语音合成结果
Syn_filt(Aq, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem_syn, 1);
for (i = L_SUBFR-M, j = 0; i < L_SUBFR; i++, j++) // M:LP滤波器借书
{
mem_err[j] = sub(speech[i_subfr+i], synth[i_subfr+i]); // 合成误差
temp = extract_h(L_shl( L_mult(y1[i], gain_pit), 1) ); // (y1[i]*gain_pit)*2
k = extract_h(L_shl( L_mult(y2[i], gain_code), 2) ); // (y2[i]*gain_code)*4
mem_w0[j] = sub(xn[i], add(temp, k)); // xn[i] - (temp + k)
}
存储更新
为下一帧做准备
// Copy vector x[] to y[]
void Copy(
Word16 x[], /* (i) : input vector */
Word16 y[], /* (o) : output vector */
Word16 L /* (i) : vector length */
)
/*--------------------------------------------------*
* Update signal for next frame. *
* -> shift to the left by L_FRAME: *
* speech[], wsp[] and exc[] *
*--------------------------------------------------*/
Copy(&old_speech[L_FRAME], &old_speech[0], L_TOTAL-L_FRAME);
Copy(&old_wsp[L_FRAME], &old_wsp[0], PIT_MAX);
Copy(&old_exc[L_FRAME], &old_exc[0], PIT_MAX+L_INTERPOL);