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 /*************************** Fraunhofer IIS FDK Tools ********************** 85 86 Author(s): Markus Lohwasser 87 Description: FDK Tools Hybrid Filterbank 88 89 ******************************************************************************/ 90 91 #include "FDK_hybrid.h" 92 93 94 #include "fft.h" 95 96 /*--------------- defines -----------------------------*/ 97 #define FFT_IDX_R(a) (2*a) 98 #define FFT_IDX_I(a) (2*a+1) 99 100 #define HYB_COEF8_0 ( 0.00746082949812f ) 101 #define HYB_COEF8_1 ( 0.02270420949825f ) 102 #define HYB_COEF8_2 ( 0.04546865930473f ) 103 #define HYB_COEF8_3 ( 0.07266113929591f ) 104 #define HYB_COEF8_4 ( 0.09885108575264f ) 105 #define HYB_COEF8_5 ( 0.11793710567217f ) 106 #define HYB_COEF8_6 ( 0.12500000000000f ) 107 #define HYB_COEF8_7 ( HYB_COEF8_5 ) 108 #define HYB_COEF8_8 ( HYB_COEF8_4 ) 109 #define HYB_COEF8_9 ( HYB_COEF8_3 ) 110 #define HYB_COEF8_10 ( HYB_COEF8_2 ) 111 #define HYB_COEF8_11 ( HYB_COEF8_1 ) 112 #define HYB_COEF8_12 ( HYB_COEF8_0 ) 113 114 115 /*--------------- structure definitions ---------------*/ 116 117 #if defined(ARCH_PREFER_MULT_32x16) 118 #define FIXP_HTB FIXP_SGL /* SGL data type. */ 119 #define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ 120 #define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ 121 #define FL2FXCONST_HTB FL2FXCONST_SGL 122 #else 123 #define FIXP_HTB FIXP_DBL /* SGL data type. */ 124 #define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ 125 #define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ 126 #define FL2FXCONST_HTB FL2FXCONST_DBL 127 #endif 128 129 #define HTCP(real,imag) { { HTC(real), HTC(imag) } } /* How to arrange the packed values. */ 130 131 132 struct FDK_HYBRID_SETUP 133 { 134 UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ 135 UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ 136 SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ 137 UCHAR protoLen; /*!< Prototype filter length. */ 138 UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ 139 const INT *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ 140 141 }; 142 143 /*--------------- constants ---------------------------*/ 144 static const INT ringbuffIdxTab[2*13] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; 145 146 static const FDK_HYBRID_SETUP setup_3_16 = { 3, { 8, 4, 4}, { 8, 4, 4}, 13, (13-1)/2, ringbuffIdxTab}; 147 static const FDK_HYBRID_SETUP setup_3_12 = { 3, { 8, 2, 2}, { 8, 2, 2}, 13, (13-1)/2, ringbuffIdxTab}; 148 static const FDK_HYBRID_SETUP setup_3_10 = { 3, { 6, 2, 2}, { -8, -2, 2}, 13, (13-1)/2, ringbuffIdxTab}; 149 150 151 static const FIXP_HTP HybFilterCoef8[] = { 152 HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), 153 HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), 154 HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), 155 HTCP(0x0df26407, 0x05c6e77e) 156 }; 157 158 static const FIXP_HTB HybFilterCoef2[13] = { 159 FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.30596630545168f), 160 FL2FXCONST_HTB( 0.50000000000000f), FL2FXCONST_HTB( 0.30596630545168f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), 161 FL2FXCONST_HTB( 0.00000000000000f) 162 }; 163 164 static const FIXP_HTB HybFilterCoef4[13] = { 165 FL2FXCONST_HTB(-0.00305151927305f), FL2FXCONST_HTB(-0.00794862316203f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.21227807049160f), 166 FL2FXCONST_HTB( 0.25f), FL2FXCONST_HTB( 0.21227807049160f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB(-0.00794862316203f), 167 FL2FXCONST_HTB(-0.00305151927305f) 168 }; 169 170 /*--------------- function declarations ---------------*/ 171 static INT kChannelFiltering( 172 const FIXP_DBL *const pQmfReal, 173 const FIXP_DBL *const pQmfImag, 174 const INT *const pReadIdx, 175 FIXP_DBL *const mHybridReal, 176 FIXP_DBL *const mHybridImag, 177 const SCHAR hybridConfig 178 ); 179 180 181 /*--------------- function definitions ----------------*/ 182 183 INT FDKhybridAnalysisOpen( 184 HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, 185 FIXP_DBL *const pLFmemory, 186 const UINT LFmemorySize, 187 FIXP_DBL *const pHFmemory, 188 const UINT HFmemorySize 189 ) 190 { 191 INT err = 0; 192 193 /* Save pointer to extern memory. */ 194 hAnalysisHybFilter->pLFmemory = pLFmemory; 195 hAnalysisHybFilter->LFmemorySize = LFmemorySize; 196 197 hAnalysisHybFilter->pHFmemory = pHFmemory; 198 hAnalysisHybFilter->HFmemorySize = HFmemorySize; 199 200 return err; 201 } 202 203 INT FDKhybridAnalysisInit( 204 HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, 205 const FDK_HYBRID_MODE mode, 206 const INT qmfBands, 207 const INT cplxBands, 208 const INT initStatesFlag 209 ) 210 { 211 int k; 212 INT err = 0; 213 FIXP_DBL *pMem = NULL; 214 HANDLE_FDK_HYBRID_SETUP setup = NULL; 215 216 switch (mode) { 217 case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; 218 case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; 219 case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; 220 default: err = -1; goto bail; 221 } 222 223 /* Initialize handle. */ 224 hAnalysisHybFilter->pSetup = setup; 225 hAnalysisHybFilter->bufferLFpos = setup->protoLen-1; 226 hAnalysisHybFilter->bufferHFpos = 0; 227 hAnalysisHybFilter->nrBands = qmfBands; 228 hAnalysisHybFilter->cplxBands = cplxBands; 229 hAnalysisHybFilter->hfMode = 0; 230 231 /* Check available memory. */ 232 if ( ((2*setup->nrQmfBands*setup->protoLen*sizeof(FIXP_DBL)) > hAnalysisHybFilter->LFmemorySize) 233 || ((setup->filterDelay*((qmfBands-setup->nrQmfBands)+(cplxBands-setup->nrQmfBands))*sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize) ) 234 { 235 err = -2; 236 goto bail; 237 } 238 239 /* Distribut LF memory. */ 240 pMem = hAnalysisHybFilter->pLFmemory; 241 for (k=0; k<setup->nrQmfBands; k++) { 242 hAnalysisHybFilter->bufferLFReal[k] = pMem; pMem += setup->protoLen; 243 hAnalysisHybFilter->bufferLFImag[k] = pMem; pMem += setup->protoLen; 244 } 245 246 /* Distribut HF memory. */ 247 pMem = hAnalysisHybFilter->pHFmemory; 248 for (k=0; k<setup->filterDelay; k++) { 249 hAnalysisHybFilter->bufferHFReal[k] = pMem; pMem += (qmfBands-setup->nrQmfBands); 250 hAnalysisHybFilter->bufferHFImag[k] = pMem; pMem += (cplxBands-setup->nrQmfBands); 251 } 252 253 if (initStatesFlag) { 254 /* Clear LF buffer */ 255 for (k=0; k<setup->nrQmfBands; k++) { 256 FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen*sizeof(FIXP_DBL)); 257 FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen*sizeof(FIXP_DBL)); 258 } 259 260 if (qmfBands > setup->nrQmfBands) { 261 /* Clear HF buffer */ 262 for (k=0; k<setup->filterDelay; k++) { 263 FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], (qmfBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); 264 FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], (cplxBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); 265 } 266 } 267 } 268 269 bail: 270 return err; 271 } 272 273 INT FDKhybridAnalysisScaleStates( 274 HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, 275 const INT scalingValue 276 ) 277 { 278 INT err = 0; 279 280 if (hAnalysisHybFilter==NULL) { 281 err = 1; /* invalid handle */ 282 } 283 else { 284 int k; 285 HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; 286 287 /* Scale LF buffer */ 288 for (k=0; k<setup->nrQmfBands; k++) { 289 scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, scalingValue); 290 scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, scalingValue); 291 } 292 if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { 293 /* Scale HF buffer */ 294 for (k=0; k<setup->filterDelay; k++) { 295 scaleValues(hAnalysisHybFilter->bufferHFReal[k], (hAnalysisHybFilter->nrBands-setup->nrQmfBands), scalingValue); 296 scaleValues(hAnalysisHybFilter->bufferHFImag[k], (hAnalysisHybFilter->cplxBands-setup->nrQmfBands), scalingValue); 297 } 298 } 299 } 300 return err; 301 } 302 303 INT FDKhybridAnalysisApply( 304 HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, 305 const FIXP_DBL *const pQmfReal, 306 const FIXP_DBL *const pQmfImag, 307 FIXP_DBL *const pHybridReal, 308 FIXP_DBL *const pHybridImag) 309 { 310 int k, hybOffset = 0; 311 INT err = 0; 312 const int nrQmfBandsLF = hAnalysisHybFilter->pSetup->nrQmfBands; /* number of QMF bands to be converted to hybrid */ 313 314 const int writIndex = hAnalysisHybFilter->bufferLFpos; 315 int readIndex = hAnalysisHybFilter->bufferLFpos; 316 317 if (++readIndex>=hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; 318 const INT* pBufferLFreadIdx = &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; 319 320 /* 321 * LF buffer. 322 */ 323 for (k=0; k<nrQmfBandsLF; k++) { 324 /* New input sample. */ 325 hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k]; 326 hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; 327 328 /* Perform hybrid filtering. */ 329 kChannelFiltering( 330 hAnalysisHybFilter->bufferLFReal[k], 331 hAnalysisHybFilter->bufferLFImag[k], 332 pBufferLFreadIdx, 333 pHybridReal+hybOffset, 334 pHybridImag+hybOffset, 335 hAnalysisHybFilter->pSetup->kHybrid[k]); 336 337 hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; 338 } 339 340 hAnalysisHybFilter->bufferLFpos = readIndex; /* Index where to write next input sample. */ 341 342 if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { 343 /* 344 * HF buffer. 345 */ 346 if (hAnalysisHybFilter->hfMode!=0) { 347 /* HF delay compensation was applied outside. */ 348 FDKmemcpy(pHybridReal+hybOffset, &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 349 FDKmemcpy(pHybridImag+hybOffset, &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 350 } 351 else { 352 /* HF delay compensation, filterlength/2. */ 353 FDKmemcpy(pHybridReal+hybOffset, hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 354 FDKmemcpy(pHybridImag+hybOffset, hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 355 356 FDKmemcpy(hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 357 FDKmemcpy(hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 358 359 if (++hAnalysisHybFilter->bufferHFpos>=hAnalysisHybFilter->pSetup->filterDelay) hAnalysisHybFilter->bufferHFpos = 0; 360 } 361 } /* process HF part*/ 362 363 return err; 364 } 365 366 INT FDKhybridAnalysisClose( 367 HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter 368 ) 369 { 370 INT err = 0; 371 372 if (hAnalysisHybFilter != NULL) { 373 hAnalysisHybFilter->pLFmemory = NULL; 374 hAnalysisHybFilter->pHFmemory = NULL; 375 hAnalysisHybFilter->LFmemorySize = 0; 376 hAnalysisHybFilter->HFmemorySize = 0; 377 } 378 379 return err; 380 } 381 382 INT FDKhybridSynthesisInit( 383 HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, 384 const FDK_HYBRID_MODE mode, 385 const INT qmfBands, 386 const INT cplxBands 387 ) 388 { 389 INT err = 0; 390 HANDLE_FDK_HYBRID_SETUP setup = NULL; 391 392 switch (mode) { 393 case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; 394 case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; 395 case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; 396 default: err = -1; goto bail; 397 } 398 399 hSynthesisHybFilter->pSetup = setup; 400 hSynthesisHybFilter->nrBands = qmfBands; 401 hSynthesisHybFilter->cplxBands = cplxBands; 402 403 bail: 404 return err; 405 } 406 407 408 INT FDKhybridSynthesisApply( 409 HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, 410 const FIXP_DBL *const pHybridReal, 411 const FIXP_DBL *const pHybridImag, 412 FIXP_DBL *const pQmfReal, 413 FIXP_DBL *const pQmfImag 414 ) 415 { 416 int k, n, hybOffset=0; 417 INT err = 0; 418 const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; 419 420 /* 421 * LF buffer. 422 */ 423 for (k=0; k<nrQmfBandsLF; k++) { 424 const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; 425 426 FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); 427 FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); 428 429 /* Perform hybrid filtering. */ 430 for (n=0; n<nHybBands; n++) { 431 accu1 += pHybridReal[hybOffset+n]; 432 accu2 += pHybridImag[hybOffset+n]; 433 } 434 pQmfReal[k] = accu1; 435 pQmfImag[k] = accu2; 436 437 hybOffset += nHybBands; 438 } 439 440 if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) { 441 /* 442 * HF buffer. 443 */ 444 FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], (hSynthesisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 445 FDKmemcpy(&pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], (hSynthesisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); 446 } 447 448 return err; 449 } 450 451 static void dualChannelFiltering( 452 const FIXP_DBL *const pQmfReal, 453 const FIXP_DBL *const pQmfImag, 454 const INT *const pReadIdx, 455 FIXP_DBL *const mHybridReal, 456 FIXP_DBL *const mHybridImag, 457 const INT invert 458 ) 459 { 460 const FIXP_HTB *p = HybFilterCoef2; 461 462 FIXP_DBL r1, r6; 463 FIXP_DBL i1, i6; 464 465 /* symmetric filter coefficients */ 466 r1 = fMultDiv2(p[1], pQmfReal[pReadIdx[1]]) + fMultDiv2(p[1], pQmfReal[pReadIdx[11]]) ; 467 i1 = fMultDiv2(p[1], pQmfImag[pReadIdx[1]]) + fMultDiv2(p[1], pQmfImag[pReadIdx[11]]) ; 468 r1 += fMultDiv2(p[3], pQmfReal[pReadIdx[3]]) + fMultDiv2(p[3], pQmfReal[pReadIdx[ 9]]) ; 469 i1 += fMultDiv2(p[3], pQmfImag[pReadIdx[3]]) + fMultDiv2(p[3], pQmfImag[pReadIdx[ 9]]) ; 470 r1 += fMultDiv2(p[5], pQmfReal[pReadIdx[5]]) + fMultDiv2(p[5], pQmfReal[pReadIdx[ 7]]) ; 471 i1 += fMultDiv2(p[5], pQmfImag[pReadIdx[5]]) + fMultDiv2(p[5], pQmfImag[pReadIdx[ 7]]) ; 472 r6 = fMultDiv2(p[6], pQmfReal[pReadIdx[6]]) ; 473 i6 = fMultDiv2(p[6], pQmfImag[pReadIdx[6]]) ; 474 475 if (invert) { 476 mHybridReal[1] = (r1 + r6) << 1; 477 mHybridImag[1] = (i1 + i6) << 1; 478 479 mHybridReal[0] = (r6 - r1) << 1; 480 mHybridImag[0] = (i6 - i1) << 1; 481 } 482 else { 483 mHybridReal[0] = (r1 + r6) << 1; 484 mHybridImag[0] = (i1 + i6) << 1; 485 486 mHybridReal[1] = (r6 - r1) << 1; 487 mHybridImag[1] = (i6 - i1) << 1; 488 } 489 } 490 491 static void fourChannelFiltering( 492 const FIXP_DBL *const pQmfReal, 493 const FIXP_DBL *const pQmfImag, 494 const INT *const pReadIdx, 495 FIXP_DBL *const mHybridReal, 496 FIXP_DBL *const mHybridImag, 497 const INT invert 498 ) 499 { 500 const FIXP_HTB *p = HybFilterCoef4; 501 502 FIXP_DBL fft[8]; 503 504 static const FIXP_DBL cr[13] = { 505 FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), 506 FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), 507 FL2FXCONST_DBL( 1.f), 508 FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), 509 FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f) 510 }; 511 static const FIXP_DBL ci[13] = { 512 FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), 513 FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f), FL2FXCONST_DBL( 0.70710678118655f), 514 FL2FXCONST_DBL( 0.f), 515 FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), 516 FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f) 517 }; 518 519 520 /* FIR filter. */ 521 /* pre twiddeling with pre-twiddling coefficients c[n] */ 522 /* multiplication with filter coefficients p[n] */ 523 /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ 524 /* write to fft coefficient n' */ 525 fft[FFT_IDX_R(0)] = ( fMult(p[10], ( fMultSub(fMultDiv2(cr[ 2], pQmfReal[pReadIdx[ 2]]), ci[ 2], pQmfImag[pReadIdx[ 2]]))) + 526 fMult(p[ 6], ( fMultSub(fMultDiv2(cr[ 6], pQmfReal[pReadIdx[ 6]]), ci[ 6], pQmfImag[pReadIdx[ 6]]))) + 527 fMult(p[ 2], ( fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], pQmfImag[pReadIdx[10]]))) ); 528 fft[FFT_IDX_I(0)] = ( fMult(p[10], ( fMultAdd(fMultDiv2(ci[ 2], pQmfReal[pReadIdx[ 2]]), cr[ 2], pQmfImag[pReadIdx[ 2]]))) + 529 fMult(p[ 6], ( fMultAdd(fMultDiv2(ci[ 6], pQmfReal[pReadIdx[ 6]]), cr[ 6], pQmfImag[pReadIdx[ 6]]))) + 530 fMult(p[ 2], ( fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], pQmfImag[pReadIdx[10]]))) ); 531 532 /* twiddle dee dum */ 533 fft[FFT_IDX_R(1)] = ( fMult(p[ 9], ( fMultSub(fMultDiv2(cr[ 3], pQmfReal[pReadIdx[ 3]]), ci[ 3], pQmfImag[pReadIdx[ 3]]))) + 534 fMult(p[ 5], ( fMultSub(fMultDiv2(cr[ 7], pQmfReal[pReadIdx[ 7]]), ci[ 7], pQmfImag[pReadIdx[ 7]]))) + 535 fMult(p[ 1], ( fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], pQmfImag[pReadIdx[11]]))) ); 536 fft[FFT_IDX_I(1)] = ( fMult(p[ 9], ( fMultAdd(fMultDiv2(ci[ 3], pQmfReal[pReadIdx[ 3]]), cr[ 3], pQmfImag[pReadIdx[ 3]]))) + 537 fMult(p[ 5], ( fMultAdd(fMultDiv2(ci[ 7], pQmfReal[pReadIdx[ 7]]), cr[ 7], pQmfImag[pReadIdx[ 7]]))) + 538 fMult(p[ 1], ( fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], pQmfImag[pReadIdx[11]]))) ); 539 540 /* twiddle dee dee */ 541 fft[FFT_IDX_R(2)] = ( fMult(p[12], ( fMultSub(fMultDiv2(cr[ 0], pQmfReal[pReadIdx[ 0]]), ci[ 0], pQmfImag[pReadIdx[ 0]]))) + 542 fMult(p[ 8], ( fMultSub(fMultDiv2(cr[ 4], pQmfReal[pReadIdx[ 4]]), ci[ 4], pQmfImag[pReadIdx[ 4]]))) + 543 fMult(p[ 4], ( fMultSub(fMultDiv2(cr[ 8], pQmfReal[pReadIdx[ 8]]), ci[ 8], pQmfImag[pReadIdx[ 8]]))) + 544 fMult(p[ 0], ( fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], pQmfImag[pReadIdx[12]]))) ); 545 fft[FFT_IDX_I(2)] = ( fMult(p[12], ( fMultAdd(fMultDiv2(ci[ 0], pQmfReal[pReadIdx[ 0]]), cr[ 0], pQmfImag[pReadIdx[ 0]]))) + 546 fMult(p[ 8], ( fMultAdd(fMultDiv2(ci[ 4], pQmfReal[pReadIdx[ 4]]), cr[ 4], pQmfImag[pReadIdx[ 4]]))) + 547 fMult(p[ 4], ( fMultAdd(fMultDiv2(ci[ 8], pQmfReal[pReadIdx[ 8]]), cr[ 8], pQmfImag[pReadIdx[ 8]]))) + 548 fMult(p[ 0], ( fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], pQmfImag[pReadIdx[12]]))) ); 549 550 fft[FFT_IDX_R(3)] = ( fMult(p[11], ( fMultSub(fMultDiv2(cr[ 1], pQmfReal[pReadIdx[ 1]]), ci[ 1], pQmfImag[pReadIdx[ 1]]))) + 551 fMult(p[ 7], ( fMultSub(fMultDiv2(cr[ 5], pQmfReal[pReadIdx[ 5]]), ci[ 5], pQmfImag[pReadIdx[ 5]]))) + 552 fMult(p[ 3], ( fMultSub(fMultDiv2(cr[ 9], pQmfReal[pReadIdx[ 9]]), ci[ 9], pQmfImag[pReadIdx[ 9]]))) ); 553 fft[FFT_IDX_I(3)] = ( fMult(p[11], ( fMultAdd(fMultDiv2(ci[ 1], pQmfReal[pReadIdx[ 1]]), cr[ 1], pQmfImag[pReadIdx[ 1]]))) + 554 fMult(p[ 7], ( fMultAdd(fMultDiv2(ci[ 5], pQmfReal[pReadIdx[ 5]]), cr[ 5], pQmfImag[pReadIdx[ 5]]))) + 555 fMult(p[ 3], ( fMultAdd(fMultDiv2(ci[ 9], pQmfReal[pReadIdx[ 9]]), cr[ 9], pQmfImag[pReadIdx[ 9]]))) ); 556 557 /* fft modulation */ 558 /* here: fast manual fft modulation for a fft of length M=4 */ 559 /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + 560 x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ 561 562 /* 563 fft bin m=0: 564 X[0, n] = x[0] + x[1] + x[2] + x[3] 565 */ 566 mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + fft[FFT_IDX_R(3)]; 567 mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + fft[FFT_IDX_I(3)]; 568 569 /* 570 fft bin m=1: 571 X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] 572 */ 573 mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - fft[FFT_IDX_I(3)]; 574 mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + fft[FFT_IDX_R(3)]; 575 576 /* 577 fft bin m=2: 578 X[2, n] = x[0] - x[1] + x[2] - x[3] 579 */ 580 mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - fft[FFT_IDX_R(3)]; 581 mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - fft[FFT_IDX_I(3)]; 582 583 /* 584 fft bin m=3: 585 X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] 586 */ 587 mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + fft[FFT_IDX_I(3)]; 588 mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - fft[FFT_IDX_R(3)]; 589 } 590 591 592 static void eightChannelFiltering( 593 const FIXP_DBL *const pQmfReal, 594 const FIXP_DBL *const pQmfImag, 595 const INT *const pReadIdx, 596 FIXP_DBL *const mHybridReal, 597 FIXP_DBL *const mHybridImag, 598 const INT invert 599 ) 600 { 601 const FIXP_HTP *p = HybFilterCoef8; 602 INT k, sc; 603 604 FIXP_DBL mfft[16+ALIGNMENT_DEFAULT]; 605 FIXP_DBL *pfft = (FIXP_DBL*)ALIGN_PTR(mfft); 606 607 FIXP_DBL accu1, accu2, accu3, accu4; 608 609 /* pre twiddeling */ 610 pfft[FFT_IDX_R(0)] = fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); 611 pfft[FFT_IDX_I(0)] = fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); 612 613 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], p[1]); 614 pfft[FFT_IDX_R(1)] = accu1; 615 pfft[FFT_IDX_I(1)] = accu2; 616 617 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], p[2]); 618 cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], p[3]); 619 pfft[FFT_IDX_R(2)] = accu1 + accu3; 620 pfft[FFT_IDX_I(2)] = accu2 + accu4; 621 622 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], p[4]); 623 cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], p[5]); 624 pfft[FFT_IDX_R(3)] = accu1 + accu3; 625 pfft[FFT_IDX_I(3)] = accu2 + accu4; 626 627 pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - fMultDiv2(pQmfImag[pReadIdx[ 2]], p[6].v.im); 628 pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[ 2]], p[6].v.im) - fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); 629 630 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 3]], pQmfImag[pReadIdx[ 3]], p[8]); 631 cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], p[9]); 632 pfft[FFT_IDX_R(5)] = accu1 + accu3; 633 pfft[FFT_IDX_I(5)] = accu2 + accu4; 634 635 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 4]], pQmfImag[pReadIdx[ 4]], p[10]); 636 cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], p[11]); 637 pfft[FFT_IDX_R(6)] = accu1 + accu3; 638 pfft[FFT_IDX_I(6)] = accu2 + accu4; 639 640 cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 5]], pQmfImag[pReadIdx[ 5]], p[12]); 641 pfft[FFT_IDX_R(7)] = accu1; 642 pfft[FFT_IDX_I(7)] = accu2; 643 644 /* fft modulation */ 645 fft_8 (pfft); 646 sc = 1 + 2; 647 648 if (invert) { 649 mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; 650 mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; 651 mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; 652 mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; 653 654 mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; 655 mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; 656 mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; 657 mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; 658 659 mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc; 660 mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc; 661 mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc; 662 mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc; 663 664 mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc; 665 mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc; 666 mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc; 667 mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc; 668 } 669 else { 670 for(k=0; k<8;k++ ) { 671 mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; 672 mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; 673 } 674 } 675 } 676 677 static INT kChannelFiltering( 678 const FIXP_DBL *const pQmfReal, 679 const FIXP_DBL *const pQmfImag, 680 const INT *const pReadIdx, 681 FIXP_DBL *const mHybridReal, 682 FIXP_DBL *const mHybridImag, 683 const SCHAR hybridConfig 684 ) 685 { 686 INT err = 0; 687 688 switch (hybridConfig) { 689 case 2: 690 case -2: 691 dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); 692 break; 693 case 4: 694 case -4: 695 fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); 696 break; 697 case 8: 698 case -8: 699 eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); 700 break; 701 default: 702 err = -1; 703 } 704 705 return err; 706 } 707 708 709 710