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