Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 #include "invf_est.h"
     85 #include "sbr_misc.h"
     86 
     87 #include "genericStds.h"
     88 
     89 #define MAX_NUM_REGIONS 10
     90 #define SCALE_FAC_QUO   512.0f
     91 #define SCALE_FAC_NRG   256.0f
     92 
     93 #ifndef min
     94 #define min(a,b) ( a < b ? a:b)
     95 #endif
     96 
     97 #ifndef max
     98 #define max(a,b) ( a > b ? a:b)
     99 #endif
    100 
    101 static const FIXP_DBL quantStepsSbr[4]  =  { 0x00400000, 0x02800000, 0x03800000, 0x04c00000 } ;    /* table scaled with SCALE_FAC_QUO */
    102 static const FIXP_DBL quantStepsOrig[4] =  { 0x00000000, 0x00c00000, 0x01c00000, 0x02800000 } ;    /* table scaled with SCALE_FAC_QUO */
    103 static const FIXP_DBL nrgBorders[4]     =  { 0x0c800000, 0x0f000000, 0x11800000, 0x14000000 } ;    /* table scaled with SCALE_FAC_NRG */
    104 
    105 static const DETECTOR_PARAMETERS detectorParamsAAC = {
    106     quantStepsSbr,
    107     quantStepsOrig,
    108     nrgBorders,
    109     4,                              /* Number of borders SBR. */
    110     4,                              /* Number of borders orig. */
    111     4,                              /* Number of borders Nrg. */
    112     {                               /* Region space. */
    113       {INVF_MID_LEVEL,   INVF_LOW_LEVEL,  INVF_OFF,        INVF_OFF, INVF_OFF}, /*    |      */
    114       {INVF_MID_LEVEL,   INVF_LOW_LEVEL,  INVF_OFF,        INVF_OFF, INVF_OFF}, /*    |      */
    115       {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
    116       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    117       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
    118     },/*------------------------ regionOrig ---------------------------------*/
    119     {                               /* Region space transient. */
    120       {INVF_LOW_LEVEL,   INVF_LOW_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    121       {INVF_LOW_LEVEL,   INVF_LOW_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    122       {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
    123       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    124       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
    125     },/*------------------------ regionOrig ---------------------------------*/
    126     {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/
    127 };
    128 
    129 static const FIXP_DBL hysteresis = 0x00400000 ; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */
    130 
    131 /*
    132  * AAC+SBR PARAMETERS for Speech
    133  *********************************/
    134 static const DETECTOR_PARAMETERS detectorParamsAACSpeech = {
    135     quantStepsSbr,
    136     quantStepsOrig,
    137     nrgBorders,
    138     4,                              /* Number of borders SBR. */
    139     4,                              /* Number of borders orig. */
    140     4,                              /* Number of borders Nrg. */
    141     {                               /* Region space. */
    142       {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    143       {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    144       {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
    145       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    146       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
    147     },/*------------------------ regionOrig ---------------------------------*/
    148     {                               /* Region space transient. */
    149       {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    150       {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    151       {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
    152       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
    153       {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
    154     },/*------------------------ regionOrig ---------------------------------*/
    155     {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/
    156 };
    157 
    158 /*
    159  * Smoothing filters.
    160  ************************/
    161 typedef const FIXP_DBL FIR_FILTER[5];
    162 
    163 static const FIR_FILTER fir_0 = { 0x7fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } ;
    164 static const FIR_FILTER fir_1 = { 0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, 0x00000000 } ;
    165 static const FIR_FILTER fir_2 = { 0x10000000, 0x30000000, 0x40000000, 0x00000000, 0x00000000 } ;
    166 static const FIR_FILTER fir_3 = { 0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, 0x00000000 } ;
    167 static const FIR_FILTER fir_4 = { 0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, 0x2aaaaa80 } ;
    168 
    169 
    170 static const FIR_FILTER *const fir_table[5] = {
    171   &fir_0,
    172   &fir_1,
    173   &fir_2,
    174   &fir_3,
    175   &fir_4
    176 };
    177 
    178 /**************************************************************************/
    179 /*!
    180   \brief     Calculates the values used for the detector.
    181 
    182 
    183   \return    none
    184 
    185 */
    186 /**************************************************************************/
    187 static void
    188 calculateDetectorValues(FIXP_DBL **quotaMatrixOrig,       /*!< Matrix holding the tonality values of the original. */
    189                         SCHAR    *indexVector,            /*!< Index vector to obtain the patched data. */
    190                         FIXP_DBL *nrgVector,              /*!< Energy vector. */
    191                         DETECTOR_VALUES *detectorValues,  /*!< pointer to DETECTOR_VALUES struct. */
    192                         INT startChannel,                 /*!< Start channel. */
    193                         INT stopChannel,                  /*!< Stop channel. */
    194                         INT startIndex,                   /*!< Start index. */
    195                         INT stopIndex,                    /*!< Stop index. */
    196                         INT numberOfStrongest             /*!< The number of sorted tonal components to be considered. */
    197                         )
    198 {
    199   INT i,temp, j;
    200 
    201   const FIXP_DBL* filter = *fir_table[INVF_SMOOTHING_LENGTH];
    202   FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest;
    203   FIXP_DBL origQuota, sbrQuota;
    204   FIXP_DBL invIndex, invChannel, invTemp;
    205   FIXP_DBL quotaVecOrig[64], quotaVecSbr[64];
    206 
    207   FDKmemclear(quotaVecOrig,64*sizeof(FIXP_DBL));
    208   FDKmemclear(quotaVecSbr,64*sizeof(FIXP_DBL));
    209 
    210   invIndex = GetInvInt(stopIndex-startIndex);
    211   invChannel = GetInvInt(stopChannel-startChannel);
    212 
    213   /*
    214    Calculate the mean value, over the current time segment, for the original, the HFR
    215    and the difference, over all channels in the current frequency range.
    216    NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION).
    217    */
    218 
    219   /* The original, the sbr signal and the total energy */
    220   detectorValues->avgNrg = FL2FXCONST_DBL(0.0f);
    221   for(j=startIndex; j<stopIndex; j++) {
    222     for(i=startChannel; i<stopChannel; i++) {
    223       quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex);
    224 
    225       if(indexVector[i] != -1)
    226         quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex);
    227     }
    228     detectorValues->avgNrg += fMult(nrgVector[j], invIndex);
    229   }
    230 
    231   /*
    232    Calculate the mean value, over the current frequency range, for the original, the HFR
    233    and the difference. Also calculate the same mean values for the three vectors, but only
    234    includeing the x strongest copmponents.
    235    */
    236 
    237   origQuota = FL2FXCONST_DBL(0.0f);
    238   sbrQuota  = FL2FXCONST_DBL(0.0f);
    239   for(i=startChannel; i<stopChannel; i++) {
    240     origQuota += fMultDiv2(quotaVecOrig[i], invChannel);
    241     sbrQuota  += fMultDiv2(quotaVecSbr[i], invChannel);
    242   }
    243 
    244   /*
    245    Calculate the mean value for the x strongest components
    246   */
    247   FDKsbrEnc_Shellsort_fract(quotaVecOrig+startChannel,stopChannel-startChannel);
    248   FDKsbrEnc_Shellsort_fract(quotaVecSbr+startChannel,stopChannel-startChannel);
    249 
    250   origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
    251   sbrQuotaMeanStrongest  = FL2FXCONST_DBL(0.0f);
    252 
    253   temp = min(stopChannel - startChannel, numberOfStrongest);
    254   invTemp = GetInvInt(temp);
    255 
    256   for(i=0; i<temp; i++) {
    257     origQuotaMeanStrongest += fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp);
    258     sbrQuotaMeanStrongest  += fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp);
    259   }
    260 
    261   /*
    262    The value for the strongest component
    263   */
    264   detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1];
    265   detectorValues->sbrQuotaMax  = quotaVecSbr[stopChannel - 1];
    266 
    267   /*
    268    Buffer values
    269   */
    270   FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
    271   FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
    272   FDKmemmove(detectorValues->origQuotaMeanStrongest, detectorValues->origQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
    273   FDKmemmove(detectorValues->sbrQuotaMeanStrongest, detectorValues->sbrQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
    274 
    275   detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH]          = origQuota<<1;
    276   detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH]           = sbrQuota<<1;
    277   detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = origQuotaMeanStrongest<<1;
    278   detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH]  = sbrQuotaMeanStrongest<<1;
    279 
    280   /*
    281    Filter values
    282   */
    283   detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
    284   detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
    285   detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
    286   detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
    287 
    288   for(i=0;i<INVF_SMOOTHING_LENGTH+1;i++) {
    289     detectorValues->origQuotaMeanFilt += fMult(detectorValues->origQuotaMean[i], filter[i]);
    290     detectorValues->sbrQuotaMeanFilt  += fMult(detectorValues->sbrQuotaMean[i], filter[i]);
    291     detectorValues->origQuotaMeanStrongestFilt += fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]);
    292     detectorValues->sbrQuotaMeanStrongestFilt  += fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]);
    293   }
    294 }
    295 
    296 /**************************************************************************/
    297 /*!
    298   \brief     Returns the region in which the input value belongs.
    299 
    300 
    301 
    302   \return    region.
    303 
    304 */
    305 /**************************************************************************/
    306 static INT
    307 findRegion(FIXP_DBL currVal,        /*!< The current value. */
    308            const FIXP_DBL *borders, /*!< The border of the regions. */
    309            const INT numBorders     /*!< The number of borders. */
    310            )
    311 {
    312   INT i;
    313 
    314   if(currVal < borders[0]){
    315     return 0;
    316   }
    317 
    318   for(i = 1; i < numBorders; i++){
    319     if( currVal >= borders[i-1] && currVal < borders[i]){
    320       return i;
    321     }
    322   }
    323 
    324   if(currVal >= borders[numBorders-1]){
    325     return numBorders;
    326   }
    327 
    328   return 0;  /* We never get here, it's just to avoid compiler warnings.*/
    329 }
    330 
    331 /**************************************************************************/
    332 /*!
    333   \brief     Makes a clever decision based on the quota vector.
    334 
    335 
    336   \return     decision on which invf mode to use
    337 
    338 */
    339 /**************************************************************************/
    340 static INVF_MODE
    341 decisionAlgorithm(const DETECTOR_PARAMETERS *detectorParams,     /*!< Struct with the detector parameters. */
    342                   DETECTOR_VALUES *detectorValues,               /*!< Struct with the detector values. */
    343                   INT transientFlag,                             /*!< Flag indicating if there is a transient present.*/
    344                   INT* prevRegionSbr,                            /*!< The previous region in which the Sbr value was. */
    345                   INT* prevRegionOrig                            /*!< The previous region in which the Orig value was. */
    346                   )
    347 {
    348   INT invFiltLevel, regionSbr, regionOrig, regionNrg;
    349 
    350   /*
    351    Current thresholds.
    352    */
    353   const FIXP_DBL *quantStepsSbr  = detectorParams->quantStepsSbr;
    354   const FIXP_DBL *quantStepsOrig = detectorParams->quantStepsOrig;
    355   const FIXP_DBL *nrgBorders     = detectorParams->nrgBorders;
    356   const INT numRegionsSbr     = detectorParams->numRegionsSbr;
    357   const INT numRegionsOrig    = detectorParams->numRegionsOrig;
    358   const INT numRegionsNrg     = detectorParams->numRegionsNrg;
    359 
    360   FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS];
    361   FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS];
    362 
    363   /*
    364    Current detector values.
    365    */
    366   FIXP_DBL origQuotaMeanFilt;
    367   FIXP_DBL sbrQuotaMeanFilt;
    368   FIXP_DBL nrg;
    369 
    370   /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = log(16)/64.0; 0.6875 = 44/64.0 */
    371   origQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0;  /* scaled by 1/2^9 */
    372   sbrQuotaMeanFilt  = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0;   /* scaled by 1/2^9 */
    373   /* If energy is zero then we will get different results for different word lengths. */
    374   nrg               = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(detectorValues->avgNrg+(FIXP_DBL)1) + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) << 0;     /* scaled by 1/2^8; 2^44 -> qmf energy scale */
    375 
    376   FDKmemcpy(quantStepsSbrTmp,quantStepsSbr,numRegionsSbr*sizeof(FIXP_DBL));
    377   FDKmemcpy(quantStepsOrigTmp,quantStepsOrig,numRegionsOrig*sizeof(FIXP_DBL));
    378 
    379   if(*prevRegionSbr < numRegionsSbr)
    380     quantStepsSbrTmp[*prevRegionSbr] = quantStepsSbr[*prevRegionSbr] + hysteresis;
    381   if(*prevRegionSbr > 0)
    382     quantStepsSbrTmp[*prevRegionSbr - 1] = quantStepsSbr[*prevRegionSbr - 1] - hysteresis;
    383 
    384   if(*prevRegionOrig < numRegionsOrig)
    385     quantStepsOrigTmp[*prevRegionOrig] = quantStepsOrig[*prevRegionOrig] + hysteresis;
    386   if(*prevRegionOrig > 0)
    387     quantStepsOrigTmp[*prevRegionOrig - 1] = quantStepsOrig[*prevRegionOrig - 1] - hysteresis;
    388 
    389   regionSbr  = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr);
    390   regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig);
    391   regionNrg  = findRegion(nrg,nrgBorders,numRegionsNrg);
    392 
    393   *prevRegionSbr = regionSbr;
    394   *prevRegionOrig = regionOrig;
    395 
    396   /* Use different settings if a transient is present*/
    397   invFiltLevel = (transientFlag == 1) ? detectorParams->regionSpaceTransient[regionSbr][regionOrig]
    398                                       : detectorParams->regionSpace[regionSbr][regionOrig];
    399 
    400   /* Compensate for low energy.*/
    401   invFiltLevel = max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg],0);
    402 
    403   return (INVF_MODE) (invFiltLevel);
    404 }
    405 
    406 /**************************************************************************/
    407 /*!
    408   \brief     Estiamtion of the inverse filtering level required
    409              in the decoder.
    410 
    411    A second order LPC is calculated for every filterbank channel, using
    412    the covariance method. THe ratio between the energy of the predicted
    413    signal and the energy of the non-predictable signal is calcualted.
    414 
    415   \return    none.
    416 
    417 */
    418 /**************************************************************************/
    419 void
    420 FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt,  /*!< Handle to the SBR_INV_FILT_EST struct. */
    421                             FIXP_DBL **quotaMatrix,            /*!< The matrix holding the tonality values of the original. */
    422                             FIXP_DBL *nrgVector,               /*!< The energy vector. */
    423                             SCHAR    *indexVector,             /*!< Index vector to obtain the patched data. */
    424                             INT startIndex,                    /*!< Start index. */
    425                             INT stopIndex,                     /*!< Stop index. */
    426                             INT transientFlag,                 /*!< Flag indicating if a transient is present or not.*/
    427                             INVF_MODE* infVec                  /*!< Vector holding the inverse filtering levels. */
    428                             )
    429 {
    430   INT band;
    431 
    432   /*
    433    * Do the inverse filtering level estimation.
    434    *****************************************************/
    435   for(band = 0 ; band < hInvFilt->noDetectorBands; band++){
    436     INT startChannel = hInvFilt->freqBandTableInvFilt[band];
    437     INT stopChannel  = hInvFilt->freqBandTableInvFilt[band+1];
    438 
    439 
    440     calculateDetectorValues( quotaMatrix,
    441                              indexVector,
    442                              nrgVector,
    443                             &hInvFilt->detectorValues[band],
    444                              startChannel,
    445                              stopChannel,
    446                              startIndex,
    447                              stopIndex,
    448                              hInvFilt->numberOfStrongest);
    449 
    450     infVec[band]= decisionAlgorithm( hInvFilt->detectorParams,
    451                                     &hInvFilt->detectorValues[band],
    452                                      transientFlag,
    453                                     &hInvFilt->prevRegionSbr[band],
    454                                     &hInvFilt->prevRegionOrig[band]);
    455   }
    456 
    457 }
    458 
    459 
    460 /**************************************************************************/
    461 /*!
    462   \brief     Initialize an instance of the inverse filtering level estimator.
    463 
    464 
    465   \return   errorCode, noError if successful.
    466 
    467 */
    468 /**************************************************************************/
    469 INT
    470 FDKsbrEnc_initInvFiltDetector (HANDLE_SBR_INV_FILT_EST hInvFilt,   /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */
    471                        INT* freqBandTableDetector,          /*!< Frequency band table for the inverse filtering. */
    472                        INT numDetectorBands,                /*!< Number of inverse filtering bands. */
    473                        UINT useSpeechConfig         /*!< Flag: adapt tuning parameters according to speech*/
    474                        )
    475 {
    476   INT i;
    477 
    478   FDKmemclear( hInvFilt,sizeof(SBR_INV_FILT_EST));
    479 
    480   hInvFilt->detectorParams = (useSpeechConfig) ? &detectorParamsAACSpeech
    481                                                : &detectorParamsAAC ;
    482 
    483   hInvFilt->noDetectorBandsMax = numDetectorBands;
    484 
    485   /*
    486      Memory initialisation
    487   */
    488   for(i=0;i<hInvFilt->noDetectorBandsMax;i++){
    489     FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES));
    490     hInvFilt->prevInvfMode[i]   = INVF_OFF;
    491     hInvFilt->prevRegionOrig[i] = 0;
    492     hInvFilt->prevRegionSbr[i]  = 0;
    493   }
    494 
    495   /*
    496   Reset the inverse fltering detector.
    497   */
    498   FDKsbrEnc_resetInvFiltDetector(hInvFilt,
    499                        freqBandTableDetector,
    500                        hInvFilt->noDetectorBandsMax);
    501 
    502   return (0);
    503 }
    504 
    505 
    506 /**************************************************************************/
    507 /*!
    508   \brief     resets sbr inverse filtering structure.
    509 
    510 
    511 
    512   \return   errorCode, noError if successful.
    513 
    514 */
    515 /**************************************************************************/
    516 INT
    517 FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */
    518                      INT* freqBandTableDetector,       /*!< Frequency band table for the inverse filtering. */
    519                      INT numDetectorBands)             /*!< Number of inverse filtering bands. */
    520 {
    521 
    522   hInvFilt->numberOfStrongest     = 1;
    523   FDKmemcpy(hInvFilt->freqBandTableInvFilt,freqBandTableDetector,(numDetectorBands+1)*sizeof(INT));
    524   hInvFilt->noDetectorBands = numDetectorBands;
    525 
    526   return (0);
    527 }
    528 
    529 
    530