274 lines
6.5 KiB
C++
274 lines
6.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 "options.h"
|
|
#include "cnst.h"
|
|
#include "prot.h"
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* calc_rc0_h()
|
|
*
|
|
* computes 1st parcor from composed filter impulse response
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
static void calc_rc0_h(
|
|
const float *h, /* i : impulse response of composed filter */
|
|
float *rc0 /* o : 1st parcor */
|
|
)
|
|
{
|
|
float acf0, acf1;
|
|
float temp, temp2;
|
|
const float *ptrs;
|
|
int i;
|
|
|
|
/* computation of the autocorrelation function acf */
|
|
temp = (float) 0.;
|
|
for (i = 0; i < LONG_H_ST; i++)
|
|
{
|
|
temp += h[i] * h[i];
|
|
}
|
|
acf0 = temp;
|
|
|
|
temp = (float) 0.;
|
|
ptrs = h;
|
|
for (i = 0; i < LONG_H_ST - 1; i++)
|
|
{
|
|
temp2 = *ptrs++;
|
|
temp += temp2 * (*ptrs);
|
|
}
|
|
acf1 = temp;
|
|
|
|
/* Initialisation of the calculation */
|
|
if (acf0 == (float) 0.)
|
|
{
|
|
*rc0 = (float) 0.;
|
|
return;
|
|
}
|
|
|
|
/* Compute 1st parcor */
|
|
if (acf0 < (float) fabs (acf1))
|
|
{
|
|
*rc0 = (float) 0.0;
|
|
return;
|
|
}
|
|
*rc0 = -acf1 / acf0;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* calc_st_filt()
|
|
*
|
|
* computes impulse response of A(gamma2) / A(gamma1)
|
|
* controls gain : computation of energy impulse response as
|
|
* SUMn (abs (h[n])) and computes parcor0
|
|
*---------------------------------------------------------------------------- */
|
|
|
|
void calc_st_filt(
|
|
const float *apond2, /* i : coefficients of numerator */
|
|
const float *apond1, /* i : coefficients of denominator */
|
|
float *parcor0, /* o : 1st parcor calcul. on composed filter */
|
|
float *sig_ltp_ptr, /* i/o: input of 1/A(gamma1) : scaled by 1/g0 */
|
|
float *mem_zero, /* i/o: All zero memory */
|
|
const short L_subfr, /* i : the length of subframe */
|
|
const short extl /* i : extension layer info */
|
|
|
|
)
|
|
{
|
|
float h[LONG_H_ST];
|
|
float g0, temp;
|
|
int i;
|
|
|
|
/* compute i.r. of composed filter apond2 / apond1 */
|
|
if( extl == SWB_TBE )
|
|
{
|
|
syn_filt( apond1, LPC_SHB_ORDER, apond2, h, LONG_H_ST, mem_zero, 0 );
|
|
}
|
|
else
|
|
{
|
|
syn_filt( apond1, M, apond2, h, LONG_H_ST, mem_zero, 0 );
|
|
}
|
|
|
|
/* compute 1st parcor */
|
|
calc_rc0_h( h, parcor0 );
|
|
|
|
/* compute g0 */
|
|
g0 = (float) 0.;
|
|
for (i = 0; i < LONG_H_ST; i++)
|
|
{
|
|
g0 += (float) fabs (h[i]);
|
|
}
|
|
|
|
/* Scale signal input of 1/A(gamma1) */
|
|
if (g0 > (float) 1.)
|
|
{
|
|
temp = (float) 1. / g0;
|
|
|
|
for (i = 0; i < L_subfr; i++)
|
|
{
|
|
sig_ltp_ptr[i] = sig_ltp_ptr[i] * temp;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* filt_mu()
|
|
*
|
|
* tilt filtering with : (1 + mu z-1) * (1/1-|mu|)
|
|
* computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1])
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
void filt_mu(
|
|
const float *sig_in, /* i : signal (beginning at sample -1) */
|
|
float *sig_out, /* o : output signal */
|
|
const float parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */
|
|
const short L_subfr, /* i : the length of subframe */
|
|
const short extl /* i : extension layer info */
|
|
)
|
|
{
|
|
short n;
|
|
float mu, ga, temp;
|
|
const float *ptrs;
|
|
|
|
if( extl == SWB_TBE )
|
|
{
|
|
if(parcor0 > 0.0f)
|
|
{
|
|
mu = parcor0 * GAMMA3_PLUS_WB;
|
|
}
|
|
else
|
|
{
|
|
mu = parcor0 * GAMMA3_MINUS_WB;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (parcor0 > 0.0f)
|
|
{
|
|
mu = parcor0 * GAMMA3_PLUS;
|
|
}
|
|
else
|
|
{
|
|
mu = parcor0 * GAMMA3_MINUS;
|
|
}
|
|
}
|
|
|
|
ga = (float) 1. / ((float) 1. - (float) fabs (mu));
|
|
|
|
ptrs = sig_in; /* points on sig_in(-1) */
|
|
|
|
for (n = 0; n < L_subfr; n++)
|
|
{
|
|
temp = mu * (*ptrs++);
|
|
temp += (*ptrs);
|
|
sig_out[n] = ga * temp;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* scale_st()
|
|
*
|
|
* control of the subframe gain
|
|
* gain[n] = AGC_FAC_FX * gain[n-1] + (1 - AGC_FAC_FX) g_in/g_out
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
void scale_st(
|
|
const float *sig_in, /* i : postfilter input signal */
|
|
float *sig_out, /* i/o: postfilter output signal */
|
|
float *gain_prec, /* i/o: last value of gain for subframe */
|
|
const short L_subfr, /* i : the length of subframe */
|
|
const short extl /* i : extension layer info */
|
|
)
|
|
{
|
|
int i;
|
|
float gain_in, gain_out;
|
|
float g0, gain;
|
|
float agc_fac1_para = 0.0f;
|
|
float agc_fac_para = 0.0f;
|
|
|
|
if( extl == SWB_TBE )
|
|
{
|
|
agc_fac1_para = AGC_FAC1_WB;
|
|
agc_fac_para = AGC_FAC_WB;
|
|
}
|
|
else
|
|
{
|
|
agc_fac1_para = AGC_FAC1;
|
|
agc_fac_para = AGC_FAC;
|
|
}
|
|
|
|
/* compute input gain */
|
|
gain_in = (float) 0.;
|
|
for (i = 0; i < L_subfr; i++)
|
|
{
|
|
gain_in += (float) fabs (sig_in[i]);
|
|
}
|
|
|
|
if ( gain_in == 0.0f )
|
|
{
|
|
g0 = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
/* Compute output gain */
|
|
gain_out = 0.0f;
|
|
for (i = 0; i < L_subfr; i++)
|
|
{
|
|
gain_out += (float) fabs (sig_out[i]);
|
|
}
|
|
|
|
if (gain_out == 0.0f)
|
|
{
|
|
*gain_prec = 0.0f;
|
|
return;
|
|
}
|
|
|
|
g0 = gain_in / gain_out;
|
|
g0 *= agc_fac1_para;
|
|
}
|
|
|
|
/* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */
|
|
/* sig_out(n) = gain(n) sig_out(n) */
|
|
gain = *gain_prec;
|
|
for (i = 0; i < L_subfr; i++)
|
|
{
|
|
gain *= agc_fac_para;
|
|
gain += g0;
|
|
sig_out[i] *= gain;
|
|
}
|
|
|
|
*gain_prec = gain;
|
|
|
|
return;
|
|
}
|
|
|
|
void blend_subfr2( float *sigIn1, float *sigIn2, float *sigOut)
|
|
{
|
|
|
|
float fac1 = 1.f - (1.f / L_SUBFR);
|
|
float fac2 = 0.f + (1.f / L_SUBFR);
|
|
float step = 1.f / (L_SUBFR/2);
|
|
int i;
|
|
|
|
for(i=0; i<L_SUBFR/2; i++)
|
|
{
|
|
sigOut[i] = fac1 * sigIn1[i] + fac2 * sigIn2[i];
|
|
fac1 -= step;
|
|
fac2 += step;
|
|
}
|
|
|
|
return;
|
|
}
|