www.pudn.com > SMV_Code.rar > lib_gcb.c
/*=========================================================================*/
/* Each of the companies; Ericsson, Lucent, Mindspeed, Motorola, Nokia, */
/* Nortel Networks, and Qualcomm (hereinafter referred to individually as */
/* “Source” or collectively as “Sources”) do hereby state: */
/* */
/* To the extent to which the Source(s) may legally and freely do so, */
/* the Source(s), upon submission of a Contribution, grant(s) a free, */
/* irrevocable, non-exclusive, license to the Third Generation Partnership */
/* Project 2 (3GPP2) and its Organizational Partners: ARIB, CCSA, TIA, */
/* TTA, and TTC, under the Source’s copyright or copyright license rights */
/* in the Contribution, to, in whole or in part, copy, make derivative */
/* works, perform, display and distribute the Contribution and derivative */
/* works thereof consistent with 3GPP2’s and each Organizational Partner’s */
/* policies and procedures, with the right to (i) sublicense the foregoing */
/* rights consistent with 3GPP2’s and each Organizational Partner’s */
/* policies and procedures and (ii) copyright and sell, if applicable) in */
/* 3GPP2's name or each Organizational Partner’s name any 3GPP2 or */
/* transposed Publication even though this Publication may contain the */
/* Contribution or a derivative work thereof. The Contribution shall */
/* disclose any known limitations on the Source’s rights to license as */
/* herein provided. */
/* */
/* When a Contribution is submitted by the Source(s) to assist the */
/* formulating groups of 3GPP2 or any of its Organizational Partners, */
/* it is proposed to the Committee as a basis for discussion and is not */
/* to be construed as a binding proposal on the Source(s). The Source(s) */
/* specifically reserve(s) the right to amend or modify the material */
/* contained in the Contribution. Nothing contained in the Contribution */
/* shall, except as herein expressly provided, be construed as conferring */
/* by implication, estoppel or otherwise, any license or right under */
/* (i) any existing or later issuing patent, whether or not the use of */
/* information in the document necessarily employs an invention of any */
/* existing or later issued patent, (ii) any copyright, (iii) any */
/* trademark, or (iv) any other intellectual property right. */
/* */
/* With respect to the Software necessary for the practice of any or all */
/* Normative portions of the Selectable Mode Vocoder (SMV) as it exists on */
/* the date of submittal of this form, should the SMV be approved as a */
/* Specification or Report by 3GPP2, or as a transposed Standard by any of */
/* the 3GPP2’s Organizational Partners, the Source(s) state(s) that a */
/* worldwide license to reproduce, use and distribute the Software, the */
/* license rights to which are held by the Source(s), will be made */
/* available to applicants under terms and conditions that are reasonable */
/* and non-discriminatory, which may include monetary compensation, */
/* and only to the extent necessary for the practice of any or all of the */
/* Normative portions of the SMV or the field of use of practice of the */
/* SMV Specification, Report, or Standard. The statement contained above */
/* is irrevocable and shall be binding upon the Source(s). In the event */
/* the rights of the Source(s) in and to copyright or copyright license */
/* rights subject to such commitment are assigned or transferred, */
/* the Source(s) shall notify the assignee or transferee of the existence */
/* of such commitments. */
/*=========================================================================*/
/* */
/*-------------------------------------------------------------------*/
/*===================================================================*/
/* LIBRARY: lib_gcb.c */
/*-------------------------------------------------------------------*/
/* PURPOSE : Library of CELP processing for gaussian codebooks. */
/*===================================================================*/
/*----------------------------------------------------------------------------*/
/*-------------------------------- INCLUDE -----------------------------------*/
/*----------------------------------------------------------------------------*/
#include "typedef.h"
#include "main.h"
#include "const.h"
#include "gputil.h"
#include "mcutil.h"
#include "ext_var.h"
#include "lib_gcb.h"
#ifdef WMOPS
#include "lib_wmp.h"
#endif
/*----------------------------------------------------------------------------*/
/*---------------------------------- DEFINE ----------------------------------*/
/*----------------------------------------------------------------------------*/
#define TABLE_SIZE 32.0
#define INV_TABLE_SIZE 1.0/32.0
#define GAUSS_AA 25173
#define GAUSS_CC 13849
#define GAUSS_MM 65536
#define UNIF_VAR_NUM 12
#define GAUSS_VEC_SIZE 40
#define MAX_VEC_NUM 2
/*----------------------------------------------------------------------------*/
/*-------------------------------- FUNCTIONS ---------------------------------*/
/*----------------------------------------------------------------------------*/
/*===================================================================*/
/* FUNCTION : GCB_init_lib (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function initialise the global variable of */
/* the library GCB. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void GCB_init_lib (void)
{
#ifdef ENC_CMP
/*-------------------------------------------------------------------*/
/* GCB_gauss_excit */
/*-------------------------------------------------------------------*/
ref_eng_gcb = 0;
fix_rate_mem2 = RATE8_5K;
seed_enc = 0x0E76;
#endif
#ifdef DEC_CMP
/*-------------------------------------------------------------------*/
/* GCB_decode_gauss_cb */
/*-------------------------------------------------------------------*/
seed_exc = 0x5555;
/*-------------------------------------------------------------------*/
/* GCB_gauss_excit_dec */
/*-------------------------------------------------------------------*/
seed_dec = 0x0E76;
#endif
/*-------------------------------------------------------------------*/
return;
/*-------------------------------------------------------------------*/
}
/*----------------------------------------------------------------------------*/
/*===================================================================*/
/* FUNCTION : GCB_decode_gauss_cb (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function extract the gaussian vector from */
/* the codebook. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (INT16 ) N_gauss: gaussian codebook size. */
/* _ (INT16 ) L_vec: gaussian vector size. */
/* _ (INT16 ) index: codebook index. */
/* _ (INT16 ) sign: sign. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (FLOAT64 []) unfcod: unfiltered excitation */
/* vector. */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (INT16 *) seed_exc: seed for excitation in FEC.*/
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void GCB_decode_gauss_cb (INT16 N_gauss, INT16 L_vec, INT16 index,
INT16 sign, FLOAT64 unfcod [],
INT16 *seed_exc)
{
/*-------------------------------------------------------------------*/
INT16 k, delay, table_entry;
FLOAT64 x, *unfcod_p;
/*-------------------------------------------------------------------*/
#ifdef WMOPS
WMP_cnt_test(2);
WMP_cnt_move(1);
#endif
if (index >= N_gauss)
{
index = (INT16)(N_gauss* GCB_quickuran(seed_exc));
x = GCB_quickuran(seed_exc);
if (x < 0.5)
sign = 1;
else
sign = -1;
}
/*-------------------------------------------------------------------*/
if (index < N_gauss)
{
delay = (INT16)(index*INV_TABLE_SIZE);
table_entry = (INT16)(index-delay*TABLE_SIZE);
#ifdef WMOPS
WMP_cnt_move(L_vec);
WMP_cnt_negate(L_vec);
WMP_cnt_add(1);
WMP_cnt_sub(1);
WMP_cnt_shift(1);
WMP_cnt_test(1);
#endif
if (sign == 1)
{
unfcod_p = unfcod - 2*delay;
for (k = delay; k < L_vec; k++)
unfcod_p[2*k] = bv[table_entry][k];
unfcod_p = unfcod + 2*(L_vec - delay);
for(k = 0; k < delay; k++)
unfcod_p[2*k] = bv[table_entry][k];
}
else
{
unfcod_p = unfcod - 2*delay;
for(k = delay; k < L_vec; k++)
unfcod_p[2*k] = -bv[table_entry][k];
unfcod_p = unfcod + 2*(L_vec - delay);
for(k = 0; k < delay; k++)
unfcod_p[2*k] = -bv[table_entry][k];
}
}
else
{
#ifdef VERBOSE
printf("FATAL ERROR: cb index (%d) out of range\n",index);
exit(0);
#endif
}
/*-------------------------------------------------------------------*/
return;
/*-------------------------------------------------------------------*/
}
/*----------------------------------------------------------------------------*/
#ifdef ENC_CMP
/*===================================================================*/
/* FUNCTION : GCB_gauss_cb (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function select the MAX_VEC_NUM gaussian */
/* vectors in the codebooks. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (FLOAT64 []) target: target vector. */
/* _ (FLOAT64 []) res: residual vector. */
/* _ (INT16 ) i_sf: sub-frame index. */
/* _ (INT16 ) l_sf: sub-frame index size. */
/* _ (FLOAT64 []) hh: impulse response. */
/* _ (FLOAT64 *) Criter: maximazed criterium. */
/* _ (INT16 ) N_gauss_1: 1st gaussian codebook size. */
/* _ (INT16 ) N_gauss_2: 2nd gaussian codebook size. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (FLOAT64 []) unfcod : unfiltered excitation */
/* vector. */
/* _ (INT16 []) index: selected codebook indexes. */
/* _ (INT16 []) sign: selected vectors sign. */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void GCB_gauss_cb (FLOAT64 target[], FLOAT64 res[], FLOAT64 hh [],
FLOAT64 *Criter, FLOAT64 unfcod [], INT16 *index,
INT16 sign [], INT16 N_gauss_1, INT16 N_gauss_2)
{
/*-------------------------------------------------------------------*/
INT16 *index1_buf, *sign1_buf;
INT16 *index2_buf, *sign2_buf;
INT16 *index_tmp, *sign_tmp;
FLOAT64 match;
/*-------------------------------------------------------------------*/
/* Temporary Memory Allocation */
/*-------------------------------------------------------------------*/
index1_buf = svector(0, NUM_PRESELECT-1);
index2_buf = svector(0, NUM_PRESELECT-1);
sign1_buf = svector(0, NUM_PRESELECT-1);
sign2_buf = svector(0, NUM_PRESELECT-1);
index_tmp = svector(0, MAX_VEC_NUM-1);
sign_tmp = svector(0, MAX_VEC_NUM-1);
/*-------------------------------------------------------------------*/
/*========================== Preselection ===========================*/
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* First basis vector */
/*-------------------------------------------------------------------*/
GCB_basis_preselect (res, N_gauss_1, GAUSS_VEC_SIZE, index1_buf,
sign1_buf, NUM_PRESELECT);
/*-------------------------------------------------------------------*/
/* Second basis vector */
/*-------------------------------------------------------------------*/
GCB_basis_preselect(res+1, N_gauss_2, GAUSS_VEC_SIZE, index2_buf,
sign2_buf, NUM_PRESELECT);
/*-------------------------------------------------------------------*/
/*=========================== Fine search ===========================*/
/*-------------------------------------------------------------------*/
match = GCB_fine_search (target, hh, index1_buf, sign1_buf,
GAUSS_VEC_SIZE, N_gauss_1, index2_buf,
sign2_buf, GAUSS_VEC_SIZE,
N_gauss_2, NUM_PRESELECT, index_tmp,
sign_tmp);
/*-------------------------------------------------------------------*/
/*========================== Compare match ==========================*/
/*-------------------------------------------------------------------*/
#ifdef WMOPS
WMP_cnt_move(5);
#endif
if(match > (*Criter))
{
(*Criter) = match;
index[0] = index_tmp[0];
index[1] = index_tmp[1];
sign[0] = sign_tmp[0];
sign[1] = sign_tmp[1];
GCB_decode_gauss_cb (N_gauss_1, GAUSS_VEC_SIZE,
index[0], sign[0], unfcod,
(INT16 *)NULL);
GCB_decode_gauss_cb (N_gauss_2, GAUSS_VEC_SIZE,
index[1], sign[1], unfcod+1,
(INT16 *)NULL);
}
/*-------------------------------------------------------------------*/
/* Temporary Memory Dellocation */
/*-------------------------------------------------------------------*/
free_svector(index1_buf, 0, NUM_PRESELECT-1);
free_svector(index2_buf, 0, NUM_PRESELECT-1);
free_svector(sign1_buf, 0, NUM_PRESELECT-1);
free_svector(sign2_buf, 0, NUM_PRESELECT-1);
free_svector(index_tmp, 0, MAX_VEC_NUM-1);
free_svector(sign_tmp, 0, MAX_VEC_NUM-1);
/*-------------------------------------------------------------------*/
return;
/*-------------------------------------------------------------------*/
}
/*----------------------------------------------------------------------------*/
/*===================================================================*/
/* FUNCTION : GCB_basis_preselect (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function pre-select the 2 gaussian vectors */
/* in the codebooks. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (FLOAT64 []) res : residual vector. */
/* _ (INT16 ) N_gauss : gaussian codebook size. */
/* _ (INT16 ) L_vec : gaussian vector size. */
/* _ (INT16 ) skip_fac: skip factor. */
/* _ (INT16 ) num_preselect: number of pre-selected */
/* candidates. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (INT16 []) index_buf: codebook index buffer. */
/* _ (INT16 []) sign_buf: codebook sign buffer. */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void GCB_basis_preselect (FLOAT64 res[], INT16 N_gauss, INT16 L_vec,
INT16 index_buf [], INT16 sign_buf [],
INT16 num_preselect)
{
/*-------------------------------------------------------------------*/
INT16 i, j, table_entry, delay;
FLOAT64 *res_p;
INT16 *sign;
FLOAT64 *tstnum;
/*-------------------------------------------------------------------*/
/* Allocate the temporary memory */
/*-------------------------------------------------------------------*/
sign = svector (0, N_gauss-1);
tstnum = dvector (0, N_gauss-1);
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* Preselection of the basis vectors */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* calculate distortions and find first best match in the same loop */
/*-------------------------------------------------------------------*/
#ifdef WMOPS
WMP_cnt_move(1);
#endif
index_buf[num_preselect-1] = 0;
for (i = 0; i < N_gauss; i++)
{
delay = (INT16)(i*INV_TABLE_SIZE);
table_entry = (INT16)(i-delay*TABLE_SIZE);
/*------------------------------------------------------------*/
/* Correlation between target and codebook vector */
/*------------------------------------------------------------*/
res_p = res - 2*delay;
#ifdef WMOPS
WMP_cnt_mac(L_vec);
WMP_cnt_move(4);
WMP_cnt_add(1);
WMP_cnt_sub(1);
WMP_cnt_shift(1);
WMP_cnt_test(1);
#endif
for(tstnum[i]=0.0, j=delay; j= 0.0)
sign[i] = 1;
else{
sign[i] = -1;
tstnum[i] = -tstnum[i];
}
#ifdef WMOPS
WMP_cnt_test(1);
WMP_cnt_move(1);
#endif
if (tstnum[i] > tstnum[index_buf[num_preselect-1]]){
index_buf[num_preselect-1] = i;
}
}
#ifdef WMOPS
WMP_cnt_move(1);
#endif
sign_buf[num_preselect-1] = sign[index_buf[num_preselect-1]];
/*-------------------------------------------------------------------*/
/* find remaining best match */
/* Note, since num_preselect=2, this loop can be removed by j=0 */
/*-------------------------------------------------------------------*/
for(j=num_preselect-2; j>=0; j--){
#ifdef WMOPS
WMP_cnt_move(2);
#endif
tstnum[index_buf[j+1]] = -1.0;
index_buf[j] = 0;
for (i = 0; i < N_gauss; i++)
{
#ifdef WMOPS
WMP_cnt_test(1);
WMP_cnt_move(1);
#endif
if (tstnum[i] > tstnum[index_buf[j]]){
index_buf[j] = i;
}
}
#ifdef WMOPS
WMP_cnt_move(1);
#endif
sign_buf[j] = sign[index_buf[j]];
}
/*-------------------------------------------------------------------*/
/* Free the temporary memory */
/*-------------------------------------------------------------------*/
free_svector (sign , 0, N_gauss-1);
free_dvector (tstnum, 0, N_gauss-1);
/*-------------------------------------------------------------------*/
return;
/*-------------------------------------------------------------------*/
}
/*----------------------------------------------------------------------------*/
/*===================================================================*/
/* FUNCTION : GCB_fine_search (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function pre-select the 2 gaussian vectors */
/* in the codebooks. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (FLOAT64 []) target: taget vector. */
/* _ (FLOAT64 []) hh: impulse response. */
/* _ (INT16 []) index1: 1st codebook vector */
/* indexes. */
/* _ (INT16 []) sign1: 1st codebook vector signs.*/
/* _ (INT16 ) l1: 1st gaussian vector size. */
/* _ (INT16 ) N1: 1st gaussian codebook */
/* size. */
/* _ (INT16 []) index2: 2nd codebook vector */
/* indexes. */
/* _ (INT16 []) sign2: 2nd codebook vector signs.*/
/* _ (INT16 ) l2: 2nd gaussian vector size. */
/* _ (INT16 ) N2: 2nd gaussian codebook */
/* size. */
/* _ (INT16 ) num_preselect: number of pre-selected */
/* vectors. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (INT16 []) index_tmp: selected codebook vector */
/* indexes. */
/* _ (INT16 []) sign_tmp: selected codebook vector */
/* signs. */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ (FLOAT64 ) tmax : maximized criterion. */
/*===================================================================*/
FLOAT64 GCB_fine_search (FLOAT64 target [], FLOAT64 hh [],
INT16 *index1, INT16 *sign1, INT16 l1, INT16 N1,
INT16 *index2, INT16 *sign2, INT16 l2, INT16 N2,
INT16 num_preselect, INT16 *index_tmp,
INT16 *sign_tmp)
{
/*-------------------------------------------------------------------*/
INT16 i1, i2, l_sf;
FLOAT64 unfcod_tmp[L_SF], fcod_tmp[L_SF], tstden, tstnum, x, tmax;
FLOAT64 **fcod_cand1, **fcod_cand2;
/*-------------------------------------------------------------------*/
/* Allocate temporary memory */
/*-------------------------------------------------------------------*/
fcod_cand1 = dmatrix (0, num_preselect-1, 0, L_SF-1);
fcod_cand2 = dmatrix (0, num_preselect-1, 0, L_SF-1);
/*-------------------------------------------------------------------*/
l_sf = l1 + l2;
/*-------------------------------------------------------------------*/
tmax = -1.0;
/*------------------------------------------------------------------*/
/* Filter the orthogonal basis vectors separately */
/*------------------------------------------------------------------*/
for (i1 = 0; i1 < num_preselect; i1++)
{
GCB_decode_gauss_cb (N1, l1, index1[i1], sign1[i1],
unfcod_tmp, (INT16 *)NULL);
GCB_decode_gauss_cb (N2, l2, index2[i1], sign2[i1],
unfcod_tmp+1, (INT16 *)NULL);
GCB_orthogonal_convolve(unfcod_tmp , hh, fcod_cand1[i1], l1,
fcod_cand2[i1], l2, l_sf);
}
#ifdef WMOPS
WMP_cnt_test((num_preselect*num_preselect-1));
WMP_cnt_move(5*(num_preselect*num_preselect-1));
WMP_cnt_mult((num_preselect*num_preselect-1));
/* do cross multiplication instead of division */
WMP_cnt_mult(2*(num_preselect*num_preselect-1));
WMP_cnt_move((num_preselect*num_preselect-1));
#endif
for (i1=0; i1 tmax)
{
tmax = x;
index_tmp[0] = index1[i1];
index_tmp[1] = index2[i2];
sign_tmp[0] = sign1[i1];
sign_tmp[1] = sign2[i2];
}
/*-------------------------------------------------------*/
}
/*---------------------------------------------------------*/
}
/*-------------------------------------------------------------------*/
/* Free the temporary memory */
/*-------------------------------------------------------------------*/
free_dmatrix (fcod_cand1, 0, num_preselect-1, 0, L_SF-1);
free_dmatrix (fcod_cand2, 0, num_preselect-1, 0, L_SF-1);
/*-------------------------------------------------------------------*/
return tmax;
/*-------------------------------------------------------------------*/
}
/*----------------------------------------------------------------------------*/
/*===================================================================*/
/* FUNCTION : GCB_orthogonal_convolve (). */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function performs a low complexity */
/* concolution of candidate excitation vectors */
/* by exploiting the comb structure. */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (FLOAT64 []) unfcod_tmp: gaussian excitation (both */
/* 1st and 2nd basis vector. */
/* _ (FLOAT64 []) hh: impulse response. */
/* _ (INT16 ) l1: 1st gaussian vector size. */
/* _ (INT16 ) l2: 2nd gaussian vector size. */
/* _ (INT16 ) l_sf: subframe size. */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (FLOAT64 []) fcod_cand1: filtered 1st basis vector.*/
/* _ (FLOAT64 []) fcod_cand2: filtered 2nd basis vector.*/
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void GCB_orthogonal_convolve(FLOAT64 *unfcod_tmp, FLOAT64 *hh,
FLOAT64 *fcod_cand1, INT16 l1,
FLOAT64 *fcod_cand2, INT16 l2, INT16 l_sf)
{
/*-------------------------------------------------------------------*/
INT16 n, k;
FLOAT64 fc1, fc2;
/*-------------------------------------------------------------------*/
/* This solution assumes the two basis vector lengths, l1 and l2, are*/
/* the same. Otherwise, separate loops or a modification is needed. */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* even elements */
/*-------------------------------------------------------------------*/
#ifdef WMOPS
WMP_cnt_mult(1);
WMP_cnt_move(2);
#endif
fcod_cand1[0] = hh[0] * unfcod_tmp[0];
fcod_cand2[0] = 0.0;
for(n=2; n