Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung 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 (at) iis.fraunhofer.de
     93 ----------------------------------------------------------------------------- */
     94 
     95 /**************************** AAC encoder library ******************************
     96 
     97    Author(s):   Alex Groeschel, Tobias Chalupka
     98 
     99    Description: Temporal noise shaping
    100 
    101 *******************************************************************************/
    102 
    103 #include "aacenc_tns.h"
    104 #include "psy_const.h"
    105 #include "psy_configuration.h"
    106 #include "tns_func.h"
    107 #include "aacEnc_rom.h"
    108 #include "aacenc_tns.h"
    109 #include "FDK_lpc.h"
    110 
    111 #define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
    112 
    113 static const FIXP_DBL acfWindowLong[12 + 3 + 1] = {
    114     0x7fffffff, 0x7fb80000, 0x7ee00000, 0x7d780000, 0x7b800000, 0x78f80000,
    115     0x75e00000, 0x72380000, 0x6e000000, 0x69380000, 0x63e00000, 0x5df80000,
    116     0x57800000, 0x50780000, 0x48e00000, 0x40b80000};
    117 
    118 static const FIXP_DBL acfWindowShort[4 + 3 + 1] = {
    119     0x7fffffff, 0x7e000000, 0x78000000, 0x6e000000,
    120     0x60000000, 0x4e000000, 0x38000000, 0x1e000000};
    121 
    122 typedef struct {
    123   INT bitRateFrom[2];                  /* noneSbr=0, useSbr=1 */
    124   INT bitRateTo[2];                    /* noneSbr=0, useSbr=1 */
    125   TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */
    126 
    127 } TNS_INFO_TAB;
    128 
    129 #define TNS_TIMERES_SCALE (1)
    130 #define FL2_TIMERES_FIX(a) (FL2FXCONST_DBL(a / (float)(1 << TNS_TIMERES_SCALE)))
    131 
    132 static const TNS_INFO_TAB tnsInfoTab[] = {
    133     {{16000, 13500},
    134      {32000, 28000},
    135      {{{1, 1},
    136        {1437, 1500},
    137        {1400, 600},
    138        {12, 12},
    139        {FILTER_DIRECTION, FILTER_DIRECTION},
    140        {3, 1},
    141        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)},
    142        1},
    143       {{1, 1},
    144        {1437, 1500},
    145        {1400, 600},
    146        {12, 12},
    147        {FILTER_DIRECTION, FILTER_DIRECTION},
    148        {3, 1},
    149        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)},
    150        1}}},
    151     {{32001, 28001},
    152      {60000, 52000},
    153      {{{1, 1},
    154        {1437, 1500},
    155        {1400, 600},
    156        {12, 10},
    157        {FILTER_DIRECTION, FILTER_DIRECTION},
    158        {3, 1},
    159        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
    160        1},
    161       {{1, 1},
    162        {1437, 1500},
    163        {1400, 600},
    164        {12, 10},
    165        {FILTER_DIRECTION, FILTER_DIRECTION},
    166        {3, 1},
    167        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
    168        1}}},
    169     {{60001, 52001},
    170      {384000, 384000},
    171      {{{1, 1},
    172        {1437, 1500},
    173        {1400, 600},
    174        {12, 8},
    175        {FILTER_DIRECTION, FILTER_DIRECTION},
    176        {3, 1},
    177        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
    178        1},
    179       {{1, 1},
    180        {1437, 1500},
    181        {1400, 600},
    182        {12, 8},
    183        {FILTER_DIRECTION, FILTER_DIRECTION},
    184        {3, 1},
    185        {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
    186        1}}}};
    187 
    188 typedef struct {
    189   INT samplingRate;
    190   SCHAR maxBands[2]; /* long=0; short=1 */
    191 
    192 } TNS_MAX_TAB_ENTRY;
    193 
    194 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] = {
    195     {96000, {31, 9}},  {88200, {31, 9}},  {64000, {34, 10}}, {48000, {40, 14}},
    196     {44100, {42, 14}}, {32000, {51, 14}}, {24000, {46, 14}}, {22050, {46, 14}},
    197     {16000, {42, 14}}, {12000, {42, 14}}, {11025, {42, 14}}, {8000, {39, 14}}};
    198 
    199 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab120[] = {
    200     {48000, {12, -1}}, /* 48000 */
    201     {44100, {12, -1}}, /* 44100 */
    202     {32000, {15, -1}}, /* 32000 */
    203     {24000, {15, -1}}, /* 24000 */
    204     {22050, {15, -1}}  /* 22050 */
    205 };
    206 
    207 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab128[] = {
    208     {48000, {12, -1}}, /* 48000 */
    209     {44100, {12, -1}}, /* 44100 */
    210     {32000, {15, -1}}, /* 32000 */
    211     {24000, {15, -1}}, /* 24000 */
    212     {22050, {15, -1}}  /* 22050 */
    213 };
    214 
    215 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab240[] = {
    216     {96000, {22, -1}}, /* 96000 */
    217     {48000, {22, -1}}, /* 48000 */
    218     {44100, {22, -1}}, /* 44100 */
    219     {32000, {21, -1}}, /* 32000 */
    220     {24000, {21, -1}}, /* 24000 */
    221     {22050, {21, -1}}  /* 22050 */
    222 };
    223 
    224 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab256[] = {
    225     {96000, {25, -1}}, /* 96000 */
    226     {48000, {25, -1}}, /* 48000 */
    227     {44100, {25, -1}}, /* 44100 */
    228     {32000, {24, -1}}, /* 32000 */
    229     {24000, {24, -1}}, /* 24000 */
    230     {22050, {24, -1}}  /* 22050 */
    231 };
    232 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] = {{48000, {31, -1}},
    233                                                       {44100, {32, -1}},
    234                                                       {32000, {37, -1}},
    235                                                       {24000, {30, -1}},
    236                                                       {22050, {30, -1}}};
    237 
    238 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] = {{48000, {31, -1}},
    239                                                       {44100, {32, -1}},
    240                                                       {32000, {37, -1}},
    241                                                       {24000, {31, -1}},
    242                                                       {22050, {31, -1}}};
    243 
    244 static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index,
    245                                    const INT order, const INT bitsPerCoeff);
    246 
    247 static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor,
    248                                    const INT order, const INT bitsPerCoeff);
    249 
    250 static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize,
    251                                       const INT samplingRate,
    252                                       const INT transformResolution,
    253                                       const FIXP_DBL timeResolution,
    254                                       const INT timeResolution_e);
    255 
    256 static const TNS_PARAMETER_TABULATED *FDKaacEnc_GetTnsParam(const INT bitRate,
    257                                                             const INT channels,
    258                                                             const INT sbrLd) {
    259   int i;
    260   const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL;
    261 
    262   for (i = 0; i < (int)(sizeof(tnsInfoTab) / sizeof(TNS_INFO_TAB)); i++) {
    263     if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd ? 1 : 0]) &&
    264         bitRate <= tnsInfoTab[i].bitRateTo[sbrLd ? 1 : 0]) {
    265       tnsConfigTab = &tnsInfoTab[i].paramTab[(channels == 1) ? 0 : 1];
    266     }
    267   }
    268 
    269   return tnsConfigTab;
    270 }
    271 
    272 static INT getTnsMaxBands(const INT sampleRate, const INT granuleLength,
    273                           const INT isShortBlock) {
    274   int i;
    275   INT numBands = -1;
    276   const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL;
    277   int maxBandsTabSize = 0;
    278 
    279   switch (granuleLength) {
    280     case 960:
    281     case 1024:
    282       pMaxBandsTab = tnsMaxBandsTab1024;
    283       maxBandsTabSize = sizeof(tnsMaxBandsTab1024) / sizeof(TNS_MAX_TAB_ENTRY);
    284       break;
    285     case 120:
    286       pMaxBandsTab = tnsMaxBandsTab120;
    287       maxBandsTabSize = sizeof(tnsMaxBandsTab120) / sizeof(TNS_MAX_TAB_ENTRY);
    288       break;
    289     case 128:
    290       pMaxBandsTab = tnsMaxBandsTab128;
    291       maxBandsTabSize = sizeof(tnsMaxBandsTab128) / sizeof(TNS_MAX_TAB_ENTRY);
    292       break;
    293     case 240:
    294       pMaxBandsTab = tnsMaxBandsTab240;
    295       maxBandsTabSize = sizeof(tnsMaxBandsTab240) / sizeof(TNS_MAX_TAB_ENTRY);
    296       break;
    297     case 256:
    298       pMaxBandsTab = tnsMaxBandsTab256;
    299       maxBandsTabSize = sizeof(tnsMaxBandsTab256) / sizeof(TNS_MAX_TAB_ENTRY);
    300       break;
    301     case 480:
    302       pMaxBandsTab = tnsMaxBandsTab480;
    303       maxBandsTabSize = sizeof(tnsMaxBandsTab480) / sizeof(TNS_MAX_TAB_ENTRY);
    304       break;
    305     case 512:
    306       pMaxBandsTab = tnsMaxBandsTab512;
    307       maxBandsTabSize = sizeof(tnsMaxBandsTab512) / sizeof(TNS_MAX_TAB_ENTRY);
    308       break;
    309     default:
    310       numBands = -1;
    311   }
    312 
    313   if (pMaxBandsTab != NULL) {
    314     for (i = 0; i < maxBandsTabSize; i++) {
    315       numBands = pMaxBandsTab[i].maxBands[(!isShortBlock) ? 0 : 1];
    316       if (sampleRate >= pMaxBandsTab[i].samplingRate) {
    317         break;
    318       }
    319     }
    320   }
    321 
    322   return numBands;
    323 }
    324 
    325 /***************************************************************************/
    326 /*!
    327   \brief     FDKaacEnc_FreqToBandWidthRounding
    328 
    329   Returns index of nearest band border
    330 
    331   \param frequency
    332   \param sampling frequency
    333   \param total number of bands
    334   \param pointer to table of band borders
    335 
    336   \return band border
    337 ****************************************************************************/
    338 
    339 INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs,
    340                                       const INT numOfBands,
    341                                       const INT *bandStartOffset) {
    342   INT lineNumber, band;
    343 
    344   /*  assert(freq >= 0);  */
    345   lineNumber = (freq * bandStartOffset[numOfBands] * 4 / fs + 1) / 2;
    346 
    347   /* freq > fs/2 */
    348   if (lineNumber >= bandStartOffset[numOfBands]) return numOfBands;
    349 
    350   /* find band the line number lies in */
    351   for (band = 0; band < numOfBands; band++) {
    352     if (bandStartOffset[band + 1] > lineNumber) break;
    353   }
    354 
    355   /* round to nearest band border */
    356   if (lineNumber - bandStartOffset[band] >
    357       bandStartOffset[band + 1] - lineNumber) {
    358     band++;
    359   }
    360 
    361   return (band);
    362 }
    363 
    364 /*****************************************************************************
    365 
    366     functionname: FDKaacEnc_InitTnsConfiguration
    367     description:  fill TNS_CONFIG structure with sensible content
    368     returns:
    369     input:        bitrate, samplerate, number of channels,
    370                   blocktype (long or short),
    371                   TNS Config struct (modified),
    372                   psy config struct,
    373                   tns active flag
    374     output:
    375 
    376 *****************************************************************************/
    377 AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(
    378     INT bitRate, INT sampleRate, INT channels, INT blockType, INT granuleLength,
    379     INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC,
    380     INT active, INT useTnsPeak) {
    381   int i;
    382   // float acfTimeRes   = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f;
    383 
    384   if (channels <= 0) return (AAC_ENCODER_ERROR)1;
    385 
    386   tC->isLowDelay = isLowDelay;
    387 
    388   /* initialize TNS filter flag, order, and coefficient resolution (in bits per
    389    * coeff) */
    390   tC->tnsActive = (active) ? TRUE : FALSE;
    391   tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */
    392   if (bitRate < 16000) tC->maxOrder -= 2;
    393   tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4;
    394 
    395   /* LPC stop line: highest MDCT line to be coded, but do not go beyond
    396    * TNS_MAX_BANDS! */
    397   tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength,
    398                                    (blockType == SHORT_WINDOW) ? 1 : 0);
    399 
    400   if (tC->lpcStopBand < 0) {
    401     return (AAC_ENCODER_ERROR)1;
    402   }
    403 
    404   tC->lpcStopBand = fMin(tC->lpcStopBand, pC->sfbActive);
    405   tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
    406 
    407   switch (granuleLength) {
    408     case 960:
    409     case 1024:
    410       /* TNS start line: skip lower MDCT lines to prevent artifacts due to
    411        * filter mismatch */
    412       if (blockType == SHORT_WINDOW) {
    413         tC->lpcStartBand[LOFILT] = 0;
    414       } else {
    415         tC->lpcStartBand[LOFILT] =
    416             (sampleRate < 9391) ? 2 : ((sampleRate < 18783) ? 4 : 8);
    417       }
    418       tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
    419 
    420       i = tC->lpcStopBand;
    421       while (pC->sfbOffset[i] >
    422              (tC->lpcStartLine[LOFILT] +
    423               (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4))
    424         i--;
    425       tC->lpcStartBand[HIFILT] = i;
    426       tC->lpcStartLine[HIFILT] = pC->sfbOffset[i];
    427 
    428       tC->confTab.threshOn[HIFILT] = 1437;
    429       tC->confTab.threshOn[LOFILT] = 1500;
    430 
    431       tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder;
    432       tC->confTab.tnsLimitOrder[LOFILT] = fMax(0, tC->maxOrder - 7);
    433 
    434       tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION;
    435       tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION;
    436 
    437       tC->confTab.acfSplit[HIFILT] =
    438           -1; /* signal Merged4to2QuartersAutoCorrelation in
    439                  FDKaacEnc_MergedAutoCorrelation*/
    440       tC->confTab.acfSplit[LOFILT] =
    441           -1; /* signal Merged4to2QuartersAutoCorrelation in
    442                  FDKaacEnc_MergedAutoCorrelation */
    443 
    444       tC->confTab.filterEnabled[HIFILT] = 1;
    445       tC->confTab.filterEnabled[LOFILT] = 1;
    446       tC->confTab.seperateFiltersAllowed = 1;
    447 
    448       /* compute autocorrelation window based on maximum filter order for given
    449        * block type */
    450       /* for (i = 0; i <= tC->maxOrder + 3; i++) {
    451            float acfWinTemp = acfTimeRes * i;
    452            acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp);
    453          }
    454       */
    455       if (blockType == SHORT_WINDOW) {
    456         FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort,
    457                   fMin((LONG)sizeof(acfWindowShort),
    458                        (LONG)sizeof(tC->acfWindow[HIFILT])));
    459         FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort,
    460                   fMin((LONG)sizeof(acfWindowShort),
    461                        (LONG)sizeof(tC->acfWindow[HIFILT])));
    462       } else {
    463         FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong,
    464                   fMin((LONG)sizeof(acfWindowLong),
    465                        (LONG)sizeof(tC->acfWindow[HIFILT])));
    466         FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong,
    467                   fMin((LONG)sizeof(acfWindowLong),
    468                        (LONG)sizeof(tC->acfWindow[HIFILT])));
    469       }
    470       break;
    471     case 480:
    472     case 512: {
    473       const TNS_PARAMETER_TABULATED *pCfg =
    474           FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
    475       if (pCfg != NULL) {
    476         FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
    477 
    478         tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWidthRounding(
    479             pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt,
    480             pC->sfbOffset);
    481         tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
    482         tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWidthRounding(
    483             pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt,
    484             pC->sfbOffset);
    485         tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
    486 
    487         FDKaacEnc_CalcGaussWindow(
    488             tC->acfWindow[HIFILT], tC->maxOrder + 1, sampleRate, granuleLength,
    489             pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE);
    490         FDKaacEnc_CalcGaussWindow(
    491             tC->acfWindow[LOFILT], tC->maxOrder + 1, sampleRate, granuleLength,
    492             pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE);
    493       } else {
    494         tC->tnsActive =
    495             FALSE; /* no configuration available, disable tns tool */
    496       }
    497     } break;
    498     default:
    499       tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
    500   }
    501 
    502   return AAC_ENC_OK;
    503 }
    504 
    505 /***************************************************************************/
    506 /*!
    507   \brief     FDKaacEnc_ScaleUpSpectrum
    508 
    509   Scales up spectrum lines in a given frequency section
    510 
    511   \param scaled spectrum
    512   \param original spectrum
    513   \param frequency line to start scaling
    514   \param frequency line to enc scaling
    515 
    516   \return scale factor
    517 
    518 ****************************************************************************/
    519 static inline INT FDKaacEnc_ScaleUpSpectrum(FIXP_DBL *dest, const FIXP_DBL *src,
    520                                             const INT startLine,
    521                                             const INT stopLine) {
    522   INT i, scale;
    523 
    524   FIXP_DBL maxVal = FL2FXCONST_DBL(0.f);
    525 
    526   /* Get highest value in given spectrum */
    527   for (i = startLine; i < stopLine; i++) {
    528     maxVal = fixMax(maxVal, fixp_abs(src[i]));
    529   }
    530   scale = CountLeadingBits(maxVal);
    531 
    532   /* Scale spectrum according to highest value */
    533   for (i = startLine; i < stopLine; i++) {
    534     dest[i] = src[i] << scale;
    535   }
    536 
    537   return scale;
    538 }
    539 
    540 /***************************************************************************/
    541 /*!
    542   \brief     FDKaacEnc_CalcAutoCorrValue
    543 
    544   Calculate autocorellation value for one lag
    545 
    546   \param pointer to spectrum
    547   \param start line
    548   \param stop line
    549   \param lag to be calculated
    550   \param scaling of the lag
    551 
    552 ****************************************************************************/
    553 static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(const FIXP_DBL *spectrum,
    554                                                    const INT startLine,
    555                                                    const INT stopLine,
    556                                                    const INT lag,
    557                                                    const INT scale) {
    558   int i;
    559   FIXP_DBL result = FL2FXCONST_DBL(0.f);
    560 
    561   /* This versions allows to save memory accesses, when computing pow2 */
    562   /* It is of interest for ARM, XTENSA without parallel memory access  */
    563   if (lag == 0) {
    564     for (i = startLine; i < stopLine; i++) {
    565       result += (fPow2(spectrum[i]) >> scale);
    566     }
    567   } else {
    568     for (i = startLine; i < (stopLine - lag); i++) {
    569       result += (fMult(spectrum[i], spectrum[i + lag]) >> scale);
    570     }
    571   }
    572 
    573   return result;
    574 }
    575 
    576 /***************************************************************************/
    577 /*!
    578   \brief     FDKaacEnc_AutoCorrNormFac
    579 
    580   Autocorrelation function for 1st and 2nd half of the spectrum
    581 
    582   \param pointer to spectrum
    583   \param pointer to autocorrelation window
    584   \param filter start line
    585 
    586 ****************************************************************************/
    587 static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(const FIXP_DBL value,
    588                                                  const INT scale, INT *sc) {
    589 #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */
    590 #define MAX_INV_NRGFAC (1.f / HLM_MIN_NRG)
    591 
    592   FIXP_DBL retValue;
    593   FIXP_DBL A, B;
    594 
    595   if (scale >= 0) {
    596     A = value;
    597     B = FL2FXCONST_DBL(HLM_MIN_NRG) >> fixMin(DFRACT_BITS - 1, scale);
    598   } else {
    599     A = value >> fixMin(DFRACT_BITS - 1, (-scale));
    600     B = FL2FXCONST_DBL(HLM_MIN_NRG);
    601   }
    602 
    603   if (A > B) {
    604     int shift = 0;
    605     FIXP_DBL tmp = invSqrtNorm2(value, &shift);
    606 
    607     retValue = fMult(tmp, tmp);
    608     *sc += (2 * shift);
    609   } else {
    610     /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */
    611     retValue =
    612         /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL;
    613     *sc += scale + 28;
    614   }
    615 
    616   return retValue;
    617 }
    618 
    619 static void FDKaacEnc_MergedAutoCorrelation(
    620     const FIXP_DBL *spectrum, const INT isLowDelay,
    621     const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1],
    622     const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStopLine,
    623     const INT maxOrder, const INT acfSplit[MAX_NUM_OF_FILTERS], FIXP_DBL *_rxx1,
    624     FIXP_DBL *_rxx2) {
    625   int i, idx0, idx1, idx2, idx3, idx4, lag;
    626   FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0;
    627 
    628   /* buffer for temporal spectrum */
    629   C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024))
    630 
    631   /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters
    632    */
    633   if ((acfSplit[LOFILT] == -1) || (acfSplit[HIFILT] == -1)) {
    634     /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the
    635      * spectrum */
    636     idx0 = lpcStartLine[LOFILT];
    637     i = lpcStopLine - lpcStartLine[LOFILT];
    638     idx1 = idx0 + i / 4;
    639     idx2 = idx0 + i / 2;
    640     idx3 = idx0 + i * 3 / 4;
    641     idx4 = lpcStopLine;
    642   } else {
    643     FDK_ASSERT(acfSplit[LOFILT] == 1);
    644     FDK_ASSERT(acfSplit[HIFILT] == 3);
    645     i = (lpcStopLine - lpcStartLine[HIFILT]) / 3;
    646     idx0 = lpcStartLine[LOFILT];
    647     idx1 = lpcStartLine[HIFILT];
    648     idx2 = idx1 + i;
    649     idx3 = idx2 + i;
    650     idx4 = lpcStopLine;
    651   }
    652 
    653   /* copy spectrum to temporal buffer and scale up as much as possible */
    654   INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1);
    655   INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2);
    656   INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3);
    657   INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4);
    658 
    659   /* get scaling values for summation */
    660   INT nsc1, nsc2, nsc3, nsc4;
    661   for (nsc1 = 1; (1 << nsc1) < (idx1 - idx0); nsc1++)
    662     ;
    663   for (nsc2 = 1; (1 << nsc2) < (idx2 - idx1); nsc2++)
    664     ;
    665   for (nsc3 = 1; (1 << nsc3) < (idx3 - idx2); nsc3++)
    666     ;
    667   for (nsc4 = 1; (1 << nsc4) < (idx4 - idx3); nsc4++)
    668     ;
    669 
    670   /* compute autocorrelation value at lag zero, i. e. energy, for each quarter
    671    */
    672   rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1);
    673   rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2);
    674   rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3);
    675   rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4);
    676 
    677   /* compute energy normalization factors, i. e. 1/energy (saves some divisions)
    678    */
    679   if (rxx1_0 != FL2FXCONST_DBL(0.f)) {
    680     INT sc_fac1 = -1;
    681     FIXP_DBL fac1 =
    682         FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2 * sc1) + nsc1), &sc_fac1);
    683     _rxx1[0] = scaleValue(fMult(rxx1_0, fac1), sc_fac1);
    684 
    685     if (isLowDelay) {
    686       for (lag = 1; lag <= maxOrder; lag++) {
    687         /* compute energy-normalized and windowed autocorrelation values at this
    688          * lag */
    689         FIXP_DBL x1 =
    690             FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
    691         _rxx1[lag] =
    692             fMult(scaleValue(fMult(x1, fac1), sc_fac1), acfWindow[LOFILT][lag]);
    693       }
    694     } else {
    695       for (lag = 1; lag <= maxOrder; lag++) {
    696         if ((3 * lag) <= maxOrder + 3) {
    697           FIXP_DBL x1 =
    698               FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
    699           _rxx1[lag] = fMult(scaleValue(fMult(x1, fac1), sc_fac1),
    700                              acfWindow[LOFILT][3 * lag]);
    701         }
    702       }
    703     }
    704   }
    705 
    706   /* auto corr over upper 3/4 of spectrum */
    707   if (!((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) &&
    708         (rxx4_0 == FL2FXCONST_DBL(0.f)))) {
    709     FIXP_DBL fac2, fac3, fac4;
    710     fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f);
    711     INT sc_fac2, sc_fac3, sc_fac4;
    712     sc_fac2 = sc_fac3 = sc_fac4 = 0;
    713 
    714     if (rxx2_0 != FL2FXCONST_DBL(0.f)) {
    715       fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2 * sc2) + nsc2), &sc_fac2);
    716       sc_fac2 -= 2;
    717     }
    718     if (rxx3_0 != FL2FXCONST_DBL(0.f)) {
    719       fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2 * sc3) + nsc3), &sc_fac3);
    720       sc_fac3 -= 2;
    721     }
    722     if (rxx4_0 != FL2FXCONST_DBL(0.f)) {
    723       fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2 * sc4) + nsc4), &sc_fac4);
    724       sc_fac4 -= 2;
    725     }
    726 
    727     _rxx2[0] = scaleValue(fMult(rxx2_0, fac2), sc_fac2) +
    728                scaleValue(fMult(rxx3_0, fac3), sc_fac3) +
    729                scaleValue(fMult(rxx4_0, fac4), sc_fac4);
    730 
    731     for (lag = 1; lag <= maxOrder; lag++) {
    732       /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays
    733        * separate */
    734       FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
    735                                          pSpectrum, idx1, idx2, lag, nsc2),
    736                                      fac2),
    737                                sc_fac2) +
    738                     scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
    739                                          pSpectrum, idx2, idx3, lag, nsc3),
    740                                      fac3),
    741                                sc_fac3) +
    742                     scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
    743                                          pSpectrum, idx3, idx4, lag, nsc4),
    744                                      fac4),
    745                                sc_fac4);
    746 
    747       _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]);
    748     }
    749   }
    750 
    751   C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024))
    752 }
    753 
    754 /*****************************************************************************
    755     functionname: FDKaacEnc_TnsDetect
    756     description:  do decision, if TNS shall be used or not
    757     returns:
    758     input:        tns data structure (modified),
    759                   tns config structure,
    760                   scalefactor size and table,
    761                   spectrum,
    762                   subblock num, blocktype,
    763                   sfb-wise energy.
    764 
    765 *****************************************************************************/
    766 INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC,
    767                         TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum,
    768                         INT subBlockNumber, INT blockType) {
    769   /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the
    770    * spectrum. */
    771   FIXP_DBL rxx1[TNS_MAX_ORDER + 1]; /* higher part */
    772   FIXP_DBL rxx2[TNS_MAX_ORDER + 1]; /* lower part */
    773   FIXP_LPC parcor_tmp[TNS_MAX_ORDER];
    774 
    775   int i;
    776 
    777   FDKmemclear(rxx1, sizeof(rxx1));
    778   FDKmemclear(rxx2, sizeof(rxx2));
    779 
    780   TNS_SUBBLOCK_INFO *tsbi =
    781       (blockType == SHORT_WINDOW)
    782           ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
    783           : &tnsData->dataRaw.Long.subBlockInfo;
    784 
    785   tnsData->filtersMerged = FALSE;
    786 
    787   tsbi->tnsActive[HIFILT] = FALSE;
    788   tsbi->predictionGain[HIFILT] = 1000;
    789   tsbi->tnsActive[LOFILT] = FALSE;
    790   tsbi->predictionGain[LOFILT] = 1000;
    791 
    792   tnsInfo->numOfFilters[subBlockNumber] = 0;
    793   tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
    794   for (i = 0; i < tC->maxOrder; i++) {
    795     tnsInfo->coef[subBlockNumber][HIFILT][i] =
    796         tnsInfo->coef[subBlockNumber][LOFILT][i] = 0;
    797   }
    798 
    799   tnsInfo->length[subBlockNumber][HIFILT] =
    800       tnsInfo->length[subBlockNumber][LOFILT] = 0;
    801   tnsInfo->order[subBlockNumber][HIFILT] =
    802       tnsInfo->order[subBlockNumber][LOFILT] = 0;
    803 
    804   if ((tC->tnsActive) && (tC->maxOrder > 0)) {
    805     int sumSqrCoef;
    806 
    807     FDKaacEnc_MergedAutoCorrelation(
    808         spectrum, tC->isLowDelay, tC->acfWindow, tC->lpcStartLine,
    809         tC->lpcStopLine, tC->maxOrder, tC->confTab.acfSplit, rxx1, rxx2);
    810 
    811     /* compute higher TNS filter coefficients in lattice form (ParCor) with
    812      * LeRoux-Gueguen/Schur algorithm */
    813     {
    814       FIXP_DBL predictionGain_m;
    815       INT predictionGain_e;
    816 
    817       CLpc_AutoToParcor(rxx2, 0, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT],
    818                         &predictionGain_m, &predictionGain_e);
    819       tsbi->predictionGain[HIFILT] =
    820           (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31);
    821     }
    822 
    823     /* non-linear quantization of TNS lattice coefficients with given resolution
    824      */
    825     FDKaacEnc_Parcor2Index(parcor_tmp, tnsInfo->coef[subBlockNumber][HIFILT],
    826                            tC->confTab.tnsLimitOrder[HIFILT], tC->coefRes);
    827 
    828     /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs))
    829      */
    830     for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) {
    831       if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
    832         break;
    833       }
    834     }
    835 
    836     tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
    837 
    838     sumSqrCoef = 0;
    839     for (; i >= 0; i--) {
    840       sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] *
    841                     tnsInfo->coef[subBlockNumber][HIFILT][i];
    842     }
    843 
    844     tnsInfo->direction[subBlockNumber][HIFILT] =
    845         tC->confTab.tnsFilterDirection[HIFILT];
    846     tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
    847 
    848     /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small
    849      */
    850     if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) ||
    851         (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT] / 2 + 2))) {
    852       tsbi->tnsActive[HIFILT] = TRUE;
    853       tnsInfo->numOfFilters[subBlockNumber]++;
    854 
    855       /* compute second filter for lower quarter; only allowed for long windows!
    856        */
    857       if ((blockType != SHORT_WINDOW) && (tC->confTab.filterEnabled[LOFILT]) &&
    858           (tC->confTab.seperateFiltersAllowed)) {
    859         /* compute second filter for lower frequencies */
    860 
    861         /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen
    862          * algorithm */
    863         INT predGain;
    864         {
    865           FIXP_DBL predictionGain_m;
    866           INT predictionGain_e;
    867 
    868           CLpc_AutoToParcor(rxx1, 0, parcor_tmp,
    869                             tC->confTab.tnsLimitOrder[LOFILT],
    870                             &predictionGain_m, &predictionGain_e);
    871           predGain =
    872               (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31);
    873         }
    874 
    875         /* non-linear quantization of TNS lattice coefficients with given
    876          * resolution */
    877         FDKaacEnc_Parcor2Index(parcor_tmp,
    878                                tnsInfo->coef[subBlockNumber][LOFILT],
    879                                tC->confTab.tnsLimitOrder[LOFILT], tC->coefRes);
    880 
    881         /* reduce filter order by truncating trailing zeros, compute
    882          * sum(abs(coefs)) */
    883         for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) {
    884           if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) {
    885             break;
    886           }
    887         }
    888         tnsInfo->order[subBlockNumber][LOFILT] = i + 1;
    889 
    890         sumSqrCoef = 0;
    891         for (; i >= 0; i--) {
    892           sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] *
    893                         tnsInfo->coef[subBlockNumber][LOFILT][i];
    894         }
    895 
    896         tnsInfo->direction[subBlockNumber][LOFILT] =
    897             tC->confTab.tnsFilterDirection[LOFILT];
    898         tnsInfo->length[subBlockNumber][LOFILT] =
    899             tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT];
    900 
    901         /* filter lower quarter if gain is high enough, but not if it's too high
    902          */
    903         if (((predGain > tC->confTab.threshOn[LOFILT]) &&
    904              (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT]))) ||
    905             ((sumSqrCoef > 9) &&
    906              (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]))) {
    907           /* compare lower to upper filter; if they are very similar, merge them
    908            */
    909           tsbi->tnsActive[LOFILT] = TRUE;
    910           sumSqrCoef = 0;
    911           for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
    912             sumSqrCoef += fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i] -
    913                                tnsInfo->coef[subBlockNumber][LOFILT][i]);
    914           }
    915           if ((sumSqrCoef < 2) &&
    916               (tnsInfo->direction[subBlockNumber][LOFILT] ==
    917                tnsInfo->direction[subBlockNumber][HIFILT])) {
    918             tnsData->filtersMerged = TRUE;
    919             tnsInfo->length[subBlockNumber][HIFILT] =
    920                 sfbCnt - tC->lpcStartBand[LOFILT];
    921             for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) {
    922               if (fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) {
    923                 break;
    924               }
    925             }
    926             for (i--; i >= 0; i--) {
    927               if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
    928                 break;
    929               }
    930             }
    931             if (i < tnsInfo->order[subBlockNumber][HIFILT]) {
    932               tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
    933             }
    934           } else {
    935             tnsInfo->numOfFilters[subBlockNumber]++;
    936           }
    937         } /* filter lower part */
    938         tsbi->predictionGain[LOFILT] = predGain;
    939 
    940       } /* second filter allowed  */
    941     }   /* if predictionGain > 1437 ... */
    942   }     /* maxOrder > 0 && tnsActive */
    943 
    944   return 0;
    945 }
    946 
    947 /***************************************************************************/
    948 /*!
    949   \brief     FDKaacLdEnc_TnsSync
    950 
    951   synchronize TNS parameters when TNS gain difference small (relative)
    952 
    953   \param pointer to TNS data structure (destination)
    954   \param pointer to TNS data structure (source)
    955   \param pointer to TNS config structure
    956   \param number of sub-block
    957   \param block type
    958 
    959   \return void
    960 ****************************************************************************/
    961 void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc,
    962                        TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc,
    963                        const INT blockTypeDest, const INT blockTypeSrc,
    964                        const TNS_CONFIG *tC) {
    965   int i, w, absDiff, nWindows;
    966   TNS_SUBBLOCK_INFO *sbInfoDest;
    967   const TNS_SUBBLOCK_INFO *sbInfoSrc;
    968 
    969   /* if one channel contains short blocks and the other not, do not synchronize
    970    */
    971   if ((blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) ||
    972       (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW)) {
    973     return;
    974   }
    975 
    976   if (blockTypeDest != SHORT_WINDOW) {
    977     sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo;
    978     sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo;
    979     nWindows = 1;
    980   } else {
    981     sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0];
    982     sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0];
    983     nWindows = 8;
    984   }
    985 
    986   for (w = 0; w < nWindows; w++) {
    987     const TNS_SUBBLOCK_INFO *pSbInfoSrcW = sbInfoSrc + w;
    988     TNS_SUBBLOCK_INFO *pSbInfoDestW = sbInfoDest + w;
    989     INT doSync = 1, absDiffSum = 0;
    990 
    991     /* if TNS is active in at least one channel, check if ParCor coefficients of
    992      * higher filter are similar */
    993     if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) {
    994       for (i = 0; i < tC->maxOrder; i++) {
    995         absDiff = fAbs(tnsInfoDest->coef[w][HIFILT][i] -
    996                        tnsInfoSrc->coef[w][HIFILT][i]);
    997         absDiffSum += absDiff;
    998         /* if coefficients diverge too much between channels, do not synchronize
    999          */
   1000         if ((absDiff > 1) || (absDiffSum > 2)) {
   1001           doSync = 0;
   1002           break;
   1003         }
   1004       }
   1005 
   1006       if (doSync) {
   1007         /* if no significant difference was detected, synchronize coefficient
   1008          * sets */
   1009         if (pSbInfoSrcW->tnsActive[HIFILT]) {
   1010           /* no dest filter, or more dest than source filters: use one dest
   1011            * filter */
   1012           if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
   1013               ((pSbInfoDestW->tnsActive[HIFILT]) &&
   1014                (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) {
   1015             pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1;
   1016           }
   1017           tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
   1018           tnsInfoDest->order[w][HIFILT] = tnsInfoSrc->order[w][HIFILT];
   1019           tnsInfoDest->length[w][HIFILT] = tnsInfoSrc->length[w][HIFILT];
   1020           tnsInfoDest->direction[w][HIFILT] = tnsInfoSrc->direction[w][HIFILT];
   1021           tnsInfoDest->coefCompress[w][HIFILT] =
   1022               tnsInfoSrc->coefCompress[w][HIFILT];
   1023 
   1024           for (i = 0; i < tC->maxOrder; i++) {
   1025             tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i];
   1026           }
   1027         } else
   1028           pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0;
   1029       }
   1030     }
   1031   }
   1032 }
   1033 
   1034 /***************************************************************************/
   1035 /*!
   1036   \brief     FDKaacEnc_TnsEncode
   1037 
   1038   perform TNS encoding
   1039 
   1040   \param pointer to TNS info structure
   1041   \param pointer to TNS data structure
   1042   \param number of sfbs
   1043   \param pointer to TNS config structure
   1044   \param low-pass line
   1045   \param pointer to spectrum
   1046   \param number of sub-block
   1047   \param block type
   1048 
   1049   \return ERROR STATUS
   1050 ****************************************************************************/
   1051 INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData,
   1052                         const INT numOfSfb, const TNS_CONFIG *tC,
   1053                         const INT lowPassLine, FIXP_DBL *spectrum,
   1054                         const INT subBlockNumber, const INT blockType) {
   1055   INT i, startLine, stopLine;
   1056 
   1057   if (((blockType == SHORT_WINDOW) &&
   1058        (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
   1059              .tnsActive[HIFILT])) ||
   1060       ((blockType != SHORT_WINDOW) &&
   1061        (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]))) {
   1062     return 1;
   1063   }
   1064 
   1065   startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT]
   1066                                        : tC->lpcStartLine[HIFILT];
   1067   stopLine = tC->lpcStopLine;
   1068 
   1069   for (i = 0; i < tnsInfo->numOfFilters[subBlockNumber]; i++) {
   1070     INT lpcGainFactor;
   1071     FIXP_LPC LpcCoeff[TNS_MAX_ORDER];
   1072     FIXP_DBL workBuffer[TNS_MAX_ORDER];
   1073     FIXP_LPC parcor_tmp[TNS_MAX_ORDER];
   1074 
   1075     FDKaacEnc_Index2Parcor(tnsInfo->coef[subBlockNumber][i], parcor_tmp,
   1076                            tnsInfo->order[subBlockNumber][i], tC->coefRes);
   1077 
   1078     lpcGainFactor = CLpc_ParcorToLpc(
   1079         parcor_tmp, LpcCoeff, tnsInfo->order[subBlockNumber][i], workBuffer);
   1080 
   1081     FDKmemclear(workBuffer, TNS_MAX_ORDER * sizeof(FIXP_DBL));
   1082     CLpc_Analysis(&spectrum[startLine], stopLine - startLine, LpcCoeff,
   1083                   lpcGainFactor, tnsInfo->order[subBlockNumber][i], workBuffer,
   1084                   NULL);
   1085 
   1086     /* update for second filter */
   1087     startLine = tC->lpcStartLine[LOFILT];
   1088     stopLine = tC->lpcStartLine[HIFILT];
   1089   }
   1090 
   1091   return (0);
   1092 }
   1093 
   1094 static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize,
   1095                                       const INT samplingRate,
   1096                                       const INT transformResolution,
   1097                                       const FIXP_DBL timeResolution,
   1098                                       const INT timeResolution_e) {
   1099 #define PI_E (2)
   1100 #define PI_M FL2FXCONST_DBL(3.1416f / (float)(1 << PI_E))
   1101 
   1102 #define EULER_E (2)
   1103 #define EULER_M FL2FXCONST_DBL(2.7183 / (float)(1 << EULER_E))
   1104 
   1105 #define COEFF_LOOP_SCALE (4)
   1106 
   1107   INT i, e1, e2, gaussExp_e;
   1108   FIXP_DBL gaussExp_m;
   1109 
   1110   /* calc. window exponent from time resolution:
   1111    *
   1112    *   gaussExp = PI * samplingRate * 0.001f * timeResolution /
   1113    * transformResolution; gaussExp = -0.5f * gaussExp * gaussExp;
   1114    */
   1115   gaussExp_m = fMultNorm(
   1116       timeResolution,
   1117       fMult(PI_M,
   1118             fDivNorm((FIXP_DBL)(samplingRate),
   1119                      (FIXP_DBL)(LONG)(transformResolution * 1000.f), &e1)),
   1120       &e2);
   1121   gaussExp_m = -fPow2Div2(gaussExp_m);
   1122   gaussExp_e = 2 * (e1 + e2 + timeResolution_e + PI_E);
   1123 
   1124   FDK_ASSERT(winSize < (1 << COEFF_LOOP_SCALE));
   1125 
   1126   /* calc. window coefficients
   1127    *   win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) );
   1128    */
   1129   for (i = 0; i < winSize; i++) {
   1130     win[i] = fPow(
   1131         EULER_M, EULER_E,
   1132         fMult(gaussExp_m,
   1133               fPow2((i * FL2FXCONST_DBL(1.f / (float)(1 << COEFF_LOOP_SCALE)) +
   1134                      FL2FXCONST_DBL(.5f / (float)(1 << COEFF_LOOP_SCALE))))),
   1135         gaussExp_e + 2 * COEFF_LOOP_SCALE, &e1);
   1136 
   1137     win[i] = scaleValueSaturate(win[i], e1);
   1138   }
   1139 }
   1140 
   1141 static INT FDKaacEnc_Search3(FIXP_LPC parcor) {
   1142   INT i, index = 0;
   1143 
   1144   for (i = 0; i < 8; i++) {
   1145     if (parcor > FDKaacEnc_tnsCoeff3Borders[i]) index = i;
   1146   }
   1147   return (index - 4);
   1148 }
   1149 
   1150 static INT FDKaacEnc_Search4(FIXP_LPC parcor) {
   1151   INT i, index = 0;
   1152 
   1153   for (i = 0; i < 16; i++) {
   1154     if (parcor > FDKaacEnc_tnsCoeff4Borders[i]) index = i;
   1155   }
   1156   return (index - 8);
   1157 }
   1158 
   1159 /*****************************************************************************
   1160 
   1161     functionname: FDKaacEnc_Parcor2Index
   1162 
   1163 *****************************************************************************/
   1164 static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index,
   1165                                    const INT order, const INT bitsPerCoeff) {
   1166   INT i;
   1167   for (i = 0; i < order; i++) {
   1168     if (bitsPerCoeff == 3)
   1169       index[i] = FDKaacEnc_Search3(parcor[i]);
   1170     else
   1171       index[i] = FDKaacEnc_Search4(parcor[i]);
   1172   }
   1173 }
   1174 
   1175 /*****************************************************************************
   1176 
   1177     functionname: FDKaacEnc_Index2Parcor
   1178     description:  inverse quantization for reflection coefficients
   1179     returns:      -
   1180     input:        quantized values, ptr. to reflection coefficients,
   1181                   no. of coefficients, resolution
   1182     output:       reflection coefficients
   1183 
   1184 *****************************************************************************/
   1185 static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor,
   1186                                    const INT order, const INT bitsPerCoeff) {
   1187   INT i;
   1188   for (i = 0; i < order; i++)
   1189     parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i] + 8]
   1190                                   : FDKaacEnc_tnsEncCoeff3[index[i] + 4];
   1191 }
   1192