📄 sp_enc.cpp
字号:
* a I: LPC coefficients [LP_ORDER+1]
* fac I: Spectral expansion factors. [LP_ORDER+1]
* a_exp O: Spectral expanded LPC coefficients [LP_ORDER+1]
*
* Function:
* Spectral expansion of LP coefficients
*
* Returns:
* void
*/
static void Weight_Ai( float a[], const float fac[], float a_exp[] )
{
INT32 i;
a_exp[0] = a[0];
for ( i = 1; i <= LP_ORDER; i++ )
{
a_exp[i] = a[i] * fac[i - 1];
}
return;
}
/*
* Residu
*
*
* Parameters:
* a I: prediction coefficients
* x I: speech signal
* y O: residual signal
*
* Function:
* Computes the LTP residual signal.
*
* Returns:
* void
*/
static void Residu( float a[], float x[], float y[] )
{
float s;
INT32 i;
for ( i = 0; i < SUBFRM_SIZE; i += 4 )
{
s = x[i] * a[0];
s += x[i - 1] *a[1];
s += x[i - 2] * a[2];
s += x[i - 3] * a[3];
s += x[i - 4] * a[4];
s += x[i - 5] * a[5];
s += x[i - 6] * a[6];
s += x[i - 7] * a[7];
s += x[i - 8] * a[8];
s += x[i - 9] * a[9];
s += x[i - 10] * a[10];
y[i] = s;
s = x[i + 1] *a[0];
s += x[i] * a[1];
s += x[i - 1] *a[2];
s += x[i - 2] * a[3];
s += x[i - 3] * a[4];
s += x[i - 4] * a[5];
s += x[i - 5] * a[6];
s += x[i - 6] * a[7];
s += x[i - 7] * a[8];
s += x[i - 8] * a[9];
s += x[i - 9] * a[10];
y[i + 1] = s;
s = x[i + 2] * a[0];
s += x[i + 1] *a[1];
s += x[i] * a[2];
s += x[i - 1] *a[3];
s += x[i - 2] * a[4];
s += x[i - 3] * a[5];
s += x[i - 4] * a[6];
s += x[i - 5] * a[7];
s += x[i - 6] * a[8];
s += x[i - 7] * a[9];
s += x[i - 8] * a[10];
y[i + 2] = s;
s = x[i + 3] * a[0];
s += x[i + 2] * a[1];
s += x[i + 1] *a[2];
s += x[i] * a[3];
s += x[i - 1] *a[4];
s += x[i - 2] * a[5];
s += x[i - 3] * a[6];
s += x[i - 4] * a[7];
s += x[i - 5] * a[8];
s += x[i - 6] * a[9];
s += x[i - 7] * a[10];
y[i + 3] = s;
}
return;
}
/*
* Syn_filt
*
*
* Parameters:
* a I: prediction coefficients [LP_ORDER+1]
* x I: input signal
* y O: output signal
* mem B: memory associated with this filtering
* update I: 0=no update, 1=update of memory.
*
* Function:
* Perform synthesis filtering through 1/A(z).
*
* Returns:
* void
*/
static void Syn_filt( float a[], float x[], float y[], float mem[], INT16 update )
{
double tmp[50];
double sum;
double *yy;
INT32 i;
/* Copy mem[] to yy[] */
yy = tmp;
for ( i = 0; i < LP_ORDER; i++ )
{
*yy++ = mem[i];
}
/* Do the filtering. */
for ( i = 0; i < SUBFRM_SIZE; i = i + 4 )
{
sum = x[i] * a[0];
sum -= a[1] * yy[ - 1];
sum -= a[2] * yy[ - 2];
sum -= a[3] * yy[ - 3];
sum -= a[4] * yy[ - 4];
sum -= a[5] * yy[ - 5];
sum -= a[6] * yy[ - 6];
sum -= a[7] * yy[ - 7];
sum -= a[8] * yy[ - 8];
sum -= a[9] * yy[ - 9];
sum -= a[10] * yy[ - 10];
*yy++ = sum;
y[i] = ( float )yy[ - 1];
sum = x[i + 1] *a[0];
sum -= a[1] * yy[ - 1];
sum -= a[2] * yy[ - 2];
sum -= a[3] * yy[ - 3];
sum -= a[4] * yy[ - 4];
sum -= a[5] * yy[ - 5];
sum -= a[6] * yy[ - 6];
sum -= a[7] * yy[ - 7];
sum -= a[8] * yy[ - 8];
sum -= a[9] * yy[ - 9];
sum -= a[10] * yy[ - 10];
*yy++ = sum;
y[i + 1] = ( float )yy[ - 1];
sum = x[i + 2] * a[0];
sum -= a[1] * yy[ - 1];
sum -= a[2] * yy[ - 2];
sum -= a[3] * yy[ - 3];
sum -= a[4] * yy[ - 4];
sum -= a[5] * yy[ - 5];
sum -= a[6] * yy[ - 6];
sum -= a[7] * yy[ - 7];
sum -= a[8] * yy[ - 8];
sum -= a[9] * yy[ - 9];
sum -= a[10] * yy[ - 10];
*yy++ = sum;
y[i + 2] = ( float )yy[ - 1];
sum = x[i + 3] * a[0];
sum -= a[1] * yy[ - 1];
sum -= a[2] * yy[ - 2];
sum -= a[3] * yy[ - 3];
sum -= a[4] * yy[ - 4];
sum -= a[5] * yy[ - 5];
sum -= a[6] * yy[ - 6];
sum -= a[7] * yy[ - 7];
sum -= a[8] * yy[ - 8];
sum -= a[9] * yy[ - 9];
sum -= a[10] * yy[ - 10];
*yy++ = sum;
y[i + 3] = ( float )yy[ - 1];
}
/* Update of memory if update==1 */
if ( update != 0 )
{
for ( i = 0; i < LP_ORDER; i++ )
{
mem[i] = y[30 + i];
}
}
return;
}
/*
* pre_big
*
*
* Parameters:
* mode I: AMR mode
* gamma1 I: spectral exp. factor 1
* gamma1_12k2 I: spectral exp. factor 1 for modes above MR795
* gamma2 I: spectral exp. factor 2
* A_t I: A(z) unquantized, for 4 subframes
* frame_offset I: frameoffset, 1st or second big_sbf
* speech I: speech
* mem_w B: synthesis filter memory state
* wsp O: weighted speech
*
* Function:
* Big subframe (2 subframes) preprocessing
*
* Open-loop pitch analysis is performed in order to simplify the pitch
* analysis and confine the closed-loop pitch search to a small number of
* lags around the open-loop estimated lags.
* Open-loop pitch estimation is based on the weighted speech signal Sw(n)
* which is obtained by filtering the input speech signal through
* the weighting filter
*
* W(z) = A(z/g1) / A(z/g2)
*
* That is, in a subframe of size L, the weighted speech is given by:
*
* 10 10
* Sw(n) = S(n) + SUM[a(i) * g1(i) * S(n-i)] - SUM[a(i) * g2(i) * Sw(n-i)],
* i=1 i=1
* n = 0, ..., L-1
*
* Returns:
* void
*/
static INT32 pre_big( enum Mode mode, const float gamma1[], const float gamma1_12k2[],
const float gamma2[], float A_t[], INT16 frame_offset,
float speech[], float mem_w[], float wsp[] )
{
float Ap1[LP_ORDER_PLUS], Ap2[LP_ORDER_PLUS];
INT32 offset, i;
/* A(z) with spectral expansion */
const float *g1;
g1 = gamma1_12k2;
if ( mode <= MR795 )
{
g1 = gamma1;
}
offset = 0;
if ( frame_offset > 0 )
{
offset = LP_ORDER_PLUS << 1;
}
/* process two subframes (which form the "big" subframe) */
for ( i = 0; i < 2; i++ )
{
/* a(i) * g1(i) */
Weight_Ai( &A_t[offset], g1, Ap1 );
/* a(i) * g2(i) */
Weight_Ai( &A_t[offset], gamma2, Ap2 );
/*
* 10
* S(n) + SUM[a(i) * g1(i) * S(n-i)]
* i=1
*/
Residu( Ap1, &speech[frame_offset], &wsp[frame_offset] );
/*
* 10 10
* S(n) + SUM[a(i) * g1(i) * S(n-i)] SUM[a(i) * g2(i) * Sn(n-i)]
* i=1 i=1
*/
Syn_filt( Ap2, &wsp[frame_offset], &wsp[frame_offset], mem_w, 1 );
offset += LP_ORDER_PLUS;
frame_offset += SUBFRM_SIZE;
}
return 0;
}
/*
* comp_corr
*
*
* Parameters:
* sig I: signal
* L_frame I: length of frame to compute pitch
* lag_max I: maximum lag
* lag_min I: minimum lag
* corr O: correlation of selected lag
*
* Function:
* Calculate all correlations in a given delay range.
*
* Returns:
* void
*/
static void comp_corr( float sig[], INT32 L_frame, INT32 lag_max,
INT32 lag_min, float corr[] )
{
INT32 i, j;
float *p, *p1;
float T0;
for ( i = lag_max; i >= lag_min; i-- )
{
p = sig;
p1 = &sig[ - i];
T0 = 0.0F;
for ( j = 0; j < L_frame; j = j + 40, p += 40, p1 += 40 )
{
T0 += p[0] * p1[0] + p[1] * p1[1] + p[2] * p1[2] + p[3] * p1[3];
T0 += p[4] * p1[4] + p[5] * p1[5] + p[6] * p1[6] + p[7] * p1[7];
T0 += p[8] * p1[8] + p[9] * p1[9] + p[10] * p1[10] + p[11] * p1[11];
T0 += p[12] * p1[12] + p[13] * p1[13] + p[14] * p1[14] + p[15] * p1[15];
T0 += p[16] * p1[16] + p[17] * p1[17] + p[18] * p1[18] + p[19] * p1[19];
T0 += p[20] * p1[20] + p[21] * p1[21] + p[22] * p1[22] + p[23] * p1[23];
T0 += p[24] * p1[24] + p[25] * p1[25] + p[26] * p1[26] + p[27] * p1[27];
T0 += p[28] * p1[28] + p[29] * p1[29] + p[30] * p1[30] + p[31] * p1[31];
T0 += p[32] * p1[32] + p[33] * p1[33] + p[34] * p1[34] + p[35] * p1[35];
T0 += p[36] * p1[36] + p[37] * p1[37] + p[38] * p1[38] + p[39] * p1[39];
}
corr[ - i] = T0;
}
return;
}
/*
* vad_tone_detection
*
*
* Parameters:
* st->tone B: flags indicating presence of a tone
* T0 I: autocorrelation maxima
* t1 I: energy
*
* Function:
* Set tone flag if pitch gain is high.
* This is used to detect signaling tones and other signals
* with high pitch gain.
*
* Returns:
* void
*/
//#ifndef VAD2
static void vad_tone_detection( vadState *st, float T0, float t1 )
{
if ( ( t1 > 0 ) && ( T0 > t1 * TONE_THR ) ) {
st->tone = st->tone | 0x00004000;
}
}
//#endif
/*
* Lag_max
*
*
* Parameters:
* vadSt B: vad structure
* corr I: correlation vector
* sig I: signal
* L_frame I: length of frame to compute pitch
* lag_max I: maximum lag
* lag_min I: minimum lag
* cor_max O: maximum correlation
* dtx I: dtx on/off
*
* Function:
* Compute the open loop pitch lag.
*
* Returns:
* p_max lag found
*/
/*
#ifdef VAD2
static INT16 Lag_max( float corr[], float sig[], INT16 L_frame,
INT32 lag_max, INT32 lag_min, float *cor_max,
INT32 dtx, float *rmax, float *r0 )
#else
*/
static INT16 Lag_max( vadState *vadSt, float corr[], float sig[], INT16 L_frame,
INT32 lag_max, INT32 lag_min, float *cor_max, INT32 dtx )
//#endif
{
float max, T0;
float *p;
INT32 i, j, p_max;
max = -FLT_MAX;
p_max = lag_max;
for ( i = lag_max, j = ( PIT_MAX - lag_max - 1 ); i >= lag_min; i--, j-- )
{
if ( corr[ - i] >= max )
{
max = corr[ - i];
p_max = i;
}
}
/* compute energy for normalization */
T0 = 0.0F;
p = &sig[ - p_max];
for ( i = 0; i < L_frame; i++, p++ )
{
T0 += *p * *p;
}
if ( dtx )
{
/*
#ifdef VAD2
*rmax = max;
*r0 = T0;
#else
*/
/* check tone */
vad_tone_detection( vadSt, max, T0 );
//#endif
}
if ( T0 > 0.0F )
T0 = 1.0F / ( float )sqrt( T0 );
else
T0 = 0.0F;
/* max = max/sqrt(energy) */
max *= T0;
*cor_max = max;
return( ( INT16 )p_max );
}
/*
* hp_max
*
*
* Parameters:
* corr I: correlation vector
* sig I: signal
* L_frame I: length of frame to compute pitch
* lag_max I: maximum lag
* lag_min I: minimum lag
* cor_hp_max O: max high-pass filtered correlation
*
* Function:
* Find the maximum correlation of scal_sig[] in a given delay range.
*
* The correlation is given by
* cor[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max
* The functions outputs the maximum correlation after normalization
* and the corresponding lag.
*
* Returns:
* void
*/
//#ifndef VAD2
static void hp_max( float corr[], float sig[], INT32 L_frame,
INT32 lag_max, INT32 lag_min, float *cor_hp_max )
{
float T0, t1, max;
float *p, *p1;
INT32 i;
max = -FLT_MAX;
T0 = 0;
for ( i = lag_max - 1; i > lag_min; i-- ) {
/* high-pass filtering */
T0 = ( ( corr[ - i] * 2 ) - corr[ - i-1] )-corr[ - i + 1];
T0 = ( float )fabs( T0 );
if ( T0 >= max ) {
max = T0;
}
}
/* compute energy */
p = sig;
p1 = &sig[0];
T0 = 0;
for ( i = 0; i < L_frame; i++, p++, p1++ ) {
T0 += *p * *p1;
}
p = sig;
p1 = &sig[ - 1];
t1 = 0;
for ( i = 0; i < L_frame; i++, p++, p1++ ) {
t1 += *p * *p1;
}
/* high-pass filtering */
T0 = T0 - t1;
T0 = ( float )fabs( T0 );
/* max/T0 */
if ( T0 != 0 ) {
*cor_hp_max = max / T0;
}
else {
*cor_hp_max = 0;
}
}
//#endif
/*
* vad_tone_detection_update
*
*
* Parameters:
* st->tone B: flags indicating presence of a tone
* one_lag_per_frame I: 1 open-loop lag is calculated per each frame
*
* Function:
* Update the tone flag register.
*
* Returns:
* void
*/
//#ifndef VAD2
static void vad_tone_detection_update( vadState *st, INT16 one_lag_per_frame )
{
/* Shift tone flags right by one bit */
st->tone = st->tone >> 1;
/*
* If open-loop lag is calculated only once in each frame,
* do extra update and assume that the other tone flag
* of the frame is one.
*/
if ( one_lag_per_frame != 0 ) {
st->tone = st->tone >> 1;
st->tone = st->tone | 0x00002000;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -