/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include "prot.h" #include "rom_com.h" #include "cnst.h" /*-----------------------------------------------------------------* * Local functions *-----------------------------------------------------------------*/ static float quantize_data( float *data, const float *w_in, float *qin, float *cv_out, int *idx_lead, int *idx_scale, const float *sigma, const float * inv_sigma, const float *scales, short no_scales, const int *no_lead ); static float q_data( float *pTmp1, const float *w1, float *quant, float *cv_out, int *idx_lead, int *idx_scale, const float * p_inv_sigma, const float *p_sigma, const float *p_scales, short *p_no_scales, const int *p_no_lead ); static void prepare_data( float *xsort, int *sign, float *data, float *w, const float *w_in, const float * sigma, const float * inv_sigma, int *p_sig ); static float calculate_min_dist( float cv_pot[LATTICE_DIM], int no_scales, const float *scale, const float *w, int *p_best_scale, int *p_best_idx, const int *no_leaders, int sig, int * indx); static int find_pos( float *c, int len, float arg, int *p ); static void take_out_val( float *v, float *v_out, float val, int len ); static int index_leaders( float *cv, int idx_lead, int dim ); static int c2idx( int n, int *p, int k ); static int encode_sign_pc1( int parity, float *cv); static int encode_comb( float *cv, int idx_lead ); static void sort_desc_ind( float *s, int len, int *ind ); /*-----------------------------------------------------------------* * mslvq() * * Encodes the LSF residual *-----------------------------------------------------------------*/ float mslvq ( float *pTmp, /* i : M-dimensional input vector */ float *quant, /* o : quantized vector */ float *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ int *idx_lead, /* o : leader index for each 8-dim subvector */ int *idx_scale, /* o : scale index for each subvector */ float *w, /* i : weights for LSF quantization */ short mode, /* i : number indicating the coding type (V/UV/G...)*/ short mode_glb, /* i : LVQ coding mode */ int pred_flag, /* i : prediction flag (0: safety net, 1,2 - predictive )*/ short no_scales[][2] ) { float dist; const float * p_scales, *p_sigma ,*p_inv_sigma ; const int *p_no_lead; short * p_no_scales; dist = 0.0f; p_no_scales = no_scales[mode_glb]; if ( pred_flag == 0 ) { p_sigma = sigma[mode]; /* inverse sigma is precomputed to save complexity */ p_inv_sigma = inv_sigma[mode]; p_scales = scales[mode_glb]; p_no_lead = no_lead[mode_glb]; } else { p_sigma = sigma_p[mode]; /* inverse sigma is precomputed to save complexity */ p_inv_sigma = inv_sigma_p[mode]; p_scales = scales_p[mode_glb]; p_no_lead = no_lead_p[mode_glb]; } /* first subvector */ dist += quantize_data( pTmp, w, quant, cv_out, idx_lead, idx_scale, p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); /* second subvector */ dist += quantize_data( pTmp+LATTICE_DIM, w+LATTICE_DIM, quant+LATTICE_DIM, cv_out+LATTICE_DIM, &idx_lead[1], &idx_scale[1], p_sigma+LATTICE_DIM, p_inv_sigma+LATTICE_DIM, p_scales+MAX_NO_SCALES, p_no_scales[1], p_no_lead+MAX_NO_SCALES ); return dist; } /*-----------------------------------------------------------------* * q_data() * * (used for LSF quantization in CNG) *-----------------------------------------------------------------*/ static float q_data ( float *pTmp1, const float *w1, float *quant, float *cv_out, int *idx_lead, int *idx_scale, const float *p_sigma, const float *p_inv_sigma, const float *p_scales, short *p_no_scales, const int *p_no_lead ) { float dist = 0.0f; /* first subvector */ dist += quantize_data( pTmp1, w1, quant, cv_out, idx_lead, idx_scale, p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); /* second subvector */ dist += quantize_data( pTmp1+LATTICE_DIM, w1+LATTICE_DIM, quant+LATTICE_DIM, cv_out+LATTICE_DIM, &idx_lead[1], &idx_scale[1], p_sigma+LATTICE_DIM,p_inv_sigma+LATTICE_DIM, p_scales+MAX_NO_SCALES, p_no_scales[1], p_no_lead+MAX_NO_SCALES ); return dist; } /*-----------------------------------------------------------------* * mslvq_cng() * * Encodes the LSF residual in SID frames *-----------------------------------------------------------------*/ float mslvq_cng ( short idx_cv, /* i : index of cv from previous stage */ float *pTmp, /* i : 16 dimensional input vector */ float *quant, /* o : quantized vector */ float *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ int *idx_lead, /* o : leader index for each 8-dim subvector */ int *idx_scale, /* o : scale index for each subvector */ const float *w, /* i : weights for LSF quantization */ short * no_scales ) { float dist; const float *p_scales, *p_sigma , *p_inv_sigma ; const int *p_no_lead; short *p_no_scales; short mode_glb, mode, i; float pTmp1[M], w1[M]; dist = 0.0f; mode = (short)LVQ_COD_MODES + idx_cv; /* for CNG there is only one bitrate but several quantizer structures, depending on the previous VQ stage */ mode_glb = START_CNG + idx_cv; p_sigma = sigma[mode]; p_inv_sigma = inv_sigma[mode]; p_scales = scales[mode_glb]; p_no_lead = no_lead[mode_glb]; p_no_scales = &no_scales[mode_glb*2]; /* check if LSF component permutation is needed or not */ if ( cng_sort[idx_cv] ) { /* change order in subvecs */ for( i=0; i0) { prepare_data( cv_pot, sign, data, w, w_in, sigma, inv_sigma, &sig ); /* sorting of the input vector based on its absolute values; indx: permutation corresponding to the sorting */ sort_desc_ind(cv_pot, LATTICE_DIM, indx); smallest = indx[LATTICE_DIM-1]; min_dist = calculate_min_dist(cv_pot, no_scales, scale, w, &best_scale, &best_idx, no_leaders, sig, indx); if (best_scale > -1) { for(j=0; j -1 ) { index1 = encode_comb(quant, idx_lead[0]) + table_no_cv[idx_lead[0]] + p_offset_scale1[mode*len_offset +idx_scale[0]]; } /* for second subvector */ index2 = 0; if ( idx_scale[1] > -1 ) { index2 = encode_comb(&quant[LATTICE_DIM], idx_lead[1]) + table_no_cv[idx_lead[1]] + p_offset_scale2[mode*len_offset+idx_scale[1]]; } multiply32_32_64(index1, (unsigned int)(p_offset_scale2[mode*len_offset+p_no_scales[mode*2+1]]), idx); tmp = idx[0] + index2; if ( tmp < idx[0] || tmp < index2 ) { idx[1] +=1; } idx[0] = tmp; /* convert to 3 short */ index[0] = ((idx[0])&(0xffff>>1)); index[1] = ((idx[0])>>15)&(0xffff>>1); index[2] = ((idx[0])>>30) + (((idx[1])<<2)&(0xffff>>1)); return; } /*-----------------------------------------------------------------* * encode_comb() * * creates an index for the lattice codevector *-----------------------------------------------------------------*/ static int encode_comb( /* o : index of the absolute valued codevector */ float *cv, /* i : codevector to be indexed */ int idx_lead /* i : leader class index, to know the values */ ) { int idx_sign, idx_ld_class; idx_sign = encode_sign_pc1( pl_par[idx_lead], cv ); idx_ld_class = index_leaders( cv, idx_lead, LATTICE_DIM ); return idx_sign * pi0[idx_lead] + idx_ld_class; } /*-----------------------------------------------------------------* * index_leaders() * * gives the index in a class of leaders without considering the sign yet *-----------------------------------------------------------------*/ static int index_leaders( /* o : index */ float *cv, /* i : codevector to be indexed */ int idx_lead, /* i : leader class index */ int dim /* i : vector dimension */ ) { int index, i, no_vals_loc, nr, p[LATTICE_DIM], dim_loc; float cv_copy[LATTICE_DIM], val_crt; no_vals_loc = no_vals[idx_lead]; if ( no_vals_loc == 1 ) { return 0; } for( i=0; i 0 ) { cnt ++; } } return idx_sign; } /*-----------------------------------------------------------------* * take_out_val() * * removes the value val from the vector v *-----------------------------------------------------------------*/ static void take_out_val( float *v, /* i : input vector */ float *v_out, /* o : output vector without the value val*/ float val, /* i : value to be removed */ int len /* i : input vector length */ ) { int i, cnt; cnt = 0; for( i=0; i