📄 lpc_lib.c
字号:
/* Currently only supports 10 loops, which is too */
/* complex and perhaps unneccesary. */
/* */
/* Systems and Info. Science Lab */
/* Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved. */
/* */
/* Q values: lsp - Q15, delta - Q15 */
Shortword lpc_clmp(Shortword lsp[], Shortword delta, Shortword order)
{
register Shortword i, j;
BOOLEAN unsorted;
Shortword temp, d, step1, step2;
/* sort the LSPs for 10 loops */
for (j = 0, unsorted = TRUE; unsorted && (j < MAX_LOOPS); j++){
for (i = 0, unsorted = FALSE; i < order - 1; i++)
if (lsp[i] > lsp[i + 1]){
temp = lsp[i + 1];
lsp[i + 1] = lsp[i];
lsp[i] = temp;
unsorted = TRUE;
}
}
/* ensure minimum separation */
if (!unsorted){
for (j = 0; j < MAX_LOOPS; j++){
for (i = 0; i < order - 1; i++){
d = sub(lsp[i + 1], lsp[i]);
if (d < delta){
step1 = step2 = shr(sub(delta, d), 1);
/* --> */ if (i == 0 && (lsp[i] < delta)){
step1 = shr(lsp[i], 1);
} else {
/* --> */ if (i > 0){
temp = sub(lsp[i], lsp[i-1]);
if (temp < delta){
step1 = 0;
} else {
if (temp < shl(delta, 1))
step1 = shr(sub(temp, delta), 1);
}
}
}
/* --> */ if (i == (order - 2) && (lsp[i + 1] > sub(ONE_Q15, delta))){
step2 = shr(sub(ONE_Q15, lsp[i + 1]), 1);
} else {
/* --> */ if (i < (order - 2)){
temp = sub(lsp[i + 2], lsp[i + 1]);
if (temp < delta){
step2 = 0;
} else {
if (temp < shl(delta, 1))
step2 = shr(sub(temp, delta), 1);
}
}
}
lsp[i] = sub(lsp[i], step1);
lsp[i + 1] = add(lsp[i + 1], step2);
}
}
}
}
/* Debug: check if the minimum separation rule was met */
temp = mult(32440, delta); /* temp = 0.99*delta */
for (i = 0; i < order - 1; i++)
if ((lsp[i + 1] - lsp[i]) < temp)
fprintf(stderr, "%s: LSPs not separated enough (line %d)\n",
__FILE__, __LINE__);
if (unsorted)
fprintf(stderr, "%s: Fxp LSPs still unsorted (line %d)\n",
__FILE__, __LINE__);
return(0);
}
/* Name: lpc_schr- Schur recursion (autocorrelations to refl coef) */
/* Aliases: lpc_schur */
/* Description: */
/* Compute reflection coefficients from autocorrelations */
/* based on schur recursion. Will also compute predictor */
/* parameters by calling lpc_refl2pred(3l) if necessary. */
/* Inputs: */
/* autocorr- autocorrelation vector (autocorr[0..p]). */
/* order- order of lpc filter. */
/* Outputs: */
/* lpc- predictor parameters (can be NULL) */
/* Returns: */
/* alphap- the minimum residual energy */
/* Includes: */
/* lpc.h */
/* See_Also: */
/* lpc_refl2pred(3l) in lpc.h or lpc(3l) */
/* */
/* Q values: */
/* autocorr - Q0, lpc - Q12, */
/* Previously the output reflection coefficients refc[] is now changed to */
/* local dynamic arrays because the calling environment does not need it nor */
/* use it. */
Shortword lpc_schr(Shortword autocorr[], Shortword lpc[], Shortword order)
{
register Shortword i, j;
Shortword shift, alphap;
Shortword *refc; /* Q15 */
Longword L_temp, *y1, *y2;
Shortword temp1, temp2;
y1 = L_v_get(order);
y2 = L_v_get((Shortword) (order + 1));
refc = v_get(order);
temp2 = abs_s(autocorr[1]);
temp1 = abs_s(autocorr[0]);
refc[0] = divide_s(temp2, temp1);
/* if (((autocorr[1] < 0) && (autocorr[0] < 0)) ||
((autocorr[1] > 0) && (autocorr[0] > 0))) */
if ((autocorr[1] ^ autocorr[0]) >= 0){
refc[0] = negate(refc[0]);
}
alphap = mult(autocorr[0], sub(ONE_Q15, mult(refc[0], refc[0])));
y2[0] = L_deposit_h(autocorr[1]);
y2[1] = L_add(L_deposit_h(autocorr[0]), L_mult(refc[0], autocorr[1]));
for (i = 1; i < order; i++){
y1[0] = L_deposit_h(autocorr[i + 1]);
L_temp = L_deposit_h(autocorr[i + 1]);
for (j = 0; j < i; j++){
y1[j + 1] = L_add(y2[j], L_mpy_ls(L_temp, refc[j]));
L_temp = L_add(L_temp, L_mpy_ls(y2[j], refc[j]));
}
/* refc[i] = -temp/y2[i]; */
/* Under normal conditions the condition for the following IF */
/* statement should never be true. */
if (L_temp > y2[i]){
v_zap(&(refc[i]), (Shortword) (order - i));
break;
}
shift = norm_l(y2[i]);
temp1 = abs_s(extract_h(L_shl(L_temp, shift)));
temp2 = abs_s(extract_h(L_shl(y2[i], shift)));
refc[i] = divide_s(temp1, temp2);
if ((L_temp ^ y2[i]) >= 0){
refc[i] = negate(refc[i]);
}
y2[i + 1] = L_add(y2[i], L_mpy_ls(L_temp, refc[i]));
L_v_equ(y2, y1, (Shortword) (i + 1));
}
lpc_refl2pred(refc, lpc, order);
alphap = autocorr[0];
for (i = 0; i < order; i++){
alphap = mult(alphap, sub(ONE_Q15, mult(refc[i], refc[i])));
}
v_free(refc);
v_free(y2);
v_free(y1);
return(alphap); /* alhap in Q15 */
}
/* LPC_REFL2PRED */
/* get predictor coefficients from the reflection coeffs */
/* Synopsis: lpc_refl2pred(refc, lpc, order) */
/* */
/* Input: */
/* refc- the reflection coeffs */
/* order- the predictor order */
/* Output: */
/* lpc- the predictor coefficients */
/* Reference: Markel and Gray, Linear Prediction of Speech */
/* */
/* Q values: */
/* refc - Q15, lpc - Q12 */
static Shortword lpc_refl2pred(Shortword refc[], Shortword lpc[],
Shortword order)
{
register Shortword i, j;
Shortword *a1;
a1 = v_get((Shortword) (order - 1));
for (i = 0; i < order; i++){
/* refl to a recursion */
lpc[i] = shift_r(refc[i], -3); /* lpc in Q12 */
v_equ(a1, lpc, i);
for (j = 0; j < i; j++){
lpc[j] = add(a1[j], mult(refc[i], a1[i - j - 1]));
}
}
v_free(a1);
return(0);
}
/* LPC_PRED2LSP */
/* get LSP coeffs from the predictor coeffs */
/* Input: */
/* lpc- the predictor coefficients */
/* order- the predictor order */
/* Output: */
/* lsf- the lsp coefficients */
/* */
/* This function uses a DFT to evaluate the P and Q polynomials, */
/* and is hard-coded to work only for 10th order LPC. */
/* */
/* Q values: */
/* lpc - Q12, lsf - Q15 */
Shortword lpc_pred2lsp(Shortword lpc[], Shortword lsf[], Shortword order)
{
register Shortword i;
Shortword p_cof[LPC_ORD/2 + 1], q_cof[LPC_ORD/2 + 1],
p_freq[LPC_ORD/2 + 1], q_freq[LPC_ORD/2 + 1];
Longword L_p_cof[LPC_ORD/2 + 1], L_q_cof[LPC_ORD/2 + 1];
Longword L_ai, L_api, L_temp;
Shortword p2;
p2 = shr(order, 1);
/* Generate P' and Q' polynomials. We only compute for indices from 0 to */
/* p2 = order/2 because lsp_to_freq() only uses p_cof[] and q_cof[] for */
/* for these indices, and hence L_p_cof[] and L_q_cof[] are needed only */
/* from 0 to order/2. */
L_p_cof[0] = (Longword) ONE_Q26;
L_q_cof[0] = (Longword) ONE_Q26;
for (i = 1; i <= p2; i++){
/* temp = sub(lpc[i - 1], lpc[order - i]); */ /* temp in Q12 */
L_ai = L_shr(L_deposit_h(lpc[i - 1]), 2);
L_api = L_shr(L_deposit_h(lpc[order - i]), 2);
L_temp = L_sub(L_ai, L_api); /* L_temp in Q26 */
L_p_cof[i] = L_add(L_temp, L_p_cof[i - 1]); /* L_p_cof in Q26 */
/* temp = add(lpc[i - 1], lpc[order - i]); */
L_temp = L_add(L_ai, L_api);
L_q_cof[i] = L_sub(L_temp, L_q_cof[i - 1]); /* L_q_cof in Q26 */
}
/* Convert p_cof and q_cof to short. We only compute for indices from 0 */
/* to p2 = order/2 because lsp_to_freq() only uses p_cof[] and q_cof[] */
/* for these indices. */
for (i = 0; i <= p2; i++){
p_cof[i] = round(L_p_cof[i]); /* p_cof in Q10 */
q_cof[i] = round(L_q_cof[i]); /* q_cof in Q10 */
}
/* Find root frequencies of LSP polynomials */
lsp_to_freq(p_cof, p_freq, order);
lsp_to_freq(q_cof, q_freq, order);
/* Combine frequencies into single array */
for (i = 0; i < p2; i++){
lsf[2*i] = q_freq[i];
lsf[2*i + 1] = p_freq[i];
}
return(0);
}
/* Subroutine LSP_TO_FREQ: Calculate line spectrum pair root frequencies from */
/* LSP polynomial. Only lsp[0], ...... lsp[order/2] are used and the other */
/* lsp[]'s are ignored. Similarly, only freq[0], ...... freq[order/2] are */
/* computed. */
/* */
/* Q values: */
/* lsp - Q10, freq - Q15 */
static void lsp_to_freq(Shortword lsp[], Shortword freq[], Shortword order)
{
register Shortword i, j;
static BOOLEAN firstTime = TRUE;
static Shortword lsp_cos[DFTLENGTH]; /* cosine table */
static Shortword default_w, default_w0;
Shortword p2, count;
BOOLEAN prev_less;
Longword mag[3];
Shortword s_mag[3];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -