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