⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qnt12.c

📁 MELPe 1200 bps, fixed point
💻 C
📖 第 1 页 / 共 4 页
字号:
					break;
			}
		}
		if (err < min){
			min = err;
			ind = index[i];
		}
		codebook += dim;                              /* Pointer arithmetics. */
	}

	return(ind);
}


/****************************************************************************
**
** Function:		gain_vq
**
** Description: 	Gain quantization for 1200bps
**
** Arguments:
**
**	melp_param *par ---- input/output melp parameters
**
** Return value:	None
**
*****************************************************************************/
void gain_vq(struct melp_param *par)
{
	register Shortword	i, j;
	Shortword	index;
	Shortword	temp, temp2;
	Shortword	gain_target[NF_X_NUM_GAINFR];
	Longword	err, minErr;                                           /* Q17 */
	Longword	L_temp;


	/* Reshape par[i].gain[j] into a one-dimensional vector gain_target[]. */
	temp = 0;
	for (i = 0; i < NF; i++){
		v_equ(&(gain_target[temp]), par[i].gain, NUM_GAINFR);
		temp = add(temp, NUM_GAINFR);
	}

	minErr = LW_MAX;
	index = 0;
	temp2 = 0;
	for (i = 0; i < GAIN_VQ_SIZE; i++){

		/*	temp2 = i * NF * NUM_GAINFR; */

		err = 0;

		/* j = 0 for the following for loop. */
		temp = sub(gain_target[0], gain_vq_cb[temp2]);                  /* Q8 */
		L_temp = L_mult(temp, temp);                                   /* Q17 */
		L_temp = L_shr(L_temp, 3);                                     /* Q14 */
		err = L_add(err, L_temp);                                      /* Q14 */

		/* For the sum of 6 terms, if the first term already exceeds minErr,  */
		/* there is no need to keep computing.                                */

		if (err < minErr){
			for (j = 1; j < NF_X_NUM_GAINFR; j++){
				/*	err += SQR(par[j].gain[k] -
						   gain_vq_cb[i*NUM_GAINFR*NF + j*NUM_GAINFR + k]); */
				temp = sub(gain_target[j], gain_vq_cb[temp2 + j]);      /* Q8 */
				L_temp = L_mult(temp, temp);                           /* Q17 */
				L_temp = L_shr(L_temp, 3);                             /* Q14 */
				err = L_add(err, L_temp);                              /* Q14 */
			}
			if (err < minErr){
				minErr = err;
				index = i;
			}
		}
		temp2 = add(temp2, NF_X_NUM_GAINFR);
	}

	/*	temp2 = index * NF * NUM_GAINFR; */
	L_temp = L_mult(index, NF_X_NUM_GAINFR);
	L_temp = L_shr(L_temp, 1);
	temp2 = extract_l(L_temp);
	for (i = 0; i < NF; i++){
		/*	v_equ(par[i].gain, &(gain_vq_cb[index*NUM_GAINFR*NF +
											i*NUM_GAINFR]), NUM_GAINFR); */
		v_equ(par[i].gain, &(gain_vq_cb[temp2]), NUM_GAINFR);
		temp2 = add(temp2, NUM_GAINFR);
	}

	quant_par.gain_index[0] = index;
}


/****************************************************************************
**
** Function:		quant_bp
**
** Description: 	Quantization the band-pass voicing for 1200bps
**
** Arguments:
**
**	melp_param *par ---- input/output melp parameters
**
** Return value:	None
**
*****************************************************************************/

void quant_bp(struct melp_param *par, Shortword num_frames)
{
	register Shortword	i;


	for (i = 0; i < num_frames; i++){
		par[i].uv_flag = q_bpvc(par[i].bpvc, &(quant_par.bpvc_index[i]),
								NUM_BANDS);
		quant_par.bpvc_index[i] = bp_index_map[quant_par.bpvc_index[i]];
	}
}


/********************************************************************
**
** Function: lspVQ ()
**
** Description:
**		Vector quantizes a set of int term filter coefficients
**		using a multi-stage M-L tree search algorithm.
**
** Arguments:
**
**	Shortword	target[]	: the target coefficients to be quantized (Q15/Q17)
**	Shortword	weight[]	: weights for mse calculation (Q11)
**	Shortword	qout[]		: the output array (Q15/Q17)
**	Shortword	codebook[]	: codebooks,   cb[0..numStages-1] (Q15/Q17)
**	Shortword	tos 		: the number of stages
**  Shortword	cb_size[]	: codebook size (multistages)
**	Shortword	cb_index[]	: codebook indeces; cb_index[0..numStages-1]
**                            (output)
**  Shortword	dim
**  BOOLEAN		flag
**
** Return value:	None
**
***********************************************************************/
static void		lspVQ(Shortword target[], Shortword weight[], Shortword qout[],
					  const Shortword codebook[], Shortword tos,
					  const Shortword cb_size[], Shortword cb_index[],
					  Shortword dim, BOOLEAN flag)
{
	register Shortword	i, entry;
	register Shortword	c1, s1;
	const Shortword		*cdbk_ptr, *cdbk_ptr2, *ptr1;
	Shortword	index[LSP_VQ_CAND][LSP_VQ_STAGES];
	Shortword	nextIndex[LSP_VQ_CAND][LSP_VQ_STAGES];
	Shortword	ncPrev;
	Shortword	cand[LSP_VQ_CAND][2*LPC_ORD];
	Shortword	max_dMin, dMin[LSP_VQ_CAND], distortion; 
	Shortword	*cand_target;
	Longword	L_temp;
	Shortword	ptr_offset = 0;
	Shortword	temp1, temp2;


	/*==================================================================*
	*	Initialize the data before starting the tree search.			*
	*	  - the number of candidates from the "previous" stage is set	*
	*		to 1 since there is no previous stage!						*
	*	  - the candidate vector from the previous stage is set to zero *
	*	  - the list of indeces for each candidate is set to 1			*
	*==================================================================*/
	for (i = 0; i < LSP_VQ_CAND; i++){
		v_zap(cand[i], dim);
		v_zap(index[i], LSP_VQ_STAGES);
		v_zap(nextIndex[i], LSP_VQ_STAGES);
	}
	cand_target = v_get(dim);
	ncPrev = 1;

	/*==================================================================*
	*	Now we start the search:										*
	*		For each stage												*
	*			For each candidate from the previous stage				*
	*				For each entry in the current stage codebook		*
	*					* add codebook vector to current candidate		*
	*					* compute the distortion with the target		*
	*					* retain candidate if one of the best so far	*
	*==================================================================*/
	cdbk_ptr = codebook;

	/* An observation for lspVQ() shows that if "flag" is FALSE, then we only */
	/* need to keep track of the best one (instead of the best LSP_VQ_CAND,   */
	/* 8) cand[][] and index[][].  This has significant influence on          */
	/* execution speed.                                                       */

	for (s1 = 0; s1 < tos; s1++){
		/* set the distortions to huge values */
		fill(dMin, SW_MAX, LSP_VQ_CAND);
		max_dMin = SW_MAX;

		/* Loop for each previous candidate selected, and try each entry */
		for (c1 = 0; c1 < ncPrev; c1++){
			ptr_offset = 0;

			/* cand_target[] is the target vector with cand[c1] removed.      */
			/* This moves some operations from the for-entry loop here.       */
			/* save_saturation(); */
			v_equ(cand_target, target, dim);
			v_sub(cand_target, cand[c1], dim);
			/* restore_saturation(); */

			for (entry = 0; entry < cb_size[s1]; entry++){
				ptr1 = cdbk_ptr + ptr_offset;         /* Pointer arithmetics. */

				/* compute the distortion */
				distortion = WeightedMSE(dim, weight, ptr1, cand_target,
																max_dMin);

				/*======================================================*
				* If the error for this entry is less than the worst	*
				* retained candidate so far, keep it. Note that the 	*
				* error list is maintained in order of best to worst.	*
				*=======================================================*/
				if (distortion < max_dMin){
					max_dMin = InsertCand(c1, s1, dMin, distortion, entry,
							 	  nextIndex[0], index[0]);
				}
				ptr_offset = add(ptr_offset, dim);
			}
		}

		/* At this point ptr_offset is (cb_size[s1]*dim).                     */

		/*==================================================================*
		*	Compute the number of candidate vectors which we kept for the	*
		*	next stage. Note that if the size of the stages is less than	*
		*	the number of candidates, we build them up using all entries	*
		*	until we have kept numCand candidates.  On the other hand, if   *
		*   flag is FALSE and (s1 == tos - 1), then we only need to use     *
		*   ncPrev = 1 because we only copy the best candidate before       *
		*   exiting lspVQ().                                                *
		*==================================================================*/

		if (!flag && s1 == tos - 1)
			ncPrev = 1;
		else {
			/* ncPrev = Min(ncPrev*cb_size[s1], LSP_VQ_CAND) for regular      */
			/* loops, and ncPrev = Min(ncPrev*cb_size[s1], LSP_INP_CAND) for  */
			/* the last lap.  Explanations are available near the end of this */			/* function.                                                      */

			L_temp = L_mult(ncPrev, cb_size[s1]);
			L_temp = L_shr(L_temp, 1);
			temp1 = extract_l(L_temp);        /* temp1 = ncPrev * cb_size[s1] */
			if (s1 == tos - 1)
				temp2 = LSP_INP_CAND;
			else
				temp2 = LSP_VQ_CAND;
			if (temp1 < temp2)
				ncPrev = temp1;
			else
				ncPrev = temp2;
		}

		/*==================================================================*
		*	We now have the  best indices for the stage just completed, so	*
		*	compute the new candidate vectors for the next stage... 		*
		*==================================================================*/
		for (c1 = 0; c1 < ncPrev; c1++){
			v_zap(cand[c1], dim);
			cdbk_ptr2 = codebook;
			temp1 = add(s1, 1);
			v_equ(index[c1], nextIndex[c1], temp1);
			for (i = 0; i < temp1; i++){
				/*	v_add(cand[c1], cdbk_ptr2 + index[c1][i]*dim, dim); */
				L_temp = L_mult(index[c1][i], dim);
				L_temp = L_shr(L_temp, 1);
				temp2 = extract_l(L_temp);
				ptr1 = cdbk_ptr2 + temp2;
				v_add(cand[c1], ptr1, dim);
				/*	cdbk_ptr2 += cb_size[i]*dim; */
				L_temp = L_mult(cb_size[i], dim);
				L_temp = L_shr(L_temp, 1);
				temp2 = extract_l(L_temp);
				cdbk_ptr2 += temp2;
			}
		}

		/*	cdbk_ptr += cb_size[s1] * dim; */
		cdbk_ptr += ptr_offset;
	}

	/* Copy best candidate and indices into output.  Here we use temp1 and    */
	/* temp2 to compute (c1*tos) and (c1*dim).                                */

	/* Originally this function copies LSP_VQ_CAND (== 8) vectors before      */
	/* exiting if flag is TRUE.  However, in the calling environment of       */
	/* lspVQ() when flag is passed in as TRUE, we only used LSP_INP_CAND      */
	/* (== 5).                                                                */

	temp1 = 0;
	temp2 = 0;
	for (i = 0; i < ncPrev; i++){
		v_equ(&(cb_index[temp1]), index[i], tos);
		v_equ(&qout[temp2], cand[i], dim);
		temp1 = add(temp1, tos);
		temp2 = add(temp2, dim);
	}
	
	v_free(cand_target);
}


/********************************************************************
**
** Function: WeightedMSE
**
** Description:
**	Given a weighting function,  computes the weighted mean squared
**	error between two vectors.
**
** Arguments:
**	Shortword n		: number of coefficients in the two vectors
**	Shortword weight[] 	: weighting function; weight[1..n] (Q11)
**	Shortword x[]		: first vector (Q15/Q17)
**	Shortword target[]	: second vector (Q15/Q17)
**
** Return value:
**
**	Shortword WeightedMSE : distortion returned as function value (Q15/Q17)
**
***********************************************************************/
static Shortword	WeightedMSE(Shortword n, Shortword weight[], 
				const Shortword x[], Shortword target[], Shortword max_dMin)
{
	register Shortword	i;
	Longword	distortion;
	Shortword	temp, half_n;


	/* x[] and target[] are either Q15 or Q17.  Since the only issue          */
	/* mattering is the relative magnitude of WeightedMSE() among different   */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -