FreeCalypso > hg > gsm-codec-lib
comparison libtwamr/c4_17pf.c @ 322:fc82b113977f
libtwamr: integrate c4_17pf.c
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 18 Apr 2024 19:41:41 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 321:5fc9a2d12048 | 322:fc82b113977f |
|---|---|
| 1 /* | |
| 2 ******************************************************************************** | |
| 3 * | |
| 4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 | |
| 5 * R99 Version 3.3.0 | |
| 6 * REL-4 Version 4.1.0 | |
| 7 * | |
| 8 ******************************************************************************** | |
| 9 * | |
| 10 * File : c4_17pf.c | |
| 11 * Purpose : Searches a 17 bit algebraic codebook containing 4 pulses | |
| 12 * in a frame of 40 samples. | |
| 13 * | |
| 14 ******************************************************************************** | |
| 15 */ | |
| 16 | |
| 17 /* | |
| 18 ******************************************************************************** | |
| 19 * MODULE INCLUDE FILE AND VERSION ID | |
| 20 ******************************************************************************** | |
| 21 */ | |
| 22 #include "namespace.h" | |
| 23 #include "c4_17pf.h" | |
| 24 | |
| 25 /* | |
| 26 ******************************************************************************** | |
| 27 * INCLUDE FILES | |
| 28 ******************************************************************************** | |
| 29 */ | |
| 30 #include "typedef.h" | |
| 31 #include "basic_op.h" | |
| 32 #include "no_count.h" | |
| 33 #include "inv_sqrt.h" | |
| 34 #include "cnst.h" | |
| 35 #include "cor_h.h" | |
| 36 #include "set_sign.h" | |
| 37 #include "graytab.h" | |
| 38 | |
| 39 /* | |
| 40 ******************************************************************************** | |
| 41 * LOCAL VARIABLES AND TABLES | |
| 42 ******************************************************************************** | |
| 43 */ | |
| 44 #define NB_PULSE 4 | |
| 45 | |
| 46 /* | |
| 47 ******************************************************************************** | |
| 48 * DECLARATION OF PROTOTYPES | |
| 49 ******************************************************************************** | |
| 50 */ | |
| 51 static void search_4i40( | |
| 52 Word16 dn[], /* i : correlation between target and h[] */ | |
| 53 Word16 dn2[], /* i : maximum of corr. in each track. */ | |
| 54 Word16 rr[][L_CODE],/* i : matrix of autocorrelation */ | |
| 55 Word16 codvec[] /* o : algebraic codebook vector */ | |
| 56 ); | |
| 57 | |
| 58 static Word16 build_code( | |
| 59 Word16 codvec[], /* i : algebraic codebook vector */ | |
| 60 Word16 dn_sign[], /* i : sign of dn[] */ | |
| 61 Word16 cod[], /* o : algebraic (fixed) codebook excitation */ | |
| 62 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
| 63 Word16 y[], /* o : filtered fixed codebook excitation */ | |
| 64 Word16 sign[] /* o : index of 4 pulses (position+sign+ampl)*4 */ | |
| 65 ); | |
| 66 | |
| 67 | |
| 68 /* | |
| 69 ******************************************************************************** | |
| 70 * PUBLIC PROGRAM CODE | |
| 71 ******************************************************************************** | |
| 72 */ | |
| 73 /************************************************************************* | |
| 74 * | |
| 75 * FUNCTION: code_4i40_17bits() | |
| 76 * | |
| 77 * PURPOSE: Searches a 17 bit algebraic codebook containing 4 pulses | |
| 78 * in a frame of 40 samples. | |
| 79 * | |
| 80 * DESCRIPTION: | |
| 81 * The code length is 40, containing 4 nonzero pulses: i0...i3. | |
| 82 * All pulses can have two possible amplitudes: +1 or -1. | |
| 83 * Pulse i0 to i2 can have 8 possible positions, pulse i3 can have | |
| 84 * 2x8=16 positions. | |
| 85 * | |
| 86 * i0 : 0, 5, 10, 15, 20, 25, 30, 35. | |
| 87 * i1 : 1, 6, 11, 16, 21, 26, 31, 36. | |
| 88 * i2 : 2, 7, 12, 17, 22, 27, 32, 37. | |
| 89 * i3 : 3, 8, 13, 18, 23, 28, 33, 38. | |
| 90 * 4, 9, 14, 19, 24, 29, 34, 39. | |
| 91 * | |
| 92 *************************************************************************/ | |
| 93 | |
| 94 Word16 code_4i40_17bits( | |
| 95 Word16 x[], /* i : target vector */ | |
| 96 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
| 97 /* h[-L_subfr..-1] must be set to zero. */ | |
| 98 Word16 T0, /* i : Pitch lag */ | |
| 99 Word16 pitch_sharp, /* i : Last quantized pitch gain */ | |
| 100 Word16 code[], /* o : Innovative codebook */ | |
| 101 Word16 y[], /* o : filtered fixed codebook excitation */ | |
| 102 Word16 * sign /* o : Signs of 4 pulses */ | |
| 103 ) | |
| 104 { | |
| 105 Word16 codvec[NB_PULSE]; | |
| 106 Word16 dn[L_CODE], dn2[L_CODE], dn_sign[L_CODE]; | |
| 107 Word16 rr[L_CODE][L_CODE]; | |
| 108 Word16 i, index, sharp; | |
| 109 | |
| 110 sharp = shl(pitch_sharp, 1); | |
| 111 test (); | |
| 112 if (sub(T0, L_CODE) < 0) | |
| 113 { | |
| 114 for (i = T0; i < L_CODE; i++) { | |
| 115 h[i] = add(h[i], mult(h[i - T0], sharp)); move16 (); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 cor_h_x(h, x, dn, 1); | |
| 120 set_sign(dn, dn_sign, dn2, 4); | |
| 121 cor_h(h, dn_sign, rr); | |
| 122 search_4i40(dn, dn2, rr, codvec); | |
| 123 move16 (); /* function result */ | |
| 124 index = build_code(codvec, dn_sign, code, h, y, sign); | |
| 125 | |
| 126 /*-----------------------------------------------------------------* | |
| 127 * Compute innovation vector gain. * | |
| 128 * Include fixed-gain pitch contribution into code[]. * | |
| 129 *-----------------------------------------------------------------*/ | |
| 130 | |
| 131 test (); | |
| 132 if (sub(T0, L_CODE) < 0) | |
| 133 { | |
| 134 for (i = T0; i < L_CODE; i++) { | |
| 135 code[i] = add(code[i], mult(code[i - T0], sharp)); move16 (); | |
| 136 } | |
| 137 } | |
| 138 return index; | |
| 139 } | |
| 140 | |
| 141 /* | |
| 142 ******************************************************************************** | |
| 143 * PRIVATE PROGRAM CODE | |
| 144 ******************************************************************************** | |
| 145 */ | |
| 146 | |
| 147 /************************************************************************* | |
| 148 * | |
| 149 * FUNCTION search_4i40() | |
| 150 * | |
| 151 * PURPOSE: Search the best codevector; determine positions of the 4 pulses | |
| 152 * in the 40-sample frame. | |
| 153 * | |
| 154 *************************************************************************/ | |
| 155 | |
| 156 #define _1_2 (Word16)(32768L/2) | |
| 157 #define _1_4 (Word16)(32768L/4) | |
| 158 #define _1_8 (Word16)(32768L/8) | |
| 159 #define _1_16 (Word16)(32768L/16) | |
| 160 | |
| 161 static void search_4i40( | |
| 162 Word16 dn[], /* i : correlation between target and h[] */ | |
| 163 Word16 dn2[], /* i : maximum of corr. in each track. */ | |
| 164 Word16 rr[][L_CODE], /* i : matrix of autocorrelation */ | |
| 165 Word16 codvec[] /* o : algebraic codebook vector */ | |
| 166 ) | |
| 167 { | |
| 168 Word16 i0, i1, i2, i3; | |
| 169 Word16 ix = 0; /* initialization only needed to keep gcc silent */ | |
| 170 Word16 ps = 0; /* initialization only needed to keep gcc silent */ | |
| 171 Word16 i, pos, track, ipos[NB_PULSE]; | |
| 172 Word16 psk, ps0, ps1, sq, sq1; | |
| 173 Word16 alpk, alp, alp_16; | |
| 174 Word32 s, alp0, alp1; | |
| 175 | |
| 176 /* Default value */ | |
| 177 psk = -1; move16 (); | |
| 178 alpk = 1; move16 (); | |
| 179 for (i = 0; i < NB_PULSE; i++) | |
| 180 { | |
| 181 codvec[i] = i; move16 (); | |
| 182 } | |
| 183 | |
| 184 for (track = 3; track < 5; track++) { | |
| 185 /* fix starting position */ | |
| 186 | |
| 187 ipos[0] = 0; move16 (); | |
| 188 ipos[1] = 1; move16 (); | |
| 189 ipos[2] = 2; move16 (); | |
| 190 ipos[3] = track; move16 (); | |
| 191 | |
| 192 /*------------------------------------------------------------------* | |
| 193 * main loop: try 4 tracks. * | |
| 194 *------------------------------------------------------------------*/ | |
| 195 | |
| 196 for (i = 0; i < NB_PULSE; i++) | |
| 197 { | |
| 198 /*----------------------------------------------------------------* | |
| 199 * i0 loop: try 4 positions (use position with max of corr.). * | |
| 200 *----------------------------------------------------------------*/ | |
| 201 | |
| 202 move16 (); /* account for ptr. init. (rr[io]) */ | |
| 203 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) | |
| 204 { | |
| 205 test (); move16 (); | |
| 206 if (dn2[i0] >= 0) | |
| 207 { | |
| 208 ps0 = dn[i0]; move16 (); | |
| 209 alp0 = L_mult(rr[i0][i0], _1_4); | |
| 210 | |
| 211 /*----------------------------------------------------------------* | |
| 212 * i1 loop: 8 positions. * | |
| 213 *----------------------------------------------------------------*/ | |
| 214 | |
| 215 sq = -1; move16 (); | |
| 216 alp = 1; move16 (); | |
| 217 ps = 0; move16 (); | |
| 218 ix = ipos[1]; move16 (); | |
| 219 | |
| 220 /* initialize 4 index for next loop. */ | |
| 221 /*-------------------------------------------------------------------* | |
| 222 * These index have low complexity address computation because * | |
| 223 * they are, in fact, pointers with fixed increment. For example, * | |
| 224 * "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]" * | |
| 225 * and incremented by "STEP". * | |
| 226 *-------------------------------------------------------------------*/ | |
| 227 | |
| 228 move16 (); /* account for ptr. init. (rr[i1]) */ | |
| 229 move16 (); /* account for ptr. init. (dn[i1]) */ | |
| 230 move16 (); /* account for ptr. init. (rr[io]) */ | |
| 231 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) | |
| 232 { | |
| 233 ps1 = add(ps0, dn[i1]); /* idx increment = STEP */ | |
| 234 | |
| 235 /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */ | |
| 236 | |
| 237 alp1 = L_mac(alp0, rr[i1][i1], _1_4); /* idx incr = STEP */ | |
| 238 alp1 = L_mac(alp1, rr[i0][i1], _1_2); /* idx incr = STEP */ | |
| 239 | |
| 240 sq1 = mult(ps1, ps1); | |
| 241 | |
| 242 alp_16 = round(alp1); | |
| 243 | |
| 244 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
| 245 | |
| 246 test (); | |
| 247 if (s > 0) | |
| 248 { | |
| 249 sq = sq1; move16 (); | |
| 250 ps = ps1; move16 (); | |
| 251 alp = alp_16; move16 (); | |
| 252 ix = i1; move16 (); | |
| 253 } | |
| 254 } | |
| 255 i1 = ix; move16 (); | |
| 256 | |
| 257 /*----------------------------------------------------------------* | |
| 258 * i2 loop: 8 positions. * | |
| 259 *----------------------------------------------------------------*/ | |
| 260 | |
| 261 ps0 = ps; move16 (); | |
| 262 alp0 = L_mult(alp, _1_4); | |
| 263 | |
| 264 sq = -1; move16 (); | |
| 265 alp = 1; move16 (); | |
| 266 ps = 0; move16 (); | |
| 267 ix = ipos[2]; move16 (); | |
| 268 | |
| 269 /* initialize 4 index for next loop (see i1 loop) */ | |
| 270 | |
| 271 move16 (); /* account for ptr. init. (rr[i2]) */ | |
| 272 move16 (); /* account for ptr. init. (rr[i1]) */ | |
| 273 move16 (); /* account for ptr. init. (dn[i2]) */ | |
| 274 move16 (); /* account for ptr. init. (rr[io]) */ | |
| 275 for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP) | |
| 276 { | |
| 277 ps1 = add(ps0, dn[i2]); /* index increment = STEP */ | |
| 278 | |
| 279 /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */ | |
| 280 | |
| 281 alp1 = L_mac(alp0, rr[i2][i2], _1_16); /* idx incr = STEP */ | |
| 282 alp1 = L_mac(alp1, rr[i1][i2], _1_8); /* idx incr = STEP */ | |
| 283 alp1 = L_mac(alp1, rr[i0][i2], _1_8); /* idx incr = STEP */ | |
| 284 | |
| 285 sq1 = mult(ps1, ps1); | |
| 286 | |
| 287 alp_16 = round(alp1); | |
| 288 | |
| 289 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
| 290 | |
| 291 test (); | |
| 292 if (s > 0) | |
| 293 { | |
| 294 sq = sq1; move16 (); | |
| 295 ps = ps1; move16 (); | |
| 296 alp = alp_16; move16 (); | |
| 297 ix = i2; move16 (); | |
| 298 } | |
| 299 } | |
| 300 i2 = ix; move16 (); | |
| 301 | |
| 302 /*----------------------------------------------------------------* | |
| 303 * i3 loop: 8 positions. * | |
| 304 *----------------------------------------------------------------*/ | |
| 305 | |
| 306 ps0 = ps; move16 (); | |
| 307 alp0 = L_deposit_h(alp); | |
| 308 | |
| 309 sq = -1; move16 (); | |
| 310 alp = 1; move16 (); | |
| 311 ps = 0; move16 (); | |
| 312 ix = ipos[3]; move16 (); | |
| 313 | |
| 314 /* initialize 5 index for next loop (see i1 loop) */ | |
| 315 | |
| 316 move16 (); /* account for ptr. init. (rr[i3]) */ | |
| 317 move16 (); /* account for ptr. init. (rr[i2]) */ | |
| 318 move16 (); /* account for ptr. init. (rr[i1]) */ | |
| 319 move16 (); /* account for ptr. init. (dn[i3]) */ | |
| 320 move16 (); /* account for ptr. init. (rr[io]) */ | |
| 321 for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP) | |
| 322 { | |
| 323 ps1 = add(ps0, dn[i3]); /* index increment = STEP */ | |
| 324 | |
| 325 /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */ | |
| 326 | |
| 327 alp1 = L_mac(alp0, rr[i3][i3], _1_16); /* idx incr = STEP */ | |
| 328 alp1 = L_mac(alp1, rr[i2][i3], _1_8); /* idx incr = STEP */ | |
| 329 alp1 = L_mac(alp1, rr[i1][i3], _1_8); /* idx incr = STEP */ | |
| 330 alp1 = L_mac(alp1, rr[i0][i3], _1_8); /* idx incr = STEP */ | |
| 331 | |
| 332 sq1 = mult(ps1, ps1); | |
| 333 | |
| 334 alp_16 = round(alp1); | |
| 335 | |
| 336 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
| 337 | |
| 338 test (); | |
| 339 if (s > 0) | |
| 340 { | |
| 341 sq = sq1; move16 (); | |
| 342 ps = ps1; move16 (); | |
| 343 alp = alp_16; move16 (); | |
| 344 ix = i3; move16 (); | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 | |
| 349 /*----------------------------------------------------------------* | |
| 350 * memorise codevector if this one is better than the last one. * | |
| 351 *----------------------------------------------------------------*/ | |
| 352 | |
| 353 s = L_msu(L_mult(alpk, sq), psk, alp); | |
| 354 | |
| 355 test (); | |
| 356 if (s > 0) | |
| 357 { | |
| 358 psk = sq; move16 (); | |
| 359 alpk = alp; move16 (); | |
| 360 codvec[0] = i0; move16 (); | |
| 361 codvec[1] = i1; move16 (); | |
| 362 codvec[2] = i2; move16 (); | |
| 363 codvec[3] = ix; move16 (); | |
| 364 } | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 /*----------------------------------------------------------------* | |
| 369 * Cyclic permutation of i0,i1,i2 and i3. * | |
| 370 *----------------------------------------------------------------*/ | |
| 371 | |
| 372 pos = ipos[3]; move16 (); | |
| 373 ipos[3] = ipos[2]; move16 (); | |
| 374 ipos[2] = ipos[1]; move16 (); | |
| 375 ipos[1] = ipos[0]; move16 (); | |
| 376 ipos[0] = pos; move16 (); | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 return; | |
| 381 } | |
| 382 | |
| 383 /************************************************************************* | |
| 384 * | |
| 385 * FUNCTION: build_code() | |
| 386 * | |
| 387 * PURPOSE: Builds the codeword, the filtered codeword and index of the | |
| 388 * codevector, based on the signs and positions of 4 pulses. | |
| 389 * | |
| 390 *************************************************************************/ | |
| 391 | |
| 392 static Word16 | |
| 393 build_code( | |
| 394 Word16 codvec[], /* i : position of pulses */ | |
| 395 Word16 dn_sign[], /* i : sign of pulses */ | |
| 396 Word16 cod[], /* o : innovative code vector */ | |
| 397 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
| 398 Word16 y[], /* o : filtered innovative code */ | |
| 399 Word16 sign[] /* o : index of 4 pulses (sign+position) */ | |
| 400 ) | |
| 401 { | |
| 402 Word16 i, j, k, track, index, _sign[NB_PULSE], indx, rsign; | |
| 403 Word16 *p0, *p1, *p2, *p3; | |
| 404 Word32 s; | |
| 405 | |
| 406 for (i = 0; i < L_CODE; i++) | |
| 407 { | |
| 408 cod[i] = 0; move16 (); | |
| 409 } | |
| 410 | |
| 411 indx = 0; move16 (); | |
| 412 rsign = 0; move16 (); | |
| 413 for (k = 0; k < NB_PULSE; k++) | |
| 414 { | |
| 415 i = codvec[k]; move16 (); /* read pulse position */ | |
| 416 j = dn_sign[i]; move16 (); /* read sign */ | |
| 417 | |
| 418 index = mult(i, 6554); /* index = pos/5 */ | |
| 419 /* track = pos%5 */ | |
| 420 track = sub(i, extract_l(L_shr(L_mult(index, 5), 1))); | |
| 421 | |
| 422 | |
| 423 index = gray[index]; move16 (); | |
| 424 | |
| 425 test (); | |
| 426 if (sub(track, 1) == 0) | |
| 427 index = shl(index, 3); | |
| 428 else if (sub(track, 2) == 0) | |
| 429 { | |
| 430 test (); | |
| 431 index = shl(index, 6); | |
| 432 } | |
| 433 else if (sub(track, 3) == 0) | |
| 434 { | |
| 435 test ();test (); | |
| 436 index = shl(index, 10); | |
| 437 } | |
| 438 else if (sub(track, 4) == 0) | |
| 439 { | |
| 440 test ();test ();test (); | |
| 441 track = 3; move16 (); | |
| 442 index = add(shl(index, 10), 512); | |
| 443 } | |
| 444 | |
| 445 test (); | |
| 446 if (j > 0) | |
| 447 { | |
| 448 cod[i] = 8191; move16 (); | |
| 449 _sign[k] = 32767; move16 (); | |
| 450 rsign = add(rsign, shl(1, track)); | |
| 451 } else { | |
| 452 cod[i] = -8192; move16 (); | |
| 453 _sign[k] = (Word16) - 32768L; move16 (); | |
| 454 } | |
| 455 | |
| 456 indx = add(indx, index); | |
| 457 } | |
| 458 *sign = rsign; move16 (); | |
| 459 | |
| 460 p0 = h - codvec[0]; move16 (); | |
| 461 p1 = h - codvec[1]; move16 (); | |
| 462 p2 = h - codvec[2]; move16 (); | |
| 463 p3 = h - codvec[3]; move16 (); | |
| 464 | |
| 465 for (i = 0; i < L_CODE; i++) | |
| 466 { | |
| 467 s = 0; move32 (); | |
| 468 s = L_mac(s, *p0++, _sign[0]); | |
| 469 s = L_mac(s, *p1++, _sign[1]); | |
| 470 s = L_mac(s, *p2++, _sign[2]); | |
| 471 s = L_mac(s, *p3++, _sign[3]); | |
| 472 y[i] = round(s); move16 (); | |
| 473 } | |
| 474 | |
| 475 return indx; | |
| 476 } |
