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