www.pudn.com > source.rar > ACELP_CA.C
/* ITU-T G.729 Software Package Release 2 (November 2006) */
/*
ITU-T G.729 Annex C - Reference C code for floating point
implementation of G.729 Annex A
Version 1.01 of 15.September.98
*/
/*
----------------------------------------------------------------------
COPYRIGHT NOTICE
----------------------------------------------------------------------
ITU-T G.729 Annex C ANSI C source code
Copyright (C) 1998, AT&T, France Telecom, NTT, University of
Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
/*
File : ACELP_CA.C
Used for the floating point version of G.729A only
(not for G.729 main body)
*/
/*---------------------------------------------------------------------------*
* Function ACELP_code_A() *
* ~~~~~~~~~~~~~~~~~~~~~~~~ *
* Find Algebraic codebook for G.729A *
*--------------------------------------------------------------------------*/
/* L_SUBFR -> Lenght of subframe. */
/* NB_POS -> Number of positios for each pulse. */
/* STEP -> Step betweem position of the same pulse. */
/* MSIZE -> Size of vectors for cross-correlation between two pulses. */
#include "typedef.h"
#include "ld8a.h"
/* local routines definition */
static void cor_h(
FLOAT *H, /* (i) :Impulse response of filters */
FLOAT *rr /* (o) :Correlations of H[] */
);
static int d4i40_17_fast(/*(o) : Index of pulses positions. */
FLOAT dn[], /* (i) : Correlations between h[] and Xn[]. */
FLOAT *rr, /* (i) : Correlations of impulse response h[]. */
FLOAT h[], /* (i) : Impulse response of filters. */
FLOAT cod[], /* (o) : Selected algebraic codeword. */
FLOAT y[], /* (o) : Filtered algebraic codeword. */
int *sign /* (o) : Signs of 4 pulses. */
);
/*-----------------------------------------------------------------*
* Main ACELP function. *
*-----------------------------------------------------------------*/
int ACELP_code_A( /* (o) :index of pulses positions */
FLOAT x[], /* (i) :Target vector */
FLOAT h[], /* (i) :Inpulse response of filters */
int T0, /* (i) :Pitch lag */
FLOAT pitch_sharp, /* (i) :Last quantized pitch gain */
FLOAT code[], /* (o) :Innovative codebook */
FLOAT y[], /* (o) :Filtered innovative codebook */
int *sign /* (o) :Signs of 4 pulses */
)
{
int i, index;
static FLOAT Dn[L_SUBFR]; /* "static" to avoid stack overflow on PC */
static FLOAT rr[DIM_RR]; /* "static" to avoid stack overflow on PC */
/*-----------------------------------------------------------------*
* Include fixed-gain pitch contribution into impulse resp. h[] *
* Find correlations of h[] needed for the codebook search. *
*-----------------------------------------------------------------*/
if (T0 < L_SUBFR)
for (i = T0; i < L_SUBFR; i++)
h[i] += pitch_sharp * h[i-T0];
cor_h(h, rr);
/*-----------------------------------------------------------------*
* Compute correlation of target vector with impulse response. *
*-----------------------------------------------------------------*/
cor_h_x(h, x, Dn);
/*-----------------------------------------------------------------*
* Find innovative codebook. *
*-----------------------------------------------------------------*/
index = d4i40_17_fast(Dn, rr, h, code, y, sign);
/*-----------------------------------------------------------------*
* Compute innovation vector gain. *
* Include fixed-gain pitch contribution into code[]. *
*-----------------------------------------------------------------*/
if(T0 < L_SUBFR)
for (i = T0; i < L_SUBFR; i++)
code[i] += pitch_sharp*code[i-T0];
return index;
}
/*--------------------------------------------------------------------------*
* Function cor_h() *
* ~~~~~~~~~~~~~~~~~ *
* Compute correlations of h[] needed for the codebook search. *
*--------------------------------------------------------------------------*/
static void cor_h(
FLOAT *h, /* (i) :Impulse response of filters */
FLOAT *rr /* (o) :Correlations of H[] */
)
{
FLOAT *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4;
FLOAT *rri0i1, *rri0i2, *rri0i3, *rri0i4;
FLOAT *rri1i2, *rri1i3, *rri1i4;
FLOAT *rri2i3, *rri2i4;
FLOAT *p0, *p1, *p2, *p3, *p4;
FLOAT *ptr_hd, *ptr_hf, *ptr_h1, *ptr_h2;
FLOAT cor;
int i, k, ldec, l_fin_sup, l_fin_inf;
/*------------------------------------------------------------*
* Compute rri0i0[], rri1i1[], rri2i2[], rri3i3 and rri4i4[] *
*------------------------------------------------------------*/
/* Init pointers */
rri0i0 = rr;
rri1i1 = rri0i0 + NB_POS;
rri2i2 = rri1i1 + NB_POS;
rri3i3 = rri2i2 + NB_POS;
rri4i4 = rri3i3 + NB_POS;
rri0i1 = rri4i4 + NB_POS;
rri0i2 = rri0i1 + MSIZE;
rri0i3 = rri0i2 + MSIZE;
rri0i4 = rri0i3 + MSIZE;
rri1i2 = rri0i4 + MSIZE;
rri1i3 = rri1i2 + MSIZE;
rri1i4 = rri1i3 + MSIZE;
rri2i3 = rri1i4 + MSIZE;
rri2i4 = rri2i3 + MSIZE;
p0 = rri0i0 + NB_POS-1; /* Init pointers to last position of rrixix[] */
p1 = rri1i1 + NB_POS-1;
p2 = rri2i2 + NB_POS-1;
p3 = rri3i3 + NB_POS-1;
p4 = rri4i4 + NB_POS-1;
ptr_h1 = h;
cor = (F)0.0;
for(i=0; i 17 bits; 4 pulses in a frame of 40 samples *
* *
*------------------------------------------------------------------------*
* The code length is 40, containing 4 nonzero pulses i0, i1, i2, i3. *
* Each pulses can have 8 possible positions (positive or negative) *
* except i3 that have 16 possible positions. *
* *
* i0 (+-1) : 0, 5, 10, 15, 20, 25, 30, 35 *
* i1 (+-1) : 1, 6, 11, 16, 21, 26, 31, 36 *
* i2 (+-1) : 2, 7, 12, 17, 22, 27, 32, 37 *
* i3 (+-1) : 3, 8, 13, 18, 23, 28, 33, 38 *
* 4, 9, 14, 19, 24, 29, 34, 39 *
*------------------------------------------------------------------------*/
static int d4i40_17_fast(/*(o) : Index of pulses positions. */
FLOAT dn[], /* (i) : Correlations between h[] and Xn[]. */
FLOAT rr[], /* (i) : Correlations of impulse response h[]. */
FLOAT h[], /* (i) : Impulse response of filters. */
FLOAT cod[], /* (o) : Selected algebraic codeword. */
FLOAT y[], /* (o) : Filtered algebraic codeword. */
int *sign /* (o) : Signs of 4 pulses. */
)
{
int i0, i1, i2, i3, ip0, ip1, ip2, ip3;
int i, j, ix, iy, track, trk;
int prev_i0, i1_offset;
FLOAT psk, ps, ps0, ps1, ps2, sq, sq2;
FLOAT alpk, alp, max;
FLOAT s, alp0, alp1, alp2;
FLOAT *p0, *p1, *p2, *p3, *p4;
FLOAT sign_dn[L_SUBFR], sign_dn_inv[L_SUBFR], *psign;
FLOAT tmp_vect[NB_POS];
FLOAT *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4;
FLOAT *rri0i1, *rri0i2, *rri0i3, *rri0i4;
FLOAT *rri1i2, *rri1i3, *rri1i4;
FLOAT *rri2i3, *rri2i4;
FLOAT *ptr_rri0i3_i4;
FLOAT *ptr_rri1i3_i4;
FLOAT *ptr_rri2i3_i4;
FLOAT *ptr_rri3i3_i4;
/* Init pointers */
rri0i0 = rr;
rri1i1 = rri0i0 + NB_POS;
rri2i2 = rri1i1 + NB_POS;
rri3i3 = rri2i2 + NB_POS;
rri4i4 = rri3i3 + NB_POS;
rri0i1 = rri4i4 + NB_POS;
rri0i2 = rri0i1 + MSIZE;
rri0i3 = rri0i2 + MSIZE;
rri0i4 = rri0i3 + MSIZE;
rri1i2 = rri0i4 + MSIZE;
rri1i3 = rri1i2 + MSIZE;
rri1i4 = rri1i3 + MSIZE;
rri2i3 = rri1i4 + MSIZE;
rri2i4 = rri2i3 + MSIZE;
/*-----------------------------------------------------------------------*
* Chose the sign of the impulse. *
*-----------------------------------------------------------------------*/
for (i=0; i= (F)0.0)
{
sign_dn[i] = (F)1.0;
sign_dn_inv[i] = (F)-1.0;
}
else
{
sign_dn[i] = (F)-1.0;
sign_dn_inv[i] = (F)1.0;
dn[i] = -dn[i];
}
}
/*-------------------------------------------------------------------*
* Modification of rrixiy[] to take signs into account. *
*-------------------------------------------------------------------*/
p0 = rri0i1;
p1 = rri0i2;
p2 = rri0i3;
p3 = rri0i4;
for(i0=0; i0 (F)0.0) && ((prev_i0-j) != 0) )
{
max = dn[j];
i0 = j;
}
}
prev_i0 = i0;
j = i0 / 5; /* j = i0/5 */
p0 = rri2i2 + j;
ps1 = dn[i0];
alp1 = 0.5 * *p0;
/* i1 loop: 8 positions in track 2 */
p0 = ptr_rri2i3_i4 + (j<<3);
p1 = ptr_rri3i3_i4;
for (i1=track; i1 (F)0.0)
{
sq = sq2;
ps = ps2;
alp = alp2;
ix = i0;
iy = i1;
}
}
}
i0 = ix;
i1 = iy;
i1_offset = (i1/5) <<3; /* j = 8*(i1/5) */
/*------------------------------------------------------------------*
* depth first search 3, phase B: track 0 and 1. *
*------------------------------------------------------------------*/
ps0 = ps;
alp0 = alp;
sq = (F)-1.0;
alp = (F)1.0;
/* build vector for next loop to decrease complexity */
p0 = rri1i2 + i0/5;
p1 = ptr_rri1i3_i4 + i1/5;
p2 = rri1i1;
p3 = tmp_vect;
for (i3=1; i3 0.0)
{
sq = sq2;
alp = alp2;
ix = i2;
iy = i3;
}
}
}
/*----------------------------------------------------------------*
* depth first search 3: compare codevector with the best case. *
*----------------------------------------------------------------*/
s = alpk*sq - psk * alp;
if (s > (F)0.0)
{
psk = sq;
alpk = alp;
ip2 = i0;
ip3 = i1;
ip0 = ix;
ip1 = iy;
}
/*------------------------------------------------------------------*
* depth first search 4, phase A: track 3 and 0. *
*------------------------------------------------------------------*/
sq = (F)-1.0;
alp = (F)1.0;
/* i0 loop: 2 positions in track 3/4 */
prev_i0 = -1;
for (i=0; i<2; i++)
{
max = (F)-1.0;
/* search "dn[]" maximum position in track 3/4 */
for (j=track; j 0) && ((prev_i0 -j) != 0) )
{
max = dn[j];
i0 = j;
}
}
prev_i0 = i0;
j = i0/5;
p0 = ptr_rri3i3_i4 + j;
ps1 = dn[i0];
alp1 = 0.5 * *p0;
/* i1 loop: 8 positions in track 0 */
p0 = ptr_rri0i3_i4 + j;
p1 = rri0i0;
for (i1=0; i1 (F)0.0)
{
sq = sq2;
ps = ps2;
alp = alp2;
ix = i0;
iy = i1;
}
}
}
i0 = ix;
i1 = iy;
i1_offset = (i1/5) <<3; /* j = 8*(i1/5) */
/*------------------------------------------------------------------*
* depth first search 4, phase B: track 1 and 2. *
*------------------------------------------------------------------*/
ps0 = ps;
alp0 = alp;
sq = (F)-1.0;
alp = (F)1.0;
/* build vector for next loop to decrease complexity */
p0 = ptr_rri2i3_i4 + i0/5;
p1 = rri0i2 + i1_offset;
p2 = rri2i2;
p3 = tmp_vect;
for (i3=2; i3 (F)0.0)
{
sq = sq2;
alp = alp2;
ix = i2;
iy = i3;
}
}
}
/*----------------------------------------------------------------*
* depth first search 1: compare codevector with the best case. *
*----------------------------------------------------------------*/
s = alpk*sq - psk*alp;
if (s > (F)0.0)
{
psk = sq;
alpk = alp;
ip3 = i0;
ip0 = i1;
ip1 = ix;
ip2 = iy;
}
ptr_rri0i3_i4 = rri0i4;
ptr_rri1i3_i4 = rri1i4;
ptr_rri2i3_i4 = rri2i4;
ptr_rri3i3_i4 = rri4i4;
}
/* Set the sign of impulses */
i0 = (int)sign_dn[ip0];
i1 = (int)sign_dn[ip1];
i2 = (int)sign_dn[ip2];
i3 = (int)sign_dn[ip3];
/* Find the codeword corresponding to the selected positions */
for(i=0; i 0)
for(i=ip0, j=0; i 0)
for(i=ip1, j=0; i 0)
for(i=ip2, j=0; i 0)
for(i=ip3, j=0; i 0) i += 1;
if(i1 > 0) i += 2;
if(i2 > 0) i += 4;
if(i3 > 0) i += 8;
*sign = i;
ip0 = ip0/5;
ip1 = ip1/5;
ip2 = ip2/5;
i = ip3/5;
j = i*5;
j = ip3 -j -3;
ip3 = i*2+j;
i = ip0 + (ip1<<3)+ (ip2<<6)+ (ip3<<9);
return i;
}