1 2 /* ----------------------------------------------------------------------------------------------------------- 3 Software License for The Fraunhofer FDK AAC Codec Library for Android 4 5 Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V. 6 All rights reserved. 7 8 1. INTRODUCTION 9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements 10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. 11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices. 12 13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual 14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by 15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part 16 of the MPEG specifications. 17 18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) 19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners 20 individually for the purpose of encoding or decoding bit streams in products that are compliant with 21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license 22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec 23 software may already be covered under those patent licenses when it is used for those licensed purposes only. 24 25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, 26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional 27 applications information and documentation. 28 29 2. COPYRIGHT LICENSE 30 31 Redistribution and use in source and binary forms, with or without modification, are permitted without 32 payment of copyright license fees provided that you satisfy the following conditions: 33 34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or 35 your modifications thereto in source code form. 36 37 You must retain the complete text of this software license in the documentation and/or other materials 38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. 39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your 40 modifications thereto to recipients of copies in binary form. 41 42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without 43 prior written permission. 44 45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec 46 software or your modifications thereto. 47 48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software 49 and the date of any change. For modified versions of the FDK AAC Codec, the term 50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term 51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." 52 53 3. NO PATENT LICENSE 54 55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, 56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with 57 respect to this software. 58 59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized 60 by appropriate patent licenses. 61 62 4. DISCLAIMER 63 64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors 65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties 66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, 68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits, 69 or business interruption, however caused and on any theory of liability, whether in contract, strict 70 liability, or tort (including negligence), arising in any way out of the use of this software, even if 71 advised of the possibility of such damage. 72 73 5. CONTACT INFORMATION 74 75 Fraunhofer Institute for Integrated Circuits IIS 76 Attention: Audio and Multimedia Departments - FDK AAC LL 77 Am Wolfsmantel 33 78 91058 Erlangen, Germany 79 80 www.iis.fraunhofer.de/amm 81 amm-info (at) iis.fraunhofer.de 82 ----------------------------------------------------------------------------------------------------------- */ 83 84 #if (QMF_NO_POLY==5) 85 86 #define FUNCTION_qmfForwardModulationLP_odd 87 88 #ifdef FUNCTION_qmfForwardModulationLP_odd 89 static void 90 qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 91 const FIXP_QMF *timeIn, /*!< Time Signal */ 92 FIXP_QMF *rSubband ) /*!< Real Output */ 93 { 94 int i; 95 int L = anaQmf->no_channels; 96 int M = L>>1; 97 int shift = (anaQmf->no_channels>>6) + 1; 98 int rSubband_e = 0; 99 100 FIXP_QMF *rSubbandPtr0 = &rSubband[M+0]; /* runs with increment */ 101 FIXP_QMF *rSubbandPtr1 = &rSubband[M-1]; /* runs with decrement */ 102 FIXP_QMF *timeIn0 = (FIXP_DBL *) &timeIn[0]; /* runs with increment */ 103 FIXP_QMF *timeIn1 = (FIXP_DBL *) &timeIn[L]; /* runs with increment */ 104 FIXP_QMF *timeIn2 = (FIXP_DBL *) &timeIn[L-1]; /* runs with decrement */ 105 FIXP_QMF *timeIn3 = (FIXP_DBL *) &timeIn[2*L-1]; /* runs with decrement */ 106 107 for (i = 0; i < M; i++) 108 { 109 *rSubbandPtr0++ = (*timeIn2-- >> 1) - (*timeIn0++ >> shift); 110 *rSubbandPtr1-- = (*timeIn1++ >> 1) + (*timeIn3-- >> shift); 111 } 112 113 dct_IV(rSubband,L, &rSubband_e); 114 } 115 #endif /* FUNCTION_qmfForwardModulationLP_odd */ 116 117 118 /* NEON optimized QMF currently builts only with RVCT toolchain */ 119 120 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_5TE__) 121 122 #if (SAMPLE_BITS == 16) 123 #define FUNCTION_qmfAnaPrototypeFirSlot 124 #endif 125 126 #ifdef FUNCTION_qmfAnaPrototypeFirSlot 127 128 #if defined(__GNUC__) /* cppp replaced: elif */ 129 130 inline INT SMULBB (const SHORT a, const LONG b) 131 { 132 INT result ; 133 __asm__ ("smulbb %0, %1, %2" 134 : "=r" (result) 135 : "r" (a), "r" (b)) ; 136 return result ; 137 } 138 inline INT SMULBT (const SHORT a, const LONG b) 139 { 140 INT result ; 141 __asm__ ("smulbt %0, %1, %2" 142 : "=r" (result) 143 : "r" (a), "r" (b)) ; 144 return result ; 145 } 146 147 inline INT SMLABB(const LONG accu, const SHORT a, const LONG b) 148 { 149 INT result ; 150 __asm__ ("smlabb %0, %1, %2,%3" 151 : "=r" (result) 152 : "r" (a), "r" (b), "r" (accu)) ; 153 return result; 154 } 155 inline INT SMLABT(const LONG accu, const SHORT a, const LONG b) 156 { 157 INT result ; 158 __asm__ ("smlabt %0, %1, %2,%3" 159 : "=r" (result) 160 : "r" (a), "r" (b), "r" (accu)) ; 161 return result; 162 } 163 #endif /* compiler selection */ 164 165 166 void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer, 167 int no_channels, /*!< Number channels of analysis filter */ 168 const FIXP_PFT *p_filter, 169 int p_stride, /*!< Stide of analysis filter */ 170 FIXP_QAS *RESTRICT pFilterStates 171 ) 172 { 173 LONG *p_flt = (LONG *) p_filter; 174 LONG flt; 175 FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1; 176 FIXP_QMF *RESTRICT pData_1 = analysisBuffer; 177 178 FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; 179 FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1; 180 181 FIXP_DBL accu0, accu1; 182 FIXP_QAS sta0, sta1; 183 184 int staStep1 = no_channels<<1; 185 int staStep2 = (no_channels<<3) - 1; /* Rewind one less */ 186 187 if (p_stride == 1) 188 { 189 /* FIR filter 0 */ 190 flt = *p_flt++; 191 sta1 = *sta_1; sta_1 -= staStep1; 192 accu1 = SMULBB( sta1, flt); 193 sta1 = *sta_1; sta_1 -= staStep1; 194 accu1 = SMLABT( accu1, sta1, flt); 195 196 flt = *p_flt++; 197 sta1 = *sta_1; sta_1 -= staStep1; 198 accu1 = SMLABB( accu1, sta1, flt); 199 sta1 = *sta_1; sta_1 -= staStep1; 200 accu1 = SMLABT( accu1, sta1, flt); 201 202 flt = *p_flt++; 203 sta1 = *sta_1; sta_1 += staStep2; 204 accu1 = SMLABB( accu1, sta1, flt); 205 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 206 207 /* FIR filters 1..63 127..65 or 1..31 63..33 */ 208 no_channels >>= 1; 209 for (; --no_channels; ) 210 { 211 sta0 = *sta_0; sta_0 += staStep1; /* 1,3,5, ... 29/61 */ 212 sta1 = *sta_1; sta_1 -= staStep1; 213 accu0 = SMULBT( sta0, flt); 214 accu1 = SMULBT( sta1, flt); 215 216 flt = *p_flt++; 217 sta0 = *sta_0; sta_0 += staStep1; 218 sta1 = *sta_1; sta_1 -= staStep1; 219 accu0 = SMLABB( accu0, sta0, flt); 220 accu1 = SMLABB( accu1, sta1, flt); 221 222 sta0 = *sta_0; sta_0 += staStep1; 223 sta1 = *sta_1; sta_1 -= staStep1; 224 accu0 = SMLABT( accu0, sta0, flt); 225 accu1 = SMLABT( accu1, sta1, flt); 226 227 flt = *p_flt++; 228 sta0 = *sta_0; sta_0 += staStep1; 229 sta1 = *sta_1; sta_1 -= staStep1; 230 accu0 = SMLABB( accu0, sta0, flt); 231 accu1 = SMLABB( accu1, sta1, flt); 232 233 sta0 = *sta_0; sta_0 -= staStep2; 234 sta1 = *sta_1; sta_1 += staStep2; 235 accu0 = SMLABT( accu0, sta0, flt); 236 accu1 = SMLABT( accu1, sta1, flt); 237 238 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 239 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 240 241 /* Same sequence as above, but mix B=bottom with T=Top */ 242 243 flt = *p_flt++; 244 sta0 = *sta_0; sta_0 += staStep1; /* 2,4,6, ... 30/62 */ 245 sta1 = *sta_1; sta_1 -= staStep1; 246 accu0 = SMULBB( sta0, flt); 247 accu1 = SMULBB( sta1, flt); 248 249 sta0 = *sta_0; sta_0 += staStep1; 250 sta1 = *sta_1; sta_1 -= staStep1; 251 accu0 = SMLABT( accu0, sta0, flt); 252 accu1 = SMLABT( accu1, sta1, flt); 253 254 flt = *p_flt++; 255 sta0 = *sta_0; sta_0 += staStep1; 256 sta1 = *sta_1; sta_1 -= staStep1; 257 accu0 = SMLABB( accu0, sta0, flt); 258 accu1 = SMLABB( accu1, sta1, flt); 259 260 sta0 = *sta_0; sta_0 += staStep1; 261 sta1 = *sta_1; sta_1 -= staStep1; 262 accu0 = SMLABT( accu0, sta0, flt); 263 accu1 = SMLABT( accu1, sta1, flt); 264 265 flt = *p_flt++; 266 sta0 = *sta_0; sta_0 -= staStep2; 267 sta1 = *sta_1; sta_1 += staStep2; 268 accu0 = SMLABB( accu0, sta0, flt); 269 accu1 = SMLABB( accu1, sta1, flt); 270 271 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 272 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 273 } 274 275 /* FIR filter 31/63 and 33/65 */ 276 sta0 = *sta_0; sta_0 += staStep1; 277 sta1 = *sta_1; sta_1 -= staStep1; 278 accu0 = SMULBT( sta0, flt); 279 accu1 = SMULBT( sta1, flt); 280 281 flt = *p_flt++; 282 sta0 = *sta_0; sta_0 += staStep1; 283 sta1 = *sta_1; sta_1 -= staStep1; 284 accu0 = SMLABB( accu0, sta0, flt); 285 accu1 = SMLABB( accu1, sta1, flt); 286 287 sta0 = *sta_0; sta_0 += staStep1; 288 sta1 = *sta_1; sta_1 -= staStep1; 289 accu0 = SMLABT( accu0, sta0, flt); 290 accu1 = SMLABT( accu1, sta1, flt); 291 292 flt = *p_flt++; 293 sta0 = *sta_0; sta_0 += staStep1; 294 sta1 = *sta_1; sta_1 -= staStep1; 295 accu0 = SMLABB( accu0, sta0, flt); 296 accu1 = SMLABB( accu1, sta1, flt); 297 298 sta0 = *sta_0; sta_0 -= staStep2; 299 sta1 = *sta_1; sta_1 += staStep2; 300 accu0 = SMLABT( accu0, sta0, flt); 301 accu1 = SMLABT( accu1, sta1, flt); 302 303 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 304 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 305 306 /* FIR filter 32/64 */ 307 flt = *p_flt++; 308 sta0 = *sta_0; sta_0 += staStep1; 309 sta1 = *sta_1; sta_1 -= staStep1; 310 accu0 = SMULBB( sta0, flt); 311 accu1 = SMULBB( sta1, flt); 312 313 sta0 = *sta_0; sta_0 += staStep1; 314 sta1 = *sta_1; sta_1 -= staStep1; 315 accu0 = SMLABT( accu0, sta0, flt); 316 accu1 = SMLABT( accu1, sta1, flt); 317 318 flt = *p_flt++; 319 sta0 = *sta_0; sta_0 += staStep1; 320 sta1 = *sta_1; sta_1 -= staStep1; 321 accu0 = SMLABB( accu0, sta0, flt); 322 accu1 = SMLABB( accu1, sta1, flt); 323 324 sta0 = *sta_0; sta_0 += staStep1; 325 sta1 = *sta_1; sta_1 -= staStep1; 326 accu0 = SMLABT( accu0, sta0, flt); 327 accu1 = SMLABT( accu1, sta1, flt); 328 329 flt = *p_flt; 330 sta0 = *sta_0; 331 sta1 = *sta_1; 332 accu0 = SMLABB( accu0, sta0, flt); 333 accu1 = SMLABB( accu1, sta1, flt); 334 335 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 336 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 337 } 338 else 339 { 340 int pfltStep = QMF_NO_POLY * (p_stride-1); 341 342 flt = p_flt[0]; 343 sta1 = *sta_1; sta_1 -= staStep1; 344 accu1 = SMULBB( sta1, flt); 345 sta1 = *sta_1; sta_1 -= staStep1; 346 accu1 = SMLABT( accu1, sta1, flt); 347 348 flt = p_flt[1]; 349 sta1 = *sta_1; sta_1 -= staStep1; 350 accu1 = SMLABB( accu1, sta1, flt); 351 sta1 = *sta_1; sta_1 -= staStep1; 352 accu1 = SMLABT( accu1, sta1, flt); 353 354 flt = p_flt[2]; p_flt += pfltStep; 355 sta1 = *sta_1; sta_1 += staStep2; 356 accu1 = SMLABB( accu1, sta1, flt); 357 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 358 359 /* FIR filters 1..63 127..65 or 1..31 63..33 */ 360 for (; --no_channels; ) 361 { 362 flt = p_flt[0]; 363 sta0 = *sta_0; sta_0 += staStep1; 364 sta1 = *sta_1; sta_1 -= staStep1; 365 accu0 = SMULBB( sta0, flt); 366 accu1 = SMULBB( sta1, flt); 367 368 sta0 = *sta_0; sta_0 += staStep1; 369 sta1 = *sta_1; sta_1 -= staStep1; 370 accu0 = SMLABT( accu0, sta0, flt); 371 accu1 = SMLABT( accu1, sta1, flt); 372 373 flt = p_flt[1]; 374 sta0 = *sta_0; sta_0 += staStep1; 375 sta1 = *sta_1; sta_1 -= staStep1; 376 accu0 = SMLABB( accu0, sta0, flt); 377 accu1 = SMLABB( accu1, sta1, flt); 378 379 sta0 = *sta_0; sta_0 += staStep1; 380 sta1 = *sta_1; sta_1 -= staStep1; 381 accu0 = SMLABT( accu0, sta0, flt); 382 accu1 = SMLABT( accu1, sta1, flt); 383 384 flt = p_flt[2]; p_flt += pfltStep; 385 sta0 = *sta_0; sta_0 -= staStep2; 386 sta1 = *sta_1; sta_1 += staStep2; 387 accu0 = SMLABB( accu0, sta0, flt); 388 accu1 = SMLABB( accu1, sta1, flt); 389 390 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 391 *pData_1++ = FX_DBL2FX_QMF(accu1<<1); 392 } 393 394 /* FIR filter 32/64 */ 395 flt = p_flt[0]; 396 sta0 = *sta_0; sta_0 += staStep1; 397 accu0 = SMULBB( sta0, flt); 398 sta0 = *sta_0; sta_0 += staStep1; 399 accu0 = SMLABT( accu0, sta0, flt); 400 401 flt = p_flt[1]; 402 sta0 = *sta_0; sta_0 += staStep1; 403 accu0 = SMLABB( accu0, sta0, flt); 404 sta0 = *sta_0; sta_0 += staStep1; 405 accu0 = SMLABT( accu0, sta0, flt); 406 407 flt = p_flt[2]; 408 sta0 = *sta_0; 409 accu0 = SMLABB( accu0, sta0, flt); 410 *pData_0-- = FX_DBL2FX_QMF(accu0<<1); 411 } 412 } 413 #endif /* FUNCTION_qmfAnaPrototypeFirSlot */ 414 #endif /* #if defined(__CC_ARM) && defined(__ARM_ARCH_6__) */ 415 416 #if ( defined(__ARM_ARCH_5TE__) && (SAMPLE_BITS == 16) ) && !defined(QMF_TABLE_FULL) 417 418 #define FUNCTION_qmfSynPrototypeFirSlot 419 420 #if defined(FUNCTION_qmfSynPrototypeFirSlot) 421 422 #if defined(__GNUC__) /* cppp replaced: elif */ 423 424 inline INT SMULWB (const LONG a, const LONG b) 425 { 426 INT result ; 427 __asm__ ("smulwb %0, %1, %2" 428 : "=r" (result) 429 : "r" (a), "r" (b)) ; 430 431 return result ; 432 } 433 inline INT SMULWT (const LONG a, const LONG b) 434 { 435 INT result ; 436 __asm__ ("smulwt %0, %1, %2" 437 : "=r" (result) 438 : "r" (a), "r" (b)) ; 439 440 return result ; 441 } 442 443 inline INT SMLAWB(const LONG accu, const LONG a, const LONG b) 444 { 445 INT result; 446 asm("smlawb %0, %1, %2, %3 " 447 : "=r" (result) 448 : "r" (a), "r" (b), "r" (accu) ); 449 return result ; 450 } 451 452 inline INT SMLAWT(const LONG accu, const LONG a, const LONG b) 453 { 454 INT result; 455 asm("smlawt %0, %1, %2, %3 " 456 : "=r" (result) 457 : "r" (a), "r" (b), "r" (accu) ); 458 return result ; 459 } 460 461 #endif /* ARM compiler selector */ 462 463 464 static void qmfSynPrototypeFirSlot1_filter(FIXP_QMF *RESTRICT realSlot, 465 FIXP_QMF *RESTRICT imagSlot, 466 const FIXP_DBL *RESTRICT p_flt, 467 FIXP_QSS *RESTRICT sta, 468 FIXP_DBL *pMyTimeOut, 469 int no_channels) 470 { 471 /* This code was the base for the above listed assembler sequence */ 472 /* It can be used for debugging purpose or further optimizations */ 473 const FIXP_DBL *RESTRICT p_fltm = p_flt + 155; 474 475 do 476 { 477 FIXP_DBL result; 478 FIXP_DBL A, B, real, imag, sta0; 479 480 real = *--realSlot; 481 imag = *--imagSlot; 482 B = p_flt[4]; /* Bottom=[8] Top=[9] */ 483 A = p_fltm[3]; /* Bottom=[316] Top=[317] */ 484 sta0 = sta[0]; /* save state[0] */ 485 *sta++ = SMLAWT( sta[1], imag, B ); /* index=9...........319 */ 486 *sta++ = SMLAWB( sta[1], real, A ); /* index=316...........6 */ 487 *sta++ = SMLAWB( sta[1], imag, B ); /* index=8,18, ...318 */ 488 B = p_flt[3]; /* Bottom=[6] Top=[7] */ 489 *sta++ = SMLAWT( sta[1], real, A ); /* index=317...........7 */ 490 A = p_fltm[4]; /* Bottom=[318] Top=[319] */ 491 *sta++ = SMLAWT( sta[1], imag, B ); /* index=7...........317 */ 492 *sta++ = SMLAWB( sta[1], real, A ); /* index=318...........8 */ 493 *sta++ = SMLAWB( sta[1], imag, B ); /* index=6...........316 */ 494 B = p_flt[2]; /* Bottom=[X] Top=[5] */ 495 *sta++ = SMLAWT( sta[1], real, A ); /* index=9...........319 */ 496 A = p_fltm[2]; /* Bottom=[X] Top=[315] */ 497 *sta++ = SMULWT( imag, B ); /* index=5,15, ... 315 */ 498 result = SMLAWT( sta0, real, A ); /* index=315...........5 */ 499 500 *pMyTimeOut++ = result; 501 502 real = *--realSlot; 503 imag = *--imagSlot; 504 A = p_fltm[0]; /* Bottom=[310] Top=[311] */ 505 B = p_flt[7]; /* Bottom=[14] Top=[15] */ 506 result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ 507 *sta++ = SMLAWB( sta[1], imag, B ); /* index=14..........324 */ 508 *pMyTimeOut++ = result; 509 B = p_flt[6]; /* Bottom=[12] Top=[13] */ 510 *sta++ = SMLAWT( sta[1], real, A ); /* index=311...........1 */ 511 A = p_fltm[1]; /* Bottom=[312] Top=[313] */ 512 *sta++ = SMLAWT( sta[1], imag, B ); /* index=13..........323 */ 513 *sta++ = SMLAWB( sta[1], real, A ); /* index=312...........2 */ 514 *sta++ = SMLAWB( sta[1], imag, B ); /* index=12..........322 */ 515 *sta++ = SMLAWT( sta[1], real, A ); /* index=313...........3 */ 516 A = p_fltm[2]; /* Bottom=[314] Top=[315] */ 517 B = p_flt[5]; /* Bottom=[10] Top=[11] */ 518 *sta++ = SMLAWT( sta[1], imag, B ); /* index=11..........321 */ 519 *sta++ = SMLAWB( sta[1], real, A ); /* index=314...........4 */ 520 *sta++ = SMULWB( imag, B ); /* index=10..........320 */ 521 522 523 p_flt += 5; 524 p_fltm -= 5; 525 } 526 while ((--no_channels) != 0); 527 528 } 529 530 531 532 INT qmfSynPrototypeFirSlot2( 533 HANDLE_QMF_FILTER_BANK qmf, 534 FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ 535 FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ 536 INT_PCM *RESTRICT timeOut, /*!< Time domain data */ 537 INT stride /*!< Time output buffer stride factor*/ 538 ) 539 { 540 FIXP_QSS *RESTRICT sta = (FIXP_QSS*)qmf->FilterStates; 541 int no_channels = qmf->no_channels; 542 int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); 543 544 /* We map an arry of 16-bit values upon an array of 2*16-bit values to read 2 values in one shot */ 545 const FIXP_DBL *RESTRICT p_flt = (FIXP_DBL *) qmf->p_filter; /* low=[0], high=[1] */ 546 const FIXP_DBL *RESTRICT p_fltm = (FIXP_DBL *) qmf->p_filter + 155; /* low=[310], high=[311] */ 547 548 FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); 549 FDK_ASSERT(qmf->p_stride==2 && qmf->no_channels == 32); 550 551 FDK_ASSERT((no_channels&3) == 0); /* should be a multiple of 4 */ 552 553 realSlot += no_channels-1; // ~~"~~ 554 imagSlot += no_channels-1; // no_channels-1 .. 0 555 556 FIXP_DBL MyTimeOut[32]; 557 FIXP_DBL *pMyTimeOut = &MyTimeOut[0]; 558 559 for (no_channels = no_channels; no_channels--;) 560 { 561 FIXP_DBL result; 562 FIXP_DBL A, B, real, imag; 563 564 real = *realSlot--; 565 imag = *imagSlot--; 566 A = p_fltm[0]; /* Bottom=[310] Top=[311] */ 567 B = p_flt[7]; /* Bottom=[14] Top=[15] */ 568 result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ 569 *sta++ = SMLAWB( sta[1], imag, B ); /* index=14..........324 */ 570 B = p_flt[6]; /* Bottom=[12] Top=[13] */ 571 *sta++ = SMLAWT( sta[1], real, A ); /* index=311...........1 */ 572 A = p_fltm[1]; /* Bottom=[312] Top=[313] */ 573 *sta++ = SMLAWT( sta[1], imag, B ); /* index=13..........323 */ 574 *sta++ = SMLAWB( sta[1], real, A ); /* index=312...........2 */ 575 *sta++ = SMLAWB( sta[1], imag, B ); /* index=12..........322 */ 576 *sta++ = SMLAWT( sta[1], real, A ); /* index=313...........3 */ 577 A = p_fltm[2]; /* Bottom=[314] Top=[315] */ 578 B = p_flt[5]; /* Bottom=[10] Top=[11] */ 579 *sta++ = SMLAWT( sta[1], imag, B ); /* index=11..........321 */ 580 *sta++ = SMLAWB( sta[1], real, A ); /* index=314...........4 */ 581 *sta++ = SMULWB( imag, B ); /* index=10..........320 */ 582 583 *pMyTimeOut++ = result; 584 585 p_fltm -= 5; 586 p_flt += 5; 587 } 588 589 pMyTimeOut = &MyTimeOut[0]; 590 #if (SAMPLE_BITS == 16) 591 const FIXP_DBL max_pos = (FIXP_DBL) 0x00007FFF << scale; 592 const FIXP_DBL max_neg = (FIXP_DBL) 0xFFFF8001 << scale; 593 #else 594 scale = -scale; 595 const FIXP_DBL max_pos = (FIXP_DBL) 0x7FFFFFFF >> scale; 596 const FIXP_DBL max_neg = (FIXP_DBL) 0x80000001 >> scale; 597 #endif 598 const FIXP_DBL add_neg = (1 << scale) - 1; 599 600 no_channels = qmf->no_channels; 601 602 timeOut += no_channels*stride; 603 604 FDK_ASSERT(scale >= 0); 605 606 if (qmf->outGain != 0x80000000) 607 { 608 FIXP_DBL gain = qmf->outGain; 609 for (no_channels>>=2; no_channels--;) 610 { 611 FIXP_DBL result1, result2; 612 613 result1 = *pMyTimeOut++; 614 result2 = *pMyTimeOut++; 615 616 result1 = fMult(result1,gain); 617 timeOut -= stride; 618 if (result1 < 0) result1 += add_neg; 619 if (result1 < max_neg) result1 = max_neg; 620 if (result1 > max_pos) result1 = max_pos; 621 #if (SAMPLE_BITS == 16) 622 timeOut[0] = result1 >> scale; 623 #else 624 timeOut[0] = result1 << scale; 625 #endif 626 627 result2 = fMult(result2,gain); 628 timeOut -= stride; 629 if (result2 < 0) result2 += add_neg; 630 if (result2 < max_neg) result2 = max_neg; 631 if (result2 > max_pos) result2 = max_pos; 632 #if (SAMPLE_BITS == 16) 633 timeOut[0] = result2 >> scale; 634 #else 635 timeOut[0] = result2 << scale; 636 #endif 637 638 result1 = *pMyTimeOut++; 639 result2 = *pMyTimeOut++; 640 641 result1 = fMult(result1,gain); 642 timeOut -= stride; 643 if (result1 < 0) result1 += add_neg; 644 if (result1 < max_neg) result1 = max_neg; 645 if (result1 > max_pos) result1 = max_pos; 646 #if (SAMPLE_BITS == 16) 647 timeOut[0] = result1 >> scale; 648 #else 649 timeOut[0] = result1 << scale; 650 #endif 651 652 result2 = fMult(result2,gain); 653 timeOut -= stride; 654 if (result2 < 0) result2 += add_neg; 655 if (result2 < max_neg) result2 = max_neg; 656 if (result2 > max_pos) result2 = max_pos; 657 #if (SAMPLE_BITS == 16) 658 timeOut[0] = result2 >> scale; 659 #else 660 timeOut[0] = result2 << scale; 661 #endif 662 } 663 } 664 else 665 { 666 for (no_channels>>=2; no_channels--;) 667 { 668 FIXP_DBL result1, result2; 669 result1 = *pMyTimeOut++; 670 result2 = *pMyTimeOut++; 671 timeOut -= stride; 672 if (result1 < 0) result1 += add_neg; 673 if (result1 < max_neg) result1 = max_neg; 674 if (result1 > max_pos) result1 = max_pos; 675 #if (SAMPLE_BITS == 16) 676 timeOut[0] = result1 >> scale; 677 #else 678 timeOut[0] = result1 << scale; 679 #endif 680 681 timeOut -= stride; 682 if (result2 < 0) result2 += add_neg; 683 if (result2 < max_neg) result2 = max_neg; 684 if (result2 > max_pos) result2 = max_pos; 685 #if (SAMPLE_BITS == 16) 686 timeOut[0] = result2 >> scale; 687 #else 688 timeOut[0] = result2 << scale; 689 #endif 690 691 result1 = *pMyTimeOut++; 692 result2 = *pMyTimeOut++; 693 timeOut -= stride; 694 if (result1 < 0) result1 += add_neg; 695 if (result1 < max_neg) result1 = max_neg; 696 if (result1 > max_pos) result1 = max_pos; 697 #if (SAMPLE_BITS == 16) 698 timeOut[0] = result1 >> scale; 699 #else 700 timeOut[0] = result1 << scale; 701 #endif 702 703 timeOut -= stride; 704 if (result2 < 0) result2 += add_neg; 705 if (result2 < max_neg) result2 = max_neg; 706 if (result2 > max_pos) result2 = max_pos; 707 #if (SAMPLE_BITS == 16) 708 timeOut[0] = result2 >> scale; 709 #else 710 timeOut[0] = result2 << scale; 711 #endif 712 } 713 } 714 return 0; 715 } 716 717 static 718 void qmfSynPrototypeFirSlot_fallback( HANDLE_QMF_FILTER_BANK qmf, 719 FIXP_DBL *realSlot, /*!< Input: Pointer to real Slot */ 720 FIXP_DBL *imagSlot, /*!< Input: Pointer to imag Slot */ 721 INT_PCM *timeOut, /*!< Time domain data */ 722 const int stride 723 ); 724 725 /*! 726 \brief Perform Synthesis Prototype Filtering on a single slot of input data. 727 728 The filter takes 2 * #MAX_SYNTHESIS_CHANNELS of input data and 729 generates #MAX_SYNTHESIS_CHANNELS time domain output samples. 730 */ 731 732 static 733 void qmfSynPrototypeFirSlot( HANDLE_QMF_FILTER_BANK qmf, 734 FIXP_DBL *realSlot, /*!< Input: Pointer to real Slot */ 735 FIXP_DBL *imagSlot, /*!< Input: Pointer to imag Slot */ 736 INT_PCM *timeOut, /*!< Time domain data */ 737 const int stride 738 ) 739 { 740 INT err = -1; 741 742 switch (qmf->p_stride) { 743 case 2: 744 err = qmfSynPrototypeFirSlot2(qmf, realSlot, imagSlot, timeOut, stride); 745 break; 746 default: 747 err = -1; 748 } 749 750 /* fallback if configuration not available or failed */ 751 if(err!=0) { 752 qmfSynPrototypeFirSlot_fallback(qmf, realSlot, imagSlot, timeOut, stride); 753 } 754 } 755 #endif /* FUNCTION_qmfSynPrototypeFirSlot */ 756 757 #endif /* ( defined(__CC_ARM) && defined(__ARM_ARCH_5TE__) && (SAMPLE_BITS == 16) ) && !defined(QMF_TABLE_FULL) */ 758 759 760 761 /* #####################################################################################*/ 762 763 764 765 #endif /* (QMF_NO_POLY==5) */ 766 767