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