📄 qnt12.c
字号:
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 + -