📄 c4t64fx.c
字号:
/*------------------------------------------------------------------------*
* C4T64FX.C *
*------------------------------------------------------------------------*
* Performs algebraic codebook search for higher modes *
*------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*
* Function ACELP_4t64_fx() *
* ~~~~~~~~~~~~~~~~~~~~~~~~~ *
* 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. *
* 4 tracks x 16 positions per track = 64 samples. *
* *
* 20 bits --> 4 pulses in a frame of 64 samples. *
* 36 bits --> 8 pulses in a frame of 64 samples. *
* 44 bits --> 10 pulses in a frame of 64 samples. *
* 52 bits --> 12 pulses in a frame of 64 samples. *
* 64 bits --> 16 pulses in a frame of 64 samples. *
* 72 bits --> 18 pulses in a frame of 64 samples. *
* 88 bits --> 24 pulses in a frame of 64 samples. *
* *
* All pulses can have two (2) possible amplitudes: +1 or -1. *
* Each pulse can have sixteen (16) possible positions. *
*-----------------------------------------------------------------------*/
#include "typedef.h"
#include "basic_op.h"
#include "math_op.h"
#include "acelp.h"
#include "count.h"
#include "cnst.h"
#include "q_pulse.h"
static Word16 tipos[36] = {
0, 1, 2, 3, /* starting point &ipos[0], 1st iter */
1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */
2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */
3, 0, 1, 2, /* starting point &ipos[12], 4th iter */
0, 1, 2, 3,
1, 2, 3, 0,
2, 3, 0, 1,
3, 0, 1, 2,
0, 1, 2, 3}; /* end point for 24 pulses &ipos[35], 4th iter */
#define NB_PULSE_MAX 24
#define L_SUBFR 64
#define NB_TRACK 4
#define STEP 4
#define NB_POS 16
#define MSIZE 256
#define NB_MAX 8
#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK-1)/NB_TRACK)
/* locals functions */
static void cor_h_vec(
Word16 h[], /* (i) scaled impulse response */
Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
Word16 track, /* (i) track to use */
Word16 sign[], /* (i) sign vector */
Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
Word16 cor[] /* (o) result of correlation (NB_POS elements) */
);
static void search_ixiy(
Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */
Word16 track_x, /* (i) track of pulse 1 */
Word16 track_y, /* (i) track of pulse 2 */
Word16 * ps, /* (i/o) correlation of all fixed pulses */
Word16 * alp, /* (i/o) energy of all fixed pulses */
Word16 * ix, /* (o) position of pulse 1 */
Word16 * iy, /* (o) position of pulse 2 */
Word16 dn[], /* (i) corr. between target and h[] */
Word16 dn2[], /* (i) vector of selected positions */
Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */
Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */
Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */
);
void ACELP_4t64_fx(
Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
Word16 cn[], /* (i) <12b : residual after long term prediction */
Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
Word16 ser_size, /* (i) : bit rate */
Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */
/* (o) : index (36): 9+9+9+9 = 36 bits. */
/* (o) : index (44): 13+9+13+9 = 44 bits. */
/* (o) : index (52): 13+13+13+13 = 52 bits. */
/* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
/* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
/* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
)
{
Word16 i, j, k, st, ix, iy, pos, index, track, nb_pulse, nbiter;
Word16 psk, ps, alpk, alp, val, k_cn, k_dn, exp;
Word16 *p0, *p1, *p2, *p3, *psign;
Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf, h_shift;
Word32 s, cor, L_tmp, L_index;
Word16 dn2[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR];
Word16 ind[NPMAXPT * NB_TRACK];
Word16 codvec[NB_PULSE_MAX], nbpos[10];
Word16 cor_x[NB_POS], cor_y[NB_POS], pos_max[NB_TRACK];
Word16 h_buf[4 * L_SUBFR];
Word16 rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE];
Word16 ipos[NB_PULSE_MAX];
switch (nbbits)
{
case 20: /* 20 bits, 4 pulses, 4 tracks */
nbiter = 4; move16(); /* 4x16x16=1024 loop */
alp = 8192; move16(); /* alp = 2.0 (Q12) */
nb_pulse = 4; move16();
nbpos[0] = 4; move16();
nbpos[1] = 8; move16();
break;
case 36: /* 36 bits, 8 pulses, 4 tracks */
nbiter = 4; move16(); /* 4x20x16=1280 loop */
alp = 4096; move16(); /* alp = 1.0 (Q12) */
nb_pulse = 8; move16();
nbpos[0] = 4; move16();
nbpos[1] = 8; move16();
nbpos[2] = 8; move16();
break;
case 44: /* 44 bits, 10 pulses, 4 tracks */
nbiter = 4; move16(); /* 4x26x16=1664 loop */
alp = 4096; move16(); /* alp = 1.0 (Q12) */
nb_pulse = 10; move16();
nbpos[0] = 4; move16();
nbpos[1] = 6; move16();
nbpos[2] = 8; move16();
nbpos[3] = 8; move16();
break;
case 52: /* 52 bits, 12 pulses, 4 tracks */
nbiter = 4; move16(); /* 4x26x16=1664 loop */
alp = 4096; move16(); /* alp = 1.0 (Q12) */
nb_pulse = 12; move16();
nbpos[0] = 4; move16();
nbpos[1] = 6; move16();
nbpos[2] = 8; move16();
nbpos[3] = 8; move16();
break;
case 64: /* 64 bits, 16 pulses, 4 tracks */
nbiter = 3; move16(); /* 3x36x16=1728 loop */
alp = 3277; move16(); /* alp = 0.8 (Q12) */
nb_pulse = 16; move16();
nbpos[0] = 4; move16();
nbpos[1] = 4; move16();
nbpos[2] = 6; move16();
nbpos[3] = 6; move16();
nbpos[4] = 8; move16();
nbpos[5] = 8; move16();
break;
case 72: /* 72 bits, 18 pulses, 4 tracks */
nbiter = 3; move16(); /* 3x35x16=1680 loop */
alp = 3072; move16(); /* alp = 0.75 (Q12) */
nb_pulse = 18; move16();
nbpos[0] = 2; move16();
nbpos[1] = 3; move16();
nbpos[2] = 4; move16();
nbpos[3] = 5; move16();
nbpos[4] = 6; move16();
nbpos[5] = 7; move16();
nbpos[6] = 8; move16();
break;
case 88: /* 88 bits, 24 pulses, 4 tracks */
test();move16();
if (sub(ser_size, 462) > 0)
nbiter = 1;
else
nbiter = 2; /* 2x53x16=1696 loop */
alp = 2048; move16(); /* alp = 0.5 (Q12) */
nb_pulse = 24; move16();
nbpos[0] = 2; move16();
nbpos[1] = 2; move16();
nbpos[2] = 3; move16();
nbpos[3] = 4; move16();
nbpos[4] = 5; move16();
nbpos[5] = 6; move16();
nbpos[6] = 7; move16();
nbpos[7] = 8; move16();
nbpos[8] = 8; move16();
nbpos[9] = 8; move16();
break;
default:
nbiter = 0;
alp = 0;
nb_pulse = 0;
}
for (i = 0; i < nb_pulse; i++)
{
codvec[i] = i; move16();
}
/*----------------------------------------------------------------*
* Find sign for each pulse position. *
*----------------------------------------------------------------*/
/* calculate energy for normalization of cn[] and dn[] */
/* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
s = Dot_product12(cn, cn, L_SUBFR, &exp);
Isqrt_n(&s, &exp);
s = L_shl(s, add(exp, 5)); /* saturation can occur here */
k_cn = round(s);
/* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
s = Dot_product12(dn, dn, L_SUBFR, &exp);
Isqrt_n(&s, &exp);
k_dn = round(L_shl(s, add(exp, 5 + 3))); /* k_dn = 256..4096 */
k_dn = mult_r(alp, k_dn); /* alp in Q12 */
/* mix normalized cn[] and dn[] */
for (i = 0; i < L_SUBFR; i++)
{
s = L_mac(L_mult(k_cn, cn[i]), k_dn, dn[i]);
dn2[i] = extract_h(L_shl(s, 8)); move16();
}
/* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */
for (k = 0; k < NB_TRACK; k++)
{
for (i = k; i < L_SUBFR; i += STEP)
{
val = dn[i]; move16();
ps = dn2[i]; move16();
test();
if (ps >= 0)
{
sign[i] = 32767; move16(); /* sign = +1 (Q12) */
vec[i] = -32768; move16();
} else
{
sign[i] = -32768; move16(); /* sign = -1 (Q12) */
vec[i] = 32767; move16();
val = negate(val);
ps = negate(ps);
}
dn[i] = val; move16(); /* modify dn[] according to the fixed sign */
dn2[i] = ps; move16(); /* dn2[] = mix of dn[] and cn[] */
}
}
/*----------------------------------------------------------------*
* Select NB_MAX position per track according to max of dn2[]. *
*----------------------------------------------------------------*/
pos = 0;
for (i = 0; i < NB_TRACK; i++)
{
for (k = 0; k < NB_MAX; k++)
{
ps = -1; move16();
for (j = i; j < L_SUBFR; j += STEP)
{
test();
if (sub(dn2[j], ps) > 0)
{
ps = dn2[j]; move16();
pos = j; move16();
}
}
move16();
dn2[pos] = sub(k, NB_MAX); /* dn2 < 0 when position is selected */
test();
if (k == 0)
{
pos_max[i] = pos; move16();
}
}
}
/*--------------------------------------------------------------*
* Scale h[] to avoid overflow and to get maximum of precision *
* on correlation. *
* *
* Maximum of h[] (h[0]) is fixed to 2048 (MAX16 / 16). *
* ==> This allow addition of 16 pulses without saturation. *
* *
* Energy worst case (on resonant impulse response), *
* - energy of h[] is approximately MAX/16. *
* - During search, the energy is divided by 8 to avoid *
* overflow on "alp". (energy of h[] = MAX/128). *
* ==> "alp" worst case detected is 22854 on sinusoidal wave. *
*--------------------------------------------------------------*/
/* impulse response buffer for fast computation */
h = h_buf; move16();
h_inv = h_buf + (2 * L_SUBFR); move16();
for (i = 0; i < L_SUBFR; i++)
{
*h++ = 0; move16();
*h_inv++ = 0; move16();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -