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