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/libSACdec/src/sac_bitdec.cpp | 2167 ++++++++++++++++++++++++++++++++++ 1 file changed, 2167 insertions(+) create mode 100644 fdk-aac/libSACdec/src/sac_bitdec.cpp (limited to 'fdk-aac/libSACdec/src/sac_bitdec.cpp') diff --git a/fdk-aac/libSACdec/src/sac_bitdec.cpp b/fdk-aac/libSACdec/src/sac_bitdec.cpp new file mode 100644 index 0000000..883e1e8 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_bitdec.cpp @@ -0,0 +1,2167 @@ +/* ----------------------------------------------------------------------------- +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 = (INT)FDKgetValidBits(bitstream); + + err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig, + sacHeaderLen, coreCodec); + + numFillBits -= + (INT)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; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + 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; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + 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); + if (pSpatialSpecificConfig->tempShapeConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + 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; + if (bitsAvailable < 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + + pSpatialSpecificConfig->sacExtCnt = 0; + pSpatialSpecificConfig->bResidualCoding = 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; + + for (int p = 0; p < frame->numParameterSets; p++) { + if (frame->paramSlot[p] > self->timeSlots - 1) { + frame->paramSlot[p] = self->timeSlots - 1; + err = MPS_PARSE_ERROR; + } + } + if (err != MPS_OK) { + goto bail; + } + } + +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); + } +} -- cgit v1.2.3