1/* ----------------------------------------------------------------------------- 2Software License for The Fraunhofer FDK AAC Codec Library for Android 3 4© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten 5Forschung e.V. All rights reserved. 6 7 1. INTRODUCTION 8The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software 9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding 10scheme for digital audio. This FDK AAC Codec software is intended to be used on 11a wide variety of Android devices. 12 13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient 14general perceptual audio codecs. AAC-ELD is considered the best-performing 15full-bandwidth communications codec by independent studies and is widely 16deployed. AAC has been standardized by ISO and IEC as part of the MPEG 17specifications. 18 19Patent licenses for necessary patent claims for the FDK AAC Codec (including 20those of Fraunhofer) may be obtained through Via Licensing 21(www.vialicensing.com) or through the respective patent owners individually for 22the purpose of encoding or decoding bit streams in products that are compliant 23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of 24Android devices already license these patent claims through Via Licensing or 25directly from the patent owners, and therefore FDK AAC Codec software may 26already be covered under those patent licenses when it is used for those 27licensed purposes only. 28 29Commercially-licensed AAC software libraries, including floating-point versions 30with enhanced sound quality, are also available from Fraunhofer. Users are 31encouraged to check the Fraunhofer website for additional applications 32information and documentation. 33 342. COPYRIGHT LICENSE 35 36Redistribution and use in source and binary forms, with or without modification, 37are permitted without payment of copyright license fees provided that you 38satisfy the following conditions: 39 40You must retain the complete text of this software license in redistributions of 41the FDK AAC Codec or your modifications thereto in source code form. 42 43You must retain the complete text of this software license in the documentation 44and/or other materials provided with redistributions of the FDK AAC Codec or 45your modifications thereto in binary form. You must make available free of 46charge copies of the complete source code of the FDK AAC Codec and your 47modifications thereto to recipients of copies in binary form. 48 49The name of Fraunhofer may not be used to endorse or promote products derived 50from this library without prior written permission. 51 52You may not charge copyright license fees for anyone to use, copy or distribute 53the FDK AAC Codec software or your modifications thereto. 54 55Your modified versions of the FDK AAC Codec must carry prominent notices stating 56that you changed the software and the date of any change. For modified versions 57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" 58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK 59AAC Codec Library for Android." 60 613. NO PATENT LICENSE 62 63NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without 64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. 65Fraunhofer provides no warranty of patent non-infringement with respect to this 66software. 67 68You may use this FDK AAC Codec software or modifications thereto only for 69purposes that are authorized by appropriate patent licenses. 70 714. DISCLAIMER 72 73This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright 74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, 75including but not limited to the implied warranties of merchantability and 76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, 78or consequential damages, including but not limited to procurement of substitute 79goods or services; loss of use, data, or profits, or business interruption, 80however caused and on any theory of liability, whether in contract, strict 81liability, or tort (including negligence), arising in any way out of the use of 82this software, even if advised of the possibility of such damage. 83 845. CONTACT INFORMATION 85 86Fraunhofer Institute for Integrated Circuits IIS 87Attention: Audio and Multimedia Departments - FDK AAC LL 88Am Wolfsmantel 33 8991058 Erlangen, Germany 90 91www.iis.fraunhofer.de/amm 92amm-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 *******************************************************************/ 113enum { BOX_0 = 0, BOX_1 = 1 }; 114 115enum { CH_L = 0, CH_R = 1 }; 116 117enum { TTO_CH_0 = 0, TTO_CH_1 = 1 }; 118 119enum { WIN_INACTIV = 0, WIN_ACTIV = 1 }; 120 121enum { MAX_KEEP_FRAMECOUNT = 100 }; 122 123/* Data Types ****************************************************************/ 124struct 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 143typedef 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 154typedef struct { 155 SPACETREE_MODE mode; 156 SPACE_TREE_DESCRIPTION treeDescription; 157 158} TREE_CONFIG; 159 160typedef 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 *****************************************************************/ 170static const TREE_CONFIG treeConfigTable[] = { 171 {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}}; 172 173static 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 ***********************************************/ 184static 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 203static 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 216FDK_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 240bail: 241 fdk_sacenc_spaceTree_Close(&hSpaceTree); 242 return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); 243} 244 245FDK_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 306bail: 307 return error; 308} 309 310static 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 339static 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 356FDK_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 441bail: 442 return error; 443} 444 445FDK_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 } 464bail: 465 return error; 466} 467 468FDK_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 481INT 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