📄 g729ev_tdac_lib_vq.c
字号:
/* ITU-T G.729EV Optimization/Characterization Candidate *//* Version: 1.0.a *//* Revision Date: June 28, 2006 *//* ITU-T G.729EV Optimization/Characterization Candidate ANSI-C Source Code Copyright (c) 2006 France Telecom, Matsushita Electric, Mindspeed, Siemens AG, ETRI, VoiceAge Corp. All rights reserved*/#include <stdlib.h>#include "G729EV_MAIN_defines.h"#include "G729EV_TDAC_lib_vq.h"#include "G729EV_TDAC_util.h"#include "G729EV_MAIN_OPER_32B.h"#include "stl.h"/*--------------------------------------------------------------------------* * Function G729EV_TDAC_VQ_quant() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Encode TDAC subband by spherical vector quantization * *--------------------------------------------------------------------------*/void G729EV_TDAC_VQ_quant(Word16 * x, /* (i) subband coefficients */ Word16 dim, /* (i) subband dimension */ Word16 nbit, /* (i) number of bits for spherical vector quantization */ UWord32 * cod /* (o) vector quantization index */ ){ Word16 tab_pos[G729EV_TDAC_N_NBC]; Word16 tab_sgn[G729EV_TDAC_N_NBC]; Word16 xn[G729EV_TDAC_N_NBC]; Word16 idic, nb_lead, ivq; /* identify codebook in dimension 'dim' with 'nbit' bits */ G729EV_TDAC_SrchDic(dim, nbit, &idic); /* compute absolute vector 'xn' as well as permutation ('tab_pos') and signs of components ('tab_sgn') */ G729EV_TDAC_SrchLead(x, dim, tab_pos, tab_sgn, xn); /* get the number of absolute leaders in the codebook 'idic' */ nb_lead = (Word16) G729EV_TDAC_getNbLead(dim, idic); /* find the best match (dot product maximization due to spherical VQ) */ G729EV_TDAC_VQLead(xn, dim, &ivq, nb_lead); /* compute the index of reconstructed vector as 'cod' = cardinality offset + rank of signed permutation */ *cod = G729EV_TDAC_schalk(dim, ivq, tab_pos, tab_sgn);#if(WMOPS) move32();#endif return;}/*--------------------------------------------------------------------------* * Function G729EV_TDAC_schalk() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Compute permutation rank by Schalkwijk's formula * *--------------------------------------------------------------------------*/UWord32 G729EV_TDAC_schalk(Word16 n, /* (i) dimension */ Word16 ind_lead, /* (i) index of leader */ Word16 * tab_pos, /* (i) permutation table */ Word16 * tab_sgn /* (i) sign table */ ){ UWord32 code, offset_lead /*, code0 */ ; UWord32 UL_rank; Word32 L_rank, L_prod; const Word16 *ptr, *ptr_fact; Word16 w[G729EV_TDAC_N_NBC + 1], D[G729EV_TDAC_N_NBC + 1]; Word16 exp[G729EV_TDAC_MAX_NB_PRM_FACT], prod_fact[G729EV_TDAC_MAX_NB_PRM_FACT]; Word16 tab_values_online[G729EV_TDAC_N_NBC]; Word16 tab_nb_values_online[G729EV_TDAC_N_NBC]; Word16 nb_sgn, sum_w; Word16 k, i, d, nb_val, j, imin, pos, delta, nb_prm_fact, d0; Word16 tmp; Word16 index; Word16 *ptr_nb_val, *ptr_pos, *ptr_val; ptr_val = tab_values_online; ptr_nb_val = tab_nb_values_online; /* get pointers to alphabet (values) and weight of sequence, size of alphabet, */ /* cardinality offset, dimension of leader */ nb_val = (Word16) G729EV_TDAC_getInfoLead(n, ind_lead, &ptr_nb_val, &ptr_val, &offset_lead, &nb_sgn); /* translate sequence into the alphabet 0, 1, 2, nb_val-1 */ /* the letter 0 is added in the alphabet when n > dimension of leader = nb_sgn */ ptr_pos = tab_pos; FOR(d = 0; d < nb_val; d++) { w[d] = ptr_nb_val[d];#if(WMOPS) move16();#endif /* sort positions in increasing order for the current letter of the alphabet */ /* (for sign encoding) */ FOR(i = 0; i < w[d]; i++) { pos = ptr_pos[i]; imin = i;#if(WMOPS) move16(); move16();#endif FOR(j = add(i, 1); j < w[d]; j++) { tmp = sub(ptr_pos[j], pos); if (tmp < 0) { pos = ptr_pos[j]; imin = j;#if(WMOPS) move16(); move16();#endif } } ptr_pos[imin] = ptr_pos[i]; ptr_pos[i] = pos; D[pos] = d;#if(WMOPS) move16(); move16(); move16();#endif } ptr_pos += w[d]; /* pointer incrementation */#if(WMOPS) move16();#endif } i = sub(n, nb_sgn); IF(i > 0) { FOR(k = nb_sgn; k < n; k++) { pos = tab_pos[k]; D[pos] = nb_val;#if(WMOPS) move16(); move16();#endif } nb_val = add(nb_val, 1); } /* ---------- compute rank using Schalkwijk's formula */ /* get the number of prime factors */ nb_prm_fact = G729EV_TDAC_tab_nb_prm_fact[n];#if(WMOPS) move16();#endif /* initialize */ L_rank = (Word32) 0;#if(WMOPS) move32();#endif FOR(d = 0; d < nb_val; d++) { w[d] = (Word16) 0;#if(WMOPS) move16();#endif } FOR(i = 0; i < nb_prm_fact; i++) { prod_fact[i] = (Word16) 0;#if(WMOPS) move16();#endif } /* treat k=n-1 apart : sum_w = 0 if d=0, and if d>0 w[0]+...+w[d-1]=0 since only w[d]=1 */ k = sub(n, 1); d0 = D[k]; w[d0] = (Word16) 1;#if(WMOPS) move16(); move16();#endif /* treat k=n-2 apart */ k = sub(n, 2); d = D[k];#if(WMOPS) move16();#endif w[d] = add(w[d], 1); tmp = sub(d, d0); IF(tmp == 0) { prod_fact[0] = (Word16) 1; /* prod_fact = 2^1; */#if(WMOPS) move16();#endif } ELSE { if (tmp > 0) { L_rank = (Word32) 1;#if(WMOPS) move32();#endif } } /* treat other cases: k=n-3...0 */ FOR(i = nb_prm_fact; i < G729EV_TDAC_MAX_NB_PRM_FACT; i++) { exp[i] = (Word16) 0;#if(WMOPS) move16();#endif } FOR(k = sub(n, 3); k >= 0; k--) { d = D[k];#if(WMOPS) move16();#endif w[d] = add(w[d], 1); /* prod_fact = prod_fact * w[d] */ i = w[d]; delta = G729EV_TDAC_delta_decomp_val[i]; ptr = G729EV_TDAC_tab_decomp_val + delta; /* pointer incrementation */#if(WMOPS) move16(); move16(); move16();#endif FOR(i = 0; i < nb_prm_fact; i++) { prod_fact[i] = add(prod_fact[i], *ptr++); } /* compute sum */ sum_w = (Word16) 0;#if(WMOPS) move16();#endif FOR(i = 0; i < d; i++) { sum_w = add(sum_w, w[i]); } /* update rank */ IF(sum_w > 0) { /* compute the prime factor decomposition of fact*sum_w/prod_fact */ index = sub(n, k); index = sub(index, 1); delta = G729EV_TDAC_delta_decomp_val[index]; /* move */ ptr_fact = G729EV_TDAC_tab_decomp_fact + delta; /* pointer incrementation */ delta = G729EV_TDAC_delta_decomp_val[sum_w]; /* move */ ptr = G729EV_TDAC_tab_decomp_val + delta; /* pointer incrementation */#if(WMOPS) move16(); move16();#endif FOR(i = 0; i < nb_prm_fact; i++) { tmp = add(*ptr++, *ptr_fact++); exp[i] = sub(tmp, prod_fact[i]);#if(WMOPS) move16();#endif } /* compute the product of powers */ L_prod = G729EV_TDAC_prod_prm_fact(exp); /* accumulate intermediate term */ L_rank = L_add(L_rank, L_prod); } } /* >>>>> switch to unsigned arithmetic */ /* ------- sign encoding */ UL_rank = L_rank; /* no count (unsigned arithmetic switching - variable renamed for the sake of clarity) */#if(WMOPS) move32();#endif FOR(i = 0; i < nb_sgn; i++) { UL_rank = L_shl(UL_rank, 1); pos = tab_pos[i];#if(WMOPS) move16();#endif if (tab_sgn[pos] < 0) { UL_rank = L_add(UL_rank, 1); } } /* -------- compute index in the codebook */ code = UL_add(offset_lead, UL_rank); return (code);}/*--------------------------------------------------------------------------* * Function G729EV_TDAC_SrchDic() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Select codebook for a given dimension and bit allocation * *--------------------------------------------------------------------------*/void G729EV_TDAC_SrchDic(Word16 dim, /* (i) dimension */ Word16 nbit, /* (i) bit allocation */ Word16 * IdicSel /* (o) index of selected codebook */ ){ const Word16 *ptr; Word16 i, tmp, nb; ptr = G729EV_MAIN_adRate[dim]; nb = G729EV_MAIN_NbDic[dim]; *IdicSel = (Word16) 0;#if(WMOPS) move16(); move16();#endif FOR(i = 1; i < nb; i++) { tmp = sub(ptr[i], nbit); if (tmp == 0) { *IdicSel = i;#if(WMOPS) move16();#endif } }}/*--------------------------------------------------------------------------* * Function G729EV_TDAC_SrchLead() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Compute absolute vector * *--------------------------------------------------------------------------*/void G729EV_TDAC_SrchLead(Word16 * x, /* (i) subband coefficients */ Word16 dim, /* (i) dimension */ Word16 * tab_pos, /* (o) permutation table */ Word16 * tab_sgn, /* (o) sign table */ Word16 * xn /* (o) absolute vector */ ){ Word16 max_value, temp, d, i, j, k, imax; /* compute absolute vector xn and initialize permutation table */ FOR(j = 0; j < dim; j++) { tab_pos[j] = j;#if(WMOPS) move16();#endif IF(x[j] < 0) { tab_sgn[j] = (Word16) - 1; xn[j] = negate(x[j]);#if(WMOPS) move16(); move16();#endif } ELSE { tab_sgn[j] = (Word16) 0; xn[j] = x[j];#if(WMOPS) move16(); move16();#endif } } /* compute absolute leader: ordering of xn in decreasing values */ FOR(k = 0; k < dim; k++) { max_value = xn[k]; imax = k;#if(WMOPS) move16(); move16();#endif temp = add(k, 1); FOR(i = temp; i < dim; i++) { d = sub(xn[i], max_value); IF(d > 0) { max_value = xn[i]; imax = i;#if(WMOPS) move16(); move16();#endif } } xn[imax] = xn[k]; xn[k] = max_value; i = tab_pos[k]; tab_pos[k] = tab_pos[imax]; tab_pos[imax] = i;#if(WMOPS) move16(); move16(); move16(); move16(); move16();#endif } return;}/*--------------------------------------------------------------------------* * Function G729EV_TDAC_getNbLead() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Get number of leaders in a codebook * *--------------------------------------------------------------------------*/Word16 G729EV_TDAC_getNbLead(Word16 dim, /* (i) dimension */ Word16 idic /* (i) index of codebook */ ){ const Word16 *ptr1; ptr1 = G729EV_MAIN_adNbLeadpRat[dim]; return (ptr1[idic]);}/*--------------------------------------------------------------------------* * Function G729EV_TDAC_VQLead() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Search for best spherical codevector * *--------------------------------------------------------------------------*/void G729EV_TDAC_VQLead(Word16 * xn, /* (i) absolute vector */ Word16 dim, /* (i) dimension */ Word16 * ILead, /* (o) index of selected leader */ Word16 ivq1 /* (i) number of candidate leaders */ ){ Word32 dist_max; Word32 ps; Word32 L_tmp; const Word16 *leader, *ptr1; Word16 *ptr2; Word16 i, k, delta; Word16 ivq; Word16 dim_lead, jlead; /* set initial survivor */ L_tmp = L_deposit_l(xn[0]); dist_max = L_shl(L_tmp, 15); ivq = (Word16) 0;#if(WMOPS) move16();#endif /* loop over other candidate */ FOR(k = 1; k < ivq1; k++) { jlead = *(G729EV_MAIN_adListLead[dim] + k); dim_lead = G729EV_MAIN_dim_leader[jlead]; delta = G729EV_MAIN_delta_leader[jlead]; leader = G729EV_MAIN_adLeader_norm[dim_lead] + delta; /* pointer incrementation */#if(WMOPS) move16(); move16(); move16();#endif /* compute normalized dot product (32 bit result) */ ptr1 = leader; /* 1Q14 */ ptr2 = xn; /* 13Q2 */ ps = L_mult(*ptr1++, *ptr2++); FOR(i = 1; i < dim_lead; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -