📄 vq_lib.c
字号:
d_cj = extract_h(L_temp);
/* determine if d is less than the maximum candidate distortion i.e., is the distortion found better than the so-called
worst of the best */
/* increment complexity for if statement */
compare_nonzero();
if (d_cj <= n_d[p_max])
{
/* replace the worst with the values just found */
/* n_d is now a Q16 */
n_d[p_max] = d_cj; data_move();
i = add(shr(extract_l(L_mult(p_max,stages)),1),s);
n_indices[i] = j; data_move();
n_parents[p_max] = c; data_move();
/* want to limit the number of times the inner loop
is entered (to reduce the *maximum* complexity) */
/* increment complexity for if statement */
compare_nonzero();
if (inner_counter < max_inner)
{
inner_counter = add(inner_counter,1);
/* increment complexity for if statement */
compare_nonzero();
if (inner_counter < max_inner)
{
p_max = 0; data_move();
/* find the new maximum */
for(i=1; i < ma; i++)
{
/* increment complexity for if statement */
compare_nonzero();
if (n_d[i] > n_d[p_max])
p_max = i; data_move();
}
}
else /* inner_counter == max_inner */
{
/* The inner loop counter now exceeds the
maximum, and the inner loop will now not
be entered. Instead of quitting the search
or doing something drastic, we simply keep
track of the best candidate (rather than the
M best) by setting p_max to equal the index
of the minimum distortion
i.e. only keep one candidate around
the MINIMUM distortion */
for(i=1; i < ma; i++)
{
/* increment complexity for if statement */
compare_nonzero();
if (n_d[i] < n_d[p_max])
p_max = i; data_move();
}
}
}
}
} /* for c */
} /* for j */
/* compute the error vectors for each node */
for(c=0; c < ma; c++)
{
/* get the error from the parent node and subtract off
the codebook value */
(void)v_equ(&n_errors[c*p],&p_errors[n_parents[c]*p],p);
(void)v_sub(&n_errors[c*p],
&cb_currentstage[n_indices[c*stages+s]*p],p);
/* get the indices that were used for the parent node */
(void)v_equ(&n_indices[c*stages],
&p_indices[n_parents[c]*stages],s);
}
/* increment complexity for if statement */
compare_nonzero(); data_move();
m = (m*levels[s] > ma) ? ma : m*levels[s];
} /* for s */
/* find the optimum candidate c */
for(i=1,c=0; i < ma; i++)
{
/* increment complexity for if statement */
compare_nonzero();
if (n_d[i] < n_d[c])
c = i; data_move();
}
d_opt = n_d[c]; data_move();
if (a_indices)
{
(void)v_equ(a_indices,&n_indices[c*stages],stages);
}
if (u_hat)
{
if (u_est)
(void)v_equ(u_hat,u_est,p);
else
(void)v_zap(u_hat,p);
cb_currentstage = cb;
for(s=0; s < stages; s++)
{
cb_table = &cb_currentstage[n_indices[c*stages+s]*p];
for (i=0; i<p; i++)
u_hat[i] = add(u_hat[i], shr(cb_table[i],2)); data_move();
cb_currentstage += levels[s]*p;
}
}
MEM_FREE(FREE,parents);
MEM_FREE(FREE,d);
MEM_FREE(FREE,uhatw);
MEM_FREE(FREE,errors);
MEM_FREE(FREE,indices);
MEM_FREE(FREE,tmp_p_e);
return(d_opt);
} /* vq_ms4 */
/*
VQ_MSD2-
Tree search multi-stage VQ decoder
Synopsis: vq_msd(cb,u,u_est,a,indices,levels,stages,p,conversion)
Input:
cb- one dimensional linear codebook array (codebook is structured
as [stages][levels for each stage][p])
indices- the codebook indices (for each stage) indices[0..stages-1]
levels- the number of levels (for each stage) levels[0..stages-1]
u_est- dimension p, the estimated parameters or mean (if NULL, assume
estimate is the all zero vector) (u_est[0..p-1])
stages- the number of stages of msvq
p- the predictor order
conversion- the conversion constant (see lpc.h, lpc_conv.c)
diff_Q- the difference between Q value of codebook and u_est
Output:
u- dimension p, the decoded parameters (if NULL, use alternate
temporary storage) (u[0..p-1])
a- predictor parameters (a[0..p]), if NULL, don't compute
Returns:
pointer to reconstruction vector (u)
Parameters:
*/
Shortword *vq_msd2(Shortword *cb, Shortword *u, Shortword *u_est,
Shortword *a, Shortword *indices, Shortword *levels,
Shortword stages, Shortword p, Shortword conversion,
Shortword diff_Q)
{
Shortword *u_hat,*cb_currentstage,*cb_table;
Shortword i,j;
Longword *L_u_hat,L_temp;
/* allocate memory (if required) */
MEM_ALLOC(MALLOC,L_u_hat,p,Longword);
if (u==(Shortword*)NULL)
{
MEM_ALLOC(MALLOC,u_hat,p,Shortword);
}
else
u_hat = u;
/* add estimate on (if non-null), or clear vector */
if (u_est)
{
(void)v_equ(u_hat,u_est,p);
}
else
{
(void)v_zap(u_hat,p);
}
/* put u_hat to a long buffer */
for (i = 0; i < p; i++)
L_u_hat[i] = L_shl(L_deposit_l(u_hat[i]),diff_Q);
/* add the contribution of each stage */
cb_currentstage = cb;
for(i=0; i < stages; i++)
{
/* (void)v_add(u_hat,&cb_currentstage[indices[i]*p],p); */
cb_table = &cb_currentstage[indices[i]*p];
for (j = 0; j < p; j++) {
L_temp = L_deposit_l(cb_table[j]);
L_u_hat[j] = L_add(L_u_hat[j],L_temp);
}
cb_currentstage += levels[i]*p;
}
/* convert long buffer back to u_hat */
for (i = 0; i < p; i++)
u_hat[i] = extract_l(L_shr(L_u_hat[i],diff_Q));
MEM_FREE(FREE,L_u_hat);
return(u);
}
/* VQ_ENC -
encode vector with full VQ using unweighted Euclidean distance
Synopsis: vq_enc(cb, u, levels, p, u_hat, indices)
Input:
cb- one dimensional linear codebook array
u- dimension p, the parameters to be encoded (u[0..p-1])
levels- the number of levels
p- the predictor order
Output:
u_hat- the reconstruction vector (if non null)
a_indices- the codebook indices (for each stage) a_indices[0..stages-1]
Parameters:
*/
/* Q values:
cb - Q13
u - Q13
u_hat - Q13 */
Longword vq_enc(Shortword *cb,Shortword *u,Shortword levels,Shortword p,
Shortword *u_hat,Shortword *indices)
{
Shortword i,j,index;
Longword d,dmin;
Shortword *p_cb;
Shortword temp;
/* Search codebook for minimum distance */
index = 0; data_move();
dmin = LW_MAX; L_data_move();
p_cb = cb;
for (i = 0; i < levels; i++) {
d = 0; data_move();
for (j = 0; j < p; j++) {
temp = sub(u[j],*p_cb);
d = L_mac(d,temp,temp);
p_cb++;
}
compare_nonzero();
if (d < dmin) {
dmin = d; data_move();
index = i; data_move();
}
}
/* Update index and quantized value, and return minimum distance */
*indices = index;
v_equ(u_hat,&cb[p*index],p);
return(dmin);
} /* vq_enc */
/* VQ_FSW -
compute the weights for Euclidean distance of Fourier harmonics */
/* Q values:
w_fs - Q14
pitch - Q9 */
void vq_fsw(Shortword *w_fs, Shortword num_harm, Shortword pitch)
{
Shortword j;
Shortword tempw0;
Shortword temp,denom;
Longword L_temp;
/* Calculate fundamental frequency */
/* w0 = TWOPI/pitch */
/* tempw0 = w0/(0.25*PI) = 8/pitch */
tempw0 = divide_s((Shortword)EIGHT_Q11,pitch); /* tempw0 in Q17 */
for(j=0; j < num_harm; j++) {
/* Bark-scale weighting */
/* w_fs[j] = 117.0 / (25.0 + 75.0*
pow(1.0 + 1.4*SQR(w0*(j+1)/(0.25*PI)),0.69)) */
temp = shl(add(j,1),11); /* Q11 */
temp = extract_h(L_shl(L_mult(tempw0,temp),1)); /* Q14 */
temp = mult(temp,temp); /* Q13 */
/* L_temp in Q28 */
L_temp = L_add((Longword)ONE_Q28,L_mult((Shortword)X14_Q14,temp));
temp = L_pow_fxp(L_temp,(Shortword)X069_Q15,28,13); /* Q13 */
denom = add((Shortword)X25_Q6,mult((Shortword)X75_Q8,temp)); /* Q6 */
w_fs[j] = divide_s((Shortword)X117_Q5,denom); /* Q14 */ data_move();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -