Home | History | Annotate | Download | only in src
      1 /*
      2  ** Copyright 2003-2010, VisualOn, Inc.
      3  **
      4  ** Licensed under the Apache License, Version 2.0 (the "License");
      5  ** you may not use this file except in compliance with the License.
      6  ** You may obtain a copy of the License at
      7  **
      8  **     http://www.apache.org/licenses/LICENSE-2.0
      9  **
     10  ** Unless required by applicable law or agreed to in writing, software
     11  ** distributed under the License is distributed on an "AS IS" BASIS,
     12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  ** See the License for the specific language governing permissions and
     14  ** limitations under the License.
     15  */
     16 
     17 /************************************************************************
     18 *      File: c2t64fx.c                                                  *
     19 *                                                                       *
     20 *	   Description:Performs algebraic codebook search for 6.60kbits mode*
     21 *                                                                       *
     22 *************************************************************************/
     23 
     24 #include "typedef.h"
     25 #include "basic_op.h"
     26 #include "math_op.h"
     27 #include "acelp.h"
     28 #include "cnst.h"
     29 
     30 #define NB_TRACK  2
     31 #define STEP      2
     32 #define NB_POS    32
     33 #define MSIZE     1024
     34 
     35 /*************************************************************************
     36 * Function:  ACELP_2t64_fx()                                             *
     37 *                                                                        *
     38 * 12 bits algebraic codebook.                                            *
     39 * 2 tracks x 32 positions per track = 64 samples.                        *
     40 *                                                                        *
     41 * 12 bits --> 2 pulses in a frame of 64 samples.                         *
     42 *                                                                        *
     43 * All pulses can have two (2) possible amplitudes: +1 or -1.             *
     44 * Each pulse can have 32 possible positions.                             *
     45 **************************************************************************/
     46 
     47 void ACELP_2t64_fx(
     48 		Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */
     49 		Word16 cn[],                          /* (i) <12b : residual after long term prediction         */
     50 		Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */
     51 		Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */
     52 		Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */
     53 		Word16 * index                        /* (o) : index (12): 5+1+5+1 = 11 bits.                   */
     54 		)
     55 {
     56 	Word32 i, j, k, i0, i1, ix, iy, pos, pos2;
     57 	Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;
     58 	Word16 alp, val, exp, k_cn, k_dn;
     59 	Word16 *p0, *p1, *p2, *psign;
     60 	Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;
     61 
     62 	Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];
     63 	Word16 h_buf[4 * L_SUBFR] = {0};
     64 	Word16 rrixix[NB_TRACK][NB_POS];
     65 	Word16 rrixiy[MSIZE];
     66 	Word32 s, cor;
     67 
     68 	/*----------------------------------------------------------------*
     69 	 * Find sign for each pulse position.                             *
     70 	 *----------------------------------------------------------------*/
     71 	alp = 8192;                              /* alp = 2.0 (Q12) */
     72 
     73 	/* calculate energy for normalization of cn[] and dn[] */
     74 	/* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
     75 #ifdef ASM_OPT             /* asm optimization branch */
     76 	s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);
     77 #else
     78 	s = Dot_product12(cn, cn, L_SUBFR, &exp);
     79 #endif
     80 
     81 	Isqrt_n(&s, &exp);
     82 	s = L_shl(s, add1(exp, 5));
     83 	k_cn = vo_round(s);
     84 
     85 	/* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
     86 #ifdef ASM_OPT                  /* asm optimization branch */
     87 	s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);
     88 #else
     89 	s = Dot_product12(dn, dn, L_SUBFR, &exp);
     90 #endif
     91 
     92 	Isqrt_n(&s, &exp);
     93 	k_dn = vo_round(L_shl(s, (exp + 8)));    /* k_dn = 256..4096 */
     94 	k_dn = vo_mult_r(alp, k_dn);              /* alp in Q12 */
     95 
     96 	/* mix normalized cn[] and dn[] */
     97 	p0 = cn;
     98 	p1 = dn;
     99 	p2 = dn2;
    100 
    101 	for (i = 0; i < L_SUBFR/4; i++)
    102 	{
    103 		s = (k_cn* (*p0++))+(k_dn * (*p1++));
    104 		*p2++ = s >> 7;
    105 		s = (k_cn* (*p0++))+(k_dn * (*p1++));
    106 		*p2++ = s >> 7;
    107 		s = (k_cn* (*p0++))+(k_dn * (*p1++));
    108 		*p2++ = s >> 7;
    109 		s = (k_cn* (*p0++))+(k_dn * (*p1++));
    110 		*p2++ = s >> 7;
    111 	}
    112 
    113 	/* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[]    */
    114 	for (i = 0; i < L_SUBFR; i ++)
    115 	{
    116 		val = dn[i];
    117 		ps = dn2[i];
    118 		if (ps >= 0)
    119 		{
    120 			sign[i] = 32767;             /* sign = +1 (Q12) */
    121 			vec[i] = -32768;
    122 		} else
    123 		{
    124 			sign[i] = -32768;            /* sign = -1 (Q12) */
    125 			vec[i] = 32767;
    126 			dn[i] = -val;
    127 		}
    128 	}
    129 	/*------------------------------------------------------------*
    130 	 * Compute h_inv[i].                                          *
    131 	 *------------------------------------------------------------*/
    132 	/* impulse response buffer for fast computation */
    133 	h = h_buf + L_SUBFR;
    134 	h_inv = h + (L_SUBFR<<1);
    135 
    136 	for (i = 0; i < L_SUBFR; i++)
    137 	{
    138 		h[i] = H[i];
    139 		h_inv[i] = vo_negate(h[i]);
    140 	}
    141 
    142 	/*------------------------------------------------------------*
    143 	 * Compute rrixix[][] needed for the codebook search.         *
    144 	 * Result is multiplied by 0.5                                *
    145 	 *------------------------------------------------------------*/
    146 	/* Init pointers to last position of rrixix[] */
    147 	p0 = &rrixix[0][NB_POS - 1];
    148 	p1 = &rrixix[1][NB_POS - 1];
    149 
    150 	ptr_h1 = h;
    151 	cor = 0x00010000L;                          /* for rounding */
    152 	for (i = 0; i < NB_POS; i++)
    153 	{
    154 		cor += ((*ptr_h1) * (*ptr_h1) << 1);
    155 		ptr_h1++;
    156 		*p1-- = (extract_h(cor) >> 1);
    157 		cor += ((*ptr_h1) * (*ptr_h1) << 1);
    158 		ptr_h1++;
    159 		*p0-- = (extract_h(cor) >> 1);
    160 	}
    161 
    162 	/*------------------------------------------------------------*
    163 	 * Compute rrixiy[][] needed for the codebook search.         *
    164 	 *------------------------------------------------------------*/
    165 	pos = MSIZE - 1;
    166 	pos2 = MSIZE - 2;
    167 	ptr_hf = h + 1;
    168 
    169 	for (k = 0; k < NB_POS; k++)
    170 	{
    171 		p1 = &rrixiy[pos];
    172 		p0 = &rrixiy[pos2];
    173 		cor = 0x00008000L;                        /* for rounding */
    174 		ptr_h1 = h;
    175 		ptr_h2 = ptr_hf;
    176 
    177 		for (i = (k + 1); i < NB_POS; i++)
    178 		{
    179 			cor += ((*ptr_h1) * (*ptr_h2))<<1;
    180 			ptr_h1++;
    181 			ptr_h2++;
    182 			*p1 = extract_h(cor);
    183 			cor += ((*ptr_h1) * (*ptr_h2))<<1;
    184 			ptr_h1++;
    185 			ptr_h2++;
    186 			*p0 = extract_h(cor);
    187 
    188 			p1 -= (NB_POS + 1);
    189 			p0 -= (NB_POS + 1);
    190 		}
    191 		cor += ((*ptr_h1) * (*ptr_h2))<<1;
    192 		ptr_h1++;
    193 		ptr_h2++;
    194 		*p1 = extract_h(cor);
    195 
    196 		pos -= NB_POS;
    197 		pos2--;
    198 		ptr_hf += STEP;
    199 	}
    200 
    201 	/*------------------------------------------------------------*
    202 	 * Modification of rrixiy[][] to take signs into account.     *
    203 	 *------------------------------------------------------------*/
    204 	p0 = rrixiy;
    205 	for (i = 0; i < L_SUBFR; i += STEP)
    206 	{
    207 		psign = sign;
    208 		if (psign[i] < 0)
    209 		{
    210 			psign = vec;
    211 		}
    212 		for (j = 1; j < L_SUBFR; j += STEP)
    213 		{
    214 			*p0 = vo_mult(*p0, psign[j]);
    215 			p0++;
    216 		}
    217 	}
    218 	/*-------------------------------------------------------------------*
    219 	 * search 2 pulses:                                                  *
    220 	 * ~@~~~~~~~~~~~~~~                                                  *
    221 	 * 32 pos x 32 pos = 1024 tests (all combinaisons is tested)         *
    222 	 *-------------------------------------------------------------------*/
    223 	p0 = rrixix[0];
    224 	p1 = rrixix[1];
    225 	p2 = rrixiy;
    226 
    227 	psk = -1;
    228 	alpk = 1;
    229 	ix = 0;
    230 	iy = 1;
    231 
    232 	for (i0 = 0; i0 < L_SUBFR; i0 += STEP)
    233 	{
    234 		ps1 = dn[i0];
    235 		alp1 = (*p0++);
    236 		pos = -1;
    237 		for (i1 = 1; i1 < L_SUBFR; i1 += STEP)
    238 		{
    239 			ps2 = add1(ps1, dn[i1]);
    240 			alp2 = add1(alp1, add1(*p1++, *p2++));
    241 			sq = vo_mult(ps2, ps2);
    242 			s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1);
    243 			if (s > 0)
    244 			{
    245 				psk = sq;
    246 				alpk = alp2;
    247 				pos = i1;
    248 			}
    249 		}
    250 		p1 -= NB_POS;
    251 		if (pos >= 0)
    252 		{
    253 			ix = i0;
    254 			iy = pos;
    255 		}
    256 	}
    257 	/*-------------------------------------------------------------------*
    258 	 * Build the codeword, the filtered codeword and index of codevector.*
    259 	 *-------------------------------------------------------------------*/
    260 
    261 	for (i = 0; i < L_SUBFR; i++)
    262 	{
    263 		code[i] = 0;
    264 	}
    265 
    266 	i0 = (ix >> 1);                       /* pos of pulse 1 (0..31) */
    267 	i1 = (iy >> 1);                       /* pos of pulse 2 (0..31) */
    268 	if (sign[ix] > 0)
    269 	{
    270 		code[ix] = 512;                     /* codeword in Q9 format */
    271 		p0 = h - ix;
    272 	} else
    273 	{
    274 		code[ix] = -512;
    275 		i0 += NB_POS;
    276 		p0 = h_inv - ix;
    277 	}
    278 	if (sign[iy] > 0)
    279 	{
    280 		code[iy] = 512;
    281 		p1 = h - iy;
    282 	} else
    283 	{
    284 		code[iy] = -512;
    285 		i1 += NB_POS;
    286 		p1 = h_inv - iy;
    287 	}
    288 	*index = add1((i0 << 6), i1);
    289 	for (i = 0; i < L_SUBFR; i++)
    290 	{
    291 		y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3);
    292 	}
    293 	return;
    294 }
    295 
    296 
    297 
    298