1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5� Copyright  1995 - 2013 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 "invf_est.h"
85#include "sbr_misc.h"
86
87#include "genericStds.h"
88
89#define MAX_NUM_REGIONS 10
90#define SCALE_FAC_QUO   512.0f
91#define SCALE_FAC_NRG   256.0f
92
93#ifndef min
94#define min(a,b) ( a < b ? a:b)
95#endif
96
97#ifndef max
98#define max(a,b) ( a > b ? a:b)
99#endif
100
101static const FIXP_DBL quantStepsSbr[4]  =  { 0x00400000, 0x02800000, 0x03800000, 0x04c00000 } ;    /* table scaled with SCALE_FAC_QUO */
102static const FIXP_DBL quantStepsOrig[4] =  { 0x00000000, 0x00c00000, 0x01c00000, 0x02800000 } ;    /* table scaled with SCALE_FAC_QUO */
103static const FIXP_DBL nrgBorders[4]     =  { 0x0c800000, 0x0f000000, 0x11800000, 0x14000000 } ;    /* table scaled with SCALE_FAC_NRG */
104
105static const DETECTOR_PARAMETERS detectorParamsAAC = {
106    quantStepsSbr,
107    quantStepsOrig,
108    nrgBorders,
109    4,                              /* Number of borders SBR. */
110    4,                              /* Number of borders orig. */
111    4,                              /* Number of borders Nrg. */
112    {                               /* Region space. */
113      {INVF_MID_LEVEL,   INVF_LOW_LEVEL,  INVF_OFF,        INVF_OFF, INVF_OFF}, /*    |      */
114      {INVF_MID_LEVEL,   INVF_LOW_LEVEL,  INVF_OFF,        INVF_OFF, INVF_OFF}, /*    |      */
115      {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
116      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
117      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
118    },/*------------------------ regionOrig ---------------------------------*/
119    {                               /* Region space transient. */
120      {INVF_LOW_LEVEL,   INVF_LOW_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
121      {INVF_LOW_LEVEL,   INVF_LOW_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
122      {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
123      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
124      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
125    },/*------------------------ regionOrig ---------------------------------*/
126    {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/
127};
128
129static const FIXP_DBL hysteresis = 0x00400000 ; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */
130
131/*
132 * AAC+SBR PARAMETERS for Speech
133 *********************************/
134static const DETECTOR_PARAMETERS detectorParamsAACSpeech = {
135    quantStepsSbr,
136    quantStepsOrig,
137    nrgBorders,
138    4,                              /* Number of borders SBR. */
139    4,                              /* Number of borders orig. */
140    4,                              /* Number of borders Nrg. */
141    {                               /* Region space. */
142      {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
143      {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
144      {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
145      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
146      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
147    },/*------------------------ regionOrig ---------------------------------*/
148    {                               /* Region space transient. */
149      {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
150      {INVF_MID_LEVEL,   INVF_MID_LEVEL,  INVF_LOW_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
151      {INVF_HIGH_LEVEL,  INVF_MID_LEVEL,  INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /* regionSbr */
152      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}, /*    |      */
153      {INVF_HIGH_LEVEL,  INVF_HIGH_LEVEL, INVF_MID_LEVEL,  INVF_OFF, INVF_OFF}  /*    |      */
154    },/*------------------------ regionOrig ---------------------------------*/
155    {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/
156};
157
158/*
159 * Smoothing filters.
160 ************************/
161typedef const FIXP_DBL FIR_FILTER[5];
162
163static const FIR_FILTER fir_0 = { 0x7fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } ;
164static const FIR_FILTER fir_1 = { 0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, 0x00000000 } ;
165static const FIR_FILTER fir_2 = { 0x10000000, 0x30000000, 0x40000000, 0x00000000, 0x00000000 } ;
166static const FIR_FILTER fir_3 = { 0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, 0x00000000 } ;
167static const FIR_FILTER fir_4 = { 0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, 0x2aaaaa80 } ;
168
169
170static const FIR_FILTER *const fir_table[5] = {
171  &fir_0,
172  &fir_1,
173  &fir_2,
174  &fir_3,
175  &fir_4
176};
177
178/**************************************************************************/
179/*!
180  \brief     Calculates the values used for the detector.
181
182
183  \return    none
184
185*/
186/**************************************************************************/
187static void
188calculateDetectorValues(FIXP_DBL **quotaMatrixOrig,       /*!< Matrix holding the tonality values of the original. */
189                        SCHAR    *indexVector,            /*!< Index vector to obtain the patched data. */
190                        FIXP_DBL *nrgVector,              /*!< Energy vector. */
191                        DETECTOR_VALUES *detectorValues,  /*!< pointer to DETECTOR_VALUES struct. */
192                        INT startChannel,                 /*!< Start channel. */
193                        INT stopChannel,                  /*!< Stop channel. */
194                        INT startIndex,                   /*!< Start index. */
195                        INT stopIndex,                    /*!< Stop index. */
196                        INT numberOfStrongest             /*!< The number of sorted tonal components to be considered. */
197                        )
198{
199  INT i,temp, j;
200
201  const FIXP_DBL* filter = *fir_table[INVF_SMOOTHING_LENGTH];
202  FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest;
203  FIXP_DBL origQuota, sbrQuota;
204  FIXP_DBL invIndex, invChannel, invTemp;
205  FIXP_DBL quotaVecOrig[64], quotaVecSbr[64];
206
207  FDKmemclear(quotaVecOrig,64*sizeof(FIXP_DBL));
208  FDKmemclear(quotaVecSbr,64*sizeof(FIXP_DBL));
209
210  invIndex = GetInvInt(stopIndex-startIndex);
211  invChannel = GetInvInt(stopChannel-startChannel);
212
213  /*
214   Calculate the mean value, over the current time segment, for the original, the HFR
215   and the difference, over all channels in the current frequency range.
216   NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION).
217   */
218
219  /* The original, the sbr signal and the total energy */
220  detectorValues->avgNrg = FL2FXCONST_DBL(0.0f);
221  for(j=startIndex; j<stopIndex; j++) {
222    for(i=startChannel; i<stopChannel; i++) {
223      quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex);
224
225      if(indexVector[i] != -1)
226        quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex);
227    }
228    detectorValues->avgNrg += fMult(nrgVector[j], invIndex);
229  }
230
231  /*
232   Calculate the mean value, over the current frequency range, for the original, the HFR
233   and the difference. Also calculate the same mean values for the three vectors, but only
234   includeing the x strongest copmponents.
235   */
236
237  origQuota = FL2FXCONST_DBL(0.0f);
238  sbrQuota  = FL2FXCONST_DBL(0.0f);
239  for(i=startChannel; i<stopChannel; i++) {
240    origQuota += fMultDiv2(quotaVecOrig[i], invChannel);
241    sbrQuota  += fMultDiv2(quotaVecSbr[i], invChannel);
242  }
243
244  /*
245   Calculate the mean value for the x strongest components
246  */
247  FDKsbrEnc_Shellsort_fract(quotaVecOrig+startChannel,stopChannel-startChannel);
248  FDKsbrEnc_Shellsort_fract(quotaVecSbr+startChannel,stopChannel-startChannel);
249
250  origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f);
251  sbrQuotaMeanStrongest  = FL2FXCONST_DBL(0.0f);
252
253  temp = min(stopChannel - startChannel, numberOfStrongest);
254  invTemp = GetInvInt(temp);
255
256  for(i=0; i<temp; i++) {
257    origQuotaMeanStrongest += fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp);
258    sbrQuotaMeanStrongest  += fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp);
259  }
260
261  /*
262   The value for the strongest component
263  */
264  detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1];
265  detectorValues->sbrQuotaMax  = quotaVecSbr[stopChannel - 1];
266
267  /*
268   Buffer values
269  */
270  FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
271  FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
272  FDKmemmove(detectorValues->origQuotaMeanStrongest, detectorValues->origQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
273  FDKmemmove(detectorValues->sbrQuotaMeanStrongest, detectorValues->sbrQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL));
274
275  detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH]          = origQuota<<1;
276  detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH]           = sbrQuota<<1;
277  detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = origQuotaMeanStrongest<<1;
278  detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH]  = sbrQuotaMeanStrongest<<1;
279
280  /*
281   Filter values
282  */
283  detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
284  detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f);
285  detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
286  detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f);
287
288  for(i=0;i<INVF_SMOOTHING_LENGTH+1;i++) {
289    detectorValues->origQuotaMeanFilt += fMult(detectorValues->origQuotaMean[i], filter[i]);
290    detectorValues->sbrQuotaMeanFilt  += fMult(detectorValues->sbrQuotaMean[i], filter[i]);
291    detectorValues->origQuotaMeanStrongestFilt += fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]);
292    detectorValues->sbrQuotaMeanStrongestFilt  += fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]);
293  }
294}
295
296/**************************************************************************/
297/*!
298  \brief     Returns the region in which the input value belongs.
299
300
301
302  \return    region.
303
304*/
305/**************************************************************************/
306static INT
307findRegion(FIXP_DBL currVal,        /*!< The current value. */
308           const FIXP_DBL *borders, /*!< The border of the regions. */
309           const INT numBorders     /*!< The number of borders. */
310           )
311{
312  INT i;
313
314  if(currVal < borders[0]){
315    return 0;
316  }
317
318  for(i = 1; i < numBorders; i++){
319    if( currVal >= borders[i-1] && currVal < borders[i]){
320      return i;
321    }
322  }
323
324  if(currVal >= borders[numBorders-1]){
325    return numBorders;
326  }
327
328  return 0;  /* We never get here, it's just to avoid compiler warnings.*/
329}
330
331/**************************************************************************/
332/*!
333  \brief     Makes a clever decision based on the quota vector.
334
335
336  \return     decision on which invf mode to use
337
338*/
339/**************************************************************************/
340static INVF_MODE
341decisionAlgorithm(const DETECTOR_PARAMETERS *detectorParams,     /*!< Struct with the detector parameters. */
342                  DETECTOR_VALUES *detectorValues,               /*!< Struct with the detector values. */
343                  INT transientFlag,                             /*!< Flag indicating if there is a transient present.*/
344                  INT* prevRegionSbr,                            /*!< The previous region in which the Sbr value was. */
345                  INT* prevRegionOrig                            /*!< The previous region in which the Orig value was. */
346                  )
347{
348  INT invFiltLevel, regionSbr, regionOrig, regionNrg;
349
350  /*
351   Current thresholds.
352   */
353  const FIXP_DBL *quantStepsSbr  = detectorParams->quantStepsSbr;
354  const FIXP_DBL *quantStepsOrig = detectorParams->quantStepsOrig;
355  const FIXP_DBL *nrgBorders     = detectorParams->nrgBorders;
356  const INT numRegionsSbr     = detectorParams->numRegionsSbr;
357  const INT numRegionsOrig    = detectorParams->numRegionsOrig;
358  const INT numRegionsNrg     = detectorParams->numRegionsNrg;
359
360  FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS];
361  FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS];
362
363  /*
364   Current detector values.
365   */
366  FIXP_DBL origQuotaMeanFilt;
367  FIXP_DBL sbrQuotaMeanFilt;
368  FIXP_DBL nrg;
369
370  /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = log(16)/64.0; 0.6875 = 44/64.0 */
371  origQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0;  /* scaled by 1/2^9 */
372  sbrQuotaMeanFilt  = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0;   /* scaled by 1/2^9 */
373  /* If energy is zero then we will get different results for different word lengths. */
374  nrg               = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(detectorValues->avgNrg+(FIXP_DBL)1) + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) << 0;     /* scaled by 1/2^8; 2^44 -> qmf energy scale */
375
376  FDKmemcpy(quantStepsSbrTmp,quantStepsSbr,numRegionsSbr*sizeof(FIXP_DBL));
377  FDKmemcpy(quantStepsOrigTmp,quantStepsOrig,numRegionsOrig*sizeof(FIXP_DBL));
378
379  if(*prevRegionSbr < numRegionsSbr)
380    quantStepsSbrTmp[*prevRegionSbr] = quantStepsSbr[*prevRegionSbr] + hysteresis;
381  if(*prevRegionSbr > 0)
382    quantStepsSbrTmp[*prevRegionSbr - 1] = quantStepsSbr[*prevRegionSbr - 1] - hysteresis;
383
384  if(*prevRegionOrig < numRegionsOrig)
385    quantStepsOrigTmp[*prevRegionOrig] = quantStepsOrig[*prevRegionOrig] + hysteresis;
386  if(*prevRegionOrig > 0)
387    quantStepsOrigTmp[*prevRegionOrig - 1] = quantStepsOrig[*prevRegionOrig - 1] - hysteresis;
388
389  regionSbr  = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr);
390  regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig);
391  regionNrg  = findRegion(nrg,nrgBorders,numRegionsNrg);
392
393  *prevRegionSbr = regionSbr;
394  *prevRegionOrig = regionOrig;
395
396  /* Use different settings if a transient is present*/
397  invFiltLevel = (transientFlag == 1) ? detectorParams->regionSpaceTransient[regionSbr][regionOrig]
398                                      : detectorParams->regionSpace[regionSbr][regionOrig];
399
400  /* Compensate for low energy.*/
401  invFiltLevel = max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg],0);
402
403  return (INVF_MODE) (invFiltLevel);
404}
405
406/**************************************************************************/
407/*!
408  \brief     Estiamtion of the inverse filtering level required
409             in the decoder.
410
411   A second order LPC is calculated for every filterbank channel, using
412   the covariance method. THe ratio between the energy of the predicted
413   signal and the energy of the non-predictable signal is calcualted.
414
415  \return    none.
416
417*/
418/**************************************************************************/
419void
420FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt,  /*!< Handle to the SBR_INV_FILT_EST struct. */
421                            FIXP_DBL **quotaMatrix,            /*!< The matrix holding the tonality values of the original. */
422                            FIXP_DBL *nrgVector,               /*!< The energy vector. */
423                            SCHAR    *indexVector,             /*!< Index vector to obtain the patched data. */
424                            INT startIndex,                    /*!< Start index. */
425                            INT stopIndex,                     /*!< Stop index. */
426                            INT transientFlag,                 /*!< Flag indicating if a transient is present or not.*/
427                            INVF_MODE* infVec                  /*!< Vector holding the inverse filtering levels. */
428                            )
429{
430  INT band;
431
432  /*
433   * Do the inverse filtering level estimation.
434   *****************************************************/
435  for(band = 0 ; band < hInvFilt->noDetectorBands; band++){
436    INT startChannel = hInvFilt->freqBandTableInvFilt[band];
437    INT stopChannel  = hInvFilt->freqBandTableInvFilt[band+1];
438
439
440    calculateDetectorValues( quotaMatrix,
441                             indexVector,
442                             nrgVector,
443                            &hInvFilt->detectorValues[band],
444                             startChannel,
445                             stopChannel,
446                             startIndex,
447                             stopIndex,
448                             hInvFilt->numberOfStrongest);
449
450    infVec[band]= decisionAlgorithm( hInvFilt->detectorParams,
451                                    &hInvFilt->detectorValues[band],
452                                     transientFlag,
453                                    &hInvFilt->prevRegionSbr[band],
454                                    &hInvFilt->prevRegionOrig[band]);
455  }
456
457}
458
459
460/**************************************************************************/
461/*!
462  \brief     Initialize an instance of the inverse filtering level estimator.
463
464
465  \return   errorCode, noError if successful.
466
467*/
468/**************************************************************************/
469INT
470FDKsbrEnc_initInvFiltDetector (HANDLE_SBR_INV_FILT_EST hInvFilt,   /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */
471                       INT* freqBandTableDetector,          /*!< Frequency band table for the inverse filtering. */
472                       INT numDetectorBands,                /*!< Number of inverse filtering bands. */
473                       UINT useSpeechConfig         /*!< Flag: adapt tuning parameters according to speech*/
474                       )
475{
476  INT i;
477
478  FDKmemclear( hInvFilt,sizeof(SBR_INV_FILT_EST));
479
480  hInvFilt->detectorParams = (useSpeechConfig) ? &detectorParamsAACSpeech
481                                               : &detectorParamsAAC ;
482
483  hInvFilt->noDetectorBandsMax = numDetectorBands;
484
485  /*
486     Memory initialisation
487  */
488  for(i=0;i<hInvFilt->noDetectorBandsMax;i++){
489    FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES));
490    hInvFilt->prevInvfMode[i]   = INVF_OFF;
491    hInvFilt->prevRegionOrig[i] = 0;
492    hInvFilt->prevRegionSbr[i]  = 0;
493  }
494
495  /*
496  Reset the inverse fltering detector.
497  */
498  FDKsbrEnc_resetInvFiltDetector(hInvFilt,
499                       freqBandTableDetector,
500                       hInvFilt->noDetectorBandsMax);
501
502  return (0);
503}
504
505
506/**************************************************************************/
507/*!
508  \brief     resets sbr inverse filtering structure.
509
510
511
512  \return   errorCode, noError if successful.
513
514*/
515/**************************************************************************/
516INT
517FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */
518                     INT* freqBandTableDetector,       /*!< Frequency band table for the inverse filtering. */
519                     INT numDetectorBands)             /*!< Number of inverse filtering bands. */
520{
521
522  hInvFilt->numberOfStrongest     = 1;
523  FDKmemcpy(hInvFilt->freqBandTableInvFilt,freqBandTableDetector,(numDetectorBands+1)*sizeof(INT));
524  hInvFilt->noDetectorBands = numDetectorBands;
525
526  return (0);
527}
528
529
530