• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung 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@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 /**************************************************************************/
diff(FIXP_DBL * RESTRICT pTonalityOrig,FIXP_DBL * pDiffMapped2Scfb,const UCHAR * RESTRICT pFreqBandTable,INT nScfb,SCHAR * indexVector)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 /**************************************************************************/
calculateFlatnessMeasure(FIXP_DBL * pQuotaBuffer,SCHAR * indexVector,FIXP_DBL * pSfmOrigVec,FIXP_DBL * pSfmSbrVec,const UCHAR * pFreqBandTable,INT nSfb)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 /**************************************************************************/
calculateDetectorInput(FIXP_DBL ** RESTRICT pQuotaBuffer,SCHAR * RESTRICT indexVector,FIXP_DBL ** RESTRICT tonalityDiff,FIXP_DBL ** RESTRICT pSfmOrig,FIXP_DBL ** RESTRICT pSfmSbr,const UCHAR * freqBandTable,INT nSfb,INT noEstPerFrame,INT move)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 /**************************************************************************/
removeLowPassDetection(UCHAR * RESTRICT pAddHarmSfb,UCHAR ** RESTRICT pDetectionVectors,INT start,INT stop,INT nSfb,const UCHAR * RESTRICT pFreqBandTable,FIXP_DBL * RESTRICT pNrgVector,THRES_HOLDS mhThresh)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 /**************************************************************************/
isDetectionOfNewToneAllowed(const SBR_FRAME_INFO * pFrameInfo,INT * pDetectionStartPos,INT noEstPerFrame,INT prevTransientFrame,INT prevTransientPos,INT prevTransientFlag,INT transientPosOffset,INT transientFlag,INT transientPos,INT deltaTime,HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector)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 /**************************************************************************/
transientCleanUp(FIXP_DBL ** quotaBuffer,INT nSfb,UCHAR ** detectionVectors,UCHAR * pAddHarmSfb,UCHAR * pPrevAddHarmSfb,INT ** signBuffer,const UCHAR * pFreqBandTable,INT start,INT stop,INT newDetectionAllowed,FIXP_DBL * pNrgVector,THRES_HOLDS mhThresh)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 /**************************************************************************/
detection(FIXP_DBL * quotaBuffer,FIXP_DBL * pDiffVecScfb,INT nSfb,UCHAR * pHarmVec,const UCHAR * pFreqBandTable,FIXP_DBL * sfmOrig,FIXP_DBL * sfmSbr,GUIDE_VECTORS guideVectors,GUIDE_VECTORS newGuideVectors,THRES_HOLDS mhThresh)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 /**************************************************************************/
detectionWithPrediction(FIXP_DBL ** quotaBuffer,FIXP_DBL ** pDiffVecScfb,INT ** signBuffer,INT nSfb,const UCHAR * pFreqBandTable,FIXP_DBL ** sfmOrig,FIXP_DBL ** sfmSbr,UCHAR ** detectionVectors,UCHAR * pPrevAddHarmSfb,GUIDE_VECTORS * guideVectors,INT noEstPerFrame,INT detectionStart,INT totNoEst,INT newDetectionAllowed,INT * pAddHarmFlag,UCHAR * pAddHarmSfb,FIXP_DBL * pNrgVector,const DETECTOR_PARAMETERS_MH * mhParams)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 /**************************************************************************/
calculateCompVector(UCHAR * pAddHarmSfb,FIXP_DBL ** pTonalityMatrix,INT ** pSignMatrix,UCHAR * pEnvComp,INT nSfb,const UCHAR * freqBandTable,INT totNoEst,INT maxComp,UCHAR * pPrevEnvComp,INT newDetectionAllowed)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 /**************************************************************************/
FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet,FIXP_DBL ** pQuotaBuffer,INT ** pSignBuffer,SCHAR * indexVector,const SBR_FRAME_INFO * pFrameInfo,const UCHAR * pTranInfo,INT * pAddHarmonicsFlag,UCHAR * pAddHarmonicsScaleFactorBands,const UCHAR * freqBandTable,INT nSfb,UCHAR * envelopeCompensation,FIXP_DBL * pNrgVector)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 /**************************************************************************/
FDKsbrEnc_CreateSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,INT chan)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 /**************************************************************************/
FDKsbrEnc_InitSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,INT sampleFreq,INT frameSize,INT nSfb,INT qmfNoChannels,INT totNoEst,INT move,INT noEstPerFrame,UINT sbrSyntaxFlags)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 /**************************************************************************/
FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet)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 /**************************************************************************/
FDKsbrEnc_ResetSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector,INT nSfb)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