c2t64fx.c revision 3cdaed88daeeebfe05e7913837f41c2d92f411cc
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// There are many integer overflows in this function, as none of them appear to 48// lead to memory accesses, and performing the appropriate checks will lead 49// to considerably larger code, mark this as ignore. 50__attribute__((no_sanitize("integer"))) 51void ACELP_2t64_fx( 52 Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */ 53 Word16 cn[], /* (i) <12b : residual after long term prediction */ 54 Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */ 55 Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */ 56 Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */ 57 Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */ 58 ) 59{ 60 Word32 i, j, k, i0, i1, ix, iy, pos, pos2; 61 Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq; 62 Word16 alp, val, exp, k_cn, k_dn; 63 Word16 *p0, *p1, *p2, *psign; 64 Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf; 65 66 Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR]; 67 Word16 h_buf[4 * L_SUBFR] = {0}; 68 Word16 rrixix[NB_TRACK][NB_POS]; 69 Word16 rrixiy[MSIZE]; 70 Word32 s, cor; 71 72 /*----------------------------------------------------------------* 73 * Find sign for each pulse position. * 74 *----------------------------------------------------------------*/ 75 alp = 8192; /* alp = 2.0 (Q12) */ 76 77 /* calculate energy for normalization of cn[] and dn[] */ 78 /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */ 79#ifdef ASM_OPT /* asm optimization branch */ 80 s = Dot_product12_asm(cn, cn, L_SUBFR, &exp); 81#else 82 s = Dot_product12(cn, cn, L_SUBFR, &exp); 83#endif 84 85 Isqrt_n(&s, &exp); 86 s = L_shl(s, add1(exp, 5)); 87 k_cn = vo_round(s); 88 89 /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */ 90#ifdef ASM_OPT /* asm optimization branch */ 91 s = Dot_product12_asm(dn, dn, L_SUBFR, &exp); 92#else 93 s = Dot_product12(dn, dn, L_SUBFR, &exp); 94#endif 95 96 Isqrt_n(&s, &exp); 97 k_dn = vo_round(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */ 98 k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */ 99 100 /* mix normalized cn[] and dn[] */ 101 p0 = cn; 102 p1 = dn; 103 p2 = dn2; 104 105 for (i = 0; i < L_SUBFR/4; i++) 106 { 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 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 112 *p2++ = s >> 7; 113 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 114 *p2++ = s >> 7; 115 } 116 117 /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */ 118 for (i = 0; i < L_SUBFR; i ++) 119 { 120 val = dn[i]; 121 ps = dn2[i]; 122 if (ps >= 0) 123 { 124 sign[i] = 32767; /* sign = +1 (Q12) */ 125 vec[i] = -32768; 126 } else 127 { 128 sign[i] = -32768; /* sign = -1 (Q12) */ 129 vec[i] = 32767; 130 dn[i] = -val; 131 } 132 } 133 /*------------------------------------------------------------* 134 * Compute h_inv[i]. * 135 *------------------------------------------------------------*/ 136 /* impulse response buffer for fast computation */ 137 h = h_buf + L_SUBFR; 138 h_inv = h + (L_SUBFR<<1); 139 140 for (i = 0; i < L_SUBFR; i++) 141 { 142 h[i] = H[i]; 143 h_inv[i] = vo_negate(h[i]); 144 } 145 146 /*------------------------------------------------------------* 147 * Compute rrixix[][] needed for the codebook search. * 148 * Result is multiplied by 0.5 * 149 *------------------------------------------------------------*/ 150 /* Init pointers to last position of rrixix[] */ 151 p0 = &rrixix[0][NB_POS - 1]; 152 p1 = &rrixix[1][NB_POS - 1]; 153 154 ptr_h1 = h; 155 cor = 0x00010000L; /* for rounding */ 156 for (i = 0; i < NB_POS; i++) 157 { 158 cor += ((*ptr_h1) * (*ptr_h1) << 1); 159 ptr_h1++; 160 *p1-- = (extract_h(cor) >> 1); 161 cor += ((*ptr_h1) * (*ptr_h1) << 1); 162 ptr_h1++; 163 *p0-- = (extract_h(cor) >> 1); 164 } 165 166 /*------------------------------------------------------------* 167 * Compute rrixiy[][] needed for the codebook search. * 168 *------------------------------------------------------------*/ 169 pos = MSIZE - 1; 170 pos2 = MSIZE - 2; 171 ptr_hf = h + 1; 172 173 for (k = 0; k < NB_POS; k++) 174 { 175 p1 = &rrixiy[pos]; 176 p0 = &rrixiy[pos2]; 177 cor = 0x00008000L; /* for rounding */ 178 ptr_h1 = h; 179 ptr_h2 = ptr_hf; 180 181 for (i = (k + 1); i < NB_POS; i++) 182 { 183 cor += ((*ptr_h1) * (*ptr_h2))<<1; 184 ptr_h1++; 185 ptr_h2++; 186 *p1 = extract_h(cor); 187 cor += ((*ptr_h1) * (*ptr_h2))<<1; 188 ptr_h1++; 189 ptr_h2++; 190 *p0 = extract_h(cor); 191 192 p1 -= (NB_POS + 1); 193 p0 -= (NB_POS + 1); 194 } 195 cor += ((*ptr_h1) * (*ptr_h2))<<1; 196 ptr_h1++; 197 ptr_h2++; 198 *p1 = extract_h(cor); 199 200 pos -= NB_POS; 201 pos2--; 202 ptr_hf += STEP; 203 } 204 205 /*------------------------------------------------------------* 206 * Modification of rrixiy[][] to take signs into account. * 207 *------------------------------------------------------------*/ 208 p0 = rrixiy; 209 for (i = 0; i < L_SUBFR; i += STEP) 210 { 211 psign = sign; 212 if (psign[i] < 0) 213 { 214 psign = vec; 215 } 216 for (j = 1; j < L_SUBFR; j += STEP) 217 { 218 *p0 = vo_mult(*p0, psign[j]); 219 p0++; 220 } 221 } 222 /*-------------------------------------------------------------------* 223 * search 2 pulses: * 224 * ~@~~~~~~~~~~~~~~ * 225 * 32 pos x 32 pos = 1024 tests (all combinaisons is tested) * 226 *-------------------------------------------------------------------*/ 227 p0 = rrixix[0]; 228 p1 = rrixix[1]; 229 p2 = rrixiy; 230 231 psk = -1; 232 alpk = 1; 233 ix = 0; 234 iy = 1; 235 236 for (i0 = 0; i0 < L_SUBFR; i0 += STEP) 237 { 238 ps1 = dn[i0]; 239 alp1 = (*p0++); 240 pos = -1; 241 for (i1 = 1; i1 < L_SUBFR; i1 += STEP) 242 { 243 ps2 = add1(ps1, dn[i1]); 244 alp2 = add1(alp1, add1(*p1++, *p2++)); 245 sq = vo_mult(ps2, ps2); 246 s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1); 247 if (s > 0) 248 { 249 psk = sq; 250 alpk = alp2; 251 pos = i1; 252 } 253 } 254 p1 -= NB_POS; 255 if (pos >= 0) 256 { 257 ix = i0; 258 iy = pos; 259 } 260 } 261 /*-------------------------------------------------------------------* 262 * Build the codeword, the filtered codeword and index of codevector.* 263 *-------------------------------------------------------------------*/ 264 265 for (i = 0; i < L_SUBFR; i++) 266 { 267 code[i] = 0; 268 } 269 270 i0 = (ix >> 1); /* pos of pulse 1 (0..31) */ 271 i1 = (iy >> 1); /* pos of pulse 2 (0..31) */ 272 if (sign[ix] > 0) 273 { 274 code[ix] = 512; /* codeword in Q9 format */ 275 p0 = h - ix; 276 } else 277 { 278 code[ix] = -512; 279 i0 += NB_POS; 280 p0 = h_inv - ix; 281 } 282 if (sign[iy] > 0) 283 { 284 code[iy] = 512; 285 p1 = h - iy; 286 } else 287 { 288 code[iy] = -512; 289 i1 += NB_POS; 290 p1 = h_inv - iy; 291 } 292 *index = add1((i0 << 6), i1); 293 for (i = 0; i < L_SUBFR; i++) 294 { 295 y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3); 296 } 297 return; 298} 299 300 301 302