2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
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.
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.
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.
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.
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:
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.
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.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
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.
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."
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.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
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.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
84 /******************************** MPEG Audio Encoder **************************
86 Initial author: Alex Groeschel, Tobias Chalupka
87 contents/description: Temporal noise shaping
89 ******************************************************************************/
91 #include "aacenc_tns.h"
92 #include "psy_const.h"
93 #include "psy_configuration.h"
95 #include "aacEnc_rom.h"
96 #include "aacenc_tns.h"
99 HIFILT
= 0, /* index of higher filter */
100 LOFILT
= 1 /* index of lower filter */
104 #define FILTER_DIRECTION 0
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
111 static const FIXP_DBL acfWindowShort
[4+3+1] = {
112 0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000
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
;
126 } TNS_PARAMETER_TABULATED
;
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 */
136 #define TNS_TIMERES_SCALE (1)
137 #define FL2_TIMERES_FIX(a) ( FL2FXCONST_DBL(a/(float)(1<<TNS_TIMERES_SCALE)) )
139 static const TNS_INFO_TAB tnsInfoTab
[] =
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 }
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 }
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 }
169 SCHAR maxBands
[2]; /* long=0; short=1 */
173 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024
[] =
189 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480
[] =
198 static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512
[] =
207 static INT
FDKaacEnc_AutoToParcor(
208 FIXP_DBL
*RESTRICT input
,
209 FIXP_DBL
*RESTRICT reflCoeff
,
213 static void FDKaacEnc_Parcor2Index(
214 const FIXP_DBL
*parcor
,
217 const INT bitsPerCoeff
220 static void FDKaacEnc_Index2Parcor(
222 FIXP_DBL
*RESTRICT parcor
,
224 const INT bitsPerCoeff
227 static INT
FDKaacEnc_ParcorToLpc(
228 const FIXP_DBL
*reflCoeff
,
229 FIXP_DBL
*RESTRICT LpcCoeff
,
230 const INT numOfCoeff
,
231 FIXP_DBL
*RESTRICT workBuffer
234 static void FDKaacEnc_AnalysisFilter(
235 FIXP_DBL
*RESTRICT signal
,
236 const INT numOfLines
,
237 const FIXP_DBL
*predictorCoeff
,
239 const INT lpcGainFactor
242 static void FDKaacEnc_CalcGaussWindow(
245 const INT samplingRate
,
246 const INT transformResolution
,
247 const FIXP_DBL timeResolution
,
248 const INT timeResolution_e
251 static const TNS_PARAMETER_TABULATED
* FDKaacEnc_GetTnsParam(
258 const TNS_PARAMETER_TABULATED
*tnsConfigTab
= NULL
;
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])
264 tnsConfigTab
= &tnsInfoTab
[i
].paramTab
[(channels
==1)?0:1];
272 static INT
getTnsMaxBands(
273 const INT sampleRate
,
274 const INT granuleLength
,
275 const INT isShortBlock
280 const TNS_MAX_TAB_ENTRY
*pMaxBandsTab
= NULL
;
281 int maxBandsTabSize
= 0;
283 switch (granuleLength
) {
285 pMaxBandsTab
= tnsMaxBandsTab1024
;
286 maxBandsTabSize
= sizeof(tnsMaxBandsTab1024
)/sizeof(TNS_MAX_TAB_ENTRY
);
289 pMaxBandsTab
= tnsMaxBandsTab480
;
290 maxBandsTabSize
= sizeof(tnsMaxBandsTab480
)/sizeof(TNS_MAX_TAB_ENTRY
);
293 pMaxBandsTab
= tnsMaxBandsTab512
;
294 maxBandsTabSize
= sizeof(tnsMaxBandsTab512
)/sizeof(TNS_MAX_TAB_ENTRY
);
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
) {
312 /***************************************************************************/
314 \brief FDKaacEnc_FreqToBandWithRounding
316 Returns index of nearest band border
319 \param sampling frequency
320 \param total number of bands
321 \param pointer to table of band borders
324 ****************************************************************************/
326 INT
FDKaacEnc_FreqToBandWithRounding(
329 const INT numOfBands
,
330 const INT
*bandStartOffset
333 INT lineNumber
, band
;
335 /* assert(freq >= 0); */
336 lineNumber
= (freq
*bandStartOffset
[numOfBands
]*4/fs
+1)/2;
339 if (lineNumber
>= bandStartOffset
[numOfBands
])
342 /* find band the line number lies in */
343 for (band
=0; band
<numOfBands
; band
++) {
344 if (bandStartOffset
[band
+1]>lineNumber
) break;
347 /* round to nearest band border */
348 if (lineNumber
- bandStartOffset
[band
] >
349 bandStartOffset
[band
+1] - lineNumber
)
358 /*****************************************************************************
360 functionname: FDKaacEnc_InitTnsConfiguration
361 description: fill TNS_CONFIG structure with sensible content
363 input: bitrate, samplerate, number of channels,
364 blocktype (long or short),
365 TNS Config struct (modified),
370 *****************************************************************************/
371 AAC_ENCODER_ERROR
FDKaacEnc_InitTnsConfiguration(INT bitRate
,
378 PSY_CONFIGURATION
*pC
,
383 //float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f;
386 return (AAC_ENCODER_ERROR
)1;
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 */
393 tC
->coefRes
= (blockType
== SHORT_WINDOW
) ? 3 : 4;
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);
398 if (tC
->lpcStopBand
< 0) {
399 return (AAC_ENCODER_ERROR
)1;
402 tC
->lpcStopBand
= FDKmin(tC
->lpcStopBand
, pC
->sfbActive
);
403 tC
->lpcStopLine
= pC
->sfbOffset
[tC
->lpcStopBand
];
405 switch (granuleLength
) {
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
]];
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
];
416 tC
->confTab
.threshOn
[HIFILT
] = 1437;
417 tC
->confTab
.threshOn
[LOFILT
] = 1500;
419 tC
->confTab
.tnsLimitOrder
[HIFILT
] = tC
->maxOrder
;
420 tC
->confTab
.tnsLimitOrder
[LOFILT
] = tC
->maxOrder
- 7;
422 tC
->confTab
.tnsFilterDirection
[HIFILT
] = FILTER_DIRECTION
;
423 tC
->confTab
.tnsFilterDirection
[LOFILT
] = FILTER_DIRECTION
;
425 tC
->confTab
.acfSplit
[HIFILT
] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation*/
426 tC
->confTab
.acfSplit
[LOFILT
] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation */
428 tC
->confTab
.filterEnabled
[HIFILT
] = 1;
429 tC
->confTab
.filterEnabled
[LOFILT
] = 1;
430 tC
->confTab
.seperateFiltersAllowed
= 1;
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);
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
])));
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
])));
450 const TNS_PARAMETER_TABULATED
* pCfg
= FDKaacEnc_GetTnsParam(bitRate
, channels
, ldSbrPresent
);
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
]];
458 tC
->confTab
.threshOn
[HIFILT
] = pCfg
->threshOn
[HIFILT
];
459 tC
->confTab
.threshOn
[LOFILT
] = pCfg
->threshOn
[LOFILT
];
461 tC
->confTab
.tnsLimitOrder
[HIFILT
] = pCfg
->tnsLimitOrder
[HIFILT
];
462 tC
->confTab
.tnsLimitOrder
[LOFILT
] = pCfg
->tnsLimitOrder
[LOFILT
];
464 tC
->confTab
.tnsFilterDirection
[HIFILT
] = pCfg
->tnsFilterDirection
[HIFILT
];
465 tC
->confTab
.tnsFilterDirection
[LOFILT
] = pCfg
->tnsFilterDirection
[LOFILT
];
467 tC
->confTab
.acfSplit
[HIFILT
] = pCfg
->acfSplit
[HIFILT
];
468 tC
->confTab
.acfSplit
[LOFILT
] = pCfg
->acfSplit
[LOFILT
];
470 tC
->confTab
.filterEnabled
[HIFILT
] = pCfg
->filterEnabled
[HIFILT
];
471 tC
->confTab
.filterEnabled
[LOFILT
] = pCfg
->filterEnabled
[LOFILT
];
472 tC
->confTab
.seperateFiltersAllowed
= pCfg
->seperateFiltersAllowed
;
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
);
478 tC
->tnsActive
= FALSE
; /* no configuration available, disable tns tool */
483 tC
->tnsActive
= FALSE
; /* no configuration available, disable tns tool */
490 /***************************************************************************/
492 \brief FDKaacEnc_ScaleUpSpectrum
494 Scales up spectrum lines in a given frequency section
496 \param scaled spectrum
497 \param original spectrum
498 \param frequency line to start scaling
499 \param frequency line to enc scaling
503 ****************************************************************************/
504 static inline INT
FDKaacEnc_ScaleUpSpectrum(
513 FIXP_DBL maxVal
= FL2FXCONST_DBL(0.f
);
515 /* Get highest value in given spectrum */
516 for (i
=startLine
; i
<stopLine
; i
++) {
517 maxVal
= fixMax(maxVal
,fixp_abs(src
[i
]));
519 scale
= CountLeadingBits(maxVal
);
521 /* Scale spectrum according to highest value */
522 for (i
=startLine
; i
<stopLine
; i
++) {
523 dest
[i
] = src
[i
]<<scale
;
529 /***************************************************************************/
531 \brief FDKaacEnc_CalcAutoCorrValue
533 Calculate autocorellation value for one lag
535 \param pointer to spectrum
538 \param lag to be calculated
539 \param scaling of the lag
541 ****************************************************************************/
542 static inline FIXP_DBL
FDKaacEnc_CalcAutoCorrValue(
543 const FIXP_DBL
*spectrum
,
551 FIXP_DBL result
= FL2FXCONST_DBL(0.f
);
554 for (i
=startLine
; i
<stopLine
; i
++) {
555 result
+= (fPow2(spectrum
[i
])>>scale
);
559 for (i
=startLine
; i
<(stopLine
-lag
); i
++) {
560 result
+= (fMult(spectrum
[i
], spectrum
[i
+lag
])>>scale
);
567 /***************************************************************************/
569 \brief FDKaacEnc_AutoCorrNormFac
571 Autocorrelation function for 1st and 2nd half of the spectrum
573 \param pointer to spectrum
574 \param pointer to autocorrelation window
575 \param filter start line
577 ****************************************************************************/
578 static inline FIXP_DBL
FDKaacEnc_AutoCorrNormFac(
579 const FIXP_DBL value
,
584 #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */
585 #define MAX_INV_NRGFAC (1.f/HLM_MIN_NRG)
592 B
= FL2FXCONST_DBL(HLM_MIN_NRG
)>>fixMin(DFRACT_BITS
-1,scale
);
595 A
= value
>>fixMin(DFRACT_BITS
-1,(-scale
));
596 B
= FL2FXCONST_DBL(HLM_MIN_NRG
);
601 FIXP_DBL tmp
= invSqrtNorm2(value
,&shift
);
603 retValue
= fMult(tmp
,tmp
);
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
;
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
,
621 const INT acfSplit
[MAX_NUM_OF_FILTERS
],
626 int i
, idx0
, idx1
, idx2
, idx3
, idx4
, lag
;
627 FIXP_DBL rxx1_0
, rxx2_0
, rxx3_0
, rxx4_0
;
629 /* buffer for temporal spectrum */
630 C_ALLOC_SCRATCH_START(pSpectrum
, FIXP_DBL
, (1024));
632 /* pre-initialization output */
633 FDKmemclear(&_rxx1
[0], sizeof(FIXP_DBL
)*(maxOrder
+1));
634 FDKmemclear(&_rxx2
[0], sizeof(FIXP_DBL
)*(maxOrder
+1));
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
];
643 idx3
= idx0
+ i
* 3 / 4;
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
];
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
);
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
++);
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
);
676 /* compute energy normalization factors, i. e. 1/energy (saves some divisions) */
677 if (rxx1_0
!= FL2FXCONST_DBL(0.f
))
680 FIXP_DBL fac1
= FDKaacEnc_AutoCorrNormFac(rxx1_0
, ((-2*sc1
)+nsc1
), &sc_fac1
);
681 _rxx1
[0] = scaleValue(fMult(rxx1_0
,fac1
),sc_fac1
);
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
]);
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
))) )
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;
700 if (rxx2_0
!=FL2FXCONST_DBL(0.f
)) {
701 fac2
= FDKaacEnc_AutoCorrNormFac(rxx2_0
, ((-2*sc2
)+nsc2
), &sc_fac2
);
704 if (rxx3_0
!=FL2FXCONST_DBL(0.f
)) {
705 fac3
= FDKaacEnc_AutoCorrNormFac(rxx3_0
, ((-2*sc3
)+nsc3
), &sc_fac3
);
708 if (rxx4_0
!=FL2FXCONST_DBL(0.f
)) {
709 fac4
= FDKaacEnc_AutoCorrNormFac(rxx4_0
, ((-2*sc4
)+nsc4
), &sc_fac4
);
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
);
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
);
723 _rxx2
[lag
] = fMult(x2
, acfWindow
[HIFILT
][lag
]);
727 C_ALLOC_SCRATCH_END(pSpectrum
, FIXP_DBL
, (1024));
731 /*****************************************************************************
732 functionname: FDKaacEnc_TnsDetect
733 description: do decision, if TNS shall be used or not
735 input: tns data structure (modified),
736 tns config structure,
737 scalefactor size and table,
739 subblock num, blocktype,
742 *****************************************************************************/
743 INT
FDKaacEnc_TnsDetect(
745 const TNS_CONFIG
*tC
,
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
];
760 TNS_SUBBLOCK_INFO
*tsbi
= (blockType
== SHORT_WINDOW
)
761 ? &tnsData
->dataRaw
.Short
.subBlockInfo
[subBlockNumber
]
762 : &tnsData
->dataRaw
.Long
.subBlockInfo
;
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;
773 tnsInfo
->length
[subBlockNumber
][HIFILT
] = tnsInfo
->length
[subBlockNumber
][LOFILT
] = 0;
774 tnsInfo
->order
[subBlockNumber
][HIFILT
] = tnsInfo
->order
[subBlockNumber
][LOFILT
] = 0;
776 if ( (tC
->tnsActive
) && (tC
->maxOrder
>0) )
780 FDKaacEnc_MergedAutoCorrelation(
786 tC
->confTab
.acfSplit
,
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
]);
793 /* non-linear quantization of TNS lattice coefficients with given resolution */
794 FDKaacEnc_Parcor2Index(
796 tnsInfo
->coef
[subBlockNumber
][HIFILT
],
797 tC
->confTab
.tnsLimitOrder
[HIFILT
],
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) {
807 tnsInfo
->order
[subBlockNumber
][HIFILT
] = i
+ 1;
810 for (; i
>= 0; i
--) {
811 sumSqrCoef
+= tnsInfo
->coef
[subBlockNumber
][HIFILT
][i
] * tnsInfo
->coef
[subBlockNumber
][HIFILT
][i
];
814 tnsInfo
->direction
[subBlockNumber
][HIFILT
] = tC
->confTab
.tnsFilterDirection
[HIFILT
];
815 tnsInfo
->length
[subBlockNumber
][HIFILT
] = sfbCnt
- tC
->lpcStartBand
[HIFILT
];
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)))
820 tsbi
->tnsActive
= TRUE
;
821 tnsInfo
->numOfFilters
[subBlockNumber
]++;
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
) )
827 /* compute second filter for lower frequencies */
829 /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
830 INT predGain
= FDKaacEnc_AutoToParcor(rxx1
, parcor_tmp
, tC
->confTab
.tnsLimitOrder
[LOFILT
]);
832 /* non-linear quantization of TNS lattice coefficients with given resolution */
833 FDKaacEnc_Parcor2Index(
835 tnsInfo
->coef
[subBlockNumber
][LOFILT
],
836 tC
->confTab
.tnsLimitOrder
[LOFILT
],
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) {
845 tnsInfo
->order
[subBlockNumber
][LOFILT
] = i
+ 1;
848 for (; i
>= 0; i
--) {
849 sumSqrCoef
+= tnsInfo
->coef
[subBlockNumber
][LOFILT
][i
] * tnsInfo
->coef
[subBlockNumber
][LOFILT
][i
];
852 tnsInfo
->direction
[subBlockNumber
][LOFILT
] = tC
->confTab
.tnsFilterDirection
[LOFILT
];
853 tnsInfo
->length
[subBlockNumber
][LOFILT
] = tC
->lpcStartBand
[HIFILT
] - tC
->lpcStartBand
[LOFILT
];
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
]) ) )
859 /* compare lower to upper filter; if they are very similar, merge them */
861 for (i
= 0; i
< tC
->confTab
.tnsLimitOrder
[LOFILT
]; i
++) {
862 sumSqrCoef
+= FDKabs(tnsInfo
->coef
[subBlockNumber
][HIFILT
][i
] - tnsInfo
->coef
[subBlockNumber
][LOFILT
][i
]);
864 if ( (sumSqrCoef
< 2) &&
865 (tnsInfo
->direction
[subBlockNumber
][LOFILT
] == tnsInfo
->direction
[subBlockNumber
][HIFILT
]) )
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) {
874 for (i
--; i
>= 0; i
--) {
875 if (tnsInfo
->coef
[subBlockNumber
][HIFILT
][i
] != 0) {
879 if (i
< tnsInfo
->order
[subBlockNumber
][HIFILT
]) {
880 tnsInfo
->order
[subBlockNumber
][HIFILT
] = i
+ 1;
884 tnsInfo
->numOfFilters
[subBlockNumber
]++;
886 } /* filter lower part */
887 } /* second filter allowed */
888 } /* if predictionGain > 1437 ... */
889 } /* maxOrder > 0 && tnsActive */
896 /***************************************************************************/
898 \brief FDKaacLdEnc_TnsSync
900 synchronize TNS parameters when TNS gain difference small (relative)
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
909 ****************************************************************************/
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
,
920 int i
, w
, absDiff
, nWindows
;
921 TNS_SUBBLOCK_INFO
*sbInfoDest
;
922 const TNS_SUBBLOCK_INFO
*sbInfoSrc
;
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
) )
931 if (blockTypeDest
!= SHORT_WINDOW
) {
932 sbInfoDest
= &tnsDataDest
->dataRaw
.Long
.subBlockInfo
;
933 sbInfoSrc
= &tnsDataSrc
->dataRaw
.Long
.subBlockInfo
;
936 sbInfoDest
= &tnsDataDest
->dataRaw
.Short
.subBlockInfo
[0];
937 sbInfoSrc
= &tnsDataSrc
->dataRaw
.Short
.subBlockInfo
[0];
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;
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)) {
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
])))
965 pSbInfoDestW
->tnsActive
= tnsInfoDest
->numOfFilters
[w
] = 1;
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
];
973 for (i
= 0; i
< tC
->maxOrder
; i
++) {
974 tnsInfoDest
->coef
[w
][HIFILT
][i
] = tnsInfoSrc
->coef
[w
][HIFILT
][i
];
978 pSbInfoDestW
->tnsActive
= tnsInfoDest
->numOfFilters
[w
] = 0;
985 /***************************************************************************/
987 \brief FDKaacEnc_TnsEncode
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
996 \param pointer to spectrum
997 \param number of sub-block
1000 \return ERROR STATUS
1001 ****************************************************************************/
1002 INT
FDKaacEnc_TnsEncode(
1006 const TNS_CONFIG
*tC
,
1007 const INT lowPassLine
,
1009 const INT subBlockNumber
,
1013 INT i
, startLine
, stopLine
;
1015 if ( ( (blockType
== SHORT_WINDOW
) && (!tnsData
->dataRaw
.Short
.subBlockInfo
[subBlockNumber
].tnsActive
) )
1016 || ( (blockType
!= SHORT_WINDOW
) && (!tnsData
->dataRaw
.Long
.subBlockInfo
.tnsActive
) ) )
1021 startLine
= (tnsData
->filtersMerged
) ? tC
->lpcStartLine
[LOFILT
] : tC
->lpcStartLine
[HIFILT
];
1022 stopLine
= tC
->lpcStopLine
;
1024 for (i
=0; i
<tnsInfo
->numOfFilters
[subBlockNumber
]; i
++) {
1027 FIXP_DBL LpcCoeff
[TNS_MAX_ORDER
];
1028 FIXP_DBL workBuffer
[TNS_MAX_ORDER
];
1029 FIXP_DBL parcor_tmp
[TNS_MAX_ORDER
];
1031 FDKaacEnc_Index2Parcor(
1032 tnsInfo
->coef
[subBlockNumber
][i
],
1034 tnsInfo
->order
[subBlockNumber
][i
],
1037 lpcGainFactor
= FDKaacEnc_ParcorToLpc(
1040 tnsInfo
->order
[subBlockNumber
][i
],
1043 FDKaacEnc_AnalysisFilter(
1044 &spectrum
[startLine
],
1045 stopLine
- startLine
,
1047 tnsInfo
->order
[subBlockNumber
][i
],
1050 /* update for second filter */
1051 startLine
= tC
->lpcStartLine
[LOFILT
];
1052 stopLine
= tC
->lpcStartLine
[HIFILT
];
1059 static void FDKaacEnc_CalcGaussWindow(
1062 const INT samplingRate
,
1063 const INT transformResolution
,
1064 const FIXP_DBL timeResolution
,
1065 const INT timeResolution_e
1069 #define PI_M FL2FXCONST_DBL(3.1416f/(float)(1<<PI_E))
1072 #define EULER_M FL2FXCONST_DBL(2.7183/(float)(1<<EULER_E))
1074 #define COEFF_LOOP_SCALE (4)
1076 INT i
, e1
, e2
, gaussExp_e
;
1077 FIXP_DBL gaussExp_m
;
1079 /* calc. window exponent from time resolution:
1081 * gaussExp = PI * samplingRate * 0.001f * timeResolution / transformResolution;
1082 * gaussExp = -0.5f * gaussExp * gaussExp;
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
);
1088 FDK_ASSERT( winSize
< (1<<COEFF_LOOP_SCALE
) );
1090 /* calc. window coefficients
1091 * win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) );
1093 for( i
=0; i
<winSize
; i
++) {
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
,
1102 win
[i
] = scaleValueSaturate(win
[i
], e1
);
1107 /***************************************************************************/
1109 \brief FDKaacEnc_AutoToParcor
1111 conversion autocorrelation to reflection coefficients
1113 \param pointer to input (acf)
1114 \param pointer to output (reflection coefficients)
1115 \param number of coefficients
1117 \return prediction gain
1118 ****************************************************************************/
1119 static INT
FDKaacEnc_AutoToParcor(
1120 FIXP_DBL
*RESTRICT input
,
1121 FIXP_DBL
*RESTRICT reflCoeff
,
1122 const INT numOfCoeff
1126 FIXP_DBL tmp
, parcorWorkBuffer
[TNS_MAX_ORDER
];
1127 INT predictionGain
= (INT
)(TNS_PREDGAIN_SCALE
);
1129 FIXP_DBL
*RESTRICT workBuffer
= parcorWorkBuffer
;
1130 const FIXP_DBL autoCorr_0
= input
[0];
1132 if((FIXP_DBL
)input
[0] == FL2FXCONST_DBL(0.0)) {
1133 FDKmemclear(reflCoeff
,numOfCoeff
*sizeof(FIXP_DBL
));
1134 return(predictionGain
);
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
);
1145 tmp
= (FIXP_DBL
)((LONG
)schur_div(tmp
, input
[0], FRACT_BITS
)^(~sign
));
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
;
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
) ) {
1162 predictionGain
= (LONG
)scaleValue(tmp
,scale
-21);
1164 return (predictionGain
);
1168 static INT
FDKaacEnc_Search3(FIXP_DBL parcor
)
1173 if(parcor
> FDKaacEnc_tnsCoeff3Borders
[i
])
1179 static INT
FDKaacEnc_Search4(FIXP_DBL parcor
)
1184 if(parcor
> FDKaacEnc_tnsCoeff4Borders
[i
])
1191 /*****************************************************************************
1193 functionname: FDKaacEnc_Parcor2Index
1195 *****************************************************************************/
1196 static void FDKaacEnc_Parcor2Index(
1197 const FIXP_DBL
*parcor
,
1198 INT
*RESTRICT index
,
1200 const INT bitsPerCoeff
1204 for(i
=0; i
<order
; i
++) {
1205 if(bitsPerCoeff
== 3)
1206 index
[i
] = FDKaacEnc_Search3(parcor
[i
]);
1208 index
[i
] = FDKaacEnc_Search4(parcor
[i
]);
1213 /*****************************************************************************
1215 functionname: FDKaacEnc_Index2Parcor
1216 description: inverse quantization for reflection coefficients
1218 input: quantized values, ptr. to reflection coefficients,
1219 no. of coefficients, resolution
1220 output: reflection coefficients
1222 *****************************************************************************/
1223 static void FDKaacEnc_Index2Parcor(
1225 FIXP_DBL
*RESTRICT parcor
,
1227 const INT bitsPerCoeff
1231 for(i
=0; i
<order
; i
++)
1232 parcor
[i
] = bitsPerCoeff
== 4 ? FDKaacEnc_tnsEncCoeff4
[index
[i
]+8] : FDKaacEnc_tnsEncCoeff3
[index
[i
]+4];
1236 /*****************************************************************************
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
1245 *****************************************************************************/
1246 static INT
FDKaacEnc_ParcorToLpc(
1247 const FIXP_DBL
*reflCoeff
,
1248 FIXP_DBL
*RESTRICT LpcCoeff
,
1249 const INT numOfCoeff
,
1250 FIXP_DBL
*RESTRICT workBuffer
1254 INT shiftval
, par2LpcShiftVal
= 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */
1255 FIXP_DBL maxVal
= FL2FXCONST_DBL(0.0f
);
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
];
1263 for(j
=0; j
<i
; j
++) {
1264 LpcCoeff
[j
] += fMult(reflCoeff
[i
],workBuffer
[j
]);
1267 LpcCoeff
[i
] = reflCoeff
[i
] >> par2LpcShiftVal
;
1270 /* normalize LpcCoeff and calc shiftfactor */
1271 for(i
=0; i
<numOfCoeff
; i
++) {
1272 maxVal
= fixMax(maxVal
,(FIXP_DBL
)fixp_abs(LpcCoeff
[i
]));
1275 shiftval
= CountLeadingBits(maxVal
);
1276 shiftval
= (shiftval
>=par2LpcShiftVal
) ? par2LpcShiftVal
: shiftval
;
1278 for(i
=0; i
<numOfCoeff
; i
++)
1279 LpcCoeff
[i
] = LpcCoeff
[i
]<<shiftval
;
1281 return (par2LpcShiftVal
- shiftval
);
1284 /***************************************************************************/
1286 \brief FDKaacEnc_AnalysisFilter
1288 TNS analysis filter (all-zero filter)
1290 \param pointer to signal spectrum
1291 \param number of lines
1292 \param pointer to lpc coefficients
1294 \param lpc gain factor
1297 ****************************************************************************/
1298 /* Note: in-place computation possible */
1299 static void FDKaacEnc_AnalysisFilter(
1300 FIXP_DBL
*RESTRICT signal
,
1301 const INT numOfLines
,
1302 const FIXP_DBL
*predictorCoeff
,
1304 const INT lpcGainFactor
1307 FIXP_DBL statusVar
[TNS_MAX_ORDER
];
1309 const INT shift
= lpcGainFactor
+ 1; /* +1, because fMultDiv2 */
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
]);
1324 FDKmemcpy(&coeff
[order
], coeff
, order
*sizeof(FIXP_SGL
));
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
));
1331 FDKmemclear(statusVar
, order
*sizeof(FIXP_DBL
));
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
]) ;
1340 if(--idx
<0) { idx
= order
-1; }
1341 statusVar
[idx
] = signal
[j
];
1343 FDK_ASSERT(lpcGainFactor
>=0);
1344 signal
[j
] = (tmp
<<shift
) + signal
[j
];