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 /**************************** SBR encoder library ******************************
     96 
     97    Author(s):
     98 
     99    Description:
    100 
    101 *******************************************************************************/
    102 
    103 #include "invf_est.h"
    104 #include "sbr_misc.h"
    105 
    106 #include "genericStds.h"
    107 
    108 #define MAX_NUM_REGIONS 10
    109 #define SCALE_FAC_QUO 512.0f
    110 #define SCALE_FAC_NRG 256.0f
    111 
    112 #ifndef min
    113 #define min(a, b) (a < b ? a : b)
    114 #endif
    115 
    116 #ifndef max
    117 #define max(a, b) (a > b ? a : b)
    118 #endif
    119 
    120 static const FIXP_DBL quantStepsSbr[4] = {
    121     0x00400000, 0x02800000, 0x03800000,
    122     0x04c00000}; /* table scaled with SCALE_FAC_QUO */
    123 static const FIXP_DBL quantStepsOrig[4] = {
    124     0x00000000, 0x00c00000, 0x01c00000,
    125     0x02800000}; /* table scaled with SCALE_FAC_QUO */
    126 static const FIXP_DBL nrgBorders[4] = {
    127     0x0c800000, 0x0f000000, 0x11800000,
    128     0x14000000}; /* table scaled with SCALE_FAC_NRG */
    129 
    130 static const DETECTOR_PARAMETERS detectorParamsAAC = {
    131     quantStepsSbr,
    132     quantStepsOrig,
    133     nrgBorders,
    134     4, /* Number of borders SBR. */
    135     4, /* Number of borders orig. */
    136     4, /* Number of borders Nrg. */
    137     {
    138         /* Region space. */
    139         {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF,
    140          INVF_OFF}, /*    |      */
    141         {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF,
    142          INVF_OFF}, /*    |      */
    143         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    144          INVF_OFF}, /* regionSbr */
    145         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    146          INVF_OFF}, /*    |      */
    147         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    148          INVF_OFF} /*    |      */
    149     }, /*------------------------ regionOrig ---------------------------------*/
    150     {
    151         /* Region space transient. */
    152         {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    153          INVF_OFF}, /*    |      */
    154         {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    155          INVF_OFF}, /*    |      */
    156         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    157          INVF_OFF}, /* regionSbr */
    158         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    159          INVF_OFF}, /*    |      */
    160         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    161          INVF_OFF} /*    |      */
    162     }, /*------------------------ regionOrig ---------------------------------*/
    163     {-4, -3, -2, -1,
    164      0} /* Reduction factor of the inverse filtering for low energies.*/
    165 };
    166 
    167 static const FIXP_DBL hysteresis =
    168     0x00400000; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */
    169 
    170 /*
    171  * AAC+SBR PARAMETERS for Speech
    172  *********************************/
    173 static const DETECTOR_PARAMETERS detectorParamsAACSpeech = {
    174     quantStepsSbr,
    175     quantStepsOrig,
    176     nrgBorders,
    177     4, /* Number of borders SBR. */
    178     4, /* Number of borders orig. */
    179     4, /* Number of borders Nrg. */
    180     {
    181         /* Region space. */
    182         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    183          INVF_OFF}, /*    |      */
    184         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    185          INVF_OFF}, /*    |      */
    186         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    187          INVF_OFF}, /* regionSbr */
    188         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    189          INVF_OFF}, /*    |      */
    190         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    191          INVF_OFF} /*    |      */
    192     }, /*------------------------ regionOrig ---------------------------------*/
    193     {
    194         /* Region space transient. */
    195         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    196          INVF_OFF}, /*    |      */
    197         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
    198          INVF_OFF}, /*    |      */
    199         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    200          INVF_OFF}, /* regionSbr */
    201         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    202          INVF_OFF}, /*    |      */
    203         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
    204          INVF_OFF} /*    |      */
    205     }, /*------------------------ regionOrig ---------------------------------*/
    206     {-4, -3, -2, -1,
    207      0} /* Reduction factor of the inverse filtering for low energies.*/
    208 };
    209 
    210 /*
    211  * Smoothing filters.
    212  ************************/
    213 typedef const FIXP_DBL FIR_FILTER[5];
    214 
    215 static const FIR_FILTER fir_0 = {0x7fffffff, 0x00000000, 0x00000000, 0x00000000,
    216                                  0x00000000};
    217 static const FIR_FILTER fir_1 = {0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000,
    218                                  0x00000000};
    219 static const FIR_FILTER fir_2 = {0x10000000, 0x30000000, 0x40000000, 0x00000000,
    220                                  0x00000000};
    221 static const FIR_FILTER fir_3 = {0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340,
    222                                  0x00000000};
    223 static const FIR_FILTER fir_4 = {0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0,
    224                                  0x2aaaaa80};
    225 
    226 static const FIR_FILTER *const fir_table[5] = {&fir_0, &fir_1, &fir_2, &fir_3,
    227                                                &fir_4};
    228 
    229 /**************************************************************************/
    230 /*!
    231   \brief     Calculates the values used for the detector.
    232 
    233 
    234   \return    none
    235 
    236 */
    237 /**************************************************************************/
    238 static void calculateDetectorValues(
    239     FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the
    240                                    original. */
    241     SCHAR *indexVector,         /*!< Index vector to obtain the patched data. */
    242     FIXP_DBL *nrgVector,        /*!< Energy vector. */
    243     DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */
    244     INT startChannel,                /*!< Start channel. */
    245     INT stopChannel,                 /*!< Stop channel. */
    246     INT startIndex,                  /*!< Start index. */
    247     INT stopIndex,                   /*!< Stop index. */
    248     INT numberOfStrongest /*!< The number of sorted tonal components to be
    249                              considered. */
    250 ) {
    251   INT i, temp, j;
    252 
    253   const FIXP_DBL *filter = *fir_table[INVF_SMOOTHING_LENGTH];
    254   FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest;
    255   FIXP_DBL origQuota, sbrQuota;
    256   FIXP_DBL invIndex, invChannel, invTemp;
    257   FIXP_DBL quotaVecOrig[64], quotaVecSbr[64];
    258 
    259   FDKmemclear(quotaVecOrig, 64 * sizeof(FIXP_DBL));
    260   FDKmemclear(quotaVecSbr, 64 * sizeof(FIXP_DBL));
    261 
    262   invIndex = GetInvInt(stopIndex - startIndex);
    263   invChannel = GetInvInt(stopChannel - startChannel);
    264 
    265   /*
    266    Calculate the mean value, over the current time segment, for the original,
    267    the HFR and the difference, over all channels in the current frequency range.
    268    NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION).
    269    */
    270 
    271   /* The original, the sbr signal and the total energy */
    272   detectorValues->avgNrg = FL2FXCONST_DBL(0.0f);
    273   for (j = startIndex; j < stopIndex; j++) {
    274     for (i = startChannel; i < stopChannel; i++) {
    275       quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex);
    276 
    277       if (indexVector[i] != -1)
    278         quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex);
    279     }
    280     detectorValues->avgNrg += fMult(nrgVector[j], invIndex);
    281   }
    282 
    283   /*
    284    Calculate the mean value, over the current frequency range, for the original,
    285    the HFR and the difference. Also calculate the same mean values for the three
    286    vectors, but only includeing the x strongest copmponents.
    287    */
    288 
    289   origQuota = FL2FXCONST_DBL(0.0f);
    290   sbrQuota = FL2FXCONST_DBL(0.0f);
    291   for (i = startChannel; i < stopChannel; i++) {
    292     origQuota += fMultDiv2(quotaVecOrig[i], invChannel);
    293     sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel);
    294   }
    295 
    296   /*
    297    Calculate the mean value for the x strongest components
    298   */
    299   FDKsbrEnc_Shellsort_fract(quotaVecOrig + startChannel,
    300                             stopChannel - startChannel);
    301   FDKsbrEnc_Shellsort_fract(quotaVecSbr + startChannel,
    302                             stopChannel - startChannel);
    303 
    304   origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
    305   sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
    306 
    307   temp = min(stopChannel - startChannel, numberOfStrongest);
    308   invTemp = GetInvInt(temp);
    309 
    310   for (i = 0; i < temp; i++) {
    311     origQuotaMeanStrongest +=
    312         fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp);
    313     sbrQuotaMeanStrongest +=
    314         fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp);
    315   }
    316 
    317   /*
    318    The value for the strongest component
    319   */
    320   detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1];
    321   detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1];
    322 
    323   /*
    324    Buffer values
    325   */
    326   FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1,
    327              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
    328   FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1,
    329              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
    330   FDKmemmove(detectorValues->origQuotaMeanStrongest,
    331              detectorValues->origQuotaMeanStrongest + 1,
    332              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
    333   FDKmemmove(detectorValues->sbrQuotaMeanStrongest,
    334              detectorValues->sbrQuotaMeanStrongest + 1,
    335              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
    336 
    337   detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota << 1;
    338   detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota << 1;
    339   detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] =
    340       origQuotaMeanStrongest << 1;
    341   detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] =
    342       sbrQuotaMeanStrongest << 1;
    343 
    344   /*
    345    Filter values
    346   */
    347   detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
    348   detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
    349   detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
    350   detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
    351 
    352   for (i = 0; i < INVF_SMOOTHING_LENGTH + 1; i++) {
    353     detectorValues->origQuotaMeanFilt +=
    354         fMult(detectorValues->origQuotaMean[i], filter[i]);
    355     detectorValues->sbrQuotaMeanFilt +=
    356         fMult(detectorValues->sbrQuotaMean[i], filter[i]);
    357     detectorValues->origQuotaMeanStrongestFilt +=
    358         fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]);
    359     detectorValues->sbrQuotaMeanStrongestFilt +=
    360         fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]);
    361   }
    362 }
    363 
    364 /**************************************************************************/
    365 /*!
    366   \brief     Returns the region in which the input value belongs.
    367 
    368 
    369 
    370   \return    region.
    371 
    372 */
    373 /**************************************************************************/
    374 static INT findRegion(
    375     FIXP_DBL currVal,        /*!< The current value. */
    376     const FIXP_DBL *borders, /*!< The border of the regions. */
    377     const INT numBorders     /*!< The number of borders. */
    378 ) {
    379   INT i;
    380 
    381   if (currVal < borders[0]) {
    382     return 0;
    383   }
    384 
    385   for (i = 1; i < numBorders; i++) {
    386     if (currVal >= borders[i - 1] && currVal < borders[i]) {
    387       return i;
    388     }
    389   }
    390 
    391   if (currVal >= borders[numBorders - 1]) {
    392     return numBorders;
    393   }
    394 
    395   return 0; /* We never get here, it's just to avoid compiler warnings.*/
    396 }
    397 
    398 /**************************************************************************/
    399 /*!
    400   \brief     Makes a clever decision based on the quota vector.
    401 
    402 
    403   \return     decision on which invf mode to use
    404 
    405 */
    406 /**************************************************************************/
    407 static INVF_MODE decisionAlgorithm(
    408     const DETECTOR_PARAMETERS
    409         *detectorParams, /*!< Struct with the detector parameters. */
    410     DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */
    411     INT transientFlag,  /*!< Flag indicating if there is a transient present.*/
    412     INT *prevRegionSbr, /*!< The previous region in which the Sbr value was. */
    413     INT *prevRegionOrig /*!< The previous region in which the Orig value was. */
    414 ) {
    415   INT invFiltLevel, regionSbr, regionOrig, regionNrg;
    416 
    417   /*
    418    Current thresholds.
    419    */
    420   const INT numRegionsSbr = detectorParams->numRegionsSbr;
    421   const INT numRegionsOrig = detectorParams->numRegionsOrig;
    422   const INT numRegionsNrg = detectorParams->numRegionsNrg;
    423 
    424   FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS];
    425   FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS];
    426 
    427   /*
    428    Current detector values.
    429    */
    430   FIXP_DBL origQuotaMeanFilt;
    431   FIXP_DBL sbrQuotaMeanFilt;
    432   FIXP_DBL nrg;
    433 
    434   /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 =
    435    * log(16)/64.0; 0.6875 = 44/64.0 */
    436   origQuotaMeanFilt =
    437       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
    438                  (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,
    439                                            (FIXP_DBL)1)) +
    440                             FL2FXCONST_DBL(0.31143075889f))))
    441       << 0; /* scaled by 1/2^9 */
    442   sbrQuotaMeanFilt =
    443       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
    444                  (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,
    445                                            (FIXP_DBL)1)) +
    446                             FL2FXCONST_DBL(0.31143075889f))))
    447       << 0; /* scaled by 1/2^9 */
    448   /* If energy is zero then we will get different results for different word
    449    * lengths. */
    450   nrg =
    451       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
    452                  (FIXP_DBL)(CalcLdData(detectorValues->avgNrg + (FIXP_DBL)1) +
    453                             FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f))))
    454       << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */
    455 
    456   FDKmemcpy(quantStepsSbrTmp, detectorParams->quantStepsSbr,
    457             numRegionsSbr * sizeof(FIXP_DBL));
    458   FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig,
    459             numRegionsOrig * sizeof(FIXP_DBL));
    460 
    461   if (*prevRegionSbr < numRegionsSbr)
    462     quantStepsSbrTmp[*prevRegionSbr] =
    463         detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis;
    464   if (*prevRegionSbr > 0)
    465     quantStepsSbrTmp[*prevRegionSbr - 1] =
    466         detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis;
    467 
    468   if (*prevRegionOrig < numRegionsOrig)
    469     quantStepsOrigTmp[*prevRegionOrig] =
    470         detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis;
    471   if (*prevRegionOrig > 0)
    472     quantStepsOrigTmp[*prevRegionOrig - 1] =
    473         detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis;
    474 
    475   regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr);
    476   regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig);
    477   regionNrg = findRegion(nrg, detectorParams->nrgBorders, numRegionsNrg);
    478 
    479   *prevRegionSbr = regionSbr;
    480   *prevRegionOrig = regionOrig;
    481 
    482   /* Use different settings if a transient is present*/
    483   invFiltLevel =
    484       (transientFlag == 1)
    485           ? detectorParams->regionSpaceTransient[regionSbr][regionOrig]
    486           : detectorParams->regionSpace[regionSbr][regionOrig];
    487 
    488   /* Compensate for low energy.*/
    489   invFiltLevel =
    490       max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg], 0);
    491 
    492   return (INVF_MODE)(invFiltLevel);
    493 }
    494 
    495 /**************************************************************************/
    496 /*!
    497   \brief     Estiamtion of the inverse filtering level required
    498              in the decoder.
    499 
    500    A second order LPC is calculated for every filterbank channel, using
    501    the covariance method. THe ratio between the energy of the predicted
    502    signal and the energy of the non-predictable signal is calcualted.
    503 
    504   \return    none.
    505 
    506 */
    507 /**************************************************************************/
    508 void FDKsbrEnc_qmfInverseFilteringDetector(
    509     HANDLE_SBR_INV_FILT_EST
    510         hInvFilt,           /*!< Handle to the SBR_INV_FILT_EST struct. */
    511     FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the
    512                                original. */
    513     FIXP_DBL *nrgVector,    /*!< The energy vector. */
    514     SCHAR *indexVector,     /*!< Index vector to obtain the patched data. */
    515     INT startIndex,         /*!< Start index. */
    516     INT stopIndex,          /*!< Stop index. */
    517     INT transientFlag, /*!< Flag indicating if a transient is present or not.*/
    518     INVF_MODE *infVec  /*!< Vector holding the inverse filtering levels. */
    519 ) {
    520   INT band;
    521 
    522   /*
    523    * Do the inverse filtering level estimation.
    524    *****************************************************/
    525   for (band = 0; band < hInvFilt->noDetectorBands; band++) {
    526     INT startChannel = hInvFilt->freqBandTableInvFilt[band];
    527     INT stopChannel = hInvFilt->freqBandTableInvFilt[band + 1];
    528 
    529     calculateDetectorValues(quotaMatrix, indexVector, nrgVector,
    530                             &hInvFilt->detectorValues[band], startChannel,
    531                             stopChannel, startIndex, stopIndex,
    532                             hInvFilt->numberOfStrongest);
    533 
    534     infVec[band] = decisionAlgorithm(
    535         hInvFilt->detectorParams, &hInvFilt->detectorValues[band],
    536         transientFlag, &hInvFilt->prevRegionSbr[band],
    537         &hInvFilt->prevRegionOrig[band]);
    538   }
    539 }
    540 
    541 /**************************************************************************/
    542 /*!
    543   \brief     Initialize an instance of the inverse filtering level estimator.
    544 
    545 
    546   \return   errorCode, noError if successful.
    547 
    548 */
    549 /**************************************************************************/
    550 INT FDKsbrEnc_initInvFiltDetector(
    551     HANDLE_SBR_INV_FILT_EST
    552         hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */
    553     INT *freqBandTableDetector, /*!< Frequency band table for the inverse
    554                                    filtering. */
    555     INT numDetectorBands,       /*!< Number of inverse filtering bands. */
    556     UINT
    557         useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/
    558 ) {
    559   INT i;
    560 
    561   FDKmemclear(hInvFilt, sizeof(SBR_INV_FILT_EST));
    562 
    563   hInvFilt->detectorParams =
    564       (useSpeechConfig) ? &detectorParamsAACSpeech : &detectorParamsAAC;
    565 
    566   hInvFilt->noDetectorBandsMax = numDetectorBands;
    567 
    568   /*
    569      Memory initialisation
    570   */
    571   for (i = 0; i < hInvFilt->noDetectorBandsMax; i++) {
    572     FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES));
    573     hInvFilt->prevInvfMode[i] = INVF_OFF;
    574     hInvFilt->prevRegionOrig[i] = 0;
    575     hInvFilt->prevRegionSbr[i] = 0;
    576   }
    577 
    578   /*
    579   Reset the inverse fltering detector.
    580   */
    581   FDKsbrEnc_resetInvFiltDetector(hInvFilt, freqBandTableDetector,
    582                                  hInvFilt->noDetectorBandsMax);
    583 
    584   return (0);
    585 }
    586 
    587 /**************************************************************************/
    588 /*!
    589   \brief     resets sbr inverse filtering structure.
    590 
    591 
    592 
    593   \return   errorCode, noError if successful.
    594 
    595 */
    596 /**************************************************************************/
    597 INT FDKsbrEnc_resetInvFiltDetector(
    598     HANDLE_SBR_INV_FILT_EST
    599         hInvFilt,               /*!< Handle to the SBR_INV_FILT_EST struct. */
    600     INT *freqBandTableDetector, /*!< Frequency band table for the inverse
    601                                    filtering. */
    602     INT numDetectorBands)       /*!< Number of inverse filtering bands. */
    603 {
    604   hInvFilt->numberOfStrongest = 1;
    605   FDKmemcpy(hInvFilt->freqBandTableInvFilt, freqBandTableDetector,
    606             (numDetectorBands + 1) * sizeof(INT));
    607   hInvFilt->noDetectorBands = numDetectorBands;
    608 
    609   return (0);
    610 }
    611