rtphone/src/libs/libevs/lib_com/basop_com_lpc.cpp

238 lines
5.5 KiB
C++

/*====================================================================================
EVS Codec 3GPP TS26.443 Nov 13, 2018. Version 12.11.0 / 13.7.0 / 14.3.0 / 15.1.0
====================================================================================*/
#include <math.h>
#include <memory.h>
#include <assert.h>
#include <stdio.h>
#include "typedef.h"
#include "basop_proto_func.h"
#include "cnst.h"
#include "basop_util.h"
#include "stl.h"
#define UNROLL_CHEBYSHEV_INNER_LOOP
#define NC_MAX 8
#define GUESS_TBL_SZ 256
#define Madd_32_16(accu, x, y) L_add(accu, Mpy_32_16(x, y))
#define Msub_32_16(accu, x, y) L_sub(accu, Mpy_32_16(x, y))
/*
* weight_a
*
* Parameters:
* a I: LP filter coefficients Q12
* ap O: weighted LP filter coefficients Q12
* gamma I: weighting factor Q15
*
* Function:
* Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i).
*
* Returns:
* void
*/
void basop_weight_a(const Word16 *a, Word16 *ap, const Word16 gamma)
{
Word16 i, fac;
Word32 Amax;
Word16 shift;
fac = gamma;
Amax = L_mult( 16384, a[0] );
FOR (i = 1; i < M; i++)
{
Amax = L_max( Amax, L_abs( L_mult0( fac, a[i] ) ) );
fac = mult_r( fac, gamma );
}
Amax = L_max( Amax, L_abs( L_mult0( fac, a[M] ) ) );
shift = norm_l( Amax );
fac = gamma;
ap[0] = shl( a[0], sub(shift,1) );
move16();
FOR (i = 1; i < M; i++)
{
ap[i] = round_fx(L_shl(L_mult0(a[i], fac),shift));
move16();
fac = mult_r( fac, gamma );
}
ap[M] = round_fx(L_shl(L_mult0(a[M], fac),shift));
move16();
return;
}
/*
* weight_a_inv
*
* Parameters:
* a I: LP filter coefficients Q12
* ap O: weighted LP filter coefficients Q12
* inv_gamma I: inverse weighting factor Q14
*
* Function:
* Weighting of LP filter coefficients, ap[i] = a[i] * (inv_gamma^i).
*
* Returns:
* void
*/
void basop_weight_a_inv(const Word16 *a, Word16 *ap, const Word16 inv_gamma)
{
Word16 i;
static const Word16 inv_gamma_tab_12k8[16] = { 17809, 19357, 21041, 22870, 24859, 27020, 29370, 31924, /* Q14 */
17350, 18859, 20499, 22281, 24219, 26325, 28614, 31102
}; /* Q13 */
static const Word16 inv_gamma_tab_16k[16] = { 17430, 18542, 19726, 20985, 22324, 23749, 25265, 26878, /* Q14 */
14297, 15209, 16180, 17213, 18312, 19480, 20724, 22047
}; /* Q13 */
const Word16 *inv_gamma_tab;
Word32 L_tmp;
Word32 Amax;
Word16 shift;
IF (inv_gamma == 16384)
{
FOR (i = 0; i <= M; i++)
{
ap[i] = a[i];
move16();
}
return;
}
assert( inv_gamma==GAMMA1_INV || inv_gamma==GAMMA16k_INV );
inv_gamma_tab = inv_gamma_tab_12k8;
move16();
if (sub(inv_gamma,GAMMA16k_INV) == 0)
{
inv_gamma_tab = inv_gamma_tab_16k;
move16();
}
Amax = L_mult( 16384, a[0] );
FOR (i = 1; i < 9; i++)
{
Amax = L_max( Amax, L_abs( L_mult( a[i], inv_gamma_tab[i-1] ) ) );
}
FOR (i = 9; i < 17; i++)
{
Amax = L_max( Amax, L_abs( L_shl( L_mult( a[i], inv_gamma_tab[i-1] ), 1 ) ) );
}
shift = norm_l( Amax );
ap[0] = shl( a[0], sub(shift,1) );
move16();
FOR (i = 1; i < 9; i++)
{
L_tmp = L_mult( a[i], inv_gamma_tab[i-1] );
ap[i] = round_fx( L_shl( L_tmp, shift ) );
move16();
}
shift = add(shift,1);
FOR (i = 9; i < 17; i++)
{
L_tmp = L_mult( a[i], inv_gamma_tab[i-1] );
ap[i] = round_fx( L_shl( L_tmp, shift ) );
move16();
}
return;
}
/*
* basop_E_LPC_a_add_tilt
*
* Parameters:
* a I: LP filter coefficients (m+1 coeffs)
* ap O: modified LP filter coefficients (m+2 coeffs)
* gamma I: tilt factor
*
* Function:
* Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1))
*
* Returns:
* void
*/
void basop_E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma)
{
Word16 i;
Word32 Amax, Atmp[M+2];
Word16 shift;
Amax = L_mult( 16384, a[0] );
FOR (i = 1; i <= M; i++)
{
Atmp[i] = L_sub( L_mult(16384, a[i]), L_mult0(gamma, a[i-1]) );
move32();
Amax = L_max( Amax, L_abs( Atmp[i] ) );
}
Atmp[M+1] = L_negate( L_mult0(gamma, a[M]) );
move32();
Amax = L_max( Amax, L_abs( Atmp[M+1] ) );
shift = norm_l( Amax );
ap[0] = shl( a[0], sub(shift,1) );
move16();
FOR (i = 1; i <= M; i++)
{
ap[i] = round_fx( L_shl( Atmp[i], shift ) );
move16();
}
ap[M+1] = round_fx( L_shl( Atmp[M+1], shift ) );
move16();
return;
}
static Word16 xsf_to_xsp(Word16 xsf)
{
/* xsp = cos(xsf * 3.1415/6400); */
return getCosWord16R2(xsf);
}
/*
* lsf2lsp
*
* Parameters:
* lsf I: lsf[m] normalized (range: 0 <= val <= 0.5) x2.56
* lsp O: lsp[m] (range: -1 <= val < 1) Q15
*
* Function:
* Transformation lsf to lsp
*
* LSF are line spectral pair in frequency domain (0 to 6400).
* LSP are line spectral pair in cosine domain (-1 to 1).
*
* Returns:
* void
*/
void basop_lsf2lsp(const Word16 lsf[], Word16 lsp[])
{
Word16 i;
/* convert ISFs to the cosine domain */
FOR (i = 0; i < M; i++)
{
*lsp++ = xsf_to_xsp(*lsf++);
move16();
}
return;
}