Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung der angewandten
      5 Forschung e.V. All rights reserved.
      6 
      7  1.    INTRODUCTION
      8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
      9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
     10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
     11 a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
     14 general perceptual audio codecs. AAC-ELD is considered the best-performing
     15 full-bandwidth communications codec by independent studies and is widely
     16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
     17 specifications.
     18 
     19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
     20 those of Fraunhofer) may be obtained through Via Licensing
     21 (www.vialicensing.com) or through the respective patent owners individually for
     22 the purpose of encoding or decoding bit streams in products that are compliant
     23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
     24 Android devices already license these patent claims through Via Licensing or
     25 directly from the patent owners, and therefore FDK AAC Codec software may
     26 already be covered under those patent licenses when it is used for those
     27 licensed purposes only.
     28 
     29 Commercially-licensed AAC software libraries, including floating-point versions
     30 with enhanced sound quality, are also available from Fraunhofer. Users are
     31 encouraged to check the Fraunhofer website for additional applications
     32 information and documentation.
     33 
     34 2.    COPYRIGHT LICENSE
     35 
     36 Redistribution and use in source and binary forms, with or without modification,
     37 are permitted without payment of copyright license fees provided that you
     38 satisfy the following conditions:
     39 
     40 You must retain the complete text of this software license in redistributions of
     41 the FDK AAC Codec or your modifications thereto in source code form.
     42 
     43 You must retain the complete text of this software license in the documentation
     44 and/or other materials provided with redistributions of the FDK AAC Codec or
     45 your modifications thereto in binary form. You must make available free of
     46 charge copies of the complete source code of the FDK AAC Codec and your
     47 modifications thereto to recipients of copies in binary form.
     48 
     49 The name of Fraunhofer may not be used to endorse or promote products derived
     50 from this library without prior written permission.
     51 
     52 You may not charge copyright license fees for anyone to use, copy or distribute
     53 the FDK AAC Codec software or your modifications thereto.
     54 
     55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
     56 that you changed the software and the date of any change. For modified versions
     57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
     58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
     59 AAC Codec Library for Android."
     60 
     61 3.    NO PATENT LICENSE
     62 
     63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
     64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
     65 Fraunhofer provides no warranty of patent non-infringement with respect to this
     66 software.
     67 
     68 You may use this FDK AAC Codec software or modifications thereto only for
     69 purposes that are authorized by appropriate patent licenses.
     70 
     71 4.    DISCLAIMER
     72 
     73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
     74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     75 including but not limited to the implied warranties of merchantability and
     76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
     78 or consequential damages, including but not limited to procurement of substitute
     79 goods or services; loss of use, data, or profits, or business interruption,
     80 however caused and on any theory of liability, whether in contract, strict
     81 liability, or tort (including negligence), arising in any way out of the use of
     82 this software, even if advised of the possibility of such damage.
     83 
     84 5.    CONTACT INFORMATION
     85 
     86 Fraunhofer Institute for Integrated Circuits IIS
     87 Attention: Audio and Multimedia Departments - FDK AAC LL
     88 Am Wolfsmantel 33
     89 91058 Erlangen, Germany
     90 
     91 www.iis.fraunhofer.de/amm
     92 amm-info (at) iis.fraunhofer.de
     93 ----------------------------------------------------------------------------- */
     94 
     95 /*********************** MPEG surround encoder library *************************
     96 
     97    Author(s):   M. Multrus
     98 
     99    Description: Parameter Extraction
    100 
    101 *******************************************************************************/
    102 
    103 /* Includes ******************************************************************/
    104 #include "sacenc_paramextract.h"
    105 #include "sacenc_tree.h"
    106 #include "sacenc_vectorfunctions.h"
    107 
    108 /* Defines *******************************************************************/
    109 #define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */
    110 #define SCALE_CLDE_SF (7)           /* maxVal in Quant tab is +/-  50 */
    111 #define SCALE_CLDD_SF (8)           /* maxVal in Quant tab is +/- 150 */
    112 
    113 /* Data Types ****************************************************************/
    114 typedef struct T_TTO_BOX {
    115   FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS];
    116   FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS];
    117   FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS];
    118 
    119   const FIXP_DBL *pIccQuantTable__FDK;
    120   const FIXP_DBL *pCldQuantTableDec__FDK;
    121   const FIXP_DBL *pCldQuantTableEnc__FDK;
    122 
    123   SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS];
    124   SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS];
    125 
    126   UCHAR *pParameterBand2HybridBandOffset;
    127   const INT *pSubbandImagSign;
    128   UCHAR nHybridBandsMax;
    129   UCHAR nParameterBands;
    130   UCHAR bFrameKeep;
    131 
    132   UCHAR iccCorrelationCoherenceBorder;
    133   BOX_QUANTMODE boxQuantMode;
    134 
    135   UCHAR nIccQuantSteps;
    136   UCHAR nIccQuantOffset;
    137 
    138   UCHAR nCldQuantSteps;
    139   UCHAR nCldQuantOffset;
    140 
    141   UCHAR bUseCoarseQuantCld;
    142   UCHAR bUseCoarseQuantIcc;
    143 
    144 } TTO_BOX;
    145 
    146 struct BOX_SUBBAND_SETUP {
    147   BOX_SUBBAND_CONFIG subbandConfig;
    148   UCHAR nParameterBands;
    149   const UCHAR *pSubband2ParameterIndexLd;
    150   UCHAR iccCorrelationCoherenceBorder;
    151 };
    152 
    153 /* Constants *****************************************************************/
    154 static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = {
    155     0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    156     2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    157     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
    158 
    159 static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = {
    160     0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    161     3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    162     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
    163 
    164 static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = {
    165     0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
    166     5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    167     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
    168 
    169 static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = {
    170     0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
    171     7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    172     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
    173 
    174 static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = {
    175     0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8,
    176     8,  8,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 10,
    177     10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    178     11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
    179 
    180 static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = {
    181     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  10, 10, 10, 11, 11,
    182     11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    183     13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    184     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
    185 
    186 static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = {
    187     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 12, 13, 13,
    188     14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19,
    189     19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
    190     22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22};
    191 
    192 static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = {
    193     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    194     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    195     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    196 };
    197 
    198 #define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF)))
    199 static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = {
    200     SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0),
    201     SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0),
    202     SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0),
    203     SCALE_CLDE(-6.0),  SCALE_CLDE(-4.0),  SCALE_CLDE(-2.0),  SCALE_CLDE(0.0),
    204     SCALE_CLDE(2.0),   SCALE_CLDE(4.0),   SCALE_CLDE(6.0),   SCALE_CLDE(8.0),
    205     SCALE_CLDE(10.0),  SCALE_CLDE(13.0),  SCALE_CLDE(16.0),  SCALE_CLDE(19.0),
    206     SCALE_CLDE(22.0),  SCALE_CLDE(25.0),  SCALE_CLDE(30.0),  SCALE_CLDE(35.0),
    207     SCALE_CLDE(40.0),  SCALE_CLDE(45.0),  SCALE_CLDE(50.0)};
    208 
    209 static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = {
    210     SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0),
    211     SCALE_CLDE(-13.0), SCALE_CLDE(-8.0),  SCALE_CLDE(-4.0),  SCALE_CLDE(0.0),
    212     SCALE_CLDE(4.0),   SCALE_CLDE(8.0),   SCALE_CLDE(13.0),  SCALE_CLDE(19.0),
    213     SCALE_CLDE(25.0),  SCALE_CLDE(35.0),  SCALE_CLDE(50.0)};
    214 
    215 #define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF)))
    216 static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = {
    217     SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0),
    218     SCALE_CLDD(-30.0),  SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0),
    219     SCALE_CLDD(-16.0),  SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0),
    220     SCALE_CLDD(-6.0),   SCALE_CLDD(-4.0),  SCALE_CLDD(-2.0),  SCALE_CLDD(0.0),
    221     SCALE_CLDD(2.0),    SCALE_CLDD(4.0),   SCALE_CLDD(6.0),   SCALE_CLDD(8.0),
    222     SCALE_CLDD(10.0),   SCALE_CLDD(13.0),  SCALE_CLDD(16.0),  SCALE_CLDD(19.0),
    223     SCALE_CLDD(22.0),   SCALE_CLDD(25.0),  SCALE_CLDD(30.0),  SCALE_CLDD(35.0),
    224     SCALE_CLDD(40.0),   SCALE_CLDD(45.0),  SCALE_CLDD(150.0)};
    225 
    226 static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = {
    227     SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0),
    228     SCALE_CLDD(-13.0),  SCALE_CLDD(-8.0),  SCALE_CLDD(-4.0),  SCALE_CLDD(0.0),
    229     SCALE_CLDD(4.0),    SCALE_CLDD(8.0),   SCALE_CLDD(13.0),  SCALE_CLDD(19.0),
    230     SCALE_CLDD(25.0),   SCALE_CLDD(35.0),  SCALE_CLDD(150.0)};
    231 
    232 #define SCALE_ICC(a) (FL2FXCONST_DBL(a))
    233 static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = {
    234     SCALE_ICC(0.99999999953), SCALE_ICC(0.937f),   SCALE_ICC(0.84118f),
    235     SCALE_ICC(0.60092f),      SCALE_ICC(0.36764f), SCALE_ICC(0.0f),
    236     SCALE_ICC(-0.589f),       SCALE_ICC(-0.99f)};
    237 
    238 static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = {
    239     SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f),
    240     SCALE_ICC(-0.5890f)};
    241 
    242 static const BOX_SUBBAND_SETUP boxSubbandSetup[] = {
    243     {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1},
    244     {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2},
    245     {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3},
    246     {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4},
    247     {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4},
    248     {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5},
    249     {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}};
    250 
    251 /* Function / Class Declarations *********************************************/
    252 
    253 /* Function / Class Definition ***********************************************/
    254 static const BOX_SUBBAND_SETUP *getBoxSubbandSetup(
    255     const BOX_SUBBAND_CONFIG subbandConfig) {
    256   int i;
    257   const BOX_SUBBAND_SETUP *setup = NULL;
    258 
    259   for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP));
    260        i++) {
    261     if (boxSubbandSetup[i].subbandConfig == subbandConfig) {
    262       setup = &boxSubbandSetup[i];
    263       break;
    264     }
    265   }
    266   return setup;
    267 }
    268 
    269 static inline void ApplyBBCuesFDK(FIXP_DBL *const pData,
    270                                   const INT nParamBands) {
    271   int i, s;
    272   FIXP_DBL tmp, invParamBands;
    273 
    274   invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s);
    275   s = -s;
    276 
    277   tmp = fMult(pData[0], invParamBands) >> s;
    278   for (i = 1; i < nParamBands; i++) {
    279     tmp += fMult(pData[i], invParamBands) >> s;
    280   }
    281 
    282   for (i = 0; i < nParamBands; i++) {
    283     pData[i] = tmp;
    284   }
    285 }
    286 
    287 static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) {
    288   const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
    289   return ((setup == NULL) ? 0 : setup->nParameterBands);
    290 }
    291 
    292 static const UCHAR *getSubband2ParameterIndex(
    293     const BOX_SUBBAND_CONFIG subbandConfig) {
    294   const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
    295 
    296   return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd));
    297 }
    298 
    299 void fdk_sacenc_calcParameterBand2HybridBandOffset(
    300     const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands,
    301     UCHAR *pParameterBand2HybridBandOffset) {
    302   const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
    303   const UCHAR *pSubband2ParameterIndex;
    304 
    305   int i, pb;
    306 
    307   pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd;
    308 
    309   for (pb = 0, i = 0; i < nHybridBands - 1; i++) {
    310     if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) {
    311       pParameterBand2HybridBandOffset[pb++] = (i + 1);
    312     }
    313   }
    314   pParameterBand2HybridBandOffset[pb++] = (i + 1);
    315 }
    316 
    317 const INT *fdk_sacenc_getSubbandImagSign() {
    318   const INT *pImagSign = NULL;
    319 
    320   pImagSign = subbandImagSign_Ld;
    321 
    322   return (pImagSign);
    323 }
    324 
    325 static INT getIccCorrelationCoherenceBorder(
    326     const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) {
    327   const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
    328   return (
    329       (setup == NULL)
    330           ? 0
    331           : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder));
    332 }
    333 
    334 FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) {
    335   FDK_SACENC_ERROR error = SACENC_OK;
    336 
    337   if (NULL == hTtoBox) {
    338     error = SACENC_INVALID_HANDLE;
    339   } else {
    340     FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX);
    341   }
    342   return error;
    343 
    344 bail:
    345   fdk_sacenc_destroyTtoBox(hTtoBox);
    346   return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
    347 }
    348 
    349 FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox,
    350                                        const TTO_BOX_CONFIG *const ttoBoxConfig,
    351                                        UCHAR *pParameterBand2HybridBandOffset) {
    352   FDK_SACENC_ERROR error = SACENC_OK;
    353 
    354   if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) ||
    355       (pParameterBand2HybridBandOffset == NULL)) {
    356     error = SACENC_INVALID_HANDLE;
    357   } else {
    358     FDKmemclear(hTtoBox, sizeof(TTO_BOX));
    359 
    360     hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld;
    361     hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc;
    362     hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode;
    363     hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder(
    364         ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly);
    365     hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax;
    366     hTtoBox->nParameterBands =
    367         getNumberParameterBands(ttoBoxConfig->subbandConfig);
    368     hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep;
    369 
    370     hTtoBox->nIccQuantSteps =
    371         fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc);
    372     hTtoBox->nIccQuantOffset =
    373         fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc);
    374 
    375     hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc
    376                                        ? iccQuantTableCoarse__FDK
    377                                        : iccQuantTableFine__FDK;
    378     hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld
    379                                           ? cldQuantTableCoarseDec__FDK
    380                                           : cldQuantTableFineDec__FDK;
    381     hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld
    382                                           ? cldQuantTableCoarseEnc__FDK
    383                                           : cldQuantTableFineEnc__FDK;
    384 
    385     hTtoBox->nCldQuantSteps =
    386         fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld);
    387     hTtoBox->nCldQuantOffset =
    388         fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld);
    389 
    390     /* sanity */
    391     if (NULL == (hTtoBox->pParameterBand2HybridBandOffset =
    392                      pParameterBand2HybridBandOffset)) {
    393       error = SACENC_INIT_ERROR;
    394       goto bail;
    395     }
    396 
    397     if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) {
    398       error = SACENC_INIT_ERROR;
    399     }
    400 
    401     if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) &&
    402         (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) &&
    403         (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) {
    404       error = SACENC_INIT_ERROR;
    405       goto bail;
    406     }
    407   }
    408 bail:
    409   return error;
    410 }
    411 
    412 FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) {
    413   FDK_SACENC_ERROR error = SACENC_OK;
    414 
    415   if (*hTtoBox != NULL) {
    416     FDKfree(*hTtoBox);
    417     *hTtoBox = NULL;
    418   }
    419 
    420   return error;
    421 }
    422 
    423 static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand,
    424                                         const INT correlationCoherenceBorder,
    425                                         const FIXP_DBL *const pPwr1,
    426                                         const FIXP_DBL *const pPwr2,
    427                                         const FIXP_DBL *const pProdReal,
    428                                         FIXP_DBL const *const pProdImag,
    429                                         FIXP_DBL *const pIcc) {
    430   FDK_SACENC_ERROR error = SACENC_OK;
    431 
    432   if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) ||
    433       (pProdImag == NULL) || (pIcc == NULL)) {
    434     error = SACENC_INVALID_HANDLE;
    435   } else {
    436     /* sanity check border */
    437     if (correlationCoherenceBorder > nParamBand) {
    438       error = SACENC_INVALID_CONFIG;
    439     } else {
    440       /* correlation */
    441       FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2,
    442                             correlationCoherenceBorder);
    443 
    444       /* coherence */
    445       calcCoherenceVec(&pIcc[correlationCoherenceBorder],
    446                        &pProdReal[correlationCoherenceBorder],
    447                        &pProdImag[correlationCoherenceBorder],
    448                        &pPwr1[correlationCoherenceBorder],
    449                        &pPwr2[correlationCoherenceBorder], 0, 0,
    450                        nParamBand - correlationCoherenceBorder);
    451 
    452     } /* valid configuration */
    453   }   /* valid handle */
    454 
    455   return error;
    456 }
    457 
    458 static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands,
    459                             const FIXP_DBL *const quantTable,
    460                             const INT idxOffset, const INT nQuantSteps,
    461                             SCHAR *const quantOut) {
    462   int band;
    463   const int reverse = (quantTable[0] > quantTable[1]);
    464 
    465   for (band = 0; band < nBands; band++) {
    466     FIXP_DBL qVal;
    467     FIXP_DBL curVal = input[band];
    468 
    469     int lower = 0;
    470     int upper = nQuantSteps - 1;
    471 
    472     if (reverse) {
    473       while (upper - lower > 1) {
    474         int idx = (lower + upper) >> 1;
    475         qVal = quantTable[idx];
    476         if (curVal >= qVal) {
    477           upper = idx;
    478         } else {
    479           lower = idx;
    480         }
    481       } /* while */
    482 
    483       if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) {
    484         quantOut[band] = lower - idxOffset;
    485       } else {
    486         quantOut[band] = upper - idxOffset;
    487       }
    488     } /* if reverse */
    489     else {
    490       while (upper - lower > 1) {
    491         int idx = (lower + upper) >> 1;
    492         qVal = quantTable[idx];
    493         if (curVal <= qVal) {
    494           upper = idx;
    495         } else {
    496           lower = idx;
    497         }
    498       } /* while */
    499 
    500       if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) {
    501         quantOut[band] = lower - idxOffset;
    502       } else {
    503         quantOut[band] = upper - idxOffset;
    504       }
    505     } /* else reverse */
    506   }   /* for band */
    507 }
    508 
    509 static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands,
    510                               const FIXP_DBL *const quantTable,
    511                               const INT idxOffset, FIXP_DBL *const dequantOut) {
    512   int band;
    513 
    514   for (band = 0; band < nBands; band++) {
    515     dequantOut[band] = quantTable[input[band] + idxOffset];
    516   }
    517 }
    518 
    519 static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1,
    520                             const FIXP_DBL *const pPwr2, const INT scaleCh1,
    521                             const INT *const pbScaleCh1, const INT scaleCh2,
    522                             const INT *const pbScaleCh2, const int nParamBand) {
    523   INT i;
    524   FIXP_DBL ldPwr1, ldPwr2, cld;
    525   FIXP_DBL maxPwr = FL2FXCONST_DBL(
    526       30.0f /
    527       (1 << (LD_DATA_SHIFT +
    528              1))); /* consider SACENC_FLOAT_EPSILON in power calculation */
    529 
    530   for (i = 0; i < nParamBand; i++) {
    531     ldPwr1 =
    532         (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i])
    533                                        << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
    534     ldPwr2 =
    535         (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i])
    536                                        << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
    537 
    538     ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr);
    539     ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr);
    540 
    541     /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit
    542      * scale by fMultDiv2() */
    543     cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)),
    544                     ldPwr1 - ldPwr2);
    545 
    546     cld =
    547         fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2)));
    548     cld =
    549         fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2)));
    550     pCld[i] = cld << (LD_DATA_SHIFT + 2);
    551   }
    552 }
    553 
    554 FDK_SACENC_ERROR fdk_sacenc_applyTtoBox(
    555     HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot,
    556     const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK,
    557     const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx,
    558     UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx,
    559     UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1,
    560     INT *scaleCh2) {
    561   FDK_SACENC_ERROR error = SACENC_OK;
    562 
    563   C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    564   C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    565   C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    566   C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    567 
    568   C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    569   C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    570   C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS)
    571   C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS)
    572 
    573   if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) ||
    574       (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) ||
    575       (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) {
    576     error = SACENC_INVALID_HANDLE;
    577   } else {
    578     int j, pb;
    579     const int nParamBands = hTtoBox->nParameterBands;
    580     const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) ||
    581                         (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2);
    582 
    583     /* sanity check */
    584     if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) {
    585       error = SACENC_INVALID_CONFIG;
    586       goto bail;
    587     }
    588 
    589     int outScale;    /* scalefactor will not be evaluated */
    590     int inScale = 5; /* scale factor determined empirically */
    591 
    592     /* calculate the headroom of the hybrid data for each parameter band */
    593     FDKcalcPbScaleFactor(ppHybridData1__FDK,
    594                          hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1,
    595                          startTimeSlot, nTimeSlots, nParamBands);
    596     FDKcalcPbScaleFactor(ppHybridData2__FDK,
    597                          hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2,
    598                          startTimeSlot, nTimeSlots, nParamBands);
    599 
    600     for (j = 0, pb = 0; pb < nParamBands; pb++) {
    601       FIXP_DBL data1, data2;
    602       data1 = data2 = (FIXP_DBL)0;
    603       for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) {
    604         data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE,
    605                                    inScale + pbScaleCh1[pb], &outScale,
    606                                    startTimeSlot, nTimeSlots, j, j + 1);
    607         data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE,
    608                                    inScale + pbScaleCh2[pb], &outScale,
    609                                    startTimeSlot, nTimeSlots, j, j + 1);
    610       } /* for j */
    611       powerHybridData1__FDK[pb] = data1;
    612       powerHybridData2__FDK[pb] = data2;
    613     } /* pb */
    614 
    615     {
    616       for (j = 0, pb = 0; pb < nParamBands; pb++) {
    617         FIXP_DBL dataReal, dataImag;
    618         dataReal = dataImag = (FIXP_DBL)0;
    619         for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) {
    620           FIXP_DPK scalarProd;
    621           cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK,
    622                                  ppHybridData2__FDK, inScale + pbScaleCh1[pb],
    623                                  inScale + pbScaleCh2[pb], &outScale,
    624                                  startTimeSlot, nTimeSlots, j, j + 1);
    625           dataReal += scalarProd.v.re;
    626           if (hTtoBox->pSubbandImagSign[j] < 0) {
    627             dataImag -= scalarProd.v.im;
    628           } else {
    629             dataImag += scalarProd.v.im;
    630           }
    631         } /* for j */
    632         prodHybridDataReal__FDK[pb] = dataReal;
    633         prodHybridDataImag__FDK[pb] = dataImag;
    634       } /* pb */
    635 
    636       if (SACENC_OK != (error = calculateIccFDK(
    637                             nParamBands, hTtoBox->iccCorrelationCoherenceBorder,
    638                             powerHybridData1__FDK, powerHybridData2__FDK,
    639                             prodHybridDataReal__FDK, prodHybridDataImag__FDK,
    640                             hTtoBox->pIcc__FDK))) {
    641         goto bail;
    642       }
    643 
    644       /* calculate correlation based Icc for downmix */
    645       if (SACENC_OK != (error = calculateIccFDK(
    646                             nParamBands, nParamBands, powerHybridData1__FDK,
    647                             powerHybridData2__FDK, prodHybridDataReal__FDK,
    648                             prodHybridDataImag__FDK, IccDownmix__FDK))) {
    649         goto bail;
    650       }
    651     }
    652 
    653     if (!bUseEbQ) {
    654       CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK,
    655                       powerHybridData2__FDK, *scaleCh1 + inScale + 1,
    656                       pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2,
    657                       nParamBands);
    658     }
    659 
    660     if (bUseBBCues) {
    661       ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands);
    662 
    663       { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); }
    664 
    665     } /* bUseBBCues */
    666 
    667     /* quantize/de-quantize icc */
    668     {
    669       QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands,
    670                       hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
    671                       hTtoBox->nIccQuantSteps, pIccIdx);
    672       QuantizeCoefFDK(IccDownmix__FDK, nParamBands,
    673                       hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
    674                       hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx);
    675       deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands,
    676                         hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
    677                         IccDownmixQuant__FDK);
    678 
    679       *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc;
    680     }
    681 
    682     /* quantize/de-quantize cld */
    683     if (!bUseEbQ) {
    684       QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands,
    685                       hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset,
    686                       hTtoBox->nCldQuantSteps, pCldIdx);
    687       deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK,
    688                         hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK);
    689     } else {
    690       FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR));
    691     }
    692     *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld;
    693 
    694   } /* valid handle */
    695 
    696 bail:
    697   C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS)
    698   C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS)
    699   C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    700   C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    701 
    702   C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    703   C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    704   C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    705   C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
    706 
    707   return error;
    708 }
    709 
    710 INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig,
    711                                  const INT nSubband) {
    712   INT nParamBand = -1;
    713   const UCHAR *pSubband2ParameterIndex =
    714       getSubband2ParameterIndex(boxSubbandConfig);
    715 
    716   if (pSubband2ParameterIndex != NULL) {
    717     const int hybrid_resolution = 64;
    718 
    719     if ((nSubband > -1) && (nSubband < hybrid_resolution)) {
    720       nParamBand = pSubband2ParameterIndex[nSubband];
    721     }
    722   }
    723 
    724   return nParamBand;
    725 }
    726