aboutsummaryrefslogtreecommitdiffstats
path: root/libSACenc/src/sacenc_paramextract.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSACenc/src/sacenc_paramextract.cpp')
-rw-r--r--libSACenc/src/sacenc_paramextract.cpp725
1 files changed, 725 insertions, 0 deletions
diff --git a/libSACenc/src/sacenc_paramextract.cpp b/libSACenc/src/sacenc_paramextract.cpp
new file mode 100644
index 0000000..dcbce1e
--- /dev/null
+++ b/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;
+}