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 if (s > INT_MAX - 0x8000) { 84 s = INT_MAX - 0x8000; 85 } 86 k_cn = vo_round(s); 87 88 /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */ 89 #ifdef ASM_OPT /* asm optimization branch */ 90 s = Dot_product12_asm(dn, dn, L_SUBFR, &exp); 91 #else 92 s = Dot_product12(dn, dn, L_SUBFR, &exp); 93 #endif 94 95 Isqrt_n(&s, &exp); 96 k_dn = voround(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */ 97 k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */ 98 99 /* mix normalized cn[] and dn[] */ 100 p0 = cn; 101 p1 = dn; 102 p2 = dn2; 103 104 for (i = 0; i < L_SUBFR/4; i++) 105 { 106 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 107 *p2++ = s >> 7; 108 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 109 *p2++ = s >> 7; 110 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 111 *p2++ = s >> 7; 112 s = (k_cn* (*p0++))+(k_dn * (*p1++)); 113 *p2++ = s >> 7; 114 } 115 116 /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */ 117 for (i = 0; i < L_SUBFR; i ++) 118 { 119 val = dn[i]; 120 ps = dn2[i]; 121 if (ps >= 0) 122 { 123 sign[i] = 32767; /* sign = +1 (Q12) */ 124 vec[i] = -32768; 125 } else 126 { 127 sign[i] = -32768; /* sign = -1 (Q12) */ 128 vec[i] = 32767; 129 dn[i] = -val; 130 } 131 } 132 /*------------------------------------------------------------* 133 * Compute h_inv[i]. * 134 *------------------------------------------------------------*/ 135 /* impulse response buffer for fast computation */ 136 h = h_buf + L_SUBFR; 137 h_inv = h + (L_SUBFR<<1); 138 139 for (i = 0; i < L_SUBFR; i++) 140 { 141 h[i] = H[i]; 142 h_inv[i] = vo_negate(h[i]); 143 } 144 145 /*------------------------------------------------------------* 146 * Compute rrixix[][] needed for the codebook search. * 147 * Result is multiplied by 0.5 * 148 *------------------------------------------------------------*/ 149 /* Init pointers to last position of rrixix[] */ 150 p0 = &rrixix[0][NB_POS - 1]; 151 p1 = &rrixix[1][NB_POS - 1]; 152 153 ptr_h1 = h; 154 cor = 0x00010000L; /* for rounding */ 155 for (i = 0; i < NB_POS; i++) 156 { 157 cor += ((*ptr_h1) * (*ptr_h1) << 1); 158 ptr_h1++; 159 *p1-- = (extract_h(cor) >> 1); 160 cor += ((*ptr_h1) * (*ptr_h1) << 1); 161 ptr_h1++; 162 *p0-- = (extract_h(cor) >> 1); 163 } 164 165 /*------------------------------------------------------------* 166 * Compute rrixiy[][] needed for the codebook search. * 167 *------------------------------------------------------------*/ 168 pos = MSIZE - 1; 169 pos2 = MSIZE - 2; 170 ptr_hf = h + 1; 171 172 for (k = 0; k < NB_POS; k++) 173 { 174 p1 = &rrixiy[pos]; 175 p0 = &rrixiy[pos2]; 176 cor = 0x00008000L; /* for rounding */ 177 ptr_h1 = h; 178 ptr_h2 = ptr_hf; 179 180 for (i = (k + 1); i < NB_POS; i++) 181 { 182 cor += ((*ptr_h1) * (*ptr_h2))<<1; 183 ptr_h1++; 184 ptr_h2++; 185 *p1 = extract_h(cor); 186 cor += ((*ptr_h1) * (*ptr_h2))<<1; 187 ptr_h1++; 188 ptr_h2++; 189 *p0 = extract_h(cor); 190 191 p1 -= (NB_POS + 1); 192 p0 -= (NB_POS + 1); 193 } 194 cor += ((*ptr_h1) * (*ptr_h2))<<1; 195 ptr_h1++; 196 ptr_h2++; 197 *p1 = extract_h(cor); 198 199 pos -= NB_POS; 200 pos2--; 201 ptr_hf += STEP; 202 } 203 204 /*------------------------------------------------------------* 205 * Modification of rrixiy[][] to take signs into account. * 206 *------------------------------------------------------------*/ 207 p0 = rrixiy; 208 for (i = 0; i < L_SUBFR; i += STEP) 209 { 210 psign = sign; 211 if (psign[i] < 0) 212 { 213 psign = vec; 214 } 215 for (j = 1; j < L_SUBFR; j += STEP) 216 { 217 *p0 = vo_mult(*p0, psign[j]); 218 p0++; 219 } 220 } 221 /*-------------------------------------------------------------------* 222 * search 2 pulses: * 223 * ~@~~~~~~~~~~~~~~ * 224 * 32 pos x 32 pos = 1024 tests (all combinaisons is tested) * 225 *-------------------------------------------------------------------*/ 226 p0 = rrixix[0]; 227 p1 = rrixix[1]; 228 p2 = rrixiy; 229 230 psk = -1; 231 alpk = 1; 232 ix = 0; 233 iy = 1; 234 235 for (i0 = 0; i0 < L_SUBFR; i0 += STEP) 236 { 237 ps1 = dn[i0]; 238 alp1 = (*p0++); 239 pos = -1; 240 for (i1 = 1; i1 < L_SUBFR; i1 += STEP) 241 { 242 ps2 = add1(ps1, dn[i1]); 243 alp2 = add1(alp1, add1(*p1++, *p2++)); 244 sq = vo_mult(ps2, ps2); 245 s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1); 246 if (s > 0) 247 { 248 psk = sq; 249 alpk = alp2; 250 pos = i1; 251 } 252 } 253 p1 -= NB_POS; 254 if (pos >= 0) 255 { 256 ix = i0; 257 iy = pos; 258 } 259 } 260 /*-------------------------------------------------------------------* 261 * Build the codeword, the filtered codeword and index of codevector.* 262 *-------------------------------------------------------------------*/ 263 264 for (i = 0; i < L_SUBFR; i++) 265 { 266 code[i] = 0; 267 } 268 269 i0 = (ix >> 1); /* pos of pulse 1 (0..31) */ 270 i1 = (iy >> 1); /* pos of pulse 2 (0..31) */ 271 if (sign[ix] > 0) 272 { 273 code[ix] = 512; /* codeword in Q9 format */ 274 p0 = h - ix; 275 } else 276 { 277 code[ix] = -512; 278 i0 += NB_POS; 279 p0 = h_inv - ix; 280 } 281 if (sign[iy] > 0) 282 { 283 code[iy] = 512; 284 p1 = h - iy; 285 } else 286 { 287 code[iy] = -512; 288 i1 += NB_POS; 289 p1 = h_inv - iy; 290 } 291 *index = add1((i0 << 6), i1); 292 for (i = 0; i < L_SUBFR; i++) 293 { 294 y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3); 295 } 296 return; 297 } 298 299 300 301