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/**************************************************************************************** 19Portions 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) 26Permission to distribute, modify and use this file under the standard license 27terms listed above has been obtained from the copyright holder. 28****************************************************************************************/ 29/* 30------------------------------------------------------------------------------ 31 32 33 34 Pathname: ./audio/gsm-amr/c/src/g_pitch.c 35 36 Date: 06/12/2000 37 38------------------------------------------------------------------------------ 39 REVISION HISTORY 40 41 Description: Placed into template and began to optimize. 42 43 Description: Synchronized file with UMTS version 3.2.0. Updated coding 44 template. Removed unnecessary include files. 45 46 Description: Replaced basic_op.h and oper_32b.h with the header files of the 47 math functions used in the file. Fixed typecasting issue with 48 TI compiler. 49 50 Description: Passing in pointer to overflow flag for EPOC compatibility. . 51 52 Description: 53 1. Eliminated unused include files. 54 2. Replaced array addressing by pointers 55 3. Eliminated math operations that unnecessary checked for 56 saturation, in some cases this by shifting before adding and 57 in other cases by evaluating the operands 58 4. Unrolled loops to speed up processing 59 60 Description: Replaced OSCL mem type functions and eliminated include 61 files that now are chosen by OSCL definitions 62 63 Description: Replaced "int" and/or "char" with OSCL defined types. 64 65 Description: Changed round function name to pv_round to avoid conflict with 66 round function in C standard library. 67 68 Description: Using inlines from fxp_arithmetic.h . 69 70 Description: Replacing fxp_arithmetic.h with basic_op.h. 71 72 Description: 73 74------------------------------------------------------------------------------ 75*/ 76 77/*---------------------------------------------------------------------------- 78; INCLUDES 79----------------------------------------------------------------------------*/ 80#include "g_pitch.h" 81#include "mode.h" 82#include "cnst.h" 83#include "basic_op.h" 84 85/*---------------------------------------------------------------------------- 86; MACROS 87; Define module specific macros here 88----------------------------------------------------------------------------*/ 89 90 91/*---------------------------------------------------------------------------- 92; DEFINES 93; Include all pre-processor statements here. Include conditional 94; compile variables also. 95----------------------------------------------------------------------------*/ 96 97/*---------------------------------------------------------------------------- 98; LOCAL FUNCTION DEFINITIONS 99; Function Prototype declaration 100----------------------------------------------------------------------------*/ 101 102/*---------------------------------------------------------------------------- 103; LOCAL STORE/BUFFER/POINTER DEFINITIONS 104; Variable declaration - defined here and used outside this module 105----------------------------------------------------------------------------*/ 106 107 108/* 109------------------------------------------------------------------------------ 110 FUNCTION NAME: G_pitch 111------------------------------------------------------------------------------ 112 INPUT AND OUTPUT DEFINITIONS 113 114 Inputs: 115 mode = AMR mode (enum Mode) 116 xn = pointer to pitch target buffer (Word16) 117 y1 = pointer to filtered adaptive codebook buffer (Word16) 118 g_coeff = pointer to buffer of correlations needed for gain quantization 119 (Word16) 120 L_subfr = length of subframe (Word16) 121 pOverflow = pointer to overflow flag (Flag) 122 123 Outputs: 124 g_coeff contains the mantissa and exponent of the two dot products. 125 pOverflow -> 1 if an overflow occurs 126 127 Returns: 128 gain = ratio of dot products.(Word16) 129 130 Global Variables Used: 131 None. 132 133 Local Variables Needed: 134 None. 135 136------------------------------------------------------------------------------ 137 FUNCTION DESCRIPTION 138 139 This function computes the pitch (adaptive codebook) gain. The adaptive 140 codebook gain is given by 141 142 g = <x[], y[]> / <y[], y[]> 143 144 where: x[] is the target vector 145 y[] is the filtered adaptive codevector 146 <> denotes dot product. 147 148 The gain is limited to the range [0,1.2] (=0..19661 Q14) 149 150------------------------------------------------------------------------------ 151 REQUIREMENTS 152 153 None. 154 155------------------------------------------------------------------------------ 156 REFERENCES 157 158 g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 159 160------------------------------------------------------------------------------ 161 PSEUDO-CODE 162 163Word16 G_pitch ( // o : Gain of pitch lag saturated to 1.2 164 enum Mode mode, // i : AMR mode 165 Word16 xn[], // i : Pitch target. 166 Word16 y1[], // i : Filtered adaptive codebook. 167 Word16 g_coeff[], // i : Correlations need for gain quantization 168 Word16 L_subfr // i : Length of subframe. 169) 170{ 171 Word16 i; 172 Word16 xy, yy, exp_xy, exp_yy, gain; 173 Word32 s; 174 175 Word16 scaled_y1[L_SUBFR]; // Usually dynamic allocation of (L_subfr) 176 177 // divide "y1[]" by 4 to avoid overflow 178 179// The reference ETSI code uses a global overflow Flag. However in the actual 180// implementation a pointer to the overflow flag is passed into the function. 181 182 for (i = 0; i < L_subfr; i++) 183 { 184 scaled_y1[i] = shr (y1[i], 2); 185 } 186 187 // Compute scalar product <y1[],y1[]> 188 189 // Q12 scaling / MR122 190 Overflow = 0; 191 s = 1L; // Avoid case of all zeros 192 for (i = 0; i < L_subfr; i++) 193 { 194 s = L_mac (s, y1[i], y1[i]); 195 } 196 if (Overflow == 0) // Test for overflow 197 { 198 exp_yy = norm_l (s); 199 yy = pv_round (L_shl (s, exp_yy)); 200 } 201 else 202 { 203 s = 1L; // Avoid case of all zeros 204 for (i = 0; i < L_subfr; i++) 205 { 206 s = L_mac (s, scaled_y1[i], scaled_y1[i]); 207 } 208 exp_yy = norm_l (s); 209 yy = pv_round (L_shl (s, exp_yy)); 210 exp_yy = sub (exp_yy, 4); 211 } 212 213 // Compute scalar product <xn[],y1[]> 214 215 Overflow = 0; 216 s = 1L; // Avoid case of all zeros 217 218 for (i = 0; i < L_subfr; i++) 219 { 220 s = L_mac(s, xn[i], y1[i]); 221 } 222 if (Overflow == 0) 223 { 224 exp_xy = norm_l (s); 225 xy = pv_round (L_shl (s, exp_xy)); 226 } 227 else 228 { 229 s = 1L; // Avoid case of all zeros 230 for (i = 0; i < L_subfr; i++) 231 { 232 s = L_mac (s, xn[i], scaled_y1[i]); 233 } 234 exp_xy = norm_l (s); 235 xy = pv_round (L_shl (s, exp_xy)); 236 exp_xy = sub (exp_xy, 2); 237 } 238 239 g_coeff[0] = yy; 240 g_coeff[1] = sub (15, exp_yy); 241 g_coeff[2] = xy; 242 g_coeff[3] = sub (15, exp_xy); 243 244 // If (xy < 4) gain = 0 245 246 i = sub (xy, 4); 247 248 if (i < 0) 249 return ((Word16) 0); 250 251 // compute gain = xy/yy 252 253 xy = shr (xy, 1); // Be sure xy < yy 254 gain = div_s (xy, yy); 255 256 i = sub (exp_xy, exp_yy); // Denormalization of division 257 gain = shr (gain, i); 258 259 // if(gain >1.2) gain = 1.2 260 261 if (sub (gain, 19661) > 0) 262 { 263 gain = 19661; 264 } 265 266 if (sub(mode, MR122) == 0) 267 { 268 // clear 2 LSBits 269 gain = gain & 0xfffC; 270 } 271 272 return (gain); 273} 274 275------------------------------------------------------------------------------ 276 RESOURCES USED [optional] 277 278 When the code is written for a specific target processor the 279 the resources used should be documented below. 280 281 HEAP MEMORY USED: x bytes 282 283 STACK MEMORY USED: x bytes 284 285 CLOCK CYCLES: (cycle count equation for this function) + (variable 286 used to represent cycle count for each subroutine 287 called) 288 where: (cycle count variable) = cycle count for [subroutine 289 name] 290 291------------------------------------------------------------------------------ 292 CAUTION [optional] 293 [State any special notes, constraints or cautions for users of this function] 294 295------------------------------------------------------------------------------ 296*/ 297 298Word16 G_pitch( /* o : Gain of pitch lag saturated to 1.2 */ 299 enum Mode mode, /* i : AMR mode */ 300 Word16 xn[], /* i : Pitch target. Q0 */ 301 Word16 y1[], /* i : Filtered adaptive codebook. Q12 */ 302 Word16 g_coeff[], /* i : Correlations need for gain quantization */ 303 Word16 L_subfr, /* i : Length of subframe. */ 304 Flag *pOverflow /* i/o : Overflow flag */ 305) 306{ 307 308 Word16 i; 309 Word16 xy; 310 Word16 yy; 311 Word16 exp_xy; 312 Word16 exp_yy; 313 Word16 gain; 314 Word16 tmp; 315 Word32 s; 316 Word32 s1; 317 Word32 L_temp; /* Use this as an intermediate value */ 318 Word16 *p_xn = &xn[0]; 319 Word16 *p_y1 = &y1[0]; 320 321 /* Compute scalar product <y1[],y1[]> */ 322 323 /* Q12 scaling / MR122 */ 324 *pOverflow = 0; 325 s = 0; 326 327 for (i = L_subfr >> 2; i != 0; i--) 328 { 329 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s); 330 p_y1++; 331 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s); 332 p_y1++; 333 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s); 334 p_y1++; 335 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s); 336 p_y1++; 337 } 338 if ((s >= 0) & (s < 0x40000000)) 339 { 340 s <<= 1; 341 s += 1; /* Avoid case of all zeros */ 342 343 exp_yy = norm_l(s); /* Note 0<=exp_yy <= 31 */ 344 L_temp = s << exp_yy; 345 yy = pv_round(L_temp, pOverflow); 346 } 347 else 348 { 349 s = 0; /* Avoid case of all zeros */ 350 p_y1 = &y1[0]; 351 for (i = (L_subfr >> 1); i != 0; i--) 352 { 353 tmp = *(p_y1++) >> 2; 354 s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s); 355 tmp = *(p_y1++) >> 2; 356 s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s); 357 } 358 359 s <<= 1; 360 s += 1; /* Avoid case of all zeros */ 361 362 exp_yy = norm_l(s); 363 L_temp = s << exp_yy; 364 yy = pv_round(L_temp, pOverflow); 365 exp_yy = exp_yy - 4; 366 367 } 368 369 /* Compute scalar product <xn[],y1[]> */ 370 371 s = 0; 372 p_y1 = &y1[0]; 373 *pOverflow = 0; 374 375 for (i = L_subfr; i != 0; i--) 376 { 377 L_temp = ((Word32) * (p_xn++) * *(p_y1++)); 378 s1 = s; 379 s = s1 + L_temp; 380 381 if ((s1 ^ L_temp) > 0) 382 { 383 if ((s1 ^ s) < 0) 384 { 385 *pOverflow = 1; 386 break; 387 } 388 } 389 } 390 391 if (!(*pOverflow)) 392 { 393 394 s <<= 1; 395 s += 1; /* Avoid case of all zeros */ 396 397 exp_xy = norm_l(s); /* Note 0<=exp_yy <= 31 */ 398 L_temp = s << exp_xy; 399 xy = pv_round(L_temp, pOverflow); 400 } 401 else 402 { 403 s = 0; /* Avoid case of all zeros */ 404 p_y1 = &y1[0]; 405 for (i = (L_subfr >> 2); i != 0; i--) 406 { 407 L_temp = (Word32)(*(p_y1++) >> 2); 408 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s); 409 L_temp = (Word32)(*(p_y1++) >> 2); 410 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s); 411 L_temp = (Word32)(*(p_y1++) >> 2); 412 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s); 413 L_temp = (Word32)(*(p_y1++) >> 2); 414 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s); 415 } 416 417 s <<= 1; 418 s += 1; /* Avoid case of all zeros */ 419 420 exp_xy = norm_l(s); 421 L_temp = s << exp_xy; 422 xy = pv_round(L_temp, pOverflow); 423 exp_xy = exp_xy - 4; 424 425 } 426 427 g_coeff[0] = yy; 428 g_coeff[1] = 15 - exp_yy; 429 g_coeff[2] = xy; 430 g_coeff[3] = 15 - exp_xy; 431 432 /* If (xy < 4) gain = 0 */ 433 if (xy < 4) 434 { 435 return ((Word16) 0); 436 } 437 438 /* compute gain = xy/yy */ 439 /* Be sure xy < yy */ 440 441 xy = xy >> 1; 442 443 gain = div_s(xy, yy); 444 445 i = exp_xy - exp_yy; /* Denormalization of division */ 446 447 gain = shr(gain, i, pOverflow); 448 449 450 /* if(gain >1.2) gain = 1.2 */ 451 if (gain > 19661) 452 { 453 gain = 19661; 454 } 455 456 if (mode == MR122) 457 { 458 /* clear 2 LSBits */ 459 gain = gain & 0xfffC; 460 } 461 462 return(gain); 463 464} 465