diff options
Diffstat (limited to 'libFDK/src/FDK_hybrid.cpp')
-rw-r--r-- | libFDK/src/FDK_hybrid.cpp | 1246 |
1 files changed, 675 insertions, 571 deletions
diff --git a/libFDK/src/FDK_hybrid.cpp b/libFDK/src/FDK_hybrid.cpp index 20816f5..b661f82 100644 --- a/libFDK/src/FDK_hybrid.cpp +++ b/libFDK/src/FDK_hybrid.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. 1. INTRODUCTION -The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements -the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. -This FDK AAC Codec software is intended to be used on a wide variety of Android devices. - -AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual -audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by -independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part -of the MPEG specifications. - -Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) -may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners -individually for the purpose of encoding or decoding bit streams in products that are compliant with -the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license -these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec -software may already be covered under those patent licenses when it is used for those licensed purposes only. - -Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, -are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional -applications information and documentation. +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. 2. COPYRIGHT LICENSE -Redistribution and use in source and binary forms, with or without modification, are permitted without -payment of copyright license fees provided that you satisfy the following conditions: +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: -You must retain the complete text of this software license in redistributions of the FDK AAC Codec or -your modifications thereto in source code form. +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. -You must retain the complete text of this software license in the documentation and/or other materials -provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. -You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your modifications thereto to recipients of copies in binary form. -The name of Fraunhofer may not be used to endorse or promote products derived from this library without -prior written permission. +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. -You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec -software or your modifications thereto. +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. -Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software -and the date of any change. For modified versions of the FDK AAC Codec, the term -"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term -"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." 3. NO PATENT LICENSE -NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, -ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with -respect to this software. +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. -You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized -by appropriate patent licenses. +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. 4. DISCLAIMER -This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors -"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties -of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, -including but not limited to procurement of substitute goods or services; loss of use, data, or profits, -or business interruption, however caused and on any theory of liability, whether in contract, strict -liability, or tort (including negligence), arising in any way out of the use of this software, even if -advised of the possibility of such damage. +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. 5. CONTACT INFORMATION @@ -79,299 +90,344 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** -/*************************** Fraunhofer IIS FDK Tools ********************** + Author(s): Markus Lohwasser - Author(s): Markus Lohwasser Description: FDK Tools Hybrid Filterbank -******************************************************************************/ +*******************************************************************************/ #include "FDK_hybrid.h" - #include "fft.h" /*--------------- defines -----------------------------*/ -#define FFT_IDX_R(a) (2*a) -#define FFT_IDX_I(a) (2*a+1) - -#define HYB_COEF8_0 ( 0.00746082949812f ) -#define HYB_COEF8_1 ( 0.02270420949825f ) -#define HYB_COEF8_2 ( 0.04546865930473f ) -#define HYB_COEF8_3 ( 0.07266113929591f ) -#define HYB_COEF8_4 ( 0.09885108575264f ) -#define HYB_COEF8_5 ( 0.11793710567217f ) -#define HYB_COEF8_6 ( 0.12500000000000f ) -#define HYB_COEF8_7 ( HYB_COEF8_5 ) -#define HYB_COEF8_8 ( HYB_COEF8_4 ) -#define HYB_COEF8_9 ( HYB_COEF8_3 ) -#define HYB_COEF8_10 ( HYB_COEF8_2 ) -#define HYB_COEF8_11 ( HYB_COEF8_1 ) -#define HYB_COEF8_12 ( HYB_COEF8_0 ) - +#define FFT_IDX_R(a) (2 * a) +#define FFT_IDX_I(a) (2 * a + 1) + +#define HYB_COEF8_0 (0.00746082949812f) +#define HYB_COEF8_1 (0.02270420949825f) +#define HYB_COEF8_2 (0.04546865930473f) +#define HYB_COEF8_3 (0.07266113929591f) +#define HYB_COEF8_4 (0.09885108575264f) +#define HYB_COEF8_5 (0.11793710567217f) +#define HYB_COEF8_6 (0.12500000000000f) +#define HYB_COEF8_7 (HYB_COEF8_5) +#define HYB_COEF8_8 (HYB_COEF8_4) +#define HYB_COEF8_9 (HYB_COEF8_3) +#define HYB_COEF8_10 (HYB_COEF8_2) +#define HYB_COEF8_11 (HYB_COEF8_1) +#define HYB_COEF8_12 (HYB_COEF8_0) /*--------------- structure definitions ---------------*/ #if defined(ARCH_PREFER_MULT_32x16) - #define FIXP_HTB FIXP_SGL /* SGL data type. */ - #define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ - #define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ - #define FL2FXCONST_HTB FL2FXCONST_SGL +#define FIXP_HTB FIXP_SGL /* SGL data type. */ +#define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ +#define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ +#define FL2FXCONST_HTB FL2FXCONST_SGL #else - #define FIXP_HTB FIXP_DBL /* SGL data type. */ - #define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ - #define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ - #define FL2FXCONST_HTB FL2FXCONST_DBL +#define FIXP_HTB FIXP_DBL /* SGL data type. */ +#define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ +#define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ +#define FL2FXCONST_HTB FL2FXCONST_DBL #endif -#define HTCP(real,imag) { { HTC(real), HTC(imag) } } /* How to arrange the packed values. */ - - -struct FDK_HYBRID_SETUP -{ - UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ - UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ - SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ - UCHAR protoLen; /*!< Prototype filter length. */ - UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ - const INT *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ - +#define HTCP(real, imag) \ + { \ + { HTC(real), HTC(imag) } \ + } /* How to arrange the packed values. */ + +struct FDK_HYBRID_SETUP { + UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ + UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ + SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ + UCHAR protoLen; /*!< Prototype filter length. */ + UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ + const INT + *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ }; /*--------------- constants ---------------------------*/ -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 }; - -static const FDK_HYBRID_SETUP setup_3_16 = { 3, { 8, 4, 4}, { 8, 4, 4}, 13, (13-1)/2, ringbuffIdxTab}; -static const FDK_HYBRID_SETUP setup_3_12 = { 3, { 8, 2, 2}, { 8, 2, 2}, 13, (13-1)/2, ringbuffIdxTab}; -static const FDK_HYBRID_SETUP setup_3_10 = { 3, { 6, 2, 2}, { -8, -2, 2}, 13, (13-1)/2, ringbuffIdxTab}; +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}; +static const FDK_HYBRID_SETUP setup_3_16 = {3, {8, 4, 4}, {8, 4, 4}, + 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_12 = {3, {8, 2, 2}, {8, 2, 2}, + 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_10 = {3, {6, 2, 2}, {-8, -2, 2}, + 13, (13 - 1) / 2, ringbuffIdxTab}; static const FIXP_HTP HybFilterCoef8[] = { - HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), - HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), - HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), - HTCP(0x0df26407, 0x05c6e77e) -}; - -static const FIXP_HTB HybFilterCoef2[13] = { - FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.30596630545168f), - FL2FXCONST_HTB( 0.50000000000000f), FL2FXCONST_HTB( 0.30596630545168f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), - FL2FXCONST_HTB( 0.00000000000000f) -}; - -static const FIXP_HTB HybFilterCoef4[13] = { - FL2FXCONST_HTB(-0.00305151927305f), FL2FXCONST_HTB(-0.00794862316203f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.21227807049160f), - FL2FXCONST_HTB( 0.25f), FL2FXCONST_HTB( 0.21227807049160f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB(-0.00794862316203f), - FL2FXCONST_HTB(-0.00305151927305f) -}; + HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), + HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), + HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), + HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), + HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), + HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), + HTCP(0x0df26407, 0x05c6e77e)}; + +static const FIXP_HTB HybFilterCoef2[3] = {FL2FXCONST_HTB(0.01899487526049f), + FL2FXCONST_HTB(-0.07293139167538f), + FL2FXCONST_HTB(0.30596630545168f)}; + +static const FIXP_HTB HybFilterCoef4[13] = {FL2FXCONST_HTB(-0.00305151927305f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.25f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(-0.00305151927305f)}; /*--------------- function declarations ---------------*/ -static INT kChannelFiltering( - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - const INT *const pReadIdx, - FIXP_DBL *const mHybridReal, - FIXP_DBL *const mHybridImag, - const SCHAR hybridConfig - ); - +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig); /*--------------- function definitions ----------------*/ -INT FDKhybridAnalysisOpen( - HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, - FIXP_DBL *const pLFmemory, - const UINT LFmemorySize, - FIXP_DBL *const pHFmemory, - const UINT HFmemorySize - ) -{ +INT FDKhybridAnalysisOpen(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, const UINT HFmemorySize) { INT err = 0; /* Save pointer to extern memory. */ - hAnalysisHybFilter->pLFmemory = pLFmemory; + hAnalysisHybFilter->pLFmemory = pLFmemory; hAnalysisHybFilter->LFmemorySize = LFmemorySize; - hAnalysisHybFilter->pHFmemory = pHFmemory; + hAnalysisHybFilter->pHFmemory = pHFmemory; hAnalysisHybFilter->HFmemorySize = HFmemorySize; return err; } -INT FDKhybridAnalysisInit( - HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, - const FDK_HYBRID_MODE mode, - const INT qmfBands, - const INT cplxBands, - const INT initStatesFlag - ) -{ - int k; - INT err = 0; - FIXP_DBL *pMem = NULL; - HANDLE_FDK_HYBRID_SETUP setup = NULL; - - switch (mode) { - case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; - case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; - case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; - default: err = -1; goto bail; - } +INT FDKhybridAnalysisInit(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands, const INT initStatesFlag) { + int k; + INT err = 0; + FIXP_DBL *pMem = NULL; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } - /* Initialize handle. */ - hAnalysisHybFilter->pSetup = setup; - hAnalysisHybFilter->bufferLFpos = setup->protoLen-1; + /* Initialize handle. */ + hAnalysisHybFilter->pSetup = setup; + if (initStatesFlag) { + hAnalysisHybFilter->bufferLFpos = setup->protoLen - 1; hAnalysisHybFilter->bufferHFpos = 0; - hAnalysisHybFilter->nrBands = qmfBands; - hAnalysisHybFilter->cplxBands = cplxBands; - hAnalysisHybFilter->hfMode = 0; - - /* Check available memory. */ - if ( ((2*setup->nrQmfBands*setup->protoLen*sizeof(FIXP_DBL)) > hAnalysisHybFilter->LFmemorySize) - || ((setup->filterDelay*((qmfBands-setup->nrQmfBands)+(cplxBands-setup->nrQmfBands))*sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize) ) - { - err = -2; + } + hAnalysisHybFilter->nrBands = qmfBands; + hAnalysisHybFilter->cplxBands = cplxBands; + hAnalysisHybFilter->hfMode = 0; + + /* Check available memory. */ + if (((2 * setup->nrQmfBands * setup->protoLen * sizeof(FIXP_DBL)) > + hAnalysisHybFilter->LFmemorySize)) { + err = -2; + goto bail; + } + if (hAnalysisHybFilter->HFmemorySize != 0) { + if (((setup->filterDelay * + ((qmfBands - setup->nrQmfBands) + (cplxBands - setup->nrQmfBands)) * + sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize)) { + err = -3; goto bail; } + } - /* Distribut LF memory. */ - pMem = hAnalysisHybFilter->pLFmemory; - for (k=0; k<setup->nrQmfBands; k++) { - hAnalysisHybFilter->bufferLFReal[k] = pMem; pMem += setup->protoLen; - hAnalysisHybFilter->bufferLFImag[k] = pMem; pMem += setup->protoLen; - } + /* Distribute LF memory. */ + pMem = hAnalysisHybFilter->pLFmemory; + for (k = 0; k < setup->nrQmfBands; k++) { + hAnalysisHybFilter->bufferLFReal[k] = pMem; + pMem += setup->protoLen; + hAnalysisHybFilter->bufferLFImag[k] = pMem; + pMem += setup->protoLen; + } - /* Distribut HF memory. */ + /* Distribute HF memory. */ + if (hAnalysisHybFilter->HFmemorySize != 0) { pMem = hAnalysisHybFilter->pHFmemory; - for (k=0; k<setup->filterDelay; k++) { - hAnalysisHybFilter->bufferHFReal[k] = pMem; pMem += (qmfBands-setup->nrQmfBands); - hAnalysisHybFilter->bufferHFImag[k] = pMem; pMem += (cplxBands-setup->nrQmfBands); + for (k = 0; k < setup->filterDelay; k++) { + hAnalysisHybFilter->bufferHFReal[k] = pMem; + pMem += (qmfBands - setup->nrQmfBands); + hAnalysisHybFilter->bufferHFImag[k] = pMem; + pMem += (cplxBands - setup->nrQmfBands); } + } - if (initStatesFlag) { - /* Clear LF buffer */ - for (k=0; k<setup->nrQmfBands; k++) { - FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen*sizeof(FIXP_DBL)); - FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen*sizeof(FIXP_DBL)); - } + if (initStatesFlag) { + /* Clear LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], + setup->protoLen * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], + setup->protoLen * sizeof(FIXP_DBL)); + } + if (hAnalysisHybFilter->HFmemorySize != 0) { if (qmfBands > setup->nrQmfBands) { - /* Clear HF buffer */ - for (k=0; k<setup->filterDelay; k++) { - FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], (qmfBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); - FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], (cplxBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); + /* Clear HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], + (qmfBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], + (cplxBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + } } } - } + } bail: - return err; + return err; } -INT FDKhybridAnalysisScaleStates( - HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, - const INT scalingValue - ) -{ - INT err = 0; +INT FDKhybridAnalysisScaleStates(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue) { + INT err = 0; - if (hAnalysisHybFilter==NULL) { - err = 1; /* invalid handle */ + if (hAnalysisHybFilter == NULL) { + err = 1; /* invalid handle */ + } else { + int k; + HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; + + /* Scale LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, + scalingValue); + scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, + scalingValue); } - else { - int k; - HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; - - /* Scale LF buffer */ - for (k=0; k<setup->nrQmfBands; k++) { - scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, scalingValue); - scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, scalingValue); - } - if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { - /* Scale HF buffer */ - for (k=0; k<setup->filterDelay; k++) { - scaleValues(hAnalysisHybFilter->bufferHFReal[k], (hAnalysisHybFilter->nrBands-setup->nrQmfBands), scalingValue); - scaleValues(hAnalysisHybFilter->bufferHFImag[k], (hAnalysisHybFilter->cplxBands-setup->nrQmfBands), scalingValue); - } + if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { + /* Scale HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + scaleValues(hAnalysisHybFilter->bufferHFReal[k], + (hAnalysisHybFilter->nrBands - setup->nrQmfBands), + scalingValue); + scaleValues(hAnalysisHybFilter->bufferHFImag[k], + (hAnalysisHybFilter->cplxBands - setup->nrQmfBands), + scalingValue); } } - return err; + } + return err; } -INT FDKhybridAnalysisApply( - HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - FIXP_DBL *const pHybridReal, - FIXP_DBL *const pHybridImag) -{ - int k, hybOffset = 0; - INT err = 0; - const int nrQmfBandsLF = hAnalysisHybFilter->pSetup->nrQmfBands; /* number of QMF bands to be converted to hybrid */ +INT FDKhybridAnalysisApply(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag) { + int k, hybOffset = 0; + INT err = 0; + const int nrQmfBandsLF = + hAnalysisHybFilter->pSetup + ->nrQmfBands; /* number of QMF bands to be converted to hybrid */ - const int writIndex = hAnalysisHybFilter->bufferLFpos; - int readIndex = hAnalysisHybFilter->bufferLFpos; + const int writIndex = hAnalysisHybFilter->bufferLFpos; + int readIndex = hAnalysisHybFilter->bufferLFpos; - if (++readIndex>=hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; - const INT* pBufferLFreadIdx = &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; + if (++readIndex >= hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; + const INT *pBufferLFreadIdx = + &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; - /* - * LF buffer. - */ - for (k=0; k<nrQmfBandsLF; k++) { - /* New input sample. */ - hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k]; - hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + /* New input sample. */ + hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k]; + hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; /* Perform hybrid filtering. */ - kChannelFiltering( - hAnalysisHybFilter->bufferLFReal[k], - hAnalysisHybFilter->bufferLFImag[k], - pBufferLFreadIdx, - pHybridReal+hybOffset, - pHybridImag+hybOffset, - hAnalysisHybFilter->pSetup->kHybrid[k]); - - hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; - } + err |= + kChannelFiltering(hAnalysisHybFilter->bufferLFReal[k], + hAnalysisHybFilter->bufferLFImag[k], pBufferLFreadIdx, + pHybridReal + hybOffset, pHybridImag + hybOffset, + hAnalysisHybFilter->pSetup->kHybrid[k]); + + hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; + } - hAnalysisHybFilter->bufferLFpos = readIndex; /* Index where to write next input sample. */ + hAnalysisHybFilter->bufferLFpos = + readIndex; /* Index where to write next input sample. */ - if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { + if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { /* * HF buffer. */ - if (hAnalysisHybFilter->hfMode!=0) { - /* HF delay compensation was applied outside. */ - FDKmemcpy(pHybridReal+hybOffset, &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - FDKmemcpy(pHybridImag+hybOffset, &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + if (hAnalysisHybFilter->hfMode != 0) { + /* HF delay compensation was applied outside. */ + FDKmemcpy( + pHybridReal + hybOffset, &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } else { + FDK_ASSERT(hAnalysisHybFilter->HFmemorySize != 0); + /* HF delay compensation, filterlength/2. */ + FDKmemcpy( + pHybridReal + hybOffset, + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + FDKmemcpy( + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + if (++hAnalysisHybFilter->bufferHFpos >= + hAnalysisHybFilter->pSetup->filterDelay) + hAnalysisHybFilter->bufferHFpos = 0; } - else { - /* HF delay compensation, filterlength/2. */ - FDKmemcpy(pHybridReal+hybOffset, hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - FDKmemcpy(pHybridImag+hybOffset, hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + } /* process HF part*/ - FDKmemcpy(hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - FDKmemcpy(hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - - if (++hAnalysisHybFilter->bufferHFpos>=hAnalysisHybFilter->pSetup->filterDelay) hAnalysisHybFilter->bufferHFpos = 0; - } - } /* process HF part*/ - - return err; + return err; } -INT FDKhybridAnalysisClose( - HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter - ) -{ +INT FDKhybridAnalysisClose(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter) { INT err = 0; if (hAnalysisHybFilter != NULL) { - hAnalysisHybFilter->pLFmemory = NULL; - hAnalysisHybFilter->pHFmemory = NULL; + hAnalysisHybFilter->pLFmemory = NULL; + hAnalysisHybFilter->pHFmemory = NULL; hAnalysisHybFilter->LFmemorySize = 0; hAnalysisHybFilter->HFmemorySize = 0; } @@ -379,331 +435,379 @@ INT FDKhybridAnalysisClose( return err; } -INT FDKhybridSynthesisInit( - HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, - const FDK_HYBRID_MODE mode, - const INT qmfBands, - const INT cplxBands - ) -{ - INT err = 0; - HANDLE_FDK_HYBRID_SETUP setup = NULL; - - switch (mode) { - case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; - case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; - case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; - default: err = -1; goto bail; - } +INT FDKhybridSynthesisInit(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands) { + INT err = 0; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } - hSynthesisHybFilter->pSetup = setup; - hSynthesisHybFilter->nrBands = qmfBands; - hSynthesisHybFilter->cplxBands = cplxBands; + hSynthesisHybFilter->pSetup = setup; + hSynthesisHybFilter->nrBands = qmfBands; + hSynthesisHybFilter->cplxBands = cplxBands; bail: - return err; + return err; } +void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag) { + int k, n, hybOffset = 0; + const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; -INT FDKhybridSynthesisApply( - HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, - const FIXP_DBL *const pHybridReal, - const FIXP_DBL *const pHybridImag, - FIXP_DBL *const pQmfReal, - FIXP_DBL *const pQmfImag - ) -{ - int k, n, hybOffset=0; - INT err = 0; - const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; - - /* - * LF buffer. - */ - for (k=0; k<nrQmfBandsLF; k++) { - const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; - - FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); - FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); - - /* Perform hybrid filtering. */ - for (n=0; n<nHybBands; n++) { - accu1 += pHybridReal[hybOffset+n]; - accu2 += pHybridImag[hybOffset+n]; - } - pQmfReal[k] = accu1; - pQmfImag[k] = accu2; - - hybOffset += nHybBands; - } + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; - if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) { - /* - * HF buffer. - */ - FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], (hSynthesisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - FDKmemcpy(&pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], (hSynthesisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); - } - - return err; -} - -static void dualChannelFiltering( - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - const INT *const pReadIdx, - FIXP_DBL *const mHybridReal, - FIXP_DBL *const mHybridImag, - const INT invert - ) -{ - const FIXP_HTB *p = HybFilterCoef2; - - FIXP_DBL r1, r6; - FIXP_DBL i1, i6; - - /* symmetric filter coefficients */ - r1 = fMultDiv2(p[1], pQmfReal[pReadIdx[1]]) + fMultDiv2(p[1], pQmfReal[pReadIdx[11]]) ; - i1 = fMultDiv2(p[1], pQmfImag[pReadIdx[1]]) + fMultDiv2(p[1], pQmfImag[pReadIdx[11]]) ; - r1 += fMultDiv2(p[3], pQmfReal[pReadIdx[3]]) + fMultDiv2(p[3], pQmfReal[pReadIdx[ 9]]) ; - i1 += fMultDiv2(p[3], pQmfImag[pReadIdx[3]]) + fMultDiv2(p[3], pQmfImag[pReadIdx[ 9]]) ; - r1 += fMultDiv2(p[5], pQmfReal[pReadIdx[5]]) + fMultDiv2(p[5], pQmfReal[pReadIdx[ 7]]) ; - i1 += fMultDiv2(p[5], pQmfImag[pReadIdx[5]]) + fMultDiv2(p[5], pQmfImag[pReadIdx[ 7]]) ; - r6 = fMultDiv2(p[6], pQmfReal[pReadIdx[6]]) ; - i6 = fMultDiv2(p[6], pQmfImag[pReadIdx[6]]) ; - - if (invert) { - mHybridReal[1] = (r1 + r6) << 1; - mHybridImag[1] = (i1 + i6) << 1; - - mHybridReal[0] = (r6 - r1) << 1; - mHybridImag[0] = (i6 - i1) << 1; - } - else { - mHybridReal[0] = (r1 + r6) << 1; - mHybridImag[0] = (i1 + i6) << 1; + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); - mHybridReal[1] = (r6 - r1) << 1; - mHybridImag[1] = (i6 - i1) << 1; + /* Perform hybrid filtering. */ + for (n = 0; n < nHybBands; n++) { + accu1 += pHybridReal[hybOffset + n]; + accu2 += pHybridImag[hybOffset + n]; } -} - -static void fourChannelFiltering( - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - const INT *const pReadIdx, - FIXP_DBL *const mHybridReal, - FIXP_DBL *const mHybridImag, - const INT invert - ) -{ - const FIXP_HTB *p = HybFilterCoef4; - - FIXP_DBL fft[8]; - - static const FIXP_DBL cr[13] = { - FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), - FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), - FL2FXCONST_DBL( 1.f), - FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), - FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f) - }; - static const FIXP_DBL ci[13] = { - FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), - FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f), FL2FXCONST_DBL( 0.70710678118655f), - FL2FXCONST_DBL( 0.f), - FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), - FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f) - }; - - - /* FIR filter. */ - /* pre twiddeling with pre-twiddling coefficients c[n] */ - /* multiplication with filter coefficients p[n] */ - /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ - /* write to fft coefficient n' */ - fft[FFT_IDX_R(0)] = ( fMult(p[10], ( fMultSub(fMultDiv2(cr[ 2], pQmfReal[pReadIdx[ 2]]), ci[ 2], pQmfImag[pReadIdx[ 2]]))) + - fMult(p[ 6], ( fMultSub(fMultDiv2(cr[ 6], pQmfReal[pReadIdx[ 6]]), ci[ 6], pQmfImag[pReadIdx[ 6]]))) + - fMult(p[ 2], ( fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], pQmfImag[pReadIdx[10]]))) ); - fft[FFT_IDX_I(0)] = ( fMult(p[10], ( fMultAdd(fMultDiv2(ci[ 2], pQmfReal[pReadIdx[ 2]]), cr[ 2], pQmfImag[pReadIdx[ 2]]))) + - fMult(p[ 6], ( fMultAdd(fMultDiv2(ci[ 6], pQmfReal[pReadIdx[ 6]]), cr[ 6], pQmfImag[pReadIdx[ 6]]))) + - fMult(p[ 2], ( fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], pQmfImag[pReadIdx[10]]))) ); - - /* twiddle dee dum */ - fft[FFT_IDX_R(1)] = ( fMult(p[ 9], ( fMultSub(fMultDiv2(cr[ 3], pQmfReal[pReadIdx[ 3]]), ci[ 3], pQmfImag[pReadIdx[ 3]]))) + - fMult(p[ 5], ( fMultSub(fMultDiv2(cr[ 7], pQmfReal[pReadIdx[ 7]]), ci[ 7], pQmfImag[pReadIdx[ 7]]))) + - fMult(p[ 1], ( fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], pQmfImag[pReadIdx[11]]))) ); - fft[FFT_IDX_I(1)] = ( fMult(p[ 9], ( fMultAdd(fMultDiv2(ci[ 3], pQmfReal[pReadIdx[ 3]]), cr[ 3], pQmfImag[pReadIdx[ 3]]))) + - fMult(p[ 5], ( fMultAdd(fMultDiv2(ci[ 7], pQmfReal[pReadIdx[ 7]]), cr[ 7], pQmfImag[pReadIdx[ 7]]))) + - fMult(p[ 1], ( fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], pQmfImag[pReadIdx[11]]))) ); - - /* twiddle dee dee */ - fft[FFT_IDX_R(2)] = ( fMult(p[12], ( fMultSub(fMultDiv2(cr[ 0], pQmfReal[pReadIdx[ 0]]), ci[ 0], pQmfImag[pReadIdx[ 0]]))) + - fMult(p[ 8], ( fMultSub(fMultDiv2(cr[ 4], pQmfReal[pReadIdx[ 4]]), ci[ 4], pQmfImag[pReadIdx[ 4]]))) + - fMult(p[ 4], ( fMultSub(fMultDiv2(cr[ 8], pQmfReal[pReadIdx[ 8]]), ci[ 8], pQmfImag[pReadIdx[ 8]]))) + - fMult(p[ 0], ( fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], pQmfImag[pReadIdx[12]]))) ); - fft[FFT_IDX_I(2)] = ( fMult(p[12], ( fMultAdd(fMultDiv2(ci[ 0], pQmfReal[pReadIdx[ 0]]), cr[ 0], pQmfImag[pReadIdx[ 0]]))) + - fMult(p[ 8], ( fMultAdd(fMultDiv2(ci[ 4], pQmfReal[pReadIdx[ 4]]), cr[ 4], pQmfImag[pReadIdx[ 4]]))) + - fMult(p[ 4], ( fMultAdd(fMultDiv2(ci[ 8], pQmfReal[pReadIdx[ 8]]), cr[ 8], pQmfImag[pReadIdx[ 8]]))) + - fMult(p[ 0], ( fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], pQmfImag[pReadIdx[12]]))) ); - - fft[FFT_IDX_R(3)] = ( fMult(p[11], ( fMultSub(fMultDiv2(cr[ 1], pQmfReal[pReadIdx[ 1]]), ci[ 1], pQmfImag[pReadIdx[ 1]]))) + - fMult(p[ 7], ( fMultSub(fMultDiv2(cr[ 5], pQmfReal[pReadIdx[ 5]]), ci[ 5], pQmfImag[pReadIdx[ 5]]))) + - fMult(p[ 3], ( fMultSub(fMultDiv2(cr[ 9], pQmfReal[pReadIdx[ 9]]), ci[ 9], pQmfImag[pReadIdx[ 9]]))) ); - fft[FFT_IDX_I(3)] = ( fMult(p[11], ( fMultAdd(fMultDiv2(ci[ 1], pQmfReal[pReadIdx[ 1]]), cr[ 1], pQmfImag[pReadIdx[ 1]]))) + - fMult(p[ 7], ( fMultAdd(fMultDiv2(ci[ 5], pQmfReal[pReadIdx[ 5]]), cr[ 5], pQmfImag[pReadIdx[ 5]]))) + - fMult(p[ 3], ( fMultAdd(fMultDiv2(ci[ 9], pQmfReal[pReadIdx[ 9]]), cr[ 9], pQmfImag[pReadIdx[ 9]]))) ); - - /* fft modulation */ - /* here: fast manual fft modulation for a fft of length M=4 */ - /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + - x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ + pQmfReal[k] = accu1; + pQmfImag[k] = accu2; - /* - fft bin m=0: - X[0, n] = x[0] + x[1] + x[2] + x[3] - */ - mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + fft[FFT_IDX_R(3)]; - mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + fft[FFT_IDX_I(3)]; - - /* - fft bin m=1: - X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] - */ - mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - fft[FFT_IDX_I(3)]; - mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + fft[FFT_IDX_R(3)]; + hybOffset += nHybBands; + } + if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) { /* - fft bin m=2: - X[2, n] = x[0] - x[1] + x[2] - x[3] - */ - mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - fft[FFT_IDX_R(3)]; - mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - fft[FFT_IDX_I(3)]; + * HF buffer. + */ + FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], + (hSynthesisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + &pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], + (hSynthesisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } - /* - fft bin m=3: - X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] - */ - mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + fft[FFT_IDX_I(3)]; - mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - fft[FFT_IDX_R(3)]; + return; } +static void dualChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + FIXP_DBL r1, r6; + FIXP_DBL i1, i6; + + const FIXP_HTB f0 = HybFilterCoef2[0]; /* corresponds to p1 and p11 */ + const FIXP_HTB f1 = HybFilterCoef2[1]; /* corresponds to p3 and p9 */ + const FIXP_HTB f2 = HybFilterCoef2[2]; /* corresponds to p5 and p7 */ + + /* symmetric filter coefficients */ + r1 = fMultDiv2(f0, pQmfReal[pReadIdx[1]]) + + fMultDiv2(f0, pQmfReal[pReadIdx[11]]); + i1 = fMultDiv2(f0, pQmfImag[pReadIdx[1]]) + + fMultDiv2(f0, pQmfImag[pReadIdx[11]]); + r1 += fMultDiv2(f1, pQmfReal[pReadIdx[3]]) + + fMultDiv2(f1, pQmfReal[pReadIdx[9]]); + i1 += fMultDiv2(f1, pQmfImag[pReadIdx[3]]) + + fMultDiv2(f1, pQmfImag[pReadIdx[9]]); + r1 += fMultDiv2(f2, pQmfReal[pReadIdx[5]]) + + fMultDiv2(f2, pQmfReal[pReadIdx[7]]); + i1 += fMultDiv2(f2, pQmfImag[pReadIdx[5]]) + + fMultDiv2(f2, pQmfImag[pReadIdx[7]]); + + r6 = pQmfReal[pReadIdx[6]] >> 2; + i6 = pQmfImag[pReadIdx[6]] >> 2; + + FDK_ASSERT((invert == 0) || (invert == 1)); + mHybridReal[0 + invert] = (r6 + r1) << 1; + mHybridImag[0 + invert] = (i6 + i1) << 1; + + mHybridReal[1 - invert] = (r6 - r1) << 1; + mHybridImag[1 - invert] = (i6 - i1) << 1; +} -static void eightChannelFiltering( - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - const INT *const pReadIdx, - FIXP_DBL *const mHybridReal, - FIXP_DBL *const mHybridImag, - const INT invert - ) -{ - const FIXP_HTP *p = HybFilterCoef8; - INT k, sc; - - FIXP_DBL mfft[16+ALIGNMENT_DEFAULT]; - FIXP_DBL *pfft = (FIXP_DBL*)ALIGN_PTR(mfft); - - FIXP_DBL accu1, accu2, accu3, accu4; - - /* pre twiddeling */ - pfft[FFT_IDX_R(0)] = fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); - pfft[FFT_IDX_I(0)] = fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], p[1]); - pfft[FFT_IDX_R(1)] = accu1; - pfft[FFT_IDX_I(1)] = accu2; - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], p[2]); - cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], p[3]); - pfft[FFT_IDX_R(2)] = accu1 + accu3; - pfft[FFT_IDX_I(2)] = accu2 + accu4; - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], p[4]); - cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], p[5]); - pfft[FFT_IDX_R(3)] = accu1 + accu3; - pfft[FFT_IDX_I(3)] = accu2 + accu4; - - pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - fMultDiv2(pQmfImag[pReadIdx[ 2]], p[6].v.im); - pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[ 2]], p[6].v.im) - fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 3]], pQmfImag[pReadIdx[ 3]], p[8]); - cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], p[9]); - pfft[FFT_IDX_R(5)] = accu1 + accu3; - pfft[FFT_IDX_I(5)] = accu2 + accu4; - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 4]], pQmfImag[pReadIdx[ 4]], p[10]); - cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], p[11]); - pfft[FFT_IDX_R(6)] = accu1 + accu3; - pfft[FFT_IDX_I(6)] = accu2 + accu4; - - cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 5]], pQmfImag[pReadIdx[ 5]], p[12]); - pfft[FFT_IDX_R(7)] = accu1; - pfft[FFT_IDX_I(7)] = accu2; - - /* fft modulation */ - fft_8 (pfft); - sc = 1 + 2; - - if (invert) { - mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; - mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; - mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; - mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; - - mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; - mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; - mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; - mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; - - mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc; - mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc; - mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc; - mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc; - - mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc; - mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc; - mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc; - mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc; - } - else { - for(k=0; k<8;k++ ) { - mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; - mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; - } - } +static void fourChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTB *p = HybFilterCoef4; + + FIXP_DBL fft[8]; + + static const FIXP_DBL cr[13] = { + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f)}; + static const FIXP_DBL ci[13] = { + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f)}; + + /* FIR filter. */ + /* pre twiddeling with pre-twiddling coefficients c[n] */ + /* multiplication with filter coefficients p[n] */ + /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ + /* write to fft coefficient n' */ + fft[FFT_IDX_R(0)] = + (fMult(p[10], (fMultSub(fMultDiv2(cr[2], pQmfReal[pReadIdx[2]]), ci[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultSub(fMultDiv2(cr[6], pQmfReal[pReadIdx[6]]), ci[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], + pQmfImag[pReadIdx[10]])))); + fft[FFT_IDX_I(0)] = + (fMult(p[10], (fMultAdd(fMultDiv2(ci[2], pQmfReal[pReadIdx[2]]), cr[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultAdd(fMultDiv2(ci[6], pQmfReal[pReadIdx[6]]), cr[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], + pQmfImag[pReadIdx[10]])))); + + /* twiddle dee dum */ + fft[FFT_IDX_R(1)] = + (fMult(p[9], (fMultSub(fMultDiv2(cr[3], pQmfReal[pReadIdx[3]]), ci[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultSub(fMultDiv2(cr[7], pQmfReal[pReadIdx[7]]), ci[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], + pQmfImag[pReadIdx[11]])))); + fft[FFT_IDX_I(1)] = + (fMult(p[9], (fMultAdd(fMultDiv2(ci[3], pQmfReal[pReadIdx[3]]), cr[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultAdd(fMultDiv2(ci[7], pQmfReal[pReadIdx[7]]), cr[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], + pQmfImag[pReadIdx[11]])))); + + /* twiddle dee dee */ + fft[FFT_IDX_R(2)] = + (fMult(p[12], (fMultSub(fMultDiv2(cr[0], pQmfReal[pReadIdx[0]]), ci[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultSub(fMultDiv2(cr[4], pQmfReal[pReadIdx[4]]), ci[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultSub(fMultDiv2(cr[8], pQmfReal[pReadIdx[8]]), ci[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], + pQmfImag[pReadIdx[12]])))); + fft[FFT_IDX_I(2)] = + (fMult(p[12], (fMultAdd(fMultDiv2(ci[0], pQmfReal[pReadIdx[0]]), cr[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultAdd(fMultDiv2(ci[4], pQmfReal[pReadIdx[4]]), cr[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultAdd(fMultDiv2(ci[8], pQmfReal[pReadIdx[8]]), cr[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], + pQmfImag[pReadIdx[12]])))); + + fft[FFT_IDX_R(3)] = + (fMult(p[11], (fMultSub(fMultDiv2(cr[1], pQmfReal[pReadIdx[1]]), ci[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultSub(fMultDiv2(cr[5], pQmfReal[pReadIdx[5]]), ci[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultSub(fMultDiv2(cr[9], pQmfReal[pReadIdx[9]]), ci[9], + pQmfImag[pReadIdx[9]])))); + fft[FFT_IDX_I(3)] = + (fMult(p[11], (fMultAdd(fMultDiv2(ci[1], pQmfReal[pReadIdx[1]]), cr[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultAdd(fMultDiv2(ci[5], pQmfReal[pReadIdx[5]]), cr[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultAdd(fMultDiv2(ci[9], pQmfReal[pReadIdx[9]]), cr[9], + pQmfImag[pReadIdx[9]])))); + + /* fft modulation */ + /* here: fast manual fft modulation for a fft of length M=4 */ + /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + + x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ + + /* + fft bin m=0: + X[0, n] = x[0] + x[1] + x[2] + x[3] + */ + mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + + fft[FFT_IDX_R(3)]; + mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + + fft[FFT_IDX_I(3)]; + + /* + fft bin m=1: + X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] + */ + mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - + fft[FFT_IDX_I(3)]; + mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + + fft[FFT_IDX_R(3)]; + + /* + fft bin m=2: + X[2, n] = x[0] - x[1] + x[2] - x[3] + */ + mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - + fft[FFT_IDX_R(3)]; + mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - + fft[FFT_IDX_I(3)]; + + /* + fft bin m=3: + X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] + */ + mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + + fft[FFT_IDX_I(3)]; + mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - + fft[FFT_IDX_R(3)]; } -static INT kChannelFiltering( - const FIXP_DBL *const pQmfReal, - const FIXP_DBL *const pQmfImag, - const INT *const pReadIdx, - FIXP_DBL *const mHybridReal, - FIXP_DBL *const mHybridImag, - const SCHAR hybridConfig - ) -{ - INT err = 0; - - switch (hybridConfig) { - case 2: - case -2: - dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); - break; - case 4: - case -4: - fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); - break; - case 8: - case -8: - eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); - break; - default: - err = -1; +static void eightChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTP *p = HybFilterCoef8; + INT k, sc; + + FIXP_DBL mfft[16 + ALIGNMENT_DEFAULT]; + FIXP_DBL *pfft = (FIXP_DBL *)ALIGN_PTR(mfft); + + FIXP_DBL accu1, accu2, accu3, accu4; + + /* pre twiddeling */ + pfft[FFT_IDX_R(0)] = + pQmfReal[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); */ + pfft[FFT_IDX_I(0)] = + pQmfImag[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); */ + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], + p[1]); + pfft[FFT_IDX_R(1)] = accu1; + pfft[FFT_IDX_I(1)] = accu2; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], + p[2]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], + p[3]); + pfft[FFT_IDX_R(2)] = accu1 + accu3; + pfft[FFT_IDX_I(2)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], + p[4]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], + p[5]); + pfft[FFT_IDX_R(3)] = accu1 + accu3; + pfft[FFT_IDX_I(3)] = accu2 + accu4; + + pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - + fMultDiv2(pQmfImag[pReadIdx[2]], p[6].v.im); + pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[2]], p[6].v.im) - + fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[3]], pQmfImag[pReadIdx[3]], + p[8]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], + p[9]); + pfft[FFT_IDX_R(5)] = accu1 + accu3; + pfft[FFT_IDX_I(5)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[4]], pQmfImag[pReadIdx[4]], + p[10]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], + p[11]); + pfft[FFT_IDX_R(6)] = accu1 + accu3; + pfft[FFT_IDX_I(6)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[5]], pQmfImag[pReadIdx[5]], + p[12]); + pfft[FFT_IDX_R(7)] = accu1; + pfft[FFT_IDX_I(7)] = accu2; + + /* fft modulation */ + fft_8(pfft); + sc = 1 + 2; + + if (invert) { + mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; + mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; + mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; + mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; + + mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; + mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; + mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; + mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; + + mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc; + mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc; + mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc; + mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc; + + mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc; + mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc; + mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc; + mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc; + } else { + for (k = 0; k < 8; k++) { + mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; + mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; } - - return err; + } } +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig) { + INT err = 0; + switch (hybridConfig) { + case 2: + case -2: + dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 4: + case -4: + fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 8: + case -8: + eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + default: + err = -1; + } + return err; +} |