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 - 2015 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 "mh_det.h"
     85 
     86 #include "sbr_ram.h"
     87 #include "sbr_misc.h"
     88 
     89 
     90 #include "genericStds.h"
     91 
     92 #define SFM_SHIFT 2     /* Attention: SFM_SCALE depends on SFM_SHIFT */
     93 #define SFM_SCALE (MAXVAL_DBL >> SFM_SHIFT)   /* 1.0 >> SFM_SHIFT */
     94 
     95 
     96 /*!< Detector Parameters for AAC core codec. */
     97 static const DETECTOR_PARAMETERS_MH paramsAac = {
     98 9,                                             /*!< deltaTime */
     99 {
    100 FL2FXCONST_DBL(20.0f*RELAXATION_FLOAT),        /*!< thresHoldDiff */
    101 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT),        /*!< thresHoldDiffGuide */
    102 FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT),        /*!< thresHoldTone */
    103 FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */
    104 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT),        /*!< thresHoldToneGuide */
    105 FL2FXCONST_DBL(0.3f)>>SFM_SHIFT,               /*!< sfmThresSbr */
    106 FL2FXCONST_DBL(0.1f)>>SFM_SHIFT,               /*!< sfmThresOrig */
    107 FL2FXCONST_DBL(0.3f),                          /*!< decayGuideOrig */
    108 FL2FXCONST_DBL(0.5f),                          /*!< decayGuideDiff */
    109 FL2FXCONST_DBL(-0.000112993269),  /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */
    110 FL2FXCONST_DBL(-0.000112993269),  /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */
    111 FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */    /*!< derivThresAboveLD64 */
    112 },
    113 50                                             /*!< maxComp */
    114 };
    115 
    116 /*!< Detector Parameters for AAC LD core codec. */
    117 static const DETECTOR_PARAMETERS_MH paramsAacLd = {
    118 16,                                            /*!< Delta time. */
    119 {
    120 FL2FXCONST_DBL(25.0f*RELAXATION_FLOAT),        /*!< thresHoldDiff */
    121 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT),        /*!< tresHoldDiffGuide */
    122 FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT),        /*!< thresHoldTone */
    123 FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */
    124 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT),        /*!< thresHoldToneGuide */
    125 FL2FXCONST_DBL(0.3f)>>SFM_SHIFT,               /*!< sfmThresSbr */
    126 FL2FXCONST_DBL(0.1f)>>SFM_SHIFT,               /*!< sfmThresOrig */
    127 FL2FXCONST_DBL(0.3f),                          /*!< decayGuideOrig */
    128 FL2FXCONST_DBL(0.2f),                          /*!< decayGuideDiff */
    129 FL2FXCONST_DBL(-0.000112993269),  /* LD64(FL2FXCONST_DBL(0.995f)) */  /*!< derivThresMaxLD64 */
    130 FL2FXCONST_DBL(-0.000112993269),  /* LD64(FL2FXCONST_DBL(0.995f)) */  /*!< derivThresBelowLD64 */
    131 FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */     /*!< derivThresAboveLD64 */
    132 },
    133 50                                             /*!< maxComp */
    134 };
    135 
    136 
    137 /**************************************************************************/
    138 /*!
    139   \brief     Calculates the difference in tonality between original and SBR
    140              for a given time and frequency region.
    141 
    142              The values for pDiffMapped2Scfb are scaled by RELAXATION
    143 
    144   \return    none.
    145 
    146 */
    147 /**************************************************************************/
    148 static void diff(FIXP_DBL *RESTRICT pTonalityOrig,
    149                  FIXP_DBL *pDiffMapped2Scfb,
    150                  const UCHAR *RESTRICT pFreqBandTable,
    151                  INT       nScfb,
    152                  SCHAR    *indexVector)
    153 {
    154   UCHAR i, ll, lu, k;
    155   FIXP_DBL maxValOrig, maxValSbr, tmp;
    156   INT scale;
    157 
    158   for(i=0; i < nScfb; i++){
    159     ll = pFreqBandTable[i];
    160     lu = pFreqBandTable[i+1];
    161 
    162     maxValOrig = FL2FXCONST_DBL(0.0f);
    163     maxValSbr = FL2FXCONST_DBL(0.0f);
    164 
    165     for(k=ll;k<lu;k++){
    166       maxValOrig = fixMax(maxValOrig, pTonalityOrig[k]);
    167       maxValSbr = fixMax(maxValSbr, pTonalityOrig[indexVector[k]]);
    168     }
    169 
    170     if ((maxValSbr >= RELAXATION)) {
    171         tmp = fDivNorm(maxValOrig, maxValSbr, &scale);
    172         pDiffMapped2Scfb[i] = scaleValue(fMult(tmp,RELAXATION_FRACT), fixMax(-(DFRACT_BITS-1),(scale-RELAXATION_SHIFT)));
    173     }
    174     else {
    175         pDiffMapped2Scfb[i] = maxValOrig;
    176     }
    177   }
    178 }
    179 
    180 
    181 /**************************************************************************/
    182 /*!
    183   \brief     Calculates a flatness measure of the tonality measures.
    184 
    185   Calculation of the power function and using scalefactor for basis:
    186     Using log2:
    187     z  = (2^k * x)^y;
    188     z' = CalcLd(z) = y*CalcLd(x) + y*k;
    189     z  = CalcInvLd(z');
    190 
    191     Using ld64:
    192     z  = (2^k * x)^y;
    193     z' = CalcLd64(z) = y*CalcLd64(x)/64 + y*k/64;
    194     z  = CalcInvLd64(z');
    195 
    196   The values pSfmOrigVec and pSfmSbrVec are scaled by the factor 1/4.0
    197 
    198   \return    none.
    199 
    200 */
    201 /**************************************************************************/
    202 static void calculateFlatnessMeasure(FIXP_DBL *pQuotaBuffer,
    203                                      SCHAR    *indexVector,
    204                                      FIXP_DBL *pSfmOrigVec,
    205                                      FIXP_DBL *pSfmSbrVec,
    206                                      const UCHAR *pFreqBandTable,
    207                                      INT       nSfb)
    208 {
    209   INT i,j;
    210   FIXP_DBL invBands,tmp1,tmp2;
    211   INT shiftFac0,shiftFacSum0;
    212   INT shiftFac1,shiftFacSum1;
    213   FIXP_DBL accu;
    214 
    215   for(i=0;i<nSfb;i++)
    216   {
    217     INT ll = pFreqBandTable[i];
    218     INT lu = pFreqBandTable[i+1];
    219     pSfmOrigVec[i] = (FIXP_DBL)(MAXVAL_DBL>>2);
    220     pSfmSbrVec[i]  = (FIXP_DBL)(MAXVAL_DBL>>2);
    221 
    222     if(lu - ll > 1){
    223       FIXP_DBL amOrig,amTransp,gmOrig,gmTransp,sfmOrig,sfmTransp;
    224       invBands = GetInvInt(lu-ll);
    225       shiftFacSum0 = 0;
    226       shiftFacSum1 = 0;
    227       amOrig = amTransp = FL2FXCONST_DBL(0.0f);
    228       gmOrig = gmTransp = (FIXP_DBL)MAXVAL_DBL;
    229 
    230       for(j= ll; j<lu; j++) {
    231         sfmOrig   = pQuotaBuffer[j];
    232         sfmTransp = pQuotaBuffer[indexVector[j]];
    233 
    234         amOrig   += fMult(sfmOrig, invBands);
    235         amTransp += fMult(sfmTransp, invBands);
    236 
    237         shiftFac0 = CountLeadingBits(sfmOrig);
    238         shiftFac1 = CountLeadingBits(sfmTransp);
    239 
    240         gmOrig   = fMult(gmOrig, sfmOrig<<shiftFac0);
    241         gmTransp = fMult(gmTransp, sfmTransp<<shiftFac1);
    242 
    243         shiftFacSum0 += shiftFac0;
    244         shiftFacSum1 += shiftFac1;
    245       }
    246 
    247       if (gmOrig > FL2FXCONST_DBL(0.0f)) {
    248 
    249         tmp1 = CalcLdData(gmOrig);      /* CalcLd64(x)/64 */
    250         tmp1 = fMult(invBands, tmp1);   /* y*CalcLd64(x)/64 */
    251 
    252         /* y*k/64 */
    253         accu = (FIXP_DBL)-shiftFacSum0 << (DFRACT_BITS-1-8);
    254         tmp2 = fMultDiv2(invBands, accu) << (2+1);
    255 
    256         tmp2 = tmp1 + tmp2;             /* y*CalcLd64(x)/64 + y*k/64 */
    257         gmOrig = CalcInvLdData(tmp2);   /* CalcInvLd64(z'); */
    258       }
    259       else {
    260         gmOrig = FL2FXCONST_DBL(0.0f);
    261       }
    262 
    263       if (gmTransp > FL2FXCONST_DBL(0.0f)) {
    264 
    265         tmp1 = CalcLdData(gmTransp);    /* CalcLd64(x)/64 */
    266         tmp1 = fMult(invBands, tmp1);   /* y*CalcLd64(x)/64 */
    267 
    268         /* y*k/64 */
    269         accu = (FIXP_DBL)-shiftFacSum1 << (DFRACT_BITS-1-8);
    270         tmp2 = fMultDiv2(invBands, accu) << (2+1);
    271 
    272         tmp2 = tmp1 + tmp2;             /* y*CalcLd64(x)/64 + y*k/64 */
    273         gmTransp = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */
    274       }
    275       else {
    276         gmTransp = FL2FXCONST_DBL(0.0f);
    277       }
    278       if ( amOrig != FL2FXCONST_DBL(0.0f) )
    279         pSfmOrigVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmOrig,amOrig,SFM_SCALE);
    280 
    281       if ( amTransp != FL2FXCONST_DBL(0.0f) )
    282         pSfmSbrVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmTransp,amTransp,SFM_SCALE);
    283     }
    284   }
    285 }
    286 
    287 /**************************************************************************/
    288 /*!
    289   \brief     Calculates the input to the missing harmonics detection.
    290 
    291 
    292   \return    none.
    293 
    294 */
    295 /**************************************************************************/
    296 static void calculateDetectorInput(FIXP_DBL **RESTRICT pQuotaBuffer,  /*!< Pointer to tonality matrix. */
    297                                    SCHAR     *RESTRICT indexVector,
    298                                    FIXP_DBL **RESTRICT tonalityDiff,
    299                                    FIXP_DBL **RESTRICT pSfmOrig,
    300                                    FIXP_DBL **RESTRICT pSfmSbr,
    301                                    const UCHAR *freqBandTable,
    302                                    INT nSfb,
    303                                    INT noEstPerFrame,
    304                                    INT move)
    305 {
    306   INT est;
    307 
    308   /*
    309   New estimate.
    310   */
    311   for (est=0; est < noEstPerFrame; est++) {
    312 
    313     diff(pQuotaBuffer[est+move],
    314          tonalityDiff[est+move],
    315          freqBandTable,
    316          nSfb,
    317          indexVector);
    318 
    319     calculateFlatnessMeasure(pQuotaBuffer[est+ move],
    320                              indexVector,
    321                              pSfmOrig[est + move],
    322                              pSfmSbr[est + move],
    323                              freqBandTable,
    324                              nSfb);
    325   }
    326 }
    327 
    328 
    329 /**************************************************************************/
    330 /*!
    331   \brief     Checks that the detection is not due to a LP filter
    332 
    333   This function determines if a newly detected missing harmonics is not
    334   in fact just a low-pass filtere input signal. If so, the detection is
    335   removed.
    336 
    337   \return    none.
    338 
    339 */
    340 /**************************************************************************/
    341 static void removeLowPassDetection(UCHAR *RESTRICT pAddHarmSfb,
    342                                    UCHAR **RESTRICT pDetectionVectors,
    343                                    INT start,
    344                                    INT stop,
    345                                    INT nSfb,
    346                                    const UCHAR *RESTRICT pFreqBandTable,
    347                                    FIXP_DBL *RESTRICT pNrgVector,
    348                                    THRES_HOLDS mhThresh)
    349 
    350 {
    351   INT i,est;
    352   INT maxDerivPos = pFreqBandTable[nSfb];
    353   INT numBands = pFreqBandTable[nSfb];
    354   FIXP_DBL nrgLow,nrgHigh;
    355   FIXP_DBL nrgLD64,nrgLowLD64,nrgHighLD64,nrgDiffLD64;
    356   FIXP_DBL valLD64,maxValLD64,maxValAboveLD64;
    357   INT bLPsignal = 0;
    358 
    359   maxValLD64 = FL2FXCONST_DBL(-1.0f);
    360   for(i = numBands - 1 - 2; i > pFreqBandTable[0];i--){
    361     nrgLow  = pNrgVector[i];
    362     nrgHigh = pNrgVector[i + 2];
    363 
    364     if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){
    365       nrgLowLD64 = CalcLdData(nrgLow>>1);
    366       nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1));
    367       valLD64 = nrgDiffLD64-nrgLowLD64;
    368       if(valLD64 > maxValLD64){
    369         maxDerivPos = i;
    370         maxValLD64 = valLD64;
    371       }
    372       if(maxValLD64 > mhThresh.derivThresMaxLD64) {
    373         break;
    374       }
    375     }
    376   }
    377 
    378   /* Find the largest "gradient" above. (should be relatively flat, hence we expect a low value
    379      if the signal is LP.*/
    380   maxValAboveLD64 = FL2FXCONST_DBL(-1.0f);
    381   for(i = numBands - 1 - 2; i > maxDerivPos + 2;i--){
    382     nrgLow  = pNrgVector[i];
    383     nrgHigh = pNrgVector[i + 2];
    384 
    385     if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){
    386 		   nrgLowLD64 = CalcLdData(nrgLow>>1);
    387 		   nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1));
    388 			 valLD64 = nrgDiffLD64-nrgLowLD64;
    389       if(valLD64 > maxValAboveLD64){
    390         maxValAboveLD64 = valLD64;
    391       }
    392     }
    393 		 else {
    394       if(nrgHigh != FL2FXCONST_DBL(0.0f) && nrgHigh > nrgLow){
    395 		     nrgHighLD64 = CalcLdData(nrgHigh>>1);
    396 		     nrgDiffLD64 = CalcLdData((nrgHigh>>1)-(nrgLow>>1));
    397 			   valLD64 = nrgDiffLD64-nrgHighLD64;
    398         if(valLD64 > maxValAboveLD64){
    399           maxValAboveLD64 = valLD64;
    400         }
    401       }
    402 		 }
    403   }
    404 
    405   if(maxValLD64 > mhThresh.derivThresMaxLD64 && maxValAboveLD64 < mhThresh.derivThresAboveLD64){
    406     bLPsignal = 1;
    407 
    408     for(i = maxDerivPos - 1; i > maxDerivPos - 5 && i >= 0 ; i--){
    409       if(pNrgVector[i] != FL2FXCONST_DBL(0.0f) && pNrgVector[i] > pNrgVector[maxDerivPos + 2]){
    410 		     nrgDiffLD64 = CalcLdData((pNrgVector[i]>>1)-(pNrgVector[maxDerivPos + 2]>>1));
    411 				 nrgLD64 = CalcLdData(pNrgVector[i]>>1);
    412   			 valLD64 = nrgDiffLD64-nrgLD64;
    413         if(valLD64 < mhThresh.derivThresBelowLD64) {
    414           bLPsignal = 0;
    415           break;
    416         }
    417       }
    418       else{
    419         bLPsignal = 0;
    420         break;
    421       }
    422     }
    423   }
    424 
    425   if(bLPsignal){
    426     for(i=0;i<nSfb;i++){
    427       if(maxDerivPos >= pFreqBandTable[i] && maxDerivPos < pFreqBandTable[i+1])
    428         break;
    429     }
    430 
    431     if(pAddHarmSfb[i]){
    432       pAddHarmSfb[i] = 0;
    433       for(est = start; est < stop ; est++){
    434         pDetectionVectors[est][i] = 0;
    435       }
    436     }
    437   }
    438 }
    439 
    440 /**************************************************************************/
    441 /*!
    442   \brief     Checks if it is allowed to detect a missing tone, that wasn't
    443              detected previously.
    444 
    445 
    446   \return    newDetectionAllowed flag.
    447 
    448 */
    449 /**************************************************************************/
    450 static INT isDetectionOfNewToneAllowed(const SBR_FRAME_INFO *pFrameInfo,
    451                                        INT *pDetectionStartPos,
    452                                        INT noEstPerFrame,
    453                                        INT prevTransientFrame,
    454                                        INT prevTransientPos,
    455                                        INT prevTransientFlag,
    456                                        INT transientPosOffset,
    457                                        INT transientFlag,
    458                                        INT transientPos,
    459                                        INT deltaTime,
    460                                        HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector)
    461 {
    462   INT transientFrame, newDetectionAllowed;
    463 
    464 
    465   /* Determine if this is a frame where a transient starts...
    466    * If the transient flag was set the previous frame but not the
    467    * transient frame flag, the transient frame flag is set in the current frame.
    468    *****************************************************************************/
    469   transientFrame = 0;
    470   if(transientFlag){
    471     if(transientPos + transientPosOffset < pFrameInfo->borders[pFrameInfo->nEnvelopes])
    472       transientFrame = 1;
    473       if(noEstPerFrame > 1){
    474         if(transientPos + transientPosOffset > h_sbrMissingHarmonicsDetector->timeSlots >> 1){
    475           *pDetectionStartPos = noEstPerFrame;
    476         }
    477         else{
    478           *pDetectionStartPos = noEstPerFrame >> 1;
    479         }
    480 
    481       }
    482       else{
    483         *pDetectionStartPos = noEstPerFrame;
    484       }
    485   }
    486   else{
    487     if(prevTransientFlag && !prevTransientFrame){
    488       transientFrame = 1;
    489       *pDetectionStartPos = 0;
    490     }
    491   }
    492 
    493   /*
    494    * Determine if detection of new missing harmonics are allowed.
    495    * If the frame contains a transient it's ok. If the previous
    496    * frame contained a transient it needs to be sufficiently close
    497    * to the start of the current frame.
    498    ****************************************************************/
    499   newDetectionAllowed = 0;
    500   if(transientFrame){
    501     newDetectionAllowed = 1;
    502   }
    503   else {
    504     if(prevTransientFrame &&
    505        fixp_abs(pFrameInfo->borders[0] - (prevTransientPos + transientPosOffset -
    506                                      h_sbrMissingHarmonicsDetector->timeSlots)) < deltaTime)
    507       newDetectionAllowed = 1;
    508       *pDetectionStartPos = 0;
    509   }
    510 
    511   h_sbrMissingHarmonicsDetector->previousTransientFlag  = transientFlag;
    512   h_sbrMissingHarmonicsDetector->previousTransientFrame = transientFrame;
    513   h_sbrMissingHarmonicsDetector->previousTransientPos   = transientPos;
    514 
    515   return (newDetectionAllowed);
    516 }
    517 
    518 
    519 /**************************************************************************/
    520 /*!
    521   \brief     Cleans up the detection after a transient.
    522 
    523 
    524   \return    none.
    525 
    526 */
    527 /**************************************************************************/
    528 static void transientCleanUp(FIXP_DBL **quotaBuffer,
    529                              INT nSfb,
    530                              UCHAR **detectionVectors,
    531                              UCHAR *pAddHarmSfb,
    532                              UCHAR *pPrevAddHarmSfb,
    533                              INT ** signBuffer,
    534                              const UCHAR *pFreqBandTable,
    535                              INT start,
    536                              INT stop,
    537                              INT newDetectionAllowed,
    538                              FIXP_DBL *pNrgVector,
    539                              THRES_HOLDS mhThresh)
    540 {
    541   INT i,j,li, ui,est;
    542 
    543   for(est=start; est < stop; est++) {
    544     for(i=0; i<nSfb; i++) {
    545       pAddHarmSfb[i] = pAddHarmSfb[i] || detectionVectors[est][i];
    546     }
    547   }
    548 
    549   if(newDetectionAllowed == 1){
    550     /*
    551      * Check for duplication of sines located
    552      * on the border of two scf-bands.
    553      *************************************************/
    554     for(i=0;i<nSfb-1;i++) {
    555       li = pFreqBandTable[i];
    556       ui = pFreqBandTable[i+1];
    557 
    558       /* detection in adjacent channels.*/
    559       if(pAddHarmSfb[i] && pAddHarmSfb[i+1]) {
    560         FIXP_DBL maxVal1, maxVal2;
    561         INT maxPos1, maxPos2, maxPosTime1, maxPosTime2;
    562 
    563         li = pFreqBandTable[i];
    564         ui = pFreqBandTable[i+1];
    565 
    566         /* Find maximum tonality in the the two scf bands.*/
    567         maxPosTime1 = start;
    568         maxPos1 = li;
    569         maxVal1 = quotaBuffer[start][li];
    570         for(est = start; est < stop; est++){
    571           for(j = li; j<ui; j++){
    572             if(quotaBuffer[est][j] > maxVal1){
    573               maxVal1 = quotaBuffer[est][j];
    574               maxPos1 = j;
    575               maxPosTime1 = est;
    576             }
    577           }
    578         }
    579 
    580         li = pFreqBandTable[i+1];
    581         ui = pFreqBandTable[i+2];
    582 
    583         /* Find maximum tonality in the the two scf bands.*/
    584         maxPosTime2 = start;
    585         maxPos2 = li;
    586         maxVal2 = quotaBuffer[start][li];
    587         for(est = start; est < stop; est++){
    588           for(j = li; j<ui; j++){
    589             if(quotaBuffer[est][j] > maxVal2){
    590               maxVal2 = quotaBuffer[est][j];
    591               maxPos2 = j;
    592               maxPosTime2 = est;
    593             }
    594           }
    595         }
    596 
    597         /* If the maximum values are in adjacent QMF-channels, we need to remove
    598            the lowest of the two.*/
    599         if(maxPos2-maxPos1 < 2){
    600 
    601           if(pPrevAddHarmSfb[i] == 1 && pPrevAddHarmSfb[i+1] == 0){
    602             /* Keep the lower, remove the upper.*/
    603             pAddHarmSfb[i+1] = 0;
    604             for(est=start; est<stop; est++){
    605               detectionVectors[est][i+1] = 0;
    606             }
    607           }
    608           else{
    609             if(pPrevAddHarmSfb[i] == 0 && pPrevAddHarmSfb[i+1] == 1){
    610               /* Keep the upper, remove the lower.*/
    611               pAddHarmSfb[i] = 0;
    612               for(est=start; est<stop; est++){
    613                 detectionVectors[est][i] = 0;
    614               }
    615             }
    616             else{
    617              /* If the maximum values are in adjacent QMF-channels, and if the signs indicate that it is the same sine,
    618                 we need to remove the lowest of the two.*/
    619               if(maxVal1 > maxVal2){
    620                 if(signBuffer[maxPosTime1][maxPos2] < 0 && signBuffer[maxPosTime1][maxPos1] > 0){
    621                   /* Keep the lower, remove the upper.*/
    622                   pAddHarmSfb[i+1] = 0;
    623                   for(est=start; est<stop; est++){
    624                     detectionVectors[est][i+1] = 0;
    625                   }
    626                 }
    627               }
    628               else{
    629                 if(signBuffer[maxPosTime2][maxPos2] < 0 && signBuffer[maxPosTime2][maxPos1] > 0){
    630                   /* Keep the upper, remove the lower.*/
    631                   pAddHarmSfb[i] = 0;
    632                   for(est=start; est<stop; est++){
    633                     detectionVectors[est][i] = 0;
    634                   }
    635                 }
    636               }
    637             }
    638           }
    639         }
    640       }
    641     }
    642 
    643     /* Make sure that the detection is not the cut-off of a low pass filter. */
    644     removeLowPassDetection(pAddHarmSfb,
    645                            detectionVectors,
    646                            start,
    647                            stop,
    648                            nSfb,
    649                            pFreqBandTable,
    650                            pNrgVector,
    651                            mhThresh);
    652   }
    653   else {
    654    /*
    655     * If a missing harmonic wasn't missing the previous frame
    656     * the transient-flag needs to be set in order to be allowed to detect it.
    657     *************************************************************************/
    658     for(i=0;i<nSfb;i++){
    659       if(pAddHarmSfb[i] - pPrevAddHarmSfb[i] > 0)
    660         pAddHarmSfb[i] = 0;
    661     }
    662   }
    663 }
    664 
    665 
    666 /*****************************************************************************/
    667 /*!
    668   \brief     Detection for one tonality estimate.
    669 
    670   This is the actual missing harmonics detection, using information from the
    671   previous detection.
    672 
    673   If a missing harmonic was detected (in a previous frame) due to too high
    674   tonality differences, but there was not enough tonality difference in the
    675   current frame, the detection algorithm still continues to trace the strongest
    676   tone in the scalefactor band (assuming that this is the tone that is going to
    677   be replaced in the decoder). This is done to avoid abrupt endings of sines
    678   fading out (e.g. in the glockenspiel).
    679 
    680   The function also tries to estimate where one sine is going to be replaced
    681   with multiple sines (due to the patching). This is done by comparing the
    682   tonality flatness measure of the original and the SBR signal.
    683 
    684   The function also tries to estimate (for the scalefactor bands only
    685   containing one qmf subband) when a strong tone in the original will be
    686   replaced by a strong tone in the adjacent QMF subband.
    687 
    688   \return    none.
    689 
    690 */
    691 /**************************************************************************/
    692 static void detection(FIXP_DBL *quotaBuffer,
    693                       FIXP_DBL *pDiffVecScfb,
    694                       INT nSfb,
    695                       UCHAR *pHarmVec,
    696                       const UCHAR *pFreqBandTable,
    697                       FIXP_DBL *sfmOrig,
    698                       FIXP_DBL *sfmSbr,
    699                       GUIDE_VECTORS guideVectors,
    700                       GUIDE_VECTORS newGuideVectors,
    701                       THRES_HOLDS mhThresh)
    702 {
    703 
    704   INT i,j,ll, lu;
    705   FIXP_DBL thresTemp,thresOrig;
    706 
    707   /*
    708    * Do detection on the difference vector, i.e. the difference between
    709    * the original and the transposed.
    710    *********************************************************************/
    711   for(i=0;i<nSfb;i++){
    712 
    713     thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f))
    714                   ? fMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide)
    715                   : mhThresh.thresHoldDiff;
    716 
    717     thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff);
    718 
    719     if(pDiffVecScfb[i] > thresTemp){
    720       pHarmVec[i] = 1;
    721       newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i];
    722     }
    723     else{
    724       /* If the guide wasn't zero, but the current level is to low,
    725          start tracking the decay on the tone in the original rather
    726          than the difference.*/
    727       if(guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
    728         guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide;
    729       }
    730     }
    731   }
    732 
    733   /*
    734    * Trace tones in the original signal that at one point
    735    * have been detected because they will be replaced by
    736    * multiple tones in the sbr signal.
    737    ****************************************************/
    738 
    739   for(i=0;i<nSfb;i++){
    740     ll = pFreqBandTable[i];
    741     lu = pFreqBandTable[i+1];
    742 
    743     thresOrig = fixMax(fMult(guideVectors.guideVectorOrig[i], mhThresh.decayGuideOrig), mhThresh.thresHoldToneGuide);
    744     thresOrig = fixMin(thresOrig, mhThresh.thresHoldTone);
    745 
    746     if(guideVectors.guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
    747       for(j= ll;j<lu;j++){
    748         if(quotaBuffer[j] > thresOrig){
    749           pHarmVec[i] = 1;
    750           newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
    751         }
    752       }
    753     }
    754   }
    755 
    756   /*
    757    * Check for multiple sines in the transposed signal,
    758    * where there is only one in the original.
    759    ****************************************************/
    760   thresOrig = mhThresh.thresHoldTone;
    761 
    762   for(i=0;i<nSfb;i++){
    763     ll = pFreqBandTable[i];
    764     lu = pFreqBandTable[i+1];
    765 
    766     if(pHarmVec[i] == 0){
    767       if(lu -ll > 1){
    768         for(j= ll;j<lu;j++){
    769           if(quotaBuffer[j] > thresOrig && (sfmSbr[i] > mhThresh.sfmThresSbr && sfmOrig[i] < mhThresh.sfmThresOrig)){
    770             pHarmVec[i] = 1;
    771             newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
    772           }
    773         }
    774       }
    775       else{
    776         if(i < nSfb -1){
    777           ll = pFreqBandTable[i];
    778 
    779           if(i>0){
    780             if(quotaBuffer[ll] > mhThresh.thresHoldTone && (pDiffVecScfb[i+1] < mhThresh.invThresHoldTone || pDiffVecScfb[i-1] < mhThresh.invThresHoldTone)){
    781                 pHarmVec[i] = 1;
    782                 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
    783             }
    784           }
    785           else{
    786             if(quotaBuffer[ll] > mhThresh.thresHoldTone && pDiffVecScfb[i+1] < mhThresh.invThresHoldTone){
    787                 pHarmVec[i] = 1;
    788                 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
    789             }
    790           }
    791         }
    792       }
    793     }
    794   }
    795 }
    796 
    797 
    798 /**************************************************************************/
    799 /*!
    800   \brief     Do detection for every tonality estimate, using forward prediction.
    801 
    802 
    803   \return    none.
    804 
    805 */
    806 /**************************************************************************/
    807 static void detectionWithPrediction(FIXP_DBL **quotaBuffer,
    808                                     FIXP_DBL **pDiffVecScfb,
    809                                     INT ** signBuffer,
    810                                     INT nSfb,
    811                                     const UCHAR* pFreqBandTable,
    812                                     FIXP_DBL **sfmOrig,
    813                                     FIXP_DBL **sfmSbr,
    814                                     UCHAR **detectionVectors,
    815                                     UCHAR *pPrevAddHarmSfb,
    816                                     GUIDE_VECTORS *guideVectors,
    817                                     INT noEstPerFrame,
    818                                     INT detectionStart,
    819                                     INT totNoEst,
    820                                     INT newDetectionAllowed,
    821                                     INT *pAddHarmFlag,
    822                                     UCHAR *pAddHarmSfb,
    823                                     FIXP_DBL *pNrgVector,
    824                                     const DETECTOR_PARAMETERS_MH *mhParams)
    825 {
    826   INT est = 0,i;
    827   INT start;
    828 
    829   FDKmemclear(pAddHarmSfb,nSfb*sizeof(UCHAR));
    830 
    831   if(newDetectionAllowed){
    832 
    833     /* Since we don't want to use the transient region for detection (since the tonality values
    834        tend to be a bit unreliable for this region) the guide-values are copied to the current
    835        starting point. */
    836     if(totNoEst > 1){
    837       start = detectionStart+1;
    838 
    839       if (start != 0) {
    840         FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    841         FDKmemcpy(guideVectors[start].guideVectorOrig,guideVectors[0].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    842         FDKmemclear(guideVectors[start-1].guideVectorDetected,nSfb*sizeof(UCHAR));
    843       }
    844     }
    845     else{
    846       start = 0;
    847     }
    848   }
    849   else{
    850     start = 0;
    851   }
    852 
    853 
    854   for(est = start; est < totNoEst; est++){
    855 
    856     /*
    857     * Do detection on the current frame using
    858     * guide-info from the previous.
    859     *******************************************/
    860     if(est > 0){
    861       FDKmemcpy(guideVectors[est].guideVectorDetected,detectionVectors[est-1],nSfb*sizeof(UCHAR));
    862     }
    863 
    864     FDKmemclear(detectionVectors[est], nSfb*sizeof(UCHAR));
    865 
    866     if(est < totNoEst-1){
    867       FDKmemclear(guideVectors[est+1].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    868       FDKmemclear(guideVectors[est+1].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    869       FDKmemclear(guideVectors[est+1].guideVectorDetected,nSfb*sizeof(UCHAR));
    870 
    871       detection(quotaBuffer[est],
    872                 pDiffVecScfb[est],
    873                 nSfb,
    874                 detectionVectors[est],
    875                 pFreqBandTable,
    876                 sfmOrig[est],
    877                 sfmSbr[est],
    878                 guideVectors[est],
    879                 guideVectors[est+1],
    880                 mhParams->thresHolds);
    881     }
    882     else{
    883       FDKmemclear(guideVectors[est].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    884       FDKmemclear(guideVectors[est].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    885       FDKmemclear(guideVectors[est].guideVectorDetected,nSfb*sizeof(UCHAR));
    886 
    887       detection(quotaBuffer[est],
    888                 pDiffVecScfb[est],
    889                 nSfb,
    890                 detectionVectors[est],
    891                 pFreqBandTable,
    892                 sfmOrig[est],
    893                 sfmSbr[est],
    894                 guideVectors[est],
    895                 guideVectors[est],
    896                 mhParams->thresHolds);
    897     }
    898   }
    899 
    900 
    901   /* Clean up the detection.*/
    902   transientCleanUp(quotaBuffer,
    903                    nSfb,
    904                    detectionVectors,
    905                    pAddHarmSfb,
    906                    pPrevAddHarmSfb,
    907                    signBuffer,
    908                    pFreqBandTable,
    909                    start,
    910                    totNoEst,
    911                    newDetectionAllowed,
    912                    pNrgVector,
    913                    mhParams->thresHolds);
    914 
    915 
    916   /* Set flag... */
    917   *pAddHarmFlag = 0;
    918   for(i=0; i<nSfb; i++){
    919     if(pAddHarmSfb[i]){
    920       *pAddHarmFlag = 1;
    921       break;
    922     }
    923   }
    924 
    925   FDKmemcpy(pPrevAddHarmSfb, pAddHarmSfb, nSfb*sizeof(UCHAR));
    926   FDKmemcpy(guideVectors[0].guideVectorDetected,pAddHarmSfb,nSfb*sizeof(INT));
    927 
    928   for(i=0; i<nSfb ; i++){
    929 
    930     guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
    931     guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
    932 
    933     if(pAddHarmSfb[i] == 1){
    934       /* If we had a detection use the guide-value in the next frame from the last estimate were the detection
    935       was done.*/
    936       for(est=start; est < totNoEst; est++){
    937         if(guideVectors[est].guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
    938           guideVectors[0].guideVectorDiff[i] = guideVectors[est].guideVectorDiff[i];
    939         }
    940         if(guideVectors[est].guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
    941           guideVectors[0].guideVectorOrig[i] = guideVectors[est].guideVectorOrig[i];
    942         }
    943       }
    944     }
    945   }
    946 
    947 }
    948 
    949 
    950 /**************************************************************************/
    951 /*!
    952   \brief     Calculates a compensation vector for the energy data.
    953 
    954   This function calculates a compensation vector for the energy data (i.e.
    955   envelope data) that is calculated elsewhere. This is since, one sine on
    956   the border of two scalefactor bands, will be replace by one sine in the
    957   middle of either scalefactor band. However, since the sine that is replaced
    958   will influence the energy estimate in both scalefactor bands (in the envelops
    959   calculation function) a compensation value is required in order to avoid
    960   noise substitution in the decoder next to the synthetic sine.
    961 
    962   \return    none.
    963 
    964 */
    965 /**************************************************************************/
    966 static void calculateCompVector(UCHAR *pAddHarmSfb,
    967                                 FIXP_DBL **pTonalityMatrix,
    968                                 INT ** pSignMatrix,
    969                                 UCHAR *pEnvComp,
    970                                 INT nSfb,
    971                                 const UCHAR *freqBandTable,
    972                                 INT totNoEst,
    973                                 INT maxComp,
    974                                 UCHAR *pPrevEnvComp,
    975                                 INT newDetectionAllowed)
    976 {
    977 
    978   INT scfBand,est,l,ll,lu,maxPosF,maxPosT;
    979   FIXP_DBL maxVal;
    980   INT compValue;
    981   FIXP_DBL tmp;
    982 
    983   FDKmemclear(pEnvComp,nSfb*sizeof(UCHAR));
    984 
    985   for(scfBand=0; scfBand < nSfb; scfBand++){
    986 
    987     if(pAddHarmSfb[scfBand]){ /* A missing sine was detected */
    988       ll = freqBandTable[scfBand];
    989       lu = freqBandTable[scfBand+1];
    990 
    991       maxPosF = 0;                        /* First find the maximum*/
    992       maxPosT = 0;
    993       maxVal = FL2FXCONST_DBL(0.0f);
    994 
    995       for(est=0;est<totNoEst;est++){
    996         for(l=ll; l<lu; l++){
    997           if(pTonalityMatrix[est][l] > maxVal){
    998             maxVal = pTonalityMatrix[est][l];
    999             maxPosF = l;
   1000             maxPosT = est;
   1001           }
   1002         }
   1003       }
   1004 
   1005       /*
   1006        * If the maximum tonality is at the lower border of the
   1007        * scalefactor band, we check the sign of the adjacent channels
   1008        * to see if this sine is shared by the lower channel. If so, the
   1009        * energy of the single sine will be present in two scalefactor bands
   1010        * in the SBR data, which will cause problems in the decoder, when we
   1011        * add a sine to just one of the channels.
   1012        *********************************************************************/
   1013       if(maxPosF == ll && scfBand){
   1014         if(!pAddHarmSfb[scfBand - 1]) {     /* No detection below*/
   1015           if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && pSignMatrix[maxPosT][maxPosF] < 0) {
   1016             /* The comp value is calulated as the tonallity value, i.e we want to
   1017                reduce the envelope data for this channel with as much as the tonality
   1018                that is spread from the channel above. (ld64(RELAXATION) = 0.31143075889) */
   1019             tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + RELAXATION_LD64);
   1020             tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1;  /* shift one bit less for rounding */
   1021             compValue = ((INT)(LONG)tmp) >> 1;
   1022 
   1023 						      /* limit the comp-value*/
   1024             if (compValue > maxComp)
   1025               compValue = maxComp;
   1026 
   1027             pEnvComp[scfBand-1] = compValue;
   1028 					     }
   1029 				    }
   1030       }
   1031 
   1032       /*
   1033        * Same as above, but for the upper end of the scalefactor-band.
   1034        ***************************************************************/
   1035       if(maxPosF == lu-1 && scfBand+1 < nSfb){        /* Upper border*/
   1036         if(!pAddHarmSfb[scfBand + 1]) {
   1037           if (pSignMatrix[maxPosT][maxPosF] > 0 && pSignMatrix[maxPosT][maxPosF + 1] < 0) {
   1038             tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + RELAXATION_LD64);
   1039             tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1;  /* shift one bit less for rounding */
   1040             compValue = ((INT)(LONG)tmp) >> 1;
   1041 
   1042             if (compValue > maxComp)
   1043               compValue = maxComp;
   1044 
   1045             pEnvComp[scfBand+1] = compValue;
   1046 					 }
   1047 				 }
   1048       }
   1049 		 }
   1050 	 }
   1051 
   1052   if(newDetectionAllowed == 0){
   1053     for(scfBand=0;scfBand<nSfb;scfBand++){
   1054       if(pEnvComp[scfBand] != 0 && pPrevEnvComp[scfBand] == 0)
   1055         pEnvComp[scfBand] = 0;
   1056     }
   1057   }
   1058 
   1059   /* remember the value for the next frame.*/
   1060   FDKmemcpy(pPrevEnvComp,pEnvComp,nSfb*sizeof(UCHAR));
   1061 }
   1062 
   1063 
   1064 /**************************************************************************/
   1065 /*!
   1066   \brief     Detects where strong tonal components will be missing after
   1067              HFR in the decoder.
   1068 
   1069 
   1070   \return    none.
   1071 
   1072 */
   1073 /**************************************************************************/
   1074 void
   1075 FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet,
   1076                                FIXP_DBL ** pQuotaBuffer,
   1077                                INT ** pSignBuffer,
   1078                                SCHAR* indexVector,
   1079                                const SBR_FRAME_INFO *pFrameInfo,
   1080                                const UCHAR* pTranInfo,
   1081                                INT* pAddHarmonicsFlag,
   1082                                UCHAR* pAddHarmonicsScaleFactorBands,
   1083                                const UCHAR* freqBandTable,
   1084                                INT nSfb,
   1085                                UCHAR* envelopeCompensation,
   1086                                FIXP_DBL *pNrgVector)
   1087 {
   1088   INT transientFlag = pTranInfo[1];
   1089   INT transientPos  = pTranInfo[0];
   1090   INT newDetectionAllowed;
   1091   INT transientDetStart = 0;
   1092 
   1093   UCHAR ** detectionVectors  = h_sbrMHDet->detectionVectors;
   1094   INT move                = h_sbrMHDet->move;
   1095   INT noEstPerFrame       = h_sbrMHDet->noEstPerFrame;
   1096   INT totNoEst            = h_sbrMHDet->totNoEst;
   1097   INT prevTransientFlag   = h_sbrMHDet->previousTransientFlag;
   1098   INT prevTransientFrame  = h_sbrMHDet->previousTransientFrame;
   1099   INT transientPosOffset  = h_sbrMHDet->transientPosOffset;
   1100   INT prevTransientPos    = h_sbrMHDet->previousTransientPos;
   1101   GUIDE_VECTORS* guideVectors = h_sbrMHDet->guideVectors;
   1102   INT deltaTime = h_sbrMHDet->mhParams->deltaTime;
   1103   INT maxComp = h_sbrMHDet->mhParams->maxComp;
   1104 
   1105   int est;
   1106 
   1107   /*
   1108   Buffer values.
   1109   */
   1110   FDK_ASSERT(move<=(MAX_NO_OF_ESTIMATES>>1));
   1111   FDK_ASSERT(noEstPerFrame<=(MAX_NO_OF_ESTIMATES>>1));
   1112 
   1113   FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES];
   1114   FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES];
   1115   FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES];
   1116 
   1117   for (est=0; est < MAX_NO_OF_ESTIMATES/2; est++) {
   1118     sfmSbr[est]       = h_sbrMHDet->sfmSbr[est];
   1119     sfmOrig[est]      = h_sbrMHDet->sfmOrig[est];
   1120     tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est];
   1121   }
   1122 
   1123   C_ALLOC_SCRATCH_START(scratch_mem, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
   1124   FIXP_DBL *scratch = scratch_mem;
   1125   for (; est < MAX_NO_OF_ESTIMATES; est++) {
   1126     sfmSbr[est]       = scratch; scratch+=MAX_FREQ_COEFFS;
   1127     sfmOrig[est]      = scratch; scratch+=MAX_FREQ_COEFFS;
   1128     tonalityDiff[est] = scratch; scratch+=MAX_FREQ_COEFFS;
   1129   }
   1130 
   1131 
   1132 
   1133   /* Determine if we're allowed to detect "missing harmonics" that wasn't detected before.
   1134      In order to be allowed to do new detection, there must be a transient in the current
   1135      frame, or a transient in the previous frame sufficiently close to the current frame. */
   1136   newDetectionAllowed = isDetectionOfNewToneAllowed(pFrameInfo,
   1137                                                     &transientDetStart,
   1138                                                     noEstPerFrame,
   1139                                                     prevTransientFrame,
   1140                                                     prevTransientPos,
   1141                                                     prevTransientFlag,
   1142                                                     transientPosOffset,
   1143                                                     transientFlag,
   1144                                                     transientPos,
   1145                                                     deltaTime,
   1146                                                     h_sbrMHDet);
   1147 
   1148   /* Calulate the variables that will be used subsequently for the actual detection */
   1149   calculateDetectorInput(pQuotaBuffer,
   1150                          indexVector,
   1151                          tonalityDiff,
   1152                          sfmOrig,
   1153                          sfmSbr,
   1154                          freqBandTable,
   1155                          nSfb,
   1156                          noEstPerFrame,
   1157                          move);
   1158 
   1159   /* Do the actual detection using information from previous detections */
   1160   detectionWithPrediction(pQuotaBuffer,
   1161                           tonalityDiff,
   1162                           pSignBuffer,
   1163                           nSfb,
   1164                           freqBandTable,
   1165                           sfmOrig,
   1166                           sfmSbr,
   1167                           detectionVectors,
   1168                           h_sbrMHDet->guideScfb,
   1169                           guideVectors,
   1170                           noEstPerFrame,
   1171                           transientDetStart,
   1172                           totNoEst,
   1173                           newDetectionAllowed,
   1174                           pAddHarmonicsFlag,
   1175                           pAddHarmonicsScaleFactorBands,
   1176                           pNrgVector,
   1177                           h_sbrMHDet->mhParams);
   1178 
   1179   /* Calculate the comp vector, so that the energy can be
   1180      compensated for a sine between two QMF-bands. */
   1181   calculateCompVector(pAddHarmonicsScaleFactorBands,
   1182                       pQuotaBuffer,
   1183                       pSignBuffer,
   1184                       envelopeCompensation,
   1185                       nSfb,
   1186                       freqBandTable,
   1187                       totNoEst,
   1188                       maxComp,
   1189                       h_sbrMHDet->prevEnvelopeCompensation,
   1190                       newDetectionAllowed);
   1191 
   1192   for (est=0; est < move; est++) {
   1193     FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1194     FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1195     FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1196   }
   1197   C_ALLOC_SCRATCH_END(scratch, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
   1198 
   1199 
   1200 }
   1201 
   1202 /**************************************************************************/
   1203 /*!
   1204   \brief     Initialize an instance of the missing harmonics detector.
   1205 
   1206 
   1207   \return    errorCode, noError if OK.
   1208 
   1209 */
   1210 /**************************************************************************/
   1211 INT
   1212 FDKsbrEnc_CreateSbrMissingHarmonicsDetector (
   1213                                    HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
   1214                                    INT chan)
   1215 {
   1216   HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1217   INT i;
   1218 
   1219   UCHAR* detectionVectors    = GetRam_Sbr_detectionVectors(chan);
   1220   UCHAR* guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan);
   1221   FIXP_DBL* guideVectorDiff  = GetRam_Sbr_guideVectorDiff(chan);
   1222   FIXP_DBL* guideVectorOrig  = GetRam_Sbr_guideVectorOrig(chan);
   1223 
   1224   FDKmemclear (hs,sizeof(SBR_MISSING_HARMONICS_DETECTOR));
   1225 
   1226   hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan);
   1227   hs->guideScfb                = GetRam_Sbr_guideScfb(chan);
   1228 
   1229   for(i=0; i<MAX_NO_OF_ESTIMATES; i++) {
   1230     hs->guideVectors[i].guideVectorDiff = guideVectorDiff + (i*MAX_FREQ_COEFFS);
   1231     hs->guideVectors[i].guideVectorOrig = guideVectorOrig + (i*MAX_FREQ_COEFFS);
   1232     hs->detectionVectors[i] = detectionVectors + (i*MAX_FREQ_COEFFS);
   1233     hs->guideVectors[i].guideVectorDetected = guideVectorDetected + (i*MAX_FREQ_COEFFS);
   1234   }
   1235 
   1236   return 0;
   1237 }
   1238 
   1239 
   1240 /**************************************************************************/
   1241 /*!
   1242   \brief     Initialize an instance of the missing harmonics detector.
   1243 
   1244 
   1245   \return    errorCode, noError if OK.
   1246 
   1247 */
   1248 /**************************************************************************/
   1249 INT
   1250 FDKsbrEnc_InitSbrMissingHarmonicsDetector (
   1251                                    HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
   1252                                    INT sampleFreq,
   1253                                    INT frameSize,
   1254                                    INT nSfb,
   1255                                    INT qmfNoChannels,
   1256                                    INT totNoEst,
   1257                                    INT move,
   1258                                    INT noEstPerFrame,
   1259                                    UINT sbrSyntaxFlags
   1260                                   )
   1261 {
   1262   HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1263   int i;
   1264 
   1265   FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES);
   1266 
   1267   if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
   1268   {
   1269     switch(frameSize){
   1270     case 1024:
   1271     case 512:
   1272         hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
   1273         hs->timeSlots          = 16;
   1274         break;
   1275     case 960:
   1276     case 480:
   1277         hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
   1278         hs->timeSlots          = 15;
   1279         break;
   1280     default:
   1281         return -1;
   1282     }
   1283   } else
   1284   {
   1285     switch(frameSize){
   1286     case 2048:
   1287     case 1024:
   1288         hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048;
   1289         hs->timeSlots          = NUMBER_TIME_SLOTS_2048;
   1290         break;
   1291     case 1920:
   1292     case 960:
   1293         hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920;
   1294         hs->timeSlots          = NUMBER_TIME_SLOTS_1920;
   1295         break;
   1296     default:
   1297         return -1;
   1298     }
   1299   }
   1300 
   1301   if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
   1302     hs->mhParams = &paramsAacLd;
   1303   } else
   1304   hs->mhParams = &paramsAac;
   1305 
   1306   hs->qmfNoChannels = qmfNoChannels;
   1307   hs->sampleFreq = sampleFreq;
   1308   hs->nSfb = nSfb;
   1309 
   1310   hs->totNoEst = totNoEst;
   1311   hs->move = move;
   1312   hs->noEstPerFrame = noEstPerFrame;
   1313 
   1314   for(i=0; i<totNoEst; i++) {
   1315     FDKmemclear (hs->guideVectors[i].guideVectorDiff,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1316     FDKmemclear (hs->guideVectors[i].guideVectorOrig,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1317     FDKmemclear (hs->detectionVectors[i],sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1318     FDKmemclear (hs->guideVectors[i].guideVectorDetected,sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1319   }
   1320 
   1321   //for(i=0; i<totNoEst/2; i++) {
   1322   for(i=0; i<MAX_NO_OF_ESTIMATES/2; i++) {
   1323     FDKmemclear (hs->tonalityDiff[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1324     FDKmemclear (hs->sfmOrig[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1325     FDKmemclear (hs->sfmSbr[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1326   }
   1327 
   1328   FDKmemclear ( hs->prevEnvelopeCompensation, sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1329   FDKmemclear ( hs->guideScfb, sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1330 
   1331   hs->previousTransientFlag = 0;
   1332   hs->previousTransientFrame = 0;
   1333   hs->previousTransientPos = 0;
   1334 
   1335   return (0);
   1336 }
   1337 
   1338 /**************************************************************************/
   1339 /*!
   1340   \brief     Deletes an instance of the missing harmonics detector.
   1341 
   1342 
   1343   \return    none.
   1344 
   1345 */
   1346 /**************************************************************************/
   1347 void
   1348 FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet)
   1349 {
   1350   if (hSbrMHDet) {
   1351     HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1352 
   1353     FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]);
   1354     FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected);
   1355     FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff);
   1356     FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig);
   1357     FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation);
   1358     FreeRam_Sbr_guideScfb(&hs->guideScfb);
   1359 
   1360   }
   1361 }
   1362 
   1363 /**************************************************************************/
   1364 /*!
   1365   \brief     Resets an instance of the missing harmonics detector.
   1366 
   1367 
   1368   \return    error code, noError if OK.
   1369 
   1370 */
   1371 /**************************************************************************/
   1372 INT
   1373 FDKsbrEnc_ResetSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector,
   1374                                   INT nSfb)
   1375 {
   1376   int i;
   1377   FIXP_DBL tempGuide[MAX_FREQ_COEFFS];
   1378   UCHAR tempGuideInt[MAX_FREQ_COEFFS];
   1379   INT nSfbPrev;
   1380 
   1381   nSfbPrev = hSbrMissingHarmonicsDetector->nSfb;
   1382   hSbrMissingHarmonicsDetector->nSfb = nSfb;
   1383 
   1384   FDKmemcpy( tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, nSfbPrev * sizeof(UCHAR) );
   1385 
   1386   if ( nSfb > nSfbPrev ) {
   1387     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1388       hSbrMissingHarmonicsDetector->guideScfb[i] = 0;
   1389     }
   1390 
   1391     for ( i = 0; i < nSfbPrev; i++ ) {
   1392       hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1393     }
   1394   }
   1395   else {
   1396     for ( i = 0; i < nSfb; i++ ) {
   1397       hSbrMissingHarmonicsDetector->guideScfb[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1398     }
   1399   }
   1400 
   1401   FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, nSfbPrev * sizeof(FIXP_DBL) );
   1402 
   1403   if (nSfb > nSfbPrev ) {
   1404     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1405       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
   1406     }
   1407 
   1408     for ( i = 0; i < nSfbPrev; i++ ) {
   1409       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i];
   1410     }
   1411   }
   1412   else {
   1413     for ( i = 0; i < nSfb; i++  ) {
   1414       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = tempGuide[i + (nSfbPrev-nSfb)];
   1415     }
   1416   }
   1417 
   1418   FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, nSfbPrev * sizeof(FIXP_DBL) );
   1419 
   1420   if ( nSfb > nSfbPrev ) {
   1421     for ( i = 0; i< (nSfb - nSfbPrev); i++ ) {
   1422       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
   1423     }
   1424 
   1425     for ( i = 0; i < nSfbPrev; i++ ) {
   1426       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i];
   1427     }
   1428   }
   1429   else {
   1430     for ( i = 0; i < nSfb; i++ ) {
   1431       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = tempGuide[i + (nSfbPrev-nSfb)];
   1432     }
   1433   }
   1434 
   1435   FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, nSfbPrev * sizeof(UCHAR) );
   1436 
   1437   if ( nSfb > nSfbPrev ) {
   1438     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1439       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0;
   1440     }
   1441 
   1442     for ( i = 0; i < nSfbPrev; i++ ) {
   1443       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1444     }
   1445   }
   1446   else {
   1447     for ( i = 0; i < nSfb; i++ ) {
   1448       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1449     }
   1450   }
   1451 
   1452   FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, nSfbPrev * sizeof(UCHAR) );
   1453 
   1454   if ( nSfb > nSfbPrev ) {
   1455     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1456       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0;
   1457     }
   1458 
   1459     for ( i = 0; i < nSfbPrev; i++ ) {
   1460       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1461     }
   1462   }
   1463   else {
   1464     for ( i = 0; i < nSfb; i++ ) {
   1465       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1466     }
   1467   }
   1468 
   1469   return 0;
   1470 }
   1471 
   1472