Imported Debian version 0.1.3.1
[deb_fdk-aac.git] / libAACenc / src / aacenc_tns.cpp
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
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
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
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 *****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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
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 *****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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
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 ****************************************************************************/
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
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
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 *****************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 */
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