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