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