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