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 20 Pathname: tns_ar_filter.c 21 22 ------------------------------------------------------------------------------ 23 REVISION HISTORY 24 25 Description: Modified from original shareware code 26 27 Description: Implemented 24-bit fixed point version 28 Optimized C code 29 30 Description: 31 - Added OVERFLOW_SHIFT_DOWN to avoid overflow. 32 - Increased precision by using the Q format of the LPC coefficient. 33 - Modified interface to add LPC Q format and scratch memory 34 for the state variables. 35 - Added pv_memset to clear state filter 36 - Updated format for comments (to PV standard) 37 - Updated copyright notice 38 39 Description: 40 - Changed multiplication scheme to increase precision. This 41 works better than older version. 42 43 Description: 44 - Include log2(order) as a scaling down parameter. 45 46 Description: 47 Modified to reflect code review comments 48 - misspelled words, extra comments and explicit requirements 49 50 Description: 51 deleted comment about fix Q format (L 107) 52 53 Description: Implemented a more efficient version, which eliminated the use 54 of "scratch memory" via introducing a pointer that references the actual 55 output. 56 57 Description: Removed the parameter "scratch_Int32_buffer" as this space 58 in memory is no longer needed by this function. 59 60 Description: Removed references to "scratch_Int32_buffer" in the Inputs 61 section. 62 63 Description: 64 Modified casting to ensure proper operations for different platforms 65 66 Description: 67 Per code review comment: 68 Eliminated casting to UInt and Int in b_low and b_high, they are 69 redundant and may add unncessary extra cycles in some platforms 70 71 Description: Updated the SW template to include the full pathname to the 72 source file and a slightly modified copyright header. 73 74 Description: Changed the order of the unsigned * signed multiply so the 75 casting to Int32 is performed on the unsigned operand. 76 77 Description: 78 Modified 32 by 16 bit multiplications to avoid unnecessary moves to 79 registers. Also split the code (based on flag direction) to simplify 80 pointer's updates 81 82 Description: 83 84 ------------------------------------------------------------------------------ 85 INPUT AND OUTPUT DEFINITIONS 86 87 Inputs: 88 spec = spectral input to be shaped by the filter. 89 Fixed point format 90 Int32[] 91 length = spec_length 92 93 spec_length = length of spec array. 94 const Int 95 96 direction = direction for application of tns filter. 97 +1 filters spectrum from low to high frequencies 98 (first input to filter is spec[0]) 99 -1 filters spectrum from high to low frequencies 100 (first input to filter is spec[spec_length-1]) 101 const Int 102 103 lpc = array of lpc coefficients, minus lpc[0] which is assumed to be "1" 104 Fixed point format 105 const Int[] 106 length = TNS_MAX_ORDER 107 108 Q_lpc = Q format for the lpc coeffcients (for max. precision, it assumes 109 that all 16 bits are used) 110 const Int 111 112 order = order of the TNS filter (Range of 1 - TNS_MAX_ORDER) 113 Int 114 115 Local Stores/Buffers/Pointers Needed: 116 None 117 118 Global Stores/Buffers/Pointers Needed: 119 None 120 121 Outputs: 122 None 123 124 Pointers and Buffers Modified: 125 spec = contains spectral data after application of TNS filter 126 Int32 array 127 length = spec_length 128 129 130 Local Stores Modified: 131 132 Global Stores Modified: 133 134 135 ------------------------------------------------------------------------------ 136 FUNCTION DESCRIPTION 137 138 A block of spectral data (Int32 spec[]) of length (const Int spec_length) 139 is processed by a simple all-pole filter defined by 140 LPC coefficients passed via (const Int lpc[]) 141 142 TNS filter equation 143 y(n) = x(n) - lpc(2)*y(n-1) - ... - lpc(order+1)*y(n-order) 144 145 The filter calculation is performed in place, i.e. the output is passed 146 back to the calling function via (Int32 spec[]) 147 148 The filter's order is defined by the variable (const Int order) 149 The direction of the filter's application is defined by (const Int inc) 150 151 ------------------------------------------------------------------------------ 152 REQUIREMENTS 153 154 This function should match the functionality of the ISO code. 155 The implementation does support filter orders bigger or equal to 1. 156 The size of the spectral coeffcients has to be bigger or equal than 1. 157 158 ------------------------------------------------------------------------------ 159 REFERENCES 160 161 (1) ISO/IEC 14496-3:1999(E) 162 Part 3 163 Subpart 4.6.8 (Temporal Noise Shaping) 164 165 (2) MPEG-2 NBC Audio Decoder 166 "This software module was originally developed by AT&T, Dolby 167 Laboratories, Fraunhofer Gesellschaft IIS in the course of development 168 of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and 169 3. This software module is an implementation of a part of one or more 170 MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 171 Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio 172 standards free license to this software module or modifications thereof 173 for use in hardware or software products claiming conformance to the 174 MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software 175 module in hardware or software products are advised that this use may 176 infringe existing patents. The original developer of this software 177 module and his/her company, the subsequent editors and their companies, 178 and ISO/IEC have no liability for use of this software module or 179 modifications thereof in an implementation. Copyright is not released 180 for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original 181 developer retains full right to use the code for his/her own purpose, 182 assign or donate the code to a third party and to inhibit third party 183 from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products. 184 This copyright notice must be included in all copies or derivative 185 works." 186 Copyright(c)1996. 187 188 ------------------------------------------------------------------------------ 189 PSEUDO-CODE 190 191 192 FOR (i=0; i<order; i++) 193 state[i] = 0; 194 ENDFOR 195 196 IF (inc == -1) 197 THEN 198 spec = spec + spec_length - 1; 199 ENDIF 200 201 FOR (i=0; i<spec_length; i++) 202 203 y = *spec; 204 205 FOR (j=0; j<order; j++) 206 207 y -= lpc[j] * state[j]; 208 209 ENDFOR 210 211 FOR (j=order-1; j>0; j--) 212 213 state[j] = state[j-1]; 214 215 ENDFOR 216 217 state[0] = y; 218 219 *spec = y; 220 221 spec = spec + inc; 222 223 ENDFOR 224 225 226 ------------------------------------------------------------------------------ 227 RESOURCES USED 228 229 When the code is written for a specific target processor 230 the resources used should be documented below. 231 232 STACK USAGE: [stack count for this module] + [variable to represent 233 stack usage for each subroutine called] 234 235 where: [stack usage variable] = stack usage for [subroutine 236 name] (see [filename].ext) 237 238 DATA MEMORY USED: x words 239 240 PROGRAM MEMORY USED: x words 241 242 CLOCK CYCLES: [cycle count equation for this module] + [variable 243 used to represent cycle count for each subroutine 244 called] 245 246 where: [cycle count variable] = cycle count for [subroutine 247 name] (see [filename].ext) 248 249 ------------------------------------------------------------------------------ 250 */ 251 252 /*---------------------------------------------------------------------------- 253 ; INCLUDES 254 ----------------------------------------------------------------------------*/ 255 #include "pv_audio_type_defs.h" 256 #include "e_tns_const.h" 257 #include "tns_ar_filter.h" 258 #include "fxp_mul32.h" 259 260 /*---------------------------------------------------------------------------- 261 ; MACROS 262 ; Define module specific macros here 263 ----------------------------------------------------------------------------*/ 264 265 /*---------------------------------------------------------------------------- 266 ; DEFINES 267 ; Include all pre-processor statements here. Include conditional 268 ; compile variables also. 269 ----------------------------------------------------------------------------*/ 270 #define MASK_LOW16 0xFFFF 271 #define UPPER16 16 272 273 /*---------------------------------------------------------------------------- 274 ; LOCAL FUNCTION DEFINITIONS 275 ; Function Prototype declaration 276 ----------------------------------------------------------------------------*/ 277 278 /*---------------------------------------------------------------------------- 279 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS 280 ; Variable declaration - defined here and used outside this module 281 ----------------------------------------------------------------------------*/ 282 283 /*---------------------------------------------------------------------------- 284 ; EXTERNAL FUNCTION REFERENCES 285 ; Declare functions defined elsewhere and referenced in this module 286 ----------------------------------------------------------------------------*/ 287 288 /*---------------------------------------------------------------------------- 289 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 290 ; Declare variables used in this module but defined elsewhere 291 ----------------------------------------------------------------------------*/ 292 293 /*---------------------------------------------------------------------------- 294 ; FUNCTION CODE 295 ----------------------------------------------------------------------------*/ 296 297 Int tns_ar_filter( 298 Int32 spec[], 299 const Int spec_length, 300 const Int direction, 301 const Int32 lpc[], 302 const Int Q_lpc, 303 const Int order) 304 { 305 306 Int i; 307 Int j; 308 309 /* 310 * Multiplication related variables 311 */ 312 313 Int32 temp; 314 315 /* 316 * Filter related variables 317 */ 318 Int32 y0; 319 320 /* 321 * Circular buffer to hold the filter's state 322 * (y[n-1],y[n-2],y[n-3],etc.) 323 * 324 * p_state and p_lpc should take advantage 325 * of any special circular buffer instructions 326 * if this code is hand-optimized in assembly. 327 */ 328 329 Int32 *p_state = NULL; 330 331 const Int32 *p_lpc; 332 333 334 Int shift_up; 335 Int shift_down_amount; 336 337 /* 338 * Pointer to the I/O memory space 339 */ 340 Int32 *p_spec = spec; 341 342 343 i = 0; 344 j = order; 345 346 /* 347 * get the power of 2 that is bigger than the order 348 * i is the bit counter and j is modified until exceed 349 * the power of 2 corresponding to TNS_MAX_ORDER 350 */ 351 352 while (j < 0x010) 353 { 354 j <<= 1; 355 i++; 356 } 357 358 /* 359 * 5 is the number of bits needed to represent 0x010 360 * TNS_MAX_ORDER = 20, power of 2 that include 20 is 5 361 */ 362 shift_down_amount = 4 - i; 363 364 shift_up = UPPER16 - Q_lpc; 365 366 /* 367 * shift_down_amount == power of 2 that is bigger than the order - 1 368 */ 369 370 shift_down_amount += shift_up; 371 372 if (direction == -1) 373 { 374 p_spec += spec_length - 1; 375 376 for (i = order; i != 0; i--) 377 { 378 379 y0 = *p_spec >> shift_down_amount; 380 381 p_lpc = lpc; 382 383 /* 32 by 32 bit multiplication */ 384 for (j = order; j > i; j--) 385 { 386 temp = *p_state++; 387 y0 -= fxp_mul32_Q31(temp, *(p_lpc++)) << shift_up; 388 } 389 390 /* 391 * Record the output in-place 392 */ 393 p_state = p_spec; 394 *(p_spec--) = y0; 395 396 } 397 398 if (spec_length > order) 399 { 400 for (i = (spec_length - order); i != 0; i--) 401 { 402 y0 = *p_spec >> shift_down_amount; 403 404 p_lpc = &(lpc[0]); 405 406 /* 32 by 32 bit multiplication */ 407 for (j = order; j != 0; j--) 408 { 409 temp = *p_state++; 410 y0 -= fxp_mul32_Q31(temp, *(p_lpc++)) << shift_up; 411 } 412 413 /* 414 * Record the output in-place 415 */ 416 p_state = p_spec; 417 *(p_spec--) = y0; 418 419 } /* END for (i = (spec_length - order); i>0; i--) */ 420 } 421 422 } 423 else 424 { 425 for (i = order; i != 0; i--) 426 { 427 428 p_lpc = lpc; 429 430 y0 = 0; 431 432 /* 32 by 32 bit multiplication */ 433 for (j = order; j > i; j--) 434 { 435 y0 -= fxp_mul32_Q31(*p_state--, *(p_lpc++)); 436 } 437 438 p_state = p_spec; 439 /* 440 * Record the output in-place 441 */ 442 *(p_spec) = (*p_spec >> shift_down_amount) + (y0 << shift_up); 443 p_spec++; 444 } 445 446 if (spec_length > order) 447 { 448 for (i = (spec_length - order); i != 0; i--) 449 { 450 p_lpc = lpc; 451 452 y0 = 0; 453 454 /* 32 by 32 bit multiplication */ 455 for (j = order; j != 0; j--) 456 { 457 y0 -= fxp_mul32_Q31(*p_state--, *(p_lpc++)); 458 } 459 460 p_state = p_spec; 461 /* 462 * Record the output in-place 463 */ 464 *(p_spec) = (*p_spec >> shift_down_amount) + (y0 << shift_up); 465 p_spec++; 466 467 } /* END for (i = (spec_length - order); i>0; i--) */ 468 } 469 } 470 471 return(shift_down_amount); 472 473 474 } /* tns_ar_filter */ 475