📄 lpc_lib.c
字号:
for(i=2; i <= p; i++)
{
y1[1] = L_deposit_h(r[i]);
L_temp = L_deposit_h(r[i]);
for(j=1; j < i; j++)
{
y1[j+1] = L_add(y2[j], L_mpy_ls(L_temp, k[j])); L_data_move();
L_temp = L_add (L_temp, L_mpy_ls(y2[j], k[j]));
y2[j] = y1[j]; L_data_move();
}
/* k[i] = -temp/y2[i]; */
if (L_temp > y2[i]) {
for (j = i; j <= p; j++)
k[j] = 0;
#if (PRINT)
printf("\nERROR: numerator bigger than denominator in lpc_schr\n");
printf("Reflection coefficients used in frame %d:\n",frames);
for (i = 1; i <= p; i++) {
printf(" %5.8f ",(float)k[i]/(1<<15));
}
printf("\n");
#endif
break;
}
shift = norm_l(y2[i]);
n_temp = abs_s(extract_h(L_shl(L_temp,shift))); data_move();
n_y2 = abs_s(extract_h(L_shl(y2[i],shift))); data_move();
k[i] = divide_s(n_temp,n_y2); data_move();
/* increment complexity for if statement */
L_logic(); compare_zero();
if ((L_temp ^ y2[i]) >= 0)
{
k[i] = negate(k[i]); data_move();
}
y2[i+1] = L_add(y2[i], L_mpy_ls(L_temp, k[i])); L_data_move();
y2[i] = y1[i]; L_data_move();
alphap = mult(alphap,sub(ONE_Q15,mult(k[i],k[i]))); data_move();
}
if (a != NULL)
{
lpc_refl2pred(k,a,p);
}
if (k_tmp == NULL)
MEM_FREE(FREE,k);
MEM_FREE(FREE,y2);
MEM_FREE(FREE,y1);
return(alphap); /* alphap in Q15 */
} /* LPC_SCHR */
/* LPC_REFL2PRED
get predictor coefficients from the reflection coeffs
Synopsis: lpc_refl2pred(k,a,p)
Input:
k- the reflection coeffs
p- the predictor order
Output:
a- the predictor coefficients
Reference: Markel and Gray, Linear Prediction of Speech
Q values:
k - Q15
a - Q12
*/
Shortword lpc_refl2pred(Shortword *k,Shortword *a,Shortword p)
{
Shortword i,j;
Shortword *a1;
MEM_ALLOC(MALLOC,a1,p+1,Shortword);
for(i=1; i <= p; i++)
{
/* refl to a recursion */
a[i] = shift_r(k[i],-3); /* a in Q12 */ data_move();
for(j=1; j < i; j++) {
a1[j] = a[j]; data_move();
}
for(j=1; j < i; j++) {
a[j] = add(a1[j],mult(k[i],a1[i-j])); data_move();
}
}
MEM_FREE(FREE,a1);
return((Shortword)0);
} /* LPC_REFL2PRED */
/* minimum LSP separation-- a global variable */
Shortword lsp_delta = 0;
/* LPC_PRED2LSP
get LSP coeffs from the predictor coeffs
Input:
a- the predictor coefficients
p- the predictor order
Output:
w- 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:
a - Q12
w - Q15
*/
static void lsp_to_freq(Shortword lsp[], Shortword w[], Shortword order);
#define LPC_ORD 10
Shortword lpc_pred2lsp(Shortword *a,Shortword *w,Shortword p)
{
Shortword i,j;
Shortword p_cof[LPC_ORD+1], q_cof[LPC_ORD+1],
p_freq[LPC_ORD+1], q_freq[LPC_ORD+1];
Longword L_p_cof[LPC_ORD+1], L_q_cof[LPC_ORD+1];
Longword L_ai,L_api,L_temp;
/* Generate P' and Q' polynomials */
L_p_cof[0] = (Longword)ONE_Q26;
L_q_cof[0] = (Longword)ONE_Q26;
for ( i = 1; i <= p; i++ ) {
/* temp = sub(a[i],a[p+1-i]); */ /* temp in Q12 */
L_ai = L_shr(L_deposit_h(a[i]),2); L_data_move();
L_api = L_shr(L_deposit_h(a[p+1-i]),2); L_data_move();
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(a[i],a[p+1-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 */
for ( i = 0; i <= p; 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,p);
lsp_to_freq(q_cof,q_freq,p);
/* Combine frequencies into single array */
w[0] = 0;
j = 1;
for (i = 0; i < (shr(p,1)); i++) {
w[j++] = q_freq[i]; data_move();
w[j++] = p_freq[i]; data_move();
}
return((Shortword)0);
} /* LPC_PRED2LSP */
/* */
/* Subroutine LSP_TO_FREQ: Calculate Line Spectrum Pair */
/* root frequencies from LSP polynomial. */
/* */
/* Q values:
lsp - Q10
w - Q15
*/
#define DFTLENGTH 512
#define DFTLENGTH_D2 (DFTLENGTH/2)
#define DFTLENGTH_D4 (DFTLENGTH/4)
static void lsp_to_freq(Shortword lsp[], Shortword w[], Shortword p)
{
Shortword i;
Shortword p2, count, prev_less, j;
static Shortword firstcall = 1;
Longword mag0, mag1, mag2;
Shortword s_mag0, s_mag1, s_mag2;
Shortword *p_cos, *p_endlsp, *p_lsp, *p_begcos, *p_endcos;
Shortword temp1, temp2;
Longword L_temp1, L_temp2;
static Shortword lsp_cos[DFTLENGTH]; /* cosine table */
static Shortword default_w, default_w0;
static Shortword cos_tab[129] =
{
32767, 32766, 32758, 32746, 32729, 32706, 32679, 32647, 32610,
32568, 32522, 32470, 32413, 32352, 32286, 32214, 32138, 32058,
31972, 31881, 31786, 31686, 31581, 31471, 31357, 31238, 31114,
30986, 30853, 30715, 30572, 30425, 30274, 30118, 29957, 29792,
29622, 29448, 29269, 29086, 28899, 28707, 28511, 28311, 28106,
27897, 27684, 27467, 27246, 27020, 26791, 26557, 26320, 26078,
25833, 25583, 25330, 25073, 24812, 24548, 24279, 24008, 23732,
23453, 23170, 22884, 22595, 22302, 22006, 21706, 21403, 21097,
20788, 20475, 20160, 19841, 19520, 19195, 18868, 18538, 18205,
17869, 17531, 17190, 16846, 16500, 16151, 15800, 15447, 15091,
14733, 14373, 14010, 13646, 13279, 12910, 12540, 12167, 11793,
11417, 11039, 10660, 10279, 9896, 9512, 9127, 8740, 8351,
7962, 7571, 7180, 6787, 6393, 5998, 5602, 5205, 4808,
4410, 4011, 3612, 3212, 2811, 2411, 2009, 1608, 1206,
804, 402, 0
};
if (firstcall) {
/* Initialization: fill cosine table */
firstcall = 0;
/* for (i = 0; i < DFTLENGTH; i++ )
lsp_cos[i] = cos(i*(TWOPI / DFTLENGTH)); */
for (i = 0; i < DFTLENGTH_D4; i++) {
lsp_cos[i] = cos_tab[i];
lsp_cos[i+DFTLENGTH_D4] = -cos_tab[DFTLENGTH_D4-i];
lsp_cos[i+2*DFTLENGTH_D4] = -cos_tab[i];
lsp_cos[i+3*DFTLENGTH_D4] = cos_tab[DFTLENGTH_D4-i];
}
/* compute default values for w[] */
/* (1./p2) in Q15 */
default_w = divide_s(ONE_Q11,shl(p,10));
/* w[0] = (0.5/p2) in Q15 */
default_w0 = shr(default_w,1);
}
prev_less = 1;
mag0 = (Longword)0x7fffffff; L_data_move();
mag1 = (Longword)0x7fffffff; L_data_move();
s_mag0 = (Shortword)0x7fff; data_move();
s_mag1 = (Shortword)0x7fff; data_move();
p2 = shr(p,1); /* p/2 */
count = 0; data_move();
p_begcos = &lsp_cos[0];
p_endcos = &lsp_cos[DFTLENGTH-1];
p_endlsp = &lsp[p2];
/* Search all frequencies for minima of Pc(w) */
for (i = 0; i <= DFTLENGTH_D2; i++ ) {
p_lsp = p_endlsp;
p_cos = p_begcos++;
/* mag2 = 0.5 * *(p_lsp--); */
mag2 = L_mult(*(p_lsp--),(Shortword)X05_Q14); /* mag2 in Q25 */
for (j = p2 - 1; j >= 0; j-- ) {
L_temp1 = L_shr(L_mult(*(p_lsp--),*(p_cos)),1);
mag2 = L_add(mag2,L_temp1);
complexity -= 4; /* this can be done with MAC on TMS320C5x */
p_cos += i;
if (p_cos > p_endcos)
p_cos -= DFTLENGTH;
}
s_mag2 = extract_h(mag2);
mag2 = L_abs(mag2);
L_compare_nonzero();
if (mag2 < mag1) {
prev_less = 1; data_move();
}
else {
if (prev_less) {
/* check for sign change */
logic(); compare_zero();
if ((s_mag0 ^ s_mag2) < 0) {
/* Minimum frequency found */
/*w[count] = i - 1 + (0.5 *
(mag0 - mag2) / (mag0 + mag2 - 2*mag1) );
w[count] *= (2. / DFTLENGTH) ;*/
L_temp1 = L_shr(L_sub(mag0,mag2),1);
L_temp2 = L_sub(mag0,L_shl(mag1,1));
L_temp2 = L_add(L_temp2,mag2);
temp1 = L_divider2(L_temp1,L_temp2,0,0); /* temp1 in Q15 */
temp1 = shr(temp1,9); /* Q6 */
temp2 = sub(i,1);
temp1 = add(shl(temp2,6),temp1);
w[count] = divide_s(temp1,shl(DFTLENGTH,5)); data_move();
count = add(count,1);
}
}
prev_less = 0; data_move();
}
mag0 = mag1; L_data_move();
mag1 = mag2; L_data_move();
s_mag0 = s_mag1; data_move();
s_mag1 = s_mag2; data_move();
}
/* Verify that all roots were found */
if (count != p2) {
#if (PRINT)
printf("ERROR: couldn't find LSP frequencies in frame %d.\n",frames);
printf(" Found were ");
for (i = 0; i < count; i++)
printf(" %10.4f ",(float)w[i]/(1<<15));
printf("\n");
#endif
/* use default values */
w[0] = default_w0;
for (i = 1; i < p2; i++) {
w[i] = w[i-1] + default_w;
}
}
} /* LSP_TO_FREQ */
#undef DFTLENGTH
#undef DFTLENGTH_D2
#undef DFTLENGTH_D4
/* LPC_PRED2REFL
get refl coeffs from the predictor coeffs
Input:
a- the predictor coefficients
p- the predictor order
Output:
k- the reflection coefficients
Returns:
energy - energy of residual signal
Reference: Markel and Gray, Linear Prediction of Speech
Q values:
*a - Q12
*k - Q15
energy - Q15
*/
Shortword lpc_pred2refl(Shortword *a,Shortword *k,Shortword p)
{
Shortword *b,*b1, e;
Shortword energy = ONE_Q15;
Shortword i,j;
Shortword shift;
Shortword temp, n_temp, n_e;
MEM_ALLOC(MALLOC,b,p+1,Shortword);
MEM_ALLOC(MALLOC,b1,p+1,Shortword);
/* equate temporary variables (b = a) */
for(i=1; i <= p; i++) {
b[i] = a[i]; data_move();
}
/* compute reflection coefficients */
for(i=p; i > 0; i--)
{
k[i] = shl(b[i],3); /* Q12 -> Q15 */
e = sub(ONE_Q15,mult(k[i],k[i]));
energy = mult(energy,e);
for(j=1; j < i; j++) {
b1[j] = b[j]; data_move();
}
for(j=1; j < i; j++) {
/* b[j] = (b1[j] - k[i]*b1[i-j])/e; */
temp = mult(k[i],b1[i-j]); /* temp in Q12 */
temp = sub(b1[j],temp);
/* check signs of temp and e before division */
n_temp = abs_s(temp);
n_e = abs_s(e);
shift = norm_s(n_e);
n_e = shl(n_e,shift);
if (n_temp > n_e) {
n_temp = shr(n_temp,1);
shift = add(shift,1);
}
b[j] = shl(divide_s(n_temp,n_e),shift); /* b[j] in Q12 */
if ((temp ^ e) < 0)
b[j] = negate(b[j]);
}
}
MEM_FREE(FREE,b1);
MEM_FREE(FREE,b);
return(energy);
} /* LPC_PRED2REFL */
/* LPC_LSP2PRED
get predictor coefficients from the LSPs
Synopsis: lpc_lsp2pred(w,a,p)
Input:
w- the LSPs
p- the predictor order
Output:
a- the predictor coefficients
Reference: Kabal and Ramachandran
*/
/* Q values:
w - Q15
a - Q12
f - Q25
c - Q14 */
Shortword lpc_lsp2pred(Shortword *w,Shortword *a,Shortword p)
{
Shortword i,j,k,p2;
Shortword c[2];
Longword **f;
Longword L_temp;
/* ensure minimum separation and sort */
(void)lpc_clmp(w,lsp_delta,p);
/* p2 = p/2 */
p2 = shr(p,1); data_move();
MEM_2ALLOC(MALLOC,f,2,p2+1,Longword);
/* f is Q25 */
f[0][0] = f[1][0] = (Longword)ONE_Q25; L_data_move(); L_data_move();
/* -2.0*cos((double)w[1]*M_PI) */
f[0][1] = L_shr(L_deposit_h(negate(cos_fxp(w[1]))),5); L_data_move();
f[1][1] = L_shr(L_deposit_h(negate(cos_fxp(w[2]))),5); L_data_move();
k = 3;
for(i=2; i <= p2; i++)
{
/* c is Q14 */
/* multiply by 2 is considered as Q15->Q14 */
c[0] = negate(cos_fxp(w[k++])); data_move();
c[1] = negate(cos_fxp(w[k++])); data_move();
f[0][i] = f[0][i-2]; L_data_move();
f[1][i] = f[1][i-2]; L_data_move();
for(j=i; j >= 2; j--)
{
/* f[0][j] += c[0]*f[0][j-1]+f[0][j-2] */
L_temp = L_mpy_ls(f[0][j-1],c[0]);
L_temp = L_add(L_shl(L_temp,1),f[0][j-2]);
f[0][j] = L_add(f[0][j],L_temp); L_data_move();
/* f[1][j] += c[1]*f[1][j-1]+f[1][j-2] */
L_temp = L_mpy_ls(f[1][j-1],c[1]);
L_temp = L_add(L_shl(L_temp,1),f[1][j-2]);
f[1][j] = L_add(f[1][j],L_temp); L_data_move();
}
f[0][1] = L_add(f[0][1],L_shl(L_mpy_ls(f[0][0],c[0]),1));
f[1][1] = L_add(f[1][1],L_shl(L_mpy_ls(f[1][0],c[1]),1));
}
for(i=p2; i > 0; i--)
{
/* short f (f is a Q14) */
f[0][i] = L_add(f[0][i],f[0][i-1]);
f[1][i] = L_sub(f[1][i],f[1][i-1]);
/* a is Q12 */
/* a[i] = 0.50*(f[0][i]+f[1][i]) */
/* a[p+1-i] = 0.50*(f[0][i]-f[1][i]) */
/* Q25 -> Q27 -> Q12 */
a[i] = extract_h(L_shl(L_add(f[0][i],f[1][i]),2));
a[p+1-i] = extract_h(L_shl(L_sub(f[0][i],f[1][i]),2));
}
MEM_2FREE(FREE,f);
return((Shortword)0);
} /* LPC_LSP2PRED */
/*
Name: lpc_syn- LPC synthesis filter.
Aliases: lpc_synthesis
Description:
LPC all-pole synthesis filter
for j = 0 to n-1
y[j] = x[j] - sum(k=1 to p) y[j-k] a[k]
Inputs:
x- input vector (n samples, x[0..n-1])
a- lpc vector (order p, a[1..p])
p- order of lpc filter
n- number of elements in vector which is to be filtered
y[-p..-1]- filter memory (past outputs)
Outputs:
y- output vector (n samples, y[0..n-1])
Returns: NULL
Includes:
spbstd.h
lpc.h
Systems and Info. Science Lab
Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.
*/
Shortword lpc_syn(Shortword *x,Shortword *y,Shortword *a,Shortword p,
Shortword n)
{
Shortword i,j;
Longword accum;
for(j=0; j < n; j++) {
accum = L_shr(L_deposit_h(x[j]),3);
for(i=p; i > 0; i--)
accum = L_msu(accum,y[j-i],a[i]);
/* Round off output */
accum = L_shl(accum,3);
y[j] = round(accum);
}
return((Shortword)0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -