From 0e5af65c467b2423a0b857ae3ad98c91acc1e190 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 11 Nov 2019 11:38:02 +0100 Subject: Include patched FDK-AAC in the repository The initial idea was to get the DAB+ patch into upstream, but since that follows the android source releases, there is no place for a custom DAB+ patch there. So instead of having to maintain a patched fdk-aac that has to have the same .so version as the distribution package on which it is installed, we prefer having a separate fdk-aac-dab library to avoid collision. At that point, there's no reason to keep fdk-aac in a separate repository, as odr-audioenc is the only tool that needs DAB+ encoding support. Including it here simplifies installation, and makes it consistent with toolame-dab, also shipped in this repository. DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop, welle.io and others) can be done using upstream FDK-AAC. --- fdk-aac/libSACenc/src/sacenc_paramextract.cpp | 725 ++++++++++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 fdk-aac/libSACenc/src/sacenc_paramextract.cpp (limited to 'fdk-aac/libSACenc/src/sacenc_paramextract.cpp') diff --git a/fdk-aac/libSACenc/src/sacenc_paramextract.cpp b/fdk-aac/libSACenc/src/sacenc_paramextract.cpp new file mode 100644 index 0000000..dcbce1e --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_paramextract.cpp @@ -0,0 +1,725 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_paramextract.h" +#include "sacenc_tree.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */ +#define SCALE_CLDE_SF (7) /* maxVal in Quant tab is +/- 50 */ +#define SCALE_CLDD_SF (8) /* maxVal in Quant tab is +/- 150 */ + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX { + FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS]; + + const FIXP_DBL *pIccQuantTable__FDK; + const FIXP_DBL *pCldQuantTableDec__FDK; + const FIXP_DBL *pCldQuantTableEnc__FDK; + + SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS]; + SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS]; + + UCHAR *pParameterBand2HybridBandOffset; + const INT *pSubbandImagSign; + UCHAR nHybridBandsMax; + UCHAR nParameterBands; + UCHAR bFrameKeep; + + UCHAR iccCorrelationCoherenceBorder; + BOX_QUANTMODE boxQuantMode; + + UCHAR nIccQuantSteps; + UCHAR nIccQuantOffset; + + UCHAR nCldQuantSteps; + UCHAR nCldQuantOffset; + + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + +} TTO_BOX; + +struct BOX_SUBBAND_SETUP { + BOX_SUBBAND_CONFIG subbandConfig; + UCHAR nParameterBands; + const UCHAR *pSubband2ParameterIndexLd; + UCHAR iccCorrelationCoherenceBorder; +}; + +/* Constants *****************************************************************/ +static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + +static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; + +static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +#define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF))) +static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0), + SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0), + SCALE_CLDE(-6.0), SCALE_CLDE(-4.0), SCALE_CLDE(-2.0), SCALE_CLDE(0.0), + SCALE_CLDE(2.0), SCALE_CLDE(4.0), SCALE_CLDE(6.0), SCALE_CLDE(8.0), + SCALE_CLDE(10.0), SCALE_CLDE(13.0), SCALE_CLDE(16.0), SCALE_CLDE(19.0), + SCALE_CLDE(22.0), SCALE_CLDE(25.0), SCALE_CLDE(30.0), SCALE_CLDE(35.0), + SCALE_CLDE(40.0), SCALE_CLDE(45.0), SCALE_CLDE(50.0)}; + +static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-13.0), SCALE_CLDE(-8.0), SCALE_CLDE(-4.0), SCALE_CLDE(0.0), + SCALE_CLDE(4.0), SCALE_CLDE(8.0), SCALE_CLDE(13.0), SCALE_CLDE(19.0), + SCALE_CLDE(25.0), SCALE_CLDE(35.0), SCALE_CLDE(50.0)}; + +#define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF))) +static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0), + SCALE_CLDD(-30.0), SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-16.0), SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0), + SCALE_CLDD(-6.0), SCALE_CLDD(-4.0), SCALE_CLDD(-2.0), SCALE_CLDD(0.0), + SCALE_CLDD(2.0), SCALE_CLDD(4.0), SCALE_CLDD(6.0), SCALE_CLDD(8.0), + SCALE_CLDD(10.0), SCALE_CLDD(13.0), SCALE_CLDD(16.0), SCALE_CLDD(19.0), + SCALE_CLDD(22.0), SCALE_CLDD(25.0), SCALE_CLDD(30.0), SCALE_CLDD(35.0), + SCALE_CLDD(40.0), SCALE_CLDD(45.0), SCALE_CLDD(150.0)}; + +static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-13.0), SCALE_CLDD(-8.0), SCALE_CLDD(-4.0), SCALE_CLDD(0.0), + SCALE_CLDD(4.0), SCALE_CLDD(8.0), SCALE_CLDD(13.0), SCALE_CLDD(19.0), + SCALE_CLDD(25.0), SCALE_CLDD(35.0), SCALE_CLDD(150.0)}; + +#define SCALE_ICC(a) (FL2FXCONST_DBL(a)) +static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.937f), SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), SCALE_ICC(0.36764f), SCALE_ICC(0.0f), + SCALE_ICC(-0.589f), SCALE_ICC(-0.99f)}; + +static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f), + SCALE_ICC(-0.5890f)}; + +static const BOX_SUBBAND_SETUP boxSubbandSetup[] = { + {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1}, + {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2}, + {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3}, + {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4}, + {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4}, + {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5}, + {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static const BOX_SUBBAND_SETUP *getBoxSubbandSetup( + const BOX_SUBBAND_CONFIG subbandConfig) { + int i; + const BOX_SUBBAND_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP)); + i++) { + if (boxSubbandSetup[i].subbandConfig == subbandConfig) { + setup = &boxSubbandSetup[i]; + break; + } + } + return setup; +} + +static inline void ApplyBBCuesFDK(FIXP_DBL *const pData, + const INT nParamBands) { + int i, s; + FIXP_DBL tmp, invParamBands; + + invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s); + s = -s; + + tmp = fMult(pData[0], invParamBands) >> s; + for (i = 1; i < nParamBands; i++) { + tmp += fMult(pData[i], invParamBands) >> s; + } + + for (i = 0; i < nParamBands; i++) { + pData[i] = tmp; + } +} + +static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ((setup == NULL) ? 0 : setup->nParameterBands); +} + +static const UCHAR *getSubband2ParameterIndex( + const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + + return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd)); +} + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + const UCHAR *pSubband2ParameterIndex; + + int i, pb; + + pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd; + + for (pb = 0, i = 0; i < nHybridBands - 1; i++) { + if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) { + pParameterBand2HybridBandOffset[pb++] = (i + 1); + } + } + pParameterBand2HybridBandOffset[pb++] = (i + 1); +} + +const INT *fdk_sacenc_getSubbandImagSign() { + const INT *pImagSign = NULL; + + pImagSign = subbandImagSign_Ld; + + return (pImagSign); +} + +static INT getIccCorrelationCoherenceBorder( + const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ( + (setup == NULL) + ? 0 + : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder)); +} + +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hTtoBox) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX); + } + return error; + +bail: + fdk_sacenc_destroyTtoBox(hTtoBox); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) || + (pParameterBand2HybridBandOffset == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKmemclear(hTtoBox, sizeof(TTO_BOX)); + + hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld; + hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc; + hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode; + hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder( + ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly); + hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax; + hTtoBox->nParameterBands = + getNumberParameterBands(ttoBoxConfig->subbandConfig); + hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep; + + hTtoBox->nIccQuantSteps = + fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc); + hTtoBox->nIccQuantOffset = + fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc); + + hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc + ? iccQuantTableCoarse__FDK + : iccQuantTableFine__FDK; + hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseDec__FDK + : cldQuantTableFineDec__FDK; + hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseEnc__FDK + : cldQuantTableFineEnc__FDK; + + hTtoBox->nCldQuantSteps = + fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld); + hTtoBox->nCldQuantOffset = + fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld); + + /* sanity */ + if (NULL == (hTtoBox->pParameterBand2HybridBandOffset = + pParameterBand2HybridBandOffset)) { + error = SACENC_INIT_ERROR; + goto bail; + } + + if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) { + error = SACENC_INIT_ERROR; + } + + if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (*hTtoBox != NULL) { + FDKfree(*hTtoBox); + *hTtoBox = NULL; + } + + return error; +} + +static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand, + const INT correlationCoherenceBorder, + const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, + const FIXP_DBL *const pProdReal, + FIXP_DBL const *const pProdImag, + FIXP_DBL *const pIcc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) || + (pProdImag == NULL) || (pIcc == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + /* sanity check border */ + if (correlationCoherenceBorder > nParamBand) { + error = SACENC_INVALID_CONFIG; + } else { + /* correlation */ + FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2, + correlationCoherenceBorder); + + /* coherence */ + calcCoherenceVec(&pIcc[correlationCoherenceBorder], + &pProdReal[correlationCoherenceBorder], + &pProdImag[correlationCoherenceBorder], + &pPwr1[correlationCoherenceBorder], + &pPwr2[correlationCoherenceBorder], 0, 0, + nParamBand - correlationCoherenceBorder); + + } /* valid configuration */ + } /* valid handle */ + + return error; +} + +static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, const INT nQuantSteps, + SCHAR *const quantOut) { + int band; + const int reverse = (quantTable[0] > quantTable[1]); + + for (band = 0; band < nBands; band++) { + FIXP_DBL qVal; + FIXP_DBL curVal = input[band]; + + int lower = 0; + int upper = nQuantSteps - 1; + + if (reverse) { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal >= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* if reverse */ + else { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal <= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* else reverse */ + } /* for band */ +} + +static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, FIXP_DBL *const dequantOut) { + int band; + + for (band = 0; band < nBands; band++) { + dequantOut[band] = quantTable[input[band] + idxOffset]; + } +} + +static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, const INT scaleCh1, + const INT *const pbScaleCh1, const INT scaleCh2, + const INT *const pbScaleCh2, const int nParamBand) { + INT i; + FIXP_DBL ldPwr1, ldPwr2, cld; + FIXP_DBL maxPwr = FL2FXCONST_DBL( + 30.0f / + (1 << (LD_DATA_SHIFT + + 1))); /* consider SACENC_FLOAT_EPSILON in power calculation */ + + for (i = 0; i < nParamBand; i++) { + ldPwr1 = + (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + ldPwr2 = + (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr); + ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr); + + /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit + * scale by fMultDiv2() */ + cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)), + ldPwr1 - ldPwr2); + + cld = + fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2))); + cld = + fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2))); + pCld[i] = cld << (LD_DATA_SHIFT + 2); + } +} + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1, + INT *scaleCh2) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + + if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) || + (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) || + (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int j, pb; + const int nParamBands = hTtoBox->nParameterBands; + const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) || + (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2); + + /* sanity check */ + if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + int outScale; /* scalefactor will not be evaluated */ + int inScale = 5; /* scale factor determined empirically */ + + /* calculate the headroom of the hybrid data for each parameter band */ + FDKcalcPbScaleFactor(ppHybridData1__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1, + startTimeSlot, nTimeSlots, nParamBands); + FDKcalcPbScaleFactor(ppHybridData2__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2, + startTimeSlot, nTimeSlots, nParamBands); + + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL data1, data2; + data1 = data2 = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh1[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + } /* for j */ + powerHybridData1__FDK[pb] = data1; + powerHybridData2__FDK[pb] = data2; + } /* pb */ + + { + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL dataReal, dataImag; + dataReal = dataImag = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + FIXP_DPK scalarProd; + cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK, + ppHybridData2__FDK, inScale + pbScaleCh1[pb], + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + dataReal += scalarProd.v.re; + if (hTtoBox->pSubbandImagSign[j] < 0) { + dataImag -= scalarProd.v.im; + } else { + dataImag += scalarProd.v.im; + } + } /* for j */ + prodHybridDataReal__FDK[pb] = dataReal; + prodHybridDataImag__FDK[pb] = dataImag; + } /* pb */ + + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, hTtoBox->iccCorrelationCoherenceBorder, + powerHybridData1__FDK, powerHybridData2__FDK, + prodHybridDataReal__FDK, prodHybridDataImag__FDK, + hTtoBox->pIcc__FDK))) { + goto bail; + } + + /* calculate correlation based Icc for downmix */ + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, nParamBands, powerHybridData1__FDK, + powerHybridData2__FDK, prodHybridDataReal__FDK, + prodHybridDataImag__FDK, IccDownmix__FDK))) { + goto bail; + } + } + + if (!bUseEbQ) { + CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK, + powerHybridData2__FDK, *scaleCh1 + inScale + 1, + pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2, + nParamBands); + } + + if (bUseBBCues) { + ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands); + + { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); } + + } /* bUseBBCues */ + + /* quantize/de-quantize icc */ + { + QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, pIccIdx); + QuantizeCoefFDK(IccDownmix__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx); + deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + IccDownmixQuant__FDK); + + *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc; + } + + /* quantize/de-quantize cld */ + if (!bUseEbQ) { + QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands, + hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset, + hTtoBox->nCldQuantSteps, pCldIdx); + deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK, + hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK); + } else { + FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR)); + } + *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld; + + } /* valid handle */ + +bail: + C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + return error; +} + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband) { + INT nParamBand = -1; + const UCHAR *pSubband2ParameterIndex = + getSubband2ParameterIndex(boxSubbandConfig); + + if (pSubband2ParameterIndex != NULL) { + const int hybrid_resolution = 64; + + if ((nSubband > -1) && (nSubband < hybrid_resolution)) { + nParamBand = pSubband2ParameterIndex[nSubband]; + } + } + + return nParamBand; +} -- cgit v1.2.3