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