aboutsummaryrefslogtreecommitdiffstats
path: root/libSACdec/src/sac_dec.cpp
diff options
context:
space:
mode:
authorFraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de>2018-02-26 20:17:00 +0100
committerJean-Michel Trivi <jmtrivi@google.com>2018-04-19 11:21:15 -0700
commit6cfabd35363c3ef5e3b209b867169a500b3ccc3c (patch)
tree01c0a19f2735e8b5d2407555fe992d4230d089eb /libSACdec/src/sac_dec.cpp
parent6288a1e34c4dede4c2806beb1736ece6580558c7 (diff)
downloadfdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.gz
fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.bz2
fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.zip
Upgrade to FDKv2
Bug: 71430241 Test: CTS DecoderTest and DecoderTestAacDrc original-Change-Id: Iaa20f749b8a04d553b20247cfe1a8930ebbabe30 Apply clang-format also on header files. original-Change-Id: I14de1ef16bbc79ec0283e745f98356a10efeb2e4 Fixes for MPEG-D DRC original-Change-Id: If1de2d74bbbac84b3f67de3b88b83f6a23b8a15c Catch unsupported tw_mdct at an early stage original-Change-Id: Ied9dd00d754162a0e3ca1ae3e6b854315d818afe Fixing PVC transition frames original-Change-Id: Ib75725abe39252806c32d71176308f2c03547a4e Move qmf bands sanity check original-Change-Id: Iab540c3013c174d9490d2ae100a4576f51d8dbc4 Initialize scaling variable original-Change-Id: I3c4087101b70e998c71c1689b122b0d7762e0f9e Add 16 qmf band configuration to getSlotNrgHQ() original-Change-Id: I49a5d30f703a1b126ff163df9656db2540df21f1 Always apply byte alignment at the end of the AudioMuxElement original-Change-Id: I42d560287506d65d4c3de8bfe3eb9a4ebeb4efc7 Setup SBR element only if no parse error exists original-Change-Id: I1915b73704bc80ab882b9173d6bec59cbd073676 Additional array index check in HCR original-Change-Id: I18cc6e501ea683b5009f1bbee26de8ddd04d8267 Fix fade-in index selection in concealment module original-Change-Id: Ibf802ed6ed8c05e9257e1f3b6d0ac1162e9b81c1 Enable explicit backward compatible parser for AAC_LD original-Change-Id: I27e9c678dcb5d40ed760a6d1e06609563d02482d Skip spatial specific config in explicit backward compatible ASC original-Change-Id: Iff7cc365561319e886090cedf30533f562ea4d6e Update flags description in decoder API original-Change-Id: I9a5b4f8da76bb652f5580cbd3ba9760425c43830 Add QMF domain reset function original-Change-Id: I4f89a8a2c0277d18103380134e4ed86996e9d8d6 DRC upgrade v2.1.0 original-Change-Id: I5731c0540139dab220094cd978ef42099fc45b74 Fix integer overflow in sqrtFixp_lookup() original-Change-Id: I429a6f0d19aa2cc957e0f181066f0ca73968c914 Fix integer overflow in invSqrtNorm2() original-Change-Id: I84de5cbf9fb3adeb611db203fe492fabf4eb6155 Fix integer overflow in GenerateRandomVector() original-Change-Id: I3118a641008bd9484d479e5b0b1ee2b5d7d44d74 Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I29d503c247c5c8282349b79df940416a512fb9d5 Fix integer overflow in FDKsbrEnc_codeEnvelope() original-Change-Id: I6b34b61ebb9d525b0c651ed08de2befc1f801449 Follow-up on: Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I6f8f578cc7089e5eb7c7b93e580b72ca35ad689a Fix integer overflow in get_pk_v2() original-Change-Id: I63375bed40d45867f6eeaa72b20b1f33e815938c Fix integer overflow in Syn_filt_zero() original-Change-Id: Ie0c02fdfbe03988f9d3b20d10cd9fe4c002d1279 Fix integer overflow in CFac_CalcFacSignal() original-Change-Id: Id2d767c40066c591b51768e978eb8af3b803f0c5 Fix integer overflow in FDKaacEnc_FDKaacEnc_calcPeNoAH() original-Change-Id: Idcbd0f4a51ae2550ed106aa6f3d678d1f9724841 Fix integer overflow in sbrDecoder_calculateGainVec() original-Change-Id: I7081bcbe29c5cede9821b38d93de07c7add2d507 Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4a95ddc18de150102352d4a1845f06094764c881 Fix integer overflow in Pred_Lt4() original-Change-Id: I4dbd012b2de7d07c3e70a47b92e3bfae8dbc750a Fix integer overflow in FDKsbrEnc_InitSbrFastTransientDetector() original-Change-Id: I788cbec1a4a00f44c2f3a72ad7a4afa219807d04 Fix unsigned integer overflow in FDKaacEnc_WriteBitstream() original-Change-Id: I68fc75166e7d2cd5cd45b18dbe3d8c2a92f1822a Fix unsigned integer overflow in FDK_MetadataEnc_Init() original-Change-Id: Ie8d025f9bcdb2442c704bd196e61065c03c10af4 Fix overflow in pseudo random number generators original-Change-Id: I3e2551ee01356297ca14e3788436ede80bd5513c Fix unsigned integer overflow in sbrDecoder_Parse() original-Change-Id: I3f231b2f437e9c37db4d5b964164686710eee971 Fix unsigned integer overflow in longsub() original-Change-Id: I73c2bc50415cac26f1f5a29e125bbe75f9180a6e Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: Ifce2db4b1454b46fa5f887e9d383f1cc43b291e4 Fix overflow at CLpdChannelStream_Read() original-Change-Id: Idb9d822ce3a4272e4794b643644f5434e2d4bf3f Fix unsigned integer overflow in Hcr_State_BODY_SIGN_ESC__ESC_WORD() original-Change-Id: I1ccf77c0015684b85534c5eb97162740a870b71c Fix unsigned integer overflow in UsacConfig_Parse() original-Change-Id: Ie6d27f84b6ae7eef092ecbff4447941c77864d9f Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I713f28e883eea3d70b6fa56a7b8f8c22bcf66ca0 Fix unsigned integer overflow in aacDecoder_drcReadCompression() original-Change-Id: Ia34dfeb88c4705c558bce34314f584965cafcf7a Fix unsigned integer overflow in CDataStreamElement_Read() original-Change-Id: Iae896cc1d11f0a893d21be6aa90bd3e60a2c25f0 Fix unsigned integer overflow in transportDec_AdjustEndOfAccessUnit() original-Change-Id: I64cf29a153ee784bb4a16fdc088baabebc0007dc Fix unsigned integer overflow in transportDec_GetAuBitsRemaining() original-Change-Id: I975b3420faa9c16a041874ba0db82e92035962e4 Fix unsigned integer overflow in extractExtendedData() original-Change-Id: I2a59eb09e2053cfb58dfb75fcecfad6b85a80a8f Fix signed integer overflow in CAacDecoder_ExtPayloadParse() original-Change-Id: I4ad5ca4e3b83b5d964f1c2f8c5e7b17c477c7929 Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: I29a39df77d45c52a0c9c5c83c1ba81f8d0f25090 Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I8fb194ffc073a3432a380845be71036a272d388f Fix signed integer overflow in _interpolateDrcGain() original-Change-Id: I879ec9ab14005069a7c47faf80e8bc6e03d22e60 Fix unsigned integer overflow in FDKreadBits() original-Change-Id: I1f47a6a8037ff70375aa8844947d5681bb4287ad Fix unsigned integer overflow in FDKbyteAlign() original-Change-Id: Id5f3a11a0c9e50fc6f76ed6c572dbd4e9f2af766 Fix unsigned integer overflow in FDK_get32() original-Change-Id: I9d33b8e97e3d38cbb80629cb859266ca0acdce96 Fix unsigned integer overflow in FDK_pushBack() original-Change-Id: Ic87f899bc8c6acf7a377a8ca7f3ba74c3a1e1c19 Fix unsigned integer overflow in FDK_pushForward() original-Change-Id: I3b754382f6776a34be1602e66694ede8e0b8effc Fix unsigned integer overflow in ReadPsData() original-Change-Id: I25361664ba8139e32bbbef2ca8c106a606ce9c37 Fix signed integer overflow in E_UTIL_residu() original-Change-Id: I8c3abd1f437ee869caa8fb5903ce7d3d641b6aad REVERT: Follow-up on: Integer overflow in CLpc_SynthesisLattice(). original-Change-Id: I3d340099acb0414795c8dfbe6362bc0a8f045f9b Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4aedb8b3a187064e9f4d985175aa55bb99cc7590 Follow-up on: Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I2aa2e13916213bf52a67e8b0518e7bf7e57fb37d Fix integer overflow in acelp original-Change-Id: Ie6390c136d84055f8b728aefbe4ebef6e029dc77 Fix unsigned integer overflow in aacDecoder_UpdateBitStreamCounters() original-Change-Id: I391ffd97ddb0b2c184cba76139bfb356a3b4d2e2 Adjust concealment default settings original-Change-Id: I6a95db935a327c47df348030bcceafcb29f54b21 Saturate estimatedStartPos original-Change-Id: I27be2085e0ae83ec9501409f65e003f6bcba1ab6 Negative shift exponent in _interpolateDrcGain() original-Change-Id: I18edb26b26d002aafd5e633d4914960f7a359c29 Negative shift exponent in calculateICC() original-Change-Id: I3dcd2ae98d2eb70ee0d59750863cbb2a6f4f8aba Too large shift exponent in FDK_put() original-Change-Id: Ib7d9aaa434d2d8de4a13b720ca0464b31ca9b671 Too large shift exponent in CalcInvLdData() original-Change-Id: I43e6e78d4cd12daeb1dcd5d82d1798bdc2550262 Member access within null pointer of type SBR_CHANNEL original-Change-Id: Idc5e4ea8997810376d2f36bbdf628923b135b097 Member access within null pointer of type CpePersistentData original-Change-Id: Ib6c91cb0d37882768e5baf63324e429589de0d9d Member access within null pointer FDKaacEnc_psyMain() original-Change-Id: I7729b7f4479970531d9dc823abff63ca52e01997 Member access within null pointer FDKaacEnc_GetPnsParam() original-Change-Id: I9aa3b9f3456ae2e0f7483dbd5b3dde95fc62da39 Member access within null pointer FDKsbrEnc_EnvEncodeFrame() original-Change-Id: I67936f90ea714e90b3e81bc0dd1472cc713eb23a Add HCR sanity check original-Change-Id: I6c1d9732ebcf6af12f50b7641400752f74be39f7 Fix memory issue for HBE edge case with 8:3 SBR original-Change-Id: I11ea58a61e69fbe8bf75034b640baee3011e63e9 Additional SBR parametrization sanity check for ELD original-Change-Id: Ie26026fbfe174c2c7b3691f6218b5ce63e322140 Add MPEG-D DRC channel layout check original-Change-Id: Iea70a74f171b227cce636a9eac4ba662777a2f72 Additional out-of-bounds checks in MPEG-D DRC original-Change-Id: Ife4a8c3452c6fde8a0a09e941154a39a769777d4 Change-Id: Ic63cb2f628720f54fe9b572b0cb528e2599c624e
Diffstat (limited to 'libSACdec/src/sac_dec.cpp')
-rw-r--r--libSACdec/src/sac_dec.cpp1509
1 files changed, 1509 insertions, 0 deletions
diff --git a/libSACdec/src/sac_dec.cpp b/libSACdec/src/sac_dec.cpp
new file mode 100644
index 0000000..4537d6e
--- /dev/null
+++ b/libSACdec/src/sac_dec.cpp
@@ -0,0 +1,1509 @@
+/* -----------------------------------------------------------------------------
+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 Decoder Library
+
+*******************************************************************************/
+
+#include "sac_dec_errorcodes.h"
+#include "sac_dec.h"
+
+#include "sac_process.h"
+#include "sac_bitdec.h"
+#include "sac_smoothing.h"
+#include "sac_calcM1andM2.h"
+#include "sac_reshapeBBEnv.h"
+#include "sac_stp.h"
+#include "sac_rom.h"
+
+#include "FDK_decorrelate.h"
+
+#include "FDK_trigFcts.h"
+#include "FDK_matrixCalloc.h"
+
+/* static int pbStrideTable[] = {1, 2, 5, 28}; see sac_rom.cpp */
+
+enum {
+ APPLY_M2_NONE = 0, /* init value */
+ APPLY_M2 = 1, /* apply m2 fallback implementation */
+ APPLY_M2_MODE212 = 2, /* apply m2 for 212 mode */
+ APPLY_M2_MODE212_Res_PhaseCoding =
+ 3 /* apply m2 for 212 mode with residuals and phase coding */
+};
+
+/******************************************************************************************/
+/* function: FDK_SpatialDecInitDefaultSpatialSpecificConfig */
+/* output: struct of type SPATIAL_SPECIFIC_CONFIG */
+/* input: core coder audio object type */
+/* input: nr of core channels */
+/* input: sampling rate */
+/* input: nr of time slots */
+/* input: decoder level */
+/* input: flag indicating upmix type blind */
+/* */
+/* returns: error code */
+/******************************************************************************************/
+int FDK_SpatialDecInitDefaultSpatialSpecificConfig(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq,
+ int nTimeSlots, int decoderLevel, int isBlind) {
+ return SpatialDecDefaultSpecificConfig(pSpatialSpecificConfig, coreCodec,
+ samplingFreq, nTimeSlots, decoderLevel,
+ isBlind, coreChannels);
+}
+
+/******************************************************************************************/
+/* function: FDK_SpatialDecCompareSpatialSpecificConfigHeader */
+/* input: 2 pointers to a ssc */
+/* */
+/* output: - */
+/* returns: error code (0 = equal, <>0 unequal) */
+/******************************************************************************************/
+int FDK_SpatialDecCompareSpatialSpecificConfigHeader(
+ SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2) {
+ int result = MPS_OK;
+
+ /* we assume: every bit must be equal */
+ if (FDKmemcmp(pSsc1, pSsc2, sizeof(SPATIAL_SPECIFIC_CONFIG)) != 0) {
+ result = MPS_UNEQUAL_SSC;
+ }
+ return result;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecClearFrameData
+ *******************************************************************************
+
+ Description: Clear/Fake frame data to avoid misconfiguration and allow proper
+ error concealment.
+ Arguments:
+ Input: self (frame data)
+ Output: No return value.
+
+*******************************************************************************/
+static void SpatialDecClearFrameData(
+ spatialDec *self, /* Shall be removed */
+ SPATIAL_BS_FRAME *bsFrame, const SACDEC_CREATION_PARAMS *const setup) {
+ int i;
+
+ FDK_ASSERT(self != NULL);
+ FDK_ASSERT(bsFrame != NULL);
+ FDK_ASSERT(setup != NULL);
+
+ /* do not apply shaping tools (GES or STP) */
+ for (i = 0; i < setup->maxNumOutputChannels;
+ i += 1) { /* MAX_OUTPUT_CHANNELS */
+ bsFrame->tempShapeEnableChannelSTP[i] = 0;
+ bsFrame->tempShapeEnableChannelGES[i] = 0;
+ }
+
+ bsFrame->TsdData->bsTsdEnable = 0;
+
+ /* use only 1 parameter set at the end of the frame */
+ bsFrame->numParameterSets = 1;
+ bsFrame->paramSlot[0] = self->timeSlots - 1;
+
+ /* parameter smoothing tool set to off */
+ bsFrame->bsSmoothMode[0] = 0;
+
+ /* reset residual data */
+ {
+ int resQmfBands, resTimeSlots = (1);
+
+ resQmfBands = setup->maxNumQmfBands;
+
+ for (i = 0; i < setup->bProcResidual
+ ? fMin(setup->maxNumResChannels,
+ setup->maxNumOttBoxes + setup->maxNumInputChannels)
+ : 0;
+ i += 1) {
+ for (int j = 0; j < resTimeSlots; j += 1) {
+ for (int k = 0; k < resQmfBands; k += 1) {
+ self->qmfResidualReal__FDK[i][j][k] = FL2FXCONST_DBL(0.0f);
+ self->qmfResidualImag__FDK[i][j][k] = FL2FXCONST_DBL(0.0f);
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+ Functionname: FDK_SpatialDecOpen
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config,
+ int stereoConfigIndex) {
+ int i;
+ int lfSize, hfSize;
+ spatialDec *self = NULL;
+ SACDEC_CREATION_PARAMS setup;
+
+ switch (config->decoderLevel) {
+ case DECODER_LEVEL_0: /* 212 maxNumOutputChannels== 2 */
+ setup.maxNumInputChannels = 1;
+ setup.maxNumOutputChannels = 2;
+ setup.maxNumQmfBands = 64;
+ setup.maxNumXChannels = 2;
+ setup.maxNumVChannels = 2;
+ setup.maxNumDecorChannels = 1;
+ setup.bProcResidual = 1;
+ setup.maxNumResidualChannels = 0;
+ setup.maxNumOttBoxes = 1;
+ setup.maxNumParams = setup.maxNumInputChannels + setup.maxNumOttBoxes;
+ break;
+ default:
+ return NULL;
+ }
+
+ setup.maxNumResChannels = 1;
+
+ {
+ switch (config->maxNumOutputChannels) {
+ case OUTPUT_CHANNELS_2_0:
+ setup.maxNumOutputChannels = fMin(setup.maxNumOutputChannels, 2);
+ break;
+ case OUTPUT_CHANNELS_DEFAULT:
+ default:
+ break;
+ }
+ }
+
+ setup.maxNumHybridBands = SacGetHybridSubbands(setup.maxNumQmfBands);
+
+ switch (config->decoderMode) {
+ case EXT_HQ_ONLY:
+ setup.maxNumCmplxQmfBands = setup.maxNumQmfBands;
+ setup.maxNumCmplxHybBands = setup.maxNumHybridBands;
+ break;
+ default:
+ setup.maxNumCmplxQmfBands = fixMax(PC_NUM_BANDS, setup.maxNumQmfBands);
+ setup.maxNumCmplxHybBands =
+ fixMax(PC_NUM_HYB_BANDS, setup.maxNumHybridBands);
+ break;
+ } /* switch config->decoderMode */
+
+ FDK_ALLOCATE_MEMORY_1D_INT(self, 1, spatialDec, SECT_DATA_L2)
+
+ self->createParams = setup;
+
+ FDK_ALLOCATE_MEMORY_1D(self->param2hyb, MAX_PARAMETER_BANDS + 1, int)
+
+ FDK_ALLOCATE_MEMORY_1D(self->numOttBands, setup.maxNumOttBoxes, int)
+
+ /* allocate arrays */
+
+ FDK_ALLOCATE_MEMORY_1D(self->smgTime, MAX_PARAMETER_SETS, int)
+ FDK_ALLOCATE_MEMORY_2D(self->smgData, MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS,
+ UCHAR)
+
+ FDK_ALLOCATE_MEMORY_3D(self->ottCLD__FDK, setup.maxNumOttBoxes,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_3D(self->ottICC__FDK, setup.maxNumOttBoxes,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_3D(self->ottIPD__FDK, setup.maxNumOttBoxes,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+
+ /* Last parameters from prev frame */
+ FDK_ALLOCATE_MEMORY_2D(self->ottCLDidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_2D(self->ottICCidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_3D(self->ottICCdiffidx, setup.maxNumOttBoxes,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_2D(self->ottIPDidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_2D(self->arbdmxGainIdxPrev, setup.maxNumInputChannels,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_2D(self->cmpOttCLDidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_2D(self->cmpOttICCidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_3D(self->outIdxData, setup.maxNumOttBoxes,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+
+ FDK_ALLOCATE_MEMORY_3D(self->arbdmxGain__FDK, setup.maxNumInputChannels,
+ MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
+ FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlpha__FDK, setup.maxNumInputChannels,
+ FIXP_DBL)
+ FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlphaPrev__FDK, setup.maxNumInputChannels,
+ FIXP_DBL)
+ FDK_ALLOCATE_MEMORY_2D(self->cmpArbdmxGainIdxPrev, setup.maxNumInputChannels,
+ MAX_PARAMETER_BANDS, SCHAR)
+
+ FDK_ALLOCATE_MEMORY_2D(self->cmpOttIPDidxPrev, setup.maxNumOttBoxes,
+ MAX_PARAMETER_BANDS, SCHAR)
+
+ FDK_ALLOCATE_MEMORY_3D_INT(self->M2Real__FDK, setup.maxNumOutputChannels,
+ setup.maxNumVChannels, MAX_PARAMETER_BANDS,
+ FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_3D(self->M2Imag__FDK, setup.maxNumOutputChannels,
+ setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL)
+
+ FDK_ALLOCATE_MEMORY_3D_INT(self->M2RealPrev__FDK, setup.maxNumOutputChannels,
+ setup.maxNumVChannels, MAX_PARAMETER_BANDS,
+ FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_3D(self->M2ImagPrev__FDK, setup.maxNumOutputChannels,
+ setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL)
+
+ FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(
+ self->qmfInputReal__FDK, setup.maxNumInputChannels, setup.maxNumQmfBands,
+ FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(
+ self->qmfInputImag__FDK, setup.maxNumInputChannels,
+ setup.maxNumCmplxQmfBands, FIXP_DBL, SECT_DATA_L2)
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputReal__FDK, setup.maxNumInputChannels,
+ setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputImag__FDK, setup.maxNumInputChannels,
+ setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
+
+ if (setup.bProcResidual) {
+ FDK_ALLOCATE_MEMORY_1D(self->qmfResidualReal__FDK, setup.maxNumResChannels,
+ FIXP_DBL **)
+ FDK_ALLOCATE_MEMORY_1D(self->qmfResidualImag__FDK, setup.maxNumResChannels,
+ FIXP_DBL **)
+
+ FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK, setup.maxNumResChannels,
+ FIXP_DBL *)
+ FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK, setup.maxNumResChannels,
+ FIXP_DBL *)
+
+ for (i = 0; i < setup.maxNumResChannels; i++) {
+ int resQmfBands = (config->decoderMode == EXT_LP_ONLY)
+ ? PC_NUM_BANDS
+ : setup.maxNumQmfBands;
+ int resHybBands = (config->decoderMode == EXT_LP_ONLY)
+ ? PC_NUM_HYB_BANDS
+ : setup.maxNumHybridBands;
+ /* Alignment is needed for USAC residuals because QMF analysis directly
+ * writes to this buffer. */
+ FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualReal__FDK[i], (1),
+ resQmfBands, FIXP_DBL, SECT_DATA_L1)
+ FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualImag__FDK[i], (1),
+ resQmfBands, FIXP_DBL, SECT_DATA_L1)
+
+ FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK[i],
+ setup.maxNumHybridBands, FIXP_DBL)
+ FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK[i], resHybBands,
+ FIXP_DBL)
+ }
+ } /* if (setup.bProcResidual) */
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->wReal__FDK, setup.maxNumVChannels,
+ setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D_INT(self->wImag__FDK, setup.maxNumVChannels,
+ setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealDry__FDK,
+ setup.maxNumOutputChannels,
+ setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagDry__FDK,
+ setup.maxNumOutputChannels,
+ setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealWet__FDK,
+ setup.maxNumOutputChannels,
+ setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagWet__FDK,
+ setup.maxNumOutputChannels,
+ setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
+
+ FDK_ALLOCATE_MEMORY_1D(self->hybridSynthesis, setup.maxNumOutputChannels,
+ FDK_SYN_HYB_FILTER)
+
+ FDK_ALLOCATE_MEMORY_1D(
+ self->hybridAnalysis,
+ setup.bProcResidual ? setup.maxNumInputChannels + setup.maxNumResChannels
+ : setup.maxNumInputChannels,
+ FDK_ANA_HYB_FILTER)
+
+ lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID;
+ {
+ hfSize =
+ BUFFER_LEN_HF * ((setup.maxNumQmfBands - MAX_QMF_BANDS_TO_HYBRID) +
+ (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID));
+ }
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFdmx,
+ setup.maxNumInputChannels, lfSize, FIXP_DBL,
+ SECT_DATA_L2) {
+ FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFdmx,
+ setup.maxNumInputChannels, hfSize, FIXP_DBL)
+ }
+
+ for (i = 0; i < setup.maxNumInputChannels; i++) {
+ FIXP_DBL *pHybridAnaStatesHFdmx;
+
+ pHybridAnaStatesHFdmx = self->pHybridAnaStatesHFdmx[i];
+
+ FDKhybridAnalysisOpen(&self->hybridAnalysis[i],
+ self->pHybridAnaStatesLFdmx[i],
+ lfSize * sizeof(FIXP_DBL), pHybridAnaStatesHFdmx,
+ hfSize * sizeof(FIXP_DBL));
+ }
+ if (setup.bProcResidual) {
+ lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID;
+ hfSize = BUFFER_LEN_HF *
+ ((((config->decoderMode == EXT_LP_ONLY) ? PC_NUM_BANDS
+ : setup.maxNumQmfBands) -
+ MAX_QMF_BANDS_TO_HYBRID) +
+ (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID));
+
+ FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFres,
+ setup.maxNumResChannels, lfSize, FIXP_DBL,
+ SECT_DATA_L2)
+ FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFres, setup.maxNumResChannels,
+ hfSize, FIXP_DBL)
+
+ for (i = setup.maxNumInputChannels;
+ i < (setup.maxNumInputChannels + setup.maxNumResChannels); i++) {
+ FDKhybridAnalysisOpen(
+ &self->hybridAnalysis[i],
+ self->pHybridAnaStatesLFres[i - setup.maxNumInputChannels],
+ lfSize * sizeof(FIXP_DBL),
+ self->pHybridAnaStatesHFres[i - setup.maxNumInputChannels],
+ hfSize * sizeof(FIXP_DBL));
+ }
+ }
+
+ FDK_ALLOCATE_MEMORY_1D(self->smoothState, 1, SMOOTHING_STATE)
+ FDK_ALLOCATE_MEMORY_1D(self->reshapeBBEnvState, 1, RESHAPE_BBENV_STATE)
+
+ FDK_ALLOCATE_MEMORY_1D(self->apDecor, setup.maxNumDecorChannels, DECORR_DEC)
+ FDK_ALLOCATE_MEMORY_2D_INT(self->pDecorBufferCplx, setup.maxNumDecorChannels,
+ (2 * ((825) + (373))), FIXP_DBL, SECT_DATA_L2)
+
+ for (i = 0; i < setup.maxNumDecorChannels; i++) {
+ if (FDKdecorrelateOpen(&self->apDecor[i], self->pDecorBufferCplx[i],
+ (2 * ((825) + (373))))) {
+ goto bail;
+ }
+ }
+
+ if (subbandTPCreate(&self->hStpDec) != MPS_OK) {
+ goto bail;
+ }
+
+ /* save general decoder configuration */
+ self->decoderLevel = config->decoderLevel;
+ self->decoderMode = config->decoderMode;
+ self->binauralMode = config->binauralMode;
+
+ /* preinitialize configuration */
+ self->partiallyComplex = (config->decoderMode != EXT_HQ_ONLY) ? 1 : 0;
+
+ /* Set to default state */
+ SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_ALL);
+
+ /* Everything is fine so return the handle */
+ return self;
+
+bail:
+ /* Collector for all errors.
+ Deallocate all memory and return a invalid handle. */
+ FDK_SpatialDecClose(self);
+
+ return NULL;
+}
+
+/*******************************************************************************
+ Functionname: isValidConfig
+ *******************************************************************************
+
+ Description: Validate if configuration is supported in present instance
+
+ Arguments:
+
+ Return: 1: all okay
+ 0: configuration not supported
+*******************************************************************************/
+static int isValidConfig(spatialDec const *const self,
+ const SPATIAL_DEC_UPMIX_TYPE upmixType,
+ SPATIALDEC_PARAM const *const pUserParams,
+ const AUDIO_OBJECT_TYPE coreAot) {
+ UPMIXTYPE nUpmixType;
+
+ FDK_ASSERT(self != NULL);
+ FDK_ASSERT(pUserParams != NULL);
+
+ nUpmixType = (UPMIXTYPE)upmixType;
+
+ switch (nUpmixType) {
+ case UPMIXTYPE_BYPASS: /* UPMIX_TYPE_BYPASS */
+ break;
+ case UPMIXTYPE_NORMAL: /* UPMIX_TYPE_NORMAL */
+ break;
+ default:
+ return 0; /* unsupported upmixType */
+ }
+
+ return 1; /* upmixType supported */
+}
+
+static SACDEC_ERROR CheckLevelTreeUpmixType(
+ const SACDEC_CREATION_PARAMS *const pCreateParams,
+ const SPATIAL_SPECIFIC_CONFIG *const pSsc, const int decoderLevel,
+ const UPMIXTYPE upmixType) {
+ SACDEC_ERROR err = MPS_OK;
+ int nOutputChannels, treeConfig;
+
+ FDK_ASSERT(pCreateParams != NULL);
+ FDK_ASSERT(pSsc != NULL);
+
+ treeConfig = pSsc->treeConfig;
+
+ switch (decoderLevel) {
+ case 0: {
+ if (treeConfig != SPATIALDEC_MODE_RSVD7) {
+ err = MPS_INVALID_TREECONFIG;
+ goto bail;
+ }
+ break;
+ }
+ default:
+ err = MPS_INVALID_PARAMETER /* MPS_UNIMPLEMENTED */;
+ goto bail;
+ }
+
+ switch (upmixType) {
+ case UPMIXTYPE_BYPASS:
+ nOutputChannels = pSsc->nInputChannels;
+ break;
+ default:
+ nOutputChannels = pSsc->nOutputChannels;
+ break;
+ }
+
+ /* Is sufficient memory allocated. */
+ if ((pSsc->nInputChannels > pCreateParams->maxNumInputChannels) ||
+ (nOutputChannels > pCreateParams->maxNumOutputChannels) ||
+ (pSsc->nOttBoxes > pCreateParams->maxNumOttBoxes)) {
+ err = MPS_INVALID_PARAMETER;
+ }
+
+bail:
+ return err;
+}
+
+void SpatialDecInitParserContext(spatialDec *self) {
+ int i, j;
+
+ for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) {
+ for (j = 0; j < MAX_PARAMETER_BANDS; j++) {
+ self->ottCLDidxPrev[i][j] = 0;
+ self->ottICCidxPrev[i][j] = 0;
+ self->cmpOttCLDidxPrev[i][j] = 0;
+ self->cmpOttICCidxPrev[i][j] = 0;
+ }
+ }
+ for (i = 0; i < self->createParams.maxNumInputChannels; i++) {
+ for (j = 0; j < MAX_PARAMETER_BANDS; j++) {
+ self->arbdmxGainIdxPrev[i][j] = 0;
+ self->cmpArbdmxGainIdxPrev[i][j] = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: FDK_SpatialDecInit
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ int nQmfBands,
+ SPATIAL_DEC_UPMIX_TYPE const upmixType,
+ SPATIALDEC_PARAM *pUserParams, UINT initFlags) {
+ SACDEC_ERROR err = MPS_OK;
+ int nCh, i, j, k;
+ int maxQmfBands;
+ int bypassMode = 0;
+
+ self->useFDreverb = 0;
+
+ /* check configuration parameter */
+ if (!isValidConfig(self, upmixType, pUserParams,
+ pSpatialSpecificConfig->coreCodec)) {
+ return MPS_INVALID_PARAMETER;
+ }
+
+ /* check tree configuration */
+ err = CheckLevelTreeUpmixType(&self->createParams, pSpatialSpecificConfig,
+ self->decoderLevel, (UPMIXTYPE)upmixType);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+ /* Store and update instance after all checks passed successfully: */
+ self->upmixType = (UPMIXTYPE)upmixType;
+
+ if (initFlags & MPEGS_INIT_PARAMS_ERROR_CONCEALMENT) { /* At least one error
+ concealment
+ parameter changed */
+ err = SpatialDecConcealment_SetParam(
+ &self->concealInfo, SAC_DEC_CONCEAL_METHOD, pUserParams->concealMethod);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ err = SpatialDecConcealment_SetParam(&self->concealInfo,
+ SAC_DEC_CONCEAL_NUM_KEEP_FRAMES,
+ pUserParams->concealNumKeepFrames);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ err = SpatialDecConcealment_SetParam(
+ &self->concealInfo, SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH,
+ pUserParams->concealFadeOutSlopeLength);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ err = SpatialDecConcealment_SetParam(&self->concealInfo,
+ SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH,
+ pUserParams->concealFadeInSlopeLength);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ err = SpatialDecConcealment_SetParam(&self->concealInfo,
+ SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES,
+ pUserParams->concealNumReleaseFrames);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ }
+
+ if (initFlags &
+ MPEGS_INIT_STATES_ERROR_CONCEALMENT) { /* Set to default state */
+ SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_STATE);
+ }
+
+ /* determine bypass mode */
+ bypassMode |= pUserParams->bypassMode;
+ bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0);
+
+ /* static decoder scale depends on number of qmf bands */
+ switch (nQmfBands) {
+ case 16:
+ case 24:
+ case 32:
+ self->staticDecScale = 21;
+ break;
+ case 64:
+ self->staticDecScale = 22;
+ break;
+ default:
+ return MPS_INVALID_PARAMETER;
+ }
+
+ self->numParameterSetsPrev = 1;
+
+ self->qmfBands = nQmfBands;
+ /* self->hybridBands will be updated in SpatialDecDecodeHeader() below. */
+
+ self->bShareDelayWithSBR = 0;
+
+ err = SpatialDecDecodeHeader(self, pSpatialSpecificConfig);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+ self->stereoConfigIndex = pSpatialSpecificConfig->stereoConfigIndex;
+
+ if (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) {
+ self->qmfInputDelayBufPos = 0;
+ self->pc_filterdelay = 1; /* Division by 0 not possible */
+ }
+
+ maxQmfBands = self->qmfBands;
+
+ /* init residual decoder */
+
+ /* init tonality smoothing */
+ if (initFlags & MPEGS_INIT_STATES_PARAM) {
+ initParameterSmoothing(self);
+ }
+
+ /* init GES */
+ initBBEnv(self, (initFlags & MPEGS_INIT_STATES_GES) ? 1 : 0);
+
+ /* Clip protection is applied only for normal processing. */
+ if (!isTwoChMode(self->upmixType) && !bypassMode) {
+ self->staticDecScale += self->clipProtectGainSF__FDK;
+ }
+
+ {
+ UINT flags = 0;
+ INT initStatesFlag = (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) ? 1 : 0;
+ INT useLdFilter =
+ (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) ? 1 : 0;
+
+ flags = self->pQmfDomain->globalConf.flags_requested;
+ flags &= (~(UINT)QMF_FLAG_LP);
+
+ if (initStatesFlag)
+ flags &= ~QMF_FLAG_KEEP_STATES;
+ else
+ flags |= QMF_FLAG_KEEP_STATES;
+
+ if (useLdFilter)
+ flags |= QMF_FLAG_MPSLDFB;
+ else
+ flags &= ~QMF_FLAG_MPSLDFB;
+
+ self->pQmfDomain->globalConf.flags_requested = flags;
+ FDK_QmfDomain_Configure(self->pQmfDomain);
+
+ /* output scaling */
+ for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) {
+ int outputScale = 0, outputGain_e = 0, scale = 0;
+ FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e);
+
+ if (!isTwoChMode(self->upmixType) && !bypassMode) {
+ outputScale +=
+ self->clipProtectGainSF__FDK; /* consider clip protection scaling at
+ synthesis qmf */
+ }
+
+ scale = outputScale;
+
+ qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale);
+ qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m,
+ outputGain_e);
+ }
+ }
+
+ for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) {
+ FDKhybridSynthesisInit(&self->hybridSynthesis[nCh], THREE_TO_TEN,
+ self->qmfBands, maxQmfBands);
+ }
+
+ /* for input, residual channels and arbitrary down-mix residual channels */
+ for (nCh = 0; nCh < self->createParams.maxNumInputChannels; nCh++) {
+ FDKhybridAnalysisInit(
+ &self->hybridAnalysis[nCh], THREE_TO_TEN, self->qmfBands, maxQmfBands,
+ (initFlags & MPEGS_INIT_STATES_ANA_HYB_FILTER) ? 1 : 0);
+ }
+ for (; nCh < (self->createParams.bProcResidual
+ ? (self->createParams.maxNumInputChannels +
+ self->createParams.maxNumResChannels)
+ : self->createParams.maxNumInputChannels);
+ nCh++) {
+ FDKhybridAnalysisInit(&self->hybridAnalysis[nCh], THREE_TO_TEN, maxQmfBands,
+ maxQmfBands, 0);
+ }
+
+ {
+ for (k = 0; k < self->numDecorSignals; k++) {
+ int errCode, idec;
+ FDK_DECORR_TYPE decorrType = DECORR_PS;
+ decorrType = DECORR_LD;
+ if (self->pConfigCurrent->syntaxFlags &
+ (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) {
+ decorrType =
+ ((self->treeConfig == TREE_212) && (self->decorrType == DECORR_PS))
+ ? DECORR_PS
+ : DECORR_USAC;
+ }
+ {
+ idec = k;
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
+ if (self->treeConfig == TREE_212 && k == 0) {
+ idec = 2;
+ }
+ }
+ }
+ errCode = FDKdecorrelateInit(
+ &self->apDecor[k], self->hybridBands, decorrType, DUCKER_AUTOMATIC,
+ self->decorrConfig, idec, 0, /* self->partiallyComplex */
+ 0, 0, /* isLegacyPS */
+ (initFlags & MPEGS_INIT_STATES_DECORRELATOR) ? 1 : 0);
+ if (errCode) return MPS_NOTOK;
+ }
+ } /* !self->partiallyComplex */
+
+ err = initM1andM2(self, (initFlags & MPEGS_INIT_STATES_M1M2) ? 1 : 0,
+ (initFlags & MPEGS_INIT_CONFIG) ? 1 : 0);
+ if (err != MPS_OK) return err;
+
+ /* Initialization of previous frame data */
+ if (initFlags & MPEGS_INIT_STATES_PARAM) {
+ for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) {
+ /* reset icc diff data */
+ for (k = 0; k < MAX_PARAMETER_SETS; k += 1) {
+ for (j = 0; j < MAX_PARAMETER_BANDS; j += 1) {
+ self->ottICCdiffidx[i][k][j] = 0;
+ }
+ }
+ }
+ /* Parameter Smoothing */
+ /* robustness: init with one of the values of smgTimeTable[] = {64, 128,
+ 256, 512} to avoid division by zero in calcFilterCoeff__FDK() */
+ self->smoothState->prevSmgTime = smgTimeTable[2]; /* == 256 */
+ FDKmemclear(self->smoothState->prevSmgData,
+ MAX_PARAMETER_BANDS * sizeof(UCHAR));
+ FDKmemclear(self->smoothState->opdLeftState__FDK,
+ MAX_PARAMETER_BANDS * sizeof(FIXP_DBL));
+ FDKmemclear(self->smoothState->opdRightState__FDK,
+ MAX_PARAMETER_BANDS * sizeof(FIXP_DBL));
+ }
+
+ self->prevTimeSlot = -1;
+ self->curTimeSlot =
+ MAX_TIME_SLOTS + 1; /* Initialize with a invalid value to trigger
+ concealment if first frame has no valid data. */
+ self->curPs = 0;
+
+ subbandTPInit(self->hStpDec);
+
+bail:
+ return err;
+}
+
+void SpatialDecChannelProperties(spatialDec *self,
+ AUDIO_CHANNEL_TYPE channelType[],
+ UCHAR channelIndices[],
+ const FDK_channelMapDescr *const mapDescr) {
+ if ((self == NULL) || (channelType == NULL) || (channelIndices == NULL) ||
+ (mapDescr == NULL)) {
+ return; /* no extern buffer to be filled */
+ }
+
+ if (self->numOutputChannelsAT !=
+ treePropertyTable[self->treeConfig].numOutputChannels) {
+ int ch;
+ /* Declare all channels to be front channels: */
+ for (ch = 0; ch < self->numOutputChannelsAT; ch += 1) {
+ channelType[ch] = ACT_FRONT;
+ channelIndices[ch] = ch;
+ }
+ } else {
+ /* ISO/IEC FDIS 23003-1:2006(E), page 46, Table 40 bsTreeConfig */
+ switch (self->treeConfig) {
+ case TREE_212:
+ channelType[0] = ACT_FRONT;
+ channelIndices[0] = 0;
+ channelType[1] = ACT_FRONT;
+ channelIndices[1] = 1;
+ break;
+ default:;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: FDK_SpatialDecClose
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+void FDK_SpatialDecClose(spatialDec *self) {
+ if (self) {
+ int k;
+
+ if (self->apDecor != NULL) {
+ for (k = 0; k < self->createParams.maxNumDecorChannels; k++) {
+ FDKdecorrelateClose(&(self->apDecor[k]));
+ }
+ FDK_FREE_MEMORY_1D(self->apDecor);
+ }
+ if (self->pDecorBufferCplx != NULL) {
+ FDK_FREE_MEMORY_2D(self->pDecorBufferCplx);
+ }
+
+ subbandTPDestroy(&self->hStpDec);
+
+ FDK_FREE_MEMORY_1D(self->reshapeBBEnvState);
+ FDK_FREE_MEMORY_1D(self->smoothState);
+
+ FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFdmx);
+ FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFdmx);
+ FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFres);
+ FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFres);
+ FDK_FREE_MEMORY_1D(self->hybridAnalysis);
+
+ FDK_FREE_MEMORY_1D(self->hybridSynthesis);
+
+ /* The time buffer is passed to the decoder from outside to avoid copying
+ * (zero copy). */
+ /* FDK_FREE_MEMORY_2D(self->timeOut__FDK); */
+
+ FDK_FREE_MEMORY_2D(self->hybOutputImagWet__FDK);
+ FDK_FREE_MEMORY_2D(self->hybOutputRealWet__FDK);
+
+ FDK_FREE_MEMORY_2D(self->hybOutputImagDry__FDK);
+ FDK_FREE_MEMORY_2D(self->hybOutputRealDry__FDK);
+
+ FDK_FREE_MEMORY_2D(self->wImag__FDK);
+ FDK_FREE_MEMORY_2D(self->wReal__FDK);
+
+ if (self->createParams.bProcResidual) {
+ int i;
+
+ for (i = 0; i < self->createParams.maxNumResChannels; i++) {
+ if (self->hybResidualImag__FDK != NULL)
+ FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK[i]);
+ if (self->hybResidualReal__FDK != NULL)
+ FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK[i]);
+ if (self->qmfResidualImag__FDK != NULL)
+ FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualImag__FDK[i]);
+ if (self->qmfResidualReal__FDK != NULL)
+ FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualReal__FDK[i]);
+ }
+
+ FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK);
+ FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK);
+
+ FDK_FREE_MEMORY_1D(self->qmfResidualImag__FDK);
+ FDK_FREE_MEMORY_1D(self->qmfResidualReal__FDK);
+
+ } /* self->createParams.bProcResidual */
+
+ FDK_FREE_MEMORY_2D(self->hybInputImag__FDK);
+ FDK_FREE_MEMORY_2D(self->hybInputReal__FDK);
+
+ FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputImag__FDK);
+ FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputReal__FDK);
+
+ FDK_FREE_MEMORY_3D(self->M2ImagPrev__FDK);
+
+ FDK_FREE_MEMORY_3D(self->M2RealPrev__FDK);
+
+ FDK_FREE_MEMORY_3D(self->M2Imag__FDK);
+
+ FDK_FREE_MEMORY_3D(self->M2Real__FDK);
+
+ FDK_FREE_MEMORY_1D(self->arbdmxAlphaPrev__FDK);
+ FDK_FREE_MEMORY_1D(self->arbdmxAlpha__FDK);
+
+ FDK_FREE_MEMORY_3D(self->arbdmxGain__FDK);
+
+ FDK_FREE_MEMORY_3D(self->ottIPD__FDK);
+ FDK_FREE_MEMORY_3D(self->ottICC__FDK);
+ FDK_FREE_MEMORY_3D(self->ottCLD__FDK);
+
+ /* Last parameters from prev frame */
+ FDK_FREE_MEMORY_2D(self->ottCLDidxPrev);
+ FDK_FREE_MEMORY_2D(self->ottICCidxPrev);
+ FDK_FREE_MEMORY_3D(self->ottICCdiffidx);
+ FDK_FREE_MEMORY_2D(self->ottIPDidxPrev);
+ FDK_FREE_MEMORY_2D(self->arbdmxGainIdxPrev);
+
+ FDK_FREE_MEMORY_2D(self->cmpOttCLDidxPrev);
+ FDK_FREE_MEMORY_2D(self->cmpOttICCidxPrev);
+ FDK_FREE_MEMORY_3D(self->outIdxData);
+ FDK_FREE_MEMORY_2D(self->cmpOttIPDidxPrev);
+ FDK_FREE_MEMORY_2D(self->cmpArbdmxGainIdxPrev);
+
+ FDK_FREE_MEMORY_2D(self->smgData);
+ FDK_FREE_MEMORY_1D(self->smgTime);
+
+ FDK_FREE_MEMORY_1D(self->numOttBands);
+
+ FDK_FREE_MEMORY_1D(self->param2hyb);
+
+ FDK_FREE_MEMORY_1D(self);
+ }
+
+ return;
+}
+
+/**
+ * \brief Apply Surround bypass buffer copies
+ * \param self spatialDec handle
+ * \param hybInputReal
+ * \param hybInputImag
+ * \param hybOutputReal
+ * \param hybOutputImag
+ * \param numInputChannels amount if input channels available in hybInputReal
+ * and hybInputImag, which may differ from self->numInputChannels.
+ */
+static void SpatialDecApplyBypass(spatialDec *self, FIXP_DBL **hybInputReal,
+ FIXP_DBL **hybInputImag,
+ FIXP_DBL **hybOutputReal,
+ FIXP_DBL **hybOutputImag,
+ const int numInputChannels) {
+ int complexHybBands;
+
+ complexHybBands = self->hybridBands;
+
+ {
+ int ch;
+ int rf = -1, lf = -1, cf = -1; /* Right Front, Left Front, Center Front */
+
+ /* Determine output channel indices according to tree config */
+ switch (self->treeConfig) {
+ case TREE_212: /* 212 */
+ lf = 0;
+ rf = 1;
+ break;
+ default:;
+ }
+
+ /* Note: numInputChannels might not match the tree config ! */
+ switch (numInputChannels) {
+ case 1:
+ if (cf > 0) {
+ FDKmemcpy(hybOutputReal[cf], hybInputReal[0],
+ self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputImag[cf], hybInputImag[0],
+ complexHybBands * sizeof(FIXP_DBL));
+ } else {
+ FDKmemcpy(hybOutputReal[lf], hybInputReal[0],
+ self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputReal[rf], hybInputReal[0],
+ self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputImag[lf], hybInputImag[0],
+ complexHybBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputImag[rf], hybInputImag[0],
+ complexHybBands * sizeof(FIXP_DBL));
+ }
+ break;
+ case 2:
+ FDK_ASSERT(lf != -1);
+ FDK_ASSERT(rf != -1);
+ FDKmemcpy(hybOutputReal[lf], hybInputReal[0],
+ self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputReal[rf], hybInputReal[1],
+ self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputImag[lf], hybInputImag[0],
+ complexHybBands * sizeof(FIXP_DBL));
+ FDKmemcpy(hybOutputImag[rf], hybInputImag[1],
+ complexHybBands * sizeof(FIXP_DBL));
+ break;
+ }
+ for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
+ if (ch == lf || ch == rf || ch == cf) {
+ continue; /* Skip bypassed channels */
+ }
+ FDKmemclear(hybOutputReal[ch], self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemclear(hybOutputImag[ch], complexHybBands * sizeof(FIXP_DBL));
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecApplyParameterSets
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR SpatialDecApplyParameterSets(
+ spatialDec *self, const SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE mode,
+ PCM_MPS *inData, /* Time domain input */
+ FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */
+ FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */
+ UINT nSamples, UINT controlFlags, int numInputChannels,
+ const FDK_channelMapDescr *const mapDescr) {
+ SACDEC_ERROR err = MPS_OK;
+
+ FIXP_SGL alpha;
+
+ int ts;
+ int ch;
+ int hyb;
+
+ int prevSlot = self->prevTimeSlot;
+ int ps = self->curPs;
+ int ts_io = 0; /* i/o dependent slot */
+ int bypassMode = (controlFlags & MPEGS_BYPASSMODE) ? 1 : 0;
+
+ /* Bypass can be triggered by the upmixType, too. */
+ bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0);
+
+ /*
+ * Decode available slots
+ */
+ for (ts = self->curTimeSlot;
+ ts <= fixMin(self->curTimeSlot + (int)nSamples / self->qmfBands - 1,
+ self->timeSlots - 1);
+ ts++, ts_io++) {
+ int currSlot = frame->paramSlot[ps];
+
+ /*
+ * Get new parameter set
+ */
+ if (ts == prevSlot + 1) {
+ err = SpatialDecCalculateM1andM2(self, ps,
+ frame); /* input: ottCLD, ottICC, ... */
+ /* output: M1param(Real/Imag), M2(Real/Imag) */
+ if (err != MPS_OK) {
+ bypassMode = 1;
+ if (self->errInt == MPS_OK) {
+ /* store internal error befor it gets overwritten */
+ self->errInt = err;
+ }
+ err = MPS_OK;
+ }
+
+ if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) {
+ /* copy matrix entries of M1/M2 of the first parameter set to the
+ previous matrices (of the last frame). This avoids the interpolation
+ of incompatible values. E.g. for residual bands the coefficients are
+ calculated differently compared to non-residual bands.
+ */
+ SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */
+ /* output: M(1/2)param(Real/Imag)Prev */
+ self->bOverwriteM1M2prev = 0;
+ }
+
+ SpatialDecSmoothM1andM2(
+ self, frame,
+ ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
+ /* output: M1param(Real/Imag), M2(Real/Imag) */
+ }
+
+ alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
+
+ switch (mode) {
+ case INPUTMODE_QMF_SBR:
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)
+ self->bShareDelayWithSBR = 0; /* We got no hybrid delay */
+ else
+ self->bShareDelayWithSBR = 1;
+ SpatialDecFeedQMF(self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
+ self->qmfInputReal__FDK, self->qmfInputImag__FDK,
+ self->numInputChannels);
+ break;
+ case INPUTMODE_TIME:
+ self->bShareDelayWithSBR = 0;
+ SpatialDecQMFAnalysis(self, inData, ts_io, bypassMode,
+ self->qmfInputReal__FDK, self->qmfInputImag__FDK,
+ self->numInputChannels);
+ break;
+ default:
+ break;
+ }
+
+ if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
+ self->residualCoding) {
+ int offset;
+ ch = 1;
+
+ offset = self->pQmfDomain->globalConf.nBandsSynthesis *
+ self->pQmfDomain->globalConf.nQmfTimeSlots;
+
+ {
+ const PCM_MPS *inSamples =
+ &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
+
+ CalculateSpaceAnalysisQmf(
+ &self->pQmfDomain->QmfDomainIn[ch].fb, inSamples + (ch * offset),
+ self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0]);
+
+ if (!isTwoChMode(self->upmixType) && !bypassMode) {
+ int i;
+ FIXP_DBL *RESTRICT self_qmfResidualReal__FDK_0_0 =
+ &self->qmfResidualReal__FDK[0][0][0];
+ FIXP_DBL *RESTRICT self_qmfResidualImag__FDK_0_0 =
+ &self->qmfResidualImag__FDK[0][0][0];
+
+ if ((self->pQmfDomain->globalConf.nBandsAnalysis == 24) &&
+ !(self->stereoConfigIndex == 3)) {
+ for (i = 0; i < self->qmfBands; i++) {
+ self_qmfResidualReal__FDK_0_0[i] =
+ fMult(self_qmfResidualReal__FDK_0_0[i] << 1,
+ self->clipProtectGain__FDK);
+ self_qmfResidualImag__FDK_0_0[i] =
+ fMult(self_qmfResidualImag__FDK_0_0[i] << 1,
+ self->clipProtectGain__FDK);
+ }
+ } else {
+ for (i = 0; i < self->qmfBands; i++) {
+ self_qmfResidualReal__FDK_0_0[i] = fMult(
+ self_qmfResidualReal__FDK_0_0[i], self->clipProtectGain__FDK);
+ self_qmfResidualImag__FDK_0_0[i] = fMult(
+ self_qmfResidualImag__FDK_0_0[i], self->clipProtectGain__FDK);
+ }
+ }
+ }
+ }
+ }
+
+ SpatialDecHybridAnalysis(
+ self, /* input: qmfInput(Real/Imag), qmfResidual(Real/Imag) */
+ self->qmfInputReal__FDK, self->qmfInputImag__FDK,
+ self->hybInputReal__FDK, self->hybInputImag__FDK, ts, numInputChannels);
+
+ if (bypassMode) {
+ SpatialDecApplyBypass(
+ self, self->hybInputReal__FDK, /* input: hybInput(Real/Imag) */
+ self->hybInputImag__FDK,
+ self->hybOutputRealDry__FDK, /* output: hybOutput(Real/Imag)Dry */
+ self->hybOutputImagDry__FDK, numInputChannels);
+ } else /* !bypassMode */
+ {
+ FIXP_DBL *pxReal[MAX_NUM_XCHANNELS] = {NULL};
+ FIXP_DBL *pxImag[MAX_NUM_XCHANNELS] = {NULL};
+
+ SpatialDecCreateX(self,
+ self->hybInputReal__FDK, /* input: hybInput(Real/Imag),
+ hybResidual(Real/Imag) */
+ self->hybInputImag__FDK, pxReal, pxImag);
+
+ {
+ SpatialDecApplyM1_CreateW_Mode212(
+ self, frame, pxReal, pxImag,
+ self->wReal__FDK, /* output: w(Real/Imag) */
+ self->wImag__FDK);
+ }
+ if (err != MPS_OK) goto bail;
+
+ int applyM2Config = APPLY_M2_NONE;
+
+ applyM2Config = APPLY_M2;
+ if ((self->pConfigCurrent->syntaxFlags &
+ (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
+ (self->tempShapeConfig != 1) && (self->tempShapeConfig != 2)) {
+ if (self->phaseCoding == 3)
+ applyM2Config = APPLY_M2_MODE212_Res_PhaseCoding;
+ else
+ applyM2Config = APPLY_M2_MODE212;
+ }
+
+ switch (applyM2Config) {
+ case APPLY_M2_MODE212: {
+ err = SpatialDecApplyM2_Mode212(
+ self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
+ self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK);
+ } break;
+ case APPLY_M2_MODE212_Res_PhaseCoding:
+ err = SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
+ self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
+ self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK);
+ break;
+ case APPLY_M2:
+ err = SpatialDecApplyM2(
+ self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
+ self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK,
+ self->hybOutputRealWet__FDK, self->hybOutputImagWet__FDK);
+ break;
+ default:
+ err = MPS_APPLY_M2_ERROR;
+ goto bail;
+ }
+
+ if (err != MPS_OK) goto bail;
+
+ if ((self->tempShapeConfig == 2) && (!isTwoChMode(self->upmixType))) {
+ SpatialDecReshapeBBEnv(self, frame,
+ ts); /* input: reshapeBBEnvState,
+ hybOutput(Real/Imag)(Dry/Wet),
+ hybInput(Real/Imag) */
+ } /* output: hybOutput(Real/Imag)Dry */
+
+ /* Merge parts of the dry and wet QMF buffers. */
+ if ((self->tempShapeConfig == 1) && (!isTwoChMode(self->upmixType))) {
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ for (hyb = 0; hyb < self->tp_hybBandBorder; hyb++) {
+ self->hybOutputRealDry__FDK[ch][hyb] +=
+ self->hybOutputRealWet__FDK[ch][hyb];
+ self->hybOutputImagDry__FDK[ch][hyb] +=
+ self->hybOutputImagWet__FDK[ch][hyb];
+ } /* loop hyb */
+ } /* loop ch */
+ err = subbandTPApply(
+ self, frame); /* input: hStpDec, hybOutput(Real/Imag)Dry/Wet */
+ /* output: hStpDec, hybOutput(Real/Imag)Dry */
+ if (err != MPS_OK) goto bail;
+ } /* (self->tempShapeConfig == 1) */
+ else {
+ /* The wet signal is added to the dry signal in applyM2 if GES and STP
+ * are disabled */
+ if ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) {
+ int nHybBands;
+ nHybBands = self->hybridBands;
+
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ FIXP_DBL *RESTRICT pRealDry = self->hybOutputRealDry__FDK[ch];
+ FIXP_DBL *RESTRICT pImagDry = self->hybOutputImagDry__FDK[ch];
+ FIXP_DBL *RESTRICT pRealWet = self->hybOutputRealWet__FDK[ch];
+ FIXP_DBL *RESTRICT pImagWet = self->hybOutputImagWet__FDK[ch];
+ for (hyb = 0; hyb < nHybBands; hyb++) {
+ pRealDry[hyb] += pRealWet[hyb];
+ pImagDry[hyb] += pImagWet[hyb];
+ } /* loop hyb */
+ for (; hyb < self->hybridBands; hyb++) {
+ pRealDry[hyb] += pRealWet[hyb];
+ } /* loop hyb */
+ } /* loop ch */
+ } /* ( self->tempShapeConfig == 1 ) || ( self->tempShapeConfig == 2 ) */
+ } /* !self->tempShapeConfig == 1 */
+ } /* !bypassMode */
+
+ if (self->phaseCoding == 1) {
+ /* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */
+
+ SpatialDecApplyPhase(
+ self, alpha, (ts == currSlot) /* signal the last slot of the set */
+ );
+ }
+
+ /*
+ * Synthesis Filtering
+ */
+
+ err = SpatialDecSynthesis(
+ self, ts_io,
+ self->hybOutputRealDry__FDK, /* input: hybOutput(Real/Imag)Dry */
+ self->hybOutputImagDry__FDK, self->timeOut__FDK, /* output: timeOut */
+ numInputChannels, mapDescr);
+
+ if (err != MPS_OK) goto bail;
+
+ /*
+ * Update parameter buffer
+ */
+ if (ts == currSlot) {
+ SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */
+ /* output: M(1/2)param(Real/Imag)Prev */
+
+ prevSlot = currSlot;
+ ps++;
+ } /* if (ts==currSlot) */
+
+ } /* ts loop */
+
+ /*
+ * Save parameter states
+ */
+ self->prevTimeSlot = prevSlot;
+ self->curTimeSlot = ts;
+ self->curPs = ps;
+
+bail:
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecApplyFrame(
+ spatialDec *self,
+ SPATIAL_BS_FRAME *frame, /* parsed frame data to be applied */
+ SPATIALDEC_INPUT_MODE inputMode, PCM_MPS *inData, /* Time domain input */
+ FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */
+ FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */
+ PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */
+ UINT nSamples, UINT *pControlFlags, int numInputChannels,
+ const FDK_channelMapDescr *const mapDescr) {
+ SACDEC_ERROR err = MPS_OK;
+
+ int fDecAndMapFrameData;
+ int controlFlags;
+
+ FDK_ASSERT(self != NULL);
+ FDK_ASSERT(pControlFlags != NULL);
+ FDK_ASSERT(pcmOutBuf != NULL);
+
+ self->errInt = err; /* Init internal error */
+
+ controlFlags = *pControlFlags;
+
+ if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
+ (self->stereoConfigIndex > 1)) {
+ numInputChannels =
+ 1; /* Do not count residual channel as input channel. It is handled
+ seperately. */
+ }
+
+ /* Check if input amount of channels is consistent */
+ if (numInputChannels != self->numInputChannels) {
+ controlFlags |= MPEGS_CONCEAL;
+ if (numInputChannels > self->createParams.maxNumInputChannels) {
+ return MPS_INVALID_PARAMETER;
+ }
+ }
+
+ self->timeOut__FDK = pcmOutBuf;
+
+ /* Determine local function control flags */
+ fDecAndMapFrameData = frame->newBsData;
+
+ if (((fDecAndMapFrameData ==
+ 0) /* assures that conceal flag will not be set for blind mode */
+ && (self->curTimeSlot + (int)nSamples / self->qmfBands >
+ self->timeSlots)) ||
+ (frame->numParameterSets ==
+ 0)) { /* New input samples but missing side info */
+ fDecAndMapFrameData = 1;
+ controlFlags |= MPEGS_CONCEAL;
+ }
+
+ if ((fDecAndMapFrameData == 0) &&
+ (frame->paramSlot[fMax(0, frame->numParameterSets - 1)] !=
+ (self->timeSlots - 1) ||
+ self->curTimeSlot >
+ frame->paramSlot[self->curPs])) { /* Detected faulty parameter slot
+ data. */
+ fDecAndMapFrameData = 1;
+ controlFlags |= MPEGS_CONCEAL;
+ }
+
+ /* Update concealment state machine */
+ SpatialDecConcealment_UpdateState(
+ &self->concealInfo,
+ (controlFlags & MPEGS_CONCEAL)
+ ? 0
+ : 1); /* convert from conceal flag to frame ok flag */
+
+ if (fDecAndMapFrameData) {
+ /* Reset spatial framing control vars */
+ frame->newBsData = 0;
+ self->prevTimeSlot = -1;
+ self->curTimeSlot = 0;
+ self->curPs = 0;
+
+ if (controlFlags & MPEGS_CONCEAL) {
+ /* Reset frame data to avoid misconfiguration. */
+ SpatialDecClearFrameData(self, frame, &self->createParams);
+ }
+
+ {
+ err = SpatialDecDecodeFrame(self, frame); /* input: ... */
+ /* output: decodeAndMapFrameDATA */
+ }
+
+ if (err != MPS_OK) {
+ /* Rescue strategy is to apply bypass mode in order
+ to keep at least the downmix channels continuous. */
+ controlFlags |= MPEGS_CONCEAL;
+ if (self->errInt == MPS_OK) {
+ /* store internal error befor it gets overwritten */
+ self->errInt = err;
+ }
+ }
+ }
+
+ err = SpatialDecApplyParameterSets(
+ self, frame, inputMode, inData, qmfInDataReal, qmfInDataImag, nSamples,
+ controlFlags | ((err == MPS_OK) ? 0 : MPEGS_BYPASSMODE), numInputChannels,
+ mapDescr);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+bail:
+
+ *pControlFlags = controlFlags;
+
+ return err;
+}