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): Max Neuendorf
98
99 Description: Encoder Library Interface
100 Tree Structure for Space Encoder
101
102 *******************************************************************************/
103
104 /* Includes ******************************************************************/
105 #include "sacenc_tree.h"
106 #include "genericStds.h"
107 #include "sacenc_const.h"
108 #include "sacenc_paramextract.h"
109 #include "sacenc_framewindowing.h"
110 #include "FDK_matrixCalloc.h"
111
112 /* Defines *******************************************************************/
113 enum { BOX_0 = 0, BOX_1 = 1 };
114
115 enum { CH_L = 0, CH_R = 1 };
116
117 enum { TTO_CH_0 = 0, TTO_CH_1 = 1 };
118
119 enum { WIN_INACTIV = 0, WIN_ACTIV = 1 };
120
121 enum { MAX_KEEP_FRAMECOUNT = 100 };
122
123 /* Data Types ****************************************************************/
124 struct SPACE_TREE {
125 SPACETREE_MODE mode;
126 SPACE_TREE_DESCRIPTION descr;
127 HANDLE_TTO_BOX ttoBox[SACENC_MAX_NUM_BOXES];
128 UCHAR nParamBands;
129 UCHAR bUseCoarseQuantTtoIcc;
130 UCHAR bUseCoarseQuantTtoCld;
131 QUANTMODE quantMode;
132 INT frameCount;
133 UCHAR bFrameKeep;
134
135 /* Intermediate buffers */
136 UCHAR pCld_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS];
137 UCHAR pIcc_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS];
138
139 UCHAR nChannelsInMax;
140 UCHAR nHybridBandsMax;
141 };
142
143 typedef struct {
144 UCHAR boxId;
145 UCHAR inCh1;
146 UCHAR inCh2;
147 UCHAR inCh3;
148 UCHAR inCh4;
149 UCHAR wCh1;
150 UCHAR wCh2;
151
152 } TTO_DESCRIPTOR;
153
154 typedef struct {
155 SPACETREE_MODE mode;
156 SPACE_TREE_DESCRIPTION treeDescription;
157
158 } TREE_CONFIG;
159
160 typedef struct {
161 SPACETREE_MODE mode;
162 UCHAR nChannelsIn;
163 UCHAR nChannelsOut;
164 UCHAR nTtoBoxes;
165 TTO_DESCRIPTOR tto_descriptor[1];
166
167 } TREE_SETUP;
168
169 /* Constants *****************************************************************/
170 static const TREE_CONFIG treeConfigTable[] = {
171 {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}};
172
173 static const TREE_SETUP treeSetupTable[] = {
174 {SPACETREE_INVALID_MODE, 0, 0, 0, {{0, 0, 0, 0, 0, 0, 0}}},
175 {SPACETREE_212,
176 2,
177 1,
178 1,
179 {{BOX_0, CH_L, CH_R, TTO_CH_0, TTO_CH_1, WIN_ACTIV, WIN_ACTIV}}}};
180
181 /* Function / Class Declarations *********************************************/
182
183 /* Function / Class Definition ***********************************************/
getTreeConfig(const SPACETREE_MODE mode,SPACE_TREE_DESCRIPTION * pTreeDescription)184 static FDK_SACENC_ERROR getTreeConfig(
185 const SPACETREE_MODE mode, SPACE_TREE_DESCRIPTION *pTreeDescription) {
186 FDK_SACENC_ERROR error = SACENC_INIT_ERROR;
187
188 if (pTreeDescription == NULL) {
189 error = SACENC_INVALID_HANDLE;
190 } else {
191 int i;
192 for (i = 0; i < (int)(sizeof(treeConfigTable) / sizeof(TREE_CONFIG)); i++) {
193 if (treeConfigTable[i].mode == mode) {
194 *pTreeDescription = treeConfigTable[i].treeDescription;
195 error = SACENC_OK;
196 break;
197 }
198 }
199 } /* valid handle */
200 return error;
201 }
202
getTreeSetup(const SPACETREE_MODE mode)203 static const TREE_SETUP *getTreeSetup(const SPACETREE_MODE mode) {
204 int i;
205 const TREE_SETUP *setup = NULL;
206
207 for (i = 0; i < (int)(sizeof(treeSetupTable) / sizeof(TREE_SETUP)); i++) {
208 if (treeSetupTable[i].mode == mode) {
209 setup = &treeSetupTable[i];
210 break;
211 }
212 }
213 return setup;
214 }
215
fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE * phSpaceTree)216 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree) {
217 FDK_SACENC_ERROR error = SACENC_OK;
218 HANDLE_SPACE_TREE hSpaceTree = NULL;
219
220 if (NULL == phSpaceTree) {
221 error = SACENC_INVALID_HANDLE;
222 } else {
223 int box;
224
225 FDK_ALLOCATE_MEMORY_1D(hSpaceTree, 1, struct SPACE_TREE);
226
227 for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) {
228 HANDLE_TTO_BOX ttoBox = NULL;
229 if (SACENC_OK != (error = fdk_sacenc_createTtoBox(&ttoBox))) {
230 goto bail;
231 }
232 if (NULL != hSpaceTree) {
233 hSpaceTree->ttoBox[box] = ttoBox;
234 }
235 }
236 *phSpaceTree = hSpaceTree;
237 }
238 return error;
239
240 bail:
241 fdk_sacenc_spaceTree_Close(&hSpaceTree);
242 return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
243 }
244
fdk_sacenc_spaceTree_Init(HANDLE_SPACE_TREE hST,const SPACE_TREE_SETUP * const hSetup,UCHAR * pParameterBand2HybridBandOffset,const INT bFrameKeep)245 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init(
246 HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup,
247 UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep) {
248 FDK_SACENC_ERROR error = SACENC_OK;
249
250 if ((hST == NULL) || (hSetup == NULL)) {
251 error = SACENC_INVALID_HANDLE;
252 } else {
253 int bTtoBoxFrontBackCombin[SACENC_MAX_NUM_BOXES] = {0};
254 int box = 0;
255
256 hST->frameCount = 0;
257 hST->bFrameKeep = bFrameKeep;
258
259 /* Init */
260 hST->mode = hSetup->mode;
261 hST->nParamBands = hSetup->nParamBands;
262 hST->bUseCoarseQuantTtoIcc = hSetup->bUseCoarseQuantTtoIcc;
263 hST->bUseCoarseQuantTtoCld = hSetup->bUseCoarseQuantTtoCld;
264 hST->quantMode = hSetup->quantMode;
265 hST->nChannelsInMax = hSetup->nChannelsInMax;
266 hST->nHybridBandsMax = hSetup->nHybridBandsMax;
267
268 if (SACENC_OK != (error = getTreeConfig(hST->mode, &hST->descr))) {
269 goto bail;
270 }
271
272 switch (hST->mode) {
273 case SPACETREE_212:
274 bTtoBoxFrontBackCombin[BOX_0] = 0;
275 break;
276 case SPACETREE_INVALID_MODE:
277 default:
278 error = SACENC_INIT_ERROR;
279 goto bail;
280 } /* switch (hST->mode) */
281
282 if (hST->descr.nOttBoxes > SACENC_MAX_NUM_BOXES) {
283 error = SACENC_INIT_ERROR;
284 goto bail;
285 }
286
287 for (box = 0; box < hST->descr.nOttBoxes; box++) {
288 TTO_BOX_CONFIG boxConfig;
289 boxConfig.subbandConfig = (BOX_SUBBAND_CONFIG)hST->nParamBands;
290 boxConfig.bUseCoarseQuantCld = hST->bUseCoarseQuantTtoCld;
291 boxConfig.bUseCoarseQuantIcc = hST->bUseCoarseQuantTtoIcc;
292 boxConfig.bUseCoherenceIccOnly = bTtoBoxFrontBackCombin[box];
293 boxConfig.boxQuantMode = (BOX_QUANTMODE)hST->quantMode;
294 boxConfig.nHybridBandsMax = hST->nHybridBandsMax;
295 boxConfig.bFrameKeep = hST->bFrameKeep;
296
297 if (SACENC_OK !=
298 (error = fdk_sacenc_initTtoBox(hST->ttoBox[box], &boxConfig,
299 pParameterBand2HybridBandOffset))) {
300 goto bail;
301 }
302 } /* for box */
303
304 } /* valid handle */
305
306 bail:
307 return error;
308 }
309
SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST,SPATIALFRAME * const hSTOut,const INT avoid_keep)310 static void SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST,
311 SPATIALFRAME *const hSTOut,
312 const INT avoid_keep) {
313 int pb;
314
315 if (avoid_keep == 0) {
316 if (hST->frameCount % 2 == 0) {
317 for (pb = 0; pb < hST->nParamBands; pb++) {
318 hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb];
319 hSTOut->ottData.cld[BOX_0][0][pb] = hST->pCld_prev[BOX_0][pb];
320 }
321 } else {
322 for (pb = 0; pb < hST->nParamBands; pb++) {
323 hSTOut->ottData.icc[BOX_0][0][pb] = hST->pIcc_prev[BOX_0][pb];
324 hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb];
325 }
326 }
327 } else {
328 for (pb = 0; pb < hST->nParamBands; pb++) {
329 hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb];
330 hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb];
331 }
332 }
333 hST->frameCount++;
334 if (hST->frameCount == MAX_KEEP_FRAMECOUNT) {
335 hST->frameCount = 0;
336 }
337 }
338
SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST,SPATIALFRAME * const hSTOut,const INT avoid_keep)339 static FDK_SACENC_ERROR SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST,
340 SPATIALFRAME *const hSTOut,
341 const INT avoid_keep) {
342 FDK_SACENC_ERROR error = SACENC_OK;
343
344 switch (hST->mode) {
345 case SPACETREE_212:
346 SpaceTree_FrameKeep212(hST, hSTOut, avoid_keep);
347 break;
348 case SPACETREE_INVALID_MODE:
349 default:
350 error = SACENC_INVALID_CONFIG;
351 break;
352 }
353 return error;
354 }
355
fdk_sacenc_spaceTree_Apply(HANDLE_SPACE_TREE hST,const INT paramSet,const INT nChannelsIn,const INT nTimeSlots,const INT startTimeSlot,const INT nHybridBands,FIXP_WIN * pFrameWindowAna__FDK,FIXP_DPK * const * const * const pppHybrid__FDK,FIXP_DPK * const * const * const pppHybridIn__FDK,SPATIALFRAME * const hSTOut,const INT avoid_keep,INT * pEncoderInputChScale)356 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply(
357 HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn,
358 const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands,
359 FIXP_WIN *pFrameWindowAna__FDK,
360 FIXP_DPK *const *const *const pppHybrid__FDK,
361 FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut,
362 const INT avoid_keep, INT *pEncoderInputChScale) {
363 /** \verbatim
364 =============================================================================================================================
365 TREE_212
366 =============================================================================================================================
367 _______
368 L -- TTO_CH_0 --| |
369 | TTO_0 |-- TTO_CH_0
370 R -- TTO_CH_1 --|_______|
371
372 \endverbatim */
373
374 FDK_SACENC_ERROR error = SACENC_OK;
375 int k;
376 const TREE_SETUP *treeSetup = NULL;
377
378 if ((hST == NULL) || (hSTOut == NULL) || (pppHybrid__FDK == NULL) ||
379 (pppHybridIn__FDK == NULL)) {
380 error = SACENC_INVALID_HANDLE;
381 goto bail;
382 }
383
384 if ((treeSetup = getTreeSetup(hST->mode)) == NULL) {
385 error = SACENC_INVALID_CONFIG;
386 goto bail;
387 }
388
389 /* Sanity Checks */
390 if ((nChannelsIn != treeSetup->nChannelsIn) ||
391 (nChannelsIn > hST->nChannelsInMax) ||
392 (nHybridBands > hST->nHybridBandsMax)) {
393 error = SACENC_INVALID_CONFIG;
394 goto bail;
395 }
396
397 /* Apply all TTO boxes. */
398 for (k = 0; k < treeSetup->nTtoBoxes; k++) {
399 const TTO_DESCRIPTOR *pTTO = &treeSetup->tto_descriptor[k];
400
401 int i, inCh[2], outCh[2], win[2];
402
403 inCh[0] = pTTO->inCh1;
404 outCh[0] = pTTO->inCh3;
405 win[0] = pTTO->wCh1;
406 inCh[1] = pTTO->inCh2;
407 outCh[1] = pTTO->inCh4;
408 win[1] = pTTO->wCh2;
409
410 for (i = 0; i < 2; i++) {
411 if (win[i] == WIN_ACTIV) {
412 fdk_sacenc_analysisWindowing(
413 nTimeSlots, startTimeSlot, pFrameWindowAna__FDK,
414 pppHybrid__FDK[inCh[i]], pppHybridIn__FDK[outCh[i]], nHybridBands,
415 FW_LEAVE_DIM);
416 }
417 }
418
419 /* Calculate output downmix within last TTO box, if no TTT box is applied.
420 */
421 if (SACENC_OK !=
422 (error = fdk_sacenc_applyTtoBox(
423 hST->ttoBox[pTTO->boxId], nTimeSlots, startTimeSlot, nHybridBands,
424 pppHybridIn__FDK[pTTO->inCh3], pppHybridIn__FDK[pTTO->inCh4],
425 hSTOut->ottData.icc[pTTO->boxId][paramSet],
426 &(hSTOut->ICCLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]),
427 hSTOut->ottData.cld[pTTO->boxId][paramSet],
428 &(hSTOut->CLDLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]),
429 hSTOut->bUseBBCues, &pEncoderInputChScale[inCh[0]],
430 &pEncoderInputChScale[inCh[1]]))) {
431 goto bail;
432 }
433 }
434
435 if (hST->bFrameKeep == 1) {
436 if (SACENC_OK != (error = SpaceTree_FrameKeep(hST, hSTOut, avoid_keep))) {
437 goto bail;
438 }
439 }
440
441 bail:
442 return error;
443 }
444
fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE * phSpaceTree)445 FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree) {
446 FDK_SACENC_ERROR error = SACENC_OK;
447
448 if ((phSpaceTree == NULL) || (*phSpaceTree == NULL)) {
449 error = SACENC_INVALID_HANDLE;
450 } else {
451 int box;
452 HANDLE_SPACE_TREE const hST = *phSpaceTree;
453
454 /* for (box = 0; box < hST->descr.nOttBoxes; ++box) { */
455 for (box = 0; box < SACENC_MAX_NUM_BOXES; ++box) {
456 if (SACENC_OK != (error = fdk_sacenc_destroyTtoBox(&hST->ttoBox[box]))) {
457 goto bail;
458 }
459 }
460
461 FDKfree(*phSpaceTree);
462 *phSpaceTree = NULL;
463 }
464 bail:
465 return error;
466 }
467
fdk_sacenc_spaceTree_GetDescription(const HANDLE_SPACE_TREE hSpaceTree,SPACE_TREE_DESCRIPTION * pSpaceTreeDescription)468 FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription(
469 const HANDLE_SPACE_TREE hSpaceTree,
470 SPACE_TREE_DESCRIPTION *pSpaceTreeDescription) {
471 FDK_SACENC_ERROR error = SACENC_OK;
472
473 if ((hSpaceTree == NULL) || (pSpaceTreeDescription == NULL)) {
474 error = SACENC_INVALID_HANDLE;
475 } else {
476 *pSpaceTreeDescription = hSpaceTree->descr;
477 }
478 return error;
479 }
480
fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands,const INT nHybridBand)481 INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands,
482 const INT nHybridBand) {
483 return fdk_sacenc_subband2ParamBand((BOX_SUBBAND_CONFIG)nParamBands,
484 nHybridBand);
485 }
486
487 /*****************************************************************************
488 ******************************************************************************/
489