/src/fdk-aac/libAACenc/src/psy_configuration.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): M.Werner |
98 | | |
99 | | Description: Psychoaccoustic configuration |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "psy_configuration.h" |
104 | | #include "adj_thr.h" |
105 | | #include "aacEnc_rom.h" |
106 | | |
107 | | #include "genericStds.h" |
108 | | |
109 | | #include "FDK_trigFcts.h" |
110 | | |
111 | | typedef struct { |
112 | | LONG sampleRate; |
113 | | const SFB_PARAM_LONG *paramLong; |
114 | | const SFB_PARAM_SHORT *paramShort; |
115 | | } SFB_INFO_TAB; |
116 | | |
117 | | static const SFB_INFO_TAB sfbInfoTab[] = { |
118 | | {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128}, |
119 | | {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128}, |
120 | | {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128}, |
121 | | {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128}, |
122 | | {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128}, |
123 | | {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128}, |
124 | | {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128}, |
125 | | {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128}, |
126 | | {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128}, |
127 | | {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128}, |
128 | | {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128}, |
129 | | {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128} |
130 | | |
131 | | }; |
132 | | |
133 | | /* 22050 and 24000 Hz */ |
134 | | static const SFB_PARAM_LONG p_22050_long_512 = { |
135 | | 31, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, |
136 | | 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; |
137 | | |
138 | | /* 32000 Hz */ |
139 | | static const SFB_PARAM_LONG p_32000_long_512 = { |
140 | | 37, |
141 | | {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, |
142 | | 12, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 32, 32, 32, 32, 32, 32, 32}}; |
143 | | |
144 | | /* 44100 Hz */ |
145 | | static const SFB_PARAM_LONG p_44100_long_512 = { |
146 | | 36, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, |
147 | | 8, 8, 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 52}}; |
148 | | |
149 | | static const SFB_INFO_TAB sfbInfoTabLD512[] = { |
150 | | {8000, &p_22050_long_512, NULL}, {11025, &p_22050_long_512, NULL}, |
151 | | {12000, &p_22050_long_512, NULL}, {16000, &p_22050_long_512, NULL}, |
152 | | {22050, &p_22050_long_512, NULL}, {24000, &p_22050_long_512, NULL}, |
153 | | {32000, &p_32000_long_512, NULL}, {44100, &p_44100_long_512, NULL}, |
154 | | {48000, &p_44100_long_512, NULL}, {64000, &p_44100_long_512, NULL}, |
155 | | {88200, &p_44100_long_512, NULL}, {96000, &p_44100_long_512, NULL}, |
156 | | {128000, &p_44100_long_512, NULL}, {176400, &p_44100_long_512, NULL}, |
157 | | {192000, &p_44100_long_512, NULL}, {256000, &p_44100_long_512, NULL}, |
158 | | {352800, &p_44100_long_512, NULL}, {384000, &p_44100_long_512, NULL}, |
159 | | }; |
160 | | |
161 | | /* 22050 and 24000 Hz */ |
162 | | static const SFB_PARAM_LONG p_22050_long_480 = { |
163 | | 30, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, |
164 | | 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; |
165 | | |
166 | | /* 32000 Hz */ |
167 | | static const SFB_PARAM_LONG p_32000_long_480 = { |
168 | | 37, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, |
169 | | 8, 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, 32, 32, 32, 32, 32, 32, 32}}; |
170 | | |
171 | | /* 44100 Hz */ |
172 | | static const SFB_PARAM_LONG p_44100_long_480 = { |
173 | | 35, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, |
174 | | 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, 32, 32, 32, 32, 48}}; |
175 | | |
176 | | static const SFB_INFO_TAB sfbInfoTabLD480[] = { |
177 | | {8000, &p_22050_long_480, NULL}, {11025, &p_22050_long_480, NULL}, |
178 | | {12000, &p_22050_long_480, NULL}, {16000, &p_22050_long_480, NULL}, |
179 | | {22050, &p_22050_long_480, NULL}, {24000, &p_22050_long_480, NULL}, |
180 | | {32000, &p_32000_long_480, NULL}, {44100, &p_44100_long_480, NULL}, |
181 | | {48000, &p_44100_long_480, NULL}, {64000, &p_44100_long_480, NULL}, |
182 | | {88200, &p_44100_long_480, NULL}, {96000, &p_44100_long_480, NULL}, |
183 | | {128000, &p_44100_long_480, NULL}, {176400, &p_44100_long_480, NULL}, |
184 | | {192000, &p_44100_long_480, NULL}, {256000, &p_44100_long_480, NULL}, |
185 | | {352800, &p_44100_long_480, NULL}, {384000, &p_44100_long_480, NULL}, |
186 | | }; |
187 | | |
188 | | /* Fixed point precision definitions */ |
189 | | #define Q_BARCVAL (25) |
190 | | |
191 | | AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate, |
192 | | const INT blockType, |
193 | | const INT granuleLength, |
194 | | INT *const sfbOffset, |
195 | 0 | INT *const sfbCnt) { |
196 | 0 | INT i, specStartOffset = 0; |
197 | 0 | INT granuleLengthWindow = granuleLength; |
198 | 0 | const UCHAR *sfbWidth = NULL; |
199 | 0 | const SFB_INFO_TAB *sfbInfo = NULL; |
200 | 0 | int size; |
201 | | |
202 | | /* |
203 | | select table |
204 | | */ |
205 | 0 | switch (granuleLength) { |
206 | 0 | case 1024: |
207 | 0 | case 960: |
208 | 0 | sfbInfo = sfbInfoTab; |
209 | 0 | size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB)); |
210 | 0 | break; |
211 | 0 | case 512: |
212 | 0 | sfbInfo = sfbInfoTabLD512; |
213 | 0 | size = sizeof(sfbInfoTabLD512); |
214 | 0 | break; |
215 | 0 | case 480: |
216 | 0 | sfbInfo = sfbInfoTabLD480; |
217 | 0 | size = sizeof(sfbInfoTabLD480); |
218 | 0 | break; |
219 | 0 | default: |
220 | 0 | return AAC_ENC_INVALID_FRAME_LENGTH; |
221 | 0 | } |
222 | | |
223 | 0 | for (i = 0; i < size; i++) { |
224 | 0 | if (sfbInfo[i].sampleRate == sampleRate) { |
225 | 0 | switch (blockType) { |
226 | 0 | case LONG_WINDOW: |
227 | 0 | case START_WINDOW: |
228 | 0 | case STOP_WINDOW: |
229 | 0 | sfbWidth = sfbInfo[i].paramLong->sfbWidth; |
230 | 0 | *sfbCnt = sfbInfo[i].paramLong->sfbCnt; |
231 | 0 | break; |
232 | 0 | case SHORT_WINDOW: |
233 | 0 | sfbWidth = sfbInfo[i].paramShort->sfbWidth; |
234 | 0 | *sfbCnt = sfbInfo[i].paramShort->sfbCnt; |
235 | 0 | granuleLengthWindow /= TRANS_FAC; |
236 | 0 | break; |
237 | 0 | } |
238 | 0 | break; |
239 | 0 | } |
240 | 0 | } |
241 | 0 | if (i == size) { |
242 | 0 | return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; |
243 | 0 | } |
244 | | |
245 | | /* |
246 | | calc sfb offsets |
247 | | */ |
248 | 0 | for (i = 0; i < *sfbCnt; i++) { |
249 | 0 | sfbOffset[i] = specStartOffset; |
250 | 0 | specStartOffset += sfbWidth[i]; |
251 | 0 | if (specStartOffset >= granuleLengthWindow) { |
252 | 0 | i++; |
253 | 0 | break; |
254 | 0 | } |
255 | 0 | } |
256 | 0 | *sfbCnt = fixMin(i, *sfbCnt); |
257 | 0 | sfbOffset[*sfbCnt] = fixMin(specStartOffset, granuleLengthWindow); |
258 | 0 | return AAC_ENC_OK; |
259 | 0 | } |
260 | | |
261 | | /***************************************************************************** |
262 | | |
263 | | functionname: FDKaacEnc_BarcLineValue |
264 | | description: Calculates barc value for one frequency line |
265 | | returns: barc value of line |
266 | | input: number of lines in transform, index of line to check, Fs |
267 | | output: |
268 | | |
269 | | *****************************************************************************/ |
270 | | static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine, |
271 | 0 | LONG samplingFreq) { |
272 | 0 | FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */ |
273 | 0 | FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a; /* 0.00076 in q41 */ |
274 | 0 | FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333; /* 13.3 in q26 */ |
275 | 0 | FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000; /* 3.5 in q27 */ |
276 | 0 | FIXP_DBL INV480 = (FIXP_DBL)0x44444444; // 1/480 in q39 |
277 | |
|
278 | 0 | FIXP_DBL center_freq, x1, x2; |
279 | 0 | FIXP_DBL bvalFFTLine, atan1, atan2; |
280 | | |
281 | | /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000 |
282 | | */ |
283 | | /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in |
284 | | * q28 */ |
285 | | /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in |
286 | | * q25 */ |
287 | |
|
288 | 0 | center_freq = fftLine * samplingFreq; /* q11 or q8 */ |
289 | |
|
290 | 0 | switch (noOfLines) { |
291 | 0 | case 1024: |
292 | 0 | center_freq = center_freq << 2; /* q13 */ |
293 | 0 | break; |
294 | 0 | case 128: |
295 | 0 | center_freq = center_freq << 5; /* q13 */ |
296 | 0 | break; |
297 | 0 | case 512: |
298 | 0 | center_freq = (fftLine * samplingFreq) << 3; // q13 |
299 | 0 | break; |
300 | 0 | case 480: |
301 | 0 | center_freq = fMult(center_freq, INV480) << 4; // q13 |
302 | 0 | break; |
303 | 0 | default: |
304 | 0 | center_freq = (FIXP_DBL)0; |
305 | 0 | } |
306 | | |
307 | 0 | x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */ |
308 | 0 | x2 = fMult(center_freq, PZZZ76) |
309 | 0 | << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */ |
310 | |
|
311 | 0 | atan1 = fixp_atan(x1); |
312 | 0 | atan2 = fixp_atan(x2); |
313 | | |
314 | | /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */ |
315 | 0 | bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1)); |
316 | 0 | return (bvalFFTLine); |
317 | 0 | } |
318 | | |
319 | | /* |
320 | | do not consider energies below a certain input signal level, |
321 | | i.e. of -96dB or 1 bit at 16 bit PCM resolution, |
322 | | might need to be configurable to e.g. 24 bit PCM Input or a lower |
323 | | resolution for low bit rates |
324 | | */ |
325 | | static void FDKaacEnc_InitMinPCMResolution(int numPb, int *pbOffset, |
326 | 0 | FIXP_DBL *sfbPCMquantThreshold) { |
327 | | /* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY * |
328 | | * FDKpow(2,PCM_QUANT_THR_SCALE) */ |
329 | 0 | #define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062) |
330 | |
|
331 | 0 | for (int i = 0; i < numPb; i++) { |
332 | 0 | sfbPCMquantThreshold[i] = (pbOffset[i + 1] - pbOffset[i]) * PCM_QUANT_NOISE; |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | | static FIXP_DBL getMaskFactor(const FIXP_DBL dbVal_fix, const INT dbVal_e, |
337 | 0 | const FIXP_DBL ten_fix, const INT ten_e) { |
338 | 0 | INT q_msk; |
339 | 0 | FIXP_DBL mask_factor; |
340 | |
|
341 | 0 | mask_factor = fPow(ten_fix, DFRACT_BITS - 1 - ten_e, -dbVal_fix, |
342 | 0 | DFRACT_BITS - 1 - dbVal_e, &q_msk); |
343 | 0 | q_msk = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), q_msk)); |
344 | |
|
345 | 0 | if ((q_msk > 0) && (mask_factor > (FIXP_DBL)MAXVAL_DBL >> q_msk)) { |
346 | 0 | mask_factor = (FIXP_DBL)MAXVAL_DBL; |
347 | 0 | } else { |
348 | 0 | mask_factor = scaleValue(mask_factor, q_msk); |
349 | 0 | } |
350 | |
|
351 | 0 | return (mask_factor); |
352 | 0 | } |
353 | | |
354 | | static void FDKaacEnc_initSpreading(INT numPb, FIXP_DBL *pbBarcValue, |
355 | | FIXP_DBL *pbMaskLoFactor, |
356 | | FIXP_DBL *pbMaskHiFactor, |
357 | | FIXP_DBL *pbMaskLoFactorSprEn, |
358 | | FIXP_DBL *pbMaskHiFactorSprEn, |
359 | | const LONG bitrate, const INT blockType) |
360 | | |
361 | 0 | { |
362 | 0 | INT i; |
363 | 0 | FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN; |
364 | |
|
365 | 0 | FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ |
366 | 0 | FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ |
367 | 0 | FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ |
368 | 0 | FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ |
369 | 0 | FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ |
370 | 0 | FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ |
371 | 0 | FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ |
372 | 0 | FIXP_DBL TEN = (FIXP_DBL)0x50000000; /* 10.0 in q27 */ |
373 | |
|
374 | 0 | if (blockType != SHORT_WINDOW) { |
375 | 0 | MASKLOWSPREN = MASKLOWSPRENLONG; |
376 | 0 | MASKHIGHSPREN = |
377 | 0 | (bitrate > 20000) ? MASKHIGHSPRENLONG : MASKHIGHSPRENLONGLOWBR; |
378 | 0 | } else { |
379 | 0 | MASKLOWSPREN = MASKLOWSPRENSHORT; |
380 | 0 | MASKHIGHSPREN = MASKHIGHSPRENSHORT; |
381 | 0 | } |
382 | |
|
383 | 0 | for (i = 0; i < numPb; i++) { |
384 | 0 | if (i > 0) { |
385 | 0 | pbMaskHiFactor[i] = getMaskFactor( |
386 | 0 | fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); |
387 | |
|
388 | 0 | pbMaskLoFactor[i - 1] = getMaskFactor( |
389 | 0 | fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); |
390 | |
|
391 | 0 | pbMaskHiFactorSprEn[i] = getMaskFactor( |
392 | 0 | fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, |
393 | 0 | 27); |
394 | |
|
395 | 0 | pbMaskLoFactorSprEn[i - 1] = getMaskFactor( |
396 | 0 | fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, |
397 | 0 | 27); |
398 | 0 | } else { |
399 | 0 | pbMaskHiFactor[i] = (FIXP_DBL)0; |
400 | 0 | pbMaskLoFactor[numPb - 1] = (FIXP_DBL)0; |
401 | 0 | pbMaskHiFactorSprEn[i] = (FIXP_DBL)0; |
402 | 0 | pbMaskLoFactorSprEn[numPb - 1] = (FIXP_DBL)0; |
403 | 0 | } |
404 | 0 | } |
405 | 0 | } |
406 | | |
407 | | static void FDKaacEnc_initBarcValues(INT numPb, INT *pbOffset, INT numLines, |
408 | 0 | INT samplingFrequency, FIXP_DBL *pbBval) { |
409 | 0 | INT i; |
410 | 0 | FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ |
411 | |
|
412 | 0 | for (i = 0; i < numPb; i++) { |
413 | 0 | FIXP_DBL v1, v2, cur_bark; |
414 | 0 | v1 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i], samplingFrequency); |
415 | 0 | v2 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i + 1], samplingFrequency); |
416 | 0 | cur_bark = (v1 >> 1) + (v2 >> 1); |
417 | 0 | pbBval[i] = fixMin(cur_bark, MAX_BARC); |
418 | 0 | } |
419 | 0 | } |
420 | | |
421 | | static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate, |
422 | | const INT numLines, const INT *sfbOffset, |
423 | | const INT sfbActive, const INT blockType, |
424 | 0 | FIXP_DBL *sfbMinSnrLdData) { |
425 | 0 | INT sfb; |
426 | | |
427 | | /* Fix conversion variables */ |
428 | 0 | INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt; |
429 | 0 | INT qtmp, qsnr, sfbWidth; |
430 | |
|
431 | 0 | FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ |
432 | 0 | FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */ |
433 | 0 | FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */ |
434 | 0 | FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2; /* 0.024 in q36 */ |
435 | 0 | FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000; /* 1.5 in q30 */ |
436 | 0 | FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333; /* 0.8 in q30 */ |
437 | 0 | FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9; /* 0.003 in q30 */ |
438 | |
|
439 | 0 | FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth; |
440 | 0 | FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5; |
441 | | |
442 | | /* relative number of active barks */ |
443 | 0 | barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue( |
444 | 0 | numLines, sfbOffset[sfbActive], samplerate), |
445 | 0 | MAX_BARC), |
446 | 0 | MAX_BARCP1, &qbfac); |
447 | |
|
448 | 0 | qbfac = DFRACT_BITS - 1 - qbfac; |
449 | |
|
450 | 0 | pePerWindow = fDivNorm(bitrate, samplerate, &qperwin); |
451 | 0 | qperwin = DFRACT_BITS - 1 - qperwin; |
452 | 0 | pePerWindow = fMult(pePerWindow, BITS2PEFAC); |
453 | 0 | qperwin = qperwin + 30 - (DFRACT_BITS - 1); |
454 | 0 | pePerWindow = fMult(pePerWindow, PERS2P4); |
455 | 0 | qperwin = qperwin + 36 - (DFRACT_BITS - 1); |
456 | |
|
457 | 0 | switch (numLines) { |
458 | 0 | case 1024: |
459 | 0 | qperwin = qperwin - 10; |
460 | 0 | break; |
461 | 0 | case 128: |
462 | 0 | qperwin = qperwin - 7; |
463 | 0 | break; |
464 | 0 | case 512: |
465 | 0 | qperwin = qperwin - 9; |
466 | 0 | break; |
467 | 0 | case 480: |
468 | 0 | qperwin = qperwin - 9; |
469 | 0 | pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f)); |
470 | 0 | break; |
471 | 0 | } |
472 | | |
473 | | /* for short blocks it is assumed that more bits are available */ |
474 | 0 | if (blockType == SHORT_WINDOW) { |
475 | 0 | pePerWindow = fMult(pePerWindow, ONEP5); |
476 | 0 | qperwin = qperwin + 30 - (DFRACT_BITS - 1); |
477 | 0 | } |
478 | 0 | pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv); |
479 | 0 | qpeprt_const = qperwin - qbfac + DFRACT_BITS - 1 - qdiv; |
480 | |
|
481 | 0 | for (sfb = 0; sfb < sfbActive; sfb++) { |
482 | 0 | barcWidth = |
483 | 0 | FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb + 1], samplerate) - |
484 | 0 | FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate); |
485 | | |
486 | | /* adapt to sfb bands */ |
487 | 0 | pePart = fMult(pePart_const, barcWidth); |
488 | 0 | qpeprt = qpeprt_const + 25 - (DFRACT_BITS - 1); |
489 | | |
490 | | /* pe -> snr calculation */ |
491 | 0 | sfbWidth = (sfbOffset[sfb + 1] - sfbOffset[sfb]); |
492 | 0 | pePart = fDivNorm(pePart, sfbWidth, &qdiv); |
493 | 0 | qpeprt += DFRACT_BITS - 1 - qdiv; |
494 | |
|
495 | 0 | tmp = f2Pow(pePart, DFRACT_BITS - 1 - qpeprt, &qtmp); |
496 | 0 | qtmp = DFRACT_BITS - 1 - qtmp; |
497 | | |
498 | | /* Subtract 1.5 */ |
499 | 0 | qsnr = fixMin(qtmp, 30); |
500 | 0 | tmp = tmp >> (qtmp - qsnr); |
501 | |
|
502 | 0 | if ((30 + 1 - qsnr) > (DFRACT_BITS - 1)) |
503 | 0 | one_point5 = (FIXP_DBL)0; |
504 | 0 | else |
505 | 0 | one_point5 = (FIXP_DBL)(ONEP5 >> (30 + 1 - qsnr)); |
506 | |
|
507 | 0 | snr = (tmp >> 1) - (one_point5); |
508 | 0 | qsnr -= 1; |
509 | | |
510 | | /* max(snr, 1.0) */ |
511 | 0 | if (qsnr > 0) |
512 | 0 | one_qsnr = (FIXP_DBL)(1 << qsnr); |
513 | 0 | else |
514 | 0 | one_qsnr = (FIXP_DBL)0; |
515 | |
|
516 | 0 | snr = fixMax(one_qsnr, snr); |
517 | | |
518 | | /* 1/snr */ |
519 | 0 | snr = fDivNorm(one_qsnr, snr, &qsnr); |
520 | 0 | qsnr = DFRACT_BITS - 1 - qsnr; |
521 | 0 | snr = (qsnr > 30) ? (snr >> (qsnr - 30)) : snr; |
522 | | |
523 | | /* upper limit is -1 dB */ |
524 | 0 | snr = (snr > MAX_SNR) ? MAX_SNR : snr; |
525 | | |
526 | | /* lower limit is -25 dB */ |
527 | 0 | snr = (snr < MIN_SNR) ? MIN_SNR : snr; |
528 | 0 | snr = snr << 1; |
529 | |
|
530 | 0 | sfbMinSnrLdData[sfb] = CalcLdData(snr); |
531 | 0 | } |
532 | 0 | } |
533 | | |
534 | | AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate, |
535 | | INT bandwidth, INT blocktype, |
536 | | INT granuleLength, INT useIS, |
537 | | INT useMS, |
538 | | PSY_CONFIGURATION *psyConf, |
539 | 0 | FB_TYPE filterbank) { |
540 | 0 | AAC_ENCODER_ERROR ErrorStatus; |
541 | 0 | INT sfb; |
542 | 0 | FIXP_DBL sfbBarcVal[MAX_SFB]; |
543 | 0 | const INT frameLengthLong = granuleLength; |
544 | 0 | const INT frameLengthShort = granuleLength / TRANS_FAC; |
545 | 0 | INT downscaleFactor = 1; |
546 | |
|
547 | 0 | switch (granuleLength) { |
548 | 0 | case 256: |
549 | 0 | case 240: |
550 | 0 | downscaleFactor = 2; |
551 | 0 | break; |
552 | 0 | case 128: |
553 | 0 | case 120: |
554 | 0 | downscaleFactor = 4; |
555 | 0 | break; |
556 | 0 | default: |
557 | 0 | downscaleFactor = 1; |
558 | 0 | break; |
559 | 0 | } |
560 | | |
561 | 0 | FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION)); |
562 | 0 | psyConf->granuleLength = granuleLength; |
563 | 0 | psyConf->filterbank = filterbank; |
564 | |
|
565 | 0 | psyConf->allowIS = (useIS) && ((bitrate / bandwidth) < 5); |
566 | 0 | psyConf->allowMS = useMS; |
567 | | |
568 | | /* init sfb table */ |
569 | 0 | ErrorStatus = FDKaacEnc_initSfbTable(samplerate * downscaleFactor, blocktype, |
570 | 0 | granuleLength * downscaleFactor, |
571 | 0 | psyConf->sfbOffset, &psyConf->sfbCnt); |
572 | |
|
573 | 0 | if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; |
574 | | |
575 | | /* calculate barc values for each pb */ |
576 | 0 | FDKaacEnc_initBarcValues(psyConf->sfbCnt, psyConf->sfbOffset, |
577 | 0 | psyConf->sfbOffset[psyConf->sfbCnt], samplerate, |
578 | 0 | sfbBarcVal); |
579 | |
|
580 | 0 | FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, psyConf->sfbOffset, |
581 | 0 | psyConf->sfbPcmQuantThreshold); |
582 | | |
583 | | /* calculate spreading function */ |
584 | 0 | FDKaacEnc_initSpreading(psyConf->sfbCnt, sfbBarcVal, |
585 | 0 | psyConf->sfbMaskLowFactor, psyConf->sfbMaskHighFactor, |
586 | 0 | psyConf->sfbMaskLowFactorSprEn, |
587 | 0 | psyConf->sfbMaskHighFactorSprEn, bitrate, blocktype); |
588 | | |
589 | | /* init ratio */ |
590 | |
|
591 | 0 | psyConf->maxAllowedIncreaseFactor = 2; /* integer */ |
592 | 0 | psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148; |
593 | | /* FL2FXCONST_SGL(0.01f); */ /* fract */ |
594 | |
|
595 | 0 | psyConf->clipEnergy = |
596 | 0 | (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */ |
597 | |
|
598 | 0 | if (blocktype != SHORT_WINDOW) { |
599 | 0 | psyConf->lowpassLine = |
600 | 0 | (INT)((2 * bandwidth * frameLengthLong) / samplerate); |
601 | 0 | psyConf->lowpassLineLFE = LFE_LOWPASS_LINE; |
602 | 0 | } else { |
603 | 0 | psyConf->lowpassLine = |
604 | 0 | (INT)((2 * bandwidth * frameLengthShort) / samplerate); |
605 | 0 | psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */ |
606 | | /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */ |
607 | 0 | psyConf->clipEnergy >>= 6; |
608 | 0 | } |
609 | |
|
610 | 0 | for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { |
611 | 0 | if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break; |
612 | 0 | } |
613 | 0 | psyConf->sfbActive = fMax(sfb, 1); |
614 | |
|
615 | 0 | for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { |
616 | 0 | if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break; |
617 | 0 | } |
618 | 0 | psyConf->sfbActiveLFE = sfb; |
619 | 0 | psyConf->sfbActive = fMax(psyConf->sfbActive, psyConf->sfbActiveLFE); |
620 | | |
621 | | /* calculate minSnr */ |
622 | 0 | FDKaacEnc_initMinSnr(bitrate, samplerate * downscaleFactor, |
623 | 0 | psyConf->sfbOffset[psyConf->sfbCnt], psyConf->sfbOffset, |
624 | 0 | psyConf->sfbActive, blocktype, psyConf->sfbMinSnrLdData); |
625 | |
|
626 | 0 | return AAC_ENC_OK; |
627 | 0 | } |