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