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