1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /**************************************************************************************** 19 Portions of this file are derived from the following 3GPP standard: 20 21 3GPP TS 26.073 22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec 23 Available from http://www.3gpp.org 24 25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC) 26 Permission to distribute, modify and use this file under the standard license 27 terms listed above has been obtained from the copyright holder. 28 ****************************************************************************************/ 29 /* 30 ------------------------------------------------------------------------------ 31 32 33 34 Pathname: ./audio/gsm-amr/c/src/qgain795.c 35 Functions: MR795_gain_code_quant3 36 MR795_gain_code_quant_mod 37 MR795_gain_quant 38 39 Date: 02/04/2002 40 41 ------------------------------------------------------------------------------ 42 REVISION HISTORY 43 44 Description: Updated template used to PV coding template. 45 Changed to accept the pOverflow flag for EPOC compatibility. 46 47 Description: 48 (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding 49 i to itself 3 times. The reason is because the mult function does a 50 right shift by 15, which will obliterate smaller numbers. 51 52 Description: Replaced OSCL mem type functions and eliminated include 53 files that now are chosen by OSCL definitions 54 55 Description: Replaced "int" and/or "char" with OSCL defined types. 56 57 Description: Changed round function name to pv_round to avoid conflict with 58 round function in C standard library. 59 60 Description: Added #ifdef __cplusplus around extern'ed table. 61 62 Description: 63 64 ------------------------------------------------------------------------------ 65 MODULE DESCRIPTION 66 67 68 ------------------------------------------------------------------------------ 69 */ 70 71 /*---------------------------------------------------------------------------- 72 ; INCLUDES 73 ----------------------------------------------------------------------------*/ 74 #include "qgain795.h" 75 #include "typedef.h" 76 #include "basic_op.h" 77 #include "cnst.h" 78 #include "log2.h" 79 #include "pow2.h" 80 #include "sqrt_l.h" 81 #include "g_adapt.h" 82 #include "calc_en.h" 83 #include "q_gain_p.h" 84 85 86 /*--------------------------------------------------------------------------*/ 87 #ifdef __cplusplus 88 extern "C" 89 { 90 #endif 91 92 /*---------------------------------------------------------------------------- 93 ; MACROS 94 ; Define module specific macros here 95 ----------------------------------------------------------------------------*/ 96 97 /*---------------------------------------------------------------------------- 98 ; DEFINES 99 ; Include all pre-processor statements here. Include conditional 100 ; compile variables also. 101 ----------------------------------------------------------------------------*/ 102 #define NB_QUA_CODE 32 103 104 /*---------------------------------------------------------------------------- 105 ; LOCAL FUNCTION DEFINITIONS 106 ; Function Prototype declaration 107 ----------------------------------------------------------------------------*/ 108 109 /*---------------------------------------------------------------------------- 110 ; LOCAL VARIABLE DEFINITIONS 111 ; Variable declaration - defined here and used outside this module 112 ----------------------------------------------------------------------------*/ 113 114 /*---------------------------------------------------------------------------- 115 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 116 ; Declare variables used in this module but defined elsewhere 117 ----------------------------------------------------------------------------*/ 118 extern const Word16 qua_gain_code[NB_QUA_CODE*3]; 119 120 121 /*--------------------------------------------------------------------------*/ 122 #ifdef __cplusplus 123 } 124 #endif 125 126 /* 127 ------------------------------------------------------------------------------ 128 FUNCTION NAME: MR795_gain_code_quant3 129 ------------------------------------------------------------------------------ 130 INPUT AND OUTPUT DEFINITIONS 131 132 Inputs: 133 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0 134 gcode0 -- Word16 -- predicted CB gain (norm.) 135 g_pitch_cand[] -- Word16 array -- Pitch gain candidates (3), Q14 136 g_pitch_cind[] -- Word16 array -- Pitch gain cand. indices (3), Q0 137 frac_coeff[] -- Word16 array -- coefficients (5), Q15 138 exp_coeff[] -- Word16 array -- energy coefficients (5), Q0 139 coefficients from calc_filt_ener() 140 141 Outputs: 142 gain_pit -- Pointer to Word16 -- Pitch gain, Q14 143 gain_pit_ind -- Pointer to Word16 -- Pitch gain index, Q0 144 gain_cod -- Pointer to Word16 -- Code gain, Q1 145 gain_cod_ind -- Pointer to Word16 -- Code gain index, Q0 146 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10 147 (for MR122 MA predictor update) 148 149 qua_ener -- Pointer to Word16 -- quantized energy error, Q10 150 (for other MA predictor update) 151 152 pOverflow -- Pointer to Flag -- overflow indicator 153 154 Returns: 155 None 156 157 Global Variables Used: 158 None 159 160 Local Variables Needed: 161 None 162 163 ------------------------------------------------------------------------------ 164 FUNCTION DESCRIPTION 165 166 PURPOSE: Pre-quantization of codebook gains, given three possible 167 LTP gains (using predicted codebook gain) 168 ------------------------------------------------------------------------------ 169 REQUIREMENTS 170 171 None 172 173 ------------------------------------------------------------------------------ 174 REFERENCES 175 176 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 177 178 ------------------------------------------------------------------------------ 179 PSEUDO-CODE 180 181 182 ------------------------------------------------------------------------------ 183 RESOURCES USED [optional] 184 185 When the code is written for a specific target processor the 186 the resources used should be documented below. 187 188 HEAP MEMORY USED: x bytes 189 190 STACK MEMORY USED: x bytes 191 192 CLOCK CYCLES: (cycle count equation for this function) + (variable 193 used to represent cycle count for each subroutine 194 called) 195 where: (cycle count variable) = cycle count for [subroutine 196 name] 197 198 ------------------------------------------------------------------------------ 199 CAUTION [optional] 200 [State any special notes, constraints or cautions for users of this function] 201 202 ------------------------------------------------------------------------------ 203 */ 204 205 static void 206 MR795_gain_code_quant3( 207 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */ 208 Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */ 209 Word16 g_pitch_cand[], /* i : Pitch gain candidates (3), Q14 */ 210 Word16 g_pitch_cind[], /* i : Pitch gain cand. indices (3), Q0 */ 211 Word16 frac_coeff[], /* i : coefficients (5), Q15 */ 212 Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */ 213 /* coefficients from calc_filt_ener()*/ 214 Word16 *gain_pit, /* o : Pitch gain, Q14 */ 215 Word16 *gain_pit_ind, /* o : Pitch gain index, Q0 */ 216 Word16 *gain_cod, /* o : Code gain, Q1 */ 217 Word16 *gain_cod_ind, /* o : Code gain index, Q0 */ 218 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */ 219 /* (for MR122 MA predictor update) */ 220 Word16 *qua_ener, /* o : quantized energy error, Q10 */ 221 /* (for other MA predictor update) */ 222 Flag *pOverflow /* o : overflow indicator */ 223 ) 224 { 225 const Word16 *p; 226 Word16 i; 227 Word16 j; 228 Word16 cod_ind; 229 Word16 pit_ind; 230 Word16 e_max; 231 Word16 exp_code; 232 Word16 g_pitch; 233 Word16 g2_pitch; 234 Word16 g_code; 235 Word16 g2_code_h; 236 Word16 g2_code_l; 237 Word16 g_pit_cod_h; 238 Word16 g_pit_cod_l; 239 Word16 coeff[5]; 240 Word16 coeff_lo[5]; 241 Word16 exp_max[5]; 242 Word32 L_tmp; 243 Word32 L_tmp0; 244 Word32 dist_min; 245 246 /* 247 * The error energy (sum) to be minimized consists of five terms, t[0..4]. 248 * 249 * t[0] = gp^2 * <y1 y1> 250 * t[1] = -2*gp * <xn y1> 251 * t[2] = gc^2 * <y2 y2> 252 * t[3] = -2*gc * <xn y2> 253 * t[4] = 2*gp*gc * <y1 y2> 254 * 255 */ 256 257 /* determine the scaling exponent for g_code: ec = ec0 - 10 */ 258 exp_code = sub(exp_gcode0, 10, pOverflow); 259 260 /* calculate exp_max[i] = s[i]-1 */ 261 exp_max[0] = sub(exp_coeff[0], 13, pOverflow); 262 exp_max[1] = sub(exp_coeff[1], 14, pOverflow); 263 exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1, pOverflow), pOverflow), pOverflow); 264 exp_max[3] = add(exp_coeff[3], exp_code, pOverflow); 265 exp_max[4] = add(exp_coeff[4], add(exp_code, 1, pOverflow), pOverflow); 266 267 268 /*-------------------------------------------------------------------* 269 * Find maximum exponent: * 270 * ~~~~~~~~~~~~~~~~~~~~~~ * 271 * * 272 * For the sum operation, all terms must have the same scaling; * 273 * that scaling should be low enough to prevent overflow. There- * 274 * fore, the maximum scale is determined and all coefficients are * 275 * re-scaled: * 276 * * 277 * e_max = max(exp_max[i]) + 1; * 278 * e = exp_max[i]-e_max; e <= 0! * 279 * c[i] = c[i]*2^e * 280 *-------------------------------------------------------------------*/ 281 282 e_max = exp_max[0]; 283 for (i = 1; i < 5; i++) /* implemented flattened */ 284 { 285 if (exp_max[i] > e_max) 286 { 287 e_max = exp_max[i]; 288 } 289 } 290 291 e_max = add(e_max, 1, pOverflow); /* To avoid overflow */ 292 293 for (i = 0; i < 5; i++) 294 { 295 j = sub(e_max, exp_max[i], pOverflow); 296 L_tmp = L_deposit_h(frac_coeff[i]); 297 L_tmp = L_shr(L_tmp, j, pOverflow); 298 L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow); 299 } 300 301 302 /*-------------------------------------------------------------------* 303 * Codebook search: * 304 * ~~~~~~~~~~~~~~~~ * 305 * * 306 * For each of the candiates LTP gains in g_pitch_cand[], the terms * 307 * t[0..4] are calculated from the values in the table (and the * 308 * pitch gain candidate) and summed up; the result is the mean * 309 * squared error for the LPT/CB gain pair. The index for the mini- * 310 * mum MSE is stored and finally used to retrieve the quantized CB * 311 * gain * 312 *-------------------------------------------------------------------*/ 313 314 /* start with "infinite" MSE */ 315 dist_min = MAX_32; 316 cod_ind = 0; 317 pit_ind = 0; 318 319 /* loop through LTP gain candidates */ 320 for (j = 0; j < 3; j++) 321 { 322 /* pre-calculate terms only dependent on pitch gain */ 323 g_pitch = g_pitch_cand[j]; 324 g2_pitch = mult(g_pitch, g_pitch, pOverflow); 325 L_tmp0 = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow); 326 L_tmp0 = Mac_32_16(L_tmp0, coeff[1], coeff_lo[1], g_pitch, pOverflow); 327 328 p = &qua_gain_code[0]; 329 for (i = 0; i < NB_QUA_CODE; i++) 330 { 331 g_code = *p++; /* this is g_fac Q11 */ 332 p++; /* skip log2(g_fac) */ 333 p++; /* skip 20*log10(g_fac) */ 334 335 g_code = mult(g_code, gcode0, pOverflow); 336 337 L_tmp = L_mult(g_code, g_code, pOverflow); 338 L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow); 339 340 L_tmp = L_mult(g_code, g_pitch, pOverflow); 341 L_Extract(L_tmp, &g_pit_cod_h, &g_pit_cod_l, pOverflow); 342 343 L_tmp = Mac_32(L_tmp0, coeff[2], coeff_lo[2], 344 g2_code_h, g2_code_l, pOverflow); 345 L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3], 346 g_code, pOverflow); 347 L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], 348 g_pit_cod_h, g_pit_cod_l, pOverflow); 349 350 /* store table index if MSE for this index is lower 351 than the minimum MSE seen so far; also store the 352 pitch gain for this (so far) lowest MSE */ 353 if (L_tmp < dist_min) 354 { 355 dist_min = L_tmp; 356 cod_ind = i; 357 pit_ind = j; 358 } 359 } 360 } 361 362 /*------------------------------------------------------------------* 363 * read quantized gains and new values for MA predictor memories * 364 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 365 *------------------------------------------------------------------*/ 366 367 /* Read the quantized gains */ 368 p = &qua_gain_code[ 369 add(add(cod_ind, cod_ind, pOverflow), cod_ind, pOverflow)]; 370 371 g_code = *p++; 372 *qua_ener_MR122 = *p++; 373 *qua_ener = *p; 374 375 /*------------------------------------------------------------------* 376 * calculate final fixed codebook gain: * 377 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 378 * * 379 * gc = gc0 * g * 380 *------------------------------------------------------------------*/ 381 382 L_tmp = L_mult(g_code, gcode0, pOverflow); 383 L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow); 384 *gain_cod = extract_h(L_tmp); 385 *gain_cod_ind = cod_ind; 386 *gain_pit = g_pitch_cand[pit_ind]; 387 *gain_pit_ind = g_pitch_cind[pit_ind]; 388 } 389 390 391 /* 392 ------------------------------------------------------------------------------ 393 FUNCTION NAME: MR795_gain_code_quant_mod 394 ------------------------------------------------------------------------------ 395 INPUT AND OUTPUT DEFINITIONS 396 397 Inputs: 398 gain_pit -- Word16 -- pitch gain, Q14 399 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0 400 gcode0 -- Word16 -- predicted CB gain (norm.), Q14 401 frac_en[] -- Word16 array -- energy coefficients (4), fraction part, Q15 402 exp_en[] -- Word16 array -- energy coefficients (4), exponent part, Q0 403 alpha -- Word16 -- gain adaptor factor (>0), Q15 404 405 gain_cod_unq -- Word16 -- Code gain (unquantized) 406 (scaling: Q10 - exp_gcode0) 407 408 gain_cod -- Pointer to Word16 -- Code gain (pre-/quantized), Q1 409 410 Outputs: 411 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10 412 (for MR122 MA predictor update) 413 qua_ener -- Pointer to Word16 -- quantized energy error, Q10 414 (for other MA predictor update) 415 pOverflow -- Pointer to Flag -- overflow indicator 416 417 Returns: 418 index of quantization (Word16) 419 420 Global Variables Used: 421 None 422 423 Local Variables Needed: 424 None 425 426 ------------------------------------------------------------------------------ 427 FUNCTION DESCRIPTION 428 429 PURPOSE: Modified quantization of the MR795 codebook gain 430 431 Uses pre-computed energy coefficients in frac_en[]/exp_en[] 432 433 frac_en[0]*2^exp_en[0] = <res res> // LP residual energy 434 frac_en[1]*2^exp_en[1] = <exc exc> // LTP residual energy 435 frac_en[2]*2^exp_en[2] = <exc code> // LTP/CB innovation dot product 436 frac_en[3]*2^exp_en[3] = <code code> // CB innovation energy 437 ------------------------------------------------------------------------------ 438 REQUIREMENTS 439 440 None 441 442 ------------------------------------------------------------------------------ 443 REFERENCES 444 445 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 446 447 ------------------------------------------------------------------------------ 448 PSEUDO-CODE 449 450 451 ------------------------------------------------------------------------------ 452 RESOURCES USED [optional] 453 454 When the code is written for a specific target processor the 455 the resources used should be documented below. 456 457 HEAP MEMORY USED: x bytes 458 459 STACK MEMORY USED: x bytes 460 461 CLOCK CYCLES: (cycle count equation for this function) + (variable 462 used to represent cycle count for each subroutine 463 called) 464 where: (cycle count variable) = cycle count for [subroutine 465 name] 466 467 ------------------------------------------------------------------------------ 468 CAUTION [optional] 469 [State any special notes, constraints or cautions for users of this function] 470 471 ------------------------------------------------------------------------------ 472 */ 473 474 static Word16 475 MR795_gain_code_quant_mod( /* o : index of quantization. */ 476 Word16 gain_pit, /* i : pitch gain, Q14 */ 477 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */ 478 Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */ 479 Word16 frac_en[], /* i : energy coefficients (4), 480 fraction part, Q15 */ 481 Word16 exp_en[], /* i : energy coefficients (4), 482 eponent part, Q0 */ 483 Word16 alpha, /* i : gain adaptor factor (>0), Q15 */ 484 Word16 gain_cod_unq, /* i : Code gain (unquantized) */ 485 /* (scaling: Q10 - exp_gcode0) */ 486 Word16 *gain_cod, /* i/o: Code gain (pre-/quantized), Q1 */ 487 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */ 488 /* (for MR122 MA predictor update) */ 489 Word16 *qua_ener, /* o : quantized energy error, Q10 */ 490 /* (for other MA predictor update) */ 491 Flag *pOverflow /* o : overflow indicator */ 492 ) 493 { 494 const Word16 *p; 495 Word16 i; 496 Word16 index; 497 Word16 tmp; 498 Word16 one_alpha; 499 Word16 exp; 500 Word16 e_max; 501 502 Word16 g2_pitch; 503 Word16 g_code; 504 Word16 g2_code_h; 505 Word16 g2_code_l; 506 Word16 d2_code_h; 507 Word16 d2_code_l; 508 Word16 coeff[5]; 509 Word16 coeff_lo[5]; 510 Word16 exp_coeff[5]; 511 Word32 L_tmp; 512 Word32 L_t0; 513 Word32 L_t1; 514 Word32 dist_min; 515 Word16 gain_code; 516 517 /* 518 Steps in calculation of the error criterion (dist): 519 --------------------------------------------------- 520 521 underlined = constant; alp = FLP value of alpha, alpha = FIP 522 ---------- 523 524 525 ExEn = gp^2 * LtpEn + 2.0*gp*gc[i] * XC + gc[i]^2 * InnEn; 526 ------------ ------ -- ----- 527 528 aExEn= alp * ExEn 529 = alp*gp^2*LtpEn + 2.0*alp*gp*XC* gc[i] + alp*InnEn* gc[i]^2 530 -------------- ------------- --------- 531 532 = t[1] + t[2] + t[3] 533 534 dist = d1 + d2; 535 536 d1 = (1.0 - alp) * InnEn * (gcu - gc[i])^2 = t[4] 537 ------------------- --- 538 539 d2 = alp * (ResEn - 2.0 * sqrt(ResEn*ExEn) + ExEn); 540 --- ----- --- ----- 541 542 = alp * (sqrt(ExEn) - sqrt(ResEn))^2 543 --- ----------- 544 545 = (sqrt(aExEn) - sqrt(alp*ResEn))^2 546 --------------- 547 548 = (sqrt(aExEn) - t[0] )^2 549 ---- 550 551 */ 552 553 /* 554 * calculate scalings of the constant terms 555 */ 556 gain_code = shl(*gain_cod, sub(10, exp_gcode0, pOverflow), pOverflow); /* Q1 -> Q11 (-ec0) */ 557 g2_pitch = mult(gain_pit, gain_pit, pOverflow); /* Q14 -> Q13 */ 558 /* 0 < alpha <= 0.5 => 0.5 <= 1-alpha < 1, i.e one_alpha is normalized */ 559 one_alpha = add(sub(32767, alpha, pOverflow), 1, pOverflow); /* 32768 - alpha */ 560 561 562 /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */ 563 L_t1 = L_mult(alpha, frac_en[1], pOverflow); 564 L_t1 = L_shl(L_t1, 1, pOverflow); 565 tmp = extract_h(L_t1); 566 567 /* directly store in 32 bit variable because no further mult. required */ 568 L_t1 = L_mult(tmp, g2_pitch, pOverflow); 569 exp_coeff[1] = sub(exp_en[1], 15, pOverflow); 570 571 572 tmp = extract_h(L_shl(L_mult(alpha, frac_en[2], pOverflow), 1, pOverflow)); 573 coeff[2] = mult(tmp, gain_pit, pOverflow); 574 exp = sub(exp_gcode0, 10, pOverflow); 575 exp_coeff[2] = add(exp_en[2], exp, pOverflow); 576 577 578 /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */ 579 coeff[3] = extract_h(L_shl(L_mult(alpha, frac_en[3], pOverflow), 1, pOverflow)); 580 exp = sub(shl(exp_gcode0, 1, pOverflow), 7, pOverflow); 581 exp_coeff[3] = add(exp_en[3], exp, pOverflow); 582 583 584 coeff[4] = mult(one_alpha, frac_en[3], pOverflow); 585 exp_coeff[4] = add(exp_coeff[3], 1, pOverflow); 586 587 588 L_tmp = L_mult(alpha, frac_en[0], pOverflow); 589 /* sqrt_l returns normalized value and 2*exponent 590 -> result = val >> (exp/2) 591 exp_coeff holds 2*exponent for c[0] */ 592 /* directly store in 32 bit variable because no further mult. required */ 593 L_t0 = sqrt_l_exp(L_tmp, &exp, pOverflow); /* normalization included in sqrt_l_exp */ 594 exp = add(exp, 47, pOverflow); 595 exp_coeff[0] = sub(exp_en[0], exp, pOverflow); 596 597 /* 598 * Determine the maximum exponent occuring in the distance calculation 599 * and adjust all fractions accordingly (including a safety margin) 600 * 601 */ 602 603 /* find max(e[1..4],e[0]+31) */ 604 e_max = add(exp_coeff[0], 31, pOverflow); 605 for (i = 1; i <= 4; i++) 606 { 607 if (exp_coeff[i] > e_max) 608 { 609 e_max = exp_coeff[i]; 610 } 611 } 612 613 /* scale c[1] (requires no further multiplication) */ 614 tmp = sub(e_max, exp_coeff[1], pOverflow); 615 L_t1 = L_shr(L_t1, tmp, pOverflow); 616 617 /* scale c[2..4] (used in Mpy_32_16 in the quantizer loop) */ 618 for (i = 2; i <= 4; i++) 619 { 620 tmp = sub(e_max, exp_coeff[i], pOverflow); 621 L_tmp = L_deposit_h(coeff[i]); 622 L_tmp = L_shr(L_tmp, tmp, pOverflow); 623 L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow); 624 } 625 626 /* scale c[0] (requires no further multiplication) */ 627 exp = sub(e_max, 31, pOverflow); /* new exponent */ 628 tmp = sub(exp, exp_coeff[0], pOverflow); 629 L_t0 = L_shr(L_t0, shr(tmp, 1, pOverflow), pOverflow); 630 /* perform correction by 1/sqrt(2) if exponent difference is odd */ 631 if ((tmp & 0x1) != 0) 632 { 633 L_Extract(L_t0, &coeff[0], &coeff_lo[0], pOverflow); 634 L_t0 = Mpy_32_16(coeff[0], coeff_lo[0], 635 23170, pOverflow); /* 23170 Q15 = 1/sqrt(2)*/ 636 } 637 638 /* search the quantizer table for the lowest value 639 of the search criterion */ 640 dist_min = MAX_32; 641 index = 0; 642 p = &qua_gain_code[0]; 643 644 for (i = 0; i < NB_QUA_CODE; i++) 645 { 646 g_code = *p++; /* this is g_fac (Q11) */ 647 p++; /* skip log2(g_fac) */ 648 p++; /* skip 20*log10(g_fac) */ 649 g_code = mult(g_code, gcode0, pOverflow); 650 651 /* only continue if gc[i] < 2.0*gc 652 which is equiv. to g_code (Q10-ec0) < gain_code (Q11-ec0) */ 653 654 if (g_code >= gain_code) 655 { 656 break; 657 } 658 659 L_tmp = L_mult(g_code, g_code, pOverflow); 660 L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow); 661 662 tmp = sub(g_code, gain_cod_unq, pOverflow); 663 L_tmp = L_mult(tmp, tmp, pOverflow); 664 L_Extract(L_tmp, &d2_code_h, &d2_code_l, pOverflow); 665 666 /* t2, t3, t4 */ 667 L_tmp = Mac_32_16(L_t1, coeff[2], coeff_lo[2], g_code, pOverflow); 668 L_tmp = Mac_32(L_tmp, coeff[3], coeff_lo[3], g2_code_h, g2_code_l, pOverflow); 669 670 L_tmp = sqrt_l_exp(L_tmp, &exp, pOverflow); 671 L_tmp = L_shr(L_tmp, shr(exp, 1, pOverflow), pOverflow); 672 673 /* d2 */ 674 tmp = pv_round(L_sub(L_tmp, L_t0, pOverflow), pOverflow); 675 L_tmp = L_mult(tmp, tmp, pOverflow); 676 677 /* dist */ 678 L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], d2_code_h, d2_code_l, pOverflow); 679 680 /* store table index if distance measure for this 681 index is lower than the minimum seen so far */ 682 if (L_tmp < dist_min) 683 { 684 dist_min = L_tmp; 685 index = i; 686 } 687 } 688 689 /*------------------------------------------------------------------* 690 * read quantized gains and new values for MA predictor memories * 691 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 692 *------------------------------------------------------------------*/ 693 694 /* Read the quantized gains */ 695 p = &qua_gain_code[add(add(index, index, pOverflow), index, pOverflow)]; 696 g_code = *p++; 697 *qua_ener_MR122 = *p++; 698 *qua_ener = *p; 699 700 /*------------------------------------------------------------------* 701 * calculate final fixed codebook gain: * 702 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 703 * * 704 * gc = gc0 * g * 705 *------------------------------------------------------------------*/ 706 707 L_tmp = L_mult(g_code, gcode0, pOverflow); 708 L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow); 709 *gain_cod = extract_h(L_tmp); 710 711 return index; 712 } 713 714 /* 715 ------------------------------------------------------------------------------ 716 FUNCTION NAME: MR795_gain_quant 717 ------------------------------------------------------------------------------ 718 INPUT AND OUTPUT DEFINITIONS 719 MR795_gain_quant( 720 721 722 Inputs: 723 adapt_st -- Pointer to GainAdaptState -- gain adapter state structure 724 res -- Word16 array -- LP residual, Q0 725 exc -- Word16 array -- LTP excitation (unfiltered), Q0 726 code -- Word16 array -- CB innovation (unfiltered), Q13 727 frac_coeff -- Word16 array -- coefficients (5), Q15 728 exp_coeff -- Word16 array -- energy coefficients (5), Q0 729 coefficients from calc_filt_ener() 730 exp_code_en -- Word16 -- innovation energy (exponent), Q0 731 frac_code_en -- Word16 -- innovation energy (fraction), Q15 732 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0 733 frac_gcode0 -- Word16 -- predicted CB gain (fraction), Q15 734 L_subfr -- Word16 -- Subframe length 735 cod_gain_frac -- Word16 -- opt. codebook gain (fraction),Q15 736 cod_gain_exp -- Word16 -- opt. codebook gain (exponent), Q0 737 gp_limit -- Word16 -- pitch gain limit 738 gain_pit -- Pointer to Word16 -- Pitch gain, Q14 739 740 Output 741 adapt_st -- Pointer to GainAdaptState -- gain adapter state structure 742 gain_pit -- Pointer to Word16 -- Pitch gain, Q14 743 744 gain_pit -- Pointer to Word16 -- Pitch gain, Q14 745 gain_cod -- Pointer to Word16 -- Code gain, Q1 746 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10 747 (for MR122 MA predictor update) 748 749 qua_ener -- Pointer to Word16 -- quantized energy error, Q10 750 (for other MA predictor update) 751 752 anap -- Double Pointer to Word16 -- Index of quantization 753 (first gain pitch, then code pitch) 754 755 pOverflow -- Pointer to Flag -- overflow indicator 756 757 Returns: 758 None 759 760 Global Variables Used: 761 None 762 763 Local Variables Needed: 764 None 765 766 ------------------------------------------------------------------------------ 767 FUNCTION DESCRIPTION 768 769 pitch and codebook quantization for MR795 770 ------------------------------------------------------------------------------ 771 REQUIREMENTS 772 773 None 774 775 ------------------------------------------------------------------------------ 776 REFERENCES 777 778 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 779 780 ------------------------------------------------------------------------------ 781 PSEUDO-CODE 782 783 784 ------------------------------------------------------------------------------ 785 RESOURCES USED [optional] 786 787 When the code is written for a specific target processor the 788 the resources used should be documented below. 789 790 HEAP MEMORY USED: x bytes 791 792 STACK MEMORY USED: x bytes 793 794 CLOCK CYCLES: (cycle count equation for this function) + (variable 795 used to represent cycle count for each subroutine 796 called) 797 where: (cycle count variable) = cycle count for [subroutine 798 name] 799 800 ------------------------------------------------------------------------------ 801 CAUTION [optional] 802 [State any special notes, constraints or cautions for users of this function] 803 804 ------------------------------------------------------------------------------ 805 */ 806 807 void 808 MR795_gain_quant( 809 GainAdaptState *adapt_st, /* i/o: gain adapter state structure */ 810 Word16 res[], /* i : LP residual, Q0 */ 811 Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */ 812 Word16 code[], /* i : CB innovation (unfiltered), Q13 */ 813 Word16 frac_coeff[], /* i : coefficients (5), Q15 */ 814 Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */ 815 /* coefficients from calc_filt_ener() */ 816 Word16 exp_code_en, /* i : innovation energy (exponent), Q0 */ 817 Word16 frac_code_en, /* i : innovation energy (fraction), Q15 */ 818 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */ 819 Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */ 820 Word16 L_subfr, /* i : Subframe length */ 821 Word16 cod_gain_frac, /* i : opt. codebook gain (fraction),Q15 */ 822 Word16 cod_gain_exp, /* i : opt. codebook gain (exponent), Q0 */ 823 Word16 gp_limit, /* i : pitch gain limit */ 824 Word16 *gain_pit, /* i/o: Pitch gain, Q14 */ 825 Word16 *gain_cod, /* o : Code gain, Q1 */ 826 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */ 827 /* (for MR122 MA predictor update) */ 828 Word16 *qua_ener, /* o : quantized energy error, Q10 */ 829 /* (for other MA predictor update) */ 830 Word16 **anap, /* o : Index of quantization */ 831 /* (first gain pitch, then code pitch)*/ 832 Flag *pOverflow /* o : overflow indicator */ 833 ) 834 { 835 Word16 frac_en[4]; 836 Word16 exp_en[4]; 837 Word16 ltpg, alpha, gcode0; 838 Word16 g_pitch_cand[3]; /* pitch gain candidates Q14 */ 839 Word16 g_pitch_cind[3]; /* pitch gain indices Q0 */ 840 Word16 gain_pit_index; 841 Word16 gain_cod_index; 842 Word16 exp; 843 Word16 gain_cod_unq; /* code gain (unq.) Q(10-exp_gcode0) */ 844 845 846 /* get list of candidate quantized pitch gain values 847 * and corresponding quantization indices 848 */ 849 gain_pit_index = q_gain_pitch(MR795, gp_limit, gain_pit, 850 g_pitch_cand, g_pitch_cind, pOverflow); 851 852 /*-------------------------------------------------------------------* 853 * predicted codebook gain * 854 * ~~~~~~~~~~~~~~~~~~~~~~~ * 855 * gc0 = 2^exp_gcode0 + 2^frac_gcode0 * 856 * * 857 * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) * 858 *-------------------------------------------------------------------*/ 859 gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow)); /* Q14 */ 860 861 /* pre-quantization of codebook gain 862 * (using three pitch gain candidates); 863 * result: best guess of pitch gain and code gain 864 */ 865 MR795_gain_code_quant3( 866 exp_gcode0, gcode0, g_pitch_cand, g_pitch_cind, 867 frac_coeff, exp_coeff, 868 gain_pit, &gain_pit_index, gain_cod, &gain_cod_index, 869 qua_ener_MR122, qua_ener, pOverflow); 870 871 /* calculation of energy coefficients and LTP coding gain */ 872 calc_unfilt_energies(res, exc, code, *gain_pit, L_subfr, 873 frac_en, exp_en, <pg, pOverflow); 874 875 /* run gain adaptor, calculate alpha factor to balance LTP/CB gain 876 * (this includes the gain adaptor update) 877 * Note: ltpg = 0 if frac_en[0] == 0, so the update is OK in that case 878 */ 879 gain_adapt(adapt_st, ltpg, *gain_cod, &alpha, pOverflow); 880 881 /* if this is a very low energy signal (threshold: see 882 * calc_unfilt_energies) or alpha <= 0 then don't run the modified quantizer 883 */ 884 if (frac_en[0] != 0 && alpha > 0) 885 { 886 /* innovation energy <cod cod> was already computed in gc_pred() */ 887 /* (this overwrites the LtpResEn which is no longer needed) */ 888 frac_en[3] = frac_code_en; 889 exp_en[3] = exp_code_en; 890 891 /* store optimum codebook gain in Q(10-exp_gcode0) */ 892 exp = add(sub(cod_gain_exp, exp_gcode0, pOverflow), 10, pOverflow); 893 gain_cod_unq = shl(cod_gain_frac, exp, pOverflow); 894 895 /* run quantization with modified criterion */ 896 gain_cod_index = MR795_gain_code_quant_mod( 897 *gain_pit, exp_gcode0, gcode0, 898 frac_en, exp_en, alpha, gain_cod_unq, 899 gain_cod, qua_ener_MR122, qua_ener, pOverflow); /* function result */ 900 } 901 902 *(*anap)++ = gain_pit_index; 903 *(*anap)++ = gain_cod_index; 904 } 905