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):   Max Neuendorf
     98 
     99    Description: Encoder Library Interface
    100                 Tree Structure for Space Encoder
    101 
    102 *******************************************************************************/
    103 
    104 /* Includes ******************************************************************/
    105 #include "sacenc_tree.h"
    106 #include "genericStds.h"
    107 #include "sacenc_const.h"
    108 #include "sacenc_paramextract.h"
    109 #include "sacenc_framewindowing.h"
    110 #include "FDK_matrixCalloc.h"
    111 
    112 /* Defines *******************************************************************/
    113 enum { BOX_0 = 0, BOX_1 = 1 };
    114 
    115 enum { CH_L = 0, CH_R = 1 };
    116 
    117 enum { TTO_CH_0 = 0, TTO_CH_1 = 1 };
    118 
    119 enum { WIN_INACTIV = 0, WIN_ACTIV = 1 };
    120 
    121 enum { MAX_KEEP_FRAMECOUNT = 100 };
    122 
    123 /* Data Types ****************************************************************/
    124 struct SPACE_TREE {
    125   SPACETREE_MODE mode;
    126   SPACE_TREE_DESCRIPTION descr;
    127   HANDLE_TTO_BOX ttoBox[SACENC_MAX_NUM_BOXES];
    128   UCHAR nParamBands;
    129   UCHAR bUseCoarseQuantTtoIcc;
    130   UCHAR bUseCoarseQuantTtoCld;
    131   QUANTMODE quantMode;
    132   INT frameCount;
    133   UCHAR bFrameKeep;
    134 
    135   /* Intermediate buffers */
    136   UCHAR pCld_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS];
    137   UCHAR pIcc_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS];
    138 
    139   UCHAR nChannelsInMax;
    140   UCHAR nHybridBandsMax;
    141 };
    142 
    143 typedef struct {
    144   UCHAR boxId;
    145   UCHAR inCh1;
    146   UCHAR inCh2;
    147   UCHAR inCh3;
    148   UCHAR inCh4;
    149   UCHAR wCh1;
    150   UCHAR wCh2;
    151 
    152 } TTO_DESCRIPTOR;
    153 
    154 typedef struct {
    155   SPACETREE_MODE mode;
    156   SPACE_TREE_DESCRIPTION treeDescription;
    157 
    158 } TREE_CONFIG;
    159 
    160 typedef struct {
    161   SPACETREE_MODE mode;
    162   UCHAR nChannelsIn;
    163   UCHAR nChannelsOut;
    164   UCHAR nTtoBoxes;
    165   TTO_DESCRIPTOR tto_descriptor[1];
    166 
    167 } TREE_SETUP;
    168 
    169 /* Constants *****************************************************************/
    170 static const TREE_CONFIG treeConfigTable[] = {
    171     {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}};
    172 
    173 static const TREE_SETUP treeSetupTable[] = {
    174     {SPACETREE_INVALID_MODE, 0, 0, 0, {{0, 0, 0, 0, 0, 0, 0}}},
    175     {SPACETREE_212,
    176      2,
    177      1,
    178      1,
    179      {{BOX_0, CH_L, CH_R, TTO_CH_0, TTO_CH_1, WIN_ACTIV, WIN_ACTIV}}}};
    180 
    181 /* Function / Class Declarations *********************************************/
    182 
    183 /* Function / Class Definition ***********************************************/
    184 static FDK_SACENC_ERROR getTreeConfig(
    185     const SPACETREE_MODE mode, SPACE_TREE_DESCRIPTION *pTreeDescription) {
    186   FDK_SACENC_ERROR error = SACENC_INIT_ERROR;
    187 
    188   if (pTreeDescription == NULL) {
    189     error = SACENC_INVALID_HANDLE;
    190   } else {
    191     int i;
    192     for (i = 0; i < (int)(sizeof(treeConfigTable) / sizeof(TREE_CONFIG)); i++) {
    193       if (treeConfigTable[i].mode == mode) {
    194         *pTreeDescription = treeConfigTable[i].treeDescription;
    195         error = SACENC_OK;
    196         break;
    197       }
    198     }
    199   } /* valid handle */
    200   return error;
    201 }
    202 
    203 static const TREE_SETUP *getTreeSetup(const SPACETREE_MODE mode) {
    204   int i;
    205   const TREE_SETUP *setup = NULL;
    206 
    207   for (i = 0; i < (int)(sizeof(treeSetupTable) / sizeof(TREE_SETUP)); i++) {
    208     if (treeSetupTable[i].mode == mode) {
    209       setup = &treeSetupTable[i];
    210       break;
    211     }
    212   }
    213   return setup;
    214 }
    215 
    216 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree) {
    217   FDK_SACENC_ERROR error = SACENC_OK;
    218   HANDLE_SPACE_TREE hSpaceTree = NULL;
    219 
    220   if (NULL == phSpaceTree) {
    221     error = SACENC_INVALID_HANDLE;
    222   } else {
    223     int box;
    224 
    225     FDK_ALLOCATE_MEMORY_1D(hSpaceTree, 1, struct SPACE_TREE);
    226 
    227     for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) {
    228       HANDLE_TTO_BOX ttoBox = NULL;
    229       if (SACENC_OK != (error = fdk_sacenc_createTtoBox(&ttoBox))) {
    230         goto bail;
    231       }
    232       if (NULL != hSpaceTree) {
    233         hSpaceTree->ttoBox[box] = ttoBox;
    234       }
    235     }
    236     *phSpaceTree = hSpaceTree;
    237   }
    238   return error;
    239 
    240 bail:
    241   fdk_sacenc_spaceTree_Close(&hSpaceTree);
    242   return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
    243 }
    244 
    245 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init(
    246     HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup,
    247     UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep) {
    248   FDK_SACENC_ERROR error = SACENC_OK;
    249 
    250   if ((hST == NULL) || (hSetup == NULL)) {
    251     error = SACENC_INVALID_HANDLE;
    252   } else {
    253     int bTtoBoxFrontBackCombin[SACENC_MAX_NUM_BOXES] = {0};
    254     int box = 0;
    255 
    256     hST->frameCount = 0;
    257     hST->bFrameKeep = bFrameKeep;
    258 
    259     /* Init */
    260     hST->mode = hSetup->mode;
    261     hST->nParamBands = hSetup->nParamBands;
    262     hST->bUseCoarseQuantTtoIcc = hSetup->bUseCoarseQuantTtoIcc;
    263     hST->bUseCoarseQuantTtoCld = hSetup->bUseCoarseQuantTtoCld;
    264     hST->quantMode = hSetup->quantMode;
    265     hST->nChannelsInMax = hSetup->nChannelsInMax;
    266     hST->nHybridBandsMax = hSetup->nHybridBandsMax;
    267 
    268     if (SACENC_OK != (error = getTreeConfig(hST->mode, &hST->descr))) {
    269       goto bail;
    270     }
    271 
    272     switch (hST->mode) {
    273       case SPACETREE_212:
    274         bTtoBoxFrontBackCombin[BOX_0] = 0;
    275         break;
    276       case SPACETREE_INVALID_MODE:
    277       default:
    278         error = SACENC_INIT_ERROR;
    279         goto bail;
    280     } /* switch (hST->mode) */
    281 
    282     if (hST->descr.nOttBoxes > SACENC_MAX_NUM_BOXES) {
    283       error = SACENC_INIT_ERROR;
    284       goto bail;
    285     }
    286 
    287     for (box = 0; box < hST->descr.nOttBoxes; box++) {
    288       TTO_BOX_CONFIG boxConfig;
    289       boxConfig.subbandConfig = (BOX_SUBBAND_CONFIG)hST->nParamBands;
    290       boxConfig.bUseCoarseQuantCld = hST->bUseCoarseQuantTtoCld;
    291       boxConfig.bUseCoarseQuantIcc = hST->bUseCoarseQuantTtoIcc;
    292       boxConfig.bUseCoherenceIccOnly = bTtoBoxFrontBackCombin[box];
    293       boxConfig.boxQuantMode = (BOX_QUANTMODE)hST->quantMode;
    294       boxConfig.nHybridBandsMax = hST->nHybridBandsMax;
    295       boxConfig.bFrameKeep = hST->bFrameKeep;
    296 
    297       if (SACENC_OK !=
    298           (error = fdk_sacenc_initTtoBox(hST->ttoBox[box], &boxConfig,
    299                                          pParameterBand2HybridBandOffset))) {
    300         goto bail;
    301       }
    302     } /* for box */
    303 
    304   } /* valid handle */
    305 
    306 bail:
    307   return error;
    308 }
    309 
    310 static void SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST,
    311                                    SPATIALFRAME *const hSTOut,
    312                                    const INT avoid_keep) {
    313   int pb;
    314 
    315   if (avoid_keep == 0) {
    316     if (hST->frameCount % 2 == 0) {
    317       for (pb = 0; pb < hST->nParamBands; pb++) {
    318         hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb];
    319         hSTOut->ottData.cld[BOX_0][0][pb] = hST->pCld_prev[BOX_0][pb];
    320       }
    321     } else {
    322       for (pb = 0; pb < hST->nParamBands; pb++) {
    323         hSTOut->ottData.icc[BOX_0][0][pb] = hST->pIcc_prev[BOX_0][pb];
    324         hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb];
    325       }
    326     }
    327   } else {
    328     for (pb = 0; pb < hST->nParamBands; pb++) {
    329       hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb];
    330       hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb];
    331     }
    332   }
    333   hST->frameCount++;
    334   if (hST->frameCount == MAX_KEEP_FRAMECOUNT) {
    335     hST->frameCount = 0;
    336   }
    337 }
    338 
    339 static FDK_SACENC_ERROR SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST,
    340                                             SPATIALFRAME *const hSTOut,
    341                                             const INT avoid_keep) {
    342   FDK_SACENC_ERROR error = SACENC_OK;
    343 
    344   switch (hST->mode) {
    345     case SPACETREE_212:
    346       SpaceTree_FrameKeep212(hST, hSTOut, avoid_keep);
    347       break;
    348     case SPACETREE_INVALID_MODE:
    349     default:
    350       error = SACENC_INVALID_CONFIG;
    351       break;
    352   }
    353   return error;
    354 }
    355 
    356 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply(
    357     HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn,
    358     const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands,
    359     FIXP_WIN *pFrameWindowAna__FDK,
    360     FIXP_DPK *const *const *const pppHybrid__FDK,
    361     FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut,
    362     const INT avoid_keep, INT *pEncoderInputChScale) {
    363   /** \verbatim
    364    =============================================================================================================================
    365       TREE_212
    366    =============================================================================================================================
    367                          _______
    368         L -- TTO_CH_0 --|       |
    369                         | TTO_0 |-- TTO_CH_0
    370         R -- TTO_CH_1 --|_______|
    371 
    372   \endverbatim */
    373 
    374   FDK_SACENC_ERROR error = SACENC_OK;
    375   int k;
    376   const TREE_SETUP *treeSetup = NULL;
    377 
    378   if ((hST == NULL) || (hSTOut == NULL) || (pppHybrid__FDK == NULL) ||
    379       (pppHybridIn__FDK == NULL)) {
    380     error = SACENC_INVALID_HANDLE;
    381     goto bail;
    382   }
    383 
    384   if ((treeSetup = getTreeSetup(hST->mode)) == NULL) {
    385     error = SACENC_INVALID_CONFIG;
    386     goto bail;
    387   }
    388 
    389   /* Sanity Checks */
    390   if ((nChannelsIn != treeSetup->nChannelsIn) ||
    391       (nChannelsIn > hST->nChannelsInMax) ||
    392       (nHybridBands > hST->nHybridBandsMax)) {
    393     error = SACENC_INVALID_CONFIG;
    394     goto bail;
    395   }
    396 
    397   /* Apply all TTO boxes. */
    398   for (k = 0; k < treeSetup->nTtoBoxes; k++) {
    399     const TTO_DESCRIPTOR *pTTO = &treeSetup->tto_descriptor[k];
    400 
    401     int i, inCh[2], outCh[2], win[2];
    402 
    403     inCh[0] = pTTO->inCh1;
    404     outCh[0] = pTTO->inCh3;
    405     win[0] = pTTO->wCh1;
    406     inCh[1] = pTTO->inCh2;
    407     outCh[1] = pTTO->inCh4;
    408     win[1] = pTTO->wCh2;
    409 
    410     for (i = 0; i < 2; i++) {
    411       if (win[i] == WIN_ACTIV) {
    412         fdk_sacenc_analysisWindowing(
    413             nTimeSlots, startTimeSlot, pFrameWindowAna__FDK,
    414             pppHybrid__FDK[inCh[i]], pppHybridIn__FDK[outCh[i]], nHybridBands,
    415             FW_LEAVE_DIM);
    416       }
    417     }
    418 
    419     /* Calculate output downmix within last TTO box, if no TTT box is applied.
    420      */
    421     if (SACENC_OK !=
    422         (error = fdk_sacenc_applyTtoBox(
    423              hST->ttoBox[pTTO->boxId], nTimeSlots, startTimeSlot, nHybridBands,
    424              pppHybridIn__FDK[pTTO->inCh3], pppHybridIn__FDK[pTTO->inCh4],
    425              hSTOut->ottData.icc[pTTO->boxId][paramSet],
    426              &(hSTOut->ICCLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]),
    427              hSTOut->ottData.cld[pTTO->boxId][paramSet],
    428              &(hSTOut->CLDLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]),
    429              hSTOut->bUseBBCues, &pEncoderInputChScale[inCh[0]],
    430              &pEncoderInputChScale[inCh[1]]))) {
    431       goto bail;
    432     }
    433   }
    434 
    435   if (hST->bFrameKeep == 1) {
    436     if (SACENC_OK != (error = SpaceTree_FrameKeep(hST, hSTOut, avoid_keep))) {
    437       goto bail;
    438     }
    439   }
    440 
    441 bail:
    442   return error;
    443 }
    444 
    445 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree) {
    446   FDK_SACENC_ERROR error = SACENC_OK;
    447 
    448   if ((phSpaceTree == NULL) || (*phSpaceTree == NULL)) {
    449     error = SACENC_INVALID_HANDLE;
    450   } else {
    451     int box;
    452     HANDLE_SPACE_TREE const hST = *phSpaceTree;
    453 
    454     /* for (box = 0; box < hST->descr.nOttBoxes; ++box) { */
    455     for (box = 0; box < SACENC_MAX_NUM_BOXES; ++box) {
    456       if (SACENC_OK != (error = fdk_sacenc_destroyTtoBox(&hST->ttoBox[box]))) {
    457         goto bail;
    458       }
    459     }
    460 
    461     FDKfree(*phSpaceTree);
    462     *phSpaceTree = NULL;
    463   }
    464 bail:
    465   return error;
    466 }
    467 
    468 FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription(
    469     const HANDLE_SPACE_TREE hSpaceTree,
    470     SPACE_TREE_DESCRIPTION *pSpaceTreeDescription) {
    471   FDK_SACENC_ERROR error = SACENC_OK;
    472 
    473   if ((hSpaceTree == NULL) || (pSpaceTreeDescription == NULL)) {
    474     error = SACENC_INVALID_HANDLE;
    475   } else {
    476     *pSpaceTreeDescription = hSpaceTree->descr;
    477   }
    478   return error;
    479 }
    480 
    481 INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands,
    482                                           const INT nHybridBand) {
    483   return fdk_sacenc_subband2ParamBand((BOX_SUBBAND_CONFIG)nParamBands,
    484                                       nHybridBand);
    485 }
    486 
    487 /*****************************************************************************
    488 ******************************************************************************/
    489