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 "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     Do detection for one tonality estimate.
    669 
    670 
    671   \return    none.
    672 
    673 */
    674 /**************************************************************************/
    675 static void detection(FIXP_DBL *quotaBuffer,
    676                       FIXP_DBL *pDiffVecScfb,
    677                       INT nSfb,
    678                       UCHAR *pHarmVec,
    679                       const UCHAR *pFreqBandTable,
    680                       FIXP_DBL *sfmOrig,
    681                       FIXP_DBL *sfmSbr,
    682                       GUIDE_VECTORS guideVectors,
    683                       GUIDE_VECTORS newGuideVectors,
    684                       THRES_HOLDS mhThresh)
    685 {
    686 
    687   INT i,j,ll, lu;
    688   FIXP_DBL thresTemp,thresOrig;
    689 
    690   /*
    691    * Do detection on the difference vector, i.e. the difference between
    692    * the original and the transposed.
    693    *********************************************************************/
    694   for(i=0;i<nSfb;i++){
    695 
    696     thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f))
    697                   ? fixMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide)
    698                   : mhThresh.thresHoldDiff;
    699 
    700     thresTemp = fixMin(thresTemp, mhThresh.thresHoldDiff);
    701 
    702     if(pDiffVecScfb[i] > thresTemp){
    703       pHarmVec[i] = 1;
    704       newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i];
    705     }
    706     else{
    707       /* If the guide wasn't zero, but the current level is to low,
    708          start tracking the decay on the tone in the original rather
    709          than the difference.*/
    710       if(guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
    711         guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide;
    712       }
    713     }
    714   }
    715 
    716   /*
    717    * Trace tones in the original signal that at one point
    718    * have been detected because they will be replaced by
    719    * multiple tones in the sbr signal.
    720    ****************************************************/
    721 
    722   for(i=0;i<nSfb;i++){
    723     ll = pFreqBandTable[i];
    724     lu = pFreqBandTable[i+1];
    725 
    726     thresOrig = fixMax(fMult(guideVectors.guideVectorOrig[i], mhThresh.decayGuideOrig), mhThresh.thresHoldToneGuide);
    727     thresOrig = fixMin(thresOrig, mhThresh.thresHoldTone);
    728 
    729     if(guideVectors.guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
    730       for(j= ll;j<lu;j++){
    731         if(quotaBuffer[j] > thresOrig){
    732           pHarmVec[i] = 1;
    733           newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
    734         }
    735       }
    736     }
    737   }
    738 
    739   /*
    740    * Check for multiple sines in the transposed signal,
    741    * where there is only one in the original.
    742    ****************************************************/
    743   thresOrig = mhThresh.thresHoldTone;
    744 
    745   for(i=0;i<nSfb;i++){
    746     ll = pFreqBandTable[i];
    747     lu = pFreqBandTable[i+1];
    748 
    749     if(pHarmVec[i] == 0){
    750       if(lu -ll > 1){
    751         for(j= ll;j<lu;j++){
    752           if(quotaBuffer[j] > thresOrig && (sfmSbr[i] > mhThresh.sfmThresSbr && sfmOrig[i] < mhThresh.sfmThresOrig)){
    753             pHarmVec[i] = 1;
    754             newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
    755           }
    756         }
    757       }
    758       else{
    759         if(i < nSfb -1){
    760           ll = pFreqBandTable[i];
    761 
    762           if(i>0){
    763             if(quotaBuffer[ll] > mhThresh.thresHoldTone && (pDiffVecScfb[i+1] < mhThresh.invThresHoldTone || pDiffVecScfb[i-1] < mhThresh.invThresHoldTone)){
    764                 pHarmVec[i] = 1;
    765                 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
    766             }
    767           }
    768           else{
    769             if(quotaBuffer[ll] > mhThresh.thresHoldTone && pDiffVecScfb[i+1] < mhThresh.invThresHoldTone){
    770                 pHarmVec[i] = 1;
    771                 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
    772             }
    773           }
    774         }
    775       }
    776     }
    777   }
    778 }
    779 
    780 
    781 /**************************************************************************/
    782 /*!
    783   \brief     Do detection for every tonality estimate, using forward prediction.
    784 
    785 
    786   \return    none.
    787 
    788 */
    789 /**************************************************************************/
    790 static void detectionWithPrediction(FIXP_DBL **quotaBuffer,
    791                                     FIXP_DBL **pDiffVecScfb,
    792                                     INT ** signBuffer,
    793                                     INT nSfb,
    794                                     const UCHAR* pFreqBandTable,
    795                                     FIXP_DBL **sfmOrig,
    796                                     FIXP_DBL **sfmSbr,
    797                                     UCHAR **detectionVectors,
    798                                     UCHAR *pPrevAddHarmSfb,
    799                                     GUIDE_VECTORS *guideVectors,
    800                                     INT noEstPerFrame,
    801                                     INT detectionStart,
    802                                     INT totNoEst,
    803                                     INT newDetectionAllowed,
    804                                     INT *pAddHarmFlag,
    805                                     UCHAR *pAddHarmSfb,
    806                                     FIXP_DBL *pNrgVector,
    807                                     const DETECTOR_PARAMETERS_MH *mhParams)
    808 {
    809   INT est = 0,i;
    810   INT start;
    811 
    812   FDKmemclear(pAddHarmSfb,nSfb*sizeof(UCHAR));
    813 
    814   if(newDetectionAllowed){
    815 
    816     if(totNoEst > 1){
    817       start = detectionStart;
    818 
    819       if (start != 0) {
    820         FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    821         FDKmemcpy(guideVectors[start].guideVectorOrig,guideVectors[0].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    822         FDKmemclear(guideVectors[start-1].guideVectorDetected,nSfb*sizeof(UCHAR));
    823       }
    824     }
    825     else{
    826       start = 0;
    827     }
    828   }
    829   else{
    830     start = 0;
    831   }
    832 
    833 
    834   for(est = start; est < totNoEst; est++){
    835 
    836     /*
    837     * Do detection on the current frame using
    838     * guide-info from the previous.
    839     *******************************************/
    840     if(est > 0){
    841       FDKmemcpy(guideVectors[est].guideVectorDetected,detectionVectors[est-1],nSfb*sizeof(UCHAR));
    842     }
    843 
    844     FDKmemclear(detectionVectors[est], nSfb*sizeof(UCHAR));
    845 
    846     if(est < totNoEst-1){
    847       FDKmemclear(guideVectors[est+1].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    848       FDKmemclear(guideVectors[est+1].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    849       FDKmemclear(guideVectors[est+1].guideVectorDetected,nSfb*sizeof(UCHAR));
    850 
    851       detection(quotaBuffer[est],
    852                 pDiffVecScfb[est],
    853                 nSfb,
    854                 detectionVectors[est],
    855                 pFreqBandTable,
    856                 sfmOrig[est],
    857                 sfmSbr[est],
    858                 guideVectors[est],
    859                 guideVectors[est+1],
    860                 mhParams->thresHolds);
    861     }
    862     else{
    863       FDKmemclear(guideVectors[est].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
    864       FDKmemclear(guideVectors[est].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
    865       FDKmemclear(guideVectors[est].guideVectorDetected,nSfb*sizeof(UCHAR));
    866 
    867       detection(quotaBuffer[est],
    868                 pDiffVecScfb[est],
    869                 nSfb,
    870                 detectionVectors[est],
    871                 pFreqBandTable,
    872                 sfmOrig[est],
    873                 sfmSbr[est],
    874                 guideVectors[est],
    875                 guideVectors[est],
    876                 mhParams->thresHolds);
    877     }
    878   }
    879 
    880 
    881   /* Clean up the detection.*/
    882   transientCleanUp(quotaBuffer,
    883                    nSfb,
    884                    detectionVectors,
    885                    pAddHarmSfb,
    886                    pPrevAddHarmSfb,
    887                    signBuffer,
    888                    pFreqBandTable,
    889                    start,
    890                    totNoEst,
    891                    newDetectionAllowed,
    892                    pNrgVector,
    893                    mhParams->thresHolds);
    894 
    895 
    896   /* Set flag... */
    897   *pAddHarmFlag = 0;
    898   for(i=0; i<nSfb; i++){
    899     if(pAddHarmSfb[i]){
    900       *pAddHarmFlag = 1;
    901       break;
    902     }
    903   }
    904 
    905   FDKmemcpy(pPrevAddHarmSfb, pAddHarmSfb, nSfb*sizeof(UCHAR));
    906   FDKmemcpy(guideVectors[0].guideVectorDetected,pAddHarmSfb,nSfb*sizeof(INT));
    907 
    908   for(i=0; i<nSfb ; i++){
    909 
    910     guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
    911     guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
    912 
    913     if(pAddHarmSfb[i] == 1){
    914       /* If we had a detection use the guide-value in the next frame from the last estimate were the detection
    915       was done.*/
    916       for(est=start; est < totNoEst; est++){
    917         if(guideVectors[est].guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
    918           guideVectors[0].guideVectorDiff[i] = guideVectors[est].guideVectorDiff[i];
    919         }
    920         if(guideVectors[est].guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
    921           guideVectors[0].guideVectorOrig[i] = guideVectors[est].guideVectorOrig[i];
    922         }
    923       }
    924     }
    925   }
    926 
    927 }
    928 
    929 
    930 /**************************************************************************/
    931 /*!
    932   \brief     Calculates a compensation vector for the energy data.
    933 
    934   This function calculates a compensation vector for the energy data (i.e.
    935   envelope data) that is calculated elsewhere. This is since, one sine on
    936   the border of two scalefactor bands, will be replace by one sine in the
    937   middle of either scalefactor band. However, since the sine that is replaced
    938   will influence the energy estimate in both scalefactor bands (in the envelops
    939   calculation function) a compensation value is required in order to avoid
    940   noise substitution in the decoder next to the synthetic sine.
    941 
    942   \return    none.
    943 
    944 */
    945 /**************************************************************************/
    946 static void calculateCompVector(UCHAR *pAddHarmSfb,
    947                                 FIXP_DBL **pTonalityMatrix,
    948                                 INT ** pSignMatrix,
    949                                 UCHAR *pEnvComp,
    950                                 INT nSfb,
    951                                 const UCHAR *freqBandTable,
    952                                 INT totNoEst,
    953                                 INT maxComp,
    954                                 UCHAR *pPrevEnvComp,
    955                                 INT newDetectionAllowed)
    956 {
    957 
    958   INT scfBand,est,l,ll,lu,maxPosF,maxPosT;
    959   FIXP_DBL maxVal;
    960   INT compValue;
    961   FIXP_DBL tmp;
    962 
    963   FDKmemclear(pEnvComp,nSfb*sizeof(UCHAR));
    964 
    965   for(scfBand=0; scfBand < nSfb; scfBand++){
    966 
    967     if(pAddHarmSfb[scfBand]){ /* A missing sine was detected */
    968       ll = freqBandTable[scfBand];
    969       lu = freqBandTable[scfBand+1];
    970 
    971       maxPosF = 0;                        /* First find the maximum*/
    972       maxPosT = 0;
    973       maxVal = FL2FXCONST_DBL(0.0f);
    974 
    975       for(est=0;est<totNoEst;est++){
    976         for(l=ll; l<lu; l++){
    977           if(pTonalityMatrix[est][l] > maxVal){
    978             maxVal = pTonalityMatrix[est][l];
    979             maxPosF = l;
    980             maxPosT = est;
    981           }
    982         }
    983       }
    984 
    985       /*
    986        * If the maximum tonality is at the lower border of the
    987        * scalefactor band, we check the sign of the adjacent channels
    988        * to see if this sine is shared by the lower channel. If so, the
    989        * energy of the single sine will be present in two scalefactor bands
    990        * in the SBR data, which will cause problems in the decoder, when we
    991        * add a sine to just one of the channels.
    992        *********************************************************************/
    993       if(maxPosF == ll && scfBand){
    994         if(!pAddHarmSfb[scfBand - 1]) {     /* No detection below*/
    995           if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && pSignMatrix[maxPosT][maxPosF] < 0) {
    996             /* The comp value is calulated as the tonallity value, i.e we want to
    997                reduce the envelope data for this channel with as much as the tonality
    998                that is spread from the channel above. (ld64(RELAXATION) = 0.31143075889) */
    999             tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + RELAXATION_LD64);
   1000             tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1;  /* shift one bit less for rounding */
   1001             compValue = ((INT)(LONG)tmp) >> 1;
   1002 
   1003 						      /* limit the comp-value*/
   1004             if (compValue > maxComp)
   1005               compValue = maxComp;
   1006 
   1007             pEnvComp[scfBand-1] = compValue;
   1008 					     }
   1009 				    }
   1010       }
   1011 
   1012       /*
   1013        * Same as above, but for the upper end of the scalefactor-band.
   1014        ***************************************************************/
   1015       if(maxPosF == lu-1 && scfBand+1 < nSfb){        /* Upper border*/
   1016         if(!pAddHarmSfb[scfBand + 1]) {
   1017           if (pSignMatrix[maxPosT][maxPosF] > 0 && pSignMatrix[maxPosT][maxPosF + 1] < 0) {
   1018             tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + RELAXATION_LD64);
   1019             tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1;  /* shift one bit less for rounding */
   1020             compValue = ((INT)(LONG)tmp) >> 1;
   1021 
   1022             if (compValue > maxComp)
   1023               compValue = maxComp;
   1024 
   1025             pEnvComp[scfBand+1] = compValue;
   1026 					 }
   1027 				 }
   1028       }
   1029 		 }
   1030 	 }
   1031 
   1032   if(newDetectionAllowed == 0){
   1033     for(scfBand=0;scfBand<nSfb;scfBand++){
   1034       if(pEnvComp[scfBand] != 0 && pPrevEnvComp[scfBand] == 0)
   1035         pEnvComp[scfBand] = 0;
   1036     }
   1037   }
   1038 
   1039   /* remember the value for the next frame.*/
   1040   FDKmemcpy(pPrevEnvComp,pEnvComp,nSfb*sizeof(UCHAR));
   1041 }
   1042 
   1043 
   1044 /**************************************************************************/
   1045 /*!
   1046   \brief     Detects where strong tonal components will be missing after
   1047              HFR in the decoder.
   1048 
   1049 
   1050   \return    none.
   1051 
   1052 */
   1053 /**************************************************************************/
   1054 void
   1055 FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet,
   1056                                FIXP_DBL ** pQuotaBuffer,
   1057                                INT ** pSignBuffer,
   1058                                SCHAR* indexVector,
   1059                                const SBR_FRAME_INFO *pFrameInfo,
   1060                                const UCHAR* pTranInfo,
   1061                                INT* pAddHarmonicsFlag,
   1062                                UCHAR* pAddHarmonicsScaleFactorBands,
   1063                                const UCHAR* freqBandTable,
   1064                                INT nSfb,
   1065                                UCHAR* envelopeCompensation,
   1066                                FIXP_DBL *pNrgVector)
   1067 {
   1068   INT transientFlag = pTranInfo[1];
   1069   INT transientPos  = pTranInfo[0];
   1070   INT newDetectionAllowed;
   1071   INT transientDetStart = 0;
   1072 
   1073   UCHAR ** detectionVectors  = h_sbrMHDet->detectionVectors;
   1074   INT move                = h_sbrMHDet->move;
   1075   INT noEstPerFrame       = h_sbrMHDet->noEstPerFrame;
   1076   INT totNoEst            = h_sbrMHDet->totNoEst;
   1077   INT prevTransientFlag   = h_sbrMHDet->previousTransientFlag;
   1078   INT prevTransientFrame  = h_sbrMHDet->previousTransientFrame;
   1079   INT transientPosOffset  = h_sbrMHDet->transientPosOffset;
   1080   INT prevTransientPos    = h_sbrMHDet->previousTransientPos;
   1081   GUIDE_VECTORS* guideVectors = h_sbrMHDet->guideVectors;
   1082   INT deltaTime = h_sbrMHDet->mhParams->deltaTime;
   1083   INT maxComp = h_sbrMHDet->mhParams->maxComp;
   1084 
   1085   int est;
   1086 
   1087   /*
   1088   Buffer values.
   1089   */
   1090   FDK_ASSERT(move<=(MAX_NO_OF_ESTIMATES>>1));
   1091   FDK_ASSERT(noEstPerFrame<=(MAX_NO_OF_ESTIMATES>>1));
   1092 
   1093   FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES];
   1094   FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES];
   1095   FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES];
   1096 
   1097   for (est=0; est < MAX_NO_OF_ESTIMATES/2; est++) {
   1098     sfmSbr[est]       = h_sbrMHDet->sfmSbr[est];
   1099     sfmOrig[est]      = h_sbrMHDet->sfmOrig[est];
   1100     tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est];
   1101   }
   1102 
   1103   C_ALLOC_SCRATCH_START(scratch_mem, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
   1104   FIXP_DBL *scratch = scratch_mem;
   1105   for (; est < MAX_NO_OF_ESTIMATES; est++) {
   1106     sfmSbr[est]       = scratch; scratch+=MAX_FREQ_COEFFS;
   1107     sfmOrig[est]      = scratch; scratch+=MAX_FREQ_COEFFS;
   1108     tonalityDiff[est] = scratch; scratch+=MAX_FREQ_COEFFS;
   1109   }
   1110 
   1111 
   1112 
   1113   /* Determine if we're allowed to detect "missing harmonics" that wasn't detected before.
   1114      In order to be allowed to do new detection, there must be a transient in the current
   1115      frame, or a transient in the previous frame sufficiently close to the current frame. */
   1116   newDetectionAllowed = isDetectionOfNewToneAllowed(pFrameInfo,
   1117                                                     &transientDetStart,
   1118                                                     noEstPerFrame,
   1119                                                     prevTransientFrame,
   1120                                                     prevTransientPos,
   1121                                                     prevTransientFlag,
   1122                                                     transientPosOffset,
   1123                                                     transientFlag,
   1124                                                     transientPos,
   1125                                                     deltaTime,
   1126                                                     h_sbrMHDet);
   1127 
   1128   /* Calulate the variables that will be used subsequently for the actual detection */
   1129   calculateDetectorInput(pQuotaBuffer,
   1130                          indexVector,
   1131                          tonalityDiff,
   1132                          sfmOrig,
   1133                          sfmSbr,
   1134                          freqBandTable,
   1135                          nSfb,
   1136                          noEstPerFrame,
   1137                          move);
   1138 
   1139   /* Do the actual detection using information from previous detections */
   1140   detectionWithPrediction(pQuotaBuffer,
   1141                           tonalityDiff,
   1142                           pSignBuffer,
   1143                           nSfb,
   1144                           freqBandTable,
   1145                           sfmOrig,
   1146                           sfmSbr,
   1147                           detectionVectors,
   1148                           h_sbrMHDet->guideScfb,
   1149                           guideVectors,
   1150                           noEstPerFrame,
   1151                           transientDetStart,
   1152                           totNoEst,
   1153                           newDetectionAllowed,
   1154                           pAddHarmonicsFlag,
   1155                           pAddHarmonicsScaleFactorBands,
   1156                           pNrgVector,
   1157                           h_sbrMHDet->mhParams);
   1158 
   1159   /* Calculate the comp vector, so that the energy can be
   1160      compensated for a sine between two QMF-bands. */
   1161   calculateCompVector(pAddHarmonicsScaleFactorBands,
   1162                       pQuotaBuffer,
   1163                       pSignBuffer,
   1164                       envelopeCompensation,
   1165                       nSfb,
   1166                       freqBandTable,
   1167                       totNoEst,
   1168                       maxComp,
   1169                       h_sbrMHDet->prevEnvelopeCompensation,
   1170                       newDetectionAllowed);
   1171 
   1172   for (est=0; est < move; est++) {
   1173     FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1174     FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1175     FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1176   }
   1177   C_ALLOC_SCRATCH_END(scratch, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
   1178 
   1179 
   1180 }
   1181 
   1182 /**************************************************************************/
   1183 /*!
   1184   \brief     Initialize an instance of the missing harmonics detector.
   1185 
   1186 
   1187   \return    errorCode, noError if OK.
   1188 
   1189 */
   1190 /**************************************************************************/
   1191 INT
   1192 FDKsbrEnc_CreateSbrMissingHarmonicsDetector (
   1193                                    HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
   1194                                    INT chan)
   1195 {
   1196   HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1197   INT i;
   1198 
   1199   UCHAR* detectionVectors    = GetRam_Sbr_detectionVectors(chan);
   1200   UCHAR* guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan);
   1201   FIXP_DBL* guideVectorDiff  = GetRam_Sbr_guideVectorDiff(chan);
   1202   FIXP_DBL* guideVectorOrig  = GetRam_Sbr_guideVectorOrig(chan);
   1203 
   1204   FDKmemclear (hs,sizeof(SBR_MISSING_HARMONICS_DETECTOR));
   1205 
   1206   hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan);
   1207   hs->guideScfb                = GetRam_Sbr_guideScfb(chan);
   1208 
   1209   for(i=0; i<MAX_NO_OF_ESTIMATES; i++) {
   1210     hs->guideVectors[i].guideVectorDiff = guideVectorDiff + (i*MAX_FREQ_COEFFS);
   1211     hs->guideVectors[i].guideVectorOrig = guideVectorOrig + (i*MAX_FREQ_COEFFS);
   1212     hs->detectionVectors[i] = detectionVectors + (i*MAX_FREQ_COEFFS);
   1213     hs->guideVectors[i].guideVectorDetected = guideVectorDetected + (i*MAX_FREQ_COEFFS);
   1214   }
   1215 
   1216   return 0;
   1217 }
   1218 
   1219 
   1220 /**************************************************************************/
   1221 /*!
   1222   \brief     Initialize an instance of the missing harmonics detector.
   1223 
   1224 
   1225   \return    errorCode, noError if OK.
   1226 
   1227 */
   1228 /**************************************************************************/
   1229 INT
   1230 FDKsbrEnc_InitSbrMissingHarmonicsDetector (
   1231                                    HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
   1232                                    INT sampleFreq,
   1233                                    INT frameSize,
   1234                                    INT nSfb,
   1235                                    INT qmfNoChannels,
   1236                                    INT totNoEst,
   1237                                    INT move,
   1238                                    INT noEstPerFrame,
   1239                                    UINT sbrSyntaxFlags
   1240                                   )
   1241 {
   1242   HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1243   int i;
   1244 
   1245   FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES);
   1246 
   1247   if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
   1248   {
   1249     switch(frameSize){
   1250     case 1024:
   1251     case 512:
   1252         hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
   1253         hs->timeSlots          = 16;
   1254         break;
   1255     case 960:
   1256     case 480:
   1257         hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
   1258         hs->timeSlots          = 15;
   1259         break;
   1260     default:
   1261         return -1;
   1262     }
   1263   } else
   1264   {
   1265     switch(frameSize){
   1266     case 2048:
   1267     case 1024:
   1268         hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048;
   1269         hs->timeSlots          = NUMBER_TIME_SLOTS_2048;
   1270         break;
   1271     case 1920:
   1272     case 960:
   1273         hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920;
   1274         hs->timeSlots          = NUMBER_TIME_SLOTS_1920;
   1275         break;
   1276     default:
   1277         return -1;
   1278     }
   1279   }
   1280 
   1281   if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
   1282     hs->mhParams = &paramsAacLd;
   1283   } else
   1284   hs->mhParams = &paramsAac;
   1285 
   1286   hs->qmfNoChannels = qmfNoChannels;
   1287   hs->sampleFreq = sampleFreq;
   1288   hs->nSfb = nSfb;
   1289 
   1290   hs->totNoEst = totNoEst;
   1291   hs->move = move;
   1292   hs->noEstPerFrame = noEstPerFrame;
   1293 
   1294   for(i=0; i<totNoEst; i++) {
   1295     FDKmemclear (hs->guideVectors[i].guideVectorDiff,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1296     FDKmemclear (hs->guideVectors[i].guideVectorOrig,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1297     FDKmemclear (hs->detectionVectors[i],sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1298     FDKmemclear (hs->guideVectors[i].guideVectorDetected,sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1299   }
   1300 
   1301   //for(i=0; i<totNoEst/2; i++) {
   1302   for(i=0; i<MAX_NO_OF_ESTIMATES/2; i++) {
   1303     FDKmemclear (hs->tonalityDiff[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1304     FDKmemclear (hs->sfmOrig[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1305     FDKmemclear (hs->sfmSbr[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
   1306   }
   1307 
   1308   FDKmemclear ( hs->prevEnvelopeCompensation, sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1309   FDKmemclear ( hs->guideScfb, sizeof(UCHAR)*MAX_FREQ_COEFFS);
   1310 
   1311   hs->previousTransientFlag = 0;
   1312   hs->previousTransientFrame = 0;
   1313   hs->previousTransientPos = 0;
   1314 
   1315   return (0);
   1316 }
   1317 
   1318 /**************************************************************************/
   1319 /*!
   1320   \brief     Deletes an instance of the missing harmonics detector.
   1321 
   1322 
   1323   \return    none.
   1324 
   1325 */
   1326 /**************************************************************************/
   1327 void
   1328 FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet)
   1329 {
   1330   if (hSbrMHDet) {
   1331     HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
   1332 
   1333     FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]);
   1334     FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected);
   1335     FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff);
   1336     FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig);
   1337     FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation);
   1338     FreeRam_Sbr_guideScfb(&hs->guideScfb);
   1339 
   1340   }
   1341 }
   1342 
   1343 /**************************************************************************/
   1344 /*!
   1345   \brief     Resets an instance of the missing harmonics detector.
   1346 
   1347 
   1348   \return    error code, noError if OK.
   1349 
   1350 */
   1351 /**************************************************************************/
   1352 INT
   1353 FDKsbrEnc_ResetSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector,
   1354                                   INT nSfb)
   1355 {
   1356   int i;
   1357   FIXP_DBL tempGuide[MAX_FREQ_COEFFS];
   1358   UCHAR tempGuideInt[MAX_FREQ_COEFFS];
   1359   INT nSfbPrev;
   1360 
   1361   nSfbPrev = hSbrMissingHarmonicsDetector->nSfb;
   1362   hSbrMissingHarmonicsDetector->nSfb = nSfb;
   1363 
   1364   FDKmemcpy( tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, nSfbPrev * sizeof(UCHAR) );
   1365 
   1366   if ( nSfb > nSfbPrev ) {
   1367     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1368       hSbrMissingHarmonicsDetector->guideScfb[i] = 0;
   1369     }
   1370 
   1371     for ( i = 0; i < nSfbPrev; i++ ) {
   1372       hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1373     }
   1374   }
   1375   else {
   1376     for ( i = 0; i < nSfb; i++ ) {
   1377       hSbrMissingHarmonicsDetector->guideScfb[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1378     }
   1379   }
   1380 
   1381   FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, nSfbPrev * sizeof(FIXP_DBL) );
   1382 
   1383   if (nSfb > nSfbPrev ) {
   1384     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1385       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
   1386     }
   1387 
   1388     for ( i = 0; i < nSfbPrev; i++ ) {
   1389       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i];
   1390     }
   1391   }
   1392   else {
   1393     for ( i = 0; i < nSfb; i++  ) {
   1394       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = tempGuide[i + (nSfbPrev-nSfb)];
   1395     }
   1396   }
   1397 
   1398   FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, nSfbPrev * sizeof(FIXP_DBL) );
   1399 
   1400   if ( nSfb > nSfbPrev ) {
   1401     for ( i = 0; i< (nSfb - nSfbPrev); i++ ) {
   1402       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
   1403     }
   1404 
   1405     for ( i = 0; i < nSfbPrev; i++ ) {
   1406       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i];
   1407     }
   1408   }
   1409   else {
   1410     for ( i = 0; i < nSfb; i++ ) {
   1411       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = tempGuide[i + (nSfbPrev-nSfb)];
   1412     }
   1413   }
   1414 
   1415   FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, nSfbPrev * sizeof(UCHAR) );
   1416 
   1417   if ( nSfb > nSfbPrev ) {
   1418     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1419       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0;
   1420     }
   1421 
   1422     for ( i = 0; i < nSfbPrev; i++ ) {
   1423       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1424     }
   1425   }
   1426   else {
   1427     for ( i = 0; i < nSfb; i++ ) {
   1428       hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1429     }
   1430   }
   1431 
   1432   FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, nSfbPrev * sizeof(UCHAR) );
   1433 
   1434   if ( nSfb > nSfbPrev ) {
   1435     for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
   1436       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0;
   1437     }
   1438 
   1439     for ( i = 0; i < nSfbPrev; i++ ) {
   1440       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
   1441     }
   1442   }
   1443   else {
   1444     for ( i = 0; i < nSfb; i++ ) {
   1445       hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
   1446     }
   1447   }
   1448 
   1449   return 0;
   1450 }
   1451 
   1452