1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5© Copyright  1995 - 2012 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
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
98enum {
99    HIFILT = 0, /* index of higher filter */
100    LOFILT = 1 /* index of lower filter */
101};
102
103
104#define FILTER_DIRECTION 0
105
106static 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
111static const FIXP_DBL acfWindowShort[4+3+1] = {
112  0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000
113};
114
115
116typedef 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
129typedef 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
139static 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
167typedef struct {
168  INT   samplingRate;
169  SCHAR maxBands[2]; /* long=0; short=1 */
170
171} TNS_MAX_TAB_ENTRY;
172
173static 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
189static 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
198static 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
207static INT FDKaacEnc_AutoToParcor(
208        FIXP_DBL *RESTRICT input,
209        FIXP_DBL *RESTRICT reflCoeff,
210        const INT numOfCoeff
211        );
212
213static void FDKaacEnc_Parcor2Index(
214        const FIXP_DBL *parcor,
215        INT *RESTRICT index,
216        const INT order,
217        const INT bitsPerCoeff
218        );
219
220static void FDKaacEnc_Index2Parcor(
221        const INT *index,
222        FIXP_DBL *RESTRICT parcor,
223        const INT order,
224        const INT bitsPerCoeff
225        );
226
227static INT FDKaacEnc_ParcorToLpc(
228        const FIXP_DBL *reflCoeff,
229        FIXP_DBL *RESTRICT LpcCoeff,
230        const INT numOfCoeff,
231        FIXP_DBL *RESTRICT workBuffer
232        );
233
234static 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
242static 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
251static 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
272static 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
327INT 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*****************************************************************************/
372AAC_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****************************************************************************/
506static 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****************************************************************************/
544static 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****************************************************************************/
580static 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
617static 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*****************************************************************************/
745INT 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****************************************************************************/
912void 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****************************************************************************/
1004INT 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
1061static 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_SCALE         (2)
1071  #define PI_FIX           FL2FXCONST_DBL(3.1416f/(float)(1<<PI_SCALE))
1072
1073  #define EULER_SCALE      (2)
1074  #define EULER_FIX        FL2FXCONST_DBL(2.7183/(float)(1<<EULER_SCALE))
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_FIX, 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_SCALE);
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_FIX,
1099            EULER_SCALE,
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] = scaleValue(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****************************************************************************/
1121static 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(autoCorr_0, input[0], &scale));
1161  predictionGain = (LONG)scaleValue(tmp,scale-21);
1162
1163  return (predictionGain);
1164}
1165
1166
1167static INT FDKaacEnc_Search3(FIXP_DBL parcor)
1168{
1169  INT i, index=0;
1170
1171  for(i=0;i<8;i++){
1172    if(parcor > FDKaacEnc_tnsCoeff3Borders[i])
1173      index=i;
1174  }
1175  return(index-4);
1176}
1177
1178static INT FDKaacEnc_Search4(FIXP_DBL parcor)
1179{
1180  INT i, index=0;
1181
1182  for(i=0;i<16;i++){
1183    if(parcor > FDKaacEnc_tnsCoeff4Borders[i])
1184      index=i;
1185  }
1186  return(index-8);
1187}
1188
1189
1190/*****************************************************************************
1191
1192    functionname: FDKaacEnc_Parcor2Index
1193
1194*****************************************************************************/
1195static void FDKaacEnc_Parcor2Index(
1196        const FIXP_DBL *parcor,
1197        INT *RESTRICT index,
1198        const INT order,
1199        const INT bitsPerCoeff
1200        )
1201{
1202  INT i;
1203  for(i=0; i<order; i++) {
1204    if(bitsPerCoeff == 3)
1205      index[i] = FDKaacEnc_Search3(parcor[i]);
1206    else
1207      index[i] = FDKaacEnc_Search4(parcor[i]);
1208  }
1209}
1210
1211
1212/*****************************************************************************
1213
1214    functionname: FDKaacEnc_Index2Parcor
1215    description:  inverse quantization for reflection coefficients
1216    returns:      -
1217    input:        quantized values, ptr. to reflection coefficients,
1218                  no. of coefficients, resolution
1219    output:       reflection coefficients
1220
1221*****************************************************************************/
1222static void FDKaacEnc_Index2Parcor(
1223        const INT *index,
1224        FIXP_DBL *RESTRICT parcor,
1225        const INT order,
1226        const INT bitsPerCoeff
1227        )
1228{
1229  INT i;
1230  for(i=0; i<order; i++)
1231    parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i]+8] : FDKaacEnc_tnsEncCoeff3[index[i]+4];
1232}
1233
1234
1235/*****************************************************************************
1236
1237    functionname: FDKaacEnc_ParcorToLpc
1238    description:  conversion reflection coefficients to LPC coefficients
1239    returns:      Gain factor
1240    input:        reflection coefficients, no. of reflection coefficients <order>,
1241                  ptr. to work buffer (required size: order)
1242    output:       <order> LPC coefficients
1243
1244*****************************************************************************/
1245static INT FDKaacEnc_ParcorToLpc(
1246        const FIXP_DBL *reflCoeff,
1247        FIXP_DBL *RESTRICT LpcCoeff,
1248        const INT numOfCoeff,
1249        FIXP_DBL *RESTRICT workBuffer
1250        )
1251{
1252  INT i, j;
1253  INT shiftval, par2LpcShiftVal = 6;  /* 6 should be enough, bec. max(numOfCoeff) = 20 */
1254  FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f);
1255
1256  LpcCoeff[0] = reflCoeff[0] >> par2LpcShiftVal;
1257  for(i=1; i<numOfCoeff; i++) {
1258    for(j=0; j<i; j++) {
1259        workBuffer[j] = LpcCoeff[i-1-j];
1260    }
1261
1262    for(j=0; j<i; j++) {
1263        LpcCoeff[j] += fMult(reflCoeff[i],workBuffer[j]);
1264    }
1265
1266    LpcCoeff[i] = reflCoeff[i] >> par2LpcShiftVal;
1267  }
1268
1269  /* normalize LpcCoeff and calc shiftfactor */
1270  for(i=0; i<numOfCoeff; i++) {
1271      maxVal = fixMax(maxVal,(FIXP_DBL)fixp_abs(LpcCoeff[i]));
1272  }
1273
1274  shiftval = CountLeadingBits(maxVal);
1275  shiftval = (shiftval>=par2LpcShiftVal) ? par2LpcShiftVal : shiftval;
1276
1277  for(i=0; i<numOfCoeff; i++)
1278      LpcCoeff[i] = LpcCoeff[i]<<shiftval;
1279
1280  return (par2LpcShiftVal - shiftval);
1281}
1282
1283/***************************************************************************/
1284/*!
1285  \brief     FDKaacEnc_AnalysisFilter
1286
1287  TNS analysis filter (all-zero filter)
1288
1289  \param pointer to signal spectrum
1290  \param number of lines
1291  \param pointer to lpc coefficients
1292  \param filter order
1293  \param lpc gain factor
1294
1295  \return void
1296****************************************************************************/
1297/* Note: in-place computation possible */
1298static void FDKaacEnc_AnalysisFilter(
1299        FIXP_DBL *RESTRICT signal,
1300        const INT numOfLines,
1301        const FIXP_DBL *predictorCoeff,
1302        const INT order,
1303        const INT lpcGainFactor
1304        )
1305{
1306  FIXP_DBL statusVar[TNS_MAX_ORDER];
1307  INT i, j;
1308  const INT shift = lpcGainFactor + 1;      /* +1, because fMultDiv2 */
1309  FIXP_DBL tmp;
1310
1311  if (order>0) {
1312
1313    INT idx = 0;
1314
1315    /* keep filter coefficients twice and save memory copy operation in
1316       modulo state buffer */
1317#if defined(ARCH_PREFER_MULT_32x16)
1318    FIXP_SGL  coeff[2*TNS_MAX_ORDER];
1319    const FIXP_SGL *pCoeff;
1320    for(i=0;i<order;i++) {
1321      coeff[i]       = FX_DBL2FX_SGL(predictorCoeff[i]);
1322    }
1323    FDKmemcpy(&coeff[order], coeff, order*sizeof(FIXP_SGL));
1324#else
1325    FIXP_DBL  coeff[2*TNS_MAX_ORDER];
1326    const FIXP_DBL *pCoeff;
1327    FDKmemcpy(&coeff[0],     predictorCoeff, order*sizeof(FIXP_DBL));
1328    FDKmemcpy(&coeff[order], predictorCoeff, order*sizeof(FIXP_DBL));
1329#endif
1330    FDKmemclear(statusVar, order*sizeof(FIXP_DBL));
1331
1332    for(j=0; j<numOfLines; j++) {
1333      pCoeff = &coeff[(order-idx)];
1334      tmp = FL2FXCONST_DBL(0);
1335      for(i=0; i<order; i++) {
1336          tmp = fMultAddDiv2(tmp, pCoeff[i], statusVar[i]) ;
1337      }
1338
1339      if(--idx<0) { idx = order-1; }
1340      statusVar[idx] = signal[j];
1341
1342      FDK_ASSERT(lpcGainFactor>=0);
1343      signal[j] = (tmp<<shift) + signal[j];
1344    }
1345  }
1346}
1347
1348
1349