• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6 
7  1.    INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18 
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28 
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33 
34 2.    COPYRIGHT LICENSE
35 
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39 
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42 
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48 
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51 
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54 
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60 
61 3.    NO PATENT LICENSE
62 
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67 
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70 
71 4.    DISCLAIMER
72 
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83 
84 5.    CONTACT INFORMATION
85 
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90 
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94 
95 /**************************** SBR encoder library ******************************
96 
97    Author(s):
98 
99    Description:
100 
101 *******************************************************************************/
102 
103 #include "invf_est.h"
104 #include "sbr_misc.h"
105 
106 #include "genericStds.h"
107 
108 #define MAX_NUM_REGIONS 10
109 #define SCALE_FAC_QUO 512.0f
110 #define SCALE_FAC_NRG 256.0f
111 
112 #ifndef min
113 #define min(a, b) (a < b ? a : b)
114 #endif
115 
116 #ifndef max
117 #define max(a, b) (a > b ? a : b)
118 #endif
119 
120 static const FIXP_DBL quantStepsSbr[4] = {
121     0x00400000, 0x02800000, 0x03800000,
122     0x04c00000}; /* table scaled with SCALE_FAC_QUO */
123 static const FIXP_DBL quantStepsOrig[4] = {
124     0x00000000, 0x00c00000, 0x01c00000,
125     0x02800000}; /* table scaled with SCALE_FAC_QUO */
126 static const FIXP_DBL nrgBorders[4] = {
127     0x0c800000, 0x0f000000, 0x11800000,
128     0x14000000}; /* table scaled with SCALE_FAC_NRG */
129 
130 static const DETECTOR_PARAMETERS detectorParamsAAC = {
131     quantStepsSbr,
132     quantStepsOrig,
133     nrgBorders,
134     4, /* Number of borders SBR. */
135     4, /* Number of borders orig. */
136     4, /* Number of borders Nrg. */
137     {
138         /* Region space. */
139         {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF,
140          INVF_OFF}, /*    |      */
141         {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF,
142          INVF_OFF}, /*    |      */
143         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
144          INVF_OFF}, /* regionSbr */
145         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
146          INVF_OFF}, /*    |      */
147         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
148          INVF_OFF} /*    |      */
149     }, /*------------------------ regionOrig ---------------------------------*/
150     {
151         /* Region space transient. */
152         {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
153          INVF_OFF}, /*    |      */
154         {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
155          INVF_OFF}, /*    |      */
156         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
157          INVF_OFF}, /* regionSbr */
158         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
159          INVF_OFF}, /*    |      */
160         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
161          INVF_OFF} /*    |      */
162     }, /*------------------------ regionOrig ---------------------------------*/
163     {-4, -3, -2, -1,
164      0} /* Reduction factor of the inverse filtering for low energies.*/
165 };
166 
167 static const FIXP_DBL hysteresis =
168     0x00400000; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */
169 
170 /*
171  * AAC+SBR PARAMETERS for Speech
172  *********************************/
173 static const DETECTOR_PARAMETERS detectorParamsAACSpeech = {
174     quantStepsSbr,
175     quantStepsOrig,
176     nrgBorders,
177     4, /* Number of borders SBR. */
178     4, /* Number of borders orig. */
179     4, /* Number of borders Nrg. */
180     {
181         /* Region space. */
182         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
183          INVF_OFF}, /*    |      */
184         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
185          INVF_OFF}, /*    |      */
186         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
187          INVF_OFF}, /* regionSbr */
188         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
189          INVF_OFF}, /*    |      */
190         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
191          INVF_OFF} /*    |      */
192     }, /*------------------------ regionOrig ---------------------------------*/
193     {
194         /* Region space transient. */
195         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
196          INVF_OFF}, /*    |      */
197         {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF,
198          INVF_OFF}, /*    |      */
199         {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF,
200          INVF_OFF}, /* regionSbr */
201         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
202          INVF_OFF}, /*    |      */
203         {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF,
204          INVF_OFF} /*    |      */
205     }, /*------------------------ regionOrig ---------------------------------*/
206     {-4, -3, -2, -1,
207      0} /* Reduction factor of the inverse filtering for low energies.*/
208 };
209 
210 /*
211  * Smoothing filters.
212  ************************/
213 typedef const FIXP_DBL FIR_FILTER[5];
214 
215 static const FIR_FILTER fir_0 = {0x7fffffff, 0x00000000, 0x00000000, 0x00000000,
216                                  0x00000000};
217 static const FIR_FILTER fir_1 = {0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000,
218                                  0x00000000};
219 static const FIR_FILTER fir_2 = {0x10000000, 0x30000000, 0x40000000, 0x00000000,
220                                  0x00000000};
221 static const FIR_FILTER fir_3 = {0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340,
222                                  0x00000000};
223 static const FIR_FILTER fir_4 = {0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0,
224                                  0x2aaaaa80};
225 
226 static const FIR_FILTER *const fir_table[5] = {&fir_0, &fir_1, &fir_2, &fir_3,
227                                                &fir_4};
228 
229 /**************************************************************************/
230 /*!
231   \brief     Calculates the values used for the detector.
232 
233 
234   \return    none
235 
236 */
237 /**************************************************************************/
calculateDetectorValues(FIXP_DBL ** quotaMatrixOrig,SCHAR * indexVector,FIXP_DBL * nrgVector,DETECTOR_VALUES * detectorValues,INT startChannel,INT stopChannel,INT startIndex,INT stopIndex,INT numberOfStrongest)238 static void calculateDetectorValues(
239     FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the
240                                    original. */
241     SCHAR *indexVector,         /*!< Index vector to obtain the patched data. */
242     FIXP_DBL *nrgVector,        /*!< Energy vector. */
243     DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */
244     INT startChannel,                /*!< Start channel. */
245     INT stopChannel,                 /*!< Stop channel. */
246     INT startIndex,                  /*!< Start index. */
247     INT stopIndex,                   /*!< Stop index. */
248     INT numberOfStrongest /*!< The number of sorted tonal components to be
249                              considered. */
250 ) {
251   INT i, temp, j;
252 
253   const FIXP_DBL *filter = *fir_table[INVF_SMOOTHING_LENGTH];
254   FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest;
255   FIXP_DBL origQuota, sbrQuota;
256   FIXP_DBL invIndex, invChannel, invTemp;
257   FIXP_DBL quotaVecOrig[64], quotaVecSbr[64];
258 
259   FDKmemclear(quotaVecOrig, 64 * sizeof(FIXP_DBL));
260   FDKmemclear(quotaVecSbr, 64 * sizeof(FIXP_DBL));
261 
262   invIndex = GetInvInt(stopIndex - startIndex);
263   invChannel = GetInvInt(stopChannel - startChannel);
264 
265   /*
266    Calculate the mean value, over the current time segment, for the original,
267    the HFR and the difference, over all channels in the current frequency range.
268    NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION).
269    */
270 
271   /* The original, the sbr signal and the total energy */
272   detectorValues->avgNrg = FL2FXCONST_DBL(0.0f);
273   for (j = startIndex; j < stopIndex; j++) {
274     for (i = startChannel; i < stopChannel; i++) {
275       quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex);
276 
277       if (indexVector[i] != -1)
278         quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex);
279     }
280     detectorValues->avgNrg += fMult(nrgVector[j], invIndex);
281   }
282 
283   /*
284    Calculate the mean value, over the current frequency range, for the original,
285    the HFR and the difference. Also calculate the same mean values for the three
286    vectors, but only includeing the x strongest copmponents.
287    */
288 
289   origQuota = FL2FXCONST_DBL(0.0f);
290   sbrQuota = FL2FXCONST_DBL(0.0f);
291   for (i = startChannel; i < stopChannel; i++) {
292     origQuota += fMultDiv2(quotaVecOrig[i], invChannel);
293     sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel);
294   }
295 
296   /*
297    Calculate the mean value for the x strongest components
298   */
299   FDKsbrEnc_Shellsort_fract(quotaVecOrig + startChannel,
300                             stopChannel - startChannel);
301   FDKsbrEnc_Shellsort_fract(quotaVecSbr + startChannel,
302                             stopChannel - startChannel);
303 
304   origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
305   sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
306 
307   temp = min(stopChannel - startChannel, numberOfStrongest);
308   invTemp = GetInvInt(temp);
309 
310   for (i = 0; i < temp; i++) {
311     origQuotaMeanStrongest +=
312         fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp);
313     sbrQuotaMeanStrongest +=
314         fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp);
315   }
316 
317   /*
318    The value for the strongest component
319   */
320   detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1];
321   detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1];
322 
323   /*
324    Buffer values
325   */
326   FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1,
327              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
328   FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1,
329              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
330   FDKmemmove(detectorValues->origQuotaMeanStrongest,
331              detectorValues->origQuotaMeanStrongest + 1,
332              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
333   FDKmemmove(detectorValues->sbrQuotaMeanStrongest,
334              detectorValues->sbrQuotaMeanStrongest + 1,
335              INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL));
336 
337   detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota << 1;
338   detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota << 1;
339   detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] =
340       origQuotaMeanStrongest << 1;
341   detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] =
342       sbrQuotaMeanStrongest << 1;
343 
344   /*
345    Filter values
346   */
347   detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
348   detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
349   detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
350   detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
351 
352   for (i = 0; i < INVF_SMOOTHING_LENGTH + 1; i++) {
353     detectorValues->origQuotaMeanFilt +=
354         fMult(detectorValues->origQuotaMean[i], filter[i]);
355     detectorValues->sbrQuotaMeanFilt +=
356         fMult(detectorValues->sbrQuotaMean[i], filter[i]);
357     detectorValues->origQuotaMeanStrongestFilt +=
358         fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]);
359     detectorValues->sbrQuotaMeanStrongestFilt +=
360         fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]);
361   }
362 }
363 
364 /**************************************************************************/
365 /*!
366   \brief     Returns the region in which the input value belongs.
367 
368 
369 
370   \return    region.
371 
372 */
373 /**************************************************************************/
findRegion(FIXP_DBL currVal,const FIXP_DBL * borders,const INT numBorders)374 static INT findRegion(
375     FIXP_DBL currVal,        /*!< The current value. */
376     const FIXP_DBL *borders, /*!< The border of the regions. */
377     const INT numBorders     /*!< The number of borders. */
378 ) {
379   INT i;
380 
381   if (currVal < borders[0]) {
382     return 0;
383   }
384 
385   for (i = 1; i < numBorders; i++) {
386     if (currVal >= borders[i - 1] && currVal < borders[i]) {
387       return i;
388     }
389   }
390 
391   if (currVal >= borders[numBorders - 1]) {
392     return numBorders;
393   }
394 
395   return 0; /* We never get here, it's just to avoid compiler warnings.*/
396 }
397 
398 /**************************************************************************/
399 /*!
400   \brief     Makes a clever decision based on the quota vector.
401 
402 
403   \return     decision on which invf mode to use
404 
405 */
406 /**************************************************************************/
decisionAlgorithm(const DETECTOR_PARAMETERS * detectorParams,DETECTOR_VALUES * detectorValues,INT transientFlag,INT * prevRegionSbr,INT * prevRegionOrig)407 static INVF_MODE decisionAlgorithm(
408     const DETECTOR_PARAMETERS
409         *detectorParams, /*!< Struct with the detector parameters. */
410     DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */
411     INT transientFlag,  /*!< Flag indicating if there is a transient present.*/
412     INT *prevRegionSbr, /*!< The previous region in which the Sbr value was. */
413     INT *prevRegionOrig /*!< The previous region in which the Orig value was. */
414 ) {
415   INT invFiltLevel, regionSbr, regionOrig, regionNrg;
416 
417   /*
418    Current thresholds.
419    */
420   const INT numRegionsSbr = detectorParams->numRegionsSbr;
421   const INT numRegionsOrig = detectorParams->numRegionsOrig;
422   const INT numRegionsNrg = detectorParams->numRegionsNrg;
423 
424   FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS];
425   FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS];
426 
427   /*
428    Current detector values.
429    */
430   FIXP_DBL origQuotaMeanFilt;
431   FIXP_DBL sbrQuotaMeanFilt;
432   FIXP_DBL nrg;
433 
434   /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 =
435    * log(16)/64.0; 0.6875 = 44/64.0 */
436   origQuotaMeanFilt =
437       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
438                  (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,
439                                            (FIXP_DBL)1)) +
440                             FL2FXCONST_DBL(0.31143075889f))))
441       << 0; /* scaled by 1/2^9 */
442   sbrQuotaMeanFilt =
443       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
444                  (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,
445                                            (FIXP_DBL)1)) +
446                             FL2FXCONST_DBL(0.31143075889f))))
447       << 0; /* scaled by 1/2^9 */
448   /* If energy is zero then we will get different results for different word
449    * lengths. */
450   nrg =
451       (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f),
452                  (FIXP_DBL)(CalcLdData(detectorValues->avgNrg + (FIXP_DBL)1) +
453                             FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f))))
454       << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */
455 
456   FDKmemcpy(quantStepsSbrTmp, detectorParams->quantStepsSbr,
457             numRegionsSbr * sizeof(FIXP_DBL));
458   FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig,
459             numRegionsOrig * sizeof(FIXP_DBL));
460 
461   if (*prevRegionSbr < numRegionsSbr)
462     quantStepsSbrTmp[*prevRegionSbr] =
463         detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis;
464   if (*prevRegionSbr > 0)
465     quantStepsSbrTmp[*prevRegionSbr - 1] =
466         detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis;
467 
468   if (*prevRegionOrig < numRegionsOrig)
469     quantStepsOrigTmp[*prevRegionOrig] =
470         detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis;
471   if (*prevRegionOrig > 0)
472     quantStepsOrigTmp[*prevRegionOrig - 1] =
473         detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis;
474 
475   regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr);
476   regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig);
477   regionNrg = findRegion(nrg, detectorParams->nrgBorders, numRegionsNrg);
478 
479   *prevRegionSbr = regionSbr;
480   *prevRegionOrig = regionOrig;
481 
482   /* Use different settings if a transient is present*/
483   invFiltLevel =
484       (transientFlag == 1)
485           ? detectorParams->regionSpaceTransient[regionSbr][regionOrig]
486           : detectorParams->regionSpace[regionSbr][regionOrig];
487 
488   /* Compensate for low energy.*/
489   invFiltLevel =
490       max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg], 0);
491 
492   return (INVF_MODE)(invFiltLevel);
493 }
494 
495 /**************************************************************************/
496 /*!
497   \brief     Estiamtion of the inverse filtering level required
498              in the decoder.
499 
500    A second order LPC is calculated for every filterbank channel, using
501    the covariance method. THe ratio between the energy of the predicted
502    signal and the energy of the non-predictable signal is calcualted.
503 
504   \return    none.
505 
506 */
507 /**************************************************************************/
FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt,FIXP_DBL ** quotaMatrix,FIXP_DBL * nrgVector,SCHAR * indexVector,INT startIndex,INT stopIndex,INT transientFlag,INVF_MODE * infVec)508 void FDKsbrEnc_qmfInverseFilteringDetector(
509     HANDLE_SBR_INV_FILT_EST
510         hInvFilt,           /*!< Handle to the SBR_INV_FILT_EST struct. */
511     FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the
512                                original. */
513     FIXP_DBL *nrgVector,    /*!< The energy vector. */
514     SCHAR *indexVector,     /*!< Index vector to obtain the patched data. */
515     INT startIndex,         /*!< Start index. */
516     INT stopIndex,          /*!< Stop index. */
517     INT transientFlag, /*!< Flag indicating if a transient is present or not.*/
518     INVF_MODE *infVec  /*!< Vector holding the inverse filtering levels. */
519 ) {
520   INT band;
521 
522   /*
523    * Do the inverse filtering level estimation.
524    *****************************************************/
525   for (band = 0; band < hInvFilt->noDetectorBands; band++) {
526     INT startChannel = hInvFilt->freqBandTableInvFilt[band];
527     INT stopChannel = hInvFilt->freqBandTableInvFilt[band + 1];
528 
529     calculateDetectorValues(quotaMatrix, indexVector, nrgVector,
530                             &hInvFilt->detectorValues[band], startChannel,
531                             stopChannel, startIndex, stopIndex,
532                             hInvFilt->numberOfStrongest);
533 
534     infVec[band] = decisionAlgorithm(
535         hInvFilt->detectorParams, &hInvFilt->detectorValues[band],
536         transientFlag, &hInvFilt->prevRegionSbr[band],
537         &hInvFilt->prevRegionOrig[band]);
538   }
539 }
540 
541 /**************************************************************************/
542 /*!
543   \brief     Initialize an instance of the inverse filtering level estimator.
544 
545 
546   \return   errorCode, noError if successful.
547 
548 */
549 /**************************************************************************/
FDKsbrEnc_initInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt,INT * freqBandTableDetector,INT numDetectorBands,UINT useSpeechConfig)550 INT FDKsbrEnc_initInvFiltDetector(
551     HANDLE_SBR_INV_FILT_EST
552         hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */
553     INT *freqBandTableDetector, /*!< Frequency band table for the inverse
554                                    filtering. */
555     INT numDetectorBands,       /*!< Number of inverse filtering bands. */
556     UINT
557         useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/
558 ) {
559   INT i;
560 
561   FDKmemclear(hInvFilt, sizeof(SBR_INV_FILT_EST));
562 
563   hInvFilt->detectorParams =
564       (useSpeechConfig) ? &detectorParamsAACSpeech : &detectorParamsAAC;
565 
566   hInvFilt->noDetectorBandsMax = numDetectorBands;
567 
568   /*
569      Memory initialisation
570   */
571   for (i = 0; i < hInvFilt->noDetectorBandsMax; i++) {
572     FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES));
573     hInvFilt->prevInvfMode[i] = INVF_OFF;
574     hInvFilt->prevRegionOrig[i] = 0;
575     hInvFilt->prevRegionSbr[i] = 0;
576   }
577 
578   /*
579   Reset the inverse fltering detector.
580   */
581   FDKsbrEnc_resetInvFiltDetector(hInvFilt, freqBandTableDetector,
582                                  hInvFilt->noDetectorBandsMax);
583 
584   return (0);
585 }
586 
587 /**************************************************************************/
588 /*!
589   \brief     resets sbr inverse filtering structure.
590 
591 
592 
593   \return   errorCode, noError if successful.
594 
595 */
596 /**************************************************************************/
FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt,INT * freqBandTableDetector,INT numDetectorBands)597 INT FDKsbrEnc_resetInvFiltDetector(
598     HANDLE_SBR_INV_FILT_EST
599         hInvFilt,               /*!< Handle to the SBR_INV_FILT_EST struct. */
600     INT *freqBandTableDetector, /*!< Frequency band table for the inverse
601                                    filtering. */
602     INT numDetectorBands)       /*!< Number of inverse filtering bands. */
603 {
604   hInvFilt->numberOfStrongest = 1;
605   FDKmemcpy(hInvFilt->freqBandTableInvFilt, freqBandTableDetector,
606             (numDetectorBands + 1) * sizeof(INT));
607   hInvFilt->noDetectorBands = numDetectorBands;
608 
609   return (0);
610 }
611