Coverage Report

Created: 2023-03-26 06:13

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