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