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