/src/aac/libSACenc/src/sacenc_paramextract.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 | | /*********************** MPEG surround encoder library ************************* |
96 | | |
97 | | Author(s): M. Multrus |
98 | | |
99 | | Description: Parameter Extraction |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /* Includes ******************************************************************/ |
104 | | #include "sacenc_paramextract.h" |
105 | | #include "sacenc_tree.h" |
106 | | #include "sacenc_vectorfunctions.h" |
107 | | |
108 | | /* Defines *******************************************************************/ |
109 | | #define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */ |
110 | | #define SCALE_CLDE_SF (7) /* maxVal in Quant tab is +/- 50 */ |
111 | | #define SCALE_CLDD_SF (8) /* maxVal in Quant tab is +/- 150 */ |
112 | | |
113 | | /* Data Types ****************************************************************/ |
114 | | typedef struct T_TTO_BOX { |
115 | | FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS]; |
116 | | FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS]; |
117 | | FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS]; |
118 | | |
119 | | const FIXP_DBL *pIccQuantTable__FDK; |
120 | | const FIXP_DBL *pCldQuantTableDec__FDK; |
121 | | const FIXP_DBL *pCldQuantTableEnc__FDK; |
122 | | |
123 | | SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS]; |
124 | | SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS]; |
125 | | |
126 | | UCHAR *pParameterBand2HybridBandOffset; |
127 | | const INT *pSubbandImagSign; |
128 | | UCHAR nHybridBandsMax; |
129 | | UCHAR nParameterBands; |
130 | | UCHAR bFrameKeep; |
131 | | |
132 | | UCHAR iccCorrelationCoherenceBorder; |
133 | | BOX_QUANTMODE boxQuantMode; |
134 | | |
135 | | UCHAR nIccQuantSteps; |
136 | | UCHAR nIccQuantOffset; |
137 | | |
138 | | UCHAR nCldQuantSteps; |
139 | | UCHAR nCldQuantOffset; |
140 | | |
141 | | UCHAR bUseCoarseQuantCld; |
142 | | UCHAR bUseCoarseQuantIcc; |
143 | | |
144 | | } TTO_BOX; |
145 | | |
146 | | struct BOX_SUBBAND_SETUP { |
147 | | BOX_SUBBAND_CONFIG subbandConfig; |
148 | | UCHAR nParameterBands; |
149 | | const UCHAR *pSubband2ParameterIndexLd; |
150 | | UCHAR iccCorrelationCoherenceBorder; |
151 | | }; |
152 | | |
153 | | /* Constants *****************************************************************/ |
154 | | static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = { |
155 | | 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
156 | | 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
157 | | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; |
158 | | |
159 | | static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = { |
160 | | 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
161 | | 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
162 | | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; |
163 | | |
164 | | static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = { |
165 | | 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, |
166 | | 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
167 | | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; |
168 | | |
169 | | static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = { |
170 | | 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, |
171 | | 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |
172 | | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; |
173 | | |
174 | | static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = { |
175 | | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, |
176 | | 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, |
177 | | 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, |
178 | | 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; |
179 | | |
180 | | static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = { |
181 | | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, |
182 | | 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, |
183 | | 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, |
184 | | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; |
185 | | |
186 | | static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = { |
187 | | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, |
188 | | 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, |
189 | | 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, |
190 | | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; |
191 | | |
192 | | static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = { |
193 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
194 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
195 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
196 | | }; |
197 | | |
198 | | #define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF))) |
199 | | static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = { |
200 | | SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0), |
201 | | SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0), |
202 | | SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0), |
203 | | SCALE_CLDE(-6.0), SCALE_CLDE(-4.0), SCALE_CLDE(-2.0), SCALE_CLDE(0.0), |
204 | | SCALE_CLDE(2.0), SCALE_CLDE(4.0), SCALE_CLDE(6.0), SCALE_CLDE(8.0), |
205 | | SCALE_CLDE(10.0), SCALE_CLDE(13.0), SCALE_CLDE(16.0), SCALE_CLDE(19.0), |
206 | | SCALE_CLDE(22.0), SCALE_CLDE(25.0), SCALE_CLDE(30.0), SCALE_CLDE(35.0), |
207 | | SCALE_CLDE(40.0), SCALE_CLDE(45.0), SCALE_CLDE(50.0)}; |
208 | | |
209 | | static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = { |
210 | | SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0), |
211 | | SCALE_CLDE(-13.0), SCALE_CLDE(-8.0), SCALE_CLDE(-4.0), SCALE_CLDE(0.0), |
212 | | SCALE_CLDE(4.0), SCALE_CLDE(8.0), SCALE_CLDE(13.0), SCALE_CLDE(19.0), |
213 | | SCALE_CLDE(25.0), SCALE_CLDE(35.0), SCALE_CLDE(50.0)}; |
214 | | |
215 | | #define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF))) |
216 | | static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = { |
217 | | SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0), |
218 | | SCALE_CLDD(-30.0), SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0), |
219 | | SCALE_CLDD(-16.0), SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0), |
220 | | SCALE_CLDD(-6.0), SCALE_CLDD(-4.0), SCALE_CLDD(-2.0), SCALE_CLDD(0.0), |
221 | | SCALE_CLDD(2.0), SCALE_CLDD(4.0), SCALE_CLDD(6.0), SCALE_CLDD(8.0), |
222 | | SCALE_CLDD(10.0), SCALE_CLDD(13.0), SCALE_CLDD(16.0), SCALE_CLDD(19.0), |
223 | | SCALE_CLDD(22.0), SCALE_CLDD(25.0), SCALE_CLDD(30.0), SCALE_CLDD(35.0), |
224 | | SCALE_CLDD(40.0), SCALE_CLDD(45.0), SCALE_CLDD(150.0)}; |
225 | | |
226 | | static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = { |
227 | | SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0), |
228 | | SCALE_CLDD(-13.0), SCALE_CLDD(-8.0), SCALE_CLDD(-4.0), SCALE_CLDD(0.0), |
229 | | SCALE_CLDD(4.0), SCALE_CLDD(8.0), SCALE_CLDD(13.0), SCALE_CLDD(19.0), |
230 | | SCALE_CLDD(25.0), SCALE_CLDD(35.0), SCALE_CLDD(150.0)}; |
231 | | |
232 | | #define SCALE_ICC(a) (FL2FXCONST_DBL(a)) |
233 | | static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = { |
234 | | SCALE_ICC(0.99999999953), SCALE_ICC(0.937f), SCALE_ICC(0.84118f), |
235 | | SCALE_ICC(0.60092f), SCALE_ICC(0.36764f), SCALE_ICC(0.0f), |
236 | | SCALE_ICC(-0.589f), SCALE_ICC(-0.99f)}; |
237 | | |
238 | | static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = { |
239 | | SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f), |
240 | | SCALE_ICC(-0.5890f)}; |
241 | | |
242 | | static const BOX_SUBBAND_SETUP boxSubbandSetup[] = { |
243 | | {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1}, |
244 | | {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2}, |
245 | | {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3}, |
246 | | {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4}, |
247 | | {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4}, |
248 | | {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5}, |
249 | | {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}}; |
250 | | |
251 | | /* Function / Class Declarations *********************************************/ |
252 | | |
253 | | /* Function / Class Definition ***********************************************/ |
254 | | static const BOX_SUBBAND_SETUP *getBoxSubbandSetup( |
255 | 0 | const BOX_SUBBAND_CONFIG subbandConfig) { |
256 | 0 | int i; |
257 | 0 | const BOX_SUBBAND_SETUP *setup = NULL; |
258 | |
|
259 | 0 | for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP)); |
260 | 0 | i++) { |
261 | 0 | if (boxSubbandSetup[i].subbandConfig == subbandConfig) { |
262 | 0 | setup = &boxSubbandSetup[i]; |
263 | 0 | break; |
264 | 0 | } |
265 | 0 | } |
266 | 0 | return setup; |
267 | 0 | } |
268 | | |
269 | | static inline void ApplyBBCuesFDK(FIXP_DBL *const pData, |
270 | 0 | const INT nParamBands) { |
271 | 0 | int i, s; |
272 | 0 | FIXP_DBL tmp, invParamBands; |
273 | |
|
274 | 0 | invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s); |
275 | 0 | s = -s; |
276 | |
|
277 | 0 | tmp = fMult(pData[0], invParamBands) >> s; |
278 | 0 | for (i = 1; i < nParamBands; i++) { |
279 | 0 | tmp += fMult(pData[i], invParamBands) >> s; |
280 | 0 | } |
281 | |
|
282 | 0 | for (i = 0; i < nParamBands; i++) { |
283 | 0 | pData[i] = tmp; |
284 | 0 | } |
285 | 0 | } |
286 | | |
287 | 0 | static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) { |
288 | 0 | const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); |
289 | 0 | return ((setup == NULL) ? 0 : setup->nParameterBands); |
290 | 0 | } |
291 | | |
292 | | static const UCHAR *getSubband2ParameterIndex( |
293 | 0 | const BOX_SUBBAND_CONFIG subbandConfig) { |
294 | 0 | const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); |
295 | |
|
296 | 0 | return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd)); |
297 | 0 | } |
298 | | |
299 | | void fdk_sacenc_calcParameterBand2HybridBandOffset( |
300 | | const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, |
301 | 0 | UCHAR *pParameterBand2HybridBandOffset) { |
302 | 0 | const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); |
303 | 0 | const UCHAR *pSubband2ParameterIndex; |
304 | |
|
305 | 0 | int i, pb; |
306 | |
|
307 | 0 | pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd; |
308 | |
|
309 | 0 | for (pb = 0, i = 0; i < nHybridBands - 1; i++) { |
310 | 0 | if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) { |
311 | 0 | pParameterBand2HybridBandOffset[pb++] = (i + 1); |
312 | 0 | } |
313 | 0 | } |
314 | 0 | pParameterBand2HybridBandOffset[pb++] = (i + 1); |
315 | 0 | } |
316 | | |
317 | 0 | const INT *fdk_sacenc_getSubbandImagSign() { |
318 | 0 | const INT *pImagSign = NULL; |
319 | |
|
320 | 0 | pImagSign = subbandImagSign_Ld; |
321 | |
|
322 | 0 | return (pImagSign); |
323 | 0 | } |
324 | | |
325 | | static INT getIccCorrelationCoherenceBorder( |
326 | 0 | const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) { |
327 | 0 | const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); |
328 | 0 | return ( |
329 | 0 | (setup == NULL) |
330 | 0 | ? 0 |
331 | 0 | : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder)); |
332 | 0 | } |
333 | | |
334 | 0 | FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) { |
335 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
336 | |
|
337 | 0 | if (NULL == hTtoBox) { |
338 | 0 | error = SACENC_INVALID_HANDLE; |
339 | 0 | } else { |
340 | 0 | FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX); |
341 | 0 | } |
342 | 0 | return error; |
343 | | |
344 | 0 | bail: |
345 | 0 | fdk_sacenc_destroyTtoBox(hTtoBox); |
346 | 0 | return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); |
347 | 0 | } |
348 | | |
349 | | FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, |
350 | | const TTO_BOX_CONFIG *const ttoBoxConfig, |
351 | 0 | UCHAR *pParameterBand2HybridBandOffset) { |
352 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
353 | |
|
354 | 0 | if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) || |
355 | 0 | (pParameterBand2HybridBandOffset == NULL)) { |
356 | 0 | error = SACENC_INVALID_HANDLE; |
357 | 0 | } else { |
358 | 0 | FDKmemclear(hTtoBox, sizeof(TTO_BOX)); |
359 | |
|
360 | 0 | hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld; |
361 | 0 | hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc; |
362 | 0 | hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode; |
363 | 0 | hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder( |
364 | 0 | ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly); |
365 | 0 | hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax; |
366 | 0 | hTtoBox->nParameterBands = |
367 | 0 | getNumberParameterBands(ttoBoxConfig->subbandConfig); |
368 | 0 | hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep; |
369 | |
|
370 | 0 | hTtoBox->nIccQuantSteps = |
371 | 0 | fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc); |
372 | 0 | hTtoBox->nIccQuantOffset = |
373 | 0 | fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc); |
374 | |
|
375 | 0 | hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc |
376 | 0 | ? iccQuantTableCoarse__FDK |
377 | 0 | : iccQuantTableFine__FDK; |
378 | 0 | hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld |
379 | 0 | ? cldQuantTableCoarseDec__FDK |
380 | 0 | : cldQuantTableFineDec__FDK; |
381 | 0 | hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld |
382 | 0 | ? cldQuantTableCoarseEnc__FDK |
383 | 0 | : cldQuantTableFineEnc__FDK; |
384 | |
|
385 | 0 | hTtoBox->nCldQuantSteps = |
386 | 0 | fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld); |
387 | 0 | hTtoBox->nCldQuantOffset = |
388 | 0 | fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld); |
389 | | |
390 | | /* sanity */ |
391 | 0 | if (NULL == (hTtoBox->pParameterBand2HybridBandOffset = |
392 | 0 | pParameterBand2HybridBandOffset)) { |
393 | 0 | error = SACENC_INIT_ERROR; |
394 | 0 | goto bail; |
395 | 0 | } |
396 | | |
397 | 0 | if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) { |
398 | 0 | error = SACENC_INIT_ERROR; |
399 | 0 | } |
400 | |
|
401 | 0 | if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) && |
402 | 0 | (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) && |
403 | 0 | (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) { |
404 | 0 | error = SACENC_INIT_ERROR; |
405 | 0 | goto bail; |
406 | 0 | } |
407 | 0 | } |
408 | 0 | bail: |
409 | 0 | return error; |
410 | 0 | } |
411 | | |
412 | 0 | FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) { |
413 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
414 | |
|
415 | 0 | if (*hTtoBox != NULL) { |
416 | 0 | FDKfree(*hTtoBox); |
417 | 0 | *hTtoBox = NULL; |
418 | 0 | } |
419 | |
|
420 | 0 | return error; |
421 | 0 | } |
422 | | |
423 | | static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand, |
424 | | const INT correlationCoherenceBorder, |
425 | | const FIXP_DBL *const pPwr1, |
426 | | const FIXP_DBL *const pPwr2, |
427 | | const FIXP_DBL *const pProdReal, |
428 | | FIXP_DBL const *const pProdImag, |
429 | 0 | FIXP_DBL *const pIcc) { |
430 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
431 | |
|
432 | 0 | if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) || |
433 | 0 | (pProdImag == NULL) || (pIcc == NULL)) { |
434 | 0 | error = SACENC_INVALID_HANDLE; |
435 | 0 | } else { |
436 | | /* sanity check border */ |
437 | 0 | if (correlationCoherenceBorder > nParamBand) { |
438 | 0 | error = SACENC_INVALID_CONFIG; |
439 | 0 | } else { |
440 | | /* correlation */ |
441 | 0 | FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2, |
442 | 0 | correlationCoherenceBorder); |
443 | | |
444 | | /* coherence */ |
445 | 0 | calcCoherenceVec(&pIcc[correlationCoherenceBorder], |
446 | 0 | &pProdReal[correlationCoherenceBorder], |
447 | 0 | &pProdImag[correlationCoherenceBorder], |
448 | 0 | &pPwr1[correlationCoherenceBorder], |
449 | 0 | &pPwr2[correlationCoherenceBorder], 0, 0, |
450 | 0 | nParamBand - correlationCoherenceBorder); |
451 | |
|
452 | 0 | } /* valid configuration */ |
453 | 0 | } /* valid handle */ |
454 | |
|
455 | 0 | return error; |
456 | 0 | } |
457 | | |
458 | | static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands, |
459 | | const FIXP_DBL *const quantTable, |
460 | | const INT idxOffset, const INT nQuantSteps, |
461 | 0 | SCHAR *const quantOut) { |
462 | 0 | int band; |
463 | 0 | const int reverse = (quantTable[0] > quantTable[1]); |
464 | |
|
465 | 0 | for (band = 0; band < nBands; band++) { |
466 | 0 | FIXP_DBL qVal; |
467 | 0 | FIXP_DBL curVal = input[band]; |
468 | |
|
469 | 0 | int lower = 0; |
470 | 0 | int upper = nQuantSteps - 1; |
471 | |
|
472 | 0 | if (reverse) { |
473 | 0 | while (upper - lower > 1) { |
474 | 0 | int idx = (lower + upper) >> 1; |
475 | 0 | qVal = quantTable[idx]; |
476 | 0 | if (curVal >= qVal) { |
477 | 0 | upper = idx; |
478 | 0 | } else { |
479 | 0 | lower = idx; |
480 | 0 | } |
481 | 0 | } /* while */ |
482 | |
|
483 | 0 | if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) { |
484 | 0 | quantOut[band] = lower - idxOffset; |
485 | 0 | } else { |
486 | 0 | quantOut[band] = upper - idxOffset; |
487 | 0 | } |
488 | 0 | } /* if reverse */ |
489 | 0 | else { |
490 | 0 | while (upper - lower > 1) { |
491 | 0 | int idx = (lower + upper) >> 1; |
492 | 0 | qVal = quantTable[idx]; |
493 | 0 | if (curVal <= qVal) { |
494 | 0 | upper = idx; |
495 | 0 | } else { |
496 | 0 | lower = idx; |
497 | 0 | } |
498 | 0 | } /* while */ |
499 | |
|
500 | 0 | if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) { |
501 | 0 | quantOut[band] = lower - idxOffset; |
502 | 0 | } else { |
503 | 0 | quantOut[band] = upper - idxOffset; |
504 | 0 | } |
505 | 0 | } /* else reverse */ |
506 | 0 | } /* for band */ |
507 | 0 | } |
508 | | |
509 | | static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands, |
510 | | const FIXP_DBL *const quantTable, |
511 | 0 | const INT idxOffset, FIXP_DBL *const dequantOut) { |
512 | 0 | int band; |
513 | |
|
514 | 0 | for (band = 0; band < nBands; band++) { |
515 | 0 | dequantOut[band] = quantTable[input[band] + idxOffset]; |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | | static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1, |
520 | | const FIXP_DBL *const pPwr2, const INT scaleCh1, |
521 | | const INT *const pbScaleCh1, const INT scaleCh2, |
522 | 0 | const INT *const pbScaleCh2, const int nParamBand) { |
523 | 0 | INT i; |
524 | 0 | FIXP_DBL ldPwr1, ldPwr2, cld; |
525 | 0 | FIXP_DBL maxPwr = FL2FXCONST_DBL( |
526 | 0 | 30.0f / |
527 | 0 | (1 << (LD_DATA_SHIFT + |
528 | 0 | 1))); /* consider SACENC_FLOAT_EPSILON in power calculation */ |
529 | |
|
530 | 0 | for (i = 0; i < nParamBand; i++) { |
531 | 0 | ldPwr1 = |
532 | 0 | (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i]) |
533 | 0 | << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); |
534 | 0 | ldPwr2 = |
535 | 0 | (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i]) |
536 | 0 | << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); |
537 | |
|
538 | 0 | ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr); |
539 | 0 | ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr); |
540 | | |
541 | | /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit |
542 | | * scale by fMultDiv2() */ |
543 | 0 | cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)), |
544 | 0 | ldPwr1 - ldPwr2); |
545 | |
|
546 | 0 | cld = |
547 | 0 | fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2))); |
548 | 0 | cld = |
549 | 0 | fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2))); |
550 | 0 | pCld[i] = cld << (LD_DATA_SHIFT + 2); |
551 | 0 | } |
552 | 0 | } |
553 | | |
554 | | FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( |
555 | | HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, |
556 | | const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, |
557 | | const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, |
558 | | UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, |
559 | | UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1, |
560 | 0 | INT *scaleCh2) { |
561 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
562 | |
|
563 | 0 | C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
564 | 0 | C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
565 | 0 | C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
566 | 0 | C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
567 | |
|
568 | 0 | C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
569 | 0 | C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
570 | 0 | C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) |
571 | 0 | C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) |
572 | |
|
573 | 0 | if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) || |
574 | 0 | (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) || |
575 | 0 | (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) { |
576 | 0 | error = SACENC_INVALID_HANDLE; |
577 | 0 | } else { |
578 | 0 | int j, pb; |
579 | 0 | const int nParamBands = hTtoBox->nParameterBands; |
580 | 0 | const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) || |
581 | 0 | (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2); |
582 | | |
583 | | /* sanity check */ |
584 | 0 | if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) { |
585 | 0 | error = SACENC_INVALID_CONFIG; |
586 | 0 | goto bail; |
587 | 0 | } |
588 | | |
589 | 0 | int outScale; /* scalefactor will not be evaluated */ |
590 | 0 | int inScale = 5; /* scale factor determined empirically */ |
591 | | |
592 | | /* calculate the headroom of the hybrid data for each parameter band */ |
593 | 0 | FDKcalcPbScaleFactor(ppHybridData1__FDK, |
594 | 0 | hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1, |
595 | 0 | startTimeSlot, nTimeSlots, nParamBands); |
596 | 0 | FDKcalcPbScaleFactor(ppHybridData2__FDK, |
597 | 0 | hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2, |
598 | 0 | startTimeSlot, nTimeSlots, nParamBands); |
599 | |
|
600 | 0 | for (j = 0, pb = 0; pb < nParamBands; pb++) { |
601 | 0 | FIXP_DBL data1, data2; |
602 | 0 | data1 = data2 = (FIXP_DBL)0; |
603 | 0 | for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { |
604 | 0 | data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE, |
605 | 0 | inScale + pbScaleCh1[pb], &outScale, |
606 | 0 | startTimeSlot, nTimeSlots, j, j + 1); |
607 | 0 | data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE, |
608 | 0 | inScale + pbScaleCh2[pb], &outScale, |
609 | 0 | startTimeSlot, nTimeSlots, j, j + 1); |
610 | 0 | } /* for j */ |
611 | 0 | powerHybridData1__FDK[pb] = data1; |
612 | 0 | powerHybridData2__FDK[pb] = data2; |
613 | 0 | } /* pb */ |
614 | |
|
615 | 0 | { |
616 | 0 | for (j = 0, pb = 0; pb < nParamBands; pb++) { |
617 | 0 | FIXP_DBL dataReal, dataImag; |
618 | 0 | dataReal = dataImag = (FIXP_DBL)0; |
619 | 0 | for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { |
620 | 0 | FIXP_DPK scalarProd; |
621 | 0 | cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK, |
622 | 0 | ppHybridData2__FDK, inScale + pbScaleCh1[pb], |
623 | 0 | inScale + pbScaleCh2[pb], &outScale, |
624 | 0 | startTimeSlot, nTimeSlots, j, j + 1); |
625 | 0 | dataReal += scalarProd.v.re; |
626 | 0 | if (hTtoBox->pSubbandImagSign[j] < 0) { |
627 | 0 | dataImag -= scalarProd.v.im; |
628 | 0 | } else { |
629 | 0 | dataImag += scalarProd.v.im; |
630 | 0 | } |
631 | 0 | } /* for j */ |
632 | 0 | prodHybridDataReal__FDK[pb] = dataReal; |
633 | 0 | prodHybridDataImag__FDK[pb] = dataImag; |
634 | 0 | } /* pb */ |
635 | |
|
636 | 0 | if (SACENC_OK != (error = calculateIccFDK( |
637 | 0 | nParamBands, hTtoBox->iccCorrelationCoherenceBorder, |
638 | 0 | powerHybridData1__FDK, powerHybridData2__FDK, |
639 | 0 | prodHybridDataReal__FDK, prodHybridDataImag__FDK, |
640 | 0 | hTtoBox->pIcc__FDK))) { |
641 | 0 | goto bail; |
642 | 0 | } |
643 | | |
644 | | /* calculate correlation based Icc for downmix */ |
645 | 0 | if (SACENC_OK != (error = calculateIccFDK( |
646 | 0 | nParamBands, nParamBands, powerHybridData1__FDK, |
647 | 0 | powerHybridData2__FDK, prodHybridDataReal__FDK, |
648 | 0 | prodHybridDataImag__FDK, IccDownmix__FDK))) { |
649 | 0 | goto bail; |
650 | 0 | } |
651 | 0 | } |
652 | | |
653 | 0 | if (!bUseEbQ) { |
654 | 0 | CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK, |
655 | 0 | powerHybridData2__FDK, *scaleCh1 + inScale + 1, |
656 | 0 | pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2, |
657 | 0 | nParamBands); |
658 | 0 | } |
659 | |
|
660 | 0 | if (bUseBBCues) { |
661 | 0 | ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands); |
662 | |
|
663 | 0 | { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); } |
664 | |
|
665 | 0 | } /* bUseBBCues */ |
666 | | |
667 | | /* quantize/de-quantize icc */ |
668 | 0 | { |
669 | 0 | QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands, |
670 | 0 | hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, |
671 | 0 | hTtoBox->nIccQuantSteps, pIccIdx); |
672 | 0 | QuantizeCoefFDK(IccDownmix__FDK, nParamBands, |
673 | 0 | hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, |
674 | 0 | hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx); |
675 | 0 | deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands, |
676 | 0 | hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, |
677 | 0 | IccDownmixQuant__FDK); |
678 | |
|
679 | 0 | *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc; |
680 | 0 | } |
681 | | |
682 | | /* quantize/de-quantize cld */ |
683 | 0 | if (!bUseEbQ) { |
684 | 0 | QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands, |
685 | 0 | hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset, |
686 | 0 | hTtoBox->nCldQuantSteps, pCldIdx); |
687 | 0 | deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK, |
688 | 0 | hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK); |
689 | 0 | } else { |
690 | 0 | FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR)); |
691 | 0 | } |
692 | 0 | *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld; |
693 | |
|
694 | 0 | } /* valid handle */ |
695 | | |
696 | 0 | bail: |
697 | 0 | C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) |
698 | 0 | C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) |
699 | 0 | C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
700 | 0 | C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
701 | |
|
702 | 0 | C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
703 | 0 | C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
704 | 0 | C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
705 | 0 | C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) |
706 | |
|
707 | 0 | return error; |
708 | 0 | } |
709 | | |
710 | | INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, |
711 | 0 | const INT nSubband) { |
712 | 0 | INT nParamBand = -1; |
713 | 0 | const UCHAR *pSubband2ParameterIndex = |
714 | 0 | getSubband2ParameterIndex(boxSubbandConfig); |
715 | |
|
716 | 0 | if (pSubband2ParameterIndex != NULL) { |
717 | 0 | const int hybrid_resolution = 64; |
718 | |
|
719 | 0 | if ((nSubband > -1) && (nSubband < hybrid_resolution)) { |
720 | 0 | nParamBand = pSubband2ParameterIndex[nSubband]; |
721 | 0 | } |
722 | 0 | } |
723 | |
|
724 | 0 | return nParamBand; |
725 | 0 | } |