📄 sp_enc.c
字号:
}
/*
* lsp
*
*
* Parameters:
* req_mode I: requested mode
* used_mode I: used mode
* lsp_old B: old LSP vector
* lsp_old_q B: old quantized LSP vector
* past_rq B: past quantized residual
* az B: interpolated LP parameters
* azQ O: quantization interpol. LP parameters
* lsp_new O: new lsp vector
* anap O: analysis parameters
*
* Function:
* From A(z) to lsp. LSP quantization and interpolation
*
* Returns:
* void
*/
static void lsp( enum Mode req_mode, enum Mode used_mode, Float32 *lsp_old,
Float32 *lsp_old_q, Float32 *past_rq, Float32 az[], Float32 azQ[], Float32
lsp_new[], Word16 **anap )
{
Float32 lsp_new_q[M]; /* LSPs at 4th subframe */
Float32 lsp_mid[M], lsp_mid_q[M]; /* LSPs at 2nd subframe */
Word32 pred_init_i; /* init index for MA prediction in DTX mode */
if ( req_mode == MR122 ) {
Az_lsp( &az[MP1], lsp_mid, lsp_old );
Az_lsp( &az[MP1 * 3], lsp_new, lsp_mid );
/*
* Find interpolated LPC parameters in all subframes
* (both quantized and unquantized).
* The interpolated parameters are in array A_t[] of size (M+1)*4
* and the quantized interpolated parameters are in array Aq_t[]
*/
Int_lpc_1and3_2( lsp_old, lsp_mid, lsp_new, az );
if ( used_mode != MRDTX ) {
/* LSP quantization (lsp_mid[] and lsp_new[] jointly quantized) */
Q_plsf_5( past_rq, lsp_mid, lsp_new, lsp_mid_q, lsp_new_q, *anap );
Int_lpc_1and3( lsp_old_q, lsp_mid_q, lsp_new_q, azQ );
/* Advance analysis parameters pointer */
( *anap ) += 5;
}
}
else {
/* From A(z) to lsp */
Az_lsp( &az[MP1 * 3], lsp_new, lsp_old );
/*
* Find interpolated LPC parameters in all subframes
* (both quantized and unquantized).
* The interpolated parameters are in array A_t[] of size (M+1)*4
* and the quantized interpolated parameters are in array Aq_t[]
*/
Int_lpc_1to3_2( lsp_old, lsp_new, az );
/* LSP quantization */
if ( used_mode != MRDTX ) {
Q_plsf_3( req_mode, past_rq, lsp_new, lsp_new_q, *anap, &pred_init_i );
Int_lpc_1to3( lsp_old_q, lsp_new_q, azQ );
/* Advance analysis parameters pointer */
( *anap ) += 3;
}
}
/* update the LSPs for the next frame */
memcpy( lsp_old, lsp_new, M <<2 );
memcpy( lsp_old_q, lsp_new_q, M <<2 );
}
/*
* check_lsp
*
*
* Parameters:
* count B: counter for resonance
* lsp B: LSP vector
*
* Function:
* Check the LSP's to detect resonances
*
* Resonances in the LPC filter are monitored to detect possible problem
* areas where divergence between the adaptive codebook memories in
* the encoder and the decoder could cause unstable filters in areas
* with highly correlated continuos signals. Typically, this divergence
* is due to channel errors.
* The monitoring of resonance signals is performed using unquantized LSPs
* q(i), i = 1,...,10. The algorithm utilises the fact that LSPs are
* closely located at a peak in the spectrum. First, two distances,
* dist 1 and dist 2 ,are calculated in two different regions,
* defined as
*
* dist1 = min[q(i) - q(i + 1)], i = 4,...,8
* dist2 = min[q(i) - q(i + 1)], i = 2,3
*
* Either of these two minimum distance conditions must be fulfilled
* to classify the frame as a resonance frame and increase the resonance
* counter.
*
* if(dist1 < TH1) || if (dist2 < TH2)
* counter++
* else
* counter = 0
*
* TH1 = 0.046
* TH2 = 0.018, q(2) > 0.98
* TH2 = 0.024, 0.93 < q(2) <= 0.98
* TH2 = 0.018, otherwise
*
* 12 consecutive resonance frames are needed to indicate possible
* problem conditions, otherwise the LSP_flag is cleared.
*
* Returns:
* resonance flag
*/
static Word16 check_lsp( Word16 *count, Float32 *lsp )
{
Float32 dist, dist_min1, dist_min2, dist_th;
Word32 i;
/*
* Check for a resonance:
* Find minimum distance between lsp[i] and lsp[i+1]
*/
dist_min1 = FLT_MAX;
for ( i = 3; i < 8; i++ ) {
dist = lsp[i] - lsp[i + 1];
if ( dist < dist_min1 ) {
dist_min1 = dist;
}
}
dist_min2 = FLT_MAX;
for ( i = 1; i < 3; i++ ) {
dist = lsp[i] - lsp[i + 1];
if ( dist < dist_min2 ) {
dist_min2 = dist;
}
}
if ( lsp[1] > 0.98F ) {
dist_th = 0.018F;
}
else if ( lsp[1] > 0.93F ) {
dist_th = 0.024F;
}
else {
dist_th = 0.034F;
}
if ( ( dist_min1 < 0.046F ) || ( dist_min2 < dist_th ) ) {
*count += 1;
}
else {
*count = 0;
}
/* Need 12 consecutive frames to set the flag */
if ( *count >= 12 ) {
*count = 12;
return 1;
}
else {
return 0;
}
}
/*
* Weight_Ai
*
*
* Parameters:
* a I: LPC coefficients [M+1]
* fac I: Spectral expansion factors. [M+1]
* a_exp O: Spectral expanded LPC coefficients [M+1]
*
* Function:
* Spectral expansion of LP coefficients
*
* Returns:
* void
*/
static void Weight_Ai( Float32 a[], const Float32 fac[], Float32 a_exp[] )
{
Word32 i;
a_exp[0] = a[0];
for ( i = 1; i <= M; 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( Float32 a[], Float32 x[], Float32 y[] )
{
Float32 s;
Word32 i;
for ( i = 0; i < L_SUBFR; 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 [M+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( Float32 a[], Float32 x[], Float32 y[], Float32 mem[],
Word16 update )
{
Float64 tmp[50];
Float64 sum;
Float64 *yy;
Word32 i;
/* Copy mem[] to yy[] */
yy = tmp;
for ( i = 0; i < M; i++ ) {
*yy++ = mem[i];
}
/* Do the filtering. */
for ( i = 0; i < L_SUBFR; 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] = ( Float32 )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] = ( Float32 )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] = ( Float32 )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] = ( Float32 )yy[ - 1];
}
/* Update of memory if update==1 */
if ( update != 0 ) {
for ( i = 0; i < M; 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 Word32 pre_big( enum Mode mode, const Float32 gamma1[], const Float32
gamma1_12k2[], const Float32 gamma2[], Float32 A_t[], Word16 frame_offset,
Float32 speech[], Float32 mem_w[], Float32 wsp[] )
{
Float32 Ap1[MP1], Ap2[MP1];
Word32 offset, i;
/* A(z) with spectral expansion */
const Float32 *g1;
g1 = gamma1_12k2;
if ( mode <= MR795 ) {
g1 = gamma1;
}
offset = 0;
if ( frame_offset > 0 ) {
offset = MP1 << 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 += MP1;
frame_offset += L_SUBFR;
}
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( Float32 sig[], Word32 L_frame, Word32 lag_max, Word32
lag_min, Float32 corr[] )
{
Word32 i, j;
Float32 *p, *p1;
Float32 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -