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_inv_filter.c 21 22 ------------------------------------------------------------------------------ 23 REVISION HISTORY 24 25 Description: Changes made per review comments. 26 27 Description: As requested by JT, the q-format for the LPC coefficients is 28 now passed via the parameter lpc_qformat. 29 30 Description: For speed, the calculation of the shift amount was pulled 31 outside of the loop. 32 33 Description: 34 Modified casting to ensure proper operations for different platforms 35 36 Description: 37 Simplified MAC operations for filter by eliminating extra variables 38 39 Who: Date: 40 Description: 41 42 ------------------------------------------------------------------------------ 43 INPUT AND OUTPUT DEFINITIONS 44 45 Inputs: 46 47 coef = spectral input to be shaped by the filter. 48 Fixed point format 49 [Int32[], length = num_coef] 50 51 num_coef = length of spec array. 52 [const Int] 53 54 direction = direction for application of tns filter. 55 +1 applies forward filter 56 (first input to filter is coef[0]) 57 -1 applies reversed filter 58 (first input to filter is coef[num_coef-1]) 59 [const Int] 60 61 lpc = array of lpc coefficients. 62 Fixed point format Q-11 63 [const Int[], length = TNS_MAX_ORDER] 64 65 lpc_qformat = The q-format of the lpc coefficients. 66 [const Int] 67 68 order = order of the TNS filter (Range of 1 : TNS_MAX_ORDER) 69 [const Int] 70 71 scratch_memory = scratch_memory needed for filter operation 72 [Int[], length = TNS_MAX_ORDER] 73 74 Local Stores/Buffers/Pointers Needed: 75 None 76 77 Global Stores/Buffers/Pointers Needed: 78 None 79 80 Outputs: 81 None 82 83 Pointers and Buffers Modified: 84 coef = contains spectral data after application of TNS filter 85 q-format is not modified. 86 Int32 array 87 length = num_coef 88 89 Local Stores Modified: 90 None 91 92 Global Stores Modified: 93 None 94 95 ------------------------------------------------------------------------------ 96 FUNCTION DESCRIPTION 97 98 A block of spectral data (Int32 coef[]) of length (const Int num_coef) 99 is processed by a simple all-zero filter defined by 100 LPC coefficients passed via (const Int lpc[]) 101 102 TNS filter equation 103 y(n) = x(n) + lpc(2)*x(n-1) + ... + lpc(order+1)*x(n-order) 104 105 The filter calculation is performed in place, i.e. the output is passed 106 back to the calling function via (Int32 coef[]) 107 108 In order to avoid overflow, the filter input (Int32 coef[]) must utilize 109 only the lower 16-bits. The upper 16-bits must be available. 110 111 The filter's order is defined by the variable (const Int order) 112 113 The direction of the filter's application is defined by 114 (const Int direction) 115 116 ------------------------------------------------------------------------------ 117 REQUIREMENTS 118 119 [Int32 coef] must store no more than 16 bits of data. 120 121 This is required to utilize methods that do not change the q-format of 122 the input data [Int32 coef], and to make use of a fast 123 16 x 16 bit multiply. 124 125 This function should not be called for order <= 0. 126 127 This function must not be called with lpc_qformat < 5 128 ------------------------------------------------------------------------------ 129 REFERENCES 130 131 (1) ISO/IEC 14496-3:1999(E) 132 Part 3 133 Subpart 4.6.6.4.1 (LTP with TNS) 134 Subpart 4.6.8 (Temporal Noise Shaping) 135 136 (2) MPEG-2 NBC Audio Decoder 137 "This software module was originally developed by AT&T, Dolby 138 Laboratories, Fraunhofer Gesellschaft IIS in the course of development 139 of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and 140 3. This software module is an implementation of a part of one or more 141 MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 142 Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio 143 standards free license to this software module or modifications thereof 144 for use in hardware or software products claiming conformance to the 145 MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software 146 module in hardware or software products are advised that this use may 147 infringe existing patents. The original developer of this software 148 module and his/her company, the subsequent editors and their companies, 149 and ISO/IEC have no liability for use of this software module or 150 modifications thereof in an implementation. Copyright is not released 151 for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original 152 developer retains full right to use the code for his/her own purpose, 153 assign or donate the code to a third party and to inhibit third party 154 from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products. 155 This copyright notice must be included in all copies or derivative 156 works." 157 Copyright(c)1996. 158 159 ------------------------------------------------------------------------------ 160 PSEUDO-CODE 161 162 IF (direction == -1) 163 THEN 164 pCoef = pCoef + (num_coef - 1); 165 END IF 166 167 FOR (i = order; i > 0; i--) 168 169 *(pFilterInput) = 0; 170 pFilterInput = pFilterInput + 1; 171 172 END FOR 173 174 wrap_point = 0; 175 176 shift_amt = (lpc_qformat - 5); 177 178 FOR (i = num_coef; i > 0; i--) 179 180 pLPC = lpc; 181 182 mult = 0; 183 184 FOR (j = wrap_point; j>0; j--) 185 186 tempInt32 = (Int32)(*(pLPC) * *(pFilterInput)); 187 tempInt32 = tempInt32 >> 5; 188 189 mult = mult + tempInt32; 190 191 pFilterInput = pFilterInput + 1; 192 pLPC = pLPC + 1; 193 194 ENDFOR 195 196 pFilterInput = scratch_memory; 197 198 FOR (j = (order - wrap_point); j>0; j--) 199 200 tempInt32 = (Int32)(*(pLPC) * *(pFilterInput)); 201 tempInt32 = tempInt32 >> 5; 202 203 mult = mult + tempInt32; 204 205 pFilterInput = pFilterInput + 1; 206 pLPC = pLPC + 1; 207 208 ENDFOR 209 210 pFilterInput = pFilterInput - 1; 211 *(pFilterInput) = (Int)(*pCoef); 212 213 mult = mult >> shift_amt; 214 215 *(pCoef) = *(pCoef) + mult; 216 217 pCoef = pCoef + direction; 218 219 wrap_point = wrap_point + 1; 220 221 IF (wrap_point == order) 222 THEN 223 wrap_point = 0; 224 END IF 225 226 END FOR 227 228 ------------------------------------------------------------------------------ 229 RESOURCES USED 230 231 When the code is written for a specific target processor 232 the resources used should be documented below. 233 234 STACK USAGE: [stack count for this module] + [variable to represent 235 stack usage for each subroutine called] 236 237 where: [stack usage variable] = stack usage for [subroutine 238 name] (see [filename].ext) 239 240 DATA MEMORY USED: x words 241 242 PROGRAM MEMORY USED: x words 243 244 CLOCK CYCLES: [cycle count equation for this module] + [variable 245 used to represent cycle count for each subroutine 246 called] 247 248 where: [cycle count variable] = cycle count for [subroutine 249 name] (see [filename].ext) 250 251 ------------------------------------------------------------------------------ 252 */ 253 254 /*---------------------------------------------------------------------------- 255 ; INCLUDES 256 ----------------------------------------------------------------------------*/ 257 #include "pv_audio_type_defs.h" 258 #include "tns_inv_filter.h" 259 #include "fxp_mul32.h" 260 261 /*---------------------------------------------------------------------------- 262 ; MACROS 263 ; Define module specific macros here 264 ----------------------------------------------------------------------------*/ 265 266 /*---------------------------------------------------------------------------- 267 ; DEFINES 268 ; Include all pre-processor statements here. Include conditional 269 ; compile variables also. 270 ----------------------------------------------------------------------------*/ 271 272 /*---------------------------------------------------------------------------- 273 ; LOCAL FUNCTION DEFINITIONS 274 ; Function Prototype declaration 275 ----------------------------------------------------------------------------*/ 276 277 /*---------------------------------------------------------------------------- 278 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS 279 ; Variable declaration - defined here and used outside this module 280 ----------------------------------------------------------------------------*/ 281 282 /*---------------------------------------------------------------------------- 283 ; EXTERNAL FUNCTION REFERENCES 284 ; Declare functions defined elsewhere and referenced in this module 285 ----------------------------------------------------------------------------*/ 286 287 /*---------------------------------------------------------------------------- 288 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 289 ; Declare variables used in this module but defined elsewhere 290 ----------------------------------------------------------------------------*/ 291 292 /*---------------------------------------------------------------------------- 293 ; FUNCTION CODE 294 ----------------------------------------------------------------------------*/ 295 296 void tns_inv_filter( 297 Int32 coef[], 298 const Int num_coef, 299 const Int direction, 300 const Int32 lpc[], 301 const Int lpc_qformat, 302 const Int order, 303 Int32 scratch_memory[]) 304 { 305 306 Int i; 307 Int j; 308 Int shift_amt; 309 Int wrap_point; 310 311 Int32 mult; 312 313 /* 314 * Circular buffer to hold the filter's input 315 * 316 * (x[n-1],x[n-2],x[n-3],etc.) 317 * 318 * This scratch space is necessary, because 319 * the filter's output is returned in-place. 320 * 321 * pFilterInput and pLPC should take advantage 322 * of any special circular buffer instructions 323 * if this code is hand-optimized in assembly. 324 * 325 */ 326 Int32 *pFilterInput = scratch_memory; 327 328 const Int32 *pLPC; 329 330 /* 331 * Pointer to the I/O memory space 332 */ 333 Int32 *pCoef = coef; 334 335 if (direction == -1) 336 { 337 pCoef += (num_coef - 1); 338 } 339 340 /* Make sure the scratch memory is "clean" */ 341 for (i = order; i != 0; i--) 342 { 343 *(pFilterInput++) = 0; 344 } 345 346 wrap_point = 0; 347 348 shift_amt = (lpc_qformat - 5); 349 350 for (i = num_coef; i > 0; i--) 351 { 352 /* 353 * Copy spectral input into special 354 * filter input buffer. 355 */ 356 pLPC = lpc; 357 358 mult = 0; 359 360 /* 361 * wrap_point = 0 when this code is 362 * entered for the first iteration of 363 * for(i=num_coef; i>0; i--) 364 * 365 * So, this first for-loop will be 366 * skipped when i == num_coef. 367 */ 368 369 for (j = wrap_point; j > 0; j--) 370 { 371 mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5; 372 373 } /* for (j = wrap_point; j>0; j--) */ 374 375 /* 376 * pFilterInput has reached &scratch_memory[order-1] 377 * Reset pointer to beginning of filter's state memory 378 */ 379 pFilterInput = scratch_memory; 380 381 for (j = (order - wrap_point); j > 0; j--) 382 { 383 mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5; 384 385 } /* for (j = wrap_point; j>0; j--) */ 386 387 388 /* 389 * Fill the filter's state buffer 390 * avoid obvious casting 391 */ 392 *(--pFilterInput) = (*pCoef); 393 394 395 /* Scale the data down so the output q-format is not adjusted. 396 * 397 * Here is an equation, which shows how the spectral coefficients 398 * and lpc coefficients are multiplied and the spectral 399 * coefficient's q-format does not change. 400 * 401 * Q-(coef) * Q-(lpc_qformat) >> 5 = Q-(coef + lpc_q_format - 5) 402 * 403 * Q-(coef + lpc_q_format - 5) >> (lpc_qformat - 5) = Q-(coef) 404 */ 405 406 /* Store output in place */ 407 *(pCoef) += (mult >> shift_amt); 408 409 /* Adjust pointers and placeholders */ 410 pCoef += direction; 411 412 wrap_point++; 413 414 if (wrap_point == order) 415 { 416 wrap_point = 0; 417 } 418 419 } /* for (i = num_coef; i > 0; i--) */ 420 421 } /* tns_inv_filter */ 422