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