aboutsummaryrefslogtreecommitdiffstats
path: root/libSACdec/src/sac_bitdec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSACdec/src/sac_bitdec.cpp')
-rw-r--r--libSACdec/src/sac_bitdec.cpp2147
1 files changed, 2147 insertions, 0 deletions
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
new file mode 100644
index 0000000..37e0cf2
--- /dev/null
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -0,0 +1,2147 @@
+/* -----------------------------------------------------------------------------
+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 decoder library *************************
+
+ Author(s):
+
+ Description: SAC Dec bitstream decoder
+
+*******************************************************************************/
+
+#include "sac_bitdec.h"
+
+#include "sac_dec_errorcodes.h"
+#include "nlc_dec.h"
+#include "sac_rom.h"
+#include "FDK_matrixCalloc.h"
+#include "sac_tsd.h"
+
+enum {
+ ottVsTotInactiv = 0,
+ ottVsTotDb1Activ = 1,
+ ottVsTotDb2Activ = 2,
+ ottVsTotDb1Db2Activ = 3
+};
+
+static SACDEC_ERROR SpatialDecDecodeHelperInfo(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType) {
+ int i;
+ UINT syntaxFlags;
+
+ /* Determine bit stream syntax */
+ syntaxFlags = 0;
+ switch (pSpatialSpecificConfig->coreCodec) {
+ case AOT_ER_AAC_ELD:
+ case AOT_ER_AAC_LD:
+ syntaxFlags |= SACDEC_SYNTAX_LD;
+ break;
+ case AOT_USAC:
+ syntaxFlags |= SACDEC_SYNTAX_USAC;
+ break;
+ case AOT_NONE:
+ default:
+ return MPS_UNSUPPORTED_FORMAT;
+ }
+
+ pSpatialSpecificConfig->syntaxFlags = syntaxFlags;
+
+ switch (pSpatialSpecificConfig->treeConfig) {
+ case TREE_212: {
+ pSpatialSpecificConfig->ottCLDdefault[0] = 0;
+ } break;
+ default:
+ return MPS_INVALID_TREECONFIG;
+ }
+
+ if (syntaxFlags & SACDEC_SYNTAX_USAC) {
+ if (pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ pSpatialSpecificConfig->numOttBandsIPD =
+ pSpatialSpecificConfig->bsOttBandsPhase;
+ } else {
+ int numParameterBands;
+
+ numParameterBands = pSpatialSpecificConfig->freqRes;
+ switch (numParameterBands) {
+ case 4:
+ case 5:
+ pSpatialSpecificConfig->numOttBandsIPD = 2;
+ break;
+ case 7:
+ pSpatialSpecificConfig->numOttBandsIPD = 3;
+ break;
+ case 10:
+ pSpatialSpecificConfig->numOttBandsIPD = 5;
+ break;
+ case 14:
+ pSpatialSpecificConfig->numOttBandsIPD = 7;
+ break;
+ case 20:
+ case 28:
+ pSpatialSpecificConfig->numOttBandsIPD = 10;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS;
+ }
+ }
+ } else {
+ pSpatialSpecificConfig->numOttBandsIPD = 0;
+ }
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ {
+ pSpatialSpecificConfig->bitstreamOttBands[i] =
+ pSpatialSpecificConfig->freqRes;
+ }
+ {
+ pSpatialSpecificConfig->numOttBands[i] =
+ pSpatialSpecificConfig->bitstreamOttBands[i];
+ if (syntaxFlags & SACDEC_SYNTAX_USAC &&
+ !pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ if (pSpatialSpecificConfig->bResidualCoding &&
+ pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent &&
+ (pSpatialSpecificConfig->numOttBandsIPD <
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands)) {
+ pSpatialSpecificConfig->numOttBandsIPD =
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands;
+ }
+ }
+ }
+ } /* i */
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecParseExtensionConfig
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+static SACDEC_ERROR SpatialDecParseExtensionConfig(
+ HANDLE_FDK_BITSTREAM bitstream, SPATIAL_SPECIFIC_CONFIG *config,
+ int numOttBoxes, int numTttBoxes, int numOutChan, int bitsAvailable) {
+ SACDEC_ERROR err = MPS_OK;
+ INT ba = bitsAvailable;
+
+ config->sacExtCnt = 0;
+ config->bResidualCoding = 0;
+
+ ba = fMin((int)FDKgetValidBits(bitstream), ba);
+
+ while ((ba >= 8) && (config->sacExtCnt < MAX_NUM_EXT_TYPES)) {
+ int bitsRead, nFillBits;
+ INT tmp;
+ UINT sacExtLen;
+
+ config->sacExtType[config->sacExtCnt] = FDKreadBits(bitstream, 4);
+ ba -= 4;
+
+ sacExtLen = FDKreadBits(bitstream, 4);
+ ba -= 4;
+
+ if (sacExtLen == 15) {
+ sacExtLen += FDKreadBits(bitstream, 8);
+ ba -= 8;
+ if (sacExtLen == 15 + 255) {
+ sacExtLen += FDKreadBits(bitstream, 16);
+ ba -= 16;
+ }
+ }
+
+ tmp = (INT)FDKgetValidBits(
+ bitstream); /* Extension config payload start anchor. */
+ if ((tmp <= 0) || (tmp < (INT)sacExtLen * 8) || (ba < (INT)sacExtLen * 8)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+
+ switch (config->sacExtType[config->sacExtCnt]) {
+ default:; /* unknown extension data => do nothing */
+ }
+
+ /* skip remaining extension data */
+ bitsRead = tmp - FDKgetValidBits(bitstream);
+ nFillBits = 8 * sacExtLen - bitsRead;
+
+ if (nFillBits < 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ } else {
+ /* Skip fill bits or an unkown extension. */
+ FDKpushFor(bitstream, nFillBits);
+ }
+
+ ba -= 8 * sacExtLen;
+ config->sacExtCnt++;
+ }
+
+bail:
+ return err;
+}
+
+SACDEC_ERROR SpatialDecParseSpecificConfigHeader(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType) {
+ SACDEC_ERROR err = MPS_OK;
+ INT numFillBits;
+ int sacHeaderLen = 0;
+ int sacTimeAlignFlag = 0;
+
+ sacTimeAlignFlag = FDKreadBits(bitstream, 1);
+ sacHeaderLen = FDKreadBits(bitstream, 7);
+
+ if (sacHeaderLen == 127) {
+ sacHeaderLen += FDKreadBits(bitstream, 16);
+ }
+ numFillBits = FDKgetValidBits(bitstream);
+
+ err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig,
+ sacHeaderLen, coreCodec);
+
+ numFillBits -=
+ FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */
+ numFillBits = (8 * sacHeaderLen) - numFillBits;
+ if (numFillBits < 0) {
+ /* Parsing went wrong */
+ err = MPS_PARSE_ERROR;
+ }
+ /* Move to the very end of the SSC */
+ FDKpushBiDirectional(bitstream, numFillBits);
+
+ if ((err == MPS_OK) && sacTimeAlignFlag) {
+ /* not supported */
+ FDKreadBits(bitstream, 16);
+ err = MPS_UNSUPPORTED_CONFIG;
+ }
+
+ /* Derive additional helper variables */
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, (UPMIXTYPE)upmixType);
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecParseMps212Config(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate,
+ AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex,
+ INT coreSbrFrameLengthIndex) {
+ int i;
+
+ pSpatialSpecificConfig->stereoConfigIndex = stereoConfigIndex;
+ pSpatialSpecificConfig->coreSbrFrameLengthIndex = coreSbrFrameLengthIndex;
+ pSpatialSpecificConfig->freqRes =
+ (SPATIALDEC_FREQ_RES)freqResTable[FDKreadBits(bitstream, 3)];
+ if (pSpatialSpecificConfig->freqRes == 0) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+
+ switch (coreCodec) {
+ case AOT_DRM_USAC:
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+ /* tempShapeConfig = (bsTempShapeConfigDrm == 1) ? 3 : 0 */
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)(FDKreadBits(bitstream, 1) * 3);
+ pSpatialSpecificConfig->decorrConfig = (SPATIALDEC_DECORR_CONF)0;
+ pSpatialSpecificConfig->bsDecorrType = 0;
+ break;
+ case AOT_USAC:
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2);
+ pSpatialSpecificConfig->decorrConfig =
+ (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2);
+ if (pSpatialSpecificConfig->decorrConfig > 2) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+ pSpatialSpecificConfig->bsDecorrType = 0;
+ break;
+ default:
+ return MPS_UNSUPPORTED_FORMAT;
+ }
+ pSpatialSpecificConfig->nTimeSlots = (coreSbrFrameLengthIndex == 4) ? 64 : 32;
+ pSpatialSpecificConfig->bsHighRateMode = (UCHAR)FDKreadBits(bitstream, 1);
+
+ {
+ pSpatialSpecificConfig->bsPhaseCoding = (UCHAR)FDKreadBits(bitstream, 1);
+ pSpatialSpecificConfig->bsOttBandsPhasePresent =
+ (UCHAR)FDKreadBits(bitstream, 1);
+ if (pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ if (MAX_PARAMETER_BANDS < (pSpatialSpecificConfig->bsOttBandsPhase =
+ FDKreadBits(bitstream, 5))) {
+ return MPS_PARSE_ERROR;
+ }
+ } else {
+ pSpatialSpecificConfig->bsOttBandsPhase = 0;
+ }
+ }
+
+ if (stereoConfigIndex > 1) { /* do residual coding */
+ pSpatialSpecificConfig->bResidualCoding = 1;
+ pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 1;
+ if (pSpatialSpecificConfig->freqRes <
+ (pSpatialSpecificConfig->ResidualConfig->nResidualBands =
+ FDKreadBits(bitstream, 5))) {
+ return MPS_PARSE_ERROR;
+ }
+ pSpatialSpecificConfig->bsOttBandsPhase =
+ fMax(pSpatialSpecificConfig->bsOttBandsPhase,
+ pSpatialSpecificConfig->ResidualConfig->nResidualBands);
+ pSpatialSpecificConfig->bsPseudoLr = (UCHAR)FDKreadBits(bitstream, 1);
+
+ if (pSpatialSpecificConfig->bsPhaseCoding) {
+ pSpatialSpecificConfig->bsPhaseCoding = 3;
+ }
+ } else {
+ pSpatialSpecificConfig->bResidualCoding = 0;
+ pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 0;
+ }
+
+ if (pSpatialSpecificConfig->tempShapeConfig == 2) {
+ switch (coreCodec) {
+ case AOT_USAC:
+ pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1);
+ break;
+ default: /* added to avoid compiler warning */
+ break; /* added to avoid compiler warning */
+ }
+ }
+
+ /* Static parameters */
+
+ pSpatialSpecificConfig->samplingFreq =
+ samplingRate; /* wrong for stereoConfigIndex == 3 but value is unused */
+ pSpatialSpecificConfig->treeConfig = SPATIALDEC_MODE_RSVD7;
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+
+ pSpatialSpecificConfig->bArbitraryDownmix = 0;
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ if (coreCodec == AOT_DRM_USAC) {
+ /* MPS payload is MPEG conform -> no need for pseudo DRM AOT */
+ coreCodec = AOT_USAC;
+ }
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+
+ /* Derive additional helper variables */
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+ return MPS_OK;
+}
+
+SACDEC_ERROR SpatialDecParseSpecificConfig(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen,
+ AUDIO_OBJECT_TYPE coreCodec) {
+ SACDEC_ERROR err = MPS_OK;
+ int i;
+ int bsSamplingFreqIndex;
+ int bsFreqRes, b3DaudioMode = 0;
+ int numHeaderBits;
+ int cfgStartPos, bitsAvailable;
+
+ cfgStartPos = FDKgetValidBits(bitstream);
+ /* It might be that we do not know the SSC length beforehand. */
+ if (sacHeaderLen == 0) {
+ bitsAvailable = cfgStartPos;
+ } else {
+ bitsAvailable = 8 * sacHeaderLen;
+ if (bitsAvailable > cfgStartPos) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ }
+
+ bsSamplingFreqIndex = FDKreadBits(bitstream, 4);
+
+ if (bsSamplingFreqIndex == 15) {
+ pSpatialSpecificConfig->samplingFreq = FDKreadBits(bitstream, 24);
+ } else {
+ pSpatialSpecificConfig->samplingFreq =
+ samplingFreqTable[bsSamplingFreqIndex];
+ if (pSpatialSpecificConfig->samplingFreq == 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ }
+
+ pSpatialSpecificConfig->nTimeSlots = FDKreadBits(bitstream, 5) + 1;
+ if ((pSpatialSpecificConfig->nTimeSlots < 1) ||
+ (pSpatialSpecificConfig->nTimeSlots > MAX_TIME_SLOTS)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+
+ bsFreqRes = FDKreadBits(bitstream, 3);
+
+ pSpatialSpecificConfig->freqRes =
+ (SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes];
+
+ pSpatialSpecificConfig->treeConfig =
+ (SPATIALDEC_TREE_CONFIG)FDKreadBits(bitstream, 4);
+
+ if (pSpatialSpecificConfig->treeConfig != SPATIALDEC_MODE_RSVD7) {
+ err = MPS_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
+
+ {
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nTttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numTttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+ }
+
+ pSpatialSpecificConfig->quantMode =
+ (SPATIALDEC_QUANT_MODE)FDKreadBits(bitstream, 2);
+
+ pSpatialSpecificConfig->bArbitraryDownmix = FDKreadBits(bitstream, 1);
+
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2);
+ pSpatialSpecificConfig->decorrConfig =
+ (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2);
+ if (pSpatialSpecificConfig->decorrConfig > 2) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ for (i = 0; i < pSpatialSpecificConfig->nTttBoxes; i++) {
+ int bTttDualMode = FDKreadBits(bitstream, 1);
+ FDKreadBits(bitstream, 3); /* not supported */
+
+ if (bTttDualMode) {
+ FDKreadBits(bitstream, 8); /* not supported */
+ }
+ }
+
+ if (pSpatialSpecificConfig->tempShapeConfig == 2) {
+ pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1);
+ }
+
+ if (b3DaudioMode) {
+ if (FDKreadBits(bitstream, 2) == 0) { /* b3DaudioHRTFset ? */
+ int hc;
+ int HRTFnumBand;
+ int HRTFfreqRes = FDKreadBits(bitstream, 3);
+ int HRTFnumChan = FDKreadBits(bitstream, 4);
+ int HRTFasymmetric = FDKreadBits(bitstream, 1);
+
+ HRTFnumBand = freqResTable_LD[HRTFfreqRes];
+
+ for (hc = 0; hc < HRTFnumChan; hc++) {
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelLeft[hc][hb] */
+ if (HRTFasymmetric) {
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelRight[hc][hb] */
+ }
+ if (FDKreadBits(bitstream, 1)) { /* HRTFphase[hc] ? */
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFphaseLR[hc][hb] */
+ }
+ if (FDKreadBits(bitstream, 1)) { /* HRTFicc[hc] ? */
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFiccLR[hc][hb] */
+ }
+ }
+ }
+ }
+
+ FDKbyteAlign(bitstream,
+ cfgStartPos); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment
+ with respect to the beginning of the syntactic
+ element in which ByteAlign() occurs. */
+
+ numHeaderBits = cfgStartPos - (INT)FDKgetValidBits(bitstream);
+ bitsAvailable -= numHeaderBits;
+
+ pSpatialSpecificConfig->sacExtCnt = 0;
+ pSpatialSpecificConfig->bResidualCoding = 0;
+
+ if ((err == MPS_OK) && (bitsAvailable > 0)) {
+ err = SpatialDecParseExtensionConfig(
+ bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes,
+ pSpatialSpecificConfig->nTttBoxes,
+ pSpatialSpecificConfig->nOutputChannels, bitsAvailable);
+ }
+
+ FDKbyteAlign(
+ bitstream,
+ cfgStartPos); /* Same alignment anchor as above because
+ SpatialExtensionConfig() always reads full bytes */
+
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+bail:
+ if (sacHeaderLen > 0) {
+ /* If the config is of known length then assure that the
+ bitbuffer is exactly at its end when leaving the function. */
+ FDKpushBiDirectional(
+ bitstream,
+ (sacHeaderLen * 8) - (cfgStartPos - (INT)FDKgetValidBits(bitstream)));
+ }
+
+ return err;
+}
+
+int SpatialDecDefaultSpecificConfig(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots,
+ int sacDecoderLevel, int isBlind, int numCoreChannels)
+
+{
+ int err = MPS_OK;
+ int i;
+
+ FDK_ASSERT(coreCodec != AOT_NONE);
+ FDK_ASSERT(nTimeSlots > 0);
+ FDK_ASSERT(samplingFreq > 0);
+
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+ pSpatialSpecificConfig->samplingFreq = samplingFreq;
+ pSpatialSpecificConfig->nTimeSlots = nTimeSlots;
+ if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) ||
+ (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD))
+ pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_23;
+ else
+ pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_28;
+
+ {
+ pSpatialSpecificConfig->treeConfig =
+ SPATIALDEC_MODE_RSVD7; /* 212 configuration */
+ }
+
+ {
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+ }
+
+ pSpatialSpecificConfig->quantMode = SPATIALDEC_QUANT_FINE_DEF;
+ pSpatialSpecificConfig->bArbitraryDownmix = 0;
+ pSpatialSpecificConfig->bResidualCoding = 0;
+ if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) ||
+ (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD))
+ pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_RSVD2;
+ else
+ pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_MODE0;
+
+ pSpatialSpecificConfig->tempShapeConfig = SPATIALDEC_TS_TPNOWHITE;
+ pSpatialSpecificConfig->decorrConfig = SPATIALDEC_DECORR_MODE0;
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: coarse2fine
+ *******************************************************************************
+
+ Description:
+ Parameter index mapping from coarse to fine quantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static void coarse2fine(SCHAR *data, DATA_TYPE dataType, int startBand,
+ int numBands) {
+ int i;
+
+ for (i = startBand; i < startBand + numBands; i++) {
+ data[i] <<= 1;
+ }
+
+ if (dataType == t_CLD) {
+ for (i = startBand; i < startBand + numBands; i++) {
+ if (data[i] == -14)
+ data[i] = -15;
+ else if (data[i] == 14)
+ data[i] = 15;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: fine2coarse
+ *******************************************************************************
+
+ Description:
+ Parameter index mapping from fine to coarse quantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static void fine2coarse(SCHAR *data, DATA_TYPE dataType, int startBand,
+ int numBands) {
+ int i;
+
+ for (i = startBand; i < startBand + numBands; i++) {
+ /* Note: the if cases below actually make a difference (negative values) */
+ if (dataType == t_CLD)
+ data[i] /= 2;
+ else
+ data[i] >>= 1;
+ }
+}
+
+/*******************************************************************************
+ Functionname: getStrideMap
+ *******************************************************************************
+
+ Description:
+ Index Mapping accroding to pbStrides
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static int getStrideMap(int freqResStride, int startBand, int stopBand,
+ int *aStrides) {
+ int i, pb, pbStride, dataBands, strOffset;
+
+ pbStride = pbStrideTable[freqResStride];
+ dataBands = (stopBand - startBand - 1) / pbStride + 1;
+
+ aStrides[0] = startBand;
+ for (pb = 1; pb <= dataBands; pb++) {
+ aStrides[pb] = aStrides[pb - 1] + pbStride;
+ }
+ strOffset = 0;
+ while (aStrides[dataBands] > stopBand) {
+ if (strOffset < dataBands) strOffset++;
+ for (i = strOffset; i <= dataBands; i++) {
+ aStrides[i]--;
+ }
+ }
+
+ return dataBands;
+}
+
+/*******************************************************************************
+ Functionname: ecDataDec
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+
+*******************************************************************************/
+
+static SACDEC_ERROR ecDataDec(
+ const SPATIAL_BS_FRAME *frame, UINT syntaxFlags,
+ HANDLE_FDK_BITSTREAM bitstream, LOSSLESSDATA *const llData,
+ SCHAR (*data)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], SCHAR **lastdata,
+ int datatype, int boxIdx, int startBand, int stopBand, SCHAR defaultValue) {
+ SACDEC_ERROR err = MPS_OK;
+ int i, j, pb, dataSets, setIdx, bsDataPair, dataBands, oldQuantCoarseXXX;
+ INT aStrides[MAX_PARAMETER_BANDS + 1] = {0};
+
+ dataSets = 0;
+ for (i = 0; i < frame->numParameterSets; i++) {
+ llData->bsXXXDataMode[i] = (SCHAR)FDKreadBits(bitstream, 2);
+
+ if ((frame->bsIndependencyFlag == 1) && (i == 0) &&
+ (llData->bsXXXDataMode[i] == 1 ||
+ llData->bsXXXDataMode[i] == 2)) { /* This check catches bitstreams
+ generated by older encoder that
+ cause trouble */
+ return MPS_PARSE_ERROR;
+ }
+ if ((i >= frame->numParameterSets - 1) &&
+ (llData->bsXXXDataMode[i] ==
+ 2)) { /* The interpolation mode must not be active for the last
+ parameter set */
+ return MPS_PARSE_ERROR;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ dataSets++;
+ }
+ }
+
+ setIdx = 0;
+ bsDataPair = 0;
+ oldQuantCoarseXXX = llData->state->bsQuantCoarseXXXprevParse;
+
+ for (i = 0; i < frame->numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 0) {
+ for (pb = startBand; pb < stopBand; pb++) {
+ lastdata[boxIdx][pb] = defaultValue;
+ }
+
+ oldQuantCoarseXXX = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ if (bsDataPair) {
+ bsDataPair = 0;
+ } else {
+ bsDataPair = FDKreadBits(bitstream, 1);
+ llData->bsQuantCoarseXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 1);
+ llData->bsFreqResStrideXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 2);
+
+ if (llData->bsQuantCoarseXXX[setIdx] != oldQuantCoarseXXX) {
+ if (oldQuantCoarseXXX) {
+ coarse2fine(lastdata[boxIdx], (DATA_TYPE)datatype, startBand,
+ stopBand - startBand);
+ } else {
+ fine2coarse(lastdata[boxIdx], (DATA_TYPE)datatype, startBand,
+ stopBand - startBand);
+ }
+ }
+
+ dataBands = getStrideMap(llData->bsFreqResStrideXXX[setIdx], startBand,
+ stopBand, aStrides);
+
+ for (pb = 0; pb < dataBands; pb++) {
+ lastdata[boxIdx][startBand + pb] = lastdata[boxIdx][aStrides[pb]];
+ }
+
+ if (boxIdx > MAX_NUM_OTT) return MPS_INVALID_BOXIDX;
+ if ((setIdx + bsDataPair) > MAX_PARAMETER_SETS)
+ return MPS_INVALID_SETIDX;
+
+ /* DECODER_TYPE defined in FDK_tools */
+ DECODER_TYPE this_decoder_type = SAC_DECODER;
+ if (syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) {
+ this_decoder_type = USAC_DECODER;
+ } else if (syntaxFlags & SACDEC_SYNTAX_LD) {
+ this_decoder_type = SAOC_DECODER;
+ }
+
+ err = (SACDEC_ERROR)EcDataPairDec(
+ this_decoder_type, bitstream, data[boxIdx][setIdx + 0],
+ data[boxIdx][setIdx + 1], lastdata[boxIdx], (DATA_TYPE)datatype,
+ startBand, dataBands, bsDataPair, llData->bsQuantCoarseXXX[setIdx],
+ !(frame->bsIndependencyFlag && (i == 0)) || (setIdx > 0));
+ if (err != MPS_OK) goto bail;
+
+ if (datatype == t_IPD) {
+ const SCHAR mask = (llData->bsQuantCoarseXXX[setIdx]) ? 7 : 15;
+ for (pb = 0; pb < dataBands; pb++) {
+ for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) {
+ lastdata[boxIdx][j] =
+ data[boxIdx][setIdx + bsDataPair][startBand + pb] & mask;
+ }
+ }
+ } else {
+ for (pb = 0; pb < dataBands; pb++) {
+ for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) {
+ lastdata[boxIdx][j] =
+ data[boxIdx][setIdx + bsDataPair][startBand + pb];
+ }
+ }
+ }
+
+ oldQuantCoarseXXX = llData->bsQuantCoarseXXX[setIdx];
+
+ if (bsDataPair) {
+ llData->bsQuantCoarseXXX[setIdx + 1] =
+ llData->bsQuantCoarseXXX[setIdx];
+ llData->bsFreqResStrideXXX[setIdx + 1] =
+ llData->bsFreqResStrideXXX[setIdx];
+ }
+ setIdx += bsDataPair + 1;
+ } /* !bsDataPair */
+ } /* llData->bsXXXDataMode[i] == 3 */
+ }
+
+ llData->state->bsQuantCoarseXXXprevParse = oldQuantCoarseXXX;
+
+bail:
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: parseArbitraryDownmixData
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR parseArbitraryDownmixData(
+ spatialDec *self, const SPATIAL_SPECIFIC_CONFIG *pSSC,
+ const UINT syntaxFlags, const SPATIAL_BS_FRAME *frame,
+ HANDLE_FDK_BITSTREAM bitstream) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+ int offset = pSSC->nOttBoxes;
+
+ /* CLD (arbitrary down-mix gains) */
+ for (ch = 0; ch < pSSC->nInputChannels; ch++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream,
+ &frame->CLDLosslessData[offset + ch],
+ frame->cmpArbdmxGainIdx, self->cmpArbdmxGainIdxPrev, t_CLD,
+ ch, 0, pSSC->freqRes, arbdmxGainDefault);
+ if (err != MPS_OK) return err;
+ }
+
+ return err;
+
+} /* parseArbitraryDownmixData */
+
+/*******************************************************************************
+ Functionname: SpatialDecParseFrame
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+*******************************************************************************/
+
+static int nBitsParamSlot(int i) {
+ int bitsParamSlot;
+
+ bitsParamSlot = fMax(0, DFRACT_BITS - 1 - fNormz((FIXP_DBL)i));
+ if ((1 << bitsParamSlot) < i) {
+ bitsParamSlot++;
+ }
+ FDK_ASSERT((bitsParamSlot >= 0) && (bitsParamSlot <= 32));
+
+ return bitsParamSlot;
+}
+
+SACDEC_ERROR SpatialDecParseFrameData(
+ spatialDec_struct *self, SPATIAL_BS_FRAME *frame,
+ HANDLE_FDK_BITSTREAM bitstream,
+ const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType,
+ int fGlobalIndependencyFlag) {
+ SACDEC_ERROR err = MPS_OK;
+ int bsFramingType, dataBands, ps, pg, i;
+ int pb;
+ int numTempShapeChan = 0;
+ int bsNumOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig]
+ .numOutputChannels; /* CAUTION: Maybe different to
+ pSpatialSpecificConfig->treeConfig in some
+ modes! */
+ int paramSetErr = 0;
+ UINT alignAnchor = FDKgetValidBits(
+ bitstream); /* Anchor for ByteAlign() function. See comment below. */
+ UINT syntaxFlags;
+
+ syntaxFlags = pSpatialSpecificConfig->syntaxFlags;
+
+ if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
+ pSpatialSpecificConfig->bsHighRateMode == 0) {
+ bsFramingType = 0; /* fixed framing */
+ frame->numParameterSets = 1;
+ } else {
+ bsFramingType = FDKreadBits(bitstream, 1);
+ if (syntaxFlags & SACDEC_SYNTAX_LD)
+ frame->numParameterSets = FDKreadBits(bitstream, 1) + 1;
+ else
+ frame->numParameterSets = FDKreadBits(bitstream, 3) + 1;
+ }
+
+ /* Any error after this line shall trigger parameter invalidation at bail
+ * label. */
+ paramSetErr = 1;
+
+ if (frame->numParameterSets >= MAX_PARAMETER_SETS) {
+ goto bail;
+ }
+
+ /* Basic config check. */
+ if (pSpatialSpecificConfig->nInputChannels <= 0 ||
+ pSpatialSpecificConfig->nOutputChannels <= 0) {
+ err = MPS_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
+
+ if (bsFramingType) {
+ int prevParamSlot = -1;
+ int bitsParamSlot;
+
+ {
+ bitsParamSlot = nBitsParamSlot(pSpatialSpecificConfig->nTimeSlots);
+
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->paramSlot[i] = FDKreadBits(bitstream, bitsParamSlot);
+ /* Sanity check */
+ if ((frame->paramSlot[i] <= prevParamSlot) ||
+ (frame->paramSlot[i] >= pSpatialSpecificConfig->nTimeSlots)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ prevParamSlot = frame->paramSlot[i];
+ }
+ }
+ } else {
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->paramSlot[i] = ((pSpatialSpecificConfig->nTimeSlots * (i + 1)) /
+ frame->numParameterSets) -
+ 1;
+ }
+ }
+
+ if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
+ fGlobalIndependencyFlag) {
+ frame->bsIndependencyFlag = 1;
+ } else {
+ frame->bsIndependencyFlag = (UCHAR)FDKreadBits(bitstream, 1);
+ }
+
+ /*
+ * OttData()
+ */
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->CLDLosslessData[i],
+ frame->cmpOttCLDidx, self->cmpOttCLDidxPrev, t_CLD, i, 0,
+ pSpatialSpecificConfig->bitstreamOttBands[i],
+ pSpatialSpecificConfig->ottCLDdefault[i]);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ } /* i < numOttBoxes */
+
+ {
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->ICCLosslessData[i],
+ frame->cmpOttICCidx, self->cmpOttICCidxPrev, t_ICC, i, 0,
+ pSpatialSpecificConfig->bitstreamOttBands[i], ICCdefault);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ } /* i < numOttBoxes */
+ } /* !oneICC */
+
+ if ((pSpatialSpecificConfig->treeConfig == SPATIALDEC_MODE_RSVD7) &&
+ (pSpatialSpecificConfig->bsPhaseCoding)) {
+ frame->phaseMode = FDKreadBits(bitstream, 1);
+
+ if (frame->phaseMode == 0) {
+ for (pb = 0; pb < pSpatialSpecificConfig->numOttBandsIPD; pb++) {
+ self->cmpOttIPDidxPrev[0][pb] = 0;
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->cmpOttIPDidx[0][i][pb] = 0;
+ // frame->ottIPDidx[0][i][pb] = 0;
+ }
+ /* self->ottIPDidxPrev[0][pb] = 0; */
+ }
+ frame->OpdSmoothingMode = 0;
+ } else {
+ frame->OpdSmoothingMode = FDKreadBits(bitstream, 1);
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->IPDLosslessData[0],
+ frame->cmpOttIPDidx, self->cmpOttIPDidxPrev, t_IPD, 0, 0,
+ pSpatialSpecificConfig->numOttBandsIPD, IPDdefault);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ }
+ }
+
+ /*
+ * SmgData()
+ */
+
+ {
+ if (!pSpatialSpecificConfig->bsHighRateMode &&
+ (syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ frame->bsSmoothMode[ps] = 0;
+ }
+ } else {
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ frame->bsSmoothMode[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ if (frame->bsSmoothMode[ps] >= 2) {
+ frame->bsSmoothTime[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ }
+ if (frame->bsSmoothMode[ps] == 3) {
+ frame->bsFreqResStrideSmg[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ dataBands = (pSpatialSpecificConfig->freqRes - 1) /
+ pbStrideTable[frame->bsFreqResStrideSmg[ps]] +
+ 1;
+ for (pg = 0; pg < dataBands; pg++) {
+ frame->bsSmgData[ps][pg] = (UCHAR)FDKreadBits(bitstream, 1);
+ }
+ }
+ } /* ps < numParameterSets */
+ }
+ }
+
+ /*
+ * TempShapeData()
+ */
+ if ((pSpatialSpecificConfig->tempShapeConfig == 3) &&
+ (syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ int TsdErr;
+ TsdErr = TsdRead(bitstream, pSpatialSpecificConfig->nTimeSlots,
+ &frame->TsdData[0]);
+ if (TsdErr) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ } else {
+ frame->TsdData[0].bsTsdEnable = 0;
+ }
+
+ for (i = 0; i < bsNumOutputChannels; i++) {
+ frame->tempShapeEnableChannelSTP[i] = 0;
+ frame->tempShapeEnableChannelGES[i] = 0;
+ }
+
+ if ((pSpatialSpecificConfig->tempShapeConfig == 1) ||
+ (pSpatialSpecificConfig->tempShapeConfig == 2)) {
+ int bsTempShapeEnable = FDKreadBits(bitstream, 1);
+ if (bsTempShapeEnable) {
+ numTempShapeChan =
+ tempShapeChanTable[pSpatialSpecificConfig->tempShapeConfig - 1]
+ [pSpatialSpecificConfig->treeConfig];
+ switch (pSpatialSpecificConfig->tempShapeConfig) {
+ case 1: /* STP */
+ for (i = 0; i < numTempShapeChan; i++) {
+ int stpEnable = FDKreadBits(bitstream, 1);
+ frame->tempShapeEnableChannelSTP[i] = stpEnable;
+ }
+ break;
+ case 2: /* GES */
+ {
+ UCHAR gesChannelEnable[MAX_OUTPUT_CHANNELS];
+
+ for (i = 0; i < numTempShapeChan; i++) {
+ gesChannelEnable[i] = (UCHAR)FDKreadBits(bitstream, 1);
+ frame->tempShapeEnableChannelGES[i] = gesChannelEnable[i];
+ }
+ for (i = 0; i < numTempShapeChan; i++) {
+ if (gesChannelEnable[i]) {
+ int envShapeData_tmp[MAX_TIME_SLOTS];
+ if (huff_dec_reshape(bitstream, envShapeData_tmp,
+ pSpatialSpecificConfig->nTimeSlots) != 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ for (int ts = 0; ts < pSpatialSpecificConfig->nTimeSlots; ts++) {
+ if (!(envShapeData_tmp[ts] >= 0) &&
+ (envShapeData_tmp[ts] <= 4)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ frame->bsEnvShapeData[i][ts] = (UCHAR)envShapeData_tmp[ts];
+ }
+ }
+ }
+ } break;
+ default:
+ err = MPS_INVALID_TEMPSHAPE;
+ goto bail;
+ }
+ } /* bsTempShapeEnable */
+ } /* pSpatialSpecificConfig->tempShapeConfig != 0 */
+
+ if (pSpatialSpecificConfig->bArbitraryDownmix != 0) {
+ err = parseArbitraryDownmixData(self, pSpatialSpecificConfig, syntaxFlags,
+ frame, bitstream);
+ if (err != MPS_OK) goto bail;
+ }
+
+ if (1 && (!(syntaxFlags & (SACDEC_SYNTAX_USAC)))) {
+ FDKbyteAlign(bitstream,
+ alignAnchor); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment
+ with respect to the beginning of the syntactic
+ element in which ByteAlign() occurs. */
+ }
+
+bail:
+ if (err != MPS_OK && paramSetErr != 0) {
+ /* Since the parameter set data has already been written to the instance we
+ * need to ... */
+ frame->numParameterSets = 0; /* ... signal that it is corrupt ... */
+ }
+
+ return err;
+
+} /* SpatialDecParseFrame */
+
+/*******************************************************************************
+ Functionname: createMapping
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void createMapping(int aMap[MAX_PARAMETER_BANDS + 1], int startBand,
+ int stopBand, int stride) {
+ int inBands, outBands, bandsAchived, bandsDiff, incr, k, i;
+ int vDk[MAX_PARAMETER_BANDS + 1];
+ inBands = stopBand - startBand;
+ outBands = (inBands - 1) / stride + 1;
+
+ if (outBands < 1) {
+ outBands = 1;
+ }
+
+ bandsAchived = outBands * stride;
+ bandsDiff = inBands - bandsAchived;
+ for (i = 0; i < outBands; i++) {
+ vDk[i] = stride;
+ }
+
+ if (bandsDiff > 0) {
+ incr = -1;
+ k = outBands - 1;
+ } else {
+ incr = 1;
+ k = 0;
+ }
+
+ while (bandsDiff != 0) {
+ vDk[k] = vDk[k] - incr;
+ k = k + incr;
+ bandsDiff = bandsDiff + incr;
+ if (k >= outBands) {
+ if (bandsDiff > 0) {
+ k = outBands - 1;
+ } else if (bandsDiff < 0) {
+ k = 0;
+ }
+ }
+ }
+ aMap[0] = startBand;
+ for (i = 0; i < outBands; i++) {
+ aMap[i + 1] = aMap[i] + vDk[i];
+ }
+} /* createMapping */
+
+/*******************************************************************************
+ Functionname: mapFrequency
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void mapFrequency(const SCHAR *pInput, /* Input */
+ SCHAR *pOutput, /* Output */
+ int *pMap, /* Mapping function */
+ int dataBands) /* Number of data Bands */
+{
+ int i, j;
+ int startBand0 = pMap[0];
+
+ for (i = 0; i < dataBands; i++) {
+ int startBand, stopBand, value;
+
+ value = pInput[i + startBand0];
+
+ startBand = pMap[i];
+ stopBand = pMap[i + 1];
+ for (j = startBand; j < stopBand; j++) {
+ pOutput[j] = value;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: deq
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static int deqIdx(int value, int paramType) {
+ int idx = -1;
+
+ switch (paramType) {
+ case t_CLD:
+ if (((value + 15) >= 0) && ((value + 15) < 31)) {
+ idx = (value + 15);
+ }
+ break;
+
+ case t_ICC:
+ if ((value >= 0) && (value < 8)) {
+ idx = value;
+ }
+ break;
+
+ case t_IPD:
+ /* (+/-)15 * MAX_PARAMETER_BANDS for differential coding in frequency
+ * domain (according to rbl) */
+ if ((value >= -420) && (value <= 420)) {
+ idx = (value & 0xf);
+ }
+ break;
+
+ default:
+ FDK_ASSERT(0);
+ }
+
+ return idx;
+}
+
+ /*******************************************************************************
+ Functionname: factorFunct
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+ *******************************************************************************/
+
+#define SF_IDX (7)
+#define SF_FACTOR (3)
+#define SCALE_FACTOR (1 << SF_FACTOR)
+#define SCALE_CLD_C1C2 (1 << SF_CLD_C1C2)
+
+static FIXP_DBL factorFunct(FIXP_DBL ottVsTotDb, INT quantMode) {
+ FIXP_DBL factor;
+
+ if (ottVsTotDb > FL2FXCONST_DBL(0.0)) {
+ ottVsTotDb = FL2FXCONST_DBL(0.0);
+ }
+
+ ottVsTotDb = -ottVsTotDb;
+
+ switch (quantMode) {
+ case 0:
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ break;
+ case 1:
+ if (ottVsTotDb >= FL2FXCONST_DBL(21.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(5.0f / SCALE_FACTOR);
+ else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ else
+ factor = (fMult(FL2FXCONST_DBL(0.2f), ottVsTotDb) +
+ FL2FXCONST_DBL(0.8f / SCALE_CLD_C1C2))
+ << (SF_CLD_C1C2 - SF_FACTOR);
+ break;
+ case 2:
+ if (ottVsTotDb >= FL2FXCONST_DBL(25.0f / SCALE_CLD_C1C2)) {
+ FDK_ASSERT(SF_FACTOR == 3);
+ factor = (FIXP_DBL)
+ MAXVAL_DBL; /* avoid warning: FL2FXCONST_DBL(8.0f/SCALE_FACTOR) */
+ } else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ else
+ factor = (fMult(FL2FXCONST_DBL(7.0f / 24.0f), ottVsTotDb) +
+ FL2FXCONST_DBL((17.0f / 24.0f) / SCALE_CLD_C1C2))
+ << (SF_CLD_C1C2 - SF_FACTOR);
+ break;
+ default:
+ factor = FL2FXCONST_DBL(0.0f);
+ }
+
+ return (factor);
+}
+
+/*******************************************************************************
+ Functionname: factorCLD
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void factorCLD(SCHAR *idx, FIXP_DBL ottVsTotDb, FIXP_DBL *ottVsTotDb1,
+ FIXP_DBL *ottVsTotDb2, SCHAR ottVsTotDbMode,
+ INT quantMode) {
+ FIXP_DBL factor;
+ FIXP_DBL cldIdxFract;
+ INT cldIdx;
+
+ factor = factorFunct(ottVsTotDb, quantMode);
+
+ cldIdxFract =
+ fMult((FIXP_DBL)((*idx) << ((DFRACT_BITS - 1) - SF_IDX)), factor);
+ cldIdxFract += FL2FXCONST_DBL(15.5f / (1 << (SF_FACTOR + SF_IDX)));
+ cldIdx = fixp_truncateToInt(cldIdxFract, SF_FACTOR + SF_IDX);
+
+ cldIdx = fMin(cldIdx, 30);
+ cldIdx = fMax(cldIdx, 0);
+
+ *idx = cldIdx - 15;
+
+ if (ottVsTotDbMode & ottVsTotDb1Activ)
+ (*ottVsTotDb1) = ottVsTotDb + dequantCLD_c1[cldIdx];
+
+ if (ottVsTotDbMode & ottVsTotDb2Activ)
+ (*ottVsTotDb2) = ottVsTotDb + dequantCLD_c1[30 - cldIdx];
+}
+
+/*******************************************************************************
+ Functionname: mapIndexData
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR mapIndexData(
+ LOSSLESSDATA *llData, SCHAR ***outputDataIdx, SCHAR ***outputIdxData,
+ const SCHAR (*cmpIdxData)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ SCHAR ***diffIdxData, SCHAR xttIdx, SCHAR **idxPrev, int paramIdx,
+ int paramType, int startBand, int stopBand, SCHAR defaultValue,
+ int numParameterSets, const int *paramSlot, int extendFrame, int quantMode,
+ SpatialDecConcealmentInfo *concealmentInfo, SCHAR ottVsTotDbMode,
+ FIXP_DBL (*pOttVsTotDbIn)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ FIXP_DBL (*pOttVsTotDb1)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ FIXP_DBL (*pOttVsTotDb2)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) {
+ int aParamSlots[MAX_PARAMETER_SETS];
+ int aInterpolate[MAX_PARAMETER_SETS];
+
+ int dataSets;
+ int aMap[MAX_PARAMETER_BANDS + 1];
+
+ int setIdx, i, band, parmSlot;
+ int dataBands;
+ int ps, pb;
+ int i1;
+
+ if (numParameterSets > MAX_PARAMETER_SETS) return MPS_WRONG_PARAMETERSETS;
+
+ dataSets = 0;
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 3) {
+ aParamSlots[dataSets] = i;
+ dataSets++;
+ }
+ }
+
+ setIdx = 0;
+
+ /* Main concealment stage is here: */
+ SpatialDecConcealment_Apply(
+ concealmentInfo, cmpIdxData[xttIdx],
+ (diffIdxData != NULL) ? diffIdxData[xttIdx] : NULL, idxPrev[xttIdx],
+ llData->bsXXXDataMode, startBand, stopBand, defaultValue, paramType,
+ numParameterSets);
+
+ /* Prepare data */
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 0) {
+ llData->nocmpQuantCoarseXXX[i] = 0;
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = defaultValue;
+ }
+ for (band = startBand; band < stopBand; band++) {
+ idxPrev[xttIdx][band] = outputIdxData[xttIdx][i][band];
+ }
+ /* Because the idxPrev are also set to the defaultValue -> signalize fine
+ */
+ llData->state->bsQuantCoarseXXXprev = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 1) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band];
+ }
+ llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev;
+ }
+
+ if (llData->bsXXXDataMode[i] == 2) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band];
+ }
+ llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev;
+ aInterpolate[i] = 1;
+ } else {
+ aInterpolate[i] = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ int stride;
+
+ parmSlot = aParamSlots[setIdx];
+ stride = pbStrideTable[llData->bsFreqResStrideXXX[setIdx]];
+ dataBands = (stopBand - startBand - 1) / stride + 1;
+ createMapping(aMap, startBand, stopBand, stride);
+ mapFrequency(&cmpIdxData[xttIdx][setIdx][0],
+ &outputIdxData[xttIdx][parmSlot][0], aMap, dataBands);
+ for (band = startBand; band < stopBand; band++) {
+ idxPrev[xttIdx][band] = outputIdxData[xttIdx][parmSlot][band];
+ }
+ llData->state->bsQuantCoarseXXXprev = llData->bsQuantCoarseXXX[setIdx];
+ llData->nocmpQuantCoarseXXX[i] = llData->bsQuantCoarseXXX[setIdx];
+
+ setIdx++;
+ }
+ if (diffIdxData != NULL) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] += diffIdxData[xttIdx][i][band];
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ /* Map all coarse data to fine */
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->nocmpQuantCoarseXXX[i] == 1) {
+ coarse2fine(outputIdxData[xttIdx][i], (DATA_TYPE)paramType, startBand,
+ stopBand - startBand);
+ llData->nocmpQuantCoarseXXX[i] = 0;
+ }
+ }
+
+ /* Interpolate */
+ i1 = 0;
+ for (i = 0; i < numParameterSets; i++) {
+ int xi, i2, x1, x2;
+
+ if (aInterpolate[i] != 1) {
+ i1 = i;
+ }
+ i2 = i;
+ while (aInterpolate[i2] == 1) {
+ i2++;
+ }
+ x1 = paramSlot[i1];
+ xi = paramSlot[i];
+ x2 = paramSlot[i2];
+
+ if (aInterpolate[i] == 1) {
+ if (i2 >= numParameterSets) return MPS_WRONG_PARAMETERSETS;
+ for (band = startBand; band < stopBand; band++) {
+ int yi, y1, y2;
+ y1 = outputIdxData[xttIdx][i1][band];
+ y2 = outputIdxData[xttIdx][i2][band];
+ if (x1 != x2) {
+ yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1);
+ } else {
+ yi = y1 /*+ (xi-x1)*(y2-y1)/1e-12*/;
+ }
+ outputIdxData[xttIdx][i][band] = yi;
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ /* Dequantize data and apply factorCLD if necessary */
+ for (ps = 0; ps < numParameterSets; ps++) {
+ if (quantMode && (paramType == t_CLD)) {
+ if (pOttVsTotDbIn == 0) return MPS_WRONG_OTT;
+ if ((pOttVsTotDb1 == 0) && (ottVsTotDbMode == ottVsTotDb1Activ))
+ return MPS_WRONG_OTT;
+ if ((pOttVsTotDb2 == 0) && (ottVsTotDbMode == ottVsTotDb2Activ))
+ return MPS_WRONG_OTT;
+
+ for (pb = startBand; pb < stopBand; pb++) {
+ factorCLD(&(outputIdxData[xttIdx][ps][pb]), (*pOttVsTotDbIn)[ps][pb],
+ (pOttVsTotDb1 != NULL) ? &((*pOttVsTotDb1)[ps][pb]) : NULL,
+ (pOttVsTotDb2 != NULL) ? &((*pOttVsTotDb2)[ps][pb]) : NULL,
+ ottVsTotDbMode, quantMode);
+ }
+ }
+
+ /* Dequantize data */
+ for (band = startBand; band < stopBand; band++) {
+ outputDataIdx[xttIdx][ps][band] =
+ deqIdx(outputIdxData[xttIdx][ps][band], paramType);
+ if (outputDataIdx[xttIdx][ps][band] == -1) {
+ outputDataIdx[xttIdx][ps][band] = defaultValue;
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ if (extendFrame) {
+ for (band = startBand; band < stopBand; band++) {
+ outputDataIdx[xttIdx][numParameterSets][band] =
+ outputDataIdx[xttIdx][numParameterSets - 1][band];
+ }
+ }
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameOtt
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameOtt(HANDLE_SPATIAL_DEC self,
+ SPATIAL_BS_FRAME *pCurBs) {
+ int i, ottIdx;
+ int numOttBoxes;
+
+ SACDEC_ERROR err = MPS_OK;
+
+ numOttBoxes = self->numOttBoxes;
+
+ switch (self->treeConfig) {
+ default: {
+ if (self->quantMode != 0) {
+ goto bail;
+ }
+ }
+ for (i = 0; i < numOttBoxes; i++) {
+ err = mapIndexData(
+ &pCurBs->CLDLosslessData[i], /* LOSSLESSDATA *llData,*/
+ self->ottCLD__FDK, self->outIdxData,
+ pCurBs
+ ->cmpOttCLDidx, /* int
+ cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ */
+ NULL, /* no differential data */
+ i, /* int xttIdx, Which ott/ttt index to use for input and
+ output buffers */
+ self->ottCLDidxPrev, /* int
+ idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS],
+ */
+ i, t_CLD, 0, /* int startBand, */
+ self->pConfigCurrent->bitstreamOttBands[i], /* int stopBand, */
+ self->pConfigCurrent->ottCLDdefault[i], /* int defaultValue, */
+ pCurBs->numParameterSets, /* int numParameterSets) */
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+
+ } /* for(i = 0; i < numOttBoxes ; i++ ) */
+ break;
+ } /* case */
+
+ for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) {
+ /* Read ICC */
+ err = mapIndexData(
+ &pCurBs->ICCLosslessData[ottIdx], /* LOSSLESSDATA *llData,*/
+ self->ottICC__FDK, self->outIdxData,
+ pCurBs
+ ->cmpOttICCidx, /* int
+ cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ */
+ self->ottICCdiffidx, /* differential data */
+ ottIdx, /* int xttIdx, Which ott/ttt index to use for input and
+ output buffers */
+ self->ottICCidxPrev, /* int idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS],
+ */
+ ottIdx, t_ICC, 0, /* int startBand, */
+ self->pConfigCurrent->bitstreamOttBands[ottIdx], /* int stopBand, */
+ ICCdefault, /* int defaultValue, */
+ pCurBs->numParameterSets, /* int numParameterSets) */
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+ } /* ottIdx */
+
+ if ((self->treeConfig == TREE_212) && (self->phaseCoding)) {
+ if (pCurBs->phaseMode == 0) {
+ for (int pb = 0; pb < self->pConfigCurrent->numOttBandsIPD; pb++) {
+ self->ottIPDidxPrev[0][pb] = 0;
+ }
+ }
+ for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) {
+ err = mapIndexData(
+ &pCurBs->IPDLosslessData[ottIdx], self->ottIPD__FDK, self->outIdxData,
+ pCurBs->cmpOttIPDidx, NULL, ottIdx, self->ottIPDidxPrev, ottIdx,
+ t_IPD, 0, self->numOttBandsIPD, IPDdefault, pCurBs->numParameterSets,
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ }
+ }
+
+bail:
+
+ return MPS_OK;
+
+} /* decodeAndMapFrameOtt */
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameSmg
+ *******************************************************************************
+
+ Description:
+ Decode smoothing flags
+
+ Arguments:
+
+Input:
+
+Output:
+
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameSmg(HANDLE_SPATIAL_DEC self,
+ const SPATIAL_BS_FRAME *frame) {
+ int ps, pb, pg, pbStride, dataBands, pbStart, pbStop,
+ aGroupToBand[MAX_PARAMETER_BANDS + 1];
+
+ if (frame->numParameterSets > MAX_PARAMETER_SETS)
+ return MPS_WRONG_PARAMETERSETS;
+ if (self->bitstreamParameterBands > MAX_PARAMETER_BANDS)
+ return MPS_WRONG_PARAMETERBANDS;
+
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ switch (frame->bsSmoothMode[ps]) {
+ case 0:
+ self->smgTime[ps] = 256;
+ FDKmemclear(self->smgData[ps],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ break;
+
+ case 1:
+ if (ps > 0) {
+ self->smgTime[ps] = self->smgTime[ps - 1];
+ FDKmemcpy(self->smgData[ps], self->smgData[ps - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ } else {
+ self->smgTime[ps] = self->smoothState->prevSmgTime;
+ FDKmemcpy(self->smgData[ps], self->smoothState->prevSmgData,
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ }
+ break;
+
+ case 2:
+ self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]];
+ for (pb = 0; pb < self->bitstreamParameterBands; pb++) {
+ self->smgData[ps][pb] = 1;
+ }
+ break;
+
+ case 3:
+ self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]];
+ pbStride = pbStrideTable[frame->bsFreqResStrideSmg[ps]];
+ dataBands = (self->bitstreamParameterBands - 1) / pbStride + 1;
+ createMapping(aGroupToBand, 0, self->bitstreamParameterBands, pbStride);
+ for (pg = 0; pg < dataBands; pg++) {
+ pbStart = aGroupToBand[pg];
+ pbStop = aGroupToBand[pg + 1];
+ for (pb = pbStart; pb < pbStop; pb++) {
+ self->smgData[ps][pb] = frame->bsSmgData[ps][pg];
+ }
+ }
+ break;
+ }
+ }
+
+ self->smoothState->prevSmgTime = self->smgTime[frame->numParameterSets - 1];
+ FDKmemcpy(self->smoothState->prevSmgData,
+ self->smgData[frame->numParameterSets - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+
+ if (self->extendFrame) {
+ self->smgTime[frame->numParameterSets] =
+ self->smgTime[frame->numParameterSets - 1];
+ FDKmemcpy(self->smgData[frame->numParameterSets],
+ self->smgData[frame->numParameterSets - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ }
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameArbdmx
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameArbdmx(HANDLE_SPATIAL_DEC self,
+ const SPATIAL_BS_FRAME *frame) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+ int offset = self->numOttBoxes;
+
+ for (ch = 0; ch < self->numInputChannels; ch++) {
+ err = mapIndexData(&frame->CLDLosslessData[offset + ch],
+ self->arbdmxGain__FDK, self->outIdxData,
+ frame->cmpArbdmxGainIdx, NULL, /* no differential data */
+ ch, self->arbdmxGainIdxPrev, offset + ch, t_CLD, 0,
+ self->bitstreamParameterBands,
+ 0 /*self->arbdmxGainDefault*/, frame->numParameterSets,
+ frame->paramSlot, self->extendFrame, 0,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+ }
+
+bail:
+ return err;
+} /* decodeAndMapFrameArbdmx */
+
+/*******************************************************************************
+ Functionname: SpatialDecDecodeFrame
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame) {
+ SACDEC_ERROR err = MPS_OK;
+
+ self->extendFrame = 0;
+ if (frame->paramSlot[frame->numParameterSets - 1] != self->timeSlots - 1) {
+ self->extendFrame = 1;
+ }
+
+ self->TsdTs = 0;
+
+ /****** DTDF and MAP DATA ********/
+ if ((err = decodeAndMapFrameOtt(self, frame)) != MPS_OK) goto bail;
+
+ if ((err = decodeAndMapFrameSmg(self, frame)) != MPS_OK) goto bail;
+
+ if (self->arbitraryDownmix != 0) {
+ if ((err = decodeAndMapFrameArbdmx(self, frame)) != MPS_OK) goto bail;
+ }
+
+ if (self->extendFrame) {
+ frame->numParameterSets =
+ fixMin(MAX_PARAMETER_SETS, frame->numParameterSets + 1);
+ frame->paramSlot[frame->numParameterSets - 1] = self->timeSlots - 1;
+ }
+
+bail:
+ return err;
+} /* SpatialDecDecodeFrame() */
+
+/*******************************************************************************
+ Functionname: SpatialDecodeHeader
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+SACDEC_ERROR SpatialDecDecodeHeader(
+ spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig) {
+ SACDEC_ERROR err = MPS_OK;
+ int i;
+
+ self->samplingFreq = pSpatialSpecificConfig->samplingFreq;
+ self->timeSlots = pSpatialSpecificConfig->nTimeSlots;
+ self->frameLength = self->timeSlots * self->qmfBands;
+ self->bitstreamParameterBands = pSpatialSpecificConfig->freqRes;
+
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)
+ self->hybridBands = self->qmfBands;
+ else
+ self->hybridBands = SacGetHybridSubbands(self->qmfBands);
+ self->tp_hybBandBorder = 12;
+
+ self->numParameterBands = self->bitstreamParameterBands;
+
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
+ switch (self->numParameterBands) {
+ case 4:
+ self->kernels = kernels_4_to_64;
+ break;
+ case 5:
+ self->kernels = kernels_5_to_64;
+ break;
+ case 7:
+ self->kernels = kernels_7_to_64;
+ break;
+ case 9:
+ self->kernels = kernels_9_to_64;
+ break;
+ case 12:
+ self->kernels = kernels_12_to_64;
+ break;
+ case 15:
+ self->kernels = kernels_15_to_64;
+ break;
+ case 23:
+ self->kernels = kernels_23_to_64;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */
+ }
+ } else {
+ switch (self->numParameterBands) {
+ case 4:
+ self->kernels = kernels_4_to_71;
+ break;
+ case 5:
+ self->kernels = kernels_5_to_71;
+ break;
+ case 7:
+ self->kernels = kernels_7_to_71;
+ break;
+ case 10:
+ self->kernels = kernels_10_to_71;
+ break;
+ case 14:
+ self->kernels = kernels_14_to_71;
+ break;
+ case 20:
+ self->kernels = kernels_20_to_71;
+ break;
+ case 28:
+ self->kernels = kernels_28_to_71;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */
+ }
+ }
+
+ /* create param to hyb band table */
+ FDKmemclear(self->param2hyb, (MAX_PARAMETER_BANDS + 1) * sizeof(int));
+ for (i = 0; i < self->hybridBands; i++) {
+ self->param2hyb[self->kernels[i] + 1] = i + 1;
+ }
+ {
+ int pb = self->kernels[i - 1] + 2;
+ for (; pb < (MAX_PARAMETER_BANDS + 1); pb++) {
+ self->param2hyb[pb] = i;
+ }
+ for (pb = 0; pb < MAX_PARAMETER_BANDS; pb += 1) {
+ self->kernels_width[pb] = self->param2hyb[pb + 1] - self->param2hyb[pb];
+ }
+ }
+
+ self->treeConfig = pSpatialSpecificConfig->treeConfig;
+
+ self->numOttBoxes = pSpatialSpecificConfig->nOttBoxes;
+
+ self->numInputChannels = pSpatialSpecificConfig->nInputChannels;
+
+ self->numOutputChannels = pSpatialSpecificConfig->nOutputChannels;
+
+ self->quantMode = pSpatialSpecificConfig->quantMode;
+
+ self->arbitraryDownmix = pSpatialSpecificConfig->bArbitraryDownmix;
+
+ self->numM2rows = self->numOutputChannels;
+
+ {
+ self->residualCoding = 0;
+ if (self->arbitraryDownmix == 2)
+ self->arbitraryDownmix = 1; /* no arbitrary downmix residuals */
+ }
+ if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ self->residualCoding = pSpatialSpecificConfig->bResidualCoding;
+ }
+
+ self->clipProtectGain__FDK =
+ FX_CFG2FX_DBL(clipGainTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]);
+ self->clipProtectGainSF__FDK =
+ clipGainSFTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX];
+
+ self->tempShapeConfig = pSpatialSpecificConfig->tempShapeConfig;
+
+ self->decorrConfig = pSpatialSpecificConfig->decorrConfig;
+
+ if (self->upmixType == UPMIXTYPE_BYPASS) {
+ self->numOutputChannels = self->numInputChannels;
+ }
+
+ self->numOutputChannelsAT = self->numOutputChannels;
+
+ self->numOttBandsIPD = pSpatialSpecificConfig->numOttBandsIPD;
+ self->phaseCoding = pSpatialSpecificConfig->bsPhaseCoding;
+ for (i = 0; i < self->numOttBoxes; i++) {
+ {
+ self->pConfigCurrent->bitstreamOttBands[i] =
+ self->bitstreamParameterBands;
+ }
+ self->numOttBands[i] = self->pConfigCurrent->bitstreamOttBands[i];
+ } /* i */
+
+ if (self->residualCoding) {
+ int numBoxes = self->numOttBoxes;
+ for (i = 0; i < numBoxes; i++) {
+ self->residualPresent[i] =
+ pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent;
+
+ if (self->residualPresent[i]) {
+ self->residualBands[i] =
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands;
+ /* conversion from hybrid bands to qmf bands */
+ self->residualQMFBands[i] =
+ fMax(self->param2hyb[self->residualBands[i]] + 3 - 10,
+ 3); /* simplification for the lowest 10 hybrid bands */
+ } else {
+ self->residualBands[i] = 0;
+ self->residualQMFBands[i] = 0;
+ }
+ }
+ } /* self->residualCoding */
+ else {
+ int boxes = self->numOttBoxes;
+ for (i = 0; i < boxes; i += 1) {
+ self->residualPresent[i] = 0;
+ self->residualBands[i] = 0;
+ }
+ }
+
+ switch (self->treeConfig) {
+ case TREE_212:
+ self->numDirektSignals = 1;
+ self->numDecorSignals = 1;
+ self->numXChannels = 1;
+ if (self->arbitraryDownmix == 2) {
+ self->numXChannels += 1;
+ }
+ self->numVChannels = self->numDirektSignals + self->numDecorSignals;
+ break;
+ default:
+ return MPS_INVALID_TREECONFIG;
+ }
+
+ self->highRateMode = pSpatialSpecificConfig->bsHighRateMode;
+ self->decorrType = pSpatialSpecificConfig->bsDecorrType;
+
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCreateBsFrame
+ *******************************************************************************
+
+ Description: Create spatial bitstream structure
+
+ Arguments: spatialDec* self
+ const SPATIAL_BS_FRAME **bsFrame
+
+ Return: -
+
+*******************************************************************************/
+SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame,
+ BS_LL_STATE *llState) {
+ SPATIAL_BS_FRAME *pBs = bsFrame;
+
+ const int maxNumOtt = MAX_NUM_OTT;
+ const int maxNumInputChannels = MAX_INPUT_CHANNELS;
+
+ FDK_ALLOCATE_MEMORY_1D_P(
+ pBs->cmpOttIPDidx, maxNumOtt * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS,
+ SCHAR, SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS])
+
+ /* Arbitrary Downmix */
+ FDK_ALLOCATE_MEMORY_1D_P(
+ pBs->cmpArbdmxGainIdx,
+ maxNumInputChannels * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, SCHAR,
+ SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS])
+
+ /* Lossless control */
+ FDK_ALLOCATE_MEMORY_1D(pBs->CLDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+ FDK_ALLOCATE_MEMORY_1D(pBs->ICCLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+
+ FDK_ALLOCATE_MEMORY_1D(pBs->IPDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+
+ pBs->newBsData = 0;
+ pBs->numParameterSets = 1;
+
+ /* Link lossless states */
+ for (int x = 0; x < MAX_NUM_PARAMETERS; x++) {
+ pBs->CLDLosslessData[x].state = &llState->CLDLosslessState[x];
+ pBs->ICCLosslessData[x].state = &llState->ICCLosslessState[x];
+
+ pBs->IPDLosslessData[x].state = &llState->IPDLosslessState[x];
+ }
+
+ return MPS_OK;
+
+bail:
+ return MPS_OUTOFMEMORY;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCloseBsFrame
+ *******************************************************************************
+
+ Description: Close spatial bitstream structure
+
+ Arguments: spatialDec* self
+
+ Return: -
+
+*******************************************************************************/
+void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *pBs) {
+ if (pBs != NULL) {
+ /* These arrays contain the compact indices, only one value per pbstride,
+ * only paramsets actually containing data. */
+
+ FDK_FREE_MEMORY_1D(pBs->cmpOttIPDidx);
+
+ /* Arbitrary Downmix */
+ FDK_FREE_MEMORY_1D(pBs->cmpArbdmxGainIdx);
+
+ /* Lossless control */
+ FDK_FREE_MEMORY_1D(pBs->IPDLosslessData);
+ FDK_FREE_MEMORY_1D(pBs->CLDLosslessData);
+ FDK_FREE_MEMORY_1D(pBs->ICCLosslessData);
+ }
+}