Files
rtphone/src/libs/libg729/g729_lpcfunc.cpp
2018-06-05 11:05:37 +03:00

301 lines
10 KiB
C++

/*
ITU-T G.729A Speech Coder ANSI-C Source Code
Version 1.1 Last modified: September 1996
Copyright (c) 1996,
AT&T, France Telecom, NTT, Universite de Sherbrooke
All rights reserved.
*/
/*-------------------------------------------------------------*
* Procedure Lsp_Az: *
* ~~~~~~ *
* Compute the LPC coefficients from lsp (order=10) *
*-------------------------------------------------------------*/
#include "g729_typedef.h"
#include "g729_basic_op.h"
#include "g729_oper_32b.h"
#include "g729_ld8a.h"
#include "g729_tab_ld8a.h"
/* local function */
void Get_lsp_pol (Word16 * lsp, Word32 * f);
void
Lsp_Az (Word16 lsp[], /* (i) Q15 : line spectral frequencies */
Word16 a[] /* (o) Q12 : predictor coefficients (order = 10) */
)
{
Word16 i, j;
Word32 f1[6], f2[6];
Word32 t0;
Get_lsp_pol (&lsp[0], f1);
Get_lsp_pol (&lsp[1], f2);
for (i = 5; i > 0; i--) {
f1[i] = L_add (f1[i], f1[i - 1]); /* f1[i] += f1[i-1]; */
f2[i] = L_sub (f2[i], f2[i - 1]); /* f2[i] -= f2[i-1]; */
}
a[0] = 4096;
for (i = 1, j = 10; i <= 5; i++, j--) {
t0 = L_add (f1[i], f2[i]); /* f1[i] + f2[i] */
a[i] = extract_l (L_shr_r (t0, 13)); /* from Q24 to Q12 and * 0.5 */
t0 = L_sub (f1[i], f2[i]); /* f1[i] - f2[i] */
a[j] = extract_l (L_shr_r (t0, 13)); /* from Q24 to Q12 and * 0.5 */
}
return;
}
/*-----------------------------------------------------------*
* procedure Get_lsp_pol: *
* ~~~~~~~~~~~ *
* Find the polynomial F1(z) or F2(z) from the LSPs *
*-----------------------------------------------------------*
* *
* Parameters: *
* lsp[] : line spectral freq. (cosine domain) in Q15 *
* f[] : the coefficients of F1 or F2 in Q24 *
*-----------------------------------------------------------*/
void
Get_lsp_pol (Word16 * lsp, Word32 * f)
{
Word16 i, j, hi, lo;
Word32 t0;
/* All computation in Q24 */
*f = L_mult (4096, 2048); /* f[0] = 1.0; in Q24 */
f++;
*f = L_msu ((Word32) 0, *lsp, 512); /* f[1] = -2.0 * lsp[0]; in Q24 */
f++;
lsp += 2; /* Advance lsp pointer */
for (i = 2; i <= 5; i++) {
*f = f[-2];
for (j = 1; j < i; j++, f--) {
L_Extract (f[-1], &hi, &lo);
t0 = Mpy_32_16 (hi, lo, *lsp); /* t0 = f[-1] * lsp */
t0 = L_shl (t0, 1);
*f = L_add (*f, f[-2]); /* *f += f[-2] */
*f = L_sub (*f, t0); /* *f -= t0 */
}
*f = L_msu (*f, *lsp, 512); /* *f -= lsp<<9 */
f += i; /* Advance f pointer */
lsp += 2; /* Advance lsp pointer */
}
return;
}
/*___________________________________________________________________________
| |
| Functions : Lsp_lsf and Lsf_lsp |
| |
| Lsp_lsf Transformation lsp to lsf |
| Lsf_lsp Transformation lsf to lsp |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| The transformation from lsp[i] to lsf[i] and lsf[i] to lsp[i] are |
| approximated by a look-up table and interpolation. |
|___________________________________________________________________________|
*/
void
Lsf_lsp (Word16 lsf[], /* (i) Q15 : lsf[m] normalized (range: 0.0<=val<=0.5) */
Word16 lsp[], /* (o) Q15 : lsp[m] (range: -1<=val<1) */
Word16 m /* (i) : LPC order */
)
{
Word16 i, ind, offset;
Word32 L_tmp;
for (i = 0; i < m; i++) {
ind = shr (lsf[i], 8); /* ind = b8-b15 of lsf[i] */
offset = lsf[i] & (Word16) 0x00ff; /* offset = b0-b7 of lsf[i] */
/* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */
L_tmp = L_mult (sub (table[ind + 1], table[ind]), offset);
lsp[i] = add (table[ind], extract_l (L_shr (L_tmp, 9)));
}
return;
}
void
Lsp_lsf (Word16 lsp[], /* (i) Q15 : lsp[m] (range: -1<=val<1) */
Word16 lsf[], /* (o) Q15 : lsf[m] normalized (range: 0.0<=val<=0.5) */
Word16 m /* (i) : LPC order */
)
{
Word16 i, ind, tmp;
Word32 L_tmp;
ind = 63; /* begin at end of table -1 */
for (i = m - (Word16) 1; i >= 0; i--) {
/* find value in table that is just greater than lsp[i] */
while (sub (table[ind], lsp[i]) < 0) {
ind = sub (ind, 1);
}
/* acos(lsp[i])= ind*256 + ( ( lsp[i]-table[ind] ) * slope[ind] )/4096 */
L_tmp = L_mult (sub (lsp[i], table[ind]), slope[ind]);
tmp = wround (L_shl (L_tmp, 3)); /*(lsp[i]-table[ind])*slope[ind])>>12 */
lsf[i] = add (tmp, shl (ind, 8));
}
return;
}
/*___________________________________________________________________________
| |
| Functions : Lsp_lsf and Lsf_lsp |
| |
| Lsp_lsf Transformation lsp to lsf |
| Lsf_lsp Transformation lsf to lsp |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| The transformation from lsp[i] to lsf[i] and lsf[i] to lsp[i] are |
| approximated by a look-up table and interpolation. |
|___________________________________________________________________________|
*/
void
Lsf_lsp2 (Word16 lsf[], /* (i) Q13 : lsf[m] (range: 0.0<=val<PI) */
Word16 lsp[], /* (o) Q15 : lsp[m] (range: -1<=val<1) */
Word16 m /* (i) : LPC order */
)
{
Word16 i, ind;
Word16 offset; /* in Q8 */
Word16 freq; /* normalized frequency in Q15 */
Word32 L_tmp;
for (i = 0; i < m; i++) {
/* freq = abs_s(freq);*/
freq = mult (lsf[i], 20861); /* 20861: 1.0/(2.0*PI) in Q17 */
ind = shr (freq, 8); /* ind = b8-b15 of freq */
offset = freq & (Word16) 0x00ff; /* offset = b0-b7 of freq */
if (sub (ind, 63) > 0) {
ind = 63; /* 0 <= ind <= 63 */
}
/* lsp[i] = table2[ind]+ (slope_cos[ind]*offset >> 12) */
L_tmp = L_mult (slope_cos[ind], offset); /* L_tmp in Q28 */
lsp[i] = add (table2[ind], extract_l (L_shr (L_tmp, 13)));
}
return;
}
void
Lsp_lsf2 (Word16 lsp[], /* (i) Q15 : lsp[m] (range: -1<=val<1) */
Word16 lsf[], /* (o) Q13 : lsf[m] (range: 0.0<=val<PI) */
Word16 m /* (i) : LPC order */
)
{
Word16 i, ind;
Word16 offset; /* in Q15 */
Word16 freq; /* normalized frequency in Q16 */
Word32 L_tmp;
ind = 63; /* begin at end of table2 -1 */
for (i = m - (Word16) 1; i >= 0; i--) {
/* find value in table2 that is just greater than lsp[i] */
while (sub (table2[ind], lsp[i]) < 0) {
ind = sub (ind, 1);
if (ind <= 0)
break;
}
offset = sub (lsp[i], table2[ind]);
/* acos(lsp[i])= ind*512 + (slope_acos[ind]*offset >> 11) */
L_tmp = L_mult (slope_acos[ind], offset); /* L_tmp in Q28 */
freq = add (shl (ind, 9), extract_l (L_shr (L_tmp, 12)));
lsf[i] = mult (freq, 25736); /* 25736: 2.0*PI in Q12 */
}
return;
}
/*-------------------------------------------------------------*
* procedure Weight_Az *
* ~~~~~~~~~ *
* Weighting of LPC coefficients. *
* ap[i] = a[i] * (gamma ** i) *
* *
*-------------------------------------------------------------*/
void
Weight_Az (Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
Word16 gamma, /* (i) Q15 : Spectral expansion factor. */
Word16 m, /* (i) : LPC order. */
Word16 ap[] /* (o) Q12 : Spectral expanded LPC coefficients */
)
{
Word16 i, fac;
ap[0] = a[0];
fac = gamma;
for (i = 1; i < m; i++) {
ap[i] = wround (L_mult (a[i], fac));
fac = wround (L_mult (fac, gamma));
}
ap[m] = wround (L_mult (a[m], fac));
return;
}
/*----------------------------------------------------------------------*
* Function Int_qlpc() *
* ~~~~~~~~~~~~~~~~~~~ *
* Interpolation of the LPC parameters. *
*----------------------------------------------------------------------*/
/* Interpolation of the quantized LSP's */
void
Int_qlpc (Word16 lsp_old[], /* input : LSP vector of past frame */
Word16 lsp_new[], /* input : LSP vector of present frame */
Word16 Az[] /* output: interpolated Az() for the 2 subframes */
)
{
Word16 i;
Word16 lsp[M10];
/* lsp[i] = lsp_new[i] * 0.5 + lsp_old[i] * 0.5 */
for (i = 0; i < M10; i++) {
lsp[i] = add (shr (lsp_new[i], 1), shr (lsp_old[i], 1));
}
Lsp_Az (lsp, Az); /* Subframe 1 */
Lsp_Az (lsp_new, &Az[MP1]); /* Subframe 2 */
return;
}