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: imdct_fxp.c 21 Funtions: imdct_fxp 22 23 ------------------------------------------------------------------------------ 24 INPUT AND OUTPUT DEFINITIONS 25 26 Inputs: 27 28 data_quant = Input vector, with quantized spectral lines: 29 type Int32 30 31 freq_2_time_buffer = Scratch memory used for in-place FFT calculation, 32 min size required 1024, 33 type Int32 34 35 n = Length of input vector "data_quant". Currently 256 or 2048 36 type const Int 37 38 Q_format = Q_format of the input vector "data_quant" 39 type Int 40 41 max = Maximum value inside input vector "data_quant" 42 type Int32 43 44 Local Stores/Buffers/Pointers Needed: 45 None 46 47 Global Stores/Buffers/Pointers Needed: 48 None 49 50 Outputs: 51 shift = shift factor to reflect scaling introduced by IFFT and imdct_fxp, 52 53 Pointers and Buffers Modified: 54 Results are return in "Data_Int_precision" 55 56 Local Stores Modified: 57 None 58 59 Global Stores Modified: 60 None 61 62 ------------------------------------------------------------------------------ 63 FUNCTION DESCRIPTION 64 65 The IMDCT is a linear orthogonal lapped transform, based on the idea of 66 time domain aliasing cancellation (TDAC). 67 IMDCT is critically sampled, which means that though it is 50% overlapped, 68 a sequence data after IMDCT has the same number of coefficients as samples 69 before the transform (after overlap-and-add). This means, that a single 70 block of IMDCT data does not correspond to the original block on which the 71 IMDCT was performed. When subsequent blocks of inverse transformed data 72 are added (still using 50% overlap), the errors introduced by the 73 transform cancels out.Thanks to the overlapping feature, the IMDCT is very 74 useful for quantization. It effectively removes the otherwise easily 75 detectable blocking artifact between transform blocks. 76 77 N = twice the length of input vector X 78 y = vector of length N, will hold fixed point IDCT 79 p = 0:1:N-1 80 81 2 N/2-1 82 y(p) = --- SUM X(m)*cos(pi/(2*N)*(2*p+1+N/2)*(2*m+1)) 83 N m=0 84 85 The window that completes the TDAC is applied before calling this function. 86 The IMDCT can be calculated using an IFFT, for this, the IMDCT need be 87 rewritten as an odd-time odd-frequency discrete Fourier transform. Thus, 88 the IMDCT can be calculated using only one n/4 point FFT and some pre and 89 post-rotation of the sample points. 90 91 92 where X(k) is the input with N frequency lines 93 94 X(k) ---------------------------- 95 | 96 | 97 Pre-rotation by exp(j(2pi/N)(k+1/8)) 98 | 99 | 100 N/4- point IFFT 101 | 102 | 103 Post-rotation by exp(j(2pi/N)(n+1/8)) 104 | 105 | 106 ------------- x(n) In the time domain 107 108 109 ------------------------------------------------------------------------------ 110 REQUIREMENTS 111 112 This function should provide a fixed point IMDCT with an average 113 quantization error less than 1 % (variance and mean). 114 115 ------------------------------------------------------------------------------ 116 REFERENCES 117 118 [1] Analysis/Synthesis Filter Bank design based on time domain 119 aliasing cancellation 120 Jhon Princen, et. al. 121 IEEE Transactions on ASSP, vol ASSP-34, No. 5 October 1986 122 Pg 1153 - 1161 123 124 [2] Regular FFT-related transform kernels for DCT/DST based 125 polyphase filterbanks 126 Rolf Gluth 127 Proc. ICASSP 1991, pg. 2205 - 2208 128 129 ------------------------------------------------------------------------------ 130 PSEUDO-CODE 131 132 Cx, Cy are complex number 133 134 135 exp = log2(n)-1 136 137 FOR ( k=0; k< n/2; k +=2) 138 139 Cx = - data_quant[k] + j data_quant[n/2-1 - k] 140 141 freq_2_time_buffer = Cx * exp(j(2pi/n)(k+1/8)) 142 143 ENDFOR 144 145 CALL IFFT( freq_2_time_buffer, n/4) 146 147 MODIFYING( freq_2_time_buffer ) 148 149 RETURNING( shift ) 150 151 FOR ( k=0; k< n/4; k +=2) 152 153 Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1] 154 155 Cy = Cx * exp(j(2pi/n)(k+1/8)) 156 157 data_quant[3n/4-1 - k ] = Real(Cy) 158 data_quant[ n/4-1 - k ] = - Imag(Cy) 159 data_quant[3n/4 + k ] = Real(Cy) 160 data_quant[ n/4 + k ] = Imag(Cy) 161 162 ENDFOR 163 164 FOR ( k=n/4; k< n/2; k +=2) 165 166 Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1] 167 168 Cy = Cx * exp(j(2pi/n)(k+1/8)) 169 170 data_quant[3n/4-1 - k ] = Real(Cy) 171 data_quant[ n/4 + k ] = - Real(Cy) 172 data_quant[5n/4 - k ] = Imag(Cy) 173 data_quant[ n/4 + k ] = Imag(Cy) 174 175 ENDFOR 176 177 MODIFIED data_quant[] 178 179 RETURN (exp - shift) 180 181 ------------------------------------------------------------------------------ 182 RESOURCES USED 183 When the code is written for a specific target processor the 184 the resources used should be documented below. 185 186 STACK USAGE: [stack count for this module] + [variable to represent 187 stack usage for each subroutine called] 188 189 where: [stack usage variable] = stack usage for [subroutine 190 name] (see [filename].ext) 191 192 DATA MEMORY USED: x words 193 194 PROGRAM MEMORY USED: x words 195 196 CLOCK CYCLES: [cycle count equation for this module] + [variable 197 used to represent cycle count for each subroutine 198 called] 199 200 where: [cycle count variable] = cycle count for [subroutine 201 name] (see [filename].ext) 202 203 ------------------------------------------------------------------------------ 204 */ 205 206 207 /*---------------------------------------------------------------------------- 208 ; INCLUDES 209 ----------------------------------------------------------------------------*/ 210 211 #include "pv_audio_type_defs.h" 212 #include "imdct_fxp.h" 213 214 215 #include "mix_radix_fft.h" 216 #include "digit_reversal_tables.h" 217 #include "fft_rx4.h" 218 #include "inv_short_complex_rot.h" 219 #include "inv_long_complex_rot.h" 220 #include "pv_normalize.h" 221 #include "fxp_mul32.h" 222 #include "aac_mem_funcs.h" 223 224 #include "window_block_fxp.h" 225 226 /*---------------------------------------------------------------------------- 227 ; MACROS 228 ; Define module specific macros here 229 ----------------------------------------------------------------------------*/ 230 231 /*---------------------------------------------------------------------------- 232 ; DEFINES 233 ; Include all pre-processor statements here. Include conditional 234 ; compile variables also. 235 ----------------------------------------------------------------------------*/ 236 #define ERROR_IN_FRAME_SIZE 10 237 238 /*---------------------------------------------------------------------------- 239 ; LOCAL FUNCTION DEFINITIONS 240 ; Function Prototype declaration 241 ----------------------------------------------------------------------------*/ 242 243 /*---------------------------------------------------------------------------- 244 ; LOCAL VARIABLE DEFINITIONS 245 ; Variable declaration - defined here and used outside this module 246 ----------------------------------------------------------------------------*/ 247 248 /*---------------------------------------------------------------------------- 249 ; EXTERNAL FUNCTION REFERENCES 250 ; Declare functions defined elsewhere and referenced in this module 251 ----------------------------------------------------------------------------*/ 252 253 /*---------------------------------------------------------------------------- 254 ; EXTERNAL VARIABLES REFERENCES 255 ; Declare variables used in this module but defined elsewhere 256 ----------------------------------------------------------------------------*/ 257 258 259 /*---------------------------------------------------------------------------- 260 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 261 ; Declare variables used in this module but defined elsewhere 262 ----------------------------------------------------------------------------*/ 263 264 /*---------------------------------------------------------------------------- 265 ; FUNCTION CODE 266 ----------------------------------------------------------------------------*/ 267 268 269 Int imdct_fxp(Int32 data_quant[], 270 Int32 freq_2_time_buffer[], 271 const Int n, 272 Int Q_format, 273 Int32 max) 274 { 275 276 Int32 exp_jw; 277 Int shift = 0; 278 279 const Int32 *p_rotate; 280 const Int32 *p_rotate_2; 281 282 Int32 *p_data_1; 283 Int32 *p_data_2; 284 285 Int32 temp_re32; 286 Int32 temp_im32; 287 288 Int shift1 = 0; 289 Int32 temp1; 290 Int32 temp2; 291 292 Int k; 293 Int n_2 = n >> 1; 294 Int n_4 = n >> 2; 295 296 297 298 if (max != 0) 299 { 300 301 switch (n) 302 { 303 case SHORT_WINDOW_TYPE: 304 p_rotate = exp_rotation_N_256; 305 shift = 21; /* log2(n)-1 + 14 acomodates 2/N factor */ 306 break; 307 308 case LONG_WINDOW_TYPE: 309 p_rotate = exp_rotation_N_2048; 310 shift = 24; /* log2(n)-1 +14 acomodates 2/N factor */ 311 break; 312 313 default: 314 /* 315 * There is no defined behavior for a non supported frame 316 * size. By returning a fixed scaling factor, the input will 317 * scaled down and the will be heard as a low level noise 318 */ 319 return(ERROR_IN_FRAME_SIZE); 320 321 } 322 323 /* 324 * p_data_1 p_data_2 325 * | | 326 * RIRIRIRIRIRIRIRIRIRIRIRIRIRIRI....RIRIRIRIRIRI 327 * | | 328 * 329 */ 330 331 p_data_1 = data_quant; /* uses first half of buffer */ 332 p_data_2 = &data_quant[n_2 - 1]; /* uses second half of buffer */ 333 334 p_rotate_2 = &p_rotate[n_4-1]; 335 336 shift1 = pv_normalize(max) - 1; /* -1 to leave room for addition */ 337 Q_format -= (16 - shift1); 338 max = 0; 339 340 341 if (shift1 >= 0) 342 { 343 temp_re32 = *(p_data_1++) << shift1; 344 temp_im32 = *(p_data_2--) << shift1; 345 346 for (k = n_4 >> 1; k != 0; k--) 347 { 348 /* 349 * Real and Imag parts have been swaped to use FFT as IFFT 350 */ 351 /* 352 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) 353 */ 354 exp_jw = *p_rotate++; 355 356 temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); 357 temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); 358 359 temp_im32 = *(p_data_1--) << shift1; 360 temp_re32 = *(p_data_2--) << shift1; 361 *(p_data_1++) = temp1; 362 *(p_data_1++) = temp2; 363 max |= (temp1 >> 31) ^ temp1; 364 max |= (temp2 >> 31) ^ temp2; 365 366 367 /* 368 * Real and Imag parts have been swaped to use FFT as IFFT 369 */ 370 371 /* 372 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) 373 */ 374 375 exp_jw = *p_rotate_2--; 376 377 temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); 378 temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); 379 380 381 temp_re32 = *(p_data_1++) << shift1; 382 temp_im32 = *(p_data_2--) << shift1; 383 384 *(p_data_2 + 2) = temp1; 385 *(p_data_2 + 3) = temp2; 386 max |= (temp1 >> 31) ^ temp1; 387 max |= (temp2 >> 31) ^ temp2; 388 389 } 390 } 391 else 392 { 393 temp_re32 = *(p_data_1++) >> 1; 394 temp_im32 = *(p_data_2--) >> 1; 395 396 for (k = n_4 >> 1; k != 0; k--) 397 { 398 /* 399 * Real and Imag parts have been swaped to use FFT as IFFT 400 */ 401 /* 402 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) 403 */ 404 exp_jw = *p_rotate++; 405 406 temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); 407 temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); 408 409 temp_im32 = *(p_data_1--) >> 1; 410 temp_re32 = *(p_data_2--) >> 1; 411 *(p_data_1++) = temp1; 412 *(p_data_1++) = temp2; 413 414 max |= (temp1 >> 31) ^ temp1; 415 max |= (temp2 >> 31) ^ temp2; 416 417 418 /* 419 * Real and Imag parts have been swaped to use FFT as IFFT 420 */ 421 422 /* 423 * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) 424 */ 425 exp_jw = *p_rotate_2--; 426 427 temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); 428 temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); 429 430 temp_re32 = *(p_data_1++) >> 1; 431 temp_im32 = *(p_data_2--) >> 1; 432 433 *(p_data_2 + 3) = temp2; 434 *(p_data_2 + 2) = temp1; 435 436 max |= (temp1 >> 31) ^ temp1; 437 max |= (temp2 >> 31) ^ temp2; 438 439 } 440 } 441 442 443 if (n != SHORT_WINDOW_TYPE) 444 { 445 446 shift -= mix_radix_fft(data_quant, 447 &max); 448 449 shift -= inv_long_complex_rot(data_quant, 450 max); 451 452 } 453 else /* n_4 is 64 */ 454 { 455 456 shift -= fft_rx4_short(data_quant, &max); 457 458 459 shift -= inv_short_complex_rot(data_quant, 460 freq_2_time_buffer, 461 max); 462 463 pv_memcpy(data_quant, 464 freq_2_time_buffer, 465 SHORT_WINDOW*sizeof(*data_quant)); 466 } 467 468 } 469 else 470 { 471 Q_format = ALL_ZEROS_BUFFER; 472 } 473 474 return(shift + Q_format); 475 476 } /* imdct_fxp */ 477