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/autocorr.c 35 36 Date: 05/15/2000 37 38 ------------------------------------------------------------------------------ 39 REVISION HISTORY 40 41 Description: Put into template...starting optimization. 42 43 Description: Removed call to mult_r routine. 44 45 Description: Modified Input/Output Definitions section to comply with the 46 current template. Fixed tabs. 47 48 Description: Updated Input/Output definitions by making them more 49 descriptive. 50 51 Description: Synchronized file with UMTS version 3.2.0. Updated coding 52 template. 53 54 Description: Made the following changes per comments from Phase 2/3 review: 55 1. Added full pathname of file. 56 2. Fixed typecasting issue with TI compiler. 57 3. Modified FOR loops to count down. 58 4. Added comment to the code. 59 60 Description: Removed extern to global paramter (Flag Overflow) and replaced 61 by passing in a pointer to Overflow. Also, made several small changes to 62 bring code more in line with PV Standards. 63 64 Description: 65 1. Added pointer to avoid adding offsets in every pass 66 2. Break last loop in two nested loop to speed up processing 67 3. Removed extra check for overflow by doing scaling right 68 after overflow is detected. 69 4. Eliminated calls to basic operations (like extract) not 70 needed because of the nature of the number (all bounded) 71 72 Description: 73 1. Fixed for: 74 overflow check was looking for positive number before a left 75 shift. When numbers were big enough, positive numbers after 76 shifted became negative, causing a 1/0 division). 77 Fixed so now it checks for numbers lesser than 0x40000000 78 before the left shift 79 80 Description: 81 1.Modified check for saturation to match bit exact test. 82 Also, when saturation is reached, a faster loop is used 83 (with no energy accumulation) to speed up processing 84 85 86 Description: 87 1.Added pointer initialization to for loop when saturation 88 is found. This because some compiler ( like Vcpp in release 89 mode) when optimizing code, may remove pointer information 90 once the loop is broken. 91 92 Description: Added casting to eliminate warnings 93 94 Description: Replaced "int" and/or "char" with OSCL defined types. 95 96 Description: Using inlines from fxp_arithmetic.h. 97 98 Description: Replacing fxp_arithmetic.h with basic_op.h. 99 100 Description: 101 102 ----------------------------------------------------------------------------*/ 103 104 /*---------------------------------------------------------------------------- 105 ; INCLUDES 106 ----------------------------------------------------------------------------*/ 107 #include "autocorr.h" 108 #include "typedef.h" 109 #include "basic_op.h" 110 #include "oper_32b.h" 111 #include "cnst.h" 112 113 /*---------------------------------------------------------------------------- 114 ; MACROS 115 ; Define module specific macros here 116 ----------------------------------------------------------------------------*/ 117 118 119 /*---------------------------------------------------------------------------- 120 ; DEFINES 121 ; Include all pre-processor statements here. Include conditional 122 ; compile variables also. 123 ----------------------------------------------------------------------------*/ 124 125 126 /*---------------------------------------------------------------------------- 127 ; LOCAL FUNCTION DEFINITIONS 128 ; Function Prototype declaration 129 ----------------------------------------------------------------------------*/ 130 131 /*---------------------------------------------------------------------------- 132 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS 133 ; Variable declaration - defined here and used outside this module 134 ----------------------------------------------------------------------------*/ 135 136 /*---------------------------------------------------------------------------- 137 ; EXTERNAL FUNCTION REFERENCES 138 ; Declare functions defined elsewhere and referenced in this module 139 ----------------------------------------------------------------------------*/ 140 141 142 /*---------------------------------------------------------------------------- 143 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 144 ; Declare variables used in this module but defined elsewhere 145 ----------------------------------------------------------------------------*/ 146 147 /* 148 ------------------------------------------------------------------------------ 149 FUNCTION NAME: Autocorr 150 ---------------------------------------------------------------------------- 151 INPUT AND OUTPUT DEFINITIONS 152 153 Inputs: 154 x = buffer of input signals of type Word16 155 m = LPC order of type Word16 156 wind = buffer of window signals of type Word16 157 r_h = buffer containing the high word of the autocorrelation values 158 of type Word16 159 r_l = buffer containing the low word of the autocorrelation values 160 of type Word16 161 162 pOverflow = pointer to variable of type Flag *, which indicates if 163 overflow occurs. 164 165 Outputs: 166 r_h buffer contains the high word of the new autocorrelation values 167 r_l buffer contains the low word of the new autocorrelation values 168 pOverflow -> 1 if overflow occurs. 169 170 Returns: 171 norm = normalized autocorrelation at lag zero of type Word16 172 173 Global Variables Used: 174 None 175 176 Local Variables Needed: 177 None 178 179 ------------------------------------------------------------------------------ 180 FUNCTION DESCRIPTION 181 182 This function windows the input signal with the provided window 183 then calculates the autocorrelation values for lags of 0,1,...m, 184 where m is the passed in LPC order. 185 186 ------------------------------------------------------------------------------ 187 REQUIREMENTS 188 189 None. 190 191 ------------------------------------------------------------------------------ 192 REFERENCES 193 194 autocorr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 195 196 ------------------------------------------------------------------------------ 197 PSEUDO-CODE 198 199 Word16 Autocorr ( 200 Word16 x[], // (i) : Input signal (L_WINDOW) 201 Word16 m, // (i) : LPC order 202 Word16 r_h[], // (o) : Autocorrelations (msb) 203 Word16 r_l[], // (o) : Autocorrelations (lsb) 204 const Word16 wind[] // (i) : window for LPC analysis (L_WINDOW) 205 ) 206 { 207 Word16 i, j, norm; 208 Word16 y[L_WINDOW]; 209 Word32 sum; 210 Word16 overfl, overfl_shft; 211 212 // Windowing of signal 213 214 for (i = 0; i < L_WINDOW; i++) 215 { 216 y[i] = mult_r (x[i], wind[i]); 217 } 218 219 // Compute r[0] and test for overflow 220 221 overfl_shft = 0; 222 223 do 224 { 225 overfl = 0; 226 sum = 0L; 227 228 for (i = 0; i < L_WINDOW; i++) 229 { 230 sum = L_mac (sum, y[i], y[i]); 231 } 232 233 // If overflow divide y[] by 4 234 235 if (L_sub (sum, MAX_32) == 0L) 236 { 237 overfl_shft = add (overfl_shft, 4); 238 overfl = 1; // Set the overflow flag 239 240 for (i = 0; i < L_WINDOW; i++) 241 { 242 y[i] = shr (y[i], 2); 243 } 244 } 245 } 246 while (overfl != 0); 247 248 sum = L_add (sum, 1L); // Avoid the case of all zeros 249 250 // Normalization of r[0] 251 252 norm = norm_l (sum); 253 sum = L_shl (sum, norm); 254 L_Extract (sum, &r_h[0], &r_l[0]); // Put in DPF format (see oper_32b) 255 256 // r[1] to r[m] 257 258 for (i = 1; i <= m; i++) 259 { 260 sum = 0; 261 262 for (j = 0; j < L_WINDOW - i; j++) 263 { 264 sum = L_mac (sum, y[j], y[j + i]); 265 } 266 267 sum = L_shl (sum, norm); 268 L_Extract (sum, &r_h[i], &r_l[i]); 269 } 270 271 norm = sub (norm, overfl_shft); 272 273 return norm; 274 } 275 276 277 ------------------------------------------------------------------------------ 278 RESOURCES USED [optional] 279 280 When the code is written for a specific target processor the 281 the resources used should be documented below. 282 283 HEAP MEMORY USED: x bytes 284 285 STACK MEMORY USED: x bytes 286 287 CLOCK CYCLES: (cycle count equation for this function) + (variable 288 used to represent cycle count for each subroutine 289 called) 290 where: (cycle count variable) = cycle count for [subroutine 291 name] 292 293 ------------------------------------------------------------------------------ 294 CAUTION [optional] 295 [State any special notes, constraints or cautions for users of this function] 296 297 ------------------------------------------------------------------------------ 298 */ 299 300 Word16 Autocorr( 301 Word16 x[], /* (i) : Input signal (L_WINDOW) */ 302 Word16 m, /* (i) : LPC order */ 303 Word16 r_h[], /* (o) : Autocorrelations (msb) */ 304 Word16 r_l[], /* (o) : Autocorrelations (lsb) */ 305 const Word16 wind[], /* (i) : window for LPC analysis (L_WINDOW) */ 306 Flag *pOverflow /* (o) : indicates overflow */ 307 ) 308 { 309 register Word16 i; 310 register Word16 j; 311 register Word16 norm; 312 313 Word16 y[L_WINDOW]; 314 Word32 sum; 315 Word16 overfl_shft; 316 317 318 /* Added for optimization */ 319 320 321 Word16 temp; 322 Word16 *p_x; 323 Word16 *p_y; 324 Word16 *p_y_1; 325 Word16 *p_y_ref; 326 Word16 *p_rh; 327 Word16 *p_rl; 328 const Word16 *p_wind; 329 p_y = y; 330 p_x = x; 331 p_wind = wind; 332 /* 333 * Windowing of the signal 334 */ 335 336 OSCL_UNUSED_ARG(pOverflow); 337 338 sum = 0L; 339 j = 0; 340 341 for (i = L_WINDOW; i != 0; i--) 342 { 343 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15; 344 *(p_y++) = temp; 345 346 sum += ((Word32)temp * temp) << 1; 347 if (sum < 0) 348 { 349 /* 350 * if oveflow exist, then stop accumulation 351 */ 352 j = 1; 353 break; 354 } 355 356 } 357 /* 358 * if oveflow existed, complete windowing operation 359 * without computing energy 360 */ 361 362 if (j) 363 { 364 p_y = &y[L_WINDOW-i]; 365 p_x = &x[L_WINDOW-i]; 366 p_wind = &wind[L_WINDOW-i]; 367 368 for (; i != 0; i--) 369 { 370 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15; 371 *(p_y++) = temp; 372 } 373 } 374 375 376 /* 377 * Compute r[0] and test for overflow 378 */ 379 380 overfl_shft = 0; 381 382 /* 383 * scale down by 1/4 only when needed 384 */ 385 while (j == 1) 386 { 387 /* If overflow divide y[] by 4 */ 388 /* FYI: For better resolution, we could */ 389 /* divide y[] by 2 */ 390 overfl_shft += 4; 391 p_y = &y[0]; 392 sum = 0L; 393 394 for (i = (L_WINDOW >> 1); i != 0 ; i--) 395 { 396 temp = *p_y >> 2; 397 *(p_y++) = temp; 398 sum += ((Word32)temp * temp) << 1; 399 temp = *p_y >> 2; 400 *(p_y++) = temp; 401 sum += ((Word32)temp * temp) << 1; 402 } 403 if (sum > 0) 404 { 405 j = 0; 406 } 407 408 } 409 410 sum += 1L; /* Avoid the case of all zeros */ 411 412 /* Normalization of r[0] */ 413 414 norm = norm_l(sum); 415 416 sum <<= norm; 417 418 /* Put in DPF format (see oper_32b) */ 419 r_h[0] = (Word16)(sum >> 16); 420 r_l[0] = (Word16)((sum >> 1) - ((Word32)(r_h[0]) << 15)); 421 422 /* r[1] to r[m] */ 423 424 p_y_ref = &y[L_WINDOW - 1 ]; 425 p_rh = &r_h[m]; 426 p_rl = &r_l[m]; 427 428 for (i = m; i > 0; i--) 429 { 430 sum = 0; 431 432 p_y = &y[L_WINDOW - i - 1]; 433 p_y_1 = p_y_ref; 434 435 for (j = (L_WINDOW - i - 1) >> 1; j != 0; j--) 436 { 437 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum); 438 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum); 439 } 440 441 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum); 442 443 if (((L_WINDOW - i - 1) & 1)) 444 { 445 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum); 446 } 447 448 sum <<= (norm + 1); 449 450 *(p_rh) = (Word16)(sum >> 16); 451 *(p_rl--) = (Word16)((sum >> 1) - ((Word32) * (p_rh--) << 15)); 452 453 } 454 455 norm -= overfl_shft; 456 457 return (norm); 458 459 } /* Autocorr */ 460