Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and 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 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This 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
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /******************************** MPEG Audio Encoder **************************
     85 
     86    Initial author:       Alex Groeschel, Tobias Chalupka
     87    contents/description: Temporal noise shaping
     88 
     89 ******************************************************************************/
     90 
     91 #include "aacenc_tns.h"
     92 #include "psy_const.h"
     93 #include "psy_configuration.h"
     94 #include "tns_func.h"
     95 #include "aacEnc_rom.h"
     96 #include "aacenc_tns.h"
     97 
     98 #define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
     99 
    100 static const FIXP_DBL acfWindowLong[12+3+1] = {
    101   0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000,
    102   0x6e000000,0x69380000,0x63e00000,0x5df80000,0x57800000,0x50780000,0x48e00000,0x40b80000
    103 };
    104 
    105 static const FIXP_DBL acfWindowShort[4+3+1] = {
    106   0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000
    107 };
    108 
    109 typedef struct{
    110   INT                      bitRateFrom[2];  /* noneSbr=0, useSbr=1 */
    111   INT                      bitRateTo[2];    /* noneSbr=0, useSbr=1 */
    112   TNS_PARAMETER_TABULATED  paramTab[2];     /* mono=0, stereo=1 */
    113 
    114 } TNS_INFO_TAB;
    115 
    116 #define TNS_TIMERES_SCALE    (1)
    117 #define FL2_TIMERES_FIX(a)   ( FL2FXCONST_DBL(a/(float)(1<<TNS_TIMERES_SCALE)) )
    118 
    119 static const TNS_INFO_TAB tnsInfoTab[] =
    120 {
    121   {
    122     {  16000,  13500},
    123     {  32000,  28000},
    124     {
    125       { {1, 1}, {1437, 1500}, {1400, 600}, {12, 12}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, 1 },
    126       { {1, 1}, {1437, 1500}, {1400, 600}, {12, 12}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, 1 }
    127     }
    128   },
    129   {
    130     {  32001,  28001},
    131     {  60000,  52000},
    132     {
    133       { {1, 1}, {1437, 1500}, {1400, 600}, {12, 10}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 },
    134       { {1, 1}, {1437, 1500}, {1400, 600}, {12, 10}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 }
    135     }
    136   },
    137   {
    138     {  60001,  52001},
    139     { 384000, 384000},
    140     {
    141       { {1, 1}, {1437, 1500}, {1400, 600}, {12,  8}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 },
    142       { {1, 1}, {1437, 1500}, {1400, 600}, {12,  8}, {FILTER_DIRECTION, FILTER_DIRECTION}, {3, 1}, {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, 1 }
    143     }
    144   }
    145 };
    146 
    147 typedef struct {
    148   INT   samplingRate;
    149   SCHAR maxBands[2]; /* long=0; short=1 */
    150 
    151 } TNS_MAX_TAB_ENTRY;
    152 
    153 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] =
    154 {
    155   { 96000, { 31,  9}},
    156   { 88200, { 31,  9}},
    157   { 64000, { 34, 10}},
    158   { 48000, { 40, 14}},
    159   { 44100, { 42, 14}},
    160   { 32000, { 51, 14}},
    161   { 24000, { 46, 14}},
    162   { 22050, { 46, 14}},
    163   { 16000, { 42, 14}},
    164   { 12000, { 42, 14}},
    165   { 11025, { 42, 14}},
    166   { 8000,  { 39, 14}}
    167 };
    168 
    169 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] =
    170 {
    171   { 48000, { 31, -1}},
    172   { 44100, { 32, -1}},
    173   { 32000, { 37, -1}},
    174   { 24000, { 30, -1}},
    175   { 22050, { 30, -1}}
    176 };
    177 
    178 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] =
    179 {
    180   { 48000, { 31, -1}},
    181   { 44100, { 32, -1}},
    182   { 32000, { 37, -1}},
    183   { 24000, { 31, -1}},
    184   { 22050, { 31, -1}}
    185 };
    186 
    187 static INT FDKaacEnc_AutoToParcor(
    188         FIXP_DBL *RESTRICT input,
    189         FIXP_DBL *RESTRICT reflCoeff,
    190         const INT numOfCoeff
    191         );
    192 
    193 static void FDKaacEnc_Parcor2Index(
    194         const FIXP_DBL *parcor,
    195         INT *RESTRICT index,
    196         const INT order,
    197         const INT bitsPerCoeff
    198         );
    199 
    200 static void FDKaacEnc_Index2Parcor(
    201         const INT *index,
    202         FIXP_DBL *RESTRICT parcor,
    203         const INT order,
    204         const INT bitsPerCoeff
    205         );
    206 
    207 static INT FDKaacEnc_ParcorToLpc(
    208         const FIXP_DBL *reflCoeff,
    209         FIXP_DBL *RESTRICT LpcCoeff,
    210         const INT numOfCoeff,
    211         FIXP_DBL *RESTRICT workBuffer
    212         );
    213 
    214 static void FDKaacEnc_AnalysisFilter(
    215         FIXP_DBL *RESTRICT signal,
    216         const INT numOfLines,
    217         const FIXP_DBL *predictorCoeff,
    218         const INT order,
    219         const INT lpcGainFactor
    220         );
    221 
    222 static void FDKaacEnc_CalcGaussWindow(
    223         FIXP_DBL *win,
    224         const int winSize,
    225         const INT samplingRate,
    226         const INT transformResolution,
    227         const FIXP_DBL timeResolution,
    228         const INT timeResolution_e
    229         );
    230 
    231 static const TNS_PARAMETER_TABULATED* FDKaacEnc_GetTnsParam(
    232         const INT bitRate,
    233         const INT channels,
    234         const INT sbrLd
    235         )
    236 {
    237   int i;
    238   const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL;
    239 
    240   for (i = 0; i < (int) (sizeof(tnsInfoTab)/sizeof(TNS_INFO_TAB)); i++) {
    241     if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd?1:0]) &&
    242          bitRate <= tnsInfoTab[i].bitRateTo[sbrLd?1:0])
    243     {
    244       tnsConfigTab = &tnsInfoTab[i].paramTab[(channels==1)?0:1];
    245     }
    246   }
    247 
    248   return tnsConfigTab;
    249 }
    250 
    251 
    252 static INT getTnsMaxBands(
    253         const INT sampleRate,
    254         const INT granuleLength,
    255         const INT isShortBlock
    256         )
    257 {
    258   int i;
    259   INT numBands = -1;
    260   const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL;
    261   int maxBandsTabSize = 0;
    262 
    263   switch (granuleLength) {
    264     case 1024:
    265       pMaxBandsTab = tnsMaxBandsTab1024;
    266       maxBandsTabSize = sizeof(tnsMaxBandsTab1024)/sizeof(TNS_MAX_TAB_ENTRY);
    267       break;
    268     case 480:
    269       pMaxBandsTab = tnsMaxBandsTab480;
    270       maxBandsTabSize = sizeof(tnsMaxBandsTab480)/sizeof(TNS_MAX_TAB_ENTRY);
    271       break;
    272     case 512:
    273       pMaxBandsTab = tnsMaxBandsTab512;
    274       maxBandsTabSize = sizeof(tnsMaxBandsTab512)/sizeof(TNS_MAX_TAB_ENTRY);
    275       break;
    276     default:
    277       numBands = -1;
    278   }
    279 
    280   if (pMaxBandsTab!=NULL) {
    281     for (i=0; i<maxBandsTabSize; i++) {
    282       numBands = pMaxBandsTab[i].maxBands[(!isShortBlock)?0:1];
    283       if (sampleRate >= pMaxBandsTab[i].samplingRate) {
    284         break;
    285       }
    286     }
    287   }
    288 
    289   return numBands;
    290 }
    291 
    292 /***************************************************************************/
    293 /*!
    294   \brief     FDKaacEnc_FreqToBandWithRounding
    295 
    296   Returns index of nearest band border
    297 
    298   \param frequency
    299   \param sampling frequency
    300   \param total number of bands
    301   \param pointer to table of band borders
    302 
    303   \return band border
    304 ****************************************************************************/
    305 
    306 INT FDKaacEnc_FreqToBandWithRounding(
    307         const INT freq,
    308         const INT fs,
    309         const INT numOfBands,
    310         const INT *bandStartOffset
    311         )
    312 {
    313   INT lineNumber, band;
    314 
    315   /*  assert(freq >= 0);  */
    316   lineNumber = (freq*bandStartOffset[numOfBands]*4/fs+1)/2;
    317 
    318   /* freq > fs/2 */
    319   if (lineNumber >= bandStartOffset[numOfBands])
    320     return numOfBands;
    321 
    322   /* find band the line number lies in */
    323   for (band=0; band<numOfBands; band++) {
    324     if (bandStartOffset[band+1]>lineNumber) break;
    325   }
    326 
    327   /* round to nearest band border */
    328   if (lineNumber - bandStartOffset[band] >
    329       bandStartOffset[band+1] - lineNumber )
    330     {
    331       band++;
    332     }
    333 
    334   return(band);
    335 }
    336 
    337 
    338 /*****************************************************************************
    339 
    340     functionname: FDKaacEnc_InitTnsConfiguration
    341     description:  fill TNS_CONFIG structure with sensible content
    342     returns:
    343     input:        bitrate, samplerate, number of channels,
    344                   blocktype (long or short),
    345                   TNS Config struct (modified),
    346                   psy config struct,
    347                   tns active flag
    348     output:
    349 
    350 *****************************************************************************/
    351 AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate,
    352                                                  INT sampleRate,
    353                                                  INT channels,
    354                                                  INT blockType,
    355                                                  INT granuleLength,
    356                                                  INT isLowDelay,
    357                                                  INT ldSbrPresent,
    358                                                  TNS_CONFIG *tC,
    359                                                  PSY_CONFIGURATION *pC,
    360                                                  INT active,
    361                                                  INT useTnsPeak)
    362 {
    363   int i;
    364   //float acfTimeRes   = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f;
    365 
    366   if (channels <= 0)
    367     return (AAC_ENCODER_ERROR)1;
    368 
    369   tC->isLowDelay = isLowDelay;
    370 
    371   /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */
    372   tC->tnsActive      = (active) ? TRUE : FALSE;
    373   tC->maxOrder       = (blockType == SHORT_WINDOW) ? 5 : 12;  /* maximum: 7, 20 */
    374   if (bitRate < 16000)
    375     tC->maxOrder -= 2;
    376   tC->coefRes        = (blockType == SHORT_WINDOW) ? 3 : 4;
    377 
    378   /* LPC stop line: highest MDCT line to be coded, but do not go beyond TNS_MAX_BANDS! */
    379   tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, (blockType == SHORT_WINDOW) ? 1 : 0);
    380 
    381   if (tC->lpcStopBand < 0) {
    382     return (AAC_ENCODER_ERROR)1;
    383   }
    384 
    385   tC->lpcStopBand = FDKmin(tC->lpcStopBand, pC->sfbActive);
    386   tC->lpcStopLine    = pC->sfbOffset[tC->lpcStopBand];
    387 
    388   switch (granuleLength) {
    389     case 1024:
    390       /* TNS start line: skip lower MDCT lines to prevent artifacts due to filter mismatch */
    391       tC->lpcStartBand[LOFILT]   = (blockType == SHORT_WINDOW) ? 0 : ((sampleRate < 18783) ? 4 : 8);
    392       tC->lpcStartLine[LOFILT]   = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
    393 
    394       i = tC->lpcStopBand;
    395       while (pC->sfbOffset[i] > (tC->lpcStartLine[LOFILT] + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) i--;
    396       tC->lpcStartBand[HIFILT]   = i;
    397       tC->lpcStartLine[HIFILT]   = pC->sfbOffset[i];
    398 
    399       tC->confTab.threshOn[HIFILT] = 1437;
    400       tC->confTab.threshOn[LOFILT] = 1500;
    401 
    402       tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder;
    403       tC->confTab.tnsLimitOrder[LOFILT] = tC->maxOrder - 7;
    404 
    405       tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION;
    406       tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION;
    407 
    408       tC->confTab.acfSplit[HIFILT] = -1;  /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation*/
    409       tC->confTab.acfSplit[LOFILT] = -1;  /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation */
    410 
    411       tC->confTab.filterEnabled[HIFILT] = 1;
    412       tC->confTab.filterEnabled[LOFILT] = 1;
    413       tC->confTab.seperateFiltersAllowed = 1;
    414 
    415       /* compute autocorrelation window based on maximum filter order for given block type */
    416       /* for (i = 0; i <= tC->maxOrder + 3; i++) {
    417            float acfWinTemp = acfTimeRes * i;
    418            acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp);
    419          }
    420       */
    421       if (blockType == SHORT_WINDOW) {
    422         FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT])));
    423         FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT])));
    424       }
    425       else {
    426         FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT])));
    427         FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT])));
    428       }
    429       break;
    430     case 480:
    431     case 512:
    432       {
    433         const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
    434 
    435         if ( pCfg != NULL ) {
    436 
    437           FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
    438 
    439           tC->lpcStartBand[HIFILT]         = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
    440           tC->lpcStartLine[HIFILT]         = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
    441           tC->lpcStartBand[LOFILT]         = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset);
    442           tC->lpcStartLine[LOFILT]         = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
    443 
    444           FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE);
    445           FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE);
    446         }
    447         else {
    448           tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
    449         }
    450       }
    451       break;
    452     default:
    453       tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
    454   }
    455 
    456   return AAC_ENC_OK;
    457 
    458 }
    459 
    460 /***************************************************************************/
    461 /*!
    462   \brief     FDKaacEnc_ScaleUpSpectrum
    463 
    464   Scales up spectrum lines in a given frequency section
    465 
    466   \param scaled spectrum
    467   \param original spectrum
    468   \param frequency line to start scaling
    469   \param frequency line to enc scaling
    470 
    471   \return scale factor
    472 
    473 ****************************************************************************/
    474 static inline INT FDKaacEnc_ScaleUpSpectrum(
    475         FIXP_DBL                 *dest,
    476         const FIXP_DBL           *src,
    477         const INT                 startLine,
    478         const INT                 stopLine
    479         )
    480 {
    481     INT i, scale;
    482 
    483     FIXP_DBL maxVal = FL2FXCONST_DBL(0.f);
    484 
    485     /* Get highest value in given spectrum */
    486     for (i=startLine; i<stopLine; i++) {
    487       maxVal = fixMax(maxVal,fixp_abs(src[i]));
    488     }
    489     scale = CountLeadingBits(maxVal);
    490 
    491     /* Scale spectrum according to highest value */
    492     for (i=startLine; i<stopLine; i++) {
    493       dest[i] = src[i]<<scale;
    494     }
    495 
    496     return scale;
    497 }
    498 
    499 /***************************************************************************/
    500 /*!
    501   \brief     FDKaacEnc_CalcAutoCorrValue
    502 
    503   Calculate autocorellation value for one lag
    504 
    505   \param pointer to spectrum
    506   \param start line
    507   \param stop line
    508   \param lag to be calculated
    509   \param scaling of the lag
    510 
    511 ****************************************************************************/
    512 static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(
    513         const FIXP_DBL           *spectrum,
    514         const INT                 startLine,
    515         const INT                 stopLine,
    516         const INT                 lag,
    517         const INT                 scale
    518         )
    519 {
    520     int i;
    521     FIXP_DBL result = FL2FXCONST_DBL(0.f);
    522 
    523     if (lag==0) {
    524       for (i=startLine; i<stopLine; i++) {
    525         result += (fPow2(spectrum[i])>>scale);
    526       }
    527     }
    528     else {
    529       for (i=startLine; i<(stopLine-lag); i++) {
    530         result += (fMult(spectrum[i], spectrum[i+lag])>>scale);
    531       }
    532     }
    533 
    534     return result;
    535 }
    536 
    537 /***************************************************************************/
    538 /*!
    539   \brief     FDKaacEnc_AutoCorrNormFac
    540 
    541   Autocorrelation function for 1st and 2nd half of the spectrum
    542 
    543   \param pointer to spectrum
    544   \param pointer to autocorrelation window
    545   \param filter start line
    546 
    547 ****************************************************************************/
    548 static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(
    549         const FIXP_DBL            value,
    550         const INT                 scale,
    551         INT                      *sc
    552         )
    553 {
    554     #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */
    555     #define MAX_INV_NRGFAC (1.f/HLM_MIN_NRG)
    556 
    557     FIXP_DBL retValue;
    558     FIXP_DBL A, B;
    559 
    560     if (scale>=0) {
    561       A = value;
    562       B = FL2FXCONST_DBL(HLM_MIN_NRG)>>fixMin(DFRACT_BITS-1,scale);
    563     }
    564     else {
    565       A = value>>fixMin(DFRACT_BITS-1,(-scale));
    566       B = FL2FXCONST_DBL(HLM_MIN_NRG);
    567     }
    568 
    569     if (A > B) {
    570       int shift = 0;
    571       FIXP_DBL tmp = invSqrtNorm2(value,&shift);
    572 
    573       retValue = fMult(tmp,tmp);
    574       *sc += (2*shift);
    575     }
    576     else {
    577       /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */
    578       retValue = /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL;
    579       *sc += scale+28;
    580     }
    581 
    582     return retValue;
    583 }
    584 
    585 static void FDKaacEnc_MergedAutoCorrelation(
    586         const FIXP_DBL           *spectrum,
    587         const INT                 isLowDelay,
    588         const FIXP_DBL            acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],
    589         const INT                 lpcStartLine[MAX_NUM_OF_FILTERS],
    590         const INT                 lpcStopLine,
    591         const INT                 maxOrder,
    592         const INT                 acfSplit[MAX_NUM_OF_FILTERS],
    593         FIXP_DBL                 *_rxx1,
    594         FIXP_DBL                 *_rxx2
    595         )
    596 {
    597     int i, idx0, idx1, idx2, idx3, idx4, lag;
    598     FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0;
    599 
    600     /* buffer for temporal spectrum */
    601     C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024));
    602 
    603     /* pre-initialization output */
    604     FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1));
    605     FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1));
    606 
    607     idx0 = idx1 = idx2 = idx3 = idx4 = 0;
    608 
    609     /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */
    610     if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) {
    611       /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */
    612       idx0 = lpcStartLine[LOFILT];
    613       i    = lpcStopLine - lpcStartLine[LOFILT];
    614       idx1 = idx0 + i / 4;
    615       idx2 = idx0 + i / 2;
    616       idx3 = idx0 + i * 3 / 4;
    617       idx4 = lpcStopLine;
    618     }
    619     else {
    620       FDK_ASSERT(acfSplit[LOFILT]==1);
    621       FDK_ASSERT(acfSplit[HIFILT]==3);
    622       i    = (lpcStopLine - lpcStartLine[HIFILT]) / 3;
    623       idx0 = lpcStartLine[LOFILT];
    624       idx1 = lpcStartLine[HIFILT];
    625       idx2 = idx1 + i;
    626       idx3 = idx2 + i;
    627       idx4 = lpcStopLine;
    628     }
    629 
    630     /* copy spectrum to temporal buffer and scale up as much as possible */
    631     INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1);
    632     INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2);
    633     INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3);
    634     INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4);
    635 
    636     /* get scaling values for summation */
    637     INT nsc1, nsc2, nsc3, nsc4;
    638     for (nsc1=1; (1<<nsc1)<(idx1-idx0); nsc1++);
    639     for (nsc2=1; (1<<nsc2)<(idx2-idx1); nsc2++);
    640     for (nsc3=1; (1<<nsc3)<(idx3-idx2); nsc3++);
    641     for (nsc4=1; (1<<nsc4)<(idx4-idx3); nsc4++);
    642 
    643     /* compute autocorrelation value at lag zero, i. e. energy, for each quarter */
    644     rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1);
    645     rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2);
    646     rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3);
    647     rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4);
    648 
    649     /* compute energy normalization factors, i. e. 1/energy (saves some divisions) */
    650     if (rxx1_0 != FL2FXCONST_DBL(0.f))
    651     {
    652       INT sc_fac1 = -1;
    653       FIXP_DBL fac1 = FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2*sc1)+nsc1), &sc_fac1);
    654       _rxx1[0] = scaleValue(fMult(rxx1_0,fac1),sc_fac1);
    655 
    656       if (isLowDelay)
    657       {
    658         for (lag = 1; lag <= maxOrder; lag++) {
    659           /* compute energy-normalized and windowed autocorrelation values at this lag */
    660           FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
    661           _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][lag]);
    662         }
    663       }
    664       else
    665       {
    666         for (lag = 1; lag <= maxOrder; lag++) {
    667           if ((3 * lag) <= maxOrder + 3) {
    668               FIXP_DBL x1 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
    669               _rxx1[lag] = fMult(scaleValue(fMult(x1,fac1),sc_fac1), acfWindow[LOFILT][3*lag]);
    670           }
    671         }
    672       }
    673     }
    674 
    675     /* auto corr over upper 3/4 of spectrum */
    676     if ( !((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) && (rxx4_0 == FL2FXCONST_DBL(0.f))) )
    677     {
    678         FIXP_DBL fac2, fac3, fac4;
    679         fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f);
    680         INT sc_fac2, sc_fac3, sc_fac4;
    681         sc_fac2 = sc_fac3 = sc_fac4 = 0;
    682 
    683         if (rxx2_0!=FL2FXCONST_DBL(0.f)) {
    684           fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2*sc2)+nsc2), &sc_fac2);
    685           sc_fac2 -= 2;
    686         }
    687         if (rxx3_0!=FL2FXCONST_DBL(0.f)) {
    688           fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2*sc3)+nsc3), &sc_fac3);
    689           sc_fac3 -= 2;
    690         }
    691         if (rxx4_0!=FL2FXCONST_DBL(0.f)) {
    692           fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2*sc4)+nsc4), &sc_fac4);
    693           sc_fac4 -= 2;
    694         }
    695 
    696         _rxx2[0] = scaleValue(fMult(rxx2_0,fac2),sc_fac2) +
    697                    scaleValue(fMult(rxx3_0,fac3),sc_fac3) +
    698                    scaleValue(fMult(rxx4_0,fac4),sc_fac4);
    699 
    700         for (lag = 1; lag <= maxOrder; lag++) {
    701           /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays separate */
    702           FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, lag, nsc2), fac2),sc_fac2) +
    703                         scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, lag, nsc3), fac3),sc_fac3) +
    704                         scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, lag, nsc4), fac4),sc_fac4);
    705 
    706           _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]);
    707         }
    708     }
    709 
    710     C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024));
    711 }
    712 
    713 
    714 /*****************************************************************************
    715     functionname: FDKaacEnc_TnsDetect
    716     description:  do decision, if TNS shall be used or not
    717     returns:
    718     input:        tns data structure (modified),
    719                   tns config structure,
    720                   scalefactor size and table,
    721                   spectrum,
    722                   subblock num, blocktype,
    723                   sfb-wise energy.
    724 
    725 *****************************************************************************/
    726 INT FDKaacEnc_TnsDetect(
    727               TNS_DATA *tnsData,
    728               const TNS_CONFIG *tC,
    729               TNS_INFO* tnsInfo,
    730               INT sfbCnt,
    731               FIXP_DBL *spectrum,
    732               INT subBlockNumber,
    733               INT blockType
    734               )
    735 {
    736   /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum. */
    737   FIXP_DBL rxx1[TNS_MAX_ORDER+1]; /* higher part */
    738   FIXP_DBL rxx2[TNS_MAX_ORDER+1]; /* lower part */
    739   FIXP_DBL parcor_tmp[TNS_MAX_ORDER];
    740 
    741   int i;
    742 
    743   TNS_SUBBLOCK_INFO *tsbi = (blockType == SHORT_WINDOW)
    744     ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
    745     : &tnsData->dataRaw.Long.subBlockInfo;
    746 
    747   tnsData->filtersMerged  = FALSE;
    748 
    749   tsbi->tnsActive[HIFILT]         = FALSE;
    750   tsbi->predictionGain[HIFILT]    = 1000;
    751   tsbi->tnsActive[LOFILT]         = FALSE;
    752   tsbi->predictionGain[LOFILT]    = 1000;
    753 
    754   tnsInfo->numOfFilters[subBlockNumber] = 0;
    755   tnsInfo->coefRes[subBlockNumber]      = tC->coefRes;
    756   for (i = 0; i < tC->maxOrder; i++) {
    757     tnsInfo->coef[subBlockNumber][HIFILT][i] = tnsInfo->coef[subBlockNumber][LOFILT][i] = 0;
    758   }
    759 
    760   tnsInfo->length[subBlockNumber][HIFILT] = tnsInfo->length[subBlockNumber][LOFILT] = 0;
    761   tnsInfo->order [subBlockNumber][HIFILT] = tnsInfo->order [subBlockNumber][LOFILT] = 0;
    762 
    763   if ( (tC->tnsActive) && (tC->maxOrder>0) )
    764   {
    765     int sumSqrCoef;
    766 
    767     FDKaacEnc_MergedAutoCorrelation(
    768           spectrum,
    769           tC->isLowDelay,
    770           tC->acfWindow,
    771           tC->lpcStartLine,
    772           tC->lpcStopLine,
    773           tC->maxOrder,
    774           tC->confTab.acfSplit,
    775           rxx1,
    776           rxx2);
    777 
    778     /* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
    779     tsbi->predictionGain[HIFILT] = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]);
    780 
    781     /* non-linear quantization of TNS lattice coefficients with given resolution */
    782     FDKaacEnc_Parcor2Index(
    783             parcor_tmp,
    784             tnsInfo->coef[subBlockNumber][HIFILT],
    785             tC->confTab.tnsLimitOrder[HIFILT],
    786             tC->coefRes);
    787 
    788     /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */
    789     for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) {
    790       if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
    791         break;
    792       }
    793     }
    794 
    795     tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
    796 
    797     sumSqrCoef = 0;
    798     for (; i >= 0; i--) {
    799       sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] * tnsInfo->coef[subBlockNumber][HIFILT][i];
    800     }
    801 
    802     tnsInfo->direction[subBlockNumber][HIFILT] = tC->confTab.tnsFilterDirection[HIFILT];
    803     tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
    804 
    805     /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */
    806     if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2)))
    807     {
    808       tsbi->tnsActive[HIFILT] = TRUE;
    809       tnsInfo->numOfFilters[subBlockNumber]++;
    810 
    811       /* compute second filter for lower quarter; only allowed for long windows! */
    812       if ( (blockType != SHORT_WINDOW) &&
    813            (tC->confTab.filterEnabled[LOFILT]) && (tC->confTab.seperateFiltersAllowed) )
    814       {
    815         /* compute second filter for lower frequencies */
    816 
    817         /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
    818         INT predGain = FDKaacEnc_AutoToParcor(rxx1, parcor_tmp, tC->confTab.tnsLimitOrder[LOFILT]);
    819 
    820         /* non-linear quantization of TNS lattice coefficients with given resolution */
    821         FDKaacEnc_Parcor2Index(
    822                 parcor_tmp,
    823                 tnsInfo->coef[subBlockNumber][LOFILT],
    824                 tC->confTab.tnsLimitOrder[LOFILT],
    825                 tC->coefRes);
    826 
    827         /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */
    828         for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) {
    829           if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) {
    830             break;
    831           }
    832         }
    833         tnsInfo->order[subBlockNumber][LOFILT] = i + 1;
    834 
    835         sumSqrCoef = 0;
    836         for (; i >= 0; i--) {
    837           sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] * tnsInfo->coef[subBlockNumber][LOFILT][i];
    838         }
    839 
    840         tnsInfo->direction[subBlockNumber][LOFILT] = tC->confTab.tnsFilterDirection[LOFILT];
    841         tnsInfo->length[subBlockNumber][LOFILT] = tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT];
    842 
    843         /* filter lower quarter if gain is high enough, but not if it's too high */
    844         if ( ( (predGain > tC->confTab.threshOn[LOFILT]) && (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT])) )
    845           || ( (sumSqrCoef > 9)  && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) )
    846         {
    847           /* compare lower to upper filter; if they are very similar, merge them */
    848           tsbi->tnsActive[LOFILT] = TRUE;
    849           sumSqrCoef = 0;
    850           for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
    851             sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]);
    852           }
    853           if ( (sumSqrCoef < 2) &&
    854                (tnsInfo->direction[subBlockNumber][LOFILT] == tnsInfo->direction[subBlockNumber][HIFILT]) )
    855           {
    856             tnsData->filtersMerged = TRUE;
    857             tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[LOFILT];
    858             for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) {
    859               if (FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) {
    860                 break;
    861               }
    862             }
    863             for (i--; i >= 0; i--) {
    864               if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
    865                 break;
    866               }
    867             }
    868             if (i < tnsInfo->order[subBlockNumber][HIFILT]) {
    869               tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
    870             }
    871           }
    872           else {
    873             tnsInfo->numOfFilters[subBlockNumber]++;
    874           }
    875         } /* filter lower part */
    876         tsbi->predictionGain[LOFILT]=predGain;
    877 
    878       } /* second filter allowed  */
    879     } /* if predictionGain > 1437 ... */
    880   } /* maxOrder > 0 && tnsActive */
    881 
    882   return 0;
    883 
    884 }
    885 
    886 
    887 /***************************************************************************/
    888 /*!
    889   \brief     FDKaacLdEnc_TnsSync
    890 
    891   synchronize TNS parameters when TNS gain difference small (relative)
    892 
    893   \param pointer to TNS data structure (destination)
    894   \param pointer to TNS data structure (source)
    895   \param pointer to TNS config structure
    896   \param number of sub-block
    897   \param block type
    898 
    899   \return void
    900 ****************************************************************************/
    901 void FDKaacEnc_TnsSync(
    902              TNS_DATA *tnsDataDest,
    903              const TNS_DATA *tnsDataSrc,
    904              TNS_INFO *tnsInfoDest,
    905              TNS_INFO *tnsInfoSrc,
    906              const INT blockTypeDest,
    907              const INT blockTypeSrc,
    908              const TNS_CONFIG *tC
    909              )
    910 {
    911   int i, w, absDiff, nWindows;
    912   TNS_SUBBLOCK_INFO *sbInfoDest;
    913   const TNS_SUBBLOCK_INFO *sbInfoSrc;
    914 
    915   /* if one channel contains short blocks and the other not, do not synchronize */
    916   if ( (blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) ||
    917        (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW) )
    918   {
    919     return;
    920   }
    921 
    922   if (blockTypeDest != SHORT_WINDOW) {
    923     sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo;
    924     sbInfoSrc  = &tnsDataSrc->dataRaw.Long.subBlockInfo;
    925     nWindows   = 1;
    926   } else {
    927     sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0];
    928     sbInfoSrc  = &tnsDataSrc->dataRaw.Short.subBlockInfo[0];
    929     nWindows   = 8;
    930   }
    931 
    932   for (w=0; w<nWindows; w++) {
    933       const TNS_SUBBLOCK_INFO *pSbInfoSrcW  = sbInfoSrc  + w;
    934       TNS_SUBBLOCK_INFO       *pSbInfoDestW = sbInfoDest + w;
    935       INT doSync = 1, absDiffSum = 0;
    936 
    937       /* if TNS is active in at least one channel, check if ParCor coefficients of higher filter are similar */
    938       if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) {
    939         for (i = 0; i < tC->maxOrder; i++) {
    940           absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]);
    941           absDiffSum += absDiff;
    942           /* if coefficients diverge too much between channels, do not synchronize */
    943           if ((absDiff > 1) || (absDiffSum > 2)) {
    944             doSync = 0;
    945             break;
    946           }
    947         }
    948 
    949         if (doSync) {
    950             /* if no significant difference was detected, synchronize coefficient sets */
    951             if (pSbInfoSrcW->tnsActive[HIFILT]) {
    952               /* no dest filter, or more dest than source filters: use one dest filter */
    953               if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
    954                   ((pSbInfoDestW->tnsActive[HIFILT]) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w])))
    955               {
    956                 pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1;
    957               }
    958               tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
    959               tnsInfoDest->order       [w][HIFILT] = tnsInfoSrc->order       [w][HIFILT];
    960               tnsInfoDest->length      [w][HIFILT] = tnsInfoSrc->length      [w][HIFILT];
    961               tnsInfoDest->direction   [w][HIFILT] = tnsInfoSrc->direction   [w][HIFILT];
    962               tnsInfoDest->coefCompress[w][HIFILT] = tnsInfoSrc->coefCompress[w][HIFILT];
    963 
    964               for (i = 0; i < tC->maxOrder; i++) {
    965                 tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i];
    966               }
    967             }
    968             else
    969               pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0;
    970             }
    971         }
    972 
    973     }
    974 }
    975 
    976 /***************************************************************************/
    977 /*!
    978   \brief     FDKaacEnc_TnsEncode
    979 
    980   perform TNS encoding
    981 
    982   \param pointer to TNS info structure
    983   \param pointer to TNS data structure
    984   \param number of sfbs
    985   \param pointer to TNS config structure
    986   \param low-pass line
    987   \param pointer to spectrum
    988   \param number of sub-block
    989   \param block type
    990 
    991   \return ERROR STATUS
    992 ****************************************************************************/
    993 INT FDKaacEnc_TnsEncode(
    994         TNS_INFO* tnsInfo,
    995         TNS_DATA* tnsData,
    996         const INT numOfSfb,
    997         const TNS_CONFIG *tC,
    998         const INT lowPassLine,
    999         FIXP_DBL* spectrum,
   1000         const INT subBlockNumber,
   1001         const INT blockType
   1002         )
   1003 {
   1004     INT i, startLine, stopLine;
   1005 
   1006     if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) )
   1007       || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) )
   1008     {
   1009       return 1;
   1010     }
   1011 
   1012     startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT] : tC->lpcStartLine[HIFILT];
   1013     stopLine  = tC->lpcStopLine;
   1014 
   1015     for (i=0; i<tnsInfo->numOfFilters[subBlockNumber]; i++) {
   1016 
   1017         INT lpcGainFactor;
   1018         FIXP_DBL LpcCoeff[TNS_MAX_ORDER];
   1019         FIXP_DBL workBuffer[TNS_MAX_ORDER];
   1020         FIXP_DBL parcor_tmp[TNS_MAX_ORDER];
   1021 
   1022         FDKaacEnc_Index2Parcor(
   1023                 tnsInfo->coef[subBlockNumber][i],
   1024                 parcor_tmp,
   1025                 tnsInfo->order[subBlockNumber][i],
   1026                 tC->coefRes);
   1027 
   1028         lpcGainFactor = FDKaacEnc_ParcorToLpc(
   1029                 parcor_tmp,
   1030                 LpcCoeff,
   1031                 tnsInfo->order[subBlockNumber][i],
   1032                 workBuffer);
   1033 
   1034         FDKaacEnc_AnalysisFilter(
   1035                 &spectrum[startLine],
   1036                 stopLine - startLine,
   1037                 LpcCoeff,
   1038                 tnsInfo->order[subBlockNumber][i],
   1039                 lpcGainFactor);
   1040 
   1041         /* update for second filter */
   1042         startLine = tC->lpcStartLine[LOFILT];
   1043         stopLine  = tC->lpcStartLine[HIFILT];
   1044     }
   1045 
   1046     return(0);
   1047 
   1048 }
   1049 
   1050 static void FDKaacEnc_CalcGaussWindow(
   1051         FIXP_DBL *win,
   1052         const int winSize,
   1053         const INT samplingRate,
   1054         const INT transformResolution,
   1055         const FIXP_DBL timeResolution,
   1056         const INT timeResolution_e
   1057         )
   1058 {
   1059   #define PI_E           (2)
   1060   #define PI_M           FL2FXCONST_DBL(3.1416f/(float)(1<<PI_E))
   1061 
   1062   #define EULER_E        (2)
   1063   #define EULER_M        FL2FXCONST_DBL(2.7183/(float)(1<<EULER_E))
   1064 
   1065   #define COEFF_LOOP_SCALE (4)
   1066 
   1067   INT i, e1, e2, gaussExp_e;
   1068   FIXP_DBL gaussExp_m;
   1069 
   1070   /* calc. window exponent from time resolution:
   1071    *
   1072    *   gaussExp = PI * samplingRate * 0.001f * timeResolution / transformResolution;
   1073    *   gaussExp = -0.5f * gaussExp * gaussExp;
   1074    */
   1075   gaussExp_m = fMultNorm(timeResolution, fMult(PI_M, fDivNorm( (FIXP_DBL)(samplingRate), (FIXP_DBL)(LONG)(transformResolution*1000.f), &e1)), &e2);
   1076   gaussExp_m = -fPow2Div2(gaussExp_m);
   1077   gaussExp_e = 2*(e1+e2+timeResolution_e+PI_E);
   1078 
   1079   FDK_ASSERT( winSize < (1<<COEFF_LOOP_SCALE) );
   1080 
   1081   /* calc. window coefficients
   1082    *   win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) );
   1083    */
   1084   for( i=0; i<winSize; i++) {
   1085 
   1086     win[i] = fPow(
   1087             EULER_M,
   1088             EULER_E,
   1089             fMult(gaussExp_m, fPow2((i*FL2FXCONST_DBL(1.f/(float)(1<<COEFF_LOOP_SCALE)) + FL2FXCONST_DBL(.5f/(float)(1<<COEFF_LOOP_SCALE))))),
   1090             gaussExp_e + 2*COEFF_LOOP_SCALE,
   1091            &e1);
   1092 
   1093     win[i] = scaleValueSaturate(win[i], e1);
   1094   }
   1095 }
   1096 
   1097 
   1098 /***************************************************************************/
   1099 /*!
   1100   \brief     FDKaacEnc_AutoToParcor
   1101 
   1102   conversion autocorrelation to reflection coefficients
   1103 
   1104   \param pointer to input (acf)
   1105   \param pointer to output (reflection coefficients)
   1106   \param number of coefficients
   1107 
   1108   \return prediction gain
   1109 ****************************************************************************/
   1110 static INT FDKaacEnc_AutoToParcor(
   1111         FIXP_DBL *RESTRICT input,
   1112         FIXP_DBL *RESTRICT reflCoeff,
   1113         const INT numOfCoeff
   1114         )
   1115 {
   1116   INT       i, j, scale=0;
   1117   FIXP_DBL  tmp, parcorWorkBuffer[TNS_MAX_ORDER];
   1118   INT       predictionGain = (INT)(TNS_PREDGAIN_SCALE);
   1119 
   1120   FIXP_DBL *RESTRICT workBuffer = parcorWorkBuffer;
   1121   const FIXP_DBL  autoCorr_0 = input[0];
   1122 
   1123   FDKmemclear(reflCoeff,numOfCoeff*sizeof(FIXP_DBL));
   1124 
   1125   if((FIXP_DBL)input[0] == FL2FXCONST_DBL(0.0)) {
   1126     return(predictionGain);
   1127   }
   1128 
   1129   FDKmemcpy(workBuffer,&input[1],numOfCoeff*sizeof(FIXP_DBL));
   1130   for(i=0; i<numOfCoeff; i++) {
   1131     LONG sign = ((LONG)workBuffer[0] >> (DFRACT_BITS-1));
   1132     tmp = (FIXP_DBL)((LONG)workBuffer[0]^sign);
   1133 
   1134     if(input[0]<tmp)
   1135       break;
   1136 
   1137     tmp = (FIXP_DBL)((LONG)schur_div(tmp, input[0], FRACT_BITS)^(~sign));
   1138     reflCoeff[i] = tmp;
   1139 
   1140     for(j=numOfCoeff-i-1; j>=0; j--) {
   1141       FIXP_DBL accu1 = fMult(tmp, input[j]);
   1142       FIXP_DBL accu2 = fMult(tmp, workBuffer[j]);
   1143       workBuffer[j] += accu1;
   1144       input[j] += accu2;
   1145     }
   1146 
   1147     workBuffer++;
   1148   }
   1149 
   1150   tmp = fMult((FIXP_DBL)((LONG)TNS_PREDGAIN_SCALE<<21), fDivNorm(fAbs(autoCorr_0), fAbs(input[0]), &scale));
   1151   if ( fMultDiv2(autoCorr_0, input[0])<FL2FXCONST_DBL(0.0f) ) {
   1152     tmp = -tmp;
   1153   }
   1154   predictionGain = (LONG)scaleValue(tmp,scale-21);
   1155 
   1156   return (predictionGain);
   1157 }
   1158 
   1159 
   1160 static INT FDKaacEnc_Search3(FIXP_DBL parcor)
   1161 {
   1162   INT i, index=0;
   1163 
   1164   for(i=0;i<8;i++){
   1165     if(parcor > FDKaacEnc_tnsCoeff3Borders[i])
   1166       index=i;
   1167   }
   1168   return(index-4);
   1169 }
   1170 
   1171 static INT FDKaacEnc_Search4(FIXP_DBL parcor)
   1172 {
   1173   INT i, index=0;
   1174 
   1175   for(i=0;i<16;i++){
   1176     if(parcor > FDKaacEnc_tnsCoeff4Borders[i])
   1177       index=i;
   1178   }
   1179   return(index-8);
   1180 }
   1181 
   1182 
   1183 /*****************************************************************************
   1184 
   1185     functionname: FDKaacEnc_Parcor2Index
   1186 
   1187 *****************************************************************************/
   1188 static void FDKaacEnc_Parcor2Index(
   1189         const FIXP_DBL *parcor,
   1190         INT *RESTRICT index,
   1191         const INT order,
   1192         const INT bitsPerCoeff
   1193         )
   1194 {
   1195   INT i;
   1196   for(i=0; i<order; i++) {
   1197     if(bitsPerCoeff == 3)
   1198       index[i] = FDKaacEnc_Search3(parcor[i]);
   1199     else
   1200       index[i] = FDKaacEnc_Search4(parcor[i]);
   1201   }
   1202 }
   1203 
   1204 
   1205 /*****************************************************************************
   1206 
   1207     functionname: FDKaacEnc_Index2Parcor
   1208     description:  inverse quantization for reflection coefficients
   1209     returns:      -
   1210     input:        quantized values, ptr. to reflection coefficients,
   1211                   no. of coefficients, resolution
   1212     output:       reflection coefficients
   1213 
   1214 *****************************************************************************/
   1215 static void FDKaacEnc_Index2Parcor(
   1216         const INT *index,
   1217         FIXP_DBL *RESTRICT parcor,
   1218         const INT order,
   1219         const INT bitsPerCoeff
   1220         )
   1221 {
   1222   INT i;
   1223   for(i=0; i<order; i++)
   1224     parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i]+8] : FDKaacEnc_tnsEncCoeff3[index[i]+4];
   1225 }
   1226 
   1227 
   1228 /*****************************************************************************
   1229 
   1230     functionname: FDKaacEnc_ParcorToLpc
   1231     description:  conversion reflection coefficients to LPC coefficients
   1232     returns:      Gain factor
   1233     input:        reflection coefficients, no. of reflection coefficients <order>,
   1234                   ptr. to work buffer (required size: order)
   1235     output:       <order> LPC coefficients
   1236 
   1237 *****************************************************************************/
   1238 static INT FDKaacEnc_ParcorToLpc(
   1239         const FIXP_DBL *reflCoeff,
   1240         FIXP_DBL *RESTRICT LpcCoeff,
   1241         const INT numOfCoeff,
   1242         FIXP_DBL *RESTRICT workBuffer
   1243         )
   1244 {
   1245   INT i, j;
   1246   INT shiftval, par2LpcShiftVal = 6;  /* 6 should be enough, bec. max(numOfCoeff) = 20 */
   1247   FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f);
   1248 
   1249   LpcCoeff[0] = reflCoeff[0] >> par2LpcShiftVal;
   1250   for(i=1; i<numOfCoeff; i++) {
   1251     for(j=0; j<i; j++) {
   1252         workBuffer[j] = LpcCoeff[i-1-j];
   1253     }
   1254 
   1255     for(j=0; j<i; j++) {
   1256         LpcCoeff[j] += fMult(reflCoeff[i],workBuffer[j]);
   1257     }
   1258 
   1259     LpcCoeff[i] = reflCoeff[i] >> par2LpcShiftVal;
   1260   }
   1261 
   1262   /* normalize LpcCoeff and calc shiftfactor */
   1263   for(i=0; i<numOfCoeff; i++) {
   1264       maxVal = fixMax(maxVal,(FIXP_DBL)fixp_abs(LpcCoeff[i]));
   1265   }
   1266 
   1267   shiftval = CountLeadingBits(maxVal);
   1268   shiftval = (shiftval>=par2LpcShiftVal) ? par2LpcShiftVal : shiftval;
   1269 
   1270   for(i=0; i<numOfCoeff; i++)
   1271       LpcCoeff[i] = LpcCoeff[i]<<shiftval;
   1272 
   1273   return (par2LpcShiftVal - shiftval);
   1274 }
   1275 
   1276 /***************************************************************************/
   1277 /*!
   1278   \brief     FDKaacEnc_AnalysisFilter
   1279 
   1280   TNS analysis filter (all-zero filter)
   1281 
   1282   \param pointer to signal spectrum
   1283   \param number of lines
   1284   \param pointer to lpc coefficients
   1285   \param filter order
   1286   \param lpc gain factor
   1287 
   1288   \return void
   1289 ****************************************************************************/
   1290 /* Note: in-place computation possible */
   1291 static void FDKaacEnc_AnalysisFilter(
   1292         FIXP_DBL *RESTRICT signal,
   1293         const INT numOfLines,
   1294         const FIXP_DBL *predictorCoeff,
   1295         const INT order,
   1296         const INT lpcGainFactor
   1297         )
   1298 {
   1299   FIXP_DBL statusVar[TNS_MAX_ORDER];
   1300   INT i, j;
   1301   const INT shift = lpcGainFactor + 1;      /* +1, because fMultDiv2 */
   1302   FIXP_DBL tmp;
   1303 
   1304   if (order>0) {
   1305 
   1306     INT idx = 0;
   1307 
   1308     /* keep filter coefficients twice and save memory copy operation in
   1309        modulo state buffer */
   1310 #if defined(ARCH_PREFER_MULT_32x16)
   1311     FIXP_SGL  coeff[2*TNS_MAX_ORDER];
   1312     const FIXP_SGL *pCoeff;
   1313     for(i=0;i<order;i++) {
   1314       coeff[i]       = FX_DBL2FX_SGL(predictorCoeff[i]);
   1315     }
   1316     FDKmemcpy(&coeff[order], coeff, order*sizeof(FIXP_SGL));
   1317 #else
   1318     FIXP_DBL  coeff[2*TNS_MAX_ORDER];
   1319     const FIXP_DBL *pCoeff;
   1320     FDKmemcpy(&coeff[0],     predictorCoeff, order*sizeof(FIXP_DBL));
   1321     FDKmemcpy(&coeff[order], predictorCoeff, order*sizeof(FIXP_DBL));
   1322 #endif
   1323     FDKmemclear(statusVar, order*sizeof(FIXP_DBL));
   1324 
   1325     for(j=0; j<numOfLines; j++) {
   1326       pCoeff = &coeff[(order-idx)];
   1327       tmp = FL2FXCONST_DBL(0);
   1328       for(i=0; i<order; i++) {
   1329           tmp = fMultAddDiv2(tmp, pCoeff[i], statusVar[i]) ;
   1330       }
   1331 
   1332       if(--idx<0) { idx = order-1; }
   1333       statusVar[idx] = signal[j];
   1334 
   1335       FDK_ASSERT(lpcGainFactor>=0);
   1336       signal[j] = (tmp<<shift) + signal[j];
   1337     }
   1338   }
   1339 }
   1340 
   1341 
   1342