aboutsummaryrefslogtreecommitdiffstats
path: root/libSACdec/src
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
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')
-rw-r--r--libSACdec/src/sac_bitdec.cpp2147
-rw-r--r--libSACdec/src/sac_bitdec.h161
-rw-r--r--libSACdec/src/sac_calcM1andM2.cpp848
-rw-r--r--libSACdec/src/sac_calcM1andM2.h129
-rw-r--r--libSACdec/src/sac_dec.cpp1509
-rw-r--r--libSACdec/src/sac_dec.h539
-rw-r--r--libSACdec/src/sac_dec_conceal.cpp392
-rw-r--r--libSACdec/src/sac_dec_conceal.h187
-rw-r--r--libSACdec/src/sac_dec_interface.h335
-rw-r--r--libSACdec/src/sac_dec_lib.cpp1912
-rw-r--r--libSACdec/src/sac_dec_ssc_struct.h283
-rw-r--r--libSACdec/src/sac_process.cpp1066
-rw-r--r--libSACdec/src/sac_process.h297
-rw-r--r--libSACdec/src/sac_qmf.cpp156
-rw-r--r--libSACdec/src/sac_qmf.h143
-rw-r--r--libSACdec/src/sac_reshapeBBEnv.cpp680
-rw-r--r--libSACdec/src/sac_reshapeBBEnv.h114
-rw-r--r--libSACdec/src/sac_rom.cpp709
-rw-r--r--libSACdec/src/sac_rom.h230
-rw-r--r--libSACdec/src/sac_smoothing.cpp295
-rw-r--r--libSACdec/src/sac_smoothing.h114
-rw-r--r--libSACdec/src/sac_stp.cpp548
-rw-r--r--libSACdec/src/sac_stp.h115
-rw-r--r--libSACdec/src/sac_tsd.cpp353
-rw-r--r--libSACdec/src/sac_tsd.h167
25 files changed, 13429 insertions, 0 deletions
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
new file mode 100644
index 0000000..b2f3b7c
--- /dev/null
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -0,0 +1,2147 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
+
+ 1. INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
+
+2. COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
+
+3. NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
+
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
+
+4. DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------- */
+
+/*********************** MPEG surround decoder library *************************
+
+ Author(s):
+
+ Description: SAC Dec bitstream decoder
+
+*******************************************************************************/
+
+#include "sac_bitdec.h"
+
+#include "sac_dec_errorcodes.h"
+#include "nlc_dec.h"
+#include "sac_rom.h"
+#include "FDK_matrixCalloc.h"
+#include "sac_tsd.h"
+
+enum {
+ ottVsTotInactiv = 0,
+ ottVsTotDb1Activ = 1,
+ ottVsTotDb2Activ = 2,
+ ottVsTotDb1Db2Activ = 3
+};
+
+static SACDEC_ERROR SpatialDecDecodeHelperInfo(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType) {
+ int i;
+ UINT syntaxFlags;
+
+ /* Determine bit stream syntax */
+ syntaxFlags = 0;
+ switch (pSpatialSpecificConfig->coreCodec) {
+ case AOT_ER_AAC_ELD:
+ case AOT_ER_AAC_LD:
+ syntaxFlags |= SACDEC_SYNTAX_LD;
+ break;
+ case AOT_USAC:
+ syntaxFlags |= SACDEC_SYNTAX_USAC;
+ break;
+ case AOT_NONE:
+ default:
+ return MPS_UNSUPPORTED_FORMAT;
+ }
+
+ pSpatialSpecificConfig->syntaxFlags = syntaxFlags;
+
+ switch (pSpatialSpecificConfig->treeConfig) {
+ case TREE_212: {
+ pSpatialSpecificConfig->ottCLDdefault[0] = 0;
+ } break;
+ default:
+ return MPS_INVALID_TREECONFIG;
+ }
+
+ if (syntaxFlags & SACDEC_SYNTAX_USAC) {
+ if (pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ pSpatialSpecificConfig->numOttBandsIPD =
+ pSpatialSpecificConfig->bsOttBandsPhase;
+ } else {
+ int numParameterBands;
+
+ numParameterBands = pSpatialSpecificConfig->freqRes;
+ switch (numParameterBands) {
+ case 4:
+ case 5:
+ pSpatialSpecificConfig->numOttBandsIPD = 2;
+ break;
+ case 7:
+ pSpatialSpecificConfig->numOttBandsIPD = 3;
+ break;
+ case 10:
+ pSpatialSpecificConfig->numOttBandsIPD = 5;
+ break;
+ case 14:
+ pSpatialSpecificConfig->numOttBandsIPD = 7;
+ break;
+ case 20:
+ case 28:
+ pSpatialSpecificConfig->numOttBandsIPD = 10;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS;
+ }
+ }
+ } else {
+ pSpatialSpecificConfig->numOttBandsIPD = 0;
+ }
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ {
+ pSpatialSpecificConfig->bitstreamOttBands[i] =
+ pSpatialSpecificConfig->freqRes;
+ }
+ {
+ pSpatialSpecificConfig->numOttBands[i] =
+ pSpatialSpecificConfig->bitstreamOttBands[i];
+ if (syntaxFlags & SACDEC_SYNTAX_USAC &&
+ !pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ if (pSpatialSpecificConfig->bResidualCoding &&
+ pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent &&
+ (pSpatialSpecificConfig->numOttBandsIPD <
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands)) {
+ pSpatialSpecificConfig->numOttBandsIPD =
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands;
+ }
+ }
+ }
+ } /* i */
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecParseExtensionConfig
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+static SACDEC_ERROR SpatialDecParseExtensionConfig(
+ HANDLE_FDK_BITSTREAM bitstream, SPATIAL_SPECIFIC_CONFIG *config,
+ int numOttBoxes, int numTttBoxes, int numOutChan, int bitsAvailable) {
+ SACDEC_ERROR err = MPS_OK;
+ INT ba = bitsAvailable;
+
+ config->sacExtCnt = 0;
+ config->bResidualCoding = 0;
+
+ ba = fMin((int)FDKgetValidBits(bitstream), ba);
+
+ while ((ba >= 8) && (config->sacExtCnt < MAX_NUM_EXT_TYPES)) {
+ int bitsRead, nFillBits;
+ INT tmp;
+ UINT sacExtLen;
+
+ config->sacExtType[config->sacExtCnt] = FDKreadBits(bitstream, 4);
+ ba -= 4;
+
+ sacExtLen = FDKreadBits(bitstream, 4);
+ ba -= 4;
+
+ if (sacExtLen == 15) {
+ sacExtLen += FDKreadBits(bitstream, 8);
+ ba -= 8;
+ if (sacExtLen == 15 + 255) {
+ sacExtLen += FDKreadBits(bitstream, 16);
+ ba -= 16;
+ }
+ }
+
+ tmp = (INT)FDKgetValidBits(
+ bitstream); /* Extension config payload start anchor. */
+ if ((tmp <= 0) || (tmp < (INT)sacExtLen * 8) || (ba < (INT)sacExtLen * 8)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+
+ switch (config->sacExtType[config->sacExtCnt]) {
+ default:; /* unknown extension data => do nothing */
+ }
+
+ /* skip remaining extension data */
+ bitsRead = tmp - FDKgetValidBits(bitstream);
+ nFillBits = 8 * sacExtLen - bitsRead;
+
+ if (nFillBits < 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ } else {
+ /* Skip fill bits or an unkown extension. */
+ FDKpushFor(bitstream, nFillBits);
+ }
+
+ ba -= 8 * sacExtLen;
+ config->sacExtCnt++;
+ }
+
+bail:
+ return err;
+}
+
+SACDEC_ERROR SpatialDecParseSpecificConfigHeader(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType) {
+ SACDEC_ERROR err = MPS_OK;
+ INT numFillBits;
+ int sacHeaderLen = 0;
+ int sacTimeAlignFlag = 0;
+
+ sacTimeAlignFlag = FDKreadBits(bitstream, 1);
+ sacHeaderLen = FDKreadBits(bitstream, 7);
+
+ if (sacHeaderLen == 127) {
+ sacHeaderLen += FDKreadBits(bitstream, 16);
+ }
+ numFillBits = FDKgetValidBits(bitstream);
+
+ err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig,
+ sacHeaderLen, coreCodec);
+
+ numFillBits -=
+ FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */
+ numFillBits = (8 * sacHeaderLen) - numFillBits;
+ if (numFillBits < 0) {
+ /* Parsing went wrong */
+ err = MPS_PARSE_ERROR;
+ }
+ /* Move to the very end of the SSC */
+ FDKpushBiDirectional(bitstream, numFillBits);
+
+ if ((err == MPS_OK) && sacTimeAlignFlag) {
+ /* not supported */
+ FDKreadBits(bitstream, 16);
+ err = MPS_UNSUPPORTED_CONFIG;
+ }
+
+ /* Derive additional helper variables */
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, (UPMIXTYPE)upmixType);
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecParseMps212Config(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate,
+ AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex,
+ INT coreSbrFrameLengthIndex) {
+ int i;
+
+ pSpatialSpecificConfig->stereoConfigIndex = stereoConfigIndex;
+ pSpatialSpecificConfig->coreSbrFrameLengthIndex = coreSbrFrameLengthIndex;
+ pSpatialSpecificConfig->freqRes =
+ (SPATIALDEC_FREQ_RES)freqResTable[FDKreadBits(bitstream, 3)];
+ if (pSpatialSpecificConfig->freqRes == 0) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+
+ switch (coreCodec) {
+ case AOT_DRM_USAC:
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+ /* tempShapeConfig = (bsTempShapeConfigDrm == 1) ? 3 : 0 */
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)(FDKreadBits(bitstream, 1) * 3);
+ pSpatialSpecificConfig->decorrConfig = (SPATIALDEC_DECORR_CONF)0;
+ pSpatialSpecificConfig->bsDecorrType = 0;
+ break;
+ case AOT_USAC:
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2);
+ pSpatialSpecificConfig->decorrConfig =
+ (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2);
+ if (pSpatialSpecificConfig->decorrConfig > 2) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+ pSpatialSpecificConfig->bsDecorrType = 0;
+ break;
+ default:
+ return MPS_UNSUPPORTED_FORMAT;
+ }
+ pSpatialSpecificConfig->nTimeSlots = (coreSbrFrameLengthIndex == 4) ? 64 : 32;
+ pSpatialSpecificConfig->bsHighRateMode = (UCHAR)FDKreadBits(bitstream, 1);
+
+ {
+ pSpatialSpecificConfig->bsPhaseCoding = (UCHAR)FDKreadBits(bitstream, 1);
+ pSpatialSpecificConfig->bsOttBandsPhasePresent =
+ (UCHAR)FDKreadBits(bitstream, 1);
+ if (pSpatialSpecificConfig->bsOttBandsPhasePresent) {
+ if (MAX_PARAMETER_BANDS < (pSpatialSpecificConfig->bsOttBandsPhase =
+ FDKreadBits(bitstream, 5))) {
+ return MPS_PARSE_ERROR;
+ }
+ } else {
+ pSpatialSpecificConfig->bsOttBandsPhase = 0;
+ }
+ }
+
+ if (stereoConfigIndex > 1) { /* do residual coding */
+ pSpatialSpecificConfig->bResidualCoding = 1;
+ pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 1;
+ if (pSpatialSpecificConfig->freqRes <
+ (pSpatialSpecificConfig->ResidualConfig->nResidualBands =
+ FDKreadBits(bitstream, 5))) {
+ return MPS_PARSE_ERROR;
+ }
+ pSpatialSpecificConfig->bsOttBandsPhase =
+ fMax(pSpatialSpecificConfig->bsOttBandsPhase,
+ pSpatialSpecificConfig->ResidualConfig->nResidualBands);
+ pSpatialSpecificConfig->bsPseudoLr = (UCHAR)FDKreadBits(bitstream, 1);
+
+ if (pSpatialSpecificConfig->bsPhaseCoding) {
+ pSpatialSpecificConfig->bsPhaseCoding = 3;
+ }
+ } else {
+ pSpatialSpecificConfig->bResidualCoding = 0;
+ pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 0;
+ }
+
+ if (pSpatialSpecificConfig->tempShapeConfig == 2) {
+ switch (coreCodec) {
+ case AOT_USAC:
+ pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1);
+ break;
+ default: /* added to avoid compiler warning */
+ break; /* added to avoid compiler warning */
+ }
+ }
+
+ /* Static parameters */
+
+ pSpatialSpecificConfig->samplingFreq =
+ samplingRate; /* wrong for stereoConfigIndex == 3 but value is unused */
+ pSpatialSpecificConfig->treeConfig = SPATIALDEC_MODE_RSVD7;
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+
+ pSpatialSpecificConfig->bArbitraryDownmix = 0;
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ if (coreCodec == AOT_DRM_USAC) {
+ /* MPS payload is MPEG conform -> no need for pseudo DRM AOT */
+ coreCodec = AOT_USAC;
+ }
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+
+ /* Derive additional helper variables */
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+ return MPS_OK;
+}
+
+SACDEC_ERROR SpatialDecParseSpecificConfig(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen,
+ AUDIO_OBJECT_TYPE coreCodec) {
+ SACDEC_ERROR err = MPS_OK;
+ int i;
+ int bsSamplingFreqIndex;
+ int bsFreqRes, b3DaudioMode = 0;
+ int numHeaderBits;
+ int cfgStartPos, bitsAvailable;
+
+ cfgStartPos = FDKgetValidBits(bitstream);
+ /* It might be that we do not know the SSC length beforehand. */
+ if (sacHeaderLen == 0) {
+ bitsAvailable = cfgStartPos;
+ } else {
+ bitsAvailable = 8 * sacHeaderLen;
+ if (bitsAvailable > cfgStartPos) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ }
+
+ bsSamplingFreqIndex = FDKreadBits(bitstream, 4);
+
+ if (bsSamplingFreqIndex == 15) {
+ pSpatialSpecificConfig->samplingFreq = FDKreadBits(bitstream, 24);
+ } else {
+ pSpatialSpecificConfig->samplingFreq =
+ samplingFreqTable[bsSamplingFreqIndex];
+ if (pSpatialSpecificConfig->samplingFreq == 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ }
+
+ pSpatialSpecificConfig->nTimeSlots = FDKreadBits(bitstream, 5) + 1;
+ if ((pSpatialSpecificConfig->nTimeSlots < 1) ||
+ (pSpatialSpecificConfig->nTimeSlots > MAX_TIME_SLOTS)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+
+ bsFreqRes = FDKreadBits(bitstream, 3);
+
+ pSpatialSpecificConfig->freqRes =
+ (SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes];
+
+ pSpatialSpecificConfig->treeConfig =
+ (SPATIALDEC_TREE_CONFIG)FDKreadBits(bitstream, 4);
+
+ if (pSpatialSpecificConfig->treeConfig != SPATIALDEC_MODE_RSVD7) {
+ err = MPS_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
+
+ {
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nTttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numTttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+ }
+
+ pSpatialSpecificConfig->quantMode =
+ (SPATIALDEC_QUANT_MODE)FDKreadBits(bitstream, 2);
+
+ pSpatialSpecificConfig->bArbitraryDownmix = FDKreadBits(bitstream, 1);
+
+ pSpatialSpecificConfig->bsFixedGainDMX =
+ (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3);
+
+ pSpatialSpecificConfig->tempShapeConfig =
+ (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2);
+ pSpatialSpecificConfig->decorrConfig =
+ (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2);
+ if (pSpatialSpecificConfig->decorrConfig > 2) {
+ return MPS_PARSE_ERROR; /* reserved value */
+ }
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ for (i = 0; i < pSpatialSpecificConfig->nTttBoxes; i++) {
+ int bTttDualMode = FDKreadBits(bitstream, 1);
+ FDKreadBits(bitstream, 3); /* not supported */
+
+ if (bTttDualMode) {
+ FDKreadBits(bitstream, 8); /* not supported */
+ }
+ }
+
+ if (pSpatialSpecificConfig->tempShapeConfig == 2) {
+ pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1);
+ }
+
+ if (b3DaudioMode) {
+ if (FDKreadBits(bitstream, 2) == 0) { /* b3DaudioHRTFset ? */
+ int hc;
+ int HRTFnumBand;
+ int HRTFfreqRes = FDKreadBits(bitstream, 3);
+ int HRTFnumChan = FDKreadBits(bitstream, 4);
+ int HRTFasymmetric = FDKreadBits(bitstream, 1);
+
+ HRTFnumBand = freqResTable_LD[HRTFfreqRes];
+
+ for (hc = 0; hc < HRTFnumChan; hc++) {
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelLeft[hc][hb] */
+ if (HRTFasymmetric) {
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelRight[hc][hb] */
+ }
+ if (FDKreadBits(bitstream, 1)) { /* HRTFphase[hc] ? */
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFphaseLR[hc][hb] */
+ }
+ if (FDKreadBits(bitstream, 1)) { /* HRTFicc[hc] ? */
+ FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFiccLR[hc][hb] */
+ }
+ }
+ }
+ }
+
+ FDKbyteAlign(bitstream,
+ cfgStartPos); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment
+ with respect to the beginning of the syntactic
+ element in which ByteAlign() occurs. */
+
+ numHeaderBits = cfgStartPos - FDKgetValidBits(bitstream);
+ bitsAvailable -= numHeaderBits;
+
+ pSpatialSpecificConfig->sacExtCnt = 0;
+ pSpatialSpecificConfig->bResidualCoding = 0;
+
+ if ((err == MPS_OK) && (bitsAvailable > 0)) {
+ err = SpatialDecParseExtensionConfig(
+ bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes,
+ pSpatialSpecificConfig->nTttBoxes,
+ pSpatialSpecificConfig->nOutputChannels, bitsAvailable);
+ }
+
+ FDKbyteAlign(
+ bitstream,
+ cfgStartPos); /* Same alignment anchor as above because
+ SpatialExtensionConfig() always reads full bytes */
+
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+bail:
+ if (sacHeaderLen > 0) {
+ /* If the config is of known length then assure that the
+ bitbuffer is exactly at its end when leaving the function. */
+ FDKpushBiDirectional(
+ bitstream,
+ (sacHeaderLen * 8) - (cfgStartPos - FDKgetValidBits(bitstream)));
+ }
+
+ return err;
+}
+
+int SpatialDecDefaultSpecificConfig(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots,
+ int sacDecoderLevel, int isBlind, int numCoreChannels)
+
+{
+ int err = MPS_OK;
+ int i;
+
+ FDK_ASSERT(coreCodec != AOT_NONE);
+ FDK_ASSERT(nTimeSlots > 0);
+ FDK_ASSERT(samplingFreq > 0);
+
+ pSpatialSpecificConfig->coreCodec = coreCodec;
+ pSpatialSpecificConfig->samplingFreq = samplingFreq;
+ pSpatialSpecificConfig->nTimeSlots = nTimeSlots;
+ if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) ||
+ (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD))
+ pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_23;
+ else
+ pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_28;
+
+ {
+ pSpatialSpecificConfig->treeConfig =
+ SPATIALDEC_MODE_RSVD7; /* 212 configuration */
+ }
+
+ {
+ pSpatialSpecificConfig->nOttBoxes =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes;
+ pSpatialSpecificConfig->nInputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels;
+ pSpatialSpecificConfig->nOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels;
+ }
+
+ pSpatialSpecificConfig->quantMode = SPATIALDEC_QUANT_FINE_DEF;
+ pSpatialSpecificConfig->bArbitraryDownmix = 0;
+ pSpatialSpecificConfig->bResidualCoding = 0;
+ if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) ||
+ (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD))
+ pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_RSVD2;
+ else
+ pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_MODE0;
+
+ pSpatialSpecificConfig->tempShapeConfig = SPATIALDEC_TS_TPNOWHITE;
+ pSpatialSpecificConfig->decorrConfig = SPATIALDEC_DECORR_MODE0;
+
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ pSpatialSpecificConfig->OttConfig[i].nOttBands = 0;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: coarse2fine
+ *******************************************************************************
+
+ Description:
+ Parameter index mapping from coarse to fine quantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static void coarse2fine(SCHAR *data, DATA_TYPE dataType, int startBand,
+ int numBands) {
+ int i;
+
+ for (i = startBand; i < startBand + numBands; i++) {
+ data[i] <<= 1;
+ }
+
+ if (dataType == t_CLD) {
+ for (i = startBand; i < startBand + numBands; i++) {
+ if (data[i] == -14)
+ data[i] = -15;
+ else if (data[i] == 14)
+ data[i] = 15;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: fine2coarse
+ *******************************************************************************
+
+ Description:
+ Parameter index mapping from fine to coarse quantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static void fine2coarse(SCHAR *data, DATA_TYPE dataType, int startBand,
+ int numBands) {
+ int i;
+
+ for (i = startBand; i < startBand + numBands; i++) {
+ /* Note: the if cases below actually make a difference (negative values) */
+ if (dataType == t_CLD)
+ data[i] /= 2;
+ else
+ data[i] >>= 1;
+ }
+}
+
+/*******************************************************************************
+ Functionname: getStrideMap
+ *******************************************************************************
+
+ Description:
+ Index Mapping accroding to pbStrides
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static int getStrideMap(int freqResStride, int startBand, int stopBand,
+ int *aStrides) {
+ int i, pb, pbStride, dataBands, strOffset;
+
+ pbStride = pbStrideTable[freqResStride];
+ dataBands = (stopBand - startBand - 1) / pbStride + 1;
+
+ aStrides[0] = startBand;
+ for (pb = 1; pb <= dataBands; pb++) {
+ aStrides[pb] = aStrides[pb - 1] + pbStride;
+ }
+ strOffset = 0;
+ while (aStrides[dataBands] > stopBand) {
+ if (strOffset < dataBands) strOffset++;
+ for (i = strOffset; i <= dataBands; i++) {
+ aStrides[i]--;
+ }
+ }
+
+ return dataBands;
+}
+
+/*******************************************************************************
+ Functionname: ecDataDec
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+
+*******************************************************************************/
+
+static SACDEC_ERROR ecDataDec(
+ const SPATIAL_BS_FRAME *frame, UINT syntaxFlags,
+ HANDLE_FDK_BITSTREAM bitstream, LOSSLESSDATA *const llData,
+ SCHAR (*data)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], SCHAR **lastdata,
+ int datatype, int boxIdx, int startBand, int stopBand, SCHAR defaultValue) {
+ SACDEC_ERROR err = MPS_OK;
+ int i, j, pb, dataSets, setIdx, bsDataPair, dataBands, oldQuantCoarseXXX;
+ INT aStrides[MAX_PARAMETER_BANDS + 1] = {0};
+
+ dataSets = 0;
+ for (i = 0; i < frame->numParameterSets; i++) {
+ llData->bsXXXDataMode[i] = (SCHAR)FDKreadBits(bitstream, 2);
+
+ if ((frame->bsIndependencyFlag == 1) && (i == 0) &&
+ (llData->bsXXXDataMode[i] == 1 ||
+ llData->bsXXXDataMode[i] == 2)) { /* This check catches bitstreams
+ generated by older encoder that
+ cause trouble */
+ return MPS_PARSE_ERROR;
+ }
+ if ((i >= frame->numParameterSets - 1) &&
+ (llData->bsXXXDataMode[i] ==
+ 2)) { /* The interpolation mode must not be active for the last
+ parameter set */
+ return MPS_PARSE_ERROR;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ dataSets++;
+ }
+ }
+
+ setIdx = 0;
+ bsDataPair = 0;
+ oldQuantCoarseXXX = llData->state->bsQuantCoarseXXXprevParse;
+
+ for (i = 0; i < frame->numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 0) {
+ for (pb = startBand; pb < stopBand; pb++) {
+ lastdata[boxIdx][pb] = defaultValue;
+ }
+
+ oldQuantCoarseXXX = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ if (bsDataPair) {
+ bsDataPair = 0;
+ } else {
+ bsDataPair = FDKreadBits(bitstream, 1);
+ llData->bsQuantCoarseXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 1);
+ llData->bsFreqResStrideXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 2);
+
+ if (llData->bsQuantCoarseXXX[setIdx] != oldQuantCoarseXXX) {
+ if (oldQuantCoarseXXX) {
+ coarse2fine(lastdata[boxIdx], (DATA_TYPE)datatype, startBand,
+ stopBand - startBand);
+ } else {
+ fine2coarse(lastdata[boxIdx], (DATA_TYPE)datatype, startBand,
+ stopBand - startBand);
+ }
+ }
+
+ dataBands = getStrideMap(llData->bsFreqResStrideXXX[setIdx], startBand,
+ stopBand, aStrides);
+
+ for (pb = 0; pb < dataBands; pb++) {
+ lastdata[boxIdx][startBand + pb] = lastdata[boxIdx][aStrides[pb]];
+ }
+
+ if (boxIdx > MAX_NUM_OTT) return MPS_INVALID_BOXIDX;
+ if ((setIdx + bsDataPair) > MAX_PARAMETER_SETS)
+ return MPS_INVALID_SETIDX;
+
+ /* DECODER_TYPE defined in FDK_tools */
+ DECODER_TYPE this_decoder_type = SAC_DECODER;
+ if (syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) {
+ this_decoder_type = USAC_DECODER;
+ } else if (syntaxFlags & SACDEC_SYNTAX_LD) {
+ this_decoder_type = SAOC_DECODER;
+ }
+
+ err = (SACDEC_ERROR)EcDataPairDec(
+ this_decoder_type, bitstream, data[boxIdx][setIdx + 0],
+ data[boxIdx][setIdx + 1], lastdata[boxIdx], (DATA_TYPE)datatype,
+ startBand, dataBands, bsDataPair, llData->bsQuantCoarseXXX[setIdx],
+ !(frame->bsIndependencyFlag && (i == 0)) || (setIdx > 0));
+ if (err != MPS_OK) goto bail;
+
+ if (datatype == t_IPD) {
+ const SCHAR mask = (llData->bsQuantCoarseXXX[setIdx]) ? 7 : 15;
+ for (pb = 0; pb < dataBands; pb++) {
+ for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) {
+ lastdata[boxIdx][j] =
+ data[boxIdx][setIdx + bsDataPair][startBand + pb] & mask;
+ }
+ }
+ } else {
+ for (pb = 0; pb < dataBands; pb++) {
+ for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) {
+ lastdata[boxIdx][j] =
+ data[boxIdx][setIdx + bsDataPair][startBand + pb];
+ }
+ }
+ }
+
+ oldQuantCoarseXXX = llData->bsQuantCoarseXXX[setIdx];
+
+ if (bsDataPair) {
+ llData->bsQuantCoarseXXX[setIdx + 1] =
+ llData->bsQuantCoarseXXX[setIdx];
+ llData->bsFreqResStrideXXX[setIdx + 1] =
+ llData->bsFreqResStrideXXX[setIdx];
+ }
+ setIdx += bsDataPair + 1;
+ } /* !bsDataPair */
+ } /* llData->bsXXXDataMode[i] == 3 */
+ }
+
+ llData->state->bsQuantCoarseXXXprevParse = oldQuantCoarseXXX;
+
+bail:
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: parseArbitraryDownmixData
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR parseArbitraryDownmixData(
+ spatialDec *self, const SPATIAL_SPECIFIC_CONFIG *pSSC,
+ const UINT syntaxFlags, const SPATIAL_BS_FRAME *frame,
+ HANDLE_FDK_BITSTREAM bitstream) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+ int offset = pSSC->nOttBoxes;
+
+ /* CLD (arbitrary down-mix gains) */
+ for (ch = 0; ch < pSSC->nInputChannels; ch++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream,
+ &frame->CLDLosslessData[offset + ch],
+ frame->cmpArbdmxGainIdx, self->cmpArbdmxGainIdxPrev, t_CLD,
+ ch, 0, pSSC->freqRes, arbdmxGainDefault);
+ if (err != MPS_OK) return err;
+ }
+
+ return err;
+
+} /* parseArbitraryDownmixData */
+
+/*******************************************************************************
+ Functionname: SpatialDecParseFrame
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+*******************************************************************************/
+
+static int nBitsParamSlot(int i) {
+ int bitsParamSlot;
+
+ bitsParamSlot = fMax(0, DFRACT_BITS - 1 - fNormz((FIXP_DBL)i));
+ if ((1 << bitsParamSlot) < i) {
+ bitsParamSlot++;
+ }
+ FDK_ASSERT((bitsParamSlot >= 0) && (bitsParamSlot <= 32));
+
+ return bitsParamSlot;
+}
+
+SACDEC_ERROR SpatialDecParseFrameData(
+ spatialDec_struct *self, SPATIAL_BS_FRAME *frame,
+ HANDLE_FDK_BITSTREAM bitstream,
+ const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType,
+ int fGlobalIndependencyFlag) {
+ SACDEC_ERROR err = MPS_OK;
+ int bsFramingType, dataBands, ps, pg, i;
+ int pb;
+ int numTempShapeChan = 0;
+ int bsNumOutputChannels =
+ treePropertyTable[pSpatialSpecificConfig->treeConfig]
+ .numOutputChannels; /* CAUTION: Maybe different to
+ pSpatialSpecificConfig->treeConfig in some
+ modes! */
+ int paramSetErr = 0;
+ UINT alignAnchor = FDKgetValidBits(
+ bitstream); /* Anchor for ByteAlign() function. See comment below. */
+ UINT syntaxFlags;
+
+ syntaxFlags = pSpatialSpecificConfig->syntaxFlags;
+
+ if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
+ pSpatialSpecificConfig->bsHighRateMode == 0) {
+ bsFramingType = 0; /* fixed framing */
+ frame->numParameterSets = 1;
+ } else {
+ bsFramingType = FDKreadBits(bitstream, 1);
+ if (syntaxFlags & SACDEC_SYNTAX_LD)
+ frame->numParameterSets = FDKreadBits(bitstream, 1) + 1;
+ else
+ frame->numParameterSets = FDKreadBits(bitstream, 3) + 1;
+ }
+
+ /* Any error after this line shall trigger parameter invalidation at bail
+ * label. */
+ paramSetErr = 1;
+
+ if (frame->numParameterSets >= MAX_PARAMETER_SETS) {
+ goto bail;
+ }
+
+ /* Basic config check. */
+ if (pSpatialSpecificConfig->nInputChannels <= 0 ||
+ pSpatialSpecificConfig->nOutputChannels <= 0) {
+ err = MPS_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
+
+ if (bsFramingType) {
+ int prevParamSlot = -1;
+ int bitsParamSlot;
+
+ {
+ bitsParamSlot = nBitsParamSlot(pSpatialSpecificConfig->nTimeSlots);
+
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->paramSlot[i] = FDKreadBits(bitstream, bitsParamSlot);
+ /* Sanity check */
+ if ((frame->paramSlot[i] <= prevParamSlot) ||
+ (frame->paramSlot[i] >= pSpatialSpecificConfig->nTimeSlots)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ prevParamSlot = frame->paramSlot[i];
+ }
+ }
+ } else {
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->paramSlot[i] = ((pSpatialSpecificConfig->nTimeSlots * (i + 1)) /
+ frame->numParameterSets) -
+ 1;
+ }
+ }
+
+ if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
+ fGlobalIndependencyFlag) {
+ frame->bsIndependencyFlag = 1;
+ } else {
+ frame->bsIndependencyFlag = (UCHAR)FDKreadBits(bitstream, 1);
+ }
+
+ /*
+ * OttData()
+ */
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->CLDLosslessData[i],
+ frame->cmpOttCLDidx, self->cmpOttCLDidxPrev, t_CLD, i, 0,
+ pSpatialSpecificConfig->bitstreamOttBands[i],
+ pSpatialSpecificConfig->ottCLDdefault[i]);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ } /* i < numOttBoxes */
+
+ {
+ for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) {
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->ICCLosslessData[i],
+ frame->cmpOttICCidx, self->cmpOttICCidxPrev, t_ICC, i, 0,
+ pSpatialSpecificConfig->bitstreamOttBands[i], ICCdefault);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ } /* i < numOttBoxes */
+ } /* !oneICC */
+
+ if ((pSpatialSpecificConfig->treeConfig == SPATIALDEC_MODE_RSVD7) &&
+ (pSpatialSpecificConfig->bsPhaseCoding)) {
+ frame->phaseMode = FDKreadBits(bitstream, 1);
+
+ if (frame->phaseMode == 0) {
+ for (pb = 0; pb < pSpatialSpecificConfig->numOttBandsIPD; pb++) {
+ self->cmpOttIPDidxPrev[0][pb] = 0;
+ for (i = 0; i < frame->numParameterSets; i++) {
+ frame->cmpOttIPDidx[0][i][pb] = 0;
+ // frame->ottIPDidx[0][i][pb] = 0;
+ }
+ /* self->ottIPDidxPrev[0][pb] = 0; */
+ }
+ frame->OpdSmoothingMode = 0;
+ } else {
+ frame->OpdSmoothingMode = FDKreadBits(bitstream, 1);
+ err = ecDataDec(frame, syntaxFlags, bitstream, &frame->IPDLosslessData[0],
+ frame->cmpOttIPDidx, self->cmpOttIPDidxPrev, t_IPD, 0, 0,
+ pSpatialSpecificConfig->numOttBandsIPD, IPDdefault);
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ }
+ }
+
+ /*
+ * SmgData()
+ */
+
+ {
+ if (!pSpatialSpecificConfig->bsHighRateMode &&
+ (syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ frame->bsSmoothMode[ps] = 0;
+ }
+ } else {
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ frame->bsSmoothMode[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ if (frame->bsSmoothMode[ps] >= 2) {
+ frame->bsSmoothTime[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ }
+ if (frame->bsSmoothMode[ps] == 3) {
+ frame->bsFreqResStrideSmg[ps] = (UCHAR)FDKreadBits(bitstream, 2);
+ dataBands = (pSpatialSpecificConfig->freqRes - 1) /
+ pbStrideTable[frame->bsFreqResStrideSmg[ps]] +
+ 1;
+ for (pg = 0; pg < dataBands; pg++) {
+ frame->bsSmgData[ps][pg] = (UCHAR)FDKreadBits(bitstream, 1);
+ }
+ }
+ } /* ps < numParameterSets */
+ }
+ }
+
+ /*
+ * TempShapeData()
+ */
+ if ((pSpatialSpecificConfig->tempShapeConfig == 3) &&
+ (syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ int TsdErr;
+ TsdErr = TsdRead(bitstream, pSpatialSpecificConfig->nTimeSlots,
+ &frame->TsdData[0]);
+ if (TsdErr) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ } else {
+ frame->TsdData[0].bsTsdEnable = 0;
+ }
+
+ for (i = 0; i < bsNumOutputChannels; i++) {
+ frame->tempShapeEnableChannelSTP[i] = 0;
+ frame->tempShapeEnableChannelGES[i] = 0;
+ }
+
+ if ((pSpatialSpecificConfig->tempShapeConfig == 1) ||
+ (pSpatialSpecificConfig->tempShapeConfig == 2)) {
+ int bsTempShapeEnable = FDKreadBits(bitstream, 1);
+ if (bsTempShapeEnable) {
+ numTempShapeChan =
+ tempShapeChanTable[pSpatialSpecificConfig->tempShapeConfig - 1]
+ [pSpatialSpecificConfig->treeConfig];
+ switch (pSpatialSpecificConfig->tempShapeConfig) {
+ case 1: /* STP */
+ for (i = 0; i < numTempShapeChan; i++) {
+ int stpEnable = FDKreadBits(bitstream, 1);
+ frame->tempShapeEnableChannelSTP[i] = stpEnable;
+ }
+ break;
+ case 2: /* GES */
+ {
+ UCHAR gesChannelEnable[MAX_OUTPUT_CHANNELS];
+
+ for (i = 0; i < numTempShapeChan; i++) {
+ gesChannelEnable[i] = (UCHAR)FDKreadBits(bitstream, 1);
+ frame->tempShapeEnableChannelGES[i] = gesChannelEnable[i];
+ }
+ for (i = 0; i < numTempShapeChan; i++) {
+ if (gesChannelEnable[i]) {
+ int envShapeData_tmp[MAX_TIME_SLOTS];
+ if (huff_dec_reshape(bitstream, envShapeData_tmp,
+ pSpatialSpecificConfig->nTimeSlots) != 0) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ for (int ts = 0; ts < pSpatialSpecificConfig->nTimeSlots; ts++) {
+ if (!(envShapeData_tmp[ts] >= 0) &&
+ (envShapeData_tmp[ts] <= 4)) {
+ err = MPS_PARSE_ERROR;
+ goto bail;
+ }
+ frame->bsEnvShapeData[i][ts] = (UCHAR)envShapeData_tmp[ts];
+ }
+ }
+ }
+ } break;
+ default:
+ err = MPS_INVALID_TEMPSHAPE;
+ goto bail;
+ }
+ } /* bsTempShapeEnable */
+ } /* pSpatialSpecificConfig->tempShapeConfig != 0 */
+
+ if (pSpatialSpecificConfig->bArbitraryDownmix != 0) {
+ err = parseArbitraryDownmixData(self, pSpatialSpecificConfig, syntaxFlags,
+ frame, bitstream);
+ if (err != MPS_OK) goto bail;
+ }
+
+ if (1 && (!(syntaxFlags & (SACDEC_SYNTAX_USAC)))) {
+ FDKbyteAlign(bitstream,
+ alignAnchor); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment
+ with respect to the beginning of the syntactic
+ element in which ByteAlign() occurs. */
+ }
+
+bail:
+ if (err != MPS_OK && paramSetErr != 0) {
+ /* Since the parameter set data has already been written to the instance we
+ * need to ... */
+ frame->numParameterSets = 0; /* ... signal that it is corrupt ... */
+ }
+
+ return err;
+
+} /* SpatialDecParseFrame */
+
+/*******************************************************************************
+ Functionname: createMapping
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void createMapping(int aMap[MAX_PARAMETER_BANDS + 1], int startBand,
+ int stopBand, int stride) {
+ int inBands, outBands, bandsAchived, bandsDiff, incr, k, i;
+ int vDk[MAX_PARAMETER_BANDS + 1];
+ inBands = stopBand - startBand;
+ outBands = (inBands - 1) / stride + 1;
+
+ if (outBands < 1) {
+ outBands = 1;
+ }
+
+ bandsAchived = outBands * stride;
+ bandsDiff = inBands - bandsAchived;
+ for (i = 0; i < outBands; i++) {
+ vDk[i] = stride;
+ }
+
+ if (bandsDiff > 0) {
+ incr = -1;
+ k = outBands - 1;
+ } else {
+ incr = 1;
+ k = 0;
+ }
+
+ while (bandsDiff != 0) {
+ vDk[k] = vDk[k] - incr;
+ k = k + incr;
+ bandsDiff = bandsDiff + incr;
+ if (k >= outBands) {
+ if (bandsDiff > 0) {
+ k = outBands - 1;
+ } else if (bandsDiff < 0) {
+ k = 0;
+ }
+ }
+ }
+ aMap[0] = startBand;
+ for (i = 0; i < outBands; i++) {
+ aMap[i + 1] = aMap[i] + vDk[i];
+ }
+} /* createMapping */
+
+/*******************************************************************************
+ Functionname: mapFrequency
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void mapFrequency(const SCHAR *pInput, /* Input */
+ SCHAR *pOutput, /* Output */
+ int *pMap, /* Mapping function */
+ int dataBands) /* Number of data Bands */
+{
+ int i, j;
+ int startBand0 = pMap[0];
+
+ for (i = 0; i < dataBands; i++) {
+ int startBand, stopBand, value;
+
+ value = pInput[i + startBand0];
+
+ startBand = pMap[i];
+ stopBand = pMap[i + 1];
+ for (j = startBand; j < stopBand; j++) {
+ pOutput[j] = value;
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: deq
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static int deqIdx(int value, int paramType) {
+ int idx = -1;
+
+ switch (paramType) {
+ case t_CLD:
+ if (((value + 15) >= 0) && ((value + 15) < 31)) {
+ idx = (value + 15);
+ }
+ break;
+
+ case t_ICC:
+ if ((value >= 0) && (value < 8)) {
+ idx = value;
+ }
+ break;
+
+ case t_IPD:
+ /* (+/-)15 * MAX_PARAMETER_BANDS for differential coding in frequency
+ * domain (according to rbl) */
+ if ((value >= -420) && (value <= 420)) {
+ idx = (value & 0xf);
+ }
+ break;
+
+ default:
+ FDK_ASSERT(0);
+ }
+
+ return idx;
+}
+
+ /*******************************************************************************
+ Functionname: factorFunct
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+ *******************************************************************************/
+
+#define SF_IDX (7)
+#define SF_FACTOR (3)
+#define SCALE_FACTOR (1 << SF_FACTOR)
+#define SCALE_CLD_C1C2 (1 << SF_CLD_C1C2)
+
+static FIXP_DBL factorFunct(FIXP_DBL ottVsTotDb, INT quantMode) {
+ FIXP_DBL factor;
+
+ if (ottVsTotDb > FL2FXCONST_DBL(0.0)) {
+ ottVsTotDb = FL2FXCONST_DBL(0.0);
+ }
+
+ ottVsTotDb = -ottVsTotDb;
+
+ switch (quantMode) {
+ case 0:
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ break;
+ case 1:
+ if (ottVsTotDb >= FL2FXCONST_DBL(21.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(5.0f / SCALE_FACTOR);
+ else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ else
+ factor = (fMult(FL2FXCONST_DBL(0.2f), ottVsTotDb) +
+ FL2FXCONST_DBL(0.8f / SCALE_CLD_C1C2))
+ << (SF_CLD_C1C2 - SF_FACTOR);
+ break;
+ case 2:
+ if (ottVsTotDb >= FL2FXCONST_DBL(25.0f / SCALE_CLD_C1C2)) {
+ FDK_ASSERT(SF_FACTOR == 3);
+ factor = (FIXP_DBL)
+ MAXVAL_DBL; /* avoid warning: FL2FXCONST_DBL(8.0f/SCALE_FACTOR) */
+ } else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2))
+ factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR);
+ else
+ factor = (fMult(FL2FXCONST_DBL(7.0f / 24.0f), ottVsTotDb) +
+ FL2FXCONST_DBL((17.0f / 24.0f) / SCALE_CLD_C1C2))
+ << (SF_CLD_C1C2 - SF_FACTOR);
+ break;
+ default:
+ factor = FL2FXCONST_DBL(0.0f);
+ }
+
+ return (factor);
+}
+
+/*******************************************************************************
+ Functionname: factorCLD
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void factorCLD(SCHAR *idx, FIXP_DBL ottVsTotDb, FIXP_DBL *ottVsTotDb1,
+ FIXP_DBL *ottVsTotDb2, SCHAR ottVsTotDbMode,
+ INT quantMode) {
+ FIXP_DBL factor;
+ FIXP_DBL cldIdxFract;
+ INT cldIdx;
+
+ factor = factorFunct(ottVsTotDb, quantMode);
+
+ cldIdxFract =
+ fMult((FIXP_DBL)((*idx) << ((DFRACT_BITS - 1) - SF_IDX)), factor);
+ cldIdxFract += FL2FXCONST_DBL(15.5f / (1 << (SF_FACTOR + SF_IDX)));
+ cldIdx = fixp_truncateToInt(cldIdxFract, SF_FACTOR + SF_IDX);
+
+ cldIdx = fMin(cldIdx, 30);
+ cldIdx = fMax(cldIdx, 0);
+
+ *idx = cldIdx - 15;
+
+ if (ottVsTotDbMode & ottVsTotDb1Activ)
+ (*ottVsTotDb1) = ottVsTotDb + dequantCLD_c1[cldIdx];
+
+ if (ottVsTotDbMode & ottVsTotDb2Activ)
+ (*ottVsTotDb2) = ottVsTotDb + dequantCLD_c1[30 - cldIdx];
+}
+
+/*******************************************************************************
+ Functionname: mapIndexData
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR mapIndexData(
+ LOSSLESSDATA *llData, SCHAR ***outputDataIdx, SCHAR ***outputIdxData,
+ const SCHAR (*cmpIdxData)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ SCHAR ***diffIdxData, SCHAR xttIdx, SCHAR **idxPrev, int paramIdx,
+ int paramType, int startBand, int stopBand, SCHAR defaultValue,
+ int numParameterSets, const int *paramSlot, int extendFrame, int quantMode,
+ SpatialDecConcealmentInfo *concealmentInfo, SCHAR ottVsTotDbMode,
+ FIXP_DBL (*pOttVsTotDbIn)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ FIXP_DBL (*pOttVsTotDb1)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ FIXP_DBL (*pOttVsTotDb2)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) {
+ int aParamSlots[MAX_PARAMETER_SETS];
+ int aInterpolate[MAX_PARAMETER_SETS];
+
+ int dataSets;
+ int aMap[MAX_PARAMETER_BANDS + 1];
+
+ int setIdx, i, band, parmSlot;
+ int dataBands;
+ int ps, pb;
+ int i1;
+
+ if (numParameterSets > MAX_PARAMETER_SETS) return MPS_WRONG_PARAMETERSETS;
+
+ dataSets = 0;
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 3) {
+ aParamSlots[dataSets] = i;
+ dataSets++;
+ }
+ }
+
+ setIdx = 0;
+
+ /* Main concealment stage is here: */
+ SpatialDecConcealment_Apply(
+ concealmentInfo, cmpIdxData[xttIdx],
+ (diffIdxData != NULL) ? diffIdxData[xttIdx] : NULL, idxPrev[xttIdx],
+ llData->bsXXXDataMode, startBand, stopBand, defaultValue, paramType,
+ numParameterSets);
+
+ /* Prepare data */
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->bsXXXDataMode[i] == 0) {
+ llData->nocmpQuantCoarseXXX[i] = 0;
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = defaultValue;
+ }
+ for (band = startBand; band < stopBand; band++) {
+ idxPrev[xttIdx][band] = outputIdxData[xttIdx][i][band];
+ }
+ /* Because the idxPrev are also set to the defaultValue -> signalize fine
+ */
+ llData->state->bsQuantCoarseXXXprev = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 1) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band];
+ }
+ llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev;
+ }
+
+ if (llData->bsXXXDataMode[i] == 2) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band];
+ }
+ llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev;
+ aInterpolate[i] = 1;
+ } else {
+ aInterpolate[i] = 0;
+ }
+
+ if (llData->bsXXXDataMode[i] == 3) {
+ int stride;
+
+ parmSlot = aParamSlots[setIdx];
+ stride = pbStrideTable[llData->bsFreqResStrideXXX[setIdx]];
+ dataBands = (stopBand - startBand - 1) / stride + 1;
+ createMapping(aMap, startBand, stopBand, stride);
+ mapFrequency(&cmpIdxData[xttIdx][setIdx][0],
+ &outputIdxData[xttIdx][parmSlot][0], aMap, dataBands);
+ for (band = startBand; band < stopBand; band++) {
+ idxPrev[xttIdx][band] = outputIdxData[xttIdx][parmSlot][band];
+ }
+ llData->state->bsQuantCoarseXXXprev = llData->bsQuantCoarseXXX[setIdx];
+ llData->nocmpQuantCoarseXXX[i] = llData->bsQuantCoarseXXX[setIdx];
+
+ setIdx++;
+ }
+ if (diffIdxData != NULL) {
+ for (band = startBand; band < stopBand; band++) {
+ outputIdxData[xttIdx][i][band] += diffIdxData[xttIdx][i][band];
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ /* Map all coarse data to fine */
+ for (i = 0; i < numParameterSets; i++) {
+ if (llData->nocmpQuantCoarseXXX[i] == 1) {
+ coarse2fine(outputIdxData[xttIdx][i], (DATA_TYPE)paramType, startBand,
+ stopBand - startBand);
+ llData->nocmpQuantCoarseXXX[i] = 0;
+ }
+ }
+
+ /* Interpolate */
+ i1 = 0;
+ for (i = 0; i < numParameterSets; i++) {
+ int xi, i2, x1, x2;
+
+ if (aInterpolate[i] != 1) {
+ i1 = i;
+ }
+ i2 = i;
+ while (aInterpolate[i2] == 1) {
+ i2++;
+ }
+ x1 = paramSlot[i1];
+ xi = paramSlot[i];
+ x2 = paramSlot[i2];
+
+ if (aInterpolate[i] == 1) {
+ if (i2 >= numParameterSets) return MPS_WRONG_PARAMETERSETS;
+ for (band = startBand; band < stopBand; band++) {
+ int yi, y1, y2;
+ y1 = outputIdxData[xttIdx][i1][band];
+ y2 = outputIdxData[xttIdx][i2][band];
+ if (x1 != x2) {
+ yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1);
+ } else {
+ yi = y1 /*+ (xi-x1)*(y2-y1)/1e-12*/;
+ }
+ outputIdxData[xttIdx][i][band] = yi;
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ /* Dequantize data and apply factorCLD if necessary */
+ for (ps = 0; ps < numParameterSets; ps++) {
+ if (quantMode && (paramType == t_CLD)) {
+ if (pOttVsTotDbIn == 0) return MPS_WRONG_OTT;
+ if ((pOttVsTotDb1 == 0) && (ottVsTotDbMode == ottVsTotDb1Activ))
+ return MPS_WRONG_OTT;
+ if ((pOttVsTotDb2 == 0) && (ottVsTotDbMode == ottVsTotDb2Activ))
+ return MPS_WRONG_OTT;
+
+ for (pb = startBand; pb < stopBand; pb++) {
+ factorCLD(&(outputIdxData[xttIdx][ps][pb]), (*pOttVsTotDbIn)[ps][pb],
+ (pOttVsTotDb1 != NULL) ? &((*pOttVsTotDb1)[ps][pb]) : NULL,
+ (pOttVsTotDb2 != NULL) ? &((*pOttVsTotDb2)[ps][pb]) : NULL,
+ ottVsTotDbMode, quantMode);
+ }
+ }
+
+ /* Dequantize data */
+ for (band = startBand; band < stopBand; band++) {
+ outputDataIdx[xttIdx][ps][band] =
+ deqIdx(outputIdxData[xttIdx][ps][band], paramType);
+ if (outputDataIdx[xttIdx][ps][band] == -1) {
+ outputDataIdx[xttIdx][ps][band] = defaultValue;
+ }
+ }
+ } /* for( i = 0 ; i < numParameterSets; i++ ) */
+
+ if (extendFrame) {
+ for (band = startBand; band < stopBand; band++) {
+ outputDataIdx[xttIdx][numParameterSets][band] =
+ outputDataIdx[xttIdx][numParameterSets - 1][band];
+ }
+ }
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameOtt
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameOtt(HANDLE_SPATIAL_DEC self,
+ SPATIAL_BS_FRAME *pCurBs) {
+ int i, ottIdx;
+ int numOttBoxes;
+
+ SACDEC_ERROR err = MPS_OK;
+
+ numOttBoxes = self->numOttBoxes;
+
+ switch (self->treeConfig) {
+ default: {
+ if (self->quantMode != 0) {
+ goto bail;
+ }
+ }
+ for (i = 0; i < numOttBoxes; i++) {
+ err = mapIndexData(
+ &pCurBs->CLDLosslessData[i], /* LOSSLESSDATA *llData,*/
+ self->ottCLD__FDK, self->outIdxData,
+ pCurBs
+ ->cmpOttCLDidx, /* int
+ cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ */
+ NULL, /* no differential data */
+ i, /* int xttIdx, Which ott/ttt index to use for input and
+ output buffers */
+ self->ottCLDidxPrev, /* int
+ idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS],
+ */
+ i, t_CLD, 0, /* int startBand, */
+ self->pConfigCurrent->bitstreamOttBands[i], /* int stopBand, */
+ self->pConfigCurrent->ottCLDdefault[i], /* int defaultValue, */
+ pCurBs->numParameterSets, /* int numParameterSets) */
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+
+ } /* for(i = 0; i < numOttBoxes ; i++ ) */
+ break;
+ } /* case */
+
+ for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) {
+ /* Read ICC */
+ err = mapIndexData(
+ &pCurBs->ICCLosslessData[ottIdx], /* LOSSLESSDATA *llData,*/
+ self->ottICC__FDK, self->outIdxData,
+ pCurBs
+ ->cmpOttICCidx, /* int
+ cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS],
+ */
+ self->ottICCdiffidx, /* differential data */
+ ottIdx, /* int xttIdx, Which ott/ttt index to use for input and
+ output buffers */
+ self->ottICCidxPrev, /* int idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS],
+ */
+ ottIdx, t_ICC, 0, /* int startBand, */
+ self->pConfigCurrent->bitstreamOttBands[ottIdx], /* int stopBand, */
+ ICCdefault, /* int defaultValue, */
+ pCurBs->numParameterSets, /* int numParameterSets) */
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+ } /* ottIdx */
+
+ if ((self->treeConfig == TREE_212) && (self->phaseCoding)) {
+ if (pCurBs->phaseMode == 0) {
+ for (int pb = 0; pb < self->pConfigCurrent->numOttBandsIPD; pb++) {
+ self->ottIPDidxPrev[0][pb] = 0;
+ }
+ }
+ for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) {
+ err = mapIndexData(
+ &pCurBs->IPDLosslessData[ottIdx], self->ottIPD__FDK, self->outIdxData,
+ pCurBs->cmpOttIPDidx, NULL, ottIdx, self->ottIPDidxPrev, ottIdx,
+ t_IPD, 0, self->numOttBandsIPD, IPDdefault, pCurBs->numParameterSets,
+ pCurBs->paramSlot, self->extendFrame, self->quantMode,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ }
+ }
+
+bail:
+
+ return MPS_OK;
+
+} /* decodeAndMapFrameOtt */
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameSmg
+ *******************************************************************************
+
+ Description:
+ Decode smoothing flags
+
+ Arguments:
+
+Input:
+
+Output:
+
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameSmg(HANDLE_SPATIAL_DEC self,
+ const SPATIAL_BS_FRAME *frame) {
+ int ps, pb, pg, pbStride, dataBands, pbStart, pbStop,
+ aGroupToBand[MAX_PARAMETER_BANDS + 1];
+
+ if (frame->numParameterSets > MAX_PARAMETER_SETS)
+ return MPS_WRONG_PARAMETERSETS;
+ if (self->bitstreamParameterBands > MAX_PARAMETER_BANDS)
+ return MPS_WRONG_PARAMETERBANDS;
+
+ for (ps = 0; ps < frame->numParameterSets; ps++) {
+ switch (frame->bsSmoothMode[ps]) {
+ case 0:
+ self->smgTime[ps] = 256;
+ FDKmemclear(self->smgData[ps],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ break;
+
+ case 1:
+ if (ps > 0) {
+ self->smgTime[ps] = self->smgTime[ps - 1];
+ FDKmemcpy(self->smgData[ps], self->smgData[ps - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ } else {
+ self->smgTime[ps] = self->smoothState->prevSmgTime;
+ FDKmemcpy(self->smgData[ps], self->smoothState->prevSmgData,
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ }
+ break;
+
+ case 2:
+ self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]];
+ for (pb = 0; pb < self->bitstreamParameterBands; pb++) {
+ self->smgData[ps][pb] = 1;
+ }
+ break;
+
+ case 3:
+ self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]];
+ pbStride = pbStrideTable[frame->bsFreqResStrideSmg[ps]];
+ dataBands = (self->bitstreamParameterBands - 1) / pbStride + 1;
+ createMapping(aGroupToBand, 0, self->bitstreamParameterBands, pbStride);
+ for (pg = 0; pg < dataBands; pg++) {
+ pbStart = aGroupToBand[pg];
+ pbStop = aGroupToBand[pg + 1];
+ for (pb = pbStart; pb < pbStop; pb++) {
+ self->smgData[ps][pb] = frame->bsSmgData[ps][pg];
+ }
+ }
+ break;
+ }
+ }
+
+ self->smoothState->prevSmgTime = self->smgTime[frame->numParameterSets - 1];
+ FDKmemcpy(self->smoothState->prevSmgData,
+ self->smgData[frame->numParameterSets - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+
+ if (self->extendFrame) {
+ self->smgTime[frame->numParameterSets] =
+ self->smgTime[frame->numParameterSets - 1];
+ FDKmemcpy(self->smgData[frame->numParameterSets],
+ self->smgData[frame->numParameterSets - 1],
+ self->bitstreamParameterBands * sizeof(UCHAR));
+ }
+
+ return MPS_OK;
+}
+
+/*******************************************************************************
+ Functionname: decodeAndMapFrameArbdmx
+ *******************************************************************************
+
+ Description:
+ Do delta decoding and dequantization
+
+ Arguments:
+
+Input:
+
+Output:
+
+*******************************************************************************/
+static SACDEC_ERROR decodeAndMapFrameArbdmx(HANDLE_SPATIAL_DEC self,
+ const SPATIAL_BS_FRAME *frame) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+ int offset = self->numOttBoxes;
+
+ for (ch = 0; ch < self->numInputChannels; ch++) {
+ err = mapIndexData(&frame->CLDLosslessData[offset + ch],
+ self->arbdmxGain__FDK, self->outIdxData,
+ frame->cmpArbdmxGainIdx, NULL, /* no differential data */
+ ch, self->arbdmxGainIdxPrev, offset + ch, t_CLD, 0,
+ self->bitstreamParameterBands,
+ 0 /*self->arbdmxGainDefault*/, frame->numParameterSets,
+ frame->paramSlot, self->extendFrame, 0,
+ &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL);
+ if (err != MPS_OK) goto bail;
+ }
+
+bail:
+ return err;
+} /* decodeAndMapFrameArbdmx */
+
+/*******************************************************************************
+ Functionname: SpatialDecDecodeFrame
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame) {
+ SACDEC_ERROR err = MPS_OK;
+
+ self->extendFrame = 0;
+ if (frame->paramSlot[frame->numParameterSets - 1] != self->timeSlots - 1) {
+ self->extendFrame = 1;
+ }
+
+ self->TsdTs = 0;
+
+ /****** DTDF and MAP DATA ********/
+ if ((err = decodeAndMapFrameOtt(self, frame)) != MPS_OK) goto bail;
+
+ if ((err = decodeAndMapFrameSmg(self, frame)) != MPS_OK) goto bail;
+
+ if (self->arbitraryDownmix != 0) {
+ if ((err = decodeAndMapFrameArbdmx(self, frame)) != MPS_OK) goto bail;
+ }
+
+ if (self->extendFrame) {
+ frame->numParameterSets =
+ fixMin(MAX_PARAMETER_SETS, frame->numParameterSets + 1);
+ frame->paramSlot[frame->numParameterSets - 1] = self->timeSlots - 1;
+ }
+
+bail:
+ return err;
+} /* SpatialDecDecodeFrame() */
+
+/*******************************************************************************
+ Functionname: SpatialDecodeHeader
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+SACDEC_ERROR SpatialDecDecodeHeader(
+ spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig) {
+ SACDEC_ERROR err = MPS_OK;
+ int i;
+
+ self->samplingFreq = pSpatialSpecificConfig->samplingFreq;
+ self->timeSlots = pSpatialSpecificConfig->nTimeSlots;
+ self->frameLength = self->timeSlots * self->qmfBands;
+ self->bitstreamParameterBands = pSpatialSpecificConfig->freqRes;
+
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)
+ self->hybridBands = self->qmfBands;
+ else
+ self->hybridBands = SacGetHybridSubbands(self->qmfBands);
+ self->tp_hybBandBorder = 12;
+
+ self->numParameterBands = self->bitstreamParameterBands;
+
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
+ switch (self->numParameterBands) {
+ case 4:
+ self->kernels = kernels_4_to_64;
+ break;
+ case 5:
+ self->kernels = kernels_5_to_64;
+ break;
+ case 7:
+ self->kernels = kernels_7_to_64;
+ break;
+ case 9:
+ self->kernels = kernels_9_to_64;
+ break;
+ case 12:
+ self->kernels = kernels_12_to_64;
+ break;
+ case 15:
+ self->kernels = kernels_15_to_64;
+ break;
+ case 23:
+ self->kernels = kernels_23_to_64;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */
+ }
+ } else {
+ switch (self->numParameterBands) {
+ case 4:
+ self->kernels = kernels_4_to_71;
+ break;
+ case 5:
+ self->kernels = kernels_5_to_71;
+ break;
+ case 7:
+ self->kernels = kernels_7_to_71;
+ break;
+ case 10:
+ self->kernels = kernels_10_to_71;
+ break;
+ case 14:
+ self->kernels = kernels_14_to_71;
+ break;
+ case 20:
+ self->kernels = kernels_20_to_71;
+ break;
+ case 28:
+ self->kernels = kernels_28_to_71;
+ break;
+ default:
+ return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */
+ }
+ }
+
+ /* create param to hyb band table */
+ FDKmemclear(self->param2hyb, (MAX_PARAMETER_BANDS + 1) * sizeof(int));
+ for (i = 0; i < self->hybridBands; i++) {
+ self->param2hyb[self->kernels[i] + 1] = i + 1;
+ }
+ {
+ int pb = self->kernels[i - 1] + 2;
+ for (; pb < (MAX_PARAMETER_BANDS + 1); pb++) {
+ self->param2hyb[pb] = i;
+ }
+ for (pb = 0; pb < MAX_PARAMETER_BANDS; pb += 1) {
+ self->kernels_width[pb] = self->param2hyb[pb + 1] - self->param2hyb[pb];
+ }
+ }
+
+ self->treeConfig = pSpatialSpecificConfig->treeConfig;
+
+ self->numOttBoxes = pSpatialSpecificConfig->nOttBoxes;
+
+ self->numInputChannels = pSpatialSpecificConfig->nInputChannels;
+
+ self->numOutputChannels = pSpatialSpecificConfig->nOutputChannels;
+
+ self->quantMode = pSpatialSpecificConfig->quantMode;
+
+ self->arbitraryDownmix = pSpatialSpecificConfig->bArbitraryDownmix;
+
+ self->numM2rows = self->numOutputChannels;
+
+ {
+ self->residualCoding = 0;
+ if (self->arbitraryDownmix == 2)
+ self->arbitraryDownmix = 1; /* no arbitrary downmix residuals */
+ }
+ if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC)) {
+ self->residualCoding = pSpatialSpecificConfig->bResidualCoding;
+ }
+
+ self->clipProtectGain__FDK =
+ FX_CFG2FX_DBL(clipGainTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]);
+ self->clipProtectGainSF__FDK =
+ clipGainSFTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX];
+
+ self->tempShapeConfig = pSpatialSpecificConfig->tempShapeConfig;
+
+ self->decorrConfig = pSpatialSpecificConfig->decorrConfig;
+
+ if (self->upmixType == UPMIXTYPE_BYPASS) {
+ self->numOutputChannels = self->numInputChannels;
+ }
+
+ self->numOutputChannelsAT = self->numOutputChannels;
+
+ self->numOttBandsIPD = pSpatialSpecificConfig->numOttBandsIPD;
+ self->phaseCoding = pSpatialSpecificConfig->bsPhaseCoding;
+ for (i = 0; i < self->numOttBoxes; i++) {
+ {
+ self->pConfigCurrent->bitstreamOttBands[i] =
+ self->bitstreamParameterBands;
+ }
+ self->numOttBands[i] = self->pConfigCurrent->bitstreamOttBands[i];
+ } /* i */
+
+ if (self->residualCoding) {
+ int numBoxes = self->numOttBoxes;
+ for (i = 0; i < numBoxes; i++) {
+ self->residualPresent[i] =
+ pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent;
+
+ if (self->residualPresent[i]) {
+ self->residualBands[i] =
+ pSpatialSpecificConfig->ResidualConfig[i].nResidualBands;
+ /* conversion from hybrid bands to qmf bands */
+ self->residualQMFBands[i] =
+ fMax(self->param2hyb[self->residualBands[i]] + 3 - 10,
+ 3); /* simplification for the lowest 10 hybrid bands */
+ } else {
+ self->residualBands[i] = 0;
+ self->residualQMFBands[i] = 0;
+ }
+ }
+ } /* self->residualCoding */
+ else {
+ int boxes = self->numOttBoxes;
+ for (i = 0; i < boxes; i += 1) {
+ self->residualPresent[i] = 0;
+ self->residualBands[i] = 0;
+ }
+ }
+
+ switch (self->treeConfig) {
+ case TREE_212:
+ self->numDirektSignals = 1;
+ self->numDecorSignals = 1;
+ self->numXChannels = 1;
+ if (self->arbitraryDownmix == 2) {
+ self->numXChannels += 1;
+ }
+ self->numVChannels = self->numDirektSignals + self->numDecorSignals;
+ break;
+ default:
+ return MPS_INVALID_TREECONFIG;
+ }
+
+ self->highRateMode = pSpatialSpecificConfig->bsHighRateMode;
+ self->decorrType = pSpatialSpecificConfig->bsDecorrType;
+
+ SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL);
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCreateBsFrame
+ *******************************************************************************
+
+ Description: Create spatial bitstream structure
+
+ Arguments: spatialDec* self
+ const SPATIAL_BS_FRAME **bsFrame
+
+ Return: -
+
+*******************************************************************************/
+SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame,
+ BS_LL_STATE *llState) {
+ SPATIAL_BS_FRAME *pBs = bsFrame;
+
+ const int maxNumOtt = MAX_NUM_OTT;
+ const int maxNumInputChannels = MAX_INPUT_CHANNELS;
+
+ FDK_ALLOCATE_MEMORY_1D_P(
+ pBs->cmpOttIPDidx, maxNumOtt * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS,
+ SCHAR, SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS])
+
+ /* Arbitrary Downmix */
+ FDK_ALLOCATE_MEMORY_1D_P(
+ pBs->cmpArbdmxGainIdx,
+ maxNumInputChannels * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, SCHAR,
+ SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS])
+
+ /* Lossless control */
+ FDK_ALLOCATE_MEMORY_1D(pBs->CLDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+ FDK_ALLOCATE_MEMORY_1D(pBs->ICCLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+
+ FDK_ALLOCATE_MEMORY_1D(pBs->IPDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA)
+
+ pBs->newBsData = 0;
+ pBs->numParameterSets = 1;
+
+ /* Link lossless states */
+ for (int x = 0; x < MAX_NUM_PARAMETERS; x++) {
+ pBs->CLDLosslessData[x].state = &llState->CLDLosslessState[x];
+ pBs->ICCLosslessData[x].state = &llState->ICCLosslessState[x];
+
+ pBs->IPDLosslessData[x].state = &llState->IPDLosslessState[x];
+ }
+
+ return MPS_OK;
+
+bail:
+ return MPS_OUTOFMEMORY;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCloseBsFrame
+ *******************************************************************************
+
+ Description: Close spatial bitstream structure
+
+ Arguments: spatialDec* self
+
+ Return: -
+
+*******************************************************************************/
+void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *pBs) {
+ if (pBs != NULL) {
+ /* These arrays contain the compact indices, only one value per pbstride,
+ * only paramsets actually containing data. */
+
+ FDK_FREE_MEMORY_1D(pBs->cmpOttIPDidx);
+
+ /* Arbitrary Downmix */
+ FDK_FREE_MEMORY_1D(pBs->cmpArbdmxGainIdx);
+
+ /* Lossless control */
+ FDK_FREE_MEMORY_1D(pBs->IPDLosslessData);
+ FDK_FREE_MEMORY_1D(pBs->CLDLosslessData);
+ FDK_FREE_MEMORY_1D(pBs->ICCLosslessData);
+ }
+}
diff --git a/libSACdec/src/sac_bitdec.h b/libSACdec/src/sac_bitdec.h
new file mode 100644
index 0000000..cb0c7d2
--- /dev/null
+++ b/libSACdec/src/sac_bitdec.h
@@ -0,0 +1,161 @@
+/* -----------------------------------------------------------------------------
+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
+
+*******************************************************************************/
+
+/*!
+ \file
+ \brief Spatial Audio bitstream decoder
+*/
+
+#ifndef SAC_BITDEC_H
+#define SAC_BITDEC_H
+
+#include "sac_dec.h"
+
+typedef struct {
+ SCHAR numInputChannels;
+ SCHAR numOutputChannels;
+ SCHAR numOttBoxes;
+ SCHAR numTttBoxes;
+ SCHAR ottModeLfe[MAX_NUM_OTT];
+} TREEPROPERTIES;
+
+enum { TREE_212 = 7, TREE_DUMMY = 255 };
+
+enum { QUANT_FINE = 0, QUANT_EBQ1 = 1, QUANT_EBQ2 = 2 };
+
+SACDEC_ERROR SpatialDecParseSpecificConfigHeader(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType);
+
+SACDEC_ERROR SpatialDecParseMps212Config(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate,
+ AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex,
+ INT coreSbrFrameLengthIndex);
+
+SACDEC_ERROR SpatialDecParseSpecificConfig(
+ HANDLE_FDK_BITSTREAM bitstream,
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen,
+ AUDIO_OBJECT_TYPE coreCodec);
+
+int SpatialDecDefaultSpecificConfig(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots,
+ int sacDecoderLevel, int isBlind, int coreChannels);
+
+SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame,
+ BS_LL_STATE *llState);
+
+void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *bsFrame);
+
+SACDEC_ERROR SpatialDecParseFrameData(
+ spatialDec *self, SPATIAL_BS_FRAME *frame, HANDLE_FDK_BITSTREAM bitstream,
+ const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType,
+ int fGlobalIndependencyFlag);
+
+SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame);
+
+SACDEC_ERROR SpatialDecDecodeHeader(
+ spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig);
+
+#endif
diff --git a/libSACdec/src/sac_calcM1andM2.cpp b/libSACdec/src/sac_calcM1andM2.cpp
new file mode 100644
index 0000000..6e5a145
--- /dev/null
+++ b/libSACdec/src/sac_calcM1andM2.cpp
@@ -0,0 +1,848 @@
+/* -----------------------------------------------------------------------------
+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 M1 and M2 calculation
+
+*******************************************************************************/
+
+#include "sac_calcM1andM2.h"
+#include "sac_bitdec.h"
+#include "sac_process.h"
+#include "sac_rom.h"
+#include "sac_smoothing.h"
+#include "FDK_trigFcts.h"
+
+/* assorted definitions and constants */
+
+#define ABS_THR2 1.0e-9
+#define SQRT2_FDK \
+ ((FIXP_DBL)FL2FXCONST_DBL(0.70710678118f)) /* FDKsqrt(2.0) scaled by 0.5 */
+
+static void param2UMX_PS__FDK(spatialDec* self,
+ FIXP_DBL H11[MAX_PARAMETER_BANDS],
+ FIXP_DBL H12[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21[MAX_PARAMETER_BANDS],
+ FIXP_DBL H22[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx,
+ int parameterSetIndx, int resBands);
+
+static void param2UMX_PS_Core__FDK(
+ const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS],
+ const int numOttBands, const int resBands,
+ FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]);
+
+static void param2UMX_PS_IPD_OPD__FDK(
+ spatialDec* self, const SPATIAL_BS_FRAME* frame,
+ FIXP_DBL H11re[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21re[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS],
+ int ottBoxIndx, int parameterSetIndx, int residualBands);
+
+static void param2UMX_Prediction__FDK(
+ spatialDec* self, FIXP_DBL H11re[MAX_PARAMETER_BANDS],
+ FIXP_DBL H11im[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS],
+ FIXP_DBL H12im[MAX_PARAMETER_BANDS], FIXP_DBL H21re[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21im[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS],
+ FIXP_DBL H22im[MAX_PARAMETER_BANDS], int ottBoxIndx, int parameterSetIndx,
+ int resBands);
+
+/* static void SpatialDecCalculateM0(spatialDec* self,int ps); */
+static SACDEC_ERROR SpatialDecCalculateM1andM2_212(
+ spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame);
+
+/*******************************************************************************
+ Functionname: SpatialDecGetResidualIndex
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+*******************************************************************************/
+int SpatialDecGetResidualIndex(spatialDec* self, int row) {
+ return row2residual[self->treeConfig][row];
+}
+
+/*******************************************************************************
+ Functionname: UpdateAlpha
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+*******************************************************************************/
+static void updateAlpha(spatialDec* self) {
+ int nChIn = self->numInputChannels;
+ int ch;
+
+ for (ch = 0; ch < nChIn; ch++) {
+ FIXP_DBL alpha = /* FL2FXCONST_DBL(1.0f) */ (FIXP_DBL)MAXVAL_DBL;
+
+ self->arbdmxAlphaPrev__FDK[ch] = self->arbdmxAlpha__FDK[ch];
+
+ self->arbdmxAlpha__FDK[ch] = alpha;
+ }
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCalculateM1andM2
+ *******************************************************************************
+ Description:
+ Arguments:
+*******************************************************************************/
+SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps,
+ const SPATIAL_BS_FRAME* frame) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if ((self->arbitraryDownmix != 0) && (ps == 0)) {
+ updateAlpha(self);
+ }
+
+ self->pActivM2ParamBands = NULL;
+
+ switch (self->upmixType) {
+ case UPMIXTYPE_BYPASS:
+ case UPMIXTYPE_NORMAL:
+ switch (self->treeConfig) {
+ case TREE_212:
+ err = SpatialDecCalculateM1andM2_212(self, ps, frame);
+ break;
+ default:
+ err = MPS_WRONG_TREECONFIG;
+ };
+ break;
+
+ default:
+ err = MPS_WRONG_TREECONFIG;
+ }
+
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+bail:
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecCalculateM1andM2_212
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static SACDEC_ERROR SpatialDecCalculateM1andM2_212(
+ spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame) {
+ SACDEC_ERROR err = MPS_OK;
+ int pb;
+
+ FIXP_DBL H11re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+ FIXP_DBL H12re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+ FIXP_DBL H21re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+ FIXP_DBL H22re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+ FIXP_DBL H11im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+ FIXP_DBL H21im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
+
+ INT phaseCoding = self->phaseCoding;
+
+ switch (phaseCoding) {
+ case 1:
+ /* phase coding: yes; residuals: no */
+ param2UMX_PS_IPD_OPD__FDK(self, frame, H11re, H12re, H21re, H22re, NULL,
+ NULL, 0, ps, self->residualBands[0]);
+ break;
+ case 3:
+ /* phase coding: yes; residuals: yes */
+ param2UMX_Prediction__FDK(self, H11re, H11im, H12re, NULL, H21re, H21im,
+ H22re, NULL, 0, ps, self->residualBands[0]);
+ break;
+ default:
+ if (self->residualCoding) {
+ /* phase coding: no; residuals: yes */
+ param2UMX_Prediction__FDK(self, H11re, NULL, H12re, NULL, H21re, NULL,
+ H22re, NULL, 0, ps, self->residualBands[0]);
+ } else {
+ /* phase coding: no; residuals: no */
+ param2UMX_PS__FDK(self, H11re, H12re, H21re, H22re, NULL, NULL, 0, ps,
+ 0);
+ }
+ break;
+ }
+
+ for (pb = 0; pb < self->numParameterBands; pb++) {
+ self->M2Real__FDK[0][0][pb] = (H11re[pb]);
+ self->M2Real__FDK[0][1][pb] = (H12re[pb]);
+
+ self->M2Real__FDK[1][0][pb] = (H21re[pb]);
+ self->M2Real__FDK[1][1][pb] = (H22re[pb]);
+ }
+ if (phaseCoding == 3) {
+ for (pb = 0; pb < self->numParameterBands; pb++) {
+ self->M2Imag__FDK[0][0][pb] = (H11im[pb]);
+ self->M2Imag__FDK[1][0][pb] = (H21im[pb]);
+ self->M2Imag__FDK[0][1][pb] = (FIXP_DBL)0; // H12im[pb];
+ self->M2Imag__FDK[1][1][pb] = (FIXP_DBL)0; // H22im[pb];
+ }
+ }
+
+ if (self->phaseCoding == 1) {
+ SpatialDecSmoothOPD(
+ self, frame,
+ ps); /* INPUT: PhaseLeft, PhaseRight, (opdLeftState, opdRightState) */
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: param2UMX_PS_Core
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void param2UMX_PS_Core__FDK(
+ const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS],
+ const int numOttBands, const int resBands,
+ FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]) {
+ int band;
+
+ if ((c_l != NULL) && (c_r != NULL)) {
+ for (band = 0; band < numOttBands; band++) {
+ SpatialDequantGetCLDValues(cld[band], &c_l[band], &c_r[band]);
+ }
+ }
+
+ band = 0;
+ FDK_ASSERT(resBands == 0);
+ for (; band < numOttBands; band++) {
+ /* compute mixing variables: */
+ const int idx1 = cld[band];
+ const int idx2 = icc[band];
+ H11[band] = FX_CFG2FX_DBL(H11_nc[idx1][idx2]);
+ H21[band] = FX_CFG2FX_DBL(H11_nc[30 - idx1][idx2]);
+ H12[band] = FX_CFG2FX_DBL(H12_nc[idx1][idx2]);
+ H22[band] = FX_CFG2FX_DBL(-H12_nc[30 - idx1][idx2]);
+ }
+}
+
+/*******************************************************************************
+ Functionname: param2UMX_PS
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void param2UMX_PS__FDK(spatialDec* self,
+ FIXP_DBL H11[MAX_PARAMETER_BANDS],
+ FIXP_DBL H12[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21[MAX_PARAMETER_BANDS],
+ FIXP_DBL H22[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx,
+ int parameterSetIndx, int residualBands) {
+ int band;
+ param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx],
+ self->ottICC__FDK[ottBoxIndx][parameterSetIndx],
+ self->numOttBands[ottBoxIndx], residualBands, H11, H12,
+ H21, H22, c_l, c_r);
+
+ for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands;
+ band++) {
+ H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f);
+ }
+}
+
+#define N_CLD (31)
+#define N_IPD (16)
+
+static const FIXP_DBL sinIpd_tab[N_IPD] = {
+ FIXP_DBL(0x00000000), FIXP_DBL(0x30fbc54e), FIXP_DBL(0x5a827999),
+ FIXP_DBL(0x7641af3d), FIXP_DBL(0x7fffffff), FIXP_DBL(0x7641af3d),
+ FIXP_DBL(0x5a82799a), FIXP_DBL(0x30fbc54d), FIXP_DBL(0xffffffff),
+ FIXP_DBL(0xcf043ab3), FIXP_DBL(0xa57d8666), FIXP_DBL(0x89be50c3),
+ FIXP_DBL(0x80000000), FIXP_DBL(0x89be50c3), FIXP_DBL(0xa57d8666),
+ FIXP_DBL(0xcf043ab2),
+};
+
+/* cosIpd[i] = sinIpd[(i+4)&15] */
+#define SIN_IPD(a) (sinIpd_tab[(a)])
+#define COS_IPD(a) (sinIpd_tab[((a) + 4) & 15]) //(cosIpd_tab[(a)])
+
+static const FIXP_SGL sqrt_one_minus_ICC2[8] = {
+ FL2FXCONST_SGL(0.0f),
+ FL2FXCONST_SGL(0.349329357483736f),
+ FL2FXCONST_SGL(0.540755219669676f),
+ FL2FXCONST_SGL(0.799309172723546f),
+ FL2FXCONST_SGL(0.929968187843004f),
+ FX_DBL2FXCONST_SGL(MAXVAL_DBL),
+ FL2FXCONST_SGL(0.80813303360276f),
+ FL2FXCONST_SGL(0.141067359796659f),
+};
+
+/* exponent of sqrt(CLD) */
+static const SCHAR sqrt_CLD_e[N_CLD] = {
+ -24, -7, -6, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1,
+ 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 25};
+
+static const FIXP_DBL sqrt_CLD_m[N_CLD] = {
+ FL2FXCONST_DBL(0.530542153566195f),
+ FL2FXCONST_DBL(0.719796896243647f),
+ FL2FXCONST_DBL(0.64f),
+ FL2FXCONST_DBL(0.569049411212455f),
+ FL2FXCONST_DBL(0.505964425626941f),
+ FL2FXCONST_DBL(0.899746120304559f),
+ FL2FXCONST_DBL(0.635462587779425f),
+ FL2FXCONST_DBL(0.897614763441571f),
+ FL2FXCONST_DBL(0.633957276984445f),
+ FL2FXCONST_DBL(0.895488455427336f),
+ FL2FXCONST_DBL(0.632455532033676f),
+ FL2FXCONST_DBL(0.796214341106995f),
+ FL2FXCONST_DBL(0.501187233627272f),
+ FL2FXCONST_DBL(0.630957344480193f),
+ FL2FXCONST_DBL(0.794328234724281f),
+ FL2FXCONST_DBL(0.5f),
+ FL2FXCONST_DBL(0.629462705897084f),
+ FL2FXCONST_DBL(0.792446596230557f),
+ FL2FXCONST_DBL(0.99763115748444f),
+ FL2FXCONST_DBL(0.627971607877395f),
+ FL2FXCONST_DBL(0.790569415042095f),
+ FL2FXCONST_DBL(0.558354490188704f),
+ FL2FXCONST_DBL(0.788696680600242f),
+ FL2FXCONST_DBL(0.557031836333591f),
+ FL2FXCONST_DBL(0.786828382371355f),
+ FL2FXCONST_DBL(0.555712315637163f),
+ FL2FXCONST_DBL(0.988211768802619f),
+ FL2FXCONST_DBL(0.87865832060992f),
+ FL2FXCONST_DBL(0.78125f),
+ FL2FXCONST_DBL(0.694640394546454f),
+ FL2FXCONST_DBL(0.942432183077448f),
+};
+
+static const FIXP_DBL CLD_m[N_CLD] = {
+ FL2FXCONST_DBL(0.281474976710656f),
+ FL2FXCONST_DBL(0.518107571841987f),
+ FL2FXCONST_DBL(0.4096f),
+ FL2FXCONST_DBL(0.323817232401242f),
+ FL2FXCONST_DBL(0.256f),
+ FL2FXCONST_DBL(0.809543081003105f),
+ FL2FXCONST_DBL(0.403812700467324f),
+ FL2FXCONST_DBL(0.805712263548267f),
+ FL2FXCONST_DBL(0.401901829041533f),
+ FL2FXCONST_DBL(0.801899573803636f),
+ FL2FXCONST_DBL(0.4f),
+ FL2FXCONST_DBL(0.633957276984445f),
+ FL2FXCONST_DBL(0.251188643150958f),
+ FL2FXCONST_DBL(0.398107170553497f),
+ FL2FXCONST_DBL(0.630957344480193f),
+ FL2FXCONST_DBL(0.25f),
+ FL2FXCONST_DBL(0.396223298115278f),
+ FL2FXCONST_DBL(0.627971607877395f),
+ FL2FXCONST_DBL(0.995267926383743f),
+ FL2FXCONST_DBL(0.394348340300121f),
+ FL2FXCONST_DBL(0.625f),
+ FL2FXCONST_DBL(0.311759736713887f),
+ FL2FXCONST_DBL(0.62204245398984f),
+ FL2FXCONST_DBL(0.310284466689172f),
+ FL2FXCONST_DBL(0.619098903305123f),
+ FL2FXCONST_DBL(0.308816177750818f),
+ FL2FXCONST_DBL(0.9765625f),
+ FL2FXCONST_DBL(0.772040444377046f),
+ FL2FXCONST_DBL(0.6103515625f),
+ FL2FXCONST_DBL(0.482525277735654f),
+ FL2FXCONST_DBL(0.888178419700125),
+};
+
+static FIXP_DBL dequantIPD_CLD_ICC_splitAngle__FDK_Function(INT ipdIdx,
+ INT cldIdx,
+ INT iccIdx) {
+ FIXP_DBL cld;
+ SpatialDequantGetCLD2Values(cldIdx, &cld);
+
+ /*const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL;
+ const int one_e = 0;*/
+ const FIXP_DBL one_m = FL2FXCONST_DBL(0.5f);
+ const int one_e = 1;
+ /* iidLin = sqrt(cld); */
+ FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx];
+ int iidLin_e = sqrt_CLD_e[cldIdx];
+ /* iidLin2 = cld; */
+ FIXP_DBL iidLin2_m = CLD_m[cldIdx];
+ int iidLin2_e = sqrt_CLD_e[cldIdx] << 1;
+ /* iidLin21 = iidLin2 + 1.0f; */
+ int iidLin21_e;
+ FIXP_DBL iidLin21_m =
+ fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e);
+ /* iidIcc2 = iidLin * icc * 2.0f; */
+ FIXP_CFG icc = dequantICC__FDK[iccIdx];
+ FIXP_DBL temp1_m, temp1c_m;
+ int temp1_e, temp1c_e;
+ temp1_m = fMult(iidLin_m, icc);
+ temp1_e = iidLin_e + 1;
+
+ FIXP_DBL cosIpd, sinIpd;
+ cosIpd = COS_IPD(ipdIdx);
+ sinIpd = SIN_IPD(ipdIdx);
+
+ temp1c_m = fMult(temp1_m, cosIpd);
+ temp1c_e = temp1_e; //+cosIpd_e;
+
+ int temp2_e, temp3_e, inv_temp3_e, ratio_e;
+ FIXP_DBL temp2_m =
+ fAddNorm(iidLin21_m, iidLin21_e, temp1c_m, temp1c_e, &temp2_e);
+ FIXP_DBL temp3_m =
+ fAddNorm(iidLin21_m, iidLin21_e, temp1_m, temp1_e, &temp3_e);
+ /* calculate 1/temp3 needed later */
+ inv_temp3_e = temp3_e;
+ FIXP_DBL inv_temp3_m = invFixp(temp3_m, &inv_temp3_e);
+ FIXP_DBL ratio_m =
+ fAddNorm(fMult(inv_temp3_m, temp2_m), (inv_temp3_e + temp2_e),
+ FL2FXCONST_DBL(1e-9f), 0, &ratio_e);
+
+ int weight2_e, tempb_atan2_e;
+ FIXP_DBL weight2_m =
+ fPow(ratio_m, ratio_e, FL2FXCONST_DBL(0.5f), -1, &weight2_e);
+ /* atan2(w2*sinIpd, w1*iidLin + w2*cosIpd) = atan2(w2*sinIpd, (2 - w2)*iidLin
+ * + w2*cosIpd) = atan2(w2*sinIpd, 2*iidLin + w2*(cosIpd - iidLin)); */
+ /* tmpa_atan2 = w2*sinIpd; tmpb_atan2 = 2*iidLin + w2*(cosIpd - iidLin); */
+ FIXP_DBL tempb_atan2_m = iidLin_m;
+ tempb_atan2_e = iidLin_e + 1;
+ int add_tmp1_e = 0;
+ FIXP_DBL add_tmp1_m = fAddNorm(cosIpd, 0, -iidLin_m, iidLin_e, &add_tmp1_e);
+ FIXP_DBL add_tmp2_m = fMult(add_tmp1_m, weight2_m);
+ int add_tmp2_e = add_tmp1_e + weight2_e;
+ tempb_atan2_m = fAddNorm(tempb_atan2_m, tempb_atan2_e, add_tmp2_m, add_tmp2_e,
+ &tempb_atan2_e);
+
+ FIXP_DBL tempa_atan2_m = fMult(weight2_m, sinIpd);
+ int tempa_atan2_e = weight2_e; // + sinIpd_e;
+
+ if (tempa_atan2_e > tempb_atan2_e) {
+ tempb_atan2_m = (tempb_atan2_m >> (tempa_atan2_e - tempb_atan2_e));
+ tempb_atan2_e = tempa_atan2_e;
+ } else if (tempb_atan2_e > tempa_atan2_e) {
+ tempa_atan2_m = (tempa_atan2_m >> (tempb_atan2_e - tempa_atan2_e));
+ }
+
+ return fixp_atan2(tempa_atan2_m, tempb_atan2_m);
+}
+
+static void calculateOpd(spatialDec* self, INT ottBoxIndx, INT parameterSetIndx,
+ FIXP_DBL opd[MAX_PARAMETER_BANDS]) {
+ INT band;
+
+ for (band = 0; band < self->numOttBandsIPD; band++) {
+ INT idxCld = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
+ INT idxIpd = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
+ INT idxIcc = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
+ FIXP_DBL cld, ipd;
+
+ ipd = FX_CFG2FX_DBL(dequantIPD__FDK[idxIpd]);
+
+ SpatialDequantGetCLD2Values(idxCld, &cld);
+
+ /* ipd(idxIpd==8) == PI */
+ if ((cld == FL2FXCONST_DBL(0.0f)) && (idxIpd == 8)) {
+ opd[2 * band] = FL2FXCONST_DBL(0.0f);
+ } else {
+ opd[2 * band] = (dequantIPD_CLD_ICC_splitAngle__FDK_Function(
+ idxIpd, idxCld, idxIcc) >>
+ (IPD_SCALE - AT2O_SF));
+ }
+ opd[2 * band + 1] = opd[2 * band] - ipd;
+ }
+}
+
+/* wrap phase in rad to the range of 0 <= x < 2*pi */
+static FIXP_DBL wrapPhase(FIXP_DBL phase) {
+ while (phase < (FIXP_DBL)0) phase += PIx2__IPD;
+ while (phase >= PIx2__IPD) phase -= PIx2__IPD;
+ FDK_ASSERT((phase >= (FIXP_DBL)0) && (phase < PIx2__IPD));
+
+ return phase;
+}
+
+/*******************************************************************************
+ Functionname: param2UMX_PS_IPD
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+static void param2UMX_PS_IPD_OPD__FDK(
+ spatialDec* self, const SPATIAL_BS_FRAME* frame,
+ FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
+ FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
+ FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS],
+ int ottBoxIndx, int parameterSetIndx, int residualBands) {
+ INT band;
+ FIXP_DBL opd[2 * MAX_PARAMETER_BANDS];
+ INT numOttBands = self->numOttBands[ottBoxIndx];
+ INT numIpdBands;
+
+ numIpdBands = frame->phaseMode ? self->numOttBandsIPD : 0;
+
+ FDK_ASSERT(self->residualCoding == 0);
+
+ param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx],
+ self->ottICC__FDK[ottBoxIndx][parameterSetIndx],
+ self->numOttBands[ottBoxIndx], residualBands, H11, H12,
+ H21, H22, c_l, c_r);
+
+ for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands;
+ band++) {
+ H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f);
+ }
+
+ if (frame->phaseMode) {
+ calculateOpd(self, ottBoxIndx, parameterSetIndx, opd);
+
+ for (band = 0; band < numIpdBands; band++) {
+ self->PhaseLeft__FDK[band] = wrapPhase(opd[2 * band]);
+ self->PhaseRight__FDK[band] = wrapPhase(opd[2 * band + 1]);
+ }
+ }
+
+ for (band = numIpdBands; band < numOttBands; band++) {
+ self->PhaseLeft__FDK[band] = FL2FXCONST_DBL(0.0f);
+ self->PhaseRight__FDK[band] = FL2FXCONST_DBL(0.0f);
+ }
+}
+
+FDK_INLINE void param2UMX_Prediction_Core__FDK(
+ FIXP_DBL* H11re, FIXP_DBL* H11im, FIXP_DBL* H12re, FIXP_DBL* H12im,
+ FIXP_DBL* H21re, FIXP_DBL* H21im, FIXP_DBL* H22re, FIXP_DBL* H22im,
+ int cldIdx, int iccIdx, int ipdIdx, int band, int numOttBandsIPD,
+ int resBands) {
+#define MAX_WEIGHT (1.2f)
+ FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
+
+ if ((band < numOttBandsIPD) && (cldIdx == 15) && (iccIdx == 0) &&
+ (ipdIdx == 8)) {
+ const FIXP_DBL gain =
+ FL2FXCONST_DBL(0.5f / MAX_WEIGHT) >> SCALE_PARAM_M2_212_PRED;
+
+ *H11re = gain;
+ if (band < resBands) {
+ *H21re = gain;
+ *H12re = gain;
+ *H22re = -gain;
+ } else {
+ *H21re = -gain;
+ *H12re = (FIXP_DBL)0;
+ *H22re = (FIXP_DBL)0;
+ }
+ if ((H11im != NULL) &&
+ (H21im != NULL) /*&& (H12im!=NULL) && (H22im!=NULL)*/) {
+ *H11im = (FIXP_DBL)0;
+ *H21im = (FIXP_DBL)0;
+ /* *H12im = (FIXP_DBL)0; */
+ /* *H22im = (FIXP_DBL)0; */
+ }
+ } else {
+ const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL;
+ const int one_e = 0;
+ /* iidLin = sqrt(cld); */
+ FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx];
+ int iidLin_e = sqrt_CLD_e[cldIdx];
+ /* iidLin2 = cld; */
+ FIXP_DBL iidLin2_m = CLD_m[cldIdx];
+ int iidLin2_e = sqrt_CLD_e[cldIdx] << 1;
+ /* iidLin21 = iidLin2 + 1.0f; */
+ int iidLin21_e;
+ FIXP_DBL iidLin21_m =
+ fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e);
+ /* iidIcc2 = iidLin * icc * 2.0f; */
+ FIXP_CFG icc = dequantICC__FDK[iccIdx];
+ int iidIcc2_e = iidLin_e + 1;
+ FIXP_DBL iidIcc2_m = fMult(iidLin_m, icc);
+ FIXP_DBL temp_m, sqrt_temp_m, inv_temp_m, weight_m;
+ int temp_e, sqrt_temp_e, inv_temp_e, weight_e, scale;
+ FIXP_DBL cosIpd, sinIpd;
+
+ cosIpd = COS_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
+ sinIpd = SIN_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
+
+ /* temp = iidLin21 + iidIcc2 * cosIpd; */
+ temp_m = fAddNorm(iidLin21_m, iidLin21_e, fMult(iidIcc2_m, cosIpd),
+ iidIcc2_e, &temp_e);
+
+ /* calculate 1/temp needed later */
+ inv_temp_e = temp_e;
+ inv_temp_m = invFixp(temp_m, &inv_temp_e);
+
+ /* 1/weight = sqrt(temp) * 1/sqrt(iidLin21) */
+ if (temp_e & 1) {
+ sqrt_temp_m = temp_m >> 1;
+ sqrt_temp_e = (temp_e + 1) >> 1;
+ } else {
+ sqrt_temp_m = temp_m;
+ sqrt_temp_e = temp_e >> 1;
+ }
+ sqrt_temp_m = sqrtFixp(sqrt_temp_m);
+ if (iidLin21_e & 1) {
+ iidLin21_e += 1;
+ iidLin21_m >>= 1;
+ }
+ /* weight_[m,e] is actually 1/weight in the next few lines */
+ weight_m = invSqrtNorm2(iidLin21_m, &weight_e);
+ weight_e -= iidLin21_e >> 1;
+ weight_m = fMult(sqrt_temp_m, weight_m);
+ weight_e += sqrt_temp_e;
+ scale = fNorm(weight_m);
+ weight_m = scaleValue(weight_m, scale);
+ weight_e -= scale;
+ /* weight = 0.5 * max(1/weight, 1/maxWeight) */
+ if ((weight_e < 0) ||
+ ((weight_e == 0) && (weight_m < FL2FXCONST_DBL(1.f / MAX_WEIGHT)))) {
+ weight_m = FL2FXCONST_DBL(1.f / MAX_WEIGHT);
+ weight_e = 0;
+ }
+ weight_e -= 1;
+
+ {
+ FIXP_DBL alphaRe_m, alphaIm_m, accu_m;
+ int alphaRe_e, alphaIm_e, accu_e;
+ /* alphaRe = (1.0f - iidLin2) / temp; */
+ alphaRe_m = fAddNorm(one_m, one_e, -iidLin2_m, iidLin2_e, &alphaRe_e);
+ alphaRe_m = fMult(alphaRe_m, inv_temp_m);
+ alphaRe_e += inv_temp_e;
+
+ /* H11re = weight - alphaRe * weight; */
+ /* H21re = weight + alphaRe * weight; */
+ accu_m = fMult(alphaRe_m, weight_m);
+ accu_e = alphaRe_e + weight_e;
+ {
+ int accu2_e;
+ FIXP_DBL accu2_m;
+ accu2_m = fAddNorm(weight_m, weight_e, -accu_m, accu_e, &accu2_e);
+ *H11re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
+ accu2_m = fAddNorm(weight_m, weight_e, accu_m, accu_e, &accu2_e);
+ *H21re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
+ }
+
+ if ((H11im != NULL) &&
+ (H21im != NULL) /*&& (H12im != NULL) && (H22im != NULL)*/) {
+ /* alphaIm = -iidIcc2 * sinIpd / temp; */
+ alphaIm_m = fMult(-iidIcc2_m, sinIpd);
+ alphaIm_m = fMult(alphaIm_m, inv_temp_m);
+ alphaIm_e = iidIcc2_e + inv_temp_e;
+ /* H11im = -alphaIm * weight; */
+ /* H21im = alphaIm * weight; */
+ accu_m = fMult(alphaIm_m, weight_m);
+ accu_e = alphaIm_e + weight_e;
+ accu_m = scaleValue(accu_m, accu_e - SCALE_PARAM_M2_212_PRED);
+ *H11im = -accu_m;
+ *H21im = accu_m;
+
+ /* *H12im = (FIXP_DBL)0; */
+ /* *H22im = (FIXP_DBL)0; */
+ }
+ }
+ if (band < resBands) {
+ FIXP_DBL weight =
+ scaleValue(weight_m, weight_e - SCALE_PARAM_M2_212_PRED);
+ *H12re = weight;
+ *H22re = -weight;
+ } else {
+ /* beta = 2.0f * iidLin * (float) sqrt(1.0f - icc * icc) * weight / temp;
+ */
+ FIXP_DBL beta_m;
+ int beta_e;
+ beta_m = FX_SGL2FX_DBL(sqrt_one_minus_ICC2[iccIdx]);
+ beta_e = 1; /* multipication with 2.0f */
+ beta_m = fMult(beta_m, weight_m);
+ beta_e += weight_e;
+ beta_m = fMult(beta_m, iidLin_m);
+ beta_e += iidLin_e;
+ beta_m = fMult(beta_m, inv_temp_m);
+ beta_e += inv_temp_e;
+
+ beta_m = scaleValue(beta_m, beta_e - SCALE_PARAM_M2_212_PRED);
+ *H12re = beta_m;
+ *H22re = -beta_m;
+ }
+ }
+}
+
+static void param2UMX_Prediction__FDK(spatialDec* self, FIXP_DBL* H11re,
+ FIXP_DBL* H11im, FIXP_DBL* H12re,
+ FIXP_DBL* H12im, FIXP_DBL* H21re,
+ FIXP_DBL* H21im, FIXP_DBL* H22re,
+ FIXP_DBL* H22im, int ottBoxIndx,
+ int parameterSetIndx, int resBands) {
+ int band;
+ FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
+
+ for (band = 0; band < self->numParameterBands; band++) {
+ int cldIdx = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
+ int iccIdx = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
+ int ipdIdx = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
+
+ param2UMX_Prediction_Core__FDK(
+ &H11re[band], (H11im ? &H11im[band] : NULL), &H12re[band], NULL,
+ &H21re[band], (H21im ? &H21im[band] : NULL), &H22re[band], NULL, cldIdx,
+ iccIdx, ipdIdx, band, self->numOttBandsIPD, resBands);
+ }
+}
+
+/*******************************************************************************
+ Functionname: initM1andM2
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Return:
+
+*******************************************************************************/
+
+SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag,
+ int configChanged) {
+ SACDEC_ERROR err = MPS_OK;
+
+ self->bOverwriteM1M2prev = (configChanged && !initStatesFlag) ? 1 : 0;
+
+ { self->numM2rows = self->numOutputChannels; }
+
+ if (initStatesFlag) {
+ int i, j, k;
+
+ for (i = 0; i < self->numM2rows; i++) {
+ for (j = 0; j < self->numVChannels; j++) {
+ for (k = 0; k < MAX_PARAMETER_BANDS; k++) {
+ self->M2Real__FDK[i][j][k] = FL2FXCONST_DBL(0);
+ self->M2RealPrev__FDK[i][j][k] = FL2FXCONST_DBL(0);
+ }
+ }
+ }
+ }
+
+ return err;
+}
diff --git a/libSACdec/src/sac_calcM1andM2.h b/libSACdec/src/sac_calcM1andM2.h
new file mode 100644
index 0000000..996238d
--- /dev/null
+++ b/libSACdec/src/sac_calcM1andM2.h
@@ -0,0 +1,129 @@
+/* -----------------------------------------------------------------------------
+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 M1 and M2 calculation
+
+*******************************************************************************/
+
+/* sa_calcM1andM2.h */
+
+#ifndef SAC_CALCM1ANDM2_H
+#define SAC_CALCM1ANDM2_H
+
+#include "sac_dec.h"
+
+#define SCALE_PARAM_M1 3
+
+/* Scaling of M2 matrix, but only for binaural upmix type. */
+#define SCALE_PARAM_CALC_M2 (3)
+#define SCALE_PARAM_M2_515X (3)
+#define SCALE_PARAM_M2_525 (SCALE_PARAM_M1 + HRG_SF + 1 - SCALE_PARAM_CALC_M2)
+#define SCALE_PARAM_M2_212_PRED (3)
+/* Scaling of spectral data after applying M2 matrix, but only for binaural
+ upmix type Scaling is compensated later in synthesis qmf filterbank */
+#define SCALE_DATA_APPLY_M2 (1)
+
+SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag,
+ int configChanged);
+
+int SpatialDecGetResidualIndex(spatialDec* self, int row);
+
+SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps,
+ const SPATIAL_BS_FRAME* frame);
+
+#endif /* SAC_CALCM1ANDM2_H */
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;
+}
diff --git a/libSACdec/src/sac_dec.h b/libSACdec/src/sac_dec.h
new file mode 100644
index 0000000..992acad
--- /dev/null
+++ b/libSACdec/src/sac_dec.h
@@ -0,0 +1,539 @@
+/* -----------------------------------------------------------------------------
+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 structures
+
+*******************************************************************************/
+
+#ifndef SAC_DEC_H
+#define SAC_DEC_H
+
+#include "common_fix.h"
+
+#include "sac_dec_interface.h" /* library interface in ../include */
+
+#include "FDK_qmf_domain.h"
+#include "sac_qmf.h"
+#include "FDK_bitstream.h" /* mp4 bitbuffer */
+#include "sac_calcM1andM2.h"
+#include "FDK_hybrid.h"
+#include "FDK_decorrelate.h"
+#include "sac_reshapeBBEnv.h"
+
+#include "sac_dec_conceal.h"
+
+#include "sac_tsd.h"
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define ICCdefault 0
+#define IPDdefault 0
+#define arbdmxGainDefault 0
+#define CPCdefault 10
+#define tttCLD1default 15
+#define tttCLD2default 0
+
+#define IS_HQ_ONLY(aot) \
+ ((aot) == AOT_ER_AAC_LD || (aot) == AOT_ER_AAC_ELD || (aot) == AOT_USAC || \
+ (aot) == AOT_RSVD50)
+
+#define SCONST(x) FL2FXCONST_DBL(x)
+
+#define PC_NUM_BANDS (8)
+#define PC_NUM_HYB_BANDS (PC_NUM_BANDS - 3 + 10)
+#define ABS_THR (1e-9f * 32768 * 32768)
+
+#define MAX_HYBRID_BANDS (MAX_NUM_QMF_BANDS - 3 + 10)
+#define HYBRID_FILTER_DELAY (6)
+
+#define MAX_RESIDUAL_FRAMES (4)
+#define MAX_RESIDUAL_BISTREAM \
+ (836) /* 48000 bps * 3 res / (8 * 44100 / 2048 ) */
+#define MAX_MDCT_COEFFS (1024)
+#define SACDEC_RESIDUAL_BS_BUF_SIZE \
+ (1024) /* used to setup and check residual bitstream buffer */
+
+#define MAX_NUM_PARAMS (MAX_NUM_OTT + 4 * MAX_NUM_TTT + MAX_INPUT_CHANNELS)
+#define MAX_NUM_PARAMETERS (MAX(MAX_NUM_PARAMS, MAX_NUM_OTT))
+
+#define MAX_PARAMETER_SETS (9)
+
+#define MAX_M2_INPUT (MAX_OUTPUT_CHANNELS) /* 3 direct + 5 diffuse */
+
+#define MAX_QMF_BANDS_TO_HYBRID \
+ (3) /* 3 bands are filtered again in "40 bands" case */
+#define PROTO_LEN (13)
+#define BUFFER_LEN_LF (PROTO_LEN)
+#define BUFFER_LEN_HF ((PROTO_LEN - 1) / 2)
+
+#define MAX_NO_DECORR_CHANNELS (MAX_OUTPUT_CHANNELS)
+#define HRTF_AZIMUTHS (5)
+
+#define MAX_NUM_OTT_AT 0
+
+/* left out */
+
+typedef enum {
+ UPMIXTYPE_BYPASS = -1, /*just bypass the input channels without processing*/
+ UPMIXTYPE_NORMAL = 0 /*multichannel loudspeaker upmix with spatial data*/
+} UPMIXTYPE;
+
+static inline int isTwoChMode(UPMIXTYPE upmixType) {
+ int retval = 0;
+ return retval;
+}
+
+ /* left out end */
+
+#define MPEGS_BYPASSMODE (0x00000001)
+#define MPEGS_CONCEAL (0x00000002)
+
+typedef struct STP_DEC *HANDLE_STP_DEC;
+
+typedef struct {
+ SCHAR bsQuantCoarseXXXprev;
+ SCHAR bsQuantCoarseXXXprevParse;
+} LOSSLESSSTATE;
+
+typedef struct {
+ SCHAR bsXXXDataMode[MAX_PARAMETER_SETS];
+ SCHAR bsQuantCoarseXXX[MAX_PARAMETER_SETS];
+ SCHAR bsFreqResStrideXXX[MAX_PARAMETER_SETS];
+ SCHAR nocmpQuantCoarseXXX[MAX_PARAMETER_SETS];
+ LOSSLESSSTATE *state; /* Link to persistent state information */
+} LOSSLESSDATA;
+
+struct SPATIAL_BS_FRAME_struct {
+ UCHAR bsIndependencyFlag;
+ UCHAR newBsData;
+ UCHAR numParameterSets;
+
+ /*
+ If bsFramingType == 0, then the paramSlot[ps] for 0 <= ps < numParamSets is
+ calculated as follows: paramSlot[ps] = ceil(numSlots*(ps+1)/numParamSets) - 1
+ Otherwise, it is
+ paramSlot[ps] = bsParamSlot[ps]
+ */
+ INT paramSlot[MAX_PARAMETER_SETS];
+
+ /* These arrays contain the compact indices, only one value per pbstride, only
+ * paramsets actually containing data. */
+ /* These values are written from the parser in ecDataDec() and read during
+ * decode in mapIndexData() */
+ SCHAR cmpOttCLDidx[MAX_NUM_OTT + MAX_NUM_OTT_AT][MAX_PARAMETER_SETS]
+ [MAX_PARAMETER_BANDS];
+ SCHAR cmpOttICCidx[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS];
+
+ /* Smoothing */
+ UCHAR bsSmoothMode[MAX_PARAMETER_SETS];
+ UCHAR bsSmoothTime[MAX_PARAMETER_SETS];
+ UCHAR bsFreqResStrideSmg[MAX_PARAMETER_SETS];
+ UCHAR bsSmgData[MAX_PARAMETER_SETS]
+ [MAX_PARAMETER_BANDS]; /* smoothing flags, one if band is
+ smoothed, otherwise zero */
+
+ /* Arbitrary Downmix */
+ SCHAR (*cmpArbdmxGainIdx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS];
+
+ /* Lossless control */
+ LOSSLESSDATA *CLDLosslessData;
+ LOSSLESSDATA *ICCLosslessData;
+ /* LOSSLESSDATA *ADGLosslessData; -> is stored in CLDLosslessData[offset] */
+
+ LOSSLESSDATA *IPDLosslessData;
+ SCHAR (*cmpOttIPDidx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS];
+ int phaseMode;
+ int OpdSmoothingMode;
+
+ UCHAR tempShapeEnableChannelGES[MAX_OUTPUT_CHANNELS]; /*!< GES side info. */
+ UCHAR bsEnvShapeData[MAX_OUTPUT_CHANNELS]
+ [MAX_TIME_SLOTS]; /*!< GES side info (quantized). */
+
+ UCHAR tempShapeEnableChannelSTP[MAX_OUTPUT_CHANNELS]; /*!< STP side info. */
+
+ TSD_DATA TsdData[1]; /*!< TSD data structure. */
+};
+
+typedef struct {
+ /* Lossless state */
+ LOSSLESSSTATE CLDLosslessState[MAX_NUM_PARAMETERS];
+ LOSSLESSSTATE ICCLosslessState[MAX_NUM_PARAMETERS];
+ LOSSLESSSTATE IPDLosslessState[MAX_NUM_PARAMETERS];
+} BS_LL_STATE;
+
+typedef struct {
+ int prevParamSlot;
+ int prevSmgTime;
+ UCHAR prevSmgData[MAX_PARAMETER_BANDS];
+
+ FIXP_DBL opdLeftState__FDK[MAX_PARAMETER_BANDS];
+ FIXP_DBL opdRightState__FDK[MAX_PARAMETER_BANDS];
+
+} SMOOTHING_STATE;
+
+typedef struct {
+ FIXP_DBL alpha__FDK;
+ FIXP_DBL beta__FDK;
+ FIXP_DBL partNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]
+ [BB_ENV_SIZE];
+ FIXP_DBL normNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+ FIXP_DBL frameNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+ INT partNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+ INT partNrgPrev2SF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+ INT normNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+ INT frameNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS];
+} RESHAPE_BBENV_STATE;
+
+typedef struct {
+ int maxNumInputChannels;
+ int maxNumOutputChannels;
+ int maxNumQmfBands;
+ int maxNumHybridBands;
+ int maxNumXChannels;
+ int maxNumVChannels;
+ int maxNumDecorChannels;
+ int maxNumCmplxQmfBands;
+ int maxNumCmplxHybBands;
+ int maxNumResChannels;
+ int bProcResidual; /* process residual */
+ int maxNumResidualChannels;
+ int maxNumOttBoxes;
+ int maxNumParams;
+
+} SACDEC_CREATION_PARAMS;
+
+struct spatialDec_struct {
+ SACDEC_ERROR
+ errInt; /* Field to store internal errors.
+ Will be clear at the very beginning of each process call. */
+ int staticDecScale; /* static scale of decoder */
+
+ /* GENERAL */
+ int samplingFreq; /* [Hz] */
+ CFG_LEVEL decoderLevel; /* 0..5 */
+ CFG_EXTENT decoderMode;
+ CFG_BINAURAL binauralMode;
+
+ SACDEC_CREATION_PARAMS createParams;
+
+ int numComplexProcessingBands;
+
+ int treeConfig; /* TREE_5151 = 5151, TREE_5152 = 5152, TREE_525 = 525, defined
+ in sac_bitdec.h */
+
+ int numInputChannels; /* 1 (M) or 2 (L,R) */
+ int numOutputChannels; /* 6 for 3/2.1 (FL,FR,FC,LF,BL,BR) */
+ int numOttBoxes; /* number of ott boxes */
+ int numM2rows;
+
+ int numOutputChannelsAT; /* Number of output channels after arbitrary tree
+ processing */
+
+ int quantMode; /* QUANT_FINE, QUANT_EBQ1, QUANT_EBQ2, defined in sac_bitdec.h
+ */
+ int arbitraryDownmix; /* (arbitraryDownmix != 0) 1 arbitrary downmix data
+ present, 2 arbitrary downmix residual data present*/
+ int residualCoding; /* (residualCoding != 0) => residual coding data present
+ */
+ UCHAR nrResidualFrame;
+ UCHAR nrArbDownmixResidualFrame;
+ FDK_BITSTREAM **hResidualBitstreams;
+ int tempShapeConfig; /* */
+ int decorrType; /* Indicates to use PS or none PS decorrelator. */
+ int decorrConfig; /* chosen decorrelator */
+ int envQuantMode; /* quantization mode of envelope reshaping data */
+
+ FIXP_DBL clipProtectGain__FDK; /* global gain for upmix */
+ char clipProtectGainSF__FDK; /* global gain for upmix */
+
+ /* Currently ignoring center decorr
+ numVChannels = numDirektSignals + numDecorSignals */
+ int numDirektSignals; /* needed for W, Number of direkt signals 515 -> 1 525
+ -> 3 */
+ int wStartResidualIdx; /* Where to start read residuals for W, = 0 for 515, =
+ 1 for 525 since one residual is used in V */
+ int numDecorSignals; /* needed for W, Number of residual and decorrelated
+ signals, = 2, 3 for center deccorelation*/
+ int numVChannels; /* direct signals + decorelator signals */
+ int numXChannels; /* direct input signals + TTT-residuals */
+
+ int timeSlots; /* length of spatial frame in QMF samples */
+ int curTimeSlot; /* pointer to the current time slot used for hyperframing */
+ int prevTimeSlot; /* */
+ int curPs;
+ int frameLength; /* number of output waveform samples/channel/frame */
+ UPMIXTYPE upmixType;
+ int partiallyComplex;
+ int useFDreverb;
+
+ int bShareDelayWithSBR;
+
+ int tp_hybBandBorder; /* Hybrid band indicating the HP filter cut-off. */
+
+ /* FREQUENCY MAPPING */
+ int qmfBands;
+ int hybridBands;
+ const SCHAR *kernels; /* Mapping hybrid band to parameter band. */
+
+ int TsdTs; /**< TSD QMF slot counter 0<= ts < numSlots */
+
+ int *param2hyb; /* Mapping parameter bands to hybrid bands */
+ int kernels_width[MAX_PARAMETER_BANDS]; /* Mapping parmeter band to hybrid
+ band offsets. */
+
+ /* Residual coding */
+ int residualSamplingFreq;
+ UCHAR residualPresent[MAX_NUM_OTT + MAX_NUM_TTT];
+ UCHAR residualBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* 0, if no residual data
+ present for this box */
+ UCHAR residualQMFBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* needed for optimized
+ mdct2qmf calculation */
+ SPATIAL_SPECIFIC_CONFIG *pConfigCurrent;
+
+ int arbdmxFramesPerSpatialFrame;
+ int arbdmxUpdQMF;
+
+ int numParameterBands; /* Number of parameter bands 40, 28, 20, 14, 10, ...
+ .*/
+ int bitstreamParameterBands;
+ int *numOttBands; /* number of bands for each ott, is != numParameterBands for
+ LFEs */
+
+ /* 1 MAPPING */
+ UCHAR extendFrame;
+ UCHAR numParameterSetsPrev;
+
+ int *smgTime;
+ UCHAR **smgData;
+
+ /* PARAMETER DATA decoded and dequantized */
+
+ /* Last parameters from prev frame required during decode in mapIndexData()
+ * and not touched during parse */
+ SCHAR **ottCLDidxPrev;
+ SCHAR **ottICCidxPrev;
+ SCHAR **arbdmxGainIdxPrev;
+ SCHAR **ottIPDidxPrev;
+ SCHAR ***outIdxData; /* is this really persistent memory ? */
+
+ /* State mem required during parse in SpatialDecParseFrameData() */
+ SCHAR **cmpOttCLDidxPrev;
+ SCHAR **cmpOttICCidxPrev;
+ SCHAR ***ottICCdiffidx;
+ SCHAR **cmpOttIPDidxPrev;
+
+ /* State mem required in parseArbitraryDownmixData */
+ SCHAR **cmpArbdmxGainIdxPrev;
+
+ SCHAR ***ottCLD__FDK;
+ SCHAR ***ottICC__FDK;
+
+ SCHAR ***arbdmxGain__FDK; /* Holds the artistic downmix correction index.*/
+
+ FIXP_DBL *arbdmxAlpha__FDK;
+ FIXP_DBL *arbdmxAlphaPrev__FDK;
+
+ UCHAR stereoConfigIndex;
+ int highRateMode;
+
+ int phaseCoding;
+
+ SCHAR ***ottIPD__FDK;
+
+ FIXP_DBL PhaseLeft__FDK[MAX_PARAMETER_BANDS];
+ FIXP_DBL PhaseRight__FDK[MAX_PARAMETER_BANDS];
+ FIXP_DBL PhasePrevLeft__FDK[MAX_PARAMETER_BANDS];
+ FIXP_DBL PhasePrevRight__FDK[MAX_PARAMETER_BANDS];
+ int numOttBandsIPD;
+
+ /* GAIN MATRICIES FOR CURRENT and PREVIOUS PARMATER SET(s)*/
+ FIXP_DBL ***M2Real__FDK;
+ FIXP_DBL ***M2Imag__FDK;
+ FIXP_DBL ***M2RealPrev__FDK;
+ FIXP_DBL ***M2ImagPrev__FDK;
+
+ /* INPUT SIGNALS */
+ FIXP_DBL ***qmfInputRealDelayBuffer__FDK;
+ FIXP_DBL ***qmfInputImagDelayBuffer__FDK;
+
+ int pc_filterdelay; /* additional delay to align HQ with LP before hybird
+ analysis */
+ int qmfInputDelayBufPos;
+ FIXP_DBL **qmfInputReal__FDK;
+ FIXP_DBL **qmfInputImag__FDK;
+
+ FIXP_DBL **hybInputReal__FDK;
+ FIXP_DBL **hybInputImag__FDK;
+
+ FIXP_DBL **binInputReverb;
+
+ FIXP_DBL binGain, reverbGain;
+ FIXP_DBL binCenterGain, reverbCenterGain;
+
+ /* RESIDUAL SIGNALS */
+
+ FIXP_DBL ***qmfResidualReal__FDK;
+ FIXP_DBL ***qmfResidualImag__FDK;
+
+ FIXP_DBL **hybResidualReal__FDK;
+ FIXP_DBL **hybResidualImag__FDK;
+
+ int qmfOutputRealDryDelayBufPos;
+ FIXP_DBL ***qmfOutputRealDryDelayBuffer__FDK;
+ FIXP_DBL ***qmfOutputImagDryFilterBuffer__FDK;
+ FIXP_DBL *qmfOutputImagDryFilterBufferBase__FDK;
+
+ /* TEMPORARY SIGNALS */
+
+ FIXP_DBL **wReal__FDK;
+ FIXP_DBL **wImag__FDK;
+
+ /* OUTPUT SIGNALS */
+ FIXP_DBL **hybOutputRealDry__FDK;
+ FIXP_DBL **hybOutputImagDry__FDK;
+ FIXP_DBL **hybOutputRealWet__FDK;
+ FIXP_DBL **hybOutputImagWet__FDK;
+ PCM_MPS *timeOut__FDK;
+
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain;
+
+ FDK_ANA_HYB_FILTER
+ *hybridAnalysis; /*!< pointer Analysis hybrid filterbank array. */
+ FDK_SYN_HYB_FILTER
+ *hybridSynthesis; /*!< pointer Synthesis hybrid filterbank array. */
+ FIXP_DBL **
+ pHybridAnaStatesLFdmx; /*!< pointer to analysis hybrid filter states LF */
+ FIXP_DBL **
+ pHybridAnaStatesHFdmx; /*!< pointer to analysis hybrid filter states HF */
+ FIXP_DBL **
+ pHybridAnaStatesLFres; /*!< pointer to analysis hybrid filter states LF */
+ FIXP_DBL **
+ pHybridAnaStatesHFres; /*!< pointer to analysis hybrid filter states HF */
+
+ DECORR_DEC *apDecor; /*!< pointer decorrelator array. */
+ FIXP_DBL **pDecorBufferCplx;
+
+ SMOOTHING_STATE *smoothState; /*!< Pointer to smoothing states. */
+
+ RESHAPE_BBENV_STATE *reshapeBBEnvState; /*!< GES handle. */
+ SCHAR row2channelDmxGES[MAX_OUTPUT_CHANNELS];
+
+ HANDLE_STP_DEC hStpDec; /*!< STP handle. */
+
+ const UCHAR *pActivM2ParamBands;
+
+ int bOverwriteM1M2prev; /* Overwrite previous M2/M2 params with first set of
+ new frame after SSC change (aka
+ decodeAfterConfigHasChangedFlag). */
+ SpatialDecConcealmentInfo concealInfo;
+};
+
+#define SACDEC_SYNTAX_MPS 1
+#define SACDEC_SYNTAX_USAC 2
+#define SACDEC_SYNTAX_RSVD50 4
+#define SACDEC_SYNTAX_L2 8
+#define SACDEC_SYNTAX_L3 16
+#define SACDEC_SYNTAX_LD 32
+
+static inline int GetProcBand(spatialDec_struct *self, int qs) {
+ return self->kernels[qs];
+}
+
+#endif /* SAC_DEC_H */
diff --git a/libSACdec/src/sac_dec_conceal.cpp b/libSACdec/src/sac_dec_conceal.cpp
new file mode 100644
index 0000000..dfeef7b
--- /dev/null
+++ b/libSACdec/src/sac_dec_conceal.cpp
@@ -0,0 +1,392 @@
+/* -----------------------------------------------------------------------------
+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): Christian Ertel, Christian Griebel
+
+ Description: SAC Dec error concealment
+
+*******************************************************************************/
+
+#include "sac_dec_conceal.h"
+
+void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info,
+ const UINT resetFlags) {
+ FDK_ASSERT(info != NULL);
+
+ if (resetFlags & MPEGS_CONCEAL_RESET_STATE) {
+ info->concealState = SpatialDecConcealState_Init;
+ /* Frame counters will be initialized implicitely in function
+ * SpatialDecConcealment_UpdateState(). */
+ }
+
+ if (resetFlags & MPEGS_CONCEAL_RESET_PARAMETER) {
+ /* Set default params */
+ info->concealParams.method = MPEGS_CONCEAL_DEFAULT_METHOD;
+ info->concealParams.numKeepFrames = MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES;
+ info->concealParams.numFadeOutFrames =
+ MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH;
+ info->concealParams.numFadeInFrames =
+ MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH;
+ info->concealParams.numReleaseFrames =
+ MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES;
+ }
+
+ return;
+}
+
+int SpatialDecConcealment_Apply(
+ SpatialDecConcealmentInfo *info,
+ const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS], SCHAR **diffIdxData,
+ SCHAR *
+ idxPrev, /* char
+ idxPrev[SPATIALDEC_MAX_NUM_OTT][SPATIALDEC_MAX_PARAMETER_BANDS],
+ */
+ SCHAR *bsXXXDataMode, const int startBand, const int stopBand,
+ const SCHAR defaultValue, const int paramType, const int numParamSets) {
+ int appliedProcessing = 0;
+ int band, dataMode = -1;
+
+ FDK_ASSERT(info != NULL);
+ FDK_ASSERT(cmpIdxData != NULL);
+ FDK_ASSERT(idxPrev != NULL);
+ FDK_ASSERT(bsXXXDataMode != NULL);
+
+ /* Processing depends only on the internal state */
+ switch (info->concealState) {
+ case SpatialDecConcealState_Init:
+ dataMode = 0; /* default */
+ break;
+
+ case SpatialDecConcealState_Ok:
+ /* Nothing to do */
+ break;
+
+ case SpatialDecConcealState_Keep:
+ dataMode = 1; /* keep */
+ break;
+
+ case SpatialDecConcealState_FadeToDefault: {
+ /* Start simple fade out */
+ FIXP_DBL fac = fDivNorm(info->cntStateFrames + 1,
+ info->concealParams.numFadeOutFrames + 1);
+
+ for (band = startBand; band < stopBand; band += 1) {
+ /* idxPrev = fac * defaultValue + (1-fac) * idxPrev; */
+ idxPrev[band] =
+ fMultI(fac, defaultValue - idxPrev[band]) + idxPrev[band];
+ }
+ dataMode = 1; /* keep */
+ appliedProcessing = 1;
+ } break;
+
+ case SpatialDecConcealState_Default:
+ for (band = startBand; band < stopBand; band += 1) {
+ idxPrev[band] = defaultValue;
+ }
+ dataMode = 1; /* keep */
+ appliedProcessing = 1;
+ break;
+
+ case SpatialDecConcealState_FadeFromDefault: {
+ FIXP_DBL fac = fDivNorm(info->cntValidFrames + 1,
+ info->concealParams.numFadeInFrames + 1);
+
+ for (band = startBand; band < stopBand; band += 1) {
+ /* idxPrev = fac * cmpIdxData + (1-fac) * defaultValue; */
+ idxPrev[band] =
+ fMultI(fac, cmpIdxData[numParamSets - 1][band] - defaultValue) +
+ defaultValue;
+ }
+ dataMode = 1; /* keep */
+ appliedProcessing = 1;
+ } break;
+
+ default:
+ FDK_ASSERT(0); /* All valid states shall be handled above. */
+ break;
+ }
+
+ if (dataMode >= 0) {
+ int i;
+ for (i = 0; i < numParamSets; i += 1) {
+ bsXXXDataMode[i] = dataMode;
+ if (diffIdxData != NULL) {
+ for (band = startBand; band < stopBand; band += 1) {
+ diffIdxData[i][band] = 0;
+ }
+ }
+ }
+ }
+
+ return appliedProcessing;
+}
+
+void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info,
+ const int frameOk) {
+ FDK_ASSERT(info != NULL);
+
+ if (frameOk) {
+ info->cntValidFrames += 1;
+ } else {
+ info->cntValidFrames = 0;
+ }
+
+ switch (info->concealState) {
+ case SpatialDecConcealState_Init:
+ if (frameOk) {
+ /* NEXT STATE: Ok */
+ info->concealState = SpatialDecConcealState_Ok;
+ info->cntStateFrames = 0;
+ }
+ break;
+
+ case SpatialDecConcealState_Ok:
+ if (!frameOk) {
+ /* NEXT STATE: Keep */
+ info->concealState = SpatialDecConcealState_Keep;
+ info->cntStateFrames = 0;
+ }
+ break;
+
+ case SpatialDecConcealState_Keep:
+ info->cntStateFrames += 1;
+ if (frameOk) {
+ /* NEXT STATE: Ok */
+ info->concealState = SpatialDecConcealState_Ok;
+ } else {
+ if (info->cntStateFrames >= info->concealParams.numKeepFrames) {
+ if (info->concealParams.numFadeOutFrames == 0) {
+ /* NEXT STATE: Default */
+ info->concealState = SpatialDecConcealState_Default;
+ } else {
+ /* NEXT STATE: Fade to default */
+ info->concealState = SpatialDecConcealState_FadeToDefault;
+ info->cntStateFrames = 0;
+ }
+ }
+ }
+ break;
+
+ case SpatialDecConcealState_FadeToDefault:
+ info->cntStateFrames += 1;
+ if (info->cntValidFrames > 0) {
+ /* NEXT STATE: Fade in from default */
+ info->concealState = SpatialDecConcealState_FadeFromDefault;
+ info->cntStateFrames = 0;
+ } else {
+ if (info->cntStateFrames >= info->concealParams.numFadeOutFrames) {
+ /* NEXT STATE: Default */
+ info->concealState = SpatialDecConcealState_Default;
+ }
+ }
+ break;
+
+ case SpatialDecConcealState_Default:
+ if (info->cntValidFrames > 0) {
+ if (info->concealParams.numFadeInFrames == 0) {
+ /* NEXT STATE: Ok */
+ info->concealState = SpatialDecConcealState_Ok;
+ } else {
+ /* NEXT STATE: Fade in from default */
+ info->concealState = SpatialDecConcealState_FadeFromDefault;
+ info->cntValidFrames = 0;
+ }
+ }
+ break;
+
+ case SpatialDecConcealState_FadeFromDefault:
+ info->cntValidFrames += 1;
+ if (frameOk) {
+ if (info->cntValidFrames >= info->concealParams.numFadeInFrames) {
+ /* NEXT STATE: Ok */
+ info->concealState = SpatialDecConcealState_Ok;
+ }
+ } else {
+ /* NEXT STATE: Fade to default */
+ info->concealState = SpatialDecConcealState_FadeToDefault;
+ info->cntStateFrames = 0;
+ }
+ break;
+
+ default:
+ FDK_ASSERT(0); /* All valid states should be handled above! */
+ break;
+ }
+}
+
+SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *self,
+ const SAC_DEC_CONCEAL_PARAM param,
+ const INT value) {
+ SACDEC_ERROR err = MPS_OK;
+
+ switch (param) {
+ case SAC_DEC_CONCEAL_METHOD:
+ switch ((SpatialDecConcealmentMethod)value) {
+ case SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT:
+ case SAC_DEC_CONCEAL_BY_FADING_PARAMETERS:
+ break;
+ default:
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+ if (self != NULL) {
+ /* store parameter value */
+ self->concealParams.method = (SpatialDecConcealmentMethod)value;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ goto bail;
+ }
+ break;
+ case SAC_DEC_CONCEAL_NUM_KEEP_FRAMES:
+ if (value < 0) {
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+ if (self != NULL) {
+ /* store parameter value */
+ self->concealParams.numKeepFrames = (UINT)value;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ goto bail;
+ }
+ break;
+ case SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH:
+ if (value < 0) {
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+ if (self != NULL) {
+ /* store parameter value */
+ self->concealParams.numFadeOutFrames = (UINT)value;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ goto bail;
+ }
+ break;
+ case SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH:
+ if (value < 0) {
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+ if (self != NULL) {
+ /* store parameter value */
+ self->concealParams.numFadeInFrames = (UINT)value;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ goto bail;
+ }
+ break;
+ case SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES:
+ if (value < 0) {
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+ if (self != NULL) {
+ /* store parameter value */
+ self->concealParams.numReleaseFrames = (UINT)value;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ goto bail;
+ }
+ break;
+ default:
+ err = MPS_INVALID_PARAMETER;
+ goto bail;
+ }
+
+bail:
+ return err;
+}
diff --git a/libSACdec/src/sac_dec_conceal.h b/libSACdec/src/sac_dec_conceal.h
new file mode 100644
index 0000000..27f5249
--- /dev/null
+++ b/libSACdec/src/sac_dec_conceal.h
@@ -0,0 +1,187 @@
+/* -----------------------------------------------------------------------------
+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): Christian Ertel, Christian Griebel
+
+ Description: SAC Dec error concealment
+
+*******************************************************************************/
+
+#ifndef SAC_DEC_CONCEAL_H
+#define SAC_DEC_CONCEAL_H
+
+#include "sac_dec_interface.h"
+
+/* Modules dynamic parameters: */
+typedef enum {
+ SAC_DEC_CONCEAL_METHOD = 0,
+ SAC_DEC_CONCEAL_NUM_KEEP_FRAMES,
+ SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH,
+ SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH,
+ SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES
+
+} SAC_DEC_CONCEAL_PARAM;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* sac_dec_interface.h */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+typedef enum {
+ SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT = 0,
+ SAC_DEC_CONCEAL_BY_FADING_PARAMETERS = 1
+
+} SpatialDecConcealmentMethod;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* Default dynamic parameter values: */
+#define MPEGS_CONCEAL_DEFAULT_METHOD SAC_DEC_CONCEAL_BY_FADING_PARAMETERS
+#define MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES (10)
+#define MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH (5)
+#define MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH (5)
+#define MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES (3)
+
+typedef enum {
+ SpatialDecConcealState_Init = 0,
+ SpatialDecConcealState_Ok,
+ SpatialDecConcealState_Keep,
+ SpatialDecConcealState_FadeToDefault,
+ SpatialDecConcealState_Default,
+ SpatialDecConcealState_FadeFromDefault
+
+} SpatialDecConcealmentState;
+
+typedef struct {
+ SpatialDecConcealmentMethod method;
+
+ UINT numKeepFrames;
+ UINT numFadeOutFrames;
+ UINT numFadeInFrames;
+ UINT numReleaseFrames;
+
+} SpatialDecConcealmentParams;
+
+typedef struct {
+ SpatialDecConcealmentParams concealParams; /* User set params */
+ SpatialDecConcealmentState
+ concealState; /* State of internal state machine (fade-in/out etc) */
+
+ UINT cntStateFrames; /* Counter for fade-in/out handling */
+ UINT cntValidFrames; /* Counter for the number of consecutive good frames*/
+
+} SpatialDecConcealmentInfo;
+
+/* Module reset flags */
+#define MPEGS_CONCEAL_RESET_STATE (0x01)
+#define MPEGS_CONCEAL_RESET_PARAMETER (0x02)
+#define MPEGS_CONCEAL_RESET_ALL (0xFF)
+
+void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info,
+ const UINT resetFlags);
+
+int SpatialDecConcealment_Apply(SpatialDecConcealmentInfo *info,
+ const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS],
+ SCHAR **diffIdxData, SCHAR *idxPrev,
+ SCHAR *bsXXXDataMode, const int startBand,
+ const int stopBand, const SCHAR defaultValue,
+ const int paramType, const int numParamSets);
+
+void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info,
+ const int frameOk);
+
+SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *info,
+ const SAC_DEC_CONCEAL_PARAM param,
+ const INT value);
+
+#endif /* SAC_DEC_CONCEAL_H */
diff --git a/libSACdec/src/sac_dec_interface.h b/libSACdec/src/sac_dec_interface.h
new file mode 100644
index 0000000..a2eea92
--- /dev/null
+++ b/libSACdec/src/sac_dec_interface.h
@@ -0,0 +1,335 @@
+/* -----------------------------------------------------------------------------
+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 Interface
+
+*******************************************************************************/
+
+#ifndef SAC_DEC_INTERFACE_H
+#define SAC_DEC_INTERFACE_H
+
+#include "common_fix.h"
+#include "FDK_audio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "sac_dec_errorcodes.h"
+#include "sac_dec_ssc_struct.h"
+
+/**
+ * \brief Baseline MPEG-Surround profile Level 1-5.
+ */
+typedef enum {
+ DECODER_LEVEL_0 = 0, /*!< Level 0: dummy level; 212 only */
+ DECODER_LEVEL_6 = 6 /*!< Level 6: no support */
+} CFG_LEVEL;
+
+/*
+ * \brief Number of output channels restriction.
+ */
+typedef enum {
+ OUTPUT_CHANNELS_DEFAULT, /*!< Default configuration depending on Decoder Level
+ */
+ OUTPUT_CHANNELS_2_0, /*!< Limitation to stereo output */
+ OUTPUT_CHANNELS_5_1 /*!< Limitation to 5.1 output */
+} CFG_RESTRICTION;
+
+/*
+ * \brief Supported decoder mode.
+ */
+typedef enum {
+ EXT_HQ_ONLY = 0, /*!< High Quality processing only */
+ EXT_LP_ONLY = 1, /*!< Low Power procesing only */
+ EXT_HQ_AND_LP = 2 /*!< Support both HQ and LP processing */
+} CFG_EXTENT;
+
+/*
+ * \brief Supported binaural mode.
+ */
+typedef enum {
+ BINAURAL_NONE = -1 /*!< No binaural procesing supported */
+} CFG_BINAURAL;
+
+/**
+ * \brief Decoder configuration structure.
+ *
+ * These structure contains all parameters necessary for decoder open function.
+ * The configuration specifies the functional range of the decoder instance.
+ */
+typedef struct {
+ CFG_LEVEL decoderLevel;
+ CFG_EXTENT decoderMode;
+ CFG_RESTRICTION maxNumOutputChannels;
+ CFG_BINAURAL binauralMode;
+
+} SPATIAL_DEC_CONFIG;
+
+typedef enum {
+ INPUTMODE_QMF = 1000,
+ INPUTMODE_QMF_SBR = 1001,
+ INPUTMODE_TIME = 1002
+} SPATIALDEC_INPUT_MODE;
+
+/**
+ * \brief MPEG Surround upmix type mode.
+ **/
+typedef enum {
+ UPMIX_TYPE_BYPASS =
+ -1, /*!< Bypass the downmix channels from the core decoder. */
+ UPMIX_TYPE_NORMAL = 0 /*!< Multi channel output. */
+
+} SPATIAL_DEC_UPMIX_TYPE;
+
+/**
+ * \brief Dynamic decoder parameters.
+ */
+typedef struct {
+ /* Basics */
+ UCHAR outputMode;
+ UCHAR blindEnable;
+ UCHAR bypassMode;
+
+ /* Error concealment */
+ UCHAR concealMethod;
+ UINT concealNumKeepFrames;
+ UINT concealFadeOutSlopeLength;
+ UINT concealFadeInSlopeLength;
+ UINT concealNumReleaseFrames;
+
+} SPATIALDEC_PARAM;
+
+/**
+ * \brief Flags which control the initialization
+ **/
+typedef enum {
+ MPEGS_INIT_NONE = 0x00000000, /*!< Indicates no initialization */
+
+ MPEGS_INIT_CONFIG = 0x00000010, /*!< Indicates a configuration change due to
+ SSC value changes */
+
+ MPEGS_INIT_STATES_ANA_QMF_FILTER =
+ 0x00000100, /*!< Controls the initialization of the analysis qmf filter
+ states */
+ MPEGS_INIT_STATES_SYN_QMF_FILTER =
+ 0x00000200, /*!< Controls the initialization of the synthesis qmf filter
+ states */
+ MPEGS_INIT_STATES_ANA_HYB_FILTER = 0x00000400, /*!< Controls the
+ initialization of the
+ analysis hybrid filter
+ states */
+ MPEGS_INIT_STATES_DECORRELATOR =
+ 0x00000800, /*!< Controls the initialization of the decorrelator states */
+ MPEGS_INIT_STATES_M1M2 = 0x00002000, /*!< Controls the initialization of the
+ history in m1 and m2 parameter
+ calculation */
+ MPEGS_INIT_STATES_GES = 0x00004000, /*!< Controls the initialization of the
+ history in the ges calculation */
+ MPEGS_INIT_STATES_REVERB =
+ 0x00008000, /*!< Controls the initialization of the reverb states */
+ MPEGS_INIT_STATES_PARAM =
+ 0x00020000, /*!< Controls the initialization of the history of all other
+ parameter */
+ MPEGS_INIT_STATES_ERROR_CONCEALMENT =
+ 0x00080000, /*!< Controls the initialization of the error concealment
+ module state */
+ MPEGS_INIT_PARAMS_ERROR_CONCEALMENT = 0x00200000 /*!< Controls the
+ initialization of the
+ whole error concealment
+ parameter set */
+
+} MPEGS_INIT_CTRL_FLAGS;
+
+#define MASK_MPEGS_INIT_ALL_STATES (0x000FFF00)
+#define MASK_MPEGS_INIT_ALL_PARAMS (0x00F00000)
+
+typedef struct spatialDec_struct spatialDec, *HANDLE_SPATIAL_DEC;
+
+typedef struct SPATIAL_BS_FRAME_struct SPATIAL_BS_FRAME;
+
+typedef struct {
+ UINT sizePersistent; /* persistent memory */
+ UINT sizeFastPersistent; /* fast persistent memory */
+
+} MEM_REQUIREMENTS;
+
+#define PCM_MPS INT_PCM
+#define PCM_MPSF FIXP_PCM
+
+#define FIXP_DBL2PCM_MPS(x) ((INT_PCM)FX_DBL2FX_PCM(x))
+
+/* exposed functions (library interface) */
+
+int FDK_SpatialDecCompareSpatialSpecificConfigHeader(
+ SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2);
+
+int FDK_SpatialDecInitDefaultSpatialSpecificConfig(
+ SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
+ AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq,
+ int nTimeSlots, int decoderLevel, int isBlind);
+
+spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config,
+ int stereoConfigIndex);
+
+/**
+ * \brief Initialize state variables of the MPS parser
+ */
+void SpatialDecInitParserContext(spatialDec *self);
+
+/**
+ * \brief Initialize state of MPS decoder. This may happen after the first parse
+ * operation.
+ */
+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 /* MPEGS_INIT_CTRL_FLAGS */
+);
+
+/**
+ * \brief Apply decoded MPEG Surround parameters to time domain or QMF down mix
+ * data.
+ * \param self spatial decoder handle.
+ * \param inData Pointer to time domain input down mix data if any.
+ * \param qmfInDataReal Pointer array of QMF domain down mix input data (real
+ * part).
+ * \param qmfInDataImag Pointer array of QMF domain down mix input data
+ * (imaginary part).
+ * \param pcmOutBuf Pointer to a time domain buffer were the upmixed output data
+ * will be stored into.
+ * \param nSamples Amount of audio samples per channel of down mix input data
+ * (frame length).
+ * \param pControlFlags pointer to control flags field; input/output.
+ * \param numInputChannels amount of down mix input channels. Might not match
+ * the current tree config, useful for internal sanity checks and bypass mode.
+ * \param channelMapping array containing the desired output channel ordering to
+ * transform MPEG PCE style ordering to any other channel ordering. First
+ * dimension is the total channel count.
+ */
+SACDEC_ERROR SpatialDecApplyFrame(
+ spatialDec *self, SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE inputMode,
+ PCM_MPS *inData, /* Time domain input */
+ FIXP_DBL **qmfInDataReal, /* interleaved l/r */
+ FIXP_DBL **qmfInDataImag, /* interleaved 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);
+
+/**
+ * \brief Fill given arrays with audio channel types and indices.
+ * \param self spatial decoder handle.
+ * \param channelType array where corresponding channel types fr each output
+ * channels are stored into.
+ * \param channelIndices array where corresponding channel type indices fr each
+ * output channels are stored into.
+ */
+void SpatialDecChannelProperties(spatialDec *self,
+ AUDIO_CHANNEL_TYPE channelType[],
+ UCHAR channelIndices[],
+ const FDK_channelMapDescr *const mapDescr);
+
+void FDK_SpatialDecClose(spatialDec *self);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAC_DEC_INTERFACE_H */
diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp
new file mode 100644
index 0000000..56d8693
--- /dev/null
+++ b/libSACdec/src/sac_dec_lib.cpp
@@ -0,0 +1,1912 @@
+/* -----------------------------------------------------------------------------
+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 Interface
+
+*******************************************************************************/
+
+#include "sac_dec_lib.h"
+#include "sac_dec_interface.h"
+#include "sac_dec.h"
+#include "sac_bitdec.h"
+#include "FDK_matrixCalloc.h"
+
+#define MPS_DATA_BUFFER_SIZE (2048)
+
+/**
+ * \brief MPEG Surround data indication.
+ **/
+typedef enum {
+ MPEGS_ANCTYPE_FRAME = 0, /*!< MPEG Surround frame, see ISO/IEC 23003-1 */
+ MPEGS_ANCTYPE_HEADER_AND_FRAME = 1, /*!< MPEG Surround header and MPEG
+ Surround frame, see ISO/IEC 23003-1 */
+ MPEGS_ANCTYPE_RESERVED_1 = 2, /*!< reserved, see ISO/IEC 23003-1 */
+ MPEGS_ANCTYPE_RESERVED_2 = 3 /*!< reserved, see ISO/IEC 23003-1*/
+} MPEGS_ANCTYPE;
+
+/**
+ * \brief MPEG Surround data segment indication.
+ **/
+typedef enum {
+ MPEGS_CONTINUE = 0, /*!< Indicates if data segment continues a data block. */
+ MPEGS_STOP = 1, /*!< Indicates if data segment ends a data block. */
+ MPEGS_START = 2, /*!< Indicates if data segment begins a data block. */
+ MPEGS_START_STOP =
+ 3 /*!< Indicates if data segment begins and ends a data block. */
+} MPEGS_ANCSTARTSTOP;
+
+/**
+ * \brief MPEG Surround synchronizaiton state.
+ *
+ * CAUTION: Changing the enumeration values can break the sync mechanism
+ *because it is based on comparing the state values.
+ **/
+typedef enum {
+ MPEGS_SYNC_LOST =
+ 0, /*!< Indicates lost sync because of current discontinuity. */
+ MPEGS_SYNC_FOUND = 1, /*!< Parsed a valid header and (re)intialization was
+ successfully completed. */
+ MPEGS_SYNC_COMPLETE = 2 /*!< In sync and continuous. Found an independent
+ frame in addition to MPEGS_SYNC_FOUND.
+ Precondition: MPEGS_SYNC_FOUND. */
+} MPEGS_SYNCSTATE;
+
+/**
+ * \brief MPEG Surround operation mode.
+ **/
+typedef enum {
+ MPEGS_OPMODE_EMM = 0, /*!< Mode: Enhanced Matrix Mode (Blind) */
+ MPEGS_OPMODE_MPS_PAYLOAD = 1, /*!< Mode: Normal, Stereo or Binaural */
+ MPEGS_OPMODE_NO_MPS_PAYLOAD = 2 /*!< Mode: no MPEG Surround payload */
+} MPEGS_OPMODE;
+
+/**
+ * \brief MPEG Surround init flags.
+ **/
+typedef enum {
+ MPEGS_INIT_OK = 0x00000000, /*!< indicate correct initialization */
+ MPEGS_INIT_ENFORCE_REINIT =
+ 0x00000001, /*!< indicate complete initialization */
+
+ MPEGS_INIT_CHANGE_OUTPUT_MODE =
+ 0x00000010, /*!< indicate change of the output mode */
+ MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX =
+ 0x00000020, /*!< indicate change of low power/high quality */
+ MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE =
+ 0x00000040, /*!< indicate change of qmf/time interface */
+ MPEGS_INIT_CHANGE_HEADER = 0x00000080, /*!< indicate change of header */
+
+ MPEGS_INIT_ERROR_PAYLOAD =
+ 0x00000100, /*!< indicate payload/ancType/ancStartStop error */
+
+ MPEGS_INIT_BS_INTERRUPTION =
+ 0x00001000, /*!< indicate bitstream interruption */
+ MPEGS_INIT_CLEAR_HISTORY =
+ 0x00002000, /*!< indicate that all states shall be cleared */
+
+ /* Re-initialization of submodules */
+
+ MPEGS_INIT_CHANGE_CONCEAL_PARAMS = 0x00100000, /*!< indicate a change of at
+ least one error concealment
+ param */
+
+ /* No re-initialization needed, currently not used */
+ MPEGS_INIT_CHANGE_BYPASS_MODE =
+ 0x01000000, /*!< indicate change of bypass mode */
+
+ /* Re-initialization needed, currently not used */
+ MPEGS_INIT_ERROR_ANC_TYPE = 0x10000000, /*!< indicate ancType error*/
+ MPEGS_INIT_ERROR_ANC_STARTSTOP =
+ 0x20000000 /*!< indicate ancStartStop error */
+} MPEGS_INIT_FLAGS;
+
+struct MpegSurroundDecoder {
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain;
+ UCHAR mpsData[MPS_DATA_BUFFER_SIZE]; /* Buffer for MPS payload accross more
+ than one segment */
+ INT mpsDataBits; /* Amount of bits in mpsData */
+ /* MPEG Surround decoder */
+ SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig[1]; /* SSC delay line which is
+ used during decoding */
+ spatialDec *pSpatialDec;
+ SPATIAL_SPECIFIC_CONFIG
+ spatialSpecificConfigBackup; /* SSC used while parsing */
+
+ /* Creation parameter */
+ UCHAR mpegSurroundDecoderLevel;
+ /* Run-time parameter */
+ UCHAR mpegSurroundSscIsGlobalCfg; /* Flag telling that the SSC
+ (::spatialSpecificConfig) is a
+ out-of-band configuration. */
+ UCHAR mpegSurroundUseTimeInterface;
+
+ SPATIAL_BS_FRAME
+ bsFrames[1]; /* Bitstream Structs that contain data read from the
+ SpatialFrame() bitstream element */
+ BS_LL_STATE llState; /* Bit stream parser state memory */
+ UCHAR bsFrameParse; /* Current parse frame context index */
+ UCHAR bsFrameDecode; /* Current decode/apply frame context index */
+ UCHAR bsFrameDelay; /* Amount of frames delay between parsing and processing.
+ Required i.e. for interpolation error concealment. */
+
+ /* User prameters */
+ SPATIALDEC_PARAM mpegSurroundUserParams;
+
+ /* Internal flags */
+ SPATIAL_DEC_UPMIX_TYPE upmixType;
+ int initFlags[1];
+ MPEGS_ANCSTARTSTOP ancStartStopPrev;
+ MPEGS_SYNCSTATE fOnSync[1];
+
+ /* Inital decoder configuration */
+ SPATIAL_DEC_CONFIG decConfig;
+};
+
+static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc);
+
+/**
+ * \brief Get the number of QMF bands from the sampling frequency (in Hz)
+ **/
+static int mpegSurroundDecoder_GetNrOfQmfBands(
+ const SPATIAL_SPECIFIC_CONFIG *pSsc, UINT sampleRate) {
+ UINT samplingFrequency = sampleRate;
+ int qmfBands = 64;
+
+ if (pSsc != NULL) {
+ switch (pSsc->coreCodec) {
+ case AOT_USAC:
+ if ((pSsc->stereoConfigIndex == 3)) {
+ static const UCHAR mapIdx2QmfBands[3] = {24, 32, 16};
+ FDK_ASSERT((pSsc->coreSbrFrameLengthIndex >= 2) &&
+ (pSsc->coreSbrFrameLengthIndex <= 4));
+ qmfBands = mapIdx2QmfBands[pSsc->coreSbrFrameLengthIndex - 2];
+ }
+ return qmfBands;
+ default:
+ samplingFrequency = pSsc->samplingFreq;
+ break;
+ }
+ }
+
+ /* number of QMF bands depend on sampling frequency, see FDIS 23003-1:2006
+ * Chapter 6.3.3 */
+ if (samplingFrequency < 27713) {
+ qmfBands = 32;
+ }
+ if (samplingFrequency > 55426) {
+ qmfBands = 128;
+ }
+
+ return qmfBands;
+}
+
+/**
+ * \brief Analyse init flags
+ **/
+static int mpegSurroundDecoder_CalcInitFlags(SPATIAL_SPECIFIC_CONFIG *pSsc1,
+ SPATIAL_SPECIFIC_CONFIG *pSsc2,
+ int upmixTypeFlag,
+ int binauralQualityFlag,
+ int partiallyComplexFlag,
+ int *ctrlFlags) {
+ /* Analyse core coder */
+ if (pSsc1->coreCodec != pSsc2->coreCodec) {
+ *ctrlFlags |= MASK_MPEGS_INIT_ALL_STATES;
+ *ctrlFlags |= MASK_MPEGS_INIT_ALL_PARAMS;
+ } else {
+ /* Analyse elements for initialization of space analysis qmf filterbank */
+ if ((partiallyComplexFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) ||
+ (pSsc1->samplingFreq != pSsc2->samplingFreq)) {
+ *ctrlFlags |= MPEGS_INIT_STATES_ANA_QMF_FILTER;
+ *ctrlFlags |= MPEGS_INIT_STATES_ANA_HYB_FILTER;
+ }
+
+ /* Analyse elements for initialization of space synthesis qmf filterbank */
+ if ((upmixTypeFlag) || (partiallyComplexFlag) ||
+ (pSsc1->treeConfig != pSsc2->treeConfig) ||
+ (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
+ (pSsc1->bsFixedGainDMX != pSsc2->bsFixedGainDMX)) {
+ *ctrlFlags |= MPEGS_INIT_STATES_SYN_QMF_FILTER;
+ }
+
+ /* Analyse elements for initialization of decorrelator */
+ if ((upmixTypeFlag) || (partiallyComplexFlag) ||
+ (pSsc1->treeConfig != pSsc2->treeConfig) ||
+ (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
+ (pSsc1->decorrConfig != pSsc2->decorrConfig)) {
+ *ctrlFlags |= MPEGS_INIT_STATES_DECORRELATOR;
+ }
+
+ /* Analyse elements for initialization of m1 and m2 calculation */
+ if ((upmixTypeFlag) || (binauralQualityFlag) ||
+ (pSsc1->treeConfig != pSsc2->treeConfig) ||
+ (pSsc1->samplingFreq != pSsc2->samplingFreq))
+
+ {
+ *ctrlFlags |= MPEGS_INIT_STATES_M1M2;
+ }
+
+ /* Analyse elements for initialization of GES */
+ if ((upmixTypeFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) ||
+ (pSsc1->tempShapeConfig != pSsc2->tempShapeConfig)) {
+ *ctrlFlags |= MPEGS_INIT_STATES_GES;
+ }
+
+ /* Analyse elements for initialization of FDreverb */
+ if ((upmixTypeFlag) || (binauralQualityFlag) || (partiallyComplexFlag) ||
+ (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
+ (pSsc1->nTimeSlots != pSsc2->nTimeSlots)) {
+ *ctrlFlags |= MPEGS_INIT_STATES_REVERB;
+ }
+
+ /* Reset previous frame data whenever the config changes */
+ if (*ctrlFlags & MPEGS_INIT_CONFIG) {
+ *ctrlFlags |= MPEGS_INIT_STATES_PARAM;
+ }
+ }
+
+ return MPS_OK;
+}
+
+/**
+ * \brief Reset MPEG Surround status info
+ **/
+static void updateMpegSurroundDecoderStatus(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, int initFlags,
+ MPEGS_SYNCSTATE fOnSync, MPEGS_ANCSTARTSTOP ancStartStopPrev) {
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ initFlags;
+ if ((pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg != 0) &&
+ (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] >=
+ MPEGS_SYNC_FOUND) &&
+ (fOnSync < MPEGS_SYNC_FOUND)) {
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ MPEGS_SYNC_FOUND;
+ } else {
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ fOnSync;
+ }
+ pMpegSurroundDecoder->ancStartStopPrev = ancStartStopPrev;
+}
+
+static SACDEC_ERROR mpegSurroundDecoder_Create(
+ CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain);
+
+SAC_INSTANCE_AVAIL
+mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable(
+ CMpegSurroundDecoder *pMpegSurroundDecoder) {
+ SAC_INSTANCE_AVAIL instanceAvailable = SAC_INSTANCE_NOT_FULL_AVAILABLE;
+
+ if (pMpegSurroundDecoder->pSpatialDec != NULL) {
+ instanceAvailable = SAC_INSTANCE_FULL_AVAILABLE;
+ }
+
+ return instanceAvailable;
+}
+
+SACDEC_ERROR mpegSurroundDecoder_Open(
+ CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
+ SACDEC_ERROR error;
+
+ error = mpegSurroundDecoder_Create(pMpegSurroundDecoder, stereoConfigIndex,
+ pQmfDomain);
+
+ return error;
+}
+
+/**
+ * \brief Renamed function from getUpmixType to check_UParam_Build_DecConfig.
+ * This function checks if user params, decoder config and SSC are valid
+ * and if the decoder build can handle all this settings.
+ * The upmix type may be modified by this function.
+ * It is called in initMpegSurroundDecoder() after the ssc parse check,
+ * to have all checks in one place and to ensure these checks are always
+ * performed if config changes (inband and out-of-band).
+ *
+ * \param pUserParams User data handle.
+ * \param pDecConfig decoder config handle.
+ * \param pSsc spatial specific config handle.
+ * \param pUpmixType upmix type which is set by this function
+ *
+ * \return MPS_OK on sucess, and else on failure.
+ */
+static SACDEC_ERROR check_UParam_Build_DecConfig(
+ SPATIALDEC_PARAM const *pUserParams, SPATIAL_DEC_CONFIG const *pDecConfig,
+ const SPATIAL_SPECIFIC_CONFIG *pSsc, SPATIAL_DEC_UPMIX_TYPE *pUpmixType) {
+ int dmxChannels, outChannels, maxNumOutChannels;
+
+ FDK_ASSERT(pUserParams != NULL);
+ FDK_ASSERT(pUpmixType != NULL);
+
+ /* checks if implementation can handle the Ssc */
+
+ switch (pSsc->treeConfig) {
+ case SPATIALDEC_MODE_RSVD7: /* 212 */
+ dmxChannels = 1;
+ outChannels = 2;
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+
+ /* ------------------------------------------- */
+
+ /* Analyse pDecConfig params */
+ switch (pDecConfig->binauralMode) {
+ case BINAURAL_NONE:
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+
+ switch (pDecConfig->decoderMode) {
+ case EXT_HQ_ONLY:
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+
+ switch (pDecConfig->maxNumOutputChannels) {
+ case OUTPUT_CHANNELS_DEFAULT:
+ /* No special restrictions -> Get the level restriction: */
+ switch (pDecConfig->decoderLevel) {
+ case DECODER_LEVEL_0:
+ maxNumOutChannels = 2;
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+ break;
+ case OUTPUT_CHANNELS_2_0:
+ maxNumOutChannels = 2;
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+ /* ------------------------- */
+
+ /* check if we can handle user params */
+ if (pUserParams->blindEnable == 1) {
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+ {
+ switch ((SAC_DEC_OUTPUT_MODE)pUserParams->outputMode) {
+ case SACDEC_OUT_MODE_NORMAL:
+ if (maxNumOutChannels >= outChannels) {
+ *pUpmixType = UPMIX_TYPE_NORMAL;
+ } else {
+ { *pUpmixType = UPMIX_TYPE_BYPASS; }
+ }
+ break;
+ case SACDEC_OUT_MODE_STEREO:
+ if (dmxChannels == 1) {
+ if (outChannels == 2) {
+ *pUpmixType = UPMIX_TYPE_NORMAL;
+ }
+ } else {
+ *pUpmixType = UPMIX_TYPE_BYPASS;
+ }
+ break;
+ case SACDEC_OUT_MODE_6CHANNEL:
+ if (outChannels > 6) {
+ { *pUpmixType = UPMIX_TYPE_BYPASS; }
+ } else {
+ *pUpmixType = UPMIX_TYPE_NORMAL;
+ }
+ break;
+ default:
+ return MPS_UNSUPPORTED_CONFIG;
+ }
+ }
+
+ return MPS_OK;
+}
+
+/**
+ * \brief Init MPEG Surround decoder.
+ **/
+static SACDEC_ERROR initMpegSurroundDecoder(
+ CMpegSurroundDecoder *pMpegSurroundDecoder) {
+ SACDEC_ERROR err;
+ int initFlags = MPEGS_INIT_NONE, initFlagsDec;
+ int upmixTypeCurr = pMpegSurroundDecoder->upmixType;
+
+ FDK_ASSERT(pMpegSurroundDecoder != NULL);
+
+ SPATIAL_SPECIFIC_CONFIG *const pSSCinput =
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup;
+ SPATIAL_SPECIFIC_CONFIG *const pSSCtarget =
+ &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
+ initFlagsDec =
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode];
+
+ if (pSSCinput->coreCodec != AOT_USAC) {
+ /* here we check if we have a valid Ssc */
+ err = sscParseCheck(pSSCinput);
+ if (err != MPS_OK) goto bail;
+ }
+
+ /* here we check if Ssc matches build; also check UParams and DecConfig */
+ /* if desired upmixType is changes */
+ err = check_UParam_Build_DecConfig(
+ &pMpegSurroundDecoder->mpegSurroundUserParams,
+ &pMpegSurroundDecoder->decConfig, pSSCinput,
+ &pMpegSurroundDecoder->upmixType);
+ if (err != MPS_OK) goto bail;
+
+ /* init config */
+ if (initFlagsDec & MPEGS_INIT_CHANGE_HEADER) {
+ initFlags |= MPEGS_INIT_CONFIG;
+ }
+ /* init all states */
+ if (initFlagsDec & MPEGS_INIT_CLEAR_HISTORY) {
+ initFlags |= MASK_MPEGS_INIT_ALL_STATES;
+ }
+ if (initFlagsDec & MPEGS_INIT_CHANGE_CONCEAL_PARAMS) {
+ initFlags |= MPEGS_INIT_PARAMS_ERROR_CONCEALMENT;
+ }
+
+ if (initFlagsDec & MPEGS_INIT_ENFORCE_REINIT) {
+ /* init all states */
+ initFlags |= MASK_MPEGS_INIT_ALL_STATES;
+ initFlags |= MASK_MPEGS_INIT_ALL_PARAMS;
+ } else {
+ /* analyse states which have to be initialized */
+ mpegSurroundDecoder_CalcInitFlags(
+ pSSCtarget, pSSCinput,
+ (upmixTypeCurr !=
+ pMpegSurroundDecoder->upmixType), /* upmixType changed */
+ 0, (initFlagsDec & MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX) ? 1 : 0,
+ &initFlags);
+ }
+
+ {
+ int nrOfQmfBands;
+ FDKmemcpy(pSSCtarget, pSSCinput, sizeof(SPATIAL_SPECIFIC_CONFIG));
+
+ nrOfQmfBands = mpegSurroundDecoder_GetNrOfQmfBands(
+ pSSCtarget, pSSCtarget->samplingFreq);
+ err = FDK_SpatialDecInit(
+ pMpegSurroundDecoder->pSpatialDec,
+ &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
+ pSSCtarget, nrOfQmfBands, pMpegSurroundDecoder->upmixType,
+ &pMpegSurroundDecoder->mpegSurroundUserParams, initFlags);
+
+ if (err != MPS_OK) goto bail;
+
+ /* Signal that we got a header and can go on decoding */
+ if (err == MPS_OK) {
+ initFlagsDec = MPEGS_INIT_OK;
+ {
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ MPEGS_SYNC_FOUND;
+ }
+ }
+ }
+
+bail:
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] =
+ initFlagsDec;
+ return err;
+}
+
+/**
+ * \brief Init MPEG Surround decoder.
+ **/
+SACDEC_ERROR mpegSurroundDecoder_Init(
+ CMpegSurroundDecoder *pMpegSurroundDecoder) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
+ err = initMpegSurroundDecoder(pMpegSurroundDecoder);
+ }
+ return err;
+}
+
+/**
+ * \brief Open MPEG Surround decoder.
+ **/
+static SACDEC_ERROR mpegSurroundDecoder_Create(
+ CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
+ SACDEC_ERROR err = MPS_OK;
+ CMpegSurroundDecoder *sacDec = NULL;
+ spatialDec *self = NULL;
+
+ /* decoderLevel decoderMode maxNumOutputChannels binauralMode */
+ static const SPATIAL_DEC_CONFIG decConfig = {
+ (CFG_LEVEL)(0), EXT_HQ_ONLY, OUTPUT_CHANNELS_DEFAULT, BINAURAL_NONE};
+
+ if (*pMpegSurroundDecoder == NULL) {
+ FDK_ALLOCATE_MEMORY_1D(*pMpegSurroundDecoder, 1, CMpegSurroundDecoder)
+
+ for (int i = 0; i < 1; i++) {
+ err = SpatialDecCreateBsFrame(&(*pMpegSurroundDecoder)->bsFrames[i],
+ &(*pMpegSurroundDecoder)->llState);
+ if (err != MPS_OK) {
+ sacDec = *pMpegSurroundDecoder;
+ goto bail;
+ }
+ }
+ (*pMpegSurroundDecoder)->pQmfDomain = pQmfDomain;
+
+ (*pMpegSurroundDecoder)->bsFrameDelay = 1;
+ (*pMpegSurroundDecoder)->bsFrameParse = 0;
+ (*pMpegSurroundDecoder)->bsFrameDecode = 0;
+
+ return err;
+ } else {
+ sacDec = *pMpegSurroundDecoder;
+ }
+
+ if (sacDec->pSpatialDec == NULL) {
+ if ((self = FDK_SpatialDecOpen(&decConfig, stereoConfigIndex)) == NULL) {
+ err = MPS_OUTOFMEMORY;
+ goto bail;
+ }
+ } else {
+ self = sacDec->pSpatialDec;
+ }
+
+ self->pQmfDomain = sacDec->pQmfDomain;
+
+ sacDec->pSpatialDec = self;
+
+ /* default parameter set */
+ sacDec->mpegSurroundUserParams.outputMode = SACDEC_OUT_MODE_NORMAL;
+ sacDec->mpegSurroundUserParams.blindEnable = 0;
+ sacDec->mpegSurroundUserParams.bypassMode = 0;
+ sacDec->mpegSurroundUserParams.concealMethod = 1;
+ sacDec->mpegSurroundUserParams.concealNumKeepFrames = 10;
+ sacDec->mpegSurroundUserParams.concealFadeOutSlopeLength = 5;
+ sacDec->mpegSurroundUserParams.concealFadeInSlopeLength = 5;
+ sacDec->mpegSurroundUserParams.concealNumReleaseFrames = 3;
+ sacDec->mpegSurroundSscIsGlobalCfg = 0;
+ sacDec->mpegSurroundUseTimeInterface = 1;
+ sacDec->mpegSurroundDecoderLevel = decConfig.decoderLevel;
+
+ sacDec->upmixType = UPMIX_TYPE_NORMAL;
+
+ /* signalize spatial decoder re-initalization */
+ updateMpegSurroundDecoderStatus(sacDec, MPEGS_INIT_ENFORCE_REINIT,
+ MPEGS_SYNC_LOST, MPEGS_STOP);
+
+ /* return decoder instance */
+ *pMpegSurroundDecoder = sacDec;
+ sacDec->decConfig = decConfig;
+
+ SpatialDecInitParserContext(sacDec->pSpatialDec);
+
+ return err;
+
+bail:
+ if (sacDec != NULL) {
+ mpegSurroundDecoder_Close(sacDec);
+ }
+ *pMpegSurroundDecoder = NULL;
+ if (err == MPS_OK) {
+ return MPS_OUTOFMEMORY;
+ } else {
+ return err;
+ }
+}
+
+/**
+ * \brief Config MPEG Surround decoder.
+ **/
+SACDEC_ERROR mpegSurroundDecoder_Config(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
+ AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT stereoConfigIndex,
+ INT coreSbrFrameLengthIndex, INT configBytes, const UCHAR configMode,
+ UCHAR *configChanged) {
+ SACDEC_ERROR err = MPS_OK;
+
+ switch (coreCodec) {
+ case AOT_DRM_USAC:
+ case AOT_USAC:
+ if (configMode == AC_CM_DET_CFG_CHANGE) {
+ /* In config detection mode write spatial specific config parameters
+ * into temporarily allocated structure */
+ SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig;
+ err = SpatialDecParseMps212Config(
+ hBs, &spatialSpecificConfig, samplingRate, coreCodec,
+ stereoConfigIndex, coreSbrFrameLengthIndex);
+ } else {
+ err = SpatialDecParseMps212Config(
+ hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ samplingRate, coreCodec, stereoConfigIndex,
+ coreSbrFrameLengthIndex);
+ }
+ break;
+ case AOT_ER_AAC_ELD:
+ case AOT_ER_AAC_LD:
+ err = SpatialDecParseSpecificConfig(
+ hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup, configBytes,
+ coreCodec);
+ break;
+ default:
+ err = MPS_UNSUPPORTED_FORMAT;
+ break;
+ }
+
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ return err;
+ }
+
+ if (configMode & AC_CM_ALLOC_MEM) {
+ if (*configChanged) {
+ if ((err = mpegSurroundDecoder_Open(&pMpegSurroundDecoder,
+ stereoConfigIndex, NULL))) {
+ return err;
+ }
+ }
+ }
+
+ {
+ SPATIAL_SPECIFIC_CONFIG *sscParse =
+ &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
+
+ if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup, sscParse)) {
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse] |=
+ MPEGS_INIT_CHANGE_HEADER;
+ /* Error resilience code */
+ if (pMpegSurroundDecoder->pSpatialDec == NULL) {
+ err = MPS_NOTOK;
+ goto bail;
+ }
+ SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
+ pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
+ &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
+ }
+ }
+
+ if (err == MPS_OK) {
+ /* We got a valid out-of-band configuration so label it accordingly. */
+ pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 1;
+ }
+
+bail:
+ return err;
+}
+
+/**
+ * \brief Determine MPEG Surround operation mode.
+ **/
+static MPEGS_OPMODE mpegSurroundOperationMode(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, int mpsDataBits) {
+ MPEGS_OPMODE mode;
+
+ {
+ if ((mpsDataBits > 0) &&
+ (pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable == 0)) {
+ mode = MPEGS_OPMODE_MPS_PAYLOAD; /* Mode: Normal, Stereo or Binaural */
+ } else {
+ mode = MPEGS_OPMODE_NO_MPS_PAYLOAD; /* Mode: No MPEG Surround Payload */
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
+ MPEGS_STOP);
+ }
+ }
+
+ return (mode);
+}
+
+/**
+ * \brief Check ssc for parse errors.
+ * This one is called in initMpegSurroundDecoder()
+ * to ensure checking of inband and out-of-band mps configs.
+ * Only parse errors checked here! Check for valid config is done
+ * in check_UParam_Build_DecConfig()!
+ *
+ * \param pSsc spatial specific config handle.
+ *
+ * \return MPS_OK on sucess, and else on parse error.
+ */
+static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if (pSsc->samplingFreq > 96000) return MPS_PARSE_ERROR;
+ if (pSsc->samplingFreq < 8000) return MPS_PARSE_ERROR;
+
+ switch (pSsc->freqRes) {
+ case SPATIALDEC_FREQ_RES_28:
+ case SPATIALDEC_FREQ_RES_20:
+ case SPATIALDEC_FREQ_RES_14:
+ case SPATIALDEC_FREQ_RES_10:
+ case SPATIALDEC_FREQ_RES_23:
+ case SPATIALDEC_FREQ_RES_15:
+ case SPATIALDEC_FREQ_RES_12:
+ case SPATIALDEC_FREQ_RES_9:
+ case SPATIALDEC_FREQ_RES_7:
+ case SPATIALDEC_FREQ_RES_5:
+ case SPATIALDEC_FREQ_RES_4:
+ break;
+ case SPATIALDEC_FREQ_RES_40: /* 40 doesn't exist in ISO/IEC 23003-1 */
+ default:
+ return MPS_PARSE_ERROR;
+ }
+
+ if ((pSsc->treeConfig < 0) || (pSsc->treeConfig > 7)) {
+ return MPS_PARSE_ERROR;
+ }
+
+ if ((pSsc->quantMode < 0) || (pSsc->quantMode > 2)) {
+ return MPS_PARSE_ERROR;
+ }
+
+ if (pSsc->tempShapeConfig == 3) {
+ return MPS_PARSE_ERROR;
+ }
+
+ if (pSsc->decorrConfig == 3) {
+ return MPS_PARSE_ERROR;
+ }
+
+ /* now we are sure there were no parsing errors */
+
+ return err;
+}
+
+/**
+ * \brief Check number of time slots
+ *
+ * Basically the mps frame length must be a multiple of the core coder frame
+ * length. The below table shows all valid configurations in detail. See ISO/IEC
+ * 23003-1: "Table 4A - Allowed values for bsFrameLength in the Baseline MPEG
+ * Surround Profile"
+ *
+ * Downmix Coder Downmix Code Allowed values for bsFrameLength
+ * Allowed frame sizes for normal, downsampled and upsampled MPS Framelength
+ * (QMF Samples)
+ *
+ * AAC 1024 16 15, 31, 47, 63 1024 2048 3072 4096
+ * downsampled MPS 32 31, 63 1024 2048 upsampled MPS
+ * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096
+ * 5120 6144 7168 8192 9216
+ *
+ * AAC 960 15 14, 29, 44, 59 960 1920 2880 3840
+ * downsampled MPS 30 29, 59 960 1920 upsampled MPS
+ * 7,5 14, 29, 44, 59 1920 3840 5760 7680
+ *
+ * HE-AAC 1024/2048 32 31, 63 2048 4096 downsampled MPS
+ * 64 63 2048 upsampled MPS
+ * 16 15, 31, 47, 63 2048 4096 6144 8192
+ *
+ * HE-AAC 960/1920 30 29, 59 1920 3840 downsampled MPS
+ * 60 59 1920 upsampled MPS
+ * 15 14, 29, 44, 59 1920 3840 5760 7680
+ *
+ * BSAC 16 15, 31, 47, 63 1024 2048 3072 4096
+ * downsampled MPS 32 31, 63 1024 2048 upsampled MPS
+ * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096
+ * 5120 6144 7168 8192 9216
+ *
+ * BSAC with SBR 32 31, 63 2048 4096 downsampled MPS
+ * 64 63 2048 upsampled MPS
+ * 16 15, 31, 47, 63 2048 4096 6144 8192
+ *
+ * AAC LD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71
+ * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS
+ * 16 15, 31, 47, 63 512 1024 1536 2048
+ *
+ * AAC ELD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71
+ * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS
+ * 16 15, 31, 47, 63 512 1024 1536 2048
+ *
+ * AAC ELD with SBR 512/1024 16 15, 31, 47, 63 1024 2048 3072 4096
+ * downsampled MPS 32 31, 63 1024 2048 upsampled MPS
+ * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096
+ * 5120 6144 7168 8192 9216
+ *
+ * MPEG1/2 Layer II 18 17, 35, 53, 71 1152 2304 3456 4608
+ * downsampled MPS 36 35, 71 1152 2304
+ *
+ * MPEG1/2 Layer III 18 17, 35, 53, 71 1152 2304 3456 4608
+ * downsampled MPS 36 35, 71 1152 2304
+ *
+ * \param frameLength
+ * \param qmfBands
+ * \param timeSlots
+ *
+ * \return error code
+ */
+SACDEC_ERROR checkTimeSlots(int frameLength, int qmfBands, int timeSlots) {
+ int len;
+ int maxFrameLength;
+
+ if (qmfBands == 64) {
+ /* normal MPEG Surround */
+ switch (frameLength) {
+ case 960:
+ case 1920:
+ maxFrameLength = 3840;
+ break;
+ case 1024:
+ case 2048:
+ maxFrameLength = 4096;
+ break;
+ case 512:
+ case 1152:
+ maxFrameLength = 4608;
+ break;
+ default:
+ return MPS_PARSE_ERROR;
+ }
+ } else if (qmfBands == 32) {
+ /* downsampled MPEG Surround */
+ switch (frameLength) {
+ case 960:
+ case 1920:
+ maxFrameLength = 1920;
+ break;
+ case 512:
+ case 1024:
+ case 2048:
+ maxFrameLength = 2048;
+ break;
+ case 1152:
+ maxFrameLength = 2304;
+ break;
+ default:
+ return MPS_PARSE_ERROR;
+ }
+ } else if (qmfBands == 128) {
+ /* upsampled MPEG Surround */
+ switch (frameLength) {
+ case 1920:
+ maxFrameLength = 7680;
+ break;
+ case 1024:
+ maxFrameLength = 9216;
+ break;
+ case 2048:
+ maxFrameLength = 8192;
+ break;
+ case 512:
+ case 960:
+ case 1152:
+ /* no break, no support for upsampled MPEG Surround */
+ default:
+ return MPS_PARSE_ERROR;
+ }
+ } else {
+ return MPS_PARSE_ERROR;
+ }
+
+ len = frameLength;
+
+ while (len <= maxFrameLength) {
+ if (len == timeSlots * qmfBands) {
+ return MPS_OK;
+ }
+ len += frameLength;
+ }
+ return MPS_PARSE_ERROR;
+}
+
+/**
+ * \brief Check ssc for consistency (e.g. bit errors could cause trouble)
+ * First of currently two ssc-checks.
+ * This (old) one is called in mpegSurroundDecoder_Apply()
+ * only if inband mps config is contained in stream.
+ *
+ * New ssc check is split in two functions sscParseCheck() and
+ * check_UParam_Build_DecConfig(). sscParseCheck() checks only for correct
+ * parsing. check_UParam_Build_DecConfig() is used to check if we have a
+ * valid config. Both are called in initMpegSurroundDecoder() to ensure
+ * checking of inband and out-of-band mps configs.
+ *
+ * If this function can be integrated into the new functions.
+ * We can remove this one.
+ *
+ * \param pSsc spatial specific config handle.
+ * \param frameLength
+ * \param sampleRate
+ *
+ * \return MPS_OK on sucess, and else on failure.
+ */
+static SACDEC_ERROR sscCheckInBand(SPATIAL_SPECIFIC_CONFIG *pSsc,
+ int frameLength, int sampleRate) {
+ SACDEC_ERROR err = MPS_OK;
+ int qmfBands;
+
+ FDK_ASSERT(pSsc != NULL);
+
+ /* core fs and mps fs must match */
+ if (pSsc->samplingFreq != sampleRate) {
+ err = MPS_PARSE_ERROR /* MPEGSDEC_SSC_PARSE_ERROR */;
+ }
+
+ qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq);
+
+ if (checkTimeSlots(frameLength, qmfBands, pSsc->nTimeSlots) != MPS_OK) {
+ err = MPS_PARSE_ERROR;
+ }
+
+ return err;
+}
+
+SACDEC_ERROR
+mpegSurroundDecoder_ConfigureQmfDomain(
+ CMpegSurroundDecoder *pMpegSurroundDecoder,
+ SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate,
+ AUDIO_OBJECT_TYPE coreCodec) {
+ SACDEC_ERROR err = MPS_OK;
+ FDK_QMF_DOMAIN_GC *pGC = NULL;
+
+ if (pMpegSurroundDecoder == NULL) {
+ return MPS_INVALID_HANDLE;
+ }
+
+ FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
+
+ pGC = &pMpegSurroundDecoder->pQmfDomain->globalConf;
+ if (pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg) {
+ SPATIAL_SPECIFIC_CONFIG *pSSC =
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup;
+ if (sac_dec_interface == SAC_INTERFACE_TIME) {
+ /* For SAC_INTERFACE_QMF these parameters are set by SBR. */
+ pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands(
+ pSSC, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for
+ SAC_INTERFACE_TIME */
+ pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested;
+ pGC->nInputChannels_requested =
+ fMax((UINT)pSSC->nInputChannels, (UINT)pGC->nInputChannels_requested);
+ }
+ pGC->nOutputChannels_requested =
+ fMax((UINT)pSSC->nOutputChannels, (UINT)pGC->nOutputChannels_requested);
+ } else {
+ if (sac_dec_interface == SAC_INTERFACE_TIME) {
+ /* For SAC_INTERFACE_QMF these parameters are set by SBR. */
+ pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands(
+ NULL, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for
+ SAC_INTERFACE_TIME */
+ pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested;
+ pGC->nInputChannels_requested =
+ pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels;
+ }
+ pGC->nOutputChannels_requested =
+ pMpegSurroundDecoder->pSpatialDec->createParams.maxNumOutputChannels;
+ }
+ pGC->nQmfProcBands_requested = 64;
+ pGC->nQmfProcChannels_requested =
+ fMin((INT)pGC->nInputChannels_requested,
+ pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels);
+
+ if (coreCodec == AOT_ER_AAC_ELD) {
+ pGC->flags_requested |= QMF_FLAG_MPSLDFB;
+ }
+
+ return err;
+}
+
+/**
+ * \brief Decode MPEG Surround frame.
+ **/
+int mpegSurroundDecoder_ParseNoHeader(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
+ int *pMpsDataBits, int fGlobalIndependencyFlag) {
+ SACDEC_ERROR err = MPS_OK;
+ SPATIAL_SPECIFIC_CONFIG *sscParse;
+ int bitsAvail, numSacBits;
+
+ if (pMpegSurroundDecoder == NULL || hBs == NULL) {
+ return MPS_INVALID_HANDLE;
+ }
+
+ sscParse = &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
+
+ bitsAvail = FDKgetValidBits(hBs);
+
+ /* First spatial specific config is parsed into spatialSpecificConfigBackup,
+ * second spatialSpecificConfigBackup is copied into
+ * spatialSpecificConfig[bsFrameDecode] */
+ if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse]) {
+ FDKmemcpy(sscParse, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ sizeof(SPATIAL_SPECIFIC_CONFIG));
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameParse] =
+ MPEGS_SYNC_FOUND;
+ }
+
+ if (bitsAvail <= 0) {
+ err = MPS_PARSE_ERROR;
+ } else {
+ err = SpatialDecParseFrameData(
+ pMpegSurroundDecoder->pSpatialDec,
+ &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse],
+ hBs, sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType,
+ fGlobalIndependencyFlag);
+ if (err == MPS_OK) {
+ pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
+ .newBsData = 1;
+ }
+ }
+
+ numSacBits = bitsAvail - (INT)FDKgetValidBits(hBs);
+
+ if (numSacBits > bitsAvail) {
+ pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
+ .newBsData = 0;
+ err = MPS_PARSE_ERROR;
+ }
+
+ *pMpsDataBits -= numSacBits;
+
+ return err;
+}
+
+/**
+ * \brief Check, if ancType is valid.
+ **/
+static int isValidAncType(CMpegSurroundDecoder *pMpegSurroundDecoder,
+ int ancType) {
+ int ret = 1;
+
+ if ((ancType != MPEGS_ANCTYPE_HEADER_AND_FRAME) &&
+ (ancType != MPEGS_ANCTYPE_FRAME)) {
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
+ MPEGS_STOP);
+ }
+
+ return (ret);
+}
+
+/**
+ * \brief Check, if ancStartStop is valid.
+ **/
+static int isValidAncStartStop(CMpegSurroundDecoder *pMpegSurroundDecoder,
+ int ancStartStop) {
+ int ret = 1;
+
+ switch (ancStartStop) {
+ case MPEGS_START:
+ /* Sequence start - start and continue - start not allowed */
+ if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START) ||
+ (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_CONTINUE)) {
+ ret = 0;
+ }
+ break;
+
+ case MPEGS_STOP:
+ /* MPS payload of the previous frame must be valid if current type is stop
+ Sequence startstop - stop and stop - stop not allowed
+ Sequence startstop - continue and stop - continue are allowed */
+ if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_STOP) ||
+ (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START_STOP)) {
+ ret = 0;
+ }
+ break;
+
+ case MPEGS_CONTINUE:
+ case MPEGS_START_STOP:
+ /* No error detection possible for this states */
+ break;
+ }
+
+ if (ret == 0) {
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
+ MPEGS_STOP);
+ } else {
+ pMpegSurroundDecoder->ancStartStopPrev = (MPEGS_ANCSTARTSTOP)ancStartStop;
+ }
+
+ return (ret);
+}
+
+int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder,
+ HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits,
+ AUDIO_OBJECT_TYPE coreCodec, int sampleRate,
+ int frameSize, int fGlobalIndependencyFlag) {
+ SACDEC_ERROR err = MPS_OK;
+ SPATIAL_SPECIFIC_CONFIG *sscParse;
+ SPATIAL_BS_FRAME *bsFrame;
+ HANDLE_FDK_BITSTREAM hMpsBsData = NULL;
+ FDK_BITSTREAM mpsBsData;
+ int mpsDataBits = *pMpsDataBits;
+ int mpsBsBits;
+ MPEGS_ANCTYPE ancType;
+ MPEGS_ANCSTARTSTOP ancStartStop;
+
+ if (pMpegSurroundDecoder == NULL) {
+ return MPS_INVALID_HANDLE;
+ }
+
+ FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
+
+ mpsBsBits = FDKgetValidBits(hBs);
+
+ sscParse = &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
+ bsFrame = &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse];
+
+ /*
+ Find operation mode of mpeg surround decoder:
+ - MPEGS_OPMODE_EMM: Mode: Enhanced Matrix Mode (Blind)
+ - MPEGS_OPMODE_MPS_PAYLOAD: Mode: Normal, Stereo or Binaural
+ - MPEGS_OPMODE_NO_MPS_PAYLOAD: Mode: No MpegSurround Payload
+ */
+ {
+ /* Parse ancType and ancStartStop */
+ ancType = (MPEGS_ANCTYPE)FDKreadBits(hBs, 2);
+ ancStartStop = (MPEGS_ANCSTARTSTOP)FDKreadBits(hBs, 2);
+ mpsDataBits -= 4;
+
+ /* Set valid anc type flag, if ancType signals a payload with either header
+ * and frame or frame */
+ if (isValidAncType(pMpegSurroundDecoder, ancType)) {
+ /* Set valid anc startstop flag, if transmitted sequence is not illegal */
+ if (isValidAncStartStop(pMpegSurroundDecoder, ancStartStop)) {
+ switch (ancStartStop) {
+ case MPEGS_START:
+ /* Assuming that core coder frame size (AAC) is smaller than MPS
+ coder frame size. Save audio data for next frame. */
+ if (mpsDataBits > MPS_DATA_BUFFER_SIZE * 8) {
+ err = MPS_NOTOK;
+ goto bail;
+ }
+ for (int i = 0; i < mpsDataBits / 8; i++) {
+ pMpegSurroundDecoder->mpsData[i] = FDKreadBits(hBs, 8);
+ }
+ pMpegSurroundDecoder->mpsDataBits = mpsDataBits;
+ break;
+
+ case MPEGS_CONTINUE:
+ case MPEGS_STOP:
+ /* Assuming that core coder frame size (AAC) is smaller than MPS
+ coder frame size. Save audio data for next frame. */
+ if ((pMpegSurroundDecoder->mpsDataBits + mpsDataBits) >
+ MPS_DATA_BUFFER_SIZE * 8) {
+ err = MPS_NOTOK;
+ goto bail;
+ }
+ for (int i = 0; i < mpsDataBits / 8; i++) {
+ pMpegSurroundDecoder
+ ->mpsData[(pMpegSurroundDecoder->mpsDataBits / 8) + i] =
+ FDKreadBits(hBs, 8);
+ }
+ pMpegSurroundDecoder->mpsDataBits += mpsDataBits;
+ FDKinitBitStream(&mpsBsData, pMpegSurroundDecoder->mpsData,
+ MAX_BUFSIZE_BYTES,
+ pMpegSurroundDecoder->mpsDataBits, BS_READER);
+ hMpsBsData = &mpsBsData;
+ break;
+
+ case MPEGS_START_STOP:
+ pMpegSurroundDecoder->mpsDataBits = mpsDataBits;
+ hMpsBsData = hBs;
+ break;
+
+ default:
+ FDK_ASSERT(0);
+ }
+
+ if ((ancStartStop == MPEGS_STOP) ||
+ (ancStartStop == MPEGS_START_STOP)) {
+ switch (ancType) {
+ case MPEGS_ANCTYPE_HEADER_AND_FRAME: {
+ int parseResult, bitsRead;
+ SPATIAL_SPECIFIC_CONFIG spatialSpecificConfigTmp =
+ pMpegSurroundDecoder->spatialSpecificConfigBackup;
+
+ /* Parse spatial specific config */
+ bitsRead = FDKgetValidBits(hMpsBsData);
+
+ err = SpatialDecParseSpecificConfigHeader(
+ hMpsBsData,
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec,
+ pMpegSurroundDecoder->upmixType);
+
+ bitsRead = (bitsRead - FDKgetValidBits(hMpsBsData));
+ parseResult = ((err == MPS_OK) ? bitsRead : -bitsRead);
+
+ if (parseResult < 0) {
+ parseResult = -parseResult;
+ err = MPS_PARSE_ERROR;
+ } else if (err == MPS_OK) {
+ /* Check SSC for consistency (e.g. bit errors could cause
+ * trouble) */
+ err = sscCheckInBand(
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ frameSize, sampleRate);
+ }
+ if (err != MPS_OK) {
+ pMpegSurroundDecoder->spatialSpecificConfigBackup =
+ spatialSpecificConfigTmp;
+ break;
+ }
+
+ pMpegSurroundDecoder->mpsDataBits -= parseResult;
+
+ /* Initiate re-initialization, if header has changed */
+ if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ sscParse) == MPS_UNEQUAL_SSC) {
+ pMpegSurroundDecoder
+ ->initFlags[pMpegSurroundDecoder->bsFrameParse] |=
+ MPEGS_INIT_CHANGE_HEADER;
+ SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
+ /* We found a valid in-band configuration. Therefore any
+ * previous config is invalid now. */
+ pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 0;
+ }
+ }
+ case MPEGS_ANCTYPE_FRAME:
+
+ if (pMpegSurroundDecoder
+ ->initFlags[pMpegSurroundDecoder->bsFrameParse] &
+ MPEGS_INIT_ERROR_PAYLOAD) {
+ err = MPS_PARSE_ERROR;
+ break;
+ }
+
+ /* First spatial specific config is parsed into
+ * spatialSpecificConfigBackup, second spatialSpecificConfigBackup
+ * is copied into spatialSpecificConfig[bsFrameDecode] */
+ if (pMpegSurroundDecoder
+ ->initFlags[pMpegSurroundDecoder->bsFrameParse]) {
+ FDKmemcpy(sscParse,
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ sizeof(SPATIAL_SPECIFIC_CONFIG));
+ pMpegSurroundDecoder
+ ->fOnSync[pMpegSurroundDecoder->bsFrameParse] =
+ MPEGS_SYNC_FOUND;
+ }
+
+ if (pMpegSurroundDecoder
+ ->fOnSync[pMpegSurroundDecoder->bsFrameParse] >=
+ MPEGS_SYNC_FOUND) {
+ int nbits = 0, bitsAvail;
+
+ if (err != MPS_OK) {
+ break;
+ }
+
+ bitsAvail = FDKgetValidBits(hMpsBsData);
+
+ if (bitsAvail <= 0) {
+ err = MPS_PARSE_ERROR;
+ } else {
+ err = SpatialDecParseFrameData(
+ pMpegSurroundDecoder->pSpatialDec, bsFrame, hMpsBsData,
+ sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType,
+ fGlobalIndependencyFlag);
+ if (err == MPS_OK) {
+ bsFrame->newBsData = 1;
+ }
+ }
+
+ nbits = bitsAvail - (INT)FDKgetValidBits(hMpsBsData);
+
+ if ((nbits > bitsAvail) ||
+ (nbits > pMpegSurroundDecoder->mpsDataBits) ||
+ (pMpegSurroundDecoder->mpsDataBits > nbits + 7 &&
+ !IS_LOWDELAY(coreCodec))) {
+ bsFrame->newBsData = 0;
+ err = MPS_PARSE_ERROR;
+ break;
+ }
+ pMpegSurroundDecoder->mpsDataBits -= nbits;
+ }
+ break;
+
+ default: /* added to avoid compiler warning */
+ err = MPS_NOTOK;
+ break; /* added to avoid compiler warning */
+ } /* switch (ancType) */
+
+ if (err == MPS_OK) {
+ pMpegSurroundDecoder->ancStartStopPrev = ancStartStop;
+ } else {
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ERROR_PAYLOAD,
+ MPEGS_SYNC_LOST, MPEGS_STOP);
+ pMpegSurroundDecoder->mpsDataBits = 0;
+ }
+ } /* (ancStartStop == MPEGS_STOP) || (ancStartStop == MPEGS_START_STOP)
+ */
+ } /* validAncStartStop */
+ } /* validAncType */
+ }
+
+bail:
+
+ *pMpsDataBits -= (mpsBsBits - FDKgetValidBits(hBs));
+
+ return err;
+}
+
+int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
+ INT_PCM *input, PCM_MPS *pTimeData,
+ const int timeDataSize, int timeDataFrameSize,
+ int *nChannels, int *frameSize, int sampleRate,
+ AUDIO_OBJECT_TYPE coreCodec,
+ AUDIO_CHANNEL_TYPE channelType[],
+ UCHAR channelIndices[],
+ const FDK_channelMapDescr *const mapDescr) {
+ SACDEC_ERROR err = MPS_OK;
+ PCM_MPS *pTimeOut = pTimeData;
+ UINT initControlFlags = 0, controlFlags = 0;
+ int timeDataRequiredSize = 0;
+ int newData;
+
+ if (pMpegSurroundDecoder == NULL) {
+ return MPS_INVALID_HANDLE;
+ }
+
+ FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
+
+ if (!FDK_chMapDescr_isValid(mapDescr)) {
+ return MPS_INVALID_HANDLE;
+ }
+
+ if ((*nChannels <= 0) || (*nChannels > 2)) {
+ return MPS_NOTOK;
+ }
+
+ pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
+ &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
+ newData = pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
+ .newBsData;
+
+ switch (mpegSurroundOperationMode(pMpegSurroundDecoder, 1000)) {
+ case MPEGS_OPMODE_MPS_PAYLOAD:
+ if (pMpegSurroundDecoder
+ ->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
+ err = initMpegSurroundDecoder(pMpegSurroundDecoder);
+ }
+
+ if (err == MPS_OK) {
+ if ((pMpegSurroundDecoder
+ ->fOnSync[pMpegSurroundDecoder->bsFrameDecode] !=
+ MPEGS_SYNC_COMPLETE) &&
+ (pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode]
+ .bsIndependencyFlag == 1)) {
+ /* We got a valid header and independently decodeable frame data.
+ -> Go to the next sync level and start processing. */
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ MPEGS_SYNC_COMPLETE;
+ }
+ } else {
+ /* We got a valid config header but found an error while parsing the
+ bitstream. Wait for the next independent frame and apply error
+ conealment in the meantime. */
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ MPEGS_SYNC_FOUND;
+ controlFlags |= MPEGS_CONCEAL;
+ err = MPS_OK;
+ }
+ /*
+ Concealment:
+ - Bitstream is available, no sync found during bitstream processing
+ - Bitstream is available, sync lost due to corrupted bitstream
+ - Bitstream is available, sync found but no independent frame
+ */
+ if (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] !=
+ MPEGS_SYNC_COMPLETE) {
+ controlFlags |= MPEGS_CONCEAL;
+ }
+ break;
+
+ case MPEGS_OPMODE_NO_MPS_PAYLOAD:
+ /* Concealment: No bitstream is available */
+ controlFlags |= MPEGS_CONCEAL;
+ break;
+
+ default:
+ err = MPS_NOTOK;
+ }
+
+ if (err != MPS_OK) {
+ goto bail;
+ }
+
+ /*
+ * Force BypassMode if choosen by user
+ */
+ if (pMpegSurroundDecoder->mpegSurroundUserParams.bypassMode) {
+ controlFlags |= MPEGS_BYPASSMODE;
+ }
+
+ if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
+ int startWithDfltCfg = 0;
+ /*
+ * Init with a default configuration if we came here and are still not
+ * initialized.
+ */
+ if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] &
+ MPEGS_INIT_ENFORCE_REINIT) {
+ /* Get default spatial specific config */
+ if (FDK_SpatialDecInitDefaultSpatialSpecificConfig(
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec,
+ *nChannels, sampleRate,
+ *frameSize /
+ mpegSurroundDecoder_GetNrOfQmfBands(NULL, sampleRate),
+ pMpegSurroundDecoder->mpegSurroundDecoderLevel,
+ pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable)) {
+ err = MPS_NOTOK;
+ goto bail;
+ }
+
+ /* Initiate re-initialization, if header has changed */
+ if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
+ &pMpegSurroundDecoder->spatialSpecificConfigBackup,
+ &pMpegSurroundDecoder->spatialSpecificConfig
+ [pMpegSurroundDecoder->bsFrameDecode]) == MPS_UNEQUAL_SSC) {
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_HEADER;
+ SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
+ }
+
+ startWithDfltCfg = 1;
+ }
+
+ /* First spatial specific config is parsed into spatialSpecificConfigBackup,
+ * second spatialSpecificConfigBackup is copied into spatialSpecificConfig
+ */
+ err = initMpegSurroundDecoder(pMpegSurroundDecoder);
+
+ if (startWithDfltCfg) {
+ /* initialized with default config, but no sync found */
+ /* maybe use updateMpegSurroundDecoderStatus later on */
+ pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
+ MPEGS_SYNC_LOST;
+ }
+
+ /* Since we do not have state MPEGS_SYNC_COMPLETE apply concealment */
+ controlFlags |= MPEGS_CONCEAL;
+
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ }
+
+ /*
+ * Process MPEG Surround Audio
+ */
+ initControlFlags = controlFlags;
+
+ /* Check that provided output buffer is large enough. */
+ timeDataRequiredSize =
+ (timeDataFrameSize *
+ pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT *
+ pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
+ pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
+ if (timeDataSize < timeDataRequiredSize) {
+ err = MPS_OUTPUT_BUFFER_TOO_SMALL;
+ goto bail;
+ }
+
+ if ((pMpegSurroundDecoder->pSpatialDec->pConfigCurrent->syntaxFlags &
+ SACDEC_SYNTAX_USAC) &&
+ (pMpegSurroundDecoder->pSpatialDec->stereoConfigIndex > 1)) {
+ FDK_ASSERT(timeDataRequiredSize >= timeDataFrameSize * *nChannels);
+ /* Place samples comprising QMF time slots spaced at QMF output Band raster
+ * to allow slot wise processing */
+ int timeDataFrameSizeOut =
+ (timeDataFrameSize *
+ pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
+ pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
+ pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput =
+ pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
+ for (int i = *nChannels - 1; i >= 0; i--) {
+ FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize,
+ pTimeData + timeDataFrameSize * i,
+ sizeof(PCM_MPS) * timeDataFrameSize);
+ FDKmemclear(pTimeData + i * timeDataFrameSizeOut,
+ sizeof(PCM_MPS) * (timeDataFrameSizeOut - timeDataFrameSize));
+ }
+ } else {
+ if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) {
+ FDKmemcpy(input, pTimeData,
+ sizeof(INT_PCM) * (*nChannels) * (*frameSize));
+ pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = input;
+ }
+ }
+
+ /*
+ * Process MPEG Surround Audio
+ */
+ err = SpatialDecApplyFrame(
+ pMpegSurroundDecoder->pSpatialDec,
+ &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
+ pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME
+ : INPUTMODE_QMF_SBR,
+ pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput, NULL, NULL,
+ pTimeOut, *frameSize, &controlFlags, *nChannels, mapDescr);
+ *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT;
+
+ if (err !=
+ MPS_OK) { /* A fatal error occured. Go back to start and try again: */
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ENFORCE_REINIT, MPEGS_SYNC_LOST,
+ MPEGS_STOP);
+ *frameSize =
+ 0; /* Declare that framework can not use the data in pTimeOut. */
+ } else {
+ if (((controlFlags & MPEGS_CONCEAL) &&
+ !(initControlFlags & MPEGS_CONCEAL)) ||
+ (pMpegSurroundDecoder->pSpatialDec->errInt !=
+ MPS_OK)) { /* Account for errors that occured in
+ SpatialDecApplyFrame(): */
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
+ MPEGS_STOP);
+ }
+ }
+
+ if ((err == MPS_OK) && !(controlFlags & MPEGS_BYPASSMODE) &&
+ !(pMpegSurroundDecoder->upmixType == UPMIX_TYPE_BYPASS)) {
+ SpatialDecChannelProperties(pMpegSurroundDecoder->pSpatialDec, channelType,
+ channelIndices, mapDescr);
+ }
+
+bail:
+
+ if (newData) {
+ /* numParameterSetsPrev shall only be read in the decode process, because of
+ that we can update this state variable here */
+ pMpegSurroundDecoder->pSpatialDec->numParameterSetsPrev =
+ pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode]
+ .numParameterSets;
+ }
+
+ return (err);
+}
+
+/**
+ * \brief Free config dependent MPEG Surround memory.
+ **/
+SACDEC_ERROR mpegSurroundDecoder_FreeMem(
+ CMpegSurroundDecoder *pMpegSurroundDecoder) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if (pMpegSurroundDecoder != NULL) {
+ FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec);
+ pMpegSurroundDecoder->pSpatialDec = NULL;
+ }
+
+ return err;
+}
+
+/**
+ * \brief Close MPEG Surround decoder.
+ **/
+void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) {
+ if (pMpegSurroundDecoder != NULL) {
+ FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec);
+ pMpegSurroundDecoder->pSpatialDec = NULL;
+
+ for (int i = 0; i < 1; i++) {
+ SpatialDecCloseBsFrame(&pMpegSurroundDecoder->bsFrames[i]);
+ }
+
+ FDK_FREE_MEMORY_1D(pMpegSurroundDecoder);
+ }
+}
+
+#define SACDEC_VL0 2
+#define SACDEC_VL1 0
+#define SACDEC_VL2 0
+
+int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) {
+ int i;
+
+ if (info == NULL) {
+ return -1;
+ }
+
+ /* search for next free tab */
+ for (i = 0; i < FDK_MODULE_LAST; i++) {
+ if (info[i].module_id == FDK_NONE) break;
+ }
+ if (i == FDK_MODULE_LAST) return -1;
+
+ info += i;
+
+ info->module_id = FDK_MPSDEC;
+#ifdef __ANDROID__
+ info->build_date = "";
+ info->build_time = "";
+#else
+ info->build_date = __DATE__;
+ info->build_time = __TIME__;
+#endif
+ info->title = "MPEG Surround Decoder";
+ info->version = LIB_VERSION(SACDEC_VL0, SACDEC_VL1, SACDEC_VL2);
+ LIB_VERSION_STRING(info);
+ info->flags = 0 | CAPF_MPS_LD | CAPF_MPS_USAC | CAPF_MPS_HQ |
+ CAPF_MPS_1CH_IN | CAPF_MPS_2CH_OUT; /* end flags */
+
+ return 0;
+}
+
+SACDEC_ERROR mpegSurroundDecoder_SetParam(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param,
+ const INT value) {
+ SACDEC_ERROR err = MPS_OK;
+ SPATIALDEC_PARAM *pUserParams = NULL;
+
+ /* check decoder handle */
+ if (pMpegSurroundDecoder != NULL) {
+ /* init local shortcuts */
+ pUserParams = &pMpegSurroundDecoder->mpegSurroundUserParams;
+ } else {
+ err = MPS_INVALID_HANDLE;
+ /* check the parameter values before exiting. */
+ }
+
+ /* apply param value */
+ switch (param) {
+ case SACDEC_OUTPUT_MODE:
+ switch ((SAC_DEC_OUTPUT_MODE)value) {
+ case SACDEC_OUT_MODE_NORMAL:
+ case SACDEC_OUT_MODE_STEREO:
+ break;
+ default:
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err == MPS_OK) {
+ if (0) {
+ err = MPS_INVALID_PARAMETER;
+ } else if (pUserParams->outputMode != (UCHAR)value) {
+ pUserParams->outputMode = (UCHAR)value;
+ pMpegSurroundDecoder
+ ->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_OUTPUT_MODE;
+ }
+ }
+ break;
+
+ case SACDEC_INTERFACE:
+ if (value < 0 || value > 1) {
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface != (UCHAR)value) {
+ pMpegSurroundDecoder->mpegSurroundUseTimeInterface = (UCHAR)value;
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE;
+ }
+ break;
+
+ case SACDEC_BS_INTERRUPTION:
+ if ((err == MPS_OK) && (value != 0)) {
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_BS_INTERRUPTION,
+ MPEGS_SYNC_LOST, MPEGS_STOP);
+ }
+ break;
+
+ case SACDEC_CLEAR_HISTORY:
+ if ((err == MPS_OK) && (value != 0)) {
+ /* Just reset the states and go on. */
+ updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
+ MPEGS_INIT_CLEAR_HISTORY,
+ MPEGS_SYNC_LOST, MPEGS_STOP);
+ }
+ break;
+
+ case SACDEC_CONCEAL_NUM_KEEP_FRAMES:
+ if (value < 0) { /* Check valid value range */
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ if (pUserParams->concealNumKeepFrames != (UINT)value) {
+ pUserParams->concealNumKeepFrames = (UINT)value;
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
+ }
+ break;
+
+ case SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH:
+ if (value < 0) { /* Check valid value range */
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ if (pUserParams->concealFadeOutSlopeLength != (UINT)value) {
+ pUserParams->concealFadeOutSlopeLength = (UINT)value;
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
+ }
+ break;
+
+ case SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH:
+ if (value < 0) { /* Check valid value range */
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ if (pUserParams->concealFadeInSlopeLength != (UINT)value) {
+ pUserParams->concealFadeInSlopeLength = (UINT)value;
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
+ }
+ break;
+
+ case SACDEC_CONCEAL_NUM_RELEASE_FRAMES:
+ if (value < 0) { /* Check valid value range */
+ err = MPS_INVALID_PARAMETER;
+ }
+ if (err != MPS_OK) {
+ goto bail;
+ }
+ if (pUserParams->concealNumReleaseFrames != (UINT)value) {
+ pUserParams->concealNumReleaseFrames = (UINT)value;
+ pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
+ MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
+ }
+ break;
+
+ default:
+ err = MPS_INVALID_PARAMETER;
+ break;
+ } /* switch(param) */
+
+bail:
+ return err;
+}
+
+SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR(
+ CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr) {
+ if (pMpegSurroundDecoder != NULL) {
+ const SPATIAL_SPECIFIC_CONFIG *sscDecode =
+ &pMpegSurroundDecoder
+ ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
+ *bsPseudoLr = (int)sscDecode->bsPseudoLr;
+ return MPS_OK;
+ } else
+ return MPS_INVALID_HANDLE;
+}
+
+/**
+ * \brief Get the signal delay caused by the MPEG Surround decoder module.
+ **/
+UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self) {
+ INT outputDelay = 0;
+
+ if (self != NULL) {
+ const SPATIAL_SPECIFIC_CONFIG *sscDecode =
+ &self->spatialSpecificConfig[self->bsFrameDecode];
+ AUDIO_OBJECT_TYPE coreCodec = sscDecode->coreCodec;
+
+ /* See chapter 4.5 (delay and synchronization) of ISO/IEC FDIS 23003-1 and
+ chapter 5.4.3 of ISO/IEC FDIS 23003-2 for details on the following
+ figures. */
+
+ if (coreCodec > AOT_NULL_OBJECT) {
+ if (IS_LOWDELAY(coreCodec)) {
+ /* All low delay variants (ER-AAC-(E)LD): */
+ outputDelay += 256;
+ } else if (!IS_USAC(coreCodec)) {
+ /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...)
+ * branch: */
+ outputDelay += 320 + 257; /* cos to exp delay + QMF synthesis */
+ if (self->mpegSurroundUseTimeInterface) {
+ outputDelay += 320 + 384; /* QMF and hybrid analysis */
+ }
+ }
+ }
+ }
+
+ return (outputDelay);
+}
diff --git a/libSACdec/src/sac_dec_ssc_struct.h b/libSACdec/src/sac_dec_ssc_struct.h
new file mode 100644
index 0000000..b67b465
--- /dev/null
+++ b/libSACdec/src/sac_dec_ssc_struct.h
@@ -0,0 +1,283 @@
+/* -----------------------------------------------------------------------------
+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: interface - spatial specific config struct
+
+*******************************************************************************/
+
+#ifndef SAC_DEC_SSC_STRUCT_H
+#define SAC_DEC_SSC_STRUCT_H
+
+#include "FDK_audio.h"
+
+#define MAX_NUM_QMF_BANDS (128)
+#define MAX_TIME_SLOTS 64
+#define MAX_INPUT_CHANNELS 1
+#define MAX_OUTPUT_CHANNELS \
+ 2 /* CAUTION: This does NOT restrict the number of \
+ output channels exclusively! In addition it \
+ affects the max number of bitstream and residual channels! */
+#define MAX_NUM_OTT (5)
+#define MAX_NUM_TTT (0)
+#define MAX_NUM_EXT_TYPES (8)
+#define MAX_PARAMETER_BANDS (28)
+#define MAX_PARAMETER_BANDS_LD (23)
+
+#define MAX_NUM_XCHANNELS (6)
+
+#define MAX_ARBITRARY_TREE_LEVELS (0)
+
+typedef enum {
+ /* CAUTION: Do not change enum values! */
+ SPATIALDEC_FREQ_RES_40 = 40,
+ SPATIALDEC_FREQ_RES_28 = 28,
+ SPATIALDEC_FREQ_RES_23 = 23,
+ SPATIALDEC_FREQ_RES_20 = 20,
+ SPATIALDEC_FREQ_RES_15 = 15,
+ SPATIALDEC_FREQ_RES_14 = 14,
+ SPATIALDEC_FREQ_RES_12 = 12,
+ SPATIALDEC_FREQ_RES_10 = 10,
+ SPATIALDEC_FREQ_RES_9 = 9,
+ SPATIALDEC_FREQ_RES_7 = 7,
+ SPATIALDEC_FREQ_RES_5 = 5,
+ SPATIALDEC_FREQ_RES_4 = 4
+
+} SPATIALDEC_FREQ_RES;
+
+typedef enum {
+
+ SPATIALDEC_QUANT_FINE_DEF = 0,
+ SPATIALDEC_QUANT_EDQ1 = 1,
+ SPATIALDEC_QUANT_EDQ2 = 2,
+ SPATIALDEC_QUANT_RSVD3 = 3,
+ SPATIALDEC_QUANT_RSVD4 = 4,
+ SPATIALDEC_QUANT_RSVD5 = 5,
+ SPATIALDEC_QUANT_RSVD6 = 6,
+ SPATIALDEC_QUANT_RSVD7 = 7
+
+} SPATIALDEC_QUANT_MODE;
+
+typedef enum { SPATIALDEC_MODE_RSVD7 = 7 } SPATIALDEC_TREE_CONFIG;
+
+typedef enum {
+
+ SPATIALDEC_GAIN_MODE0 = 0,
+ SPATIALDEC_GAIN_RSVD1 = 1,
+ SPATIALDEC_GAIN_RSVD2 = 2,
+ SPATIALDEC_GAIN_RSVD3 = 3,
+ SPATIALDEC_GAIN_RSVD4 = 4,
+ SPATIALDEC_GAIN_RSVD5 = 5,
+ SPATIALDEC_GAIN_RSVD6 = 6,
+ SPATIALDEC_GAIN_RSVD7 = 7,
+ SPATIALDEC_GAIN_RSVD8 = 8,
+ SPATIALDEC_GAIN_RSVD9 = 9,
+ SPATIALDEC_GAIN_RSVD10 = 10,
+ SPATIALDEC_GAIN_RSVD11 = 11,
+ SPATIALDEC_GAIN_RSVD12 = 12,
+ SPATIALDEC_GAIN_RSVD13 = 13,
+ SPATIALDEC_GAIN_RSVD14 = 14,
+ SPATIALDEC_GAIN_RSVD15 = 15
+
+} SPATIALDEC_FIXED_GAINS;
+
+typedef enum {
+
+ SPATIALDEC_TS_TPNOWHITE = 0,
+ SPATIALDEC_TS_TPWHITE = 1,
+ SPATIALDEC_TS_TES = 2,
+ SPATIALDEC_TS_NOTS = 3,
+ SPATIALDEC_TS_RSVD4 = 4,
+ SPATIALDEC_TS_RSVD5 = 5,
+ SPATIALDEC_TS_RSVD6 = 6,
+ SPATIALDEC_TS_RSVD7 = 7,
+ SPATIALDEC_TS_RSVD8 = 8,
+ SPATIALDEC_TS_RSVD9 = 9,
+ SPATIALDEC_TS_RSVD10 = 10,
+ SPATIALDEC_TS_RSVD11 = 11,
+ SPATIALDEC_TS_RSVD12 = 12,
+ SPATIALDEC_TS_RSVD13 = 13,
+ SPATIALDEC_TS_RSVD14 = 14,
+ SPATIALDEC_TS_RSVD15 = 15
+
+} SPATIALDEC_TS_CONF;
+
+typedef enum {
+
+ SPATIALDEC_DECORR_MODE0 = 0,
+ SPATIALDEC_DECORR_MODE1 = 1,
+ SPATIALDEC_DECORR_MODE2 = 2,
+ SPATIALDEC_DECORR_RSVD3 = 3,
+ SPATIALDEC_DECORR_RSVD4 = 4,
+ SPATIALDEC_DECORR_RSVD5 = 5,
+ SPATIALDEC_DECORR_RSVD6 = 6,
+ SPATIALDEC_DECORR_RSVD7 = 7,
+ SPATIALDEC_DECORR_RSVD8 = 8,
+ SPATIALDEC_DECORR_RSVD9 = 9,
+ SPATIALDEC_DECORR_RSVD10 = 10,
+ SPATIALDEC_DECORR_RSVD11 = 11,
+ SPATIALDEC_DECORR_RSVD12 = 12,
+ SPATIALDEC_DECORR_RSVD13 = 13,
+ SPATIALDEC_DECORR_RSVD14 = 14,
+ SPATIALDEC_DECORR_RSVD15 = 15
+
+} SPATIALDEC_DECORR_CONF;
+
+typedef struct T_SPATIALDEC_OTT_CONF {
+ int nOttBands;
+
+} SPATIALDEC_OTT_CONF;
+
+typedef struct T_SPATIALDEC_RESIDUAL_CONF {
+ int bResidualPresent;
+ int nResidualBands;
+
+} SPATIALDEC_RESIDUAL_CONF;
+
+typedef struct T_SPATIAL_SPECIFIC_CONFIG {
+ UINT syntaxFlags;
+ int samplingFreq;
+ int nTimeSlots;
+ SPATIALDEC_FREQ_RES freqRes;
+ SPATIALDEC_TREE_CONFIG treeConfig;
+ SPATIALDEC_QUANT_MODE quantMode;
+ int bArbitraryDownmix;
+
+ int bResidualCoding;
+ SPATIALDEC_FIXED_GAINS bsFixedGainDMX;
+
+ SPATIALDEC_TS_CONF tempShapeConfig;
+ SPATIALDEC_DECORR_CONF decorrConfig;
+
+ int nInputChannels; /* derived from treeConfig */
+ int nOutputChannels; /* derived from treeConfig */
+
+ /* ott config */
+ int nOttBoxes; /* derived from treeConfig */
+ SPATIALDEC_OTT_CONF OttConfig[MAX_NUM_OTT]; /* dimension nOttBoxes */
+
+ /* ttt config */
+ int nTttBoxes; /* derived from treeConfig */
+
+ /* residual config */
+ SPATIALDEC_RESIDUAL_CONF
+ ResidualConfig[MAX_NUM_OTT +
+ MAX_NUM_TTT]; /* dimension (nOttBoxes + nTttBoxes) */
+
+ int sacExtCnt;
+ int sacExtType[MAX_NUM_EXT_TYPES];
+ int envQuantMode;
+
+ AUDIO_OBJECT_TYPE coreCodec;
+
+ UCHAR stereoConfigIndex;
+ UCHAR coreSbrFrameLengthIndex; /* Table 70 in ISO/IEC FDIS 23003-3:2011 */
+ UCHAR bsHighRateMode;
+ UCHAR bsDecorrType;
+ UCHAR bsPseudoLr;
+ UCHAR bsPhaseCoding;
+ UCHAR bsOttBandsPhasePresent;
+ int bsOttBandsPhase;
+
+ SCHAR ottCLDdefault[MAX_NUM_OTT];
+ UCHAR numOttBandsIPD;
+ UCHAR bitstreamOttBands[MAX_NUM_OTT];
+ UCHAR numOttBands[MAX_NUM_OTT];
+
+} SPATIAL_SPECIFIC_CONFIG;
+
+#endif
diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp
new file mode 100644
index 0000000..56c72ad
--- /dev/null
+++ b/libSACdec/src/sac_process.cpp
@@ -0,0 +1,1066 @@
+/* -----------------------------------------------------------------------------
+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 Processing
+
+*******************************************************************************/
+
+/* data structures and interfaces for spatial audio reference software */
+#include "sac_process.h"
+
+#include "sac_bitdec.h"
+#include "sac_calcM1andM2.h"
+#include "sac_smoothing.h"
+#include "sac_rom.h"
+
+#include "sac_dec_errorcodes.h"
+
+#include "FDK_trigFcts.h"
+#include "FDK_decorrelate.h"
+
+/**
+ * \brief Linear interpolation between two parameter values.
+ * a*alpha + b*(1-alpha)
+ * = a*alpha + b - b*alpha
+ *
+ * \param alpha Weighting factor.
+ * \param a Parameter a.
+ * \param b Parameter b.
+ *
+ * \return Interpolated parameter value.
+ */
+FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a,
+ const FIXP_DBL b) {
+ return (b - fMult(alpha, b) + fMult(alpha, a));
+}
+
+/**
+ * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices.
+ * \param self Spatial decoder handle.
+ * \param ch MPEG Surround channel index.
+ * \return MPEG 4 PCE style channel index, corresponding to the given MPEG
+ * Surround channel index.
+ */
+static UINT mapChannel(spatialDec *self, UINT ch) {
+ static const UCHAR chanelIdx[][8] = {
+ {0, 1, 2, 3, 4, 5, 6, 7}, /* binaural, TREE_212, arbitrary tree */
+ };
+
+ int idx = 0;
+
+ return (chanelIdx[idx][ch]);
+}
+
+FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) {
+ /* init no gain modifier */
+ FIXP_DBL gain = 0x80000000;
+ *scale = 0;
+
+ if ((!isTwoChMode(self->upmixType)) &&
+ (self->upmixType != UPMIXTYPE_BYPASS)) {
+ if ((ch == 0) || (ch == 1) || (ch == 2)) {
+ /* no modifier */
+ }
+ }
+
+ return gain;
+}
+
+SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
+ const INT ts, const INT bypassMode,
+ FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
+ const int numInputChannels) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch, offset;
+
+ offset = self->pQmfDomain->globalConf.nBandsSynthesis *
+ self->pQmfDomain->globalConf.nQmfTimeSlots;
+
+ {
+ for (ch = 0; ch < numInputChannels; ch++) {
+ const PCM_MPS *inSamples =
+ &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
+ FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */
+ FIXP_DBL *pQmfImagAnalysis = qmfImag[ch];
+
+ CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb,
+ inSamples + (ch * offset), pQmfRealAnalysis,
+ pQmfImagAnalysis);
+
+ if (!isTwoChMode(self->upmixType) && !bypassMode) {
+ int i;
+ for (i = 0; i < self->qmfBands; i++) {
+ qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK);
+ qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK);
+ }
+ }
+ }
+ }
+
+ self->qmfInputDelayBufPos =
+ (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
+ FIXP_DBL **qmfInDataImag, const INT ts,
+ const INT bypassMode, FIXP_DBL **qmfReal__FDK,
+ FIXP_DBL **qmfImag__FDK,
+ const INT numInputChannels) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+
+ {
+ for (ch = 0; ch < numInputChannels; ch++) {
+ FIXP_DBL *pQmfRealAnalysis =
+ qmfReal__FDK[ch]; /* no delay in blind mode */
+ FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch];
+
+ /* Write Input data to pQmfRealAnalysis. */
+ if (self->bShareDelayWithSBR) {
+ FDK_QmfDomain_GetSlot(
+ &self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0,
+ MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15);
+ FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
+ MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
+ pQmfRealAnalysis, pQmfImagAnalysis, 15);
+ } else {
+ FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
+ self->qmfBands, pQmfRealAnalysis,
+ pQmfImagAnalysis, 15);
+ }
+ if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
+ /* Is currently also needed in case we dont have any overlap. We need to
+ * save lb_scale to ov_lb_scale */
+ FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0);
+ }
+
+ /* Apply clip protection to output. */
+ if (!isTwoChMode(self->upmixType) && !bypassMode) {
+ int i;
+ for (i = 0; i < self->qmfBands; i++) {
+ qmfReal__FDK[ch][i] =
+ fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK);
+ qmfImag__FDK[ch][i] =
+ fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK);
+ }
+ }
+
+ } /* End of loop over numInputChannels */
+ }
+
+ self->qmfInputDelayBufPos =
+ (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: SpatialDecHybridAnalysis
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+ float** pointers[4] leftReal, leftIm, rightReal, rightIm
+
+ Output:
+ float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
+ float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
+
+ float
+self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float
+self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS];
+
+
+*******************************************************************************/
+SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal,
+ FIXP_DBL **qmfInputImag,
+ FIXP_DBL **hybOutputReal,
+ FIXP_DBL **hybOutputImag, const INT ts,
+ const INT numInputChannels) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+
+ for (ch = 0; ch < numInputChannels;
+ ch++) /* hybrid filtering for down-mix signals */
+ {
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
+ int k;
+ /* No hybrid filtering. Just copy the QMF data. */
+ for (k = 0; k < self->hybridBands; k += 1) {
+ hybOutputReal[ch][k] = qmfInputReal[ch][k];
+ hybOutputImag[ch][k] = qmfInputImag[ch][k];
+ }
+ } else {
+ self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR;
+
+ if (self->stereoConfigIndex == 3)
+ FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0);
+ FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch],
+ qmfInputImag[ch], hybOutputReal[ch],
+ hybOutputImag[ch]);
+ }
+ }
+
+ if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
+ self->residualCoding) {
+ self->hybridAnalysis[numInputChannels].hfMode = 0;
+ FDKhybridAnalysisApply(
+ &self->hybridAnalysis[numInputChannels],
+ self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0],
+ self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]);
+ }
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
+ FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
+ FIXP_DBL **pxImag) {
+ SACDEC_ERROR err = MPS_OK;
+ int row;
+
+ /* Creating wDry */
+ for (row = 0; row < self->numInputChannels; row++) {
+ /* pointer to direct signals */
+ pxReal[row] = hybInputReal[row];
+ pxImag[row] = hybInputImag[row];
+ }
+
+ return err;
+}
+
+static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel,
+ FIXP_DBL *RESTRICT Mparam,
+ FIXP_DBL *RESTRICT MparamPrev,
+ int *RESTRICT pWidth, FIXP_SGL alpha__FDK,
+ int nBands) {
+ int pb;
+
+ for (pb = 0; pb < nBands; pb++) {
+ FIXP_SGL tmp = FX_DBL2FX_SGL(
+ interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb]));
+
+ int i = pWidth[pb];
+ if (i & 1) *pKernel++ = tmp;
+ if (i & 2) {
+ *pKernel++ = tmp;
+ *pKernel++ = tmp;
+ }
+ for (i >>= 2; i--;) {
+ *pKernel++ = tmp;
+ *pKernel++ = tmp;
+ *pKernel++ = tmp;
+ *pKernel++ = tmp;
+ }
+ }
+}
+
+SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
+ spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
+ FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) {
+ SACDEC_ERROR err = MPS_OK;
+ int res;
+ FIXP_DBL *decorrInReal = vReal[0];
+ FIXP_DBL *decorrInImag = vImag[0];
+
+ /* M1 does not do anything in 212 mode, so use simplified processing */
+ FDK_ASSERT(self->numVChannels == 2);
+ FDK_ASSERT(self->numDirektSignals == 1);
+ FDK_ASSERT(self->numDecorSignals == 1);
+ FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL));
+ FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL));
+
+ if (isTsdActive(frame->TsdData)) {
+ /* Generate v_{x,nonTr} as input for allpass based decorrelator */
+ TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0],
+ vImag[0], vReal[1], vImag[1], &decorrInReal,
+ &decorrInImag);
+ }
+ /* - Decorrelate */
+ res = SpatialDecGetResidualIndex(self, 1);
+ if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag,
+ vReal[1], vImag[1],
+ self->param2hyb[self->residualBands[res]])) {
+ return MPS_NOTOK;
+ }
+ if (isTsdActive(frame->TsdData)) {
+ /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based
+ * decorrelator output */
+ TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs,
+ vReal[0], /* input: v_x */
+ vImag[0],
+ vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */
+ vImag[1]);
+ }
+
+ /* Write residual signal in approriate parameter bands */
+ if (self->residualBands[res] > 0) {
+ int stopBand = self->param2hyb[self->residualBands[res]];
+ FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res],
+ fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
+ FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res],
+ fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
+ } /* (self->residualBands[res]>0) */
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps,
+ const FIXP_SGL alpha, FIXP_DBL **wReal,
+ FIXP_DBL **wImag,
+ FIXP_DBL **hybOutputRealDry,
+ FIXP_DBL **hybOutputImagDry) {
+ SACDEC_ERROR err = MPS_OK;
+ INT row;
+
+ INT *pWidth = self->kernels_width;
+ /* for stereoConfigIndex == 3 case hybridBands is < 71 */
+ INT pb_max = self->kernels[self->hybridBands - 1] + 1;
+ INT max_row = self->numOutputChannels;
+
+ INT M2_exp = 0;
+ if (self->residualCoding) M2_exp = 3;
+
+ for (row = 0; row < max_row; row++) // 2 times
+ {
+ FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0];
+ FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1];
+ FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0];
+ FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1];
+
+ FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
+ FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
+
+ FIXP_DBL *RESTRICT pWReal0 = wReal[0];
+ FIXP_DBL *RESTRICT pWReal1 = wReal[1];
+ FIXP_DBL *RESTRICT pWImag0 = wImag[0];
+ FIXP_DBL *RESTRICT pWImag1 = wImag[1];
+ for (INT pb = 0; pb < pb_max; pb++) {
+ FIXP_DBL tmp0, tmp1;
+
+ tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]);
+ tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]);
+
+ INT i = pWidth[pb];
+
+ do // about 3-4 times
+ {
+ FIXP_DBL var0, var1, real, imag;
+
+ var0 = *pWReal0++;
+ var1 = *pWReal1++;
+ real = fMultDiv2(var0, tmp0);
+ var0 = *pWImag0++;
+ real = fMultAddDiv2(real, var1, tmp1);
+ var1 = *pWImag1++;
+ imag = fMultDiv2(var0, tmp0);
+ *pHybOutRealDry++ = real << (1 + M2_exp);
+ imag = fMultAddDiv2(imag, var1, tmp1);
+ *pHybOutImagDry++ = imag << (1 + M2_exp);
+ } while (--i != 0);
+ }
+ }
+ return err;
+}
+
+SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
+ spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal,
+ FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry,
+ FIXP_DBL **hybOutputImagDry) {
+ SACDEC_ERROR err = MPS_OK;
+ INT row;
+ INT scale_param_m2;
+ INT *pWidth = self->kernels_width;
+ INT pb_max = self->kernels[self->hybridBands - 1] + 1;
+
+ scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
+
+ for (row = 0; row < self->numM2rows; row++) {
+ INT qs, pb;
+
+ FIXP_DBL *RESTRICT pWReal0 = wReal[0];
+ FIXP_DBL *RESTRICT pWImag0 = wImag[0];
+ FIXP_DBL *RESTRICT pWReal1 = wReal[1];
+ FIXP_DBL *RESTRICT pWImag1 = wImag[1];
+
+ FIXP_DBL *MReal0 = self->M2Real__FDK[row][0];
+ FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0];
+ FIXP_DBL *MReal1 = self->M2Real__FDK[row][1];
+ FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0];
+ FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0];
+ FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1];
+
+ FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
+ FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
+
+ FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD));
+ FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3);
+
+ for (pb = 0, qs = 3; pb < 2; pb++) {
+ INT s;
+ FIXP_DBL maxVal;
+ FIXP_SGL mReal1;
+ FIXP_SGL mReal0, mImag0;
+ FIXP_DBL iReal0, iImag0, iReal1;
+
+ iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
+ iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
+ iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
+
+ maxVal = fAbs(iReal0) | fAbs(iImag0);
+ maxVal |= fAbs(iReal1);
+
+ s = fMax(CntLeadingZeros(maxVal) - 1, 0);
+ s = fMin(s, scale_param_m2);
+
+ mReal0 = FX_DBL2FX_SGL(iReal0 << s);
+ mImag0 = FX_DBL2FX_SGL(iImag0 << s);
+ mReal1 = FX_DBL2FX_SGL(iReal1 << s);
+
+ s = scale_param_m2 - s;
+
+ INT i = pWidth[pb];
+
+ do {
+ FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
+
+ wReal0 = *pWReal0++;
+ wImag0 = *pWImag0++;
+ wReal1 = *pWReal1++;
+ wImag1 = *pWImag1++;
+
+ cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
+
+ *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
+ *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
+
+ if (qs > 0) {
+ mImag0 = -mImag0;
+ qs--;
+ }
+ } while (--i != 0);
+ }
+
+ for (; pb < pb_max; pb++) {
+ INT s;
+ FIXP_DBL maxVal;
+ FIXP_SGL mReal1;
+ FIXP_SGL mReal0, mImag0;
+ FIXP_DBL iReal0, iImag0, iReal1;
+
+ iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
+ iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
+ iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
+
+ maxVal = fAbs(iReal0) | fAbs(iImag0);
+ maxVal |= fAbs(iReal1);
+
+ s = fMax(CntLeadingZeros(maxVal) - 1, 0);
+ s = fMin(s, scale_param_m2);
+
+ mReal0 = FX_DBL2FX_SGL(iReal0 << s);
+ mImag0 = FX_DBL2FX_SGL(iImag0 << s);
+ mReal1 = FX_DBL2FX_SGL(iReal1 << s);
+
+ s = scale_param_m2 - s;
+
+ INT i = pWidth[pb];
+
+ do {
+ FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
+
+ wReal0 = *pWReal0++;
+ wImag0 = *pWImag0++;
+ wReal1 = *pWReal1++;
+ wImag1 = *pWImag1++;
+
+ cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
+
+ *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
+ *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
+ } while (--i != 0);
+ }
+ }
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
+ FIXP_DBL **wReal, FIXP_DBL **wImag,
+ FIXP_DBL **hybOutputRealDry,
+ FIXP_DBL **hybOutputImagDry,
+ FIXP_DBL **hybOutputRealWet,
+ FIXP_DBL **hybOutputImagWet) {
+ SACDEC_ERROR err = MPS_OK;
+
+ {
+ int qs, row, col;
+ int complexHybBands;
+ int complexParBands;
+ int scale_param_m2 = 0;
+ int toolsDisabled;
+
+ UCHAR activParamBands;
+ FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
+ *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
+ *RESTRICT pHybOutImagWet;
+ C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
+
+ /* The wet signal is added to the dry signal directly in applyM2 if GES and
+ * STP are disabled */
+ toolsDisabled =
+ ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
+
+ {
+ complexHybBands = self->hybridBands;
+ complexParBands = self->numParameterBands;
+ }
+
+ FDKmemclear(hybOutputImagDry[0],
+ self->createParams.maxNumOutputChannels *
+ self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
+ FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
+ self->createParams.maxNumHybridBands *
+ sizeof(FIXP_DBL));
+
+ if (!toolsDisabled) {
+ FDKmemclear(hybOutputRealWet[0],
+ self->createParams.maxNumOutputChannels *
+ self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
+ FDKmemclear(hybOutputImagWet[0],
+ self->createParams.maxNumOutputChannels *
+ self->createParams.maxNumCmplxHybBands *
+ sizeof(FIXP_DBL));
+ }
+
+ if (self->phaseCoding == 3) {
+ /* + SCALE_DATA_APPLY_M2 to compensate for Div2 below ?! */
+ scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
+ }
+
+ for (row = 0; row < self->numM2rows; row++) {
+ pHybOutRealDry = hybOutputRealDry[row];
+ pHybOutImagDry = hybOutputImagDry[row];
+
+ if (toolsDisabled) {
+ pHybOutRealWet = hybOutputRealDry[row];
+ pHybOutImagWet = hybOutputImagDry[row];
+ } else {
+ pHybOutRealWet = hybOutputRealWet[row];
+ pHybOutImagWet = hybOutputImagWet[row];
+ }
+
+ for (col = 0; col < self->numDirektSignals; col++) {
+ if (self->pActivM2ParamBands ==
+ 0) { /* default setting, calculate all rows and columns */
+ activParamBands = 1;
+ } else {
+ if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
+ col]) /* table with activ and inactiv
+ bands exists for current
+ configuration */
+ activParamBands = 1;
+ else
+ activParamBands = 0;
+ }
+ if (activParamBands) {
+ pWReal = wReal[col];
+ pWImag = wImag[col];
+
+ M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
+ self->M2RealPrev__FDK[row][col],
+ self->kernels_width, alpha,
+ self->numParameterBands);
+
+ if (1 && (self->phaseCoding != 3)) {
+ /* direct signals */
+ {
+ /* only one sample will be assigned to each row, hence
+ * accumulation is not neccessary; that is valid for all
+ * configurations */
+ for (qs = 0; qs < complexHybBands; qs++) {
+ pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
+ pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
+ }
+ }
+ } else { /* isBinauralMode(self->upmixType) */
+
+ for (qs = 0; qs < complexHybBands; qs++) {
+ pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+
+ M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
+ self->M2ImagPrev__FDK[row][col],
+ self->kernels_width, alpha, complexParBands);
+
+ /* direct signals sign is -1 for qs = 0,2 */
+ pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0])
+ << (scale_param_m2);
+ pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0])
+ << (scale_param_m2);
+
+ pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2])
+ << (scale_param_m2);
+ pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2])
+ << (scale_param_m2);
+
+ /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
+ pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1])
+ << (scale_param_m2);
+ pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1])
+ << (scale_param_m2);
+
+ for (qs = 3; qs < complexHybBands; qs++) {
+ pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+ } /* self->upmixType */
+ } /* if (activParamBands) */
+ } /* self->numDirektSignals */
+
+ for (; col < self->numVChannels; col++) {
+ if (self->pActivM2ParamBands ==
+ 0) { /* default setting, calculate all rows and columns */
+ activParamBands = 1;
+ } else {
+ if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
+ col]) /* table with activ and inactiv
+ bands exists for current
+ configuration */
+ activParamBands = 1;
+ else
+ activParamBands = 0;
+ }
+
+ if (activParamBands) {
+ int resBandIndex;
+ int resHybIndex;
+
+ resBandIndex =
+ self->residualBands[SpatialDecGetResidualIndex(self, col)];
+ resHybIndex = self->param2hyb[resBandIndex];
+
+ pWReal = wReal[col];
+ pWImag = wImag[col];
+
+ M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
+ self->M2RealPrev__FDK[row][col],
+ self->kernels_width, alpha,
+ self->numParameterBands);
+
+ if (1 && (self->phaseCoding != 3)) {
+ /* residual signals */
+ for (qs = 0; qs < resHybIndex; qs++) {
+ pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
+ pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
+ }
+ /* decor signals */
+ for (; qs < complexHybBands; qs++) {
+ pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
+ pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
+ }
+ } else { /* self->upmixType */
+ /* residual signals */
+ FIXP_DBL *RESTRICT pHybOutReal;
+ FIXP_DBL *RESTRICT pHybOutImag;
+
+ for (qs = 0; qs < resHybIndex; qs++) {
+ pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+ /* decor signals */
+ for (; qs < complexHybBands; qs++) {
+ pHybOutRealWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagWet[qs] += fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+
+ M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
+ self->M2ImagPrev__FDK[row][col],
+ self->kernels_width, alpha, complexParBands);
+
+ /* direct signals sign is -1 for qs = 0,2 */
+ /* direct signals sign is +1 for qs = 1,3.. */
+ if (toolsDisabled) {
+ pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0])
+ << (scale_param_m2);
+ pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0])
+ << (scale_param_m2);
+
+ pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1])
+ << (scale_param_m2);
+ pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1])
+ << (scale_param_m2);
+
+ pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2])
+ << (scale_param_m2);
+ pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2])
+ << (scale_param_m2);
+ } else {
+ pHybOutReal = &pHybOutRealDry[0];
+ pHybOutImag = &pHybOutImagDry[0];
+ if (0 == resHybIndex) {
+ pHybOutReal = &pHybOutRealWet[0];
+ pHybOutImag = &pHybOutImagWet[0];
+ }
+ pHybOutReal[0] += fMultDiv2(pWImag[0], pKernel[0])
+ << (scale_param_m2);
+ pHybOutImag[0] -= fMultDiv2(pWReal[0], pKernel[0])
+ << (scale_param_m2);
+
+ if (1 == resHybIndex) {
+ pHybOutReal = &pHybOutRealWet[0];
+ pHybOutImag = &pHybOutImagWet[0];
+ }
+ pHybOutReal[1] -= fMultDiv2(pWImag[1], pKernel[1])
+ << (scale_param_m2);
+ pHybOutImag[1] += fMultDiv2(pWReal[1], pKernel[1])
+ << (scale_param_m2);
+
+ if (2 == resHybIndex) {
+ pHybOutReal = &pHybOutRealWet[0];
+ pHybOutImag = &pHybOutImagWet[0];
+ }
+ pHybOutReal[2] += fMultDiv2(pWImag[2], pKernel[2])
+ << (scale_param_m2);
+ pHybOutImag[2] -= fMultDiv2(pWReal[2], pKernel[2])
+ << (scale_param_m2);
+ }
+
+ for (qs = 3; qs < resHybIndex; qs++) {
+ pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+ /* decor signals */
+ for (; qs < complexHybBands; qs++) {
+ pHybOutRealWet[qs] -= fMultDiv2(pWImag[qs], pKernel[qs])
+ << (scale_param_m2);
+ pHybOutImagWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs])
+ << (scale_param_m2);
+ }
+ } /* self->upmixType */
+ } /* if (activParamBands) { */
+ } /* self->numVChannels */
+ }
+
+ C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
+ }
+
+ return err;
+}
+
+SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
+ FIXP_DBL **hybOutputReal,
+ FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
+ const INT numInputChannels,
+ const FDK_channelMapDescr *const mapDescr) {
+ SACDEC_ERROR err = MPS_OK;
+
+ int ch;
+ int stride, offset;
+
+ stride = self->numOutputChannelsAT;
+ offset = 1;
+
+ PCM_MPS *pTimeOut__FDK =
+ &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
+ C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
+ C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
+
+ for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
+ if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
+ int k;
+ /* No hybrid filtering. Just copy the QMF data. */
+ for (k = 0; k < self->hybridBands; k += 1) {
+ pQmfReal[k] = hybOutputReal[ch][k];
+ pQmfImag[k] = hybOutputImag[ch][k];
+ }
+ } else {
+ FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
+ hybOutputImag[ch], pQmfReal, pQmfImag);
+ }
+
+ /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
+ */
+ FDK_ASSERT(self->numOutputChannelsAT <= 6);
+ int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
+ self->numOutputChannelsAT);
+
+ {
+ if (self->stereoConfigIndex == 3) {
+ /* MPS -> SBR */
+ int i;
+ FIXP_DBL *pWorkBufReal, *pWorkBufImag;
+ FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
+ (FIXP_DBL)0x80000000) &&
+ (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
+ FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
+ &pWorkBufReal, &pWorkBufImag);
+ FDK_ASSERT(self->qmfBands <=
+ self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
+ for (i = 0; i < self->qmfBands; i++) {
+ pWorkBufReal[i] = pQmfReal[i];
+ pWorkBufImag[i] = pQmfImag[i];
+ }
+ self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
+ -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
+ self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
+ self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
+ self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
+ self->clipProtectGainSF__FDK;
+
+ } else {
+ /* Call the QMF synthesis for dry. */
+ err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
+ pQmfReal, pQmfImag, stride,
+ pTimeOut__FDK + (offset * outCh));
+ }
+ if (err != MPS_OK) goto bail;
+ }
+ } /* ch loop */
+
+bail:
+ C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
+ C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
+
+ return err;
+}
+
+void SpatialDecBufferMatrices(spatialDec *self) {
+ int row, col;
+ int complexParBands;
+ complexParBands = self->numParameterBands;
+
+ /*
+ buffer matrices M2
+ */
+ for (row = 0; row < self->numM2rows; row++) {
+ for (col = 0; col < self->numVChannels; col++) {
+ FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
+ self->numParameterBands * sizeof(FIXP_DBL));
+ if (0 || (self->phaseCoding == 3)) {
+ FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
+ complexParBands * sizeof(FIXP_DBL));
+ }
+ }
+ }
+
+ /* buffer phase */
+ FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
+ self->numParameterBands * sizeof(FIXP_DBL));
+ FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
+ self->numParameterBands * sizeof(FIXP_DBL));
+}
+
+#define PHASE_SCALE 2
+
+#ifndef P_PI
+#define P_PI 3.1415926535897932
+#endif
+
+/* For better precision, PI (pi_x2) is already doubled */
+static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2,
+ FIXP_SGL alpha, FIXP_DBL pi_x2) {
+ if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
+
+ if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
+
+ return interpolateParameter(alpha, angle2, angle1);
+}
+
+/*
+ *
+ */
+void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
+ int lastSlotOfParamSet) {
+ int pb, qs;
+ FIXP_DBL ppb[MAX_PARAMETER_BANDS *
+ 4]; /* left real, imag - right real, imag interleaved */
+
+ const FIXP_DBL pi_x2 = PIx2__IPD;
+ for (pb = 0; pb < self->numParameterBands; pb++) {
+ FIXP_DBL pl, pr;
+
+ pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
+ self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
+ pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
+ self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
+
+ inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
+ }
+
+ /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
+
+ const SCHAR *kernels = &self->kernels[0];
+
+ FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
+ FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
+ FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
+ FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
+
+ for (qs = 2; qs >= 0; qs--) {
+ FIXP_DBL out_re, out_im;
+
+ pb = *kernels++;
+ if (qs == 1) /* sign[qs] >= 0 */
+ {
+ cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
+ ppb[4 * pb + 1]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real0++ = out_re;
+ *Dry_imag0++ = out_im;
+
+ cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
+ ppb[4 * pb + 3]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real1++ = out_re;
+ *Dry_imag1++ = out_im;
+ } else {
+ cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
+ -ppb[4 * pb + 1]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real0++ = out_re;
+ *Dry_imag0++ = out_im;
+
+ cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
+ -ppb[4 * pb + 3]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real1++ = out_re;
+ *Dry_imag1++ = out_im;
+ }
+ }
+
+ /* sign is +1 for qs >=3 */
+ for (qs = self->hybridBands - 3; qs--;) {
+ FIXP_DBL out_re, out_im;
+
+ pb = *kernels++;
+ cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
+ ppb[4 * pb + 1]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real0++ = out_re;
+ *Dry_imag0++ = out_im;
+
+ cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
+ ppb[4 * pb + 3]);
+ out_re <<= PHASE_SCALE - 1;
+ out_im <<= PHASE_SCALE - 1;
+ *Dry_real1++ = out_re;
+ *Dry_imag1++ = out_im;
+ }
+}
diff --git a/libSACdec/src/sac_process.h b/libSACdec/src/sac_process.h
new file mode 100644
index 0000000..ee2f2fe
--- /dev/null
+++ b/libSACdec/src/sac_process.h
@@ -0,0 +1,297 @@
+/* -----------------------------------------------------------------------------
+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 Processing
+
+*******************************************************************************/
+
+/*!
+ \file
+ \brief Polyphase Filterbank
+*/
+
+#ifndef SAC_PROCESS_H
+#define SAC_PROCESS_H
+
+#include "sac_dec.h"
+
+void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha,
+ int lastSlotOfParamSet);
+
+/**
+ * \brief Apply QMF Analysis Filterbank.
+ *
+ * Calculates qmf data on downmix input time data.
+ * Delaylines will be applied if necessaray.
+ *
+ * \param self A spatial decoder handle.
+ * \param inData Downmix channel time data as input.
+ * \param ts Signals time slot offset for input buffer.
+ * \param qmfReal Downmix channel qmf output data.
+ * \param qmfImag Downmix channel qmf output data.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
+ const INT ts, const INT bypassMode,
+ FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
+ const int numInputChannels);
+
+/**
+ * \brief Feed spatial decoder with external qmf data.
+ *
+ * \param self A spatial decoder handle.
+ * \param qmfInDataReal External qmf downmix data as input.
+ * \param qmfInDataImag External qmf downmix data as input.
+ * \param ts Signals time slot in input buffer to process.
+ * \param qmfReal Downmix channel qmf output data.
+ * \param qmfImag Downmix channel qmf output data.
+ * \param numInputChannels Number of input channels. Might differ from
+ * self->numInputChannels.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
+ FIXP_DBL **qmfInDataImag, const INT ts,
+ const INT bypassMode, FIXP_DBL **qmfReal,
+ FIXP_DBL **qmfImag, const INT numInputChannels);
+
+/**
+ * \brief Apply Hybrdid Analysis Filterbank.
+ *
+ * Calculates hybrid data on downmix input data.
+ * Residual hybrid signals will also be calculated on current slot if available.
+ *
+ * \param self A spatial decoder handle.
+ * \param qmfInputReal Downmix channel qmf data as input.
+ * \param qmfInputImag Downmix channel qmf data as input.
+ * \param hybOutputReal Downmix channel hybrid output data.
+ * \param hybOutputImag Downmix channel hybrid output data.
+ * \param ts Signals time slot in spatial frame to process.
+ * \param numInputChannels Number of input channels. Might differ from
+ * self->numInputChannels.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal,
+ FIXP_DBL **qmfInputImag,
+ FIXP_DBL **hybOutputReal,
+ FIXP_DBL **hybOutputImag, const INT ts,
+ const INT numInputChannels);
+
+/**
+ * \brief Create X data.
+ *
+ * Returns a pointer list over Xchannels pointing to downmix input channels
+ * and to residual channels when provided.
+ *
+ * \param self A spatial decoder handle.
+ * \param hybInputReal Downmix channel hybrid data as input.
+ * \param hybInputImag Downmix channel hybrid data as input.
+ * \param pxReal Pointer to hybrid and residual data as output.
+ * \param pxImag Pointer to hybrid and residual data as output.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
+ FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
+ FIXP_DBL **pxImag);
+
+/**
+ * \brief MPS212 combined version of apply M1 parameters and create wet signal
+ *
+ * \param self A spatial decoder handle.
+ * \param xReal Downmix and residual X data as input.
+ * \param xImag Downmix and residual X data as input.
+ * \param vReal output data: [0] direct signal (V); [1] wet signal
+ * (W).
+ * \param vImag output data: [0] direct signal (V); [1] wet signal
+ * (W).
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
+ spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
+ FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag);
+
+/**
+ * \brief Apply M2 parameters.
+ *
+ * \param self A spatial decoder handle.
+ * \param ps Signals parameter band from where M2 parameter to
+ * use.
+ * \param alpha Smoothing factor between current and previous
+ * parameter band. Rangeability between 0.f and 1.f.
+ * \param wReal Wet input data.
+ * \param wImag Wet input data.
+ * \param hybOutputRealDry Dry output data.
+ * \param hybOutputImagDry Dry output data.
+ * \param hybOutputRealWet Wet output data.
+ * \param hybOutputImagWet Wet output data.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
+ FIXP_DBL **wReal, FIXP_DBL **wImag,
+ FIXP_DBL **hybOutputRealDry,
+ FIXP_DBL **hybOutputImagDry,
+ FIXP_DBL **hybOutputRealWet,
+ FIXP_DBL **hybOutputImagWet);
+
+/**
+ * \brief Apply M2 parameter for 212 mode with residualCoding and phaseCoding.
+ *
+ * \param self [i] A spatial decoder handle.
+ * \param ps [i] Signals parameter band from where M2 parameter
+ * to use.
+ * \param alpha [i] Smoothing factor between current and previous
+ * parameter band. Rangeability between 0.f and 1.f.
+ * \param wReal [i] Wet input data.
+ * \param wImag [i] Wet input data.
+ * \param hybOutputRealDry [o] Dry output data.
+ * \param hybOutputImagDry [o] Dry output data.
+ *
+ * \return error
+ */
+SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
+ spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal,
+ FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, FIXP_DBL **hybOutputImagDry);
+
+/**
+ * \brief Apply M2 parameter for 212 mode, upmix from mono to stereo.
+ *
+ * \param self [i] A spatial decoder handle.
+ * \param ps [i] Signals parameter band from where M2 parameter
+ * to use.
+ * \param alpha [i] Smoothing factor between current and previous
+ * parameter band. Rangeability between 0.f and 1.f.
+ * \param wReal [i] Wet input data.
+ * \param wImag [i] Wet input data.
+ * \param hybOutputRealDry [o] Dry output data.
+ * \param hybOutputImagDry [o] Dry output data.
+ *
+ * \return error
+ */
+SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps,
+ const FIXP_SGL alpha, FIXP_DBL **wReal,
+ FIXP_DBL **wImag,
+ FIXP_DBL **hybOutputRealDry,
+ FIXP_DBL **hybOutputImagDry);
+
+/**
+ * \brief Convert Hybrid input to output audio data.
+ *
+ * \param hSpaceSynthesisQmf A spatial decoder handle.
+ * \param ts Signals time slot in spatial frame to process.
+ * \param hybOutputReal Hybrid data as input.
+ * \param hybOutputImag Hybrid data as input.
+ * \param timeOut audio output data.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
+ FIXP_DBL **hybOutputReal,
+ FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
+ const INT numInputChannels,
+ const FDK_channelMapDescr *const mapDescr);
+
+void SpatialDecBufferMatrices(spatialDec *self);
+
+FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale);
+
+#endif
diff --git a/libSACdec/src/sac_qmf.cpp b/libSACdec/src/sac_qmf.cpp
new file mode 100644
index 0000000..a075490
--- /dev/null
+++ b/libSACdec/src/sac_qmf.cpp
@@ -0,0 +1,156 @@
+/* -----------------------------------------------------------------------------
+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 QMF processing
+
+*******************************************************************************/
+
+#include "sac_qmf.h"
+
+#include "FDK_matrixCalloc.h"
+#include "sac_dec_interface.h"
+#include "sac_rom.h"
+
+#include "qmf.h"
+
+SACDEC_ERROR CalculateSpaceSynthesisQmf(
+ const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr,
+ const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if (hQmfDomainOutCh == NULL) {
+ err = MPS_INVALID_HANDLE;
+ } else {
+ HANDLE_SPACE_SYNTHESIS_QMF hSpaceSynthesisQmf = &hQmfDomainOutCh->fb;
+#if (QMF_MAX_SYNTHESIS_BANDS <= 64)
+ C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL,
+ (QMF_MAX_SYNTHESIS_BANDS << 1));
+#else
+ C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1));
+#endif
+
+ qmfSynthesisFilteringSlot(hSpaceSynthesisQmf, Sr, Si, 0, 0, timeSig, stride,
+ pWorkBuffer);
+
+#if (QMF_MAX_SYNTHESIS_BANDS <= 64)
+ C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1));
+#else
+ C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1));
+#endif
+ }
+
+ return err;
+}
+
+SACDEC_ERROR CalculateSpaceAnalysisQmf(
+ HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig,
+ FIXP_DBL *Sr, FIXP_DBL *Si) {
+ SACDEC_ERROR err = MPS_OK;
+
+ if (hSpaceAnalysisQmf == NULL) {
+ err = MPS_INVALID_HANDLE;
+ } else {
+ C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (64 << 1));
+
+ qmfAnalysisFilteringSlot(hSpaceAnalysisQmf, Sr, Si, timeSig, 1,
+ pWorkBuffer);
+ C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (64 << 1));
+ }
+
+ return err;
+}
diff --git a/libSACdec/src/sac_qmf.h b/libSACdec/src/sac_qmf.h
new file mode 100644
index 0000000..d1dc837
--- /dev/null
+++ b/libSACdec/src/sac_qmf.h
@@ -0,0 +1,143 @@
+/* -----------------------------------------------------------------------------
+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 QMF processing
+
+*******************************************************************************/
+
+#ifndef SAC_QMF_H
+#define SAC_QMF_H
+
+#include "common_fix.h"
+
+#include "sac_dec_interface.h"
+
+#include "FDK_qmf_domain.h"
+#define HANDLE_SPACE_ANALYSIS_QMF HANDLE_QMF_FILTER_BANK
+#define HANDLE_SPACE_SYNTHESIS_QMF HANDLE_QMF_FILTER_BANK
+
+/**
+ * \brief Convert Qmf input to output audio data.
+ *
+ * \param hSpaceSynthesisQmf A Qmf Synthesis Filterbank handle.
+ * \param Sr Pointer to Qmf input buffer.
+ * \param Si Pointer to Qmf input buffer.
+ * \param stride Stride factor for output data, 1 if none.
+ * \param timeSig (None-)Interleaved audio output data.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR CalculateSpaceSynthesisQmf(
+ const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr,
+ const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig);
+
+/**
+ * \brief Convert audio input data to qmf representation.
+ *
+ * \param hSpaceAnalysisQmf A Qmf Analysis Filterbank handle.
+ * \param timeSig (None-)Interleavd audio input data.
+ * \param Sr Pointer to Qmf output buffer.
+ * \param Si Pointer to Qmf output buffer.
+ *
+ * \return Error status.
+ */
+SACDEC_ERROR CalculateSpaceAnalysisQmf(
+ HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig,
+ FIXP_DBL *Sr, FIXP_DBL *Si);
+
+#endif /* SAC_QMF_H */
diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp
new file mode 100644
index 0000000..87c0ac6
--- /dev/null
+++ b/libSACdec/src/sac_reshapeBBEnv.cpp
@@ -0,0 +1,680 @@
+/* -----------------------------------------------------------------------------
+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 guided envelope shaping
+
+*******************************************************************************/
+
+#include "sac_reshapeBBEnv.h"
+
+#include "sac_dec.h"
+#include "sac_bitdec.h"
+#include "sac_calcM1andM2.h"
+#include "sac_reshapeBBEnv.h"
+#include "sac_rom.h"
+
+#define INP_DRY_WET 0
+#define INP_DMX 1
+
+#define SF_SHAPE 1
+#define SF_DIV32 6
+#define SF_FACTOR_SLOT 5
+
+#define START_BB_ENV 0 /* 10 */
+#define END_BB_ENV 9 /* 18 */
+
+#define SF_ALPHA1 8
+#define SF_BETA1 4
+
+void initBBEnv(spatialDec *self, int initStatesFlag) {
+ INT ch, k;
+
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ k = row2channelGES[self->treeConfig][ch];
+ self->row2channelDmxGES[ch] = k;
+ if (k == -1) continue;
+
+ switch (self->treeConfig) {
+ case TREE_212:
+ self->row2channelDmxGES[ch] = 0;
+ break;
+ default:;
+ }
+ }
+
+ if (initStatesFlag) {
+ for (k = 0; k < 2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS; k++) {
+ self->reshapeBBEnvState->normNrgPrev__FDK[k] =
+ FL2FXCONST_DBL(0.5f); /* 32768.f*32768.f */
+ self->reshapeBBEnvState->normNrgPrevSF[k] = DFRACT_BITS - 1;
+ self->reshapeBBEnvState->partNrgPrevSF[k] = 0;
+ self->reshapeBBEnvState->partNrgPrev2SF[k] = 0;
+ self->reshapeBBEnvState->frameNrgPrevSF[k] = 0;
+ }
+ }
+
+ self->reshapeBBEnvState->alpha__FDK =
+ FL2FXCONST_DBL(0.99637845575f); /* FDKexp(-64 / (0.4f * 44100)) */
+ self->reshapeBBEnvState->beta__FDK =
+ FL2FXCONST_DBL(0.96436909488f); /* FDKexp(-64 / (0.04f * 44100)) */
+}
+
+static inline void getSlotNrgHQ(FIXP_DBL *RESTRICT pReal,
+ FIXP_DBL *RESTRICT pImag,
+ FIXP_DBL *RESTRICT slotNrg, INT maxValSF,
+ INT hybBands) {
+ INT qs;
+ FIXP_DBL nrg;
+
+ /* qs = 12, 13, 14 */
+ slotNrg[0] = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[1] = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[2] = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 15 */
+ slotNrg[3] = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 16, 17 */
+ nrg = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[4] = nrg + ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 18, 19, 20 */
+ nrg = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ nrg += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[5] = nrg + ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 21, 22 */
+ nrg = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[6] = nrg + ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 23, 24 */
+ if (hybBands > 23) {
+ slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 25, 26, 29, 28, 29 */
+ nrg = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ nrg += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ nrg += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ nrg += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ slotNrg[7] = nrg + ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ /* qs = 30 ... min(41,hybBands-1) */
+ nrg = ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ for (qs = 31; qs < hybBands; qs++) {
+ nrg += ((fPow2Div2((*pReal++) << maxValSF) +
+ fPow2Div2((*pImag++) << maxValSF)) >>
+ (SF_FACTOR_SLOT - 1));
+ }
+ slotNrg[8] = nrg;
+ } else {
+ slotNrg[7] = (FIXP_DBL)0;
+ slotNrg[8] = (FIXP_DBL)0;
+ }
+}
+
+static inline INT getMaxValDmx(FIXP_DBL *RESTRICT pReal,
+ FIXP_DBL *RESTRICT pImag, INT cplxBands,
+ INT hybBands) {
+ INT qs, clz;
+ FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f);
+
+ for (qs = 12; qs < cplxBands; qs++) {
+ maxVal |= fAbs(pReal[qs]);
+ maxVal |= fAbs(pImag[qs]);
+ }
+ for (; qs < hybBands; qs++) {
+ maxVal |= fAbs(pReal[qs]);
+ }
+
+ clz = fixMax(0, CntLeadingZeros(maxVal) - 1);
+
+ return (clz);
+}
+
+static inline INT getMaxValDryWet(FIXP_DBL *RESTRICT pReal,
+ FIXP_DBL *RESTRICT pImag,
+ FIXP_DBL *RESTRICT pHybOutputRealDry,
+ FIXP_DBL *RESTRICT pHybOutputImagDry,
+ FIXP_DBL *RESTRICT pHybOutputRealWet,
+ FIXP_DBL *RESTRICT pHybOutputImagWet,
+ INT cplxBands, INT hybBands) {
+ INT qs, clz;
+ FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f);
+
+ for (qs = 12; qs < cplxBands; qs++) {
+ pReal[qs] = pHybOutputRealDry[qs] + pHybOutputRealWet[qs];
+ maxVal |= fAbs(pReal[qs]);
+ pImag[qs] = pHybOutputImagDry[qs] + pHybOutputImagWet[qs];
+ maxVal |= fAbs(pImag[qs]);
+ }
+ for (; qs < hybBands; qs++) {
+ pReal[qs] = pHybOutputRealDry[qs] + pHybOutputRealWet[qs];
+ maxVal |= fAbs(pReal[qs]);
+ }
+
+ clz = fixMax(0, CntLeadingZeros(maxVal) - 1);
+
+ return (clz);
+}
+
+static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
+ FIXP_DBL *RESTRICT slotAmp_wet,
+ FIXP_DBL *RESTRICT pHybOutputRealDry,
+ FIXP_DBL *RESTRICT pHybOutputImagDry,
+ FIXP_DBL *RESTRICT pHybOutputRealWet,
+ FIXP_DBL *RESTRICT pHybOutputImagWet, INT cplxBands,
+ INT hybBands) {
+ INT qs;
+ FIXP_DBL dry, wet;
+
+ dry = wet = FL2FXCONST_DBL(0.0f);
+ for (qs = 0; qs < cplxBands; qs++) {
+ dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]) +
+ fPow2Div2(pHybOutputImagDry[qs]));
+ wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]) +
+ fPow2Div2(pHybOutputImagWet[qs]));
+ }
+ for (; qs < hybBands; qs++) {
+ dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]));
+ wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]));
+ }
+ *slotAmp_dry = dry;
+ *slotAmp_wet = wet;
+}
+
+#if defined(__aarch64__)
+__attribute__((noinline))
+#endif
+static void
+shapeBBEnv(FIXP_DBL *pHybOutputRealDry, FIXP_DBL *pHybOutputImagDry,
+ FIXP_DBL dryFac, INT scale, INT cplxBands, INT hybBands) {
+ INT qs;
+
+ if (scale == 0) {
+ for (qs = 0; qs < cplxBands; qs++) {
+ pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac);
+ pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac);
+ }
+ for (; qs < hybBands; qs++) {
+ pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac);
+ }
+ } else {
+ for (qs = 0; qs < cplxBands; qs++) {
+ pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac) << scale;
+ pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac) << scale;
+ }
+ for (; qs < hybBands; qs++) {
+ pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac) << scale;
+ }
+ }
+}
+
+static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels,
+ FIXP_DBL *pEnv, const SPATIAL_BS_FRAME *frame) {
+ INT ch, pb, prevChOffs;
+ INT clz, scale, scale_min, envSF;
+ INT scaleCur, scalePrev, commonScale;
+ INT slotNrgSF, partNrgSF, frameNrgSF;
+ INT *pPartNrgPrevSF, *pFrameNrgPrevSF;
+ INT *pNormNrgPrevSF, *pPartNrgPrev2SF;
+
+ FIXP_DBL maxVal, env, frameNrg, normNrg;
+ FIXP_DBL *pReal, *pImag;
+ FIXP_DBL *partNrg, *partNrgPrev;
+
+ C_ALLOC_SCRATCH_START(pScratchBuffer, FIXP_DBL,
+ (2 * 42 + MAX_PARAMETER_BANDS));
+ C_ALLOC_SCRATCH_START(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV));
+ C_ALLOC_SCRATCH_START(resPbSF, INT, (END_BB_ENV - START_BB_ENV));
+
+ FIXP_DBL *slotNrg = pScratchBuffer + (2 * 42);
+
+ RESHAPE_BBENV_STATE *pBBEnvState = self->reshapeBBEnvState;
+
+ FIXP_DBL alpha = pBBEnvState->alpha__FDK;
+ /*FIXP_DBL alpha1 = (FL2FXCONST_DBL(1.0f) - alpha) << SF_ALPHA1;*/
+ FIXP_DBL alpha1 = ((FIXP_DBL)MAXVAL_DBL - alpha) << SF_ALPHA1;
+ FIXP_DBL beta = pBBEnvState->beta__FDK;
+ /*FIXP_DBL beta1 = (FL2FXCONST_DBL(1.0f) - beta) << SF_BETA1;*/
+ FIXP_DBL beta1 = ((FIXP_DBL)MAXVAL_DBL - beta) << SF_BETA1;
+
+ INT shapeActiv = 1;
+ INT hybBands = fixMin(42, self->hybridBands);
+ INT staticScale = self->staticDecScale;
+ INT cplxBands;
+ cplxBands = fixMin(42, self->hybridBands);
+
+ for (ch = start; ch < channels; ch++) {
+ if (inp == INP_DRY_WET) {
+ INT ch2 = row2channelGES[self->treeConfig][ch];
+ if (ch2 == -1) {
+ continue;
+ } else {
+ if (frame->tempShapeEnableChannelGES[ch2]) {
+ shapeActiv = 1;
+ } else {
+ shapeActiv = 0;
+ }
+ }
+ prevChOffs = ch;
+ pReal = pScratchBuffer;
+ pImag = pScratchBuffer + 42;
+ clz = getMaxValDryWet(
+ pReal, pImag, self->hybOutputRealDry__FDK[ch],
+ self->hybOutputImagDry__FDK[ch], self->hybOutputRealWet__FDK[ch],
+ self->hybOutputImagWet__FDK[ch], cplxBands, hybBands);
+ } else {
+ prevChOffs = ch + self->numOutputChannels;
+ pReal = self->hybInputReal__FDK[ch];
+ pImag = self->hybInputImag__FDK[ch];
+ clz = getMaxValDmx(pReal, pImag, cplxBands, hybBands);
+ }
+
+ partNrg = partNrgPrev = pBBEnvState->partNrgPrev__FDK[prevChOffs];
+ pPartNrgPrevSF = &pBBEnvState->partNrgPrevSF[prevChOffs];
+ pFrameNrgPrevSF = &pBBEnvState->frameNrgPrevSF[prevChOffs];
+ pNormNrgPrevSF = &pBBEnvState->normNrgPrevSF[prevChOffs];
+ pPartNrgPrev2SF = &pBBEnvState->partNrgPrev2SF[prevChOffs];
+
+ /* calculate slot energy */
+ {
+ getSlotNrgHQ(&pReal[12], &pImag[12], slotNrg, clz,
+ fixMin(42, self->hybridBands)); /* scale slotNrg:
+ 2*(staticScale-clz) +
+ SF_FACTOR_SLOT */
+ }
+
+ slotNrgSF = 2 * (staticScale - clz) + SF_FACTOR_SLOT;
+ frameNrgSF = 2 * (staticScale - clz) + SF_FACTOR_SLOT;
+
+ partNrgSF = fixMax(slotNrgSF - SF_ALPHA1 + 1,
+ pPartNrgPrevSF[0] - pPartNrgPrev2SF[0] + 1);
+ scalePrev = fixMax(fixMin(partNrgSF - pPartNrgPrevSF[0], DFRACT_BITS - 1),
+ -(DFRACT_BITS - 1));
+ scaleCur =
+ fixMax(fixMin(partNrgSF - slotNrgSF + SF_ALPHA1, DFRACT_BITS - 1),
+ -(DFRACT_BITS - 1));
+
+ maxVal = FL2FXCONST_DBL(0.0f);
+ frameNrg = FL2FXCONST_DBL(0.0f);
+ if ((scaleCur < 0) && (scalePrev < 0)) {
+ scaleCur = -scaleCur;
+ scalePrev = -scalePrev;
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) +
+ (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev))
+ << 1;
+ maxVal |= partNrg[pb];
+ frameNrg += slotNrg[pb] >> 3;
+ }
+ } else if ((scaleCur >= 0) && (scalePrev >= 0)) {
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) +
+ (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev))
+ << 1;
+ maxVal |= partNrg[pb];
+ frameNrg += slotNrg[pb] >> 3;
+ }
+ } else if ((scaleCur < 0) && (scalePrev >= 0)) {
+ scaleCur = -scaleCur;
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) +
+ (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev))
+ << 1;
+ maxVal |= partNrg[pb];
+ frameNrg += slotNrg[pb] >> 3;
+ }
+ } else { /* if ( (scaleCur >= 0) && (scalePrev < 0) ) */
+ scalePrev = -scalePrev;
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) +
+ (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev))
+ << 1;
+ maxVal |= partNrg[pb];
+ frameNrg += slotNrg[pb] >> 3;
+ }
+ }
+
+ /* frameNrg /= (END_BB_ENV - START_BB_ENV); 0.88888888888f =
+ * (1/(END_BB_ENV-START_BB_ENV)<<3; shift with 3 is compensated in loop
+ * above */
+ frameNrg = fMult(frameNrg, FL2FXCONST_DBL(0.88888888888f));
+
+ /* store scalefactor and headroom for part nrg prev */
+ pPartNrgPrevSF[0] = partNrgSF;
+ pPartNrgPrev2SF[0] = fixMax(0, CntLeadingZeros(maxVal) - 1);
+
+ commonScale = fixMax(frameNrgSF - SF_ALPHA1 + 1, pFrameNrgPrevSF[0] + 1);
+ scalePrev = fixMin(commonScale - pFrameNrgPrevSF[0], DFRACT_BITS - 1);
+ scaleCur = fixMin(commonScale - frameNrgSF + SF_ALPHA1, DFRACT_BITS - 1);
+ frameNrgSF = commonScale;
+
+ frameNrg = ((fMultDiv2(alpha1, frameNrg) >> scaleCur) +
+ (fMultDiv2(alpha, pBBEnvState->frameNrgPrev__FDK[prevChOffs]) >>
+ scalePrev))
+ << 1;
+
+ clz = fixMax(0, CntLeadingZeros(frameNrg) - 1);
+ pBBEnvState->frameNrgPrev__FDK[prevChOffs] = frameNrg << clz;
+ pFrameNrgPrevSF[0] = frameNrgSF - clz;
+
+ env = FL2FXCONST_DBL(0.0f);
+ scale = clz + partNrgSF - frameNrgSF;
+ scale_min = DFRACT_BITS - 1;
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ if ((partNrg[pb] | slotNrg[pb]) != FL2FXCONST_DBL(0.0f)) {
+ INT s;
+ INT sc = 0;
+ INT sn = fixMax(0, CntLeadingZeros(slotNrg[pb]) - 1);
+ FIXP_DBL inv_sqrt = invSqrtNorm2(partNrg[pb], &sc);
+ FIXP_DBL res = fMult(slotNrg[pb] << sn, fPow2(inv_sqrt));
+
+ s = fixMax(0, CntLeadingZeros(res) - 1);
+ res = res << s;
+
+ sc = scale - (2 * sc - sn - s);
+ scale_min = fixMin(scale_min, sc);
+
+ resPb[pb] = res;
+ resPbSF[pb] = sc;
+ } else {
+ resPb[pb] = (FIXP_DBL)0;
+ resPbSF[pb] = 0;
+ }
+ }
+
+ scale_min = 4 - scale_min;
+
+ for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) {
+ INT sc = fixMax(fixMin(resPbSF[pb] + scale_min, DFRACT_BITS - 1),
+ -(DFRACT_BITS - 1));
+
+ if (sc < 0) {
+ env += resPb[pb] << (-sc);
+ } else {
+ env += resPb[pb] >> (sc);
+ }
+ }
+
+ env = fMultDiv2(env, pBBEnvState->frameNrgPrev__FDK[prevChOffs]);
+ envSF = slotNrgSF + scale_min + 1;
+
+ commonScale = fixMax(envSF - SF_BETA1 + 1, pNormNrgPrevSF[0] + 1);
+ scalePrev = fixMin(commonScale - pNormNrgPrevSF[0], DFRACT_BITS - 1);
+ scaleCur = fixMin(commonScale - envSF + SF_BETA1, DFRACT_BITS - 1);
+
+ normNrg = ((fMultDiv2(beta1, env) >> scaleCur) +
+ (fMultDiv2(beta, pBBEnvState->normNrgPrev__FDK[prevChOffs]) >>
+ scalePrev))
+ << 1;
+
+ clz = fixMax(0, CntLeadingZeros(normNrg) - 1);
+ pBBEnvState->normNrgPrev__FDK[prevChOffs] = normNrg << clz;
+ pNormNrgPrevSF[0] = commonScale - clz;
+
+ if (shapeActiv) {
+ if ((env | normNrg) != FL2FXCONST_DBL(0.0f)) {
+ INT sc, se, sn;
+ se = fixMax(0, CntLeadingZeros(env) - 1);
+ sc = commonScale + SF_DIV32 - envSF + se;
+ env = fMult(sqrtFixp((env << se) >> (sc & 0x1)),
+ invSqrtNorm2(normNrg, &sn));
+
+ sc = fixMin((sc >> 1) - sn, DFRACT_BITS - 1);
+ if (sc < 0) {
+ env <<= (-sc);
+ } else {
+ env >>= (sc);
+ }
+ }
+ /* env is scaled by SF_DIV32/2 bits */
+ }
+ pEnv[ch] = env;
+ }
+
+ C_ALLOC_SCRATCH_END(resPbSF, INT, (END_BB_ENV - START_BB_ENV));
+ C_ALLOC_SCRATCH_END(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV));
+ C_ALLOC_SCRATCH_END(pScratchBuffer, FIXP_DBL, (2 * 42 + MAX_PARAMETER_BANDS));
+}
+
+void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ INT ts) {
+ INT ch, scale;
+ INT dryFacSF, slotAmpSF;
+ FIXP_DBL tmp, dryFac, envShape;
+ FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio;
+ FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2];
+
+ INT cplxBands;
+ INT hybBands = self->hybridBands - 6;
+
+ cplxBands = self->hybridBands - 6;
+
+ /* extract downmix envelope(s) */
+ switch (self->treeConfig) {
+ default:
+ extractBBEnv(self, INP_DMX, 0, fMin(self->numInputChannels, 2), envDmx,
+ frame);
+ }
+
+ /* extract dry and wet envelopes */
+ extractBBEnv(self, INP_DRY_WET, 0, self->numOutputChannels, envDry, frame);
+
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ INT ch2;
+
+ ch2 = row2channelGES[self->treeConfig][ch];
+
+ if (ch2 == -1) continue;
+
+ if (frame->tempShapeEnableChannelGES[ch2]) {
+ INT sc;
+
+ /* reshape dry and wet signals according to transmitted envelope */
+
+ /* De-quantize GES data */
+ FDK_ASSERT((frame->bsEnvShapeData[ch2][ts] >= 0) &&
+ (frame->bsEnvShapeData[ch2][ts] <= 4));
+ FDK_ASSERT((self->envQuantMode == 0) || (self->envQuantMode == 1));
+ envShape =
+ FX_CFG2FX_DBL(envShapeDataTable__FDK[frame->bsEnvShapeData[ch2][ts]]
+ [self->envQuantMode]);
+
+ /* get downmix channel */
+ ch2 = self->row2channelDmxGES[ch];
+
+ /* multiply ratio with dmx envelope; tmp is scaled by SF_DIV32/2+SF_SHAPE
+ * bits */
+ if (ch2 == 2) {
+ tmp = fMultDiv2(envShape, envDmx[0]) + fMultDiv2(envShape, envDmx[1]);
+ } else {
+ tmp = fMult(envShape, envDmx[ch2]);
+ }
+
+ /* weighting factors */
+ dryFacSF = slotAmpSF = 0;
+ dryFac = slotAmp_ratio = FL2FXCONST_DBL(0.0f);
+
+ /* dryFac will be scaled by dryFacSF bits */
+ if (envDry[ch] != FL2FXCONST_DBL(0.0f)) {
+ envDry[ch] = invSqrtNorm2(envDry[ch], &dryFacSF);
+ dryFac = fMultDiv2(tmp, fPow2Div2(envDry[ch])) << 2;
+ dryFacSF = SF_SHAPE + 2 * dryFacSF;
+ }
+
+ /* calculate slotAmp_dry and slotAmp_wet */
+ slotAmp(&slotAmp_dry, &slotAmp_wet, &self->hybOutputRealDry__FDK[ch][6],
+ &self->hybOutputImagDry__FDK[ch][6],
+ &self->hybOutputRealWet__FDK[ch][6],
+ &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands);
+
+ /* slotAmp_ratio will be scaled by slotAmpSF bits */
+ if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) {
+ sc = fixMax(0, CntLeadingZeros(slotAmp_wet) - 1);
+ sc = sc - (sc & 1);
+
+ slotAmp_wet = sqrtFixp(slotAmp_wet << sc);
+ slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF);
+
+ slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry);
+ slotAmpSF = slotAmpSF - (sc >> 1);
+ }
+
+ /* calculate common scale factor */
+ scale =
+ fixMax(3, fixMax(dryFacSF, slotAmpSF)); /* scale is at least with 3
+ bits to avoid overflows
+ when calculating dryFac */
+ dryFac = dryFac >> (scale - dryFacSF);
+ slotAmp_ratio = slotAmp_ratio >> (scale - slotAmpSF);
+
+ /* limit dryFac */
+ dryFac = fixMax(
+ FL2FXCONST_DBL(0.25f) >> (INT)fixMin(2 * scale, DFRACT_BITS - 1),
+ fMult(dryFac, slotAmp_ratio) - (slotAmp_ratio >> scale) +
+ (dryFac >> scale));
+ dryFac = fixMin(
+ FL2FXCONST_DBL(0.50f) >> (INT)fixMin(2 * scale - 3, DFRACT_BITS - 1),
+ dryFac); /* reduce shift bits by 3, because upper
+ limit 4.0 is scaled with 3 bits */
+ scale = 2 * scale + 1;
+
+ /* improve precision for dryFac */
+ sc = fixMax(0, CntLeadingZeros(dryFac) - 1);
+ dryFac = dryFac << (INT)fixMin(scale, sc);
+ scale = scale - fixMin(scale, sc);
+
+ /* shaping */
+ shapeBBEnv(&self->hybOutputRealDry__FDK[ch][6],
+ &self->hybOutputImagDry__FDK[ch][6], dryFac, scale, cplxBands,
+ hybBands);
+ }
+ }
+}
diff --git a/libSACdec/src/sac_reshapeBBEnv.h b/libSACdec/src/sac_reshapeBBEnv.h
new file mode 100644
index 0000000..1658530
--- /dev/null
+++ b/libSACdec/src/sac_reshapeBBEnv.h
@@ -0,0 +1,114 @@
+/* -----------------------------------------------------------------------------
+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 guided envelope shaping
+
+*******************************************************************************/
+
+#ifndef SAC_RESHAPEBBENV_H
+#define SAC_RESHAPEBBENV_H
+
+#include "sac_dec_interface.h"
+
+#define BB_ENV_SIZE 9 /* END_BB_ENV - START_BB_ENV */
+
+void initBBEnv(spatialDec *self, int initStatesFlag);
+void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ int ts);
+
+#endif
diff --git a/libSACdec/src/sac_rom.cpp b/libSACdec/src/sac_rom.cpp
new file mode 100644
index 0000000..4285b65
--- /dev/null
+++ b/libSACdec/src/sac_rom.cpp
@@ -0,0 +1,709 @@
+/* -----------------------------------------------------------------------------
+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 tables
+
+*******************************************************************************/
+
+#include "sac_rom.h"
+#include "sac_calcM1andM2.h"
+
+#define SCALE_CPC(a) (FL2FXCONST_CFG(a / (float)(1 << SCALE_PARAM_M1)))
+const FIXP_CFG dequantCPC__FDK[] = {
+ SCALE_CPC(-2.0f), SCALE_CPC(-1.9f), SCALE_CPC(-1.8f), SCALE_CPC(-1.7f),
+ SCALE_CPC(-1.6f), SCALE_CPC(-1.5f), SCALE_CPC(-1.4f), SCALE_CPC(-1.3f),
+ SCALE_CPC(-1.2f), SCALE_CPC(-1.1f), SCALE_CPC(-1.0f), SCALE_CPC(-0.9f),
+ SCALE_CPC(-0.8f), SCALE_CPC(-0.7f), SCALE_CPC(-0.6f), SCALE_CPC(-0.5f),
+ SCALE_CPC(-0.4f), SCALE_CPC(-0.3f), SCALE_CPC(-0.2f), SCALE_CPC(-0.1f),
+ SCALE_CPC(0.0f), SCALE_CPC(0.1f), SCALE_CPC(0.2f), SCALE_CPC(0.3f),
+ SCALE_CPC(0.4f), SCALE_CPC(0.5f), SCALE_CPC(0.6f), SCALE_CPC(0.7f),
+ SCALE_CPC(0.8f), SCALE_CPC(0.9f), SCALE_CPC(1.0f), SCALE_CPC(1.1f),
+ SCALE_CPC(1.2f), SCALE_CPC(1.3f), SCALE_CPC(1.4f), SCALE_CPC(1.5f),
+ SCALE_CPC(1.6f), SCALE_CPC(1.7f), SCALE_CPC(1.8f), SCALE_CPC(1.9f),
+ SCALE_CPC(2.0f), SCALE_CPC(2.1f), SCALE_CPC(2.2f), SCALE_CPC(2.3f),
+ SCALE_CPC(2.4f), SCALE_CPC(2.5f), SCALE_CPC(2.6f), SCALE_CPC(2.7f),
+ SCALE_CPC(2.8f), SCALE_CPC(2.9f), SCALE_CPC(3.0f)};
+
+#define SCALE_ICC(a) (FL2FXCONST_CFG(a))
+const FIXP_CFG dequantICC__FDK[8] = {
+ /*SCALE_ICC(1.00000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL),
+ SCALE_ICC(0.9370f),
+ SCALE_ICC(0.84118f),
+ SCALE_ICC(0.60092f),
+ SCALE_ICC(0.36764f),
+ SCALE_ICC(0.0000f),
+ SCALE_ICC(-0.58900f),
+ SCALE_ICC(-0.9900f)};
+
+#define SCALE_CLD2(a) (FL2FXCONST_CFG(a / (float)(1 << 8)))
+const FIXP_CFG dequantCLD__FDK[31] = {
+ SCALE_CLD2(-150.0f), SCALE_CLD2(-45.0f), SCALE_CLD2(-40.0f),
+ SCALE_CLD2(-35.0f), SCALE_CLD2(-30.0f), SCALE_CLD2(-25.0f),
+ SCALE_CLD2(-22.0f), SCALE_CLD2(-19.0f), SCALE_CLD2(-16.0f),
+ SCALE_CLD2(-13.0f), SCALE_CLD2(-10.0f), SCALE_CLD2(-8.0f),
+ SCALE_CLD2(-6.0f), SCALE_CLD2(-4.0f), SCALE_CLD2(-2.0f),
+ SCALE_CLD2(0.0f), SCALE_CLD2(2.0f), SCALE_CLD2(4.0f),
+ SCALE_CLD2(6.0f), SCALE_CLD2(8.0f), SCALE_CLD2(10.0f),
+ SCALE_CLD2(13.0f), SCALE_CLD2(16.0f), SCALE_CLD2(19.0f),
+ SCALE_CLD2(22.0f), SCALE_CLD2(25.0f), SCALE_CLD2(30.0f),
+ SCALE_CLD2(35.0f), SCALE_CLD2(40.0f), SCALE_CLD2(45.0f),
+ SCALE_CLD2(150.0f)};
+
+#define SCALE_IPD(a) (FL2FXCONST_CFG(a / (float)(1 << IPD_SCALE)))
+const FIXP_CFG dequantIPD__FDK[16] = {
+ /* SCALE_IPD(0.000000000f), SCALE_IPD(0.392699082f),
+ SCALE_IPD(0.785398163f), SCALE_IPD(1.178097245f),
+ SCALE_IPD(1.570796327f), SCALE_IPD(1.963495408f),
+ SCALE_IPD(2.356194490f), SCALE_IPD(2.748893572f),
+ SCALE_IPD(3.141592654f), SCALE_IPD(3.534291735f),
+ SCALE_IPD(3.926990817f), SCALE_IPD(4.319689899f),
+ SCALE_IPD(4.712388980f), SCALE_IPD(5.105088062f),
+ SCALE_IPD(5.497787144f), SCALE_IPD(5.890486225f) */
+ SCALE_IPD(0.00000000000000f), SCALE_IPD(0.392699082f),
+ SCALE_IPD(0.78539816339745f), SCALE_IPD(1.178097245f),
+ SCALE_IPD(1.57079632679490f), SCALE_IPD(1.963495408f),
+ SCALE_IPD(2.35619449019234f), SCALE_IPD(2.748893572f),
+ SCALE_IPD(3.14159265358979f), SCALE_IPD(3.534291735f),
+ SCALE_IPD(3.92699081698724f), SCALE_IPD(4.319689899f),
+ SCALE_IPD(4.71238898038469f), SCALE_IPD(5.105088062f),
+ SCALE_IPD(5.49778714378214f), SCALE_IPD(5.890486225f)};
+
+#define SCALE_SPLIT_ANGLE(a) (FL2FXCONST_CFG(a / (float)(1 << IPD_SCALE)))
+/*
+ Generate table dequantIPD_CLD_ICC_splitAngle__FDK[16][31][8]:
+
+ #define ABS_THR ( 1e-9f * 32768 * 32768 )
+
+ float dequantICC[] =
+ {1.0000f,0.9370f,0.84118f,0.60092f,0.36764f,0.0f,-0.5890f,-0.9900f}; float
+ dequantCLD[] =
+ {-150.0,-45.0,-40.0,-35.0,-30.0,-25.0,-22.0,-19.0,-16.0,-13.0,-10.0, -8.0,
+ -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0,
+ 10.0, 13.0, 16.0, 19.0, 22.0, 25.0, 30.0, 35.0, 40.0, 45.0, 150.0 }; float
+ dequantIPD[] =
+ {0.f,0.392699082f,0.785398163f,1.178097245f,1.570796327f,1.963495408f,
+ 2.35619449f,2.748893572f,3.141592654f,3.534291735f,3.926990817f,
+ 4.319689899f,4.71238898f,5.105088062f,5.497787144f,5.890486225f};
+
+ for (ipdIdx=0; ipdIdx<16; ipdIdx++)
+ for (cldIdx=0; cldIdx<31; cldIdx++)
+ for (iccIdx=0; iccIdx<8; iccIdx++) {
+ ipd = dequantIPD[ipdIdx];
+ cld = dequantCLD[cldIdx];
+ icc = dequantICC[iccIdx];
+ iidLin = (float) pow(10.0f, cld / 20.0f);
+ iidLin2 = iidLin * iidLin;
+ iidLin21 = iidLin2 + 1.0f;
+ sinIpd = (float) sin(ipd);
+ cosIpd = (float) cos(ipd);
+ temp1 = 2.0f * icc * iidLin;
+ temp1c = temp1 * cosIpd;
+ ratio = (iidLin21 + temp1c) / (iidLin21 + temp1) + ABS_THR;
+ w2 = (float) pow(ratio, 0.25f);
+ w1 = 2.0f - w2;
+ dequantIPD_CLD_ICC_splitAngle__FDK[ipdIdx][cldIdx][iccIdx] = (float)
+ atan2(w2 * sinIpd, w1 * iidLin + w2 * cosIpd);
+ }
+*/
+
+#define SCALE_CLD(a) (FL2FXCONST_CFG(a))
+
+const FIXP_CFG dequantCLD_c_l[31] = {
+ SCALE_CLD(0.0000000316f),
+ SCALE_CLD(0.0056233243f),
+ SCALE_CLD(0.0099994997f),
+ SCALE_CLD(0.0177799836f),
+ SCALE_CLD(0.0316069759f),
+ SCALE_CLD(0.0561454296f),
+ SCALE_CLD(0.0791834071f),
+ SCALE_CLD(0.1115021780f),
+ SCALE_CLD(0.1565355062f),
+ SCALE_CLD(0.2184644639f),
+ SCALE_CLD(0.3015113473f),
+ SCALE_CLD(0.3698741496f),
+ SCALE_CLD(0.4480624795f),
+ SCALE_CLD(0.5336171389f),
+ SCALE_CLD(0.6219832301f),
+ SCALE_CLD(0.7071067691f),
+ SCALE_CLD(0.7830305696f),
+ SCALE_CLD(0.8457261920f),
+ SCALE_CLD(0.8940021992f),
+ SCALE_CLD(0.9290818572f),
+ SCALE_CLD(0.9534626007f),
+ SCALE_CLD(0.9758449197f),
+ SCALE_CLD(0.9876723289f),
+ SCALE_CLD(0.9937641621f),
+ SCALE_CLD(0.9968600869f),
+ SCALE_CLD(0.9984226227f),
+ SCALE_CLD(0.9995003939f),
+ SCALE_CLD(0.9998419285f),
+ SCALE_CLD(0.9999499917f),
+ SCALE_CLD(0.9999842048f),
+ /*SCALE_CLD(1.0000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)};
+
+#define SC_H(a) (FL2FXCONST_CFG(a))
+#define DATA_TYPE_H FIXP_CFG
+
+/* not correlated tables */
+const DATA_TYPE_H H11_nc[31][8] = {
+ {SC_H(0.0000000316f), SC_H(0.0000000296f), SC_H(0.0000000266f),
+ SC_H(0.0000000190f), SC_H(0.0000000116f), SC_H(0.0000000000f),
+ SC_H(-0.0000000186f), SC_H(-0.0000000313f)},
+ {SC_H(0.0056233243f), SC_H(0.0052728835f), SC_H(0.0047394098f),
+ SC_H(0.0033992692f), SC_H(0.0020946222f), SC_H(0.0000316215f),
+ SC_H(-0.0032913829f), SC_H(-0.0055664564f)},
+ {SC_H(0.0099994997f), SC_H(0.0093815643f), SC_H(0.0084402543f),
+ SC_H(0.0060722125f), SC_H(0.0037622179f), SC_H(0.0000999898f),
+ SC_H(-0.0058238208f), SC_H(-0.0098974844f)},
+ {SC_H(0.0177799836f), SC_H(0.0166974831f), SC_H(0.0150465844f),
+ SC_H(0.0108831404f), SC_H(0.0068073822f), SC_H(0.0003161267f),
+ SC_H(-0.0102626514f), SC_H(-0.0175957214f)},
+ {SC_H(0.0316069759f), SC_H(0.0297324844f), SC_H(0.0268681273f),
+ SC_H(0.0196138974f), SC_H(0.0124691967f), SC_H(0.0009989988f),
+ SC_H(-0.0179452803f), SC_H(-0.0312700421f)},
+ {SC_H(0.0561454296f), SC_H(0.0529650487f), SC_H(0.0480896905f),
+ SC_H(0.0356564634f), SC_H(0.0232860073f), SC_H(0.0031523081f),
+ SC_H(-0.0309029408f), SC_H(-0.0555154830f)},
+ {SC_H(0.0791834071f), SC_H(0.0748842582f), SC_H(0.0682762116f),
+ SC_H(0.0513241664f), SC_H(0.0343080349f), SC_H(0.0062700072f),
+ SC_H(-0.0422340371f), SC_H(-0.0782499388f)},
+ {SC_H(0.1115021780f), SC_H(0.1057924852f), SC_H(0.0969873071f),
+ SC_H(0.0742305145f), SC_H(0.0511277616f), SC_H(0.0124327289f),
+ SC_H(-0.0566596612f), SC_H(-0.1100896299f)},
+ {SC_H(0.1565355062f), SC_H(0.1491366178f), SC_H(0.1376826316f),
+ SC_H(0.1078186408f), SC_H(0.0770794004f), SC_H(0.0245033558f),
+ SC_H(-0.0735980421f), SC_H(-0.1543303132f)},
+ {SC_H(0.2184644639f), SC_H(0.2091979682f), SC_H(0.1947948188f),
+ SC_H(0.1568822265f), SC_H(0.1172478944f), SC_H(0.0477267131f),
+ SC_H(-0.0899507254f), SC_H(-0.2148526460f)},
+ {SC_H(0.3015113473f), SC_H(0.2904391289f), SC_H(0.2731673419f),
+ SC_H(0.2273024023f), SC_H(0.1786239147f), SC_H(0.0909090787f),
+ SC_H(-0.0964255333f), SC_H(-0.2951124907f)},
+ {SC_H(0.3698741496f), SC_H(0.3578284085f), SC_H(0.3390066922f),
+ SC_H(0.2888108492f), SC_H(0.2351117432f), SC_H(0.1368068755f),
+ SC_H(-0.0850296095f), SC_H(-0.3597966135f)},
+ {SC_H(0.4480624795f), SC_H(0.4354025424f), SC_H(0.4156077504f),
+ SC_H(0.3627120256f), SC_H(0.3058823943f), SC_H(0.2007599771f),
+ SC_H(-0.0484020934f), SC_H(-0.4304940701f)},
+ {SC_H(0.5336171389f), SC_H(0.5208471417f), SC_H(0.5008935928f),
+ SC_H(0.4476420581f), SC_H(0.3905044496f), SC_H(0.2847472429f),
+ SC_H(0.0276676007f), SC_H(-0.4966579080f)},
+ {SC_H(0.6219832301f), SC_H(0.6096963882f), SC_H(0.5905415416f),
+ SC_H(0.5396950245f), SC_H(0.4856070578f), SC_H(0.3868631124f),
+ SC_H(0.1531652957f), SC_H(-0.5045361519f)},
+ {SC_H(0.7071067691f), SC_H(0.6958807111f), SC_H(0.6784504056f),
+ SC_H(0.6326373219f), SC_H(0.5847306848f), SC_H(0.4999999702f),
+ SC_H(0.3205464482f), SC_H(0.0500000045f)},
+ {SC_H(0.7830305696f), SC_H(0.7733067870f), SC_H(0.7582961321f),
+ SC_H(0.7194055915f), SC_H(0.6797705293f), SC_H(0.6131368876f),
+ SC_H(0.4997332692f), SC_H(0.6934193969f)},
+ {SC_H(0.8457261920f), SC_H(0.8377274871f), SC_H(0.8254694939f),
+ SC_H(0.7942851782f), SC_H(0.7635439038f), SC_H(0.7152527571f),
+ SC_H(0.6567122936f), SC_H(0.8229061961f)},
+ {SC_H(0.8940021992f), SC_H(0.8877248168f), SC_H(0.8781855106f),
+ SC_H(0.8544237614f), SC_H(0.8318918347f), SC_H(0.7992399335f),
+ SC_H(0.7751275301f), SC_H(0.8853276968f)},
+ {SC_H(0.9290818572f), SC_H(0.9243524075f), SC_H(0.9172304869f),
+ SC_H(0.8998877406f), SC_H(0.8841174841f), SC_H(0.8631930947f),
+ SC_H(0.8565139771f), SC_H(0.9251161218f)},
+ {SC_H(0.9534626007f), SC_H(0.9500193000f), SC_H(0.9448821545f),
+ SC_H(0.9326565266f), SC_H(0.9220023751f), SC_H(0.9090909362f),
+ SC_H(0.9096591473f), SC_H(0.9514584541f)},
+ {SC_H(0.9758449197f), SC_H(0.9738122821f), SC_H(0.9708200693f),
+ SC_H(0.9639287591f), SC_H(0.9582763910f), SC_H(0.9522733092f),
+ SC_H(0.9553207159f), SC_H(0.9750427008f)},
+ {SC_H(0.9876723289f), SC_H(0.9865267277f), SC_H(0.9848603010f),
+ SC_H(0.9811310172f), SC_H(0.9782302976f), SC_H(0.9754966497f),
+ SC_H(0.9779621363f), SC_H(0.9873252511f)},
+ {SC_H(0.9937641621f), SC_H(0.9931397438f), SC_H(0.9922404289f),
+ SC_H(0.9902750254f), SC_H(0.9888116717f), SC_H(0.9875672460f),
+ SC_H(0.9891131520f), SC_H(0.9936066866f)},
+ {SC_H(0.9968600869f), SC_H(0.9965277910f), SC_H(0.9960530400f),
+ SC_H(0.9950347543f), SC_H(0.9943022728f), SC_H(0.9937300086f),
+ SC_H(0.9946073294f), SC_H(0.9967863560f)},
+ {SC_H(0.9984226227f), SC_H(0.9982488155f), SC_H(0.9980020523f),
+ SC_H(0.9974802136f), SC_H(0.9971146584f), SC_H(0.9968476892f),
+ SC_H(0.9973216057f), SC_H(0.9983873963f)},
+ {SC_H(0.9995003939f), SC_H(0.9994428754f), SC_H(0.9993617535f),
+ SC_H(0.9991930723f), SC_H(0.9990783334f), SC_H(0.9990010262f),
+ SC_H(0.9991616607f), SC_H(0.9994897842f)},
+ {SC_H(0.9998419285f), SC_H(0.9998232722f), SC_H(0.9997970462f),
+ SC_H(0.9997430444f), SC_H(0.9997069836f), SC_H(0.9996838570f),
+ SC_H(0.9997364879f), SC_H(0.9998386502f)},
+ {SC_H(0.9999499917f), SC_H(0.9999440312f), SC_H(0.9999356270f),
+ SC_H(0.9999184012f), SC_H(0.9999070764f), SC_H(0.9998999834f),
+ SC_H(0.9999169707f), SC_H(0.9999489784f)},
+ {SC_H(0.9999842048f), SC_H(0.9999822974f), SC_H(0.9999796152f),
+ SC_H(0.9999741912f), SC_H(0.9999706149f), SC_H(0.9999684095f),
+ SC_H(0.9999738336f), SC_H(0.9999839067f)},
+ /* { SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f),
+ SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f),
+ SC_H( 1.0000000000f), SC_H( 1.0000000000f)} */
+ {FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL),
+ FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL),
+ FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL),
+ FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL)}};
+const DATA_TYPE_H H12_nc[31][8] = {
+ {SC_H(0.0000000000f), SC_H(0.0000000110f), SC_H(0.0000000171f),
+ SC_H(0.0000000253f), SC_H(0.0000000294f), SC_H(0.0000000316f),
+ SC_H(0.0000000256f), SC_H(0.0000000045f)},
+ {SC_H(0.0000000000f), SC_H(0.0019540924f), SC_H(0.0030265113f),
+ SC_H(0.0044795922f), SC_H(0.0052186525f), SC_H(0.0056232354f),
+ SC_H(0.0045594489f), SC_H(0.0007977085f)},
+ {SC_H(0.0000000000f), SC_H(0.0034606720f), SC_H(0.0053620986f),
+ SC_H(0.0079446984f), SC_H(0.0092647560f), SC_H(0.0099989995f),
+ SC_H(0.0081285369f), SC_H(0.0014247064f)},
+ {SC_H(0.0000000000f), SC_H(0.0061091618f), SC_H(0.0094724922f),
+ SC_H(0.0140600521f), SC_H(0.0164252054f), SC_H(0.0177771728f),
+ SC_H(0.0145191532f), SC_H(0.0025531140f)},
+ {SC_H(0.0000000000f), SC_H(0.0107228858f), SC_H(0.0166464616f),
+ SC_H(0.0247849934f), SC_H(0.0290434174f), SC_H(0.0315911844f),
+ SC_H(0.0260186065f), SC_H(0.0046027615f)},
+ {SC_H(0.0000000000f), SC_H(0.0186282862f), SC_H(0.0289774220f),
+ SC_H(0.0433696397f), SC_H(0.0510888547f), SC_H(0.0560568646f),
+ SC_H(0.0468755551f), SC_H(0.0083869267f)},
+ {SC_H(0.0000000000f), SC_H(0.0257363543f), SC_H(0.0401044972f),
+ SC_H(0.0602979437f), SC_H(0.0713650510f), SC_H(0.0789347738f),
+ SC_H(0.0669798329f), SC_H(0.0121226767f)},
+ {SC_H(0.0000000000f), SC_H(0.0352233723f), SC_H(0.0550108925f),
+ SC_H(0.0832019597f), SC_H(0.0990892947f), SC_H(0.1108068749f),
+ SC_H(0.0960334241f), SC_H(0.0176920593f)},
+ {SC_H(0.0000000000f), SC_H(0.0475566536f), SC_H(0.0744772255f),
+ SC_H(0.1134835035f), SC_H(0.1362429112f), SC_H(0.1546057910f),
+ SC_H(0.1381545961f), SC_H(0.0261824392f)},
+ {SC_H(0.0000000000f), SC_H(0.0629518181f), SC_H(0.0989024863f),
+ SC_H(0.1520351619f), SC_H(0.1843357086f), SC_H(0.2131874412f),
+ SC_H(0.1990868896f), SC_H(0.0395608991f)},
+ {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f),
+ SC_H(0.1980977356f), SC_H(0.2429044843f), SC_H(0.2874797881f),
+ SC_H(0.2856767476f), SC_H(0.0617875643f)},
+ {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f),
+ SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f),
+ SC_H(0.3599678576f), SC_H(0.0857512727f)},
+ {SC_H(0.0000000000f), SC_H(0.1057573780f), SC_H(0.1674221754f),
+ SC_H(0.2630588412f), SC_H(0.3274079263f), SC_H(0.4005688727f),
+ SC_H(0.4454404712f), SC_H(0.1242370531f)},
+ {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915067f),
+ SC_H(0.2904545665f), SC_H(0.3636667728f), SC_H(0.4512939751f),
+ SC_H(0.5328993797f), SC_H(0.1951362640f)},
+ {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952532977f),
+ SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870318770f),
+ SC_H(0.6028295755f), SC_H(0.3637395203f)},
+ {SC_H(0.0000000000f), SC_H(0.1254990250f), SC_H(0.1992611140f),
+ SC_H(0.3158638775f), SC_H(0.3976053298f), SC_H(0.5000000000f),
+ SC_H(0.6302776933f), SC_H(0.7053368092f)},
+ {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952533126f),
+ SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870319068f),
+ SC_H(0.6028295755f), SC_H(0.3637394905f)},
+ {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915216f),
+ SC_H(0.2904545665f), SC_H(0.3636668026f), SC_H(0.4512939751f),
+ SC_H(0.5328993797f), SC_H(0.1951362044f)},
+ {SC_H(0.0000000000f), SC_H(0.1057573855f), SC_H(0.1674221754f),
+ SC_H(0.2630588710f), SC_H(0.3274079263f), SC_H(0.4005688727f),
+ SC_H(0.4454405010f), SC_H(0.1242370382f)},
+ {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f),
+ SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f),
+ SC_H(0.3599678576f), SC_H(0.0857512653f)},
+ {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f),
+ SC_H(0.1980977207f), SC_H(0.2429044843f), SC_H(0.2874797881f),
+ SC_H(0.2856767476f), SC_H(0.0617875606f)},
+ {SC_H(0.0000000000f), SC_H(0.0629518107f), SC_H(0.0989024863f),
+ SC_H(0.1520351619f), SC_H(0.1843357235f), SC_H(0.2131874412f),
+ SC_H(0.1990868896f), SC_H(0.0395609401f)},
+ {SC_H(0.0000000000f), SC_H(0.0475566462f), SC_H(0.0744772255f),
+ SC_H(0.1134835184f), SC_H(0.1362429112f), SC_H(0.1546057761f),
+ SC_H(0.1381545961f), SC_H(0.0261824802f)},
+ {SC_H(0.0000000000f), SC_H(0.0352233797f), SC_H(0.0550108962f),
+ SC_H(0.0832019448f), SC_H(0.0990892798f), SC_H(0.1108068526f),
+ SC_H(0.0960334465f), SC_H(0.0176920686f)},
+ {SC_H(0.0000000000f), SC_H(0.0257363524f), SC_H(0.0401044935f),
+ SC_H(0.0602979474f), SC_H(0.0713650808f), SC_H(0.0789347589f),
+ SC_H(0.0669797957f), SC_H(0.0121226516f)},
+ {SC_H(0.0000000000f), SC_H(0.0186282881f), SC_H(0.0289774258f),
+ SC_H(0.0433696248f), SC_H(0.0510888547f), SC_H(0.0560568906f),
+ SC_H(0.0468755886f), SC_H(0.0083869714f)},
+ {SC_H(0.0000000000f), SC_H(0.0107228830f), SC_H(0.0166464727f),
+ SC_H(0.0247849822f), SC_H(0.0290434249f), SC_H(0.0315911621f),
+ SC_H(0.0260186475f), SC_H(0.0046027377f)},
+ {SC_H(0.0000000000f), SC_H(0.0061091576f), SC_H(0.0094724894f),
+ SC_H(0.0140600465f), SC_H(0.0164251942f), SC_H(0.0177771524f),
+ SC_H(0.0145191504f), SC_H(0.0025530567f)},
+ {SC_H(0.0000000000f), SC_H(0.0034606743f), SC_H(0.0053620976f),
+ SC_H(0.0079446994f), SC_H(0.0092647672f), SC_H(0.0099990256f),
+ SC_H(0.0081285043f), SC_H(0.0014247177f)},
+ {SC_H(0.0000000000f), SC_H(0.0019540912f), SC_H(0.0030265225f),
+ SC_H(0.0044795908f), SC_H(0.0052186381f), SC_H(0.0056232223f),
+ SC_H(0.0045594289f), SC_H(0.0007977359f)},
+ {SC_H(0.0000000000f), SC_H(0.0000000149f), SC_H(0.0000000298f),
+ SC_H(0.0000000298f), SC_H(0.0000000000f), SC_H(0.0000000596f),
+ SC_H(0.0000000000f), SC_H(0.0000000000f)}};
+
+/*
+ for (i=0; i<31; i++) {
+ cld = dequantCLD[i];
+ val = (float)(FDKexp(cld/dbe)/(1+FDKexp(cld/dbe)));
+ val = (float)(dbe*FDKlog(val));
+ }
+*/
+#define SCALE_CLD_C1C2(a) (FL2FXCONST_DBL(a / (float)(1 << SF_CLD_C1C2)))
+const FIXP_DBL dequantCLD_c1[31] = {SCALE_CLD_C1C2(-1.5000000000000000e+002f),
+ SCALE_CLD_C1C2(-4.5000137329101563e+001f),
+ SCALE_CLD_C1C2(-4.0000434875488281e+001f),
+ SCALE_CLD_C1C2(-3.5001373291015625e+001f),
+ SCALE_CLD_C1C2(-3.0004341125488281e+001f),
+ SCALE_CLD_C1C2(-2.5013711929321289e+001f),
+ SCALE_CLD_C1C2(-2.2027315139770508e+001f),
+ SCALE_CLD_C1C2(-1.9054332733154297e+001f),
+ SCALE_CLD_C1C2(-1.6107742309570313e+001f),
+ SCALE_CLD_C1C2(-1.3212384223937988e+001f),
+ SCALE_CLD_C1C2(-1.0413927078247070e+001f),
+ SCALE_CLD_C1C2(-8.6389207839965820e+000f),
+ SCALE_CLD_C1C2(-6.9732279777526855e+000f),
+ SCALE_CLD_C1C2(-5.4554042816162109e+000f),
+ SCALE_CLD_C1C2(-4.1244258880615234e+000f),
+ SCALE_CLD_C1C2(-3.0102999210357666e+000f),
+ SCALE_CLD_C1C2(-2.1244258880615234e+000f),
+ SCALE_CLD_C1C2(-1.4554045200347900e+000f),
+ SCALE_CLD_C1C2(-9.7322785854339600e-001f),
+ SCALE_CLD_C1C2(-6.3892036676406860e-001f),
+ SCALE_CLD_C1C2(-4.1392669081687927e-001f),
+ SCALE_CLD_C1C2(-2.1238386631011963e-001f),
+ SCALE_CLD_C1C2(-1.0774217545986176e-001f),
+ SCALE_CLD_C1C2(-5.4333221167325974e-002f),
+ SCALE_CLD_C1C2(-2.7315950021147728e-002f),
+ SCALE_CLD_C1C2(-1.3711934909224510e-002f),
+ SCALE_CLD_C1C2(-4.3406565673649311e-003f),
+ SCALE_CLD_C1C2(-1.3732088264077902e-003f),
+ SCALE_CLD_C1C2(-4.3438826105557382e-004f),
+ SCALE_CLD_C1C2(-1.3745666365139186e-004f),
+ SCALE_CLD_C1C2(0.0000000000000000e+000f)};
+
+/* sac_stp */
+/* none scaled */
+const FIXP_CFG BP__FDK[] = {FL2FXCONST_CFG(0.73919999599457),
+ FL2FXCONST_CFG(0.97909998893738),
+ FL2FXCONST_CFG(0.99930000305176)};
+
+/* scaled with 26 bits */
+const FIXP_CFG BP_GF__FDK[] = {
+ FL2FXCONST_CFG(0.00000000643330), FL2FXCONST_CFG(0.00004396850232),
+ FL2FXCONST_CFG(0.00087456948552), FL2FXCONST_CFG(0.00474648220243),
+ FL2FXCONST_CFG(0.01717987244800), FL2FXCONST_CFG(0.04906742491073),
+ FL2FXCONST_CFG(0.10569518656729), FL2FXCONST_CFG(0.21165767592653),
+ FL2FXCONST_CFG(0.36036762478024), FL2FXCONST_CFG(0.59894182766948),
+ FL2FXCONST_CFG(0.81641678929129), FL2FXCONST_CFG(0.97418481133397),
+ FL2FXCONST_CFG(0.99575411610845), FL2FXCONST_CFG(0.88842666281361),
+ FL2FXCONST_CFG(0.79222317063736), FL2FXCONST_CFG(0.70828604318604),
+ FL2FXCONST_CFG(0.66395054816338), FL2FXCONST_CFG(0.64633739516952),
+ FL2FXCONST_CFG(0.66098278185255)};
+
+/* sac_bitdec */
+const INT samplingFreqTable[16] = {96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ 7350, 0, 0, 0};
+
+const UCHAR freqResTable[] = {0, 28, 20, 14, 10, 7, 5, 4};
+
+const UCHAR freqResTable_LD[] = {0, 23, 15, 12, 9, 7, 5, 4};
+
+const UCHAR tempShapeChanTable[][8] = {{5, 5, 4, 6, 6, 4, 4, 2},
+ {5, 5, 5, 7, 7, 4, 4, 2}};
+
+const TREEPROPERTIES treePropertyTable[] = {
+ {1, 6, 5, 0, {0, 0, 0, 0, 1}}, {1, 6, 5, 0, {0, 0, 1, 0, 0}},
+ {2, 6, 3, 1, {1, 0, 0, 0, 0}}, {2, 8, 5, 1, {1, 0, 0, 0, 0}},
+ {2, 8, 5, 1, {1, 0, 0, 0, 0}}, {6, 8, 2, 0, {0, 0, 0, 0, 0}},
+ {6, 8, 2, 0, {0, 0, 0, 0, 0}}, {1, 2, 1, 0, {0, 0, 0, 0, 0}}};
+
+const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
+
+const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
+
+const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
+
+const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
+
+const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 0, 0, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8,
+ 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
+
+const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19};
+
+const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS] = {
+ 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23,
+ 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27};
+
+const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS] = {
+ 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
+
+const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
+
+const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
+
+const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
+
+const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9,
+ 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
+
+const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12,
+ 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
+
+const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15,
+ 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20,
+ 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22};
+
+const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14};
+
+const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11};
+
+const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8};
+
+const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6};
+
+const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4};
+
+const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD] = {
+ 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3};
+
+const FIXP_CFG clipGainTable__FDK[] = {
+ /*CLIP_PROTECT_GAIN_0(1.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL),
+ CLIP_PROTECT_GAIN_1(1.189207f),
+ CLIP_PROTECT_GAIN_1(1.414213f),
+ CLIP_PROTECT_GAIN_1(1.681792f),
+ /*CLIP_PROTECT_GAIN_1(2.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL),
+ CLIP_PROTECT_GAIN_2(2.378414f),
+ CLIP_PROTECT_GAIN_2(2.828427f),
+ /*CLIP_PROTECT_GAIN_2(4.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)};
+
+const UCHAR clipGainSFTable__FDK[] = {0, 1, 1, 1, 1, 2, 2, 2};
+
+const UCHAR pbStrideTable[] = {1, 2, 5, 28};
+
+const int smgTimeTable[] = {64, 128, 256, 512};
+
+/* table is scaled by factor 0.5 */
+const FIXP_CFG envShapeDataTable__FDK[5][2] = {
+ {FL2FXCONST_CFG(0.25000000000000f), FL2FXCONST_CFG(0.25000000000000f)},
+ {FL2FXCONST_CFG(0.35355339059327f), FL2FXCONST_CFG(0.31498026247372f)},
+ {FL2FXCONST_CFG(0.50000000000000f), FL2FXCONST_CFG(0.39685026299205f)},
+ {FL2FXCONST_CFG(0.70710678118655f), FL2FXCONST_CFG(0.50000000000000f)},
+ {/*FL2FXCONST_CFG( 1.00000000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL),
+ FL2FXCONST_CFG(0.62996052494744f)}};
+
+/* sac_calcM1andM2 */
+const SCHAR row2channelSTP[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 2}, {0, 4},
+ {0, 4}, {0, 2}, {-1, 2}, {0, 1}};
+
+const SCHAR row2channelGES[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 3}, {0, 5},
+ {0, 5}, {0, 2}, {-1, 2}, {0, 1}};
+
+const SCHAR row2residual[][MAX_M2_INPUT] = {{-1, 0}, {-1, 0}, {-1, -1},
+ {-1, -1}, {-1, -1}, {-1, -1},
+ {-1, -1}, {-1, 0}};
+
+/*******************************************************************************
+ Functionname: sac_getCLDValues
+ *******************************************************************************
+
+ Description: Get CLD values from table index.
+
+ Arguments:
+ index: Table index
+ *cu, *cl : Pointer to locations where resulting values will be written to.
+
+ Return: nothing
+
+*******************************************************************************/
+void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl) {
+ *cu = FX_CFG2FX_DBL(dequantCLD_c_l[index]);
+ *cl = FX_CFG2FX_DBL(dequantCLD_c_l[31 - 1 - index]);
+}
+
+void SpatialDequantGetCLD2Values(int idx, FIXP_DBL* x) {
+ *x = FX_CFG2FX_DBL(dequantCLD__FDK[idx]);
+}
diff --git a/libSACdec/src/sac_rom.h b/libSACdec/src/sac_rom.h
new file mode 100644
index 0000000..d366fb6
--- /dev/null
+++ b/libSACdec/src/sac_rom.h
@@ -0,0 +1,230 @@
+/* -----------------------------------------------------------------------------
+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 tables
+
+*******************************************************************************/
+
+#ifndef SAC_ROM_H
+#define SAC_ROM_H
+
+#include "FDK_archdef.h"
+#include "sac_dec_interface.h"
+
+#include "huff_nodes.h"
+#include "sac_bitdec.h"
+#include "machine_type.h"
+
+/* Global ROM table data type: */
+#ifndef ARCH_PREFER_MULT_32x32
+#define FIXP_CFG FIXP_SGL
+#define FX_CFG2FX_DBL FX_SGL2FX_DBL
+#define FX_CFG2FX_SGL
+#define CFG(a) (FX_DBL2FXCONST_SGL(a))
+#define FL2FXCONST_CFG FL2FXCONST_SGL
+#define FX_DBL2FX_CFG(x) FX_DBL2FX_SGL((FIXP_DBL)(x))
+#else
+#define FIXP_CFG FIXP_DBL
+#define FX_CFG2FX_DBL
+#define FX_CFG2FX_SGL FX_DBL2FX_SGL
+#define CFG(a) FIXP_DBL(a)
+#define FL2FXCONST_CFG FL2FXCONST_DBL
+#define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x))
+#endif
+
+/* others */
+#define SCALE_INV_ICC (2)
+#define G_dd_SCALE (2)
+
+#define QCC_SCALE 1
+#define M1M2_DATA FIXP_DBL
+#ifndef ARCH_PREFER_MULT_32x32
+#define M1M2_CDATA FIXP_SGL
+#define M1M2_CDATA2FX_DBL(a) FX_SGL2FX_DBL(a)
+#define FX_DBL2M1M2_CDATA(a) FX_DBL2FX_SGL(a)
+#else
+#define M1M2_CDATA FIXP_DBL
+#define M1M2_CDATA2FX_DBL(a) (a)
+#define FX_DBL2M1M2_CDATA(a) (a)
+#endif
+
+#define CLIP_PROTECT_GAIN_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0)))
+#define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1)))
+#define CLIP_PROTECT_GAIN_2(x) FL2FXCONST_CFG(((x) / (float)(1 << 2)))
+
+#define SF_CLD_C1C2 (8)
+
+extern const FIXP_CFG dequantCPC__FDK[];
+extern const FIXP_CFG dequantICC__FDK[8];
+extern const FIXP_CFG dequantCLD__FDK[31];
+
+#define IPD_SCALE (5)
+#define PI__IPD (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << IPD_SCALE)))
+/* Define for PI*2 for better precision in SpatialDecApplyPhase() */
+#define PIx2__IPD \
+ (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << (IPD_SCALE - 1))))
+
+extern const FIXP_CFG dequantIPD__FDK[16];
+
+extern const FIXP_CFG H11_nc[31][8];
+extern const FIXP_CFG H12_nc[31][8];
+
+extern const FIXP_DBL dequantCLD_c1[31];
+
+extern const FIXP_CFG BP__FDK[];
+extern const FIXP_CFG BP_GF__FDK[];
+extern const SCHAR row2channelSTP[][MAX_M2_INPUT];
+
+/* sac_bitdec */
+extern const INT samplingFreqTable[16];
+extern const UCHAR freqResTable[];
+extern const UCHAR freqResTable_LD[];
+extern const UCHAR tempShapeChanTable[2][8];
+extern const TREEPROPERTIES treePropertyTable[];
+
+extern const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS];
+
+extern const UCHAR mapping_4_to_28[MAX_PARAMETER_BANDS];
+extern const UCHAR mapping_5_to_28[MAX_PARAMETER_BANDS];
+extern const UCHAR mapping_7_to_28[MAX_PARAMETER_BANDS];
+extern const UCHAR mapping_10_to_28[MAX_PARAMETER_BANDS];
+extern const UCHAR mapping_14_to_28[MAX_PARAMETER_BANDS];
+extern const UCHAR mapping_20_to_28[MAX_PARAMETER_BANDS];
+extern const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS];
+extern const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS];
+
+extern const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD];
+extern const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD];
+extern const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD];
+extern const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD];
+extern const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD];
+extern const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD];
+
+extern const FIXP_CFG clipGainTable__FDK[];
+extern const UCHAR clipGainSFTable__FDK[];
+
+extern const UCHAR pbStrideTable[];
+extern const int smgTimeTable[];
+
+extern const FIXP_CFG envShapeDataTable__FDK[5][2];
+extern const SCHAR row2channelGES[][MAX_M2_INPUT];
+
+/* sac_calcM1andM2 */
+extern const SCHAR row2residual[][MAX_M2_INPUT];
+
+void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl);
+
+void SpatialDequantGetCLD2Values(int index, FIXP_DBL* x);
+
+/* External helper functions */
+static inline int SacGetHybridSubbands(int qmfSubbands) {
+ return qmfSubbands - MAX_QMF_BANDS_TO_HYBRID + 10;
+}
+
+#endif /* SAC_ROM_H */
diff --git a/libSACdec/src/sac_smoothing.cpp b/libSACdec/src/sac_smoothing.cpp
new file mode 100644
index 0000000..bee6551
--- /dev/null
+++ b/libSACdec/src/sac_smoothing.cpp
@@ -0,0 +1,295 @@
+/* -----------------------------------------------------------------------------
+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 parameter smoothing
+
+*******************************************************************************/
+
+#include "sac_dec.h"
+#include "sac_bitdec.h"
+#include "sac_smoothing.h"
+#include "sac_rom.h"
+
+/*******************************************************************************
+ Functionname: calcFilterCoeff
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+
+*******************************************************************************/
+static FIXP_DBL calcFilterCoeff__FDK(spatialDec *self, int ps,
+ const SPATIAL_BS_FRAME *frame) {
+ int dSlots;
+ FIXP_DBL delta;
+
+ dSlots = frame->paramSlot[ps] - self->smoothState->prevParamSlot;
+
+ if (dSlots <= 0) {
+ dSlots += self->timeSlots;
+ }
+
+ delta = fDivNorm(dSlots, self->smgTime[ps]);
+
+ return delta;
+}
+
+/*******************************************************************************
+ Functionname: getSmoothOnOff
+ *******************************************************************************
+
+ Description:
+
+ Arguments:
+
+ Input:
+
+ Output:
+
+
+*******************************************************************************/
+static int getSmoothOnOff(spatialDec *self, int ps, int pb) {
+ int smoothBand = 0;
+
+ smoothBand = self->smgData[ps][pb];
+
+ return smoothBand;
+}
+
+void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ int ps) {
+ FIXP_DBL delta__FDK;
+ FIXP_DBL one_minus_delta__FDK;
+
+ int pb, row, col;
+ int residualBands = 0;
+
+ if (self->residualCoding) {
+ int i;
+ int boxes = self->numOttBoxes;
+ for (i = 0; i < boxes; i++) {
+ if (self->residualBands[i] > residualBands) {
+ residualBands = self->residualBands[i];
+ }
+ }
+ }
+
+ delta__FDK = calcFilterCoeff__FDK(self, ps, frame);
+ if (delta__FDK == /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL)
+ one_minus_delta__FDK = FL2FXCONST_DBL(0.0f);
+ else if (delta__FDK == FL2FXCONST_DBL(0.0f))
+ one_minus_delta__FDK = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL;
+ else
+ one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1;
+
+ for (pb = 0; pb < self->numParameterBands; pb++) {
+ int smoothBand;
+
+ smoothBand = getSmoothOnOff(self, ps, pb);
+
+ if (smoothBand && (pb >= residualBands)) {
+ for (row = 0; row < self->numM2rows; row++) {
+ for (col = 0; col < self->numVChannels; col++) {
+ self->M2Real__FDK[row][col][pb] =
+ ((fMultDiv2(delta__FDK, self->M2Real__FDK[row][col][pb]) +
+ fMultDiv2(one_minus_delta__FDK,
+ self->M2RealPrev__FDK[row][col][pb]))
+ << 1);
+ if (0 || (self->phaseCoding == 3)) {
+ self->M2Imag__FDK[row][col][pb] =
+ ((fMultDiv2(delta__FDK, self->M2Imag__FDK[row][col][pb]) +
+ fMultDiv2(one_minus_delta__FDK,
+ self->M2ImagPrev__FDK[row][col][pb]))
+ << 1);
+ }
+ }
+ }
+ }
+ }
+ self->smoothState->prevParamSlot = frame->paramSlot[ps];
+}
+
+/* init states */
+void initParameterSmoothing(spatialDec *self) {
+ self->smoothState->prevParamSlot = 0;
+}
+
+void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ int ps) {
+ int pb;
+ int dSlots;
+ FIXP_DBL delta__FDK;
+ FIXP_DBL one_minus_delta__FDK;
+ FIXP_DBL *phaseLeftSmooth__FDK = self->smoothState->opdLeftState__FDK;
+ FIXP_DBL *phaseRightSmooth__FDK = self->smoothState->opdRightState__FDK;
+ int quantCoarse;
+
+ quantCoarse = frame->IPDLosslessData[0].bsQuantCoarseXXX[ps];
+
+ if (frame->OpdSmoothingMode == 0) {
+ FDKmemcpy(phaseLeftSmooth__FDK, self->PhaseLeft__FDK,
+ self->numParameterBands * sizeof(FIXP_DBL));
+ FDKmemcpy(phaseRightSmooth__FDK, self->PhaseRight__FDK,
+ self->numParameterBands * sizeof(FIXP_DBL));
+ } else {
+ if (ps == 0) {
+ dSlots = frame->paramSlot[ps] + 1;
+ } else {
+ dSlots = frame->paramSlot[ps] - frame->paramSlot[ps - 1];
+ }
+
+ delta__FDK = (FIXP_DBL)((INT)(FL2FXCONST_DBL(0.0078125f)) * dSlots);
+
+ if (delta__FDK == (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/)
+ one_minus_delta__FDK = FL2FXCONST_DBL(0.0f);
+ else if (delta__FDK == FL2FXCONST_DBL(0.0f))
+ one_minus_delta__FDK = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/;
+ else
+ one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1;
+
+ for (pb = 0; pb < self->numParameterBands; pb++) {
+ FIXP_DBL tmpL, tmpR, tmp;
+
+ tmpL = self->PhaseLeft__FDK[pb];
+ tmpR = self->PhaseRight__FDK[pb];
+
+ while (tmpL > phaseLeftSmooth__FDK[pb] + PI__IPD) tmpL -= PI__IPD << 1;
+ while (tmpL < phaseLeftSmooth__FDK[pb] - PI__IPD) tmpL += PI__IPD << 1;
+ while (tmpR > phaseRightSmooth__FDK[pb] + PI__IPD) tmpR -= PI__IPD << 1;
+ while (tmpR < phaseRightSmooth__FDK[pb] - PI__IPD) tmpR += PI__IPD << 1;
+
+ phaseLeftSmooth__FDK[pb] =
+ fMult(delta__FDK, tmpL) +
+ fMult(one_minus_delta__FDK, phaseLeftSmooth__FDK[pb]);
+ phaseRightSmooth__FDK[pb] =
+ fMult(delta__FDK, tmpR) +
+ fMult(one_minus_delta__FDK, phaseRightSmooth__FDK[pb]);
+
+ tmp = (((tmpL >> 1) - (tmpR >> 1)) - ((phaseLeftSmooth__FDK[pb] >> 1) -
+ (phaseRightSmooth__FDK[pb] >> 1)))
+ << 1;
+ while (tmp > PI__IPD) tmp -= PI__IPD << 1;
+ while (tmp < -PI__IPD) tmp += PI__IPD << 1;
+ if (fixp_abs(tmp) > fMult((quantCoarse ? FL2FXCONST_DBL(50.f / 180.f)
+ : FL2FXCONST_DBL(25.f / 180.f)),
+ PI__IPD)) {
+ phaseLeftSmooth__FDK[pb] = tmpL;
+ phaseRightSmooth__FDK[pb] = tmpR;
+ }
+
+ while (phaseLeftSmooth__FDK[pb] > PI__IPD << 1)
+ phaseLeftSmooth__FDK[pb] -= PI__IPD << 1;
+ while (phaseLeftSmooth__FDK[pb] < (FIXP_DBL)0)
+ phaseLeftSmooth__FDK[pb] += PI__IPD << 1;
+ while (phaseRightSmooth__FDK[pb] > PI__IPD << 1)
+ phaseRightSmooth__FDK[pb] -= PI__IPD << 1;
+ while (phaseRightSmooth__FDK[pb] < (FIXP_DBL)0)
+ phaseRightSmooth__FDK[pb] += PI__IPD << 1;
+
+ self->PhaseLeft__FDK[pb] = phaseLeftSmooth__FDK[pb];
+ self->PhaseRight__FDK[pb] = phaseRightSmooth__FDK[pb];
+ }
+ }
+ return;
+}
diff --git a/libSACdec/src/sac_smoothing.h b/libSACdec/src/sac_smoothing.h
new file mode 100644
index 0000000..fdf3f5b
--- /dev/null
+++ b/libSACdec/src/sac_smoothing.h
@@ -0,0 +1,114 @@
+/* -----------------------------------------------------------------------------
+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 parameter smoothing
+
+*******************************************************************************/
+
+#ifndef SAC_SMOOTHING_H
+#define SAC_SMOOTHING_H
+
+#include "sac_dec.h"
+
+void initParameterSmoothing(spatialDec *self);
+void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ int ps);
+void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame,
+ int ps);
+
+#endif
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
new file mode 100644
index 0000000..818e9df
--- /dev/null
+++ b/libSACdec/src/sac_stp.cpp
@@ -0,0 +1,548 @@
+/* -----------------------------------------------------------------------------
+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 subband processing
+
+*******************************************************************************/
+
+#include "sac_stp.h"
+#include "sac_calcM1andM2.h"
+#include "sac_bitdec.h"
+#include "FDK_matrixCalloc.h"
+#include "sac_rom.h"
+
+#define BP_GF_START 6
+#define BP_GF_SIZE 25
+#define HP_SIZE 9
+#define STP_UPDATE_ENERGY_RATE 32
+
+#define SF_WET 5
+#define SF_DRY \
+ 3 /* SF_DRY == 2 would produce good conformance test results as well */
+#define SF_PRODUCT_BP_GF 13
+#define SF_PRODUCT_BP_GF_GF 26
+#define SF_SCALE 2
+
+#define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125) /* LD64((1<<SF_SCALE))*/
+#define STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.950f) /* 0.95 */
+#define ONE_MINUS_STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.05f) /* 1.0 - 0.95 */
+#define STP_LPF_COEFF2__FDK FL2FXCONST_DBL(0.450f) /* 0.45 */
+#define ONE_MINUS_STP_LPF_COEFF2__FDK \
+ FL2FXCONST_DBL(1.0f - 0.450f) /* 1.0 - 0.45 */
+#define STP_SCALE_LIMIT__FDK \
+ FL2FXCONST_DBL(2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE */
+#define ONE_DIV_STP_SCALE_LIMIT__FDK \
+ FL2FXCONST_DBL(1.0f / 2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE \
+ */
+#define ABS_THR__FDK \
+ FL2FXCONST_DBL(ABS_THR / \
+ ((float)(1 << (22 + 22 - 26)))) /* scaled by 18 bits */
+#define ABS_THR2__FDK \
+ FL2FXCONST_DBL(ABS_THR * 32.0f * 32.0f / \
+ ((float)(1 << (22 + 22 - 26)))) /* scaled by 10 bits */
+#define STP_SCALE_LIMIT_HI \
+ FL2FXCONST_DBL(3.02222222222 / (1 << SF_SCALE)) /* see 4. below */
+#define STP_SCALE_LIMIT_LO \
+ FL2FXCONST_DBL(0.28289992119 / (1 << SF_SCALE)) /* see 4. below */
+#define STP_SCALE_LIMIT_HI_LD64 \
+ FL2FXCONST_DBL(0.04986280452) /* see 4. below \
+ */
+#define STP_SCALE_LIMIT_LO_LD64 \
+ FL2FXCONST_DBL(0.05692613500) /* see 4. below \
+ */
+
+/* Scale factor calculation for the diffuse signal needs adapted thresholds
+ for STP_SCALE_LIMIT and 1/STP_SCALE_LIMIT:
+
+ 1. scale = sqrt(DryNrg/WetNrg)
+
+ 2. Damping of scale factor
+ scale2 = 0.1 + 0.9 * scale
+
+ 3. Limiting of scale factor
+ STP_SCALE_LIMIT >= scale2 >= 1/STP_SCALE_LIMIT
+ => STP_SCALE_LIMIT >= (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT
+ => (STP_SCALE_LIMIT-0.1)/0.9 >= scale >=
+ (1/STP_SCALE_LIMIT-0.1)/0.9
+
+ 3. Limiting of scale factor before sqrt calculation
+ ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >=
+ ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2 >= (scale^2) >=
+ (STP_SCALE_LIMIT_LO)^2
+
+ 4. Thresholds for limiting of scale factor
+ STP_SCALE_LIMIT_HI = ((2.82-0.1)/0.9)
+ STP_SCALE_LIMIT_LO = (((1.0/2.82)-0.1)/0.9)
+ STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI)
+ STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
+*/
+
+#define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx
+
+#define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx
+
+#define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \
+ DryEner += \
+ fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2)
+
+#define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \
+ DryEner += fMultDiv2( \
+ fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n])
+
+#define CALC_WET_SCALE(dryIdx, wetIdx) \
+ if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \
+ scale[wetIdx] = STP_SCALE_LIMIT_HI; \
+ } else if (DryEnerLD64[dryIdx] < \
+ (WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) { \
+ scale[wetIdx] = STP_SCALE_LIMIT_LO; \
+ } else { \
+ tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64; \
+ scale[wetIdx] = CalcInvLdData(tmp); \
+ }
+
+struct STP_DEC {
+ FIXP_DBL runDryEner[MAX_INPUT_CHANNELS];
+ FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS];
+ FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS];
+ FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS];
+ FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS];
+ const FIXP_CFG *BP;
+ const FIXP_CFG *BP_GF;
+ int update_old_ener;
+};
+
+inline void combineSignalReal(FIXP_DBL *hybOutputRealDry,
+ FIXP_DBL *hybOutputRealWet, int bands) {
+ int n;
+
+ for (n = bands - 1; n >= 0; n--) {
+ *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
+ hybOutputRealDry++, hybOutputRealWet++;
+ }
+}
+
+inline void combineSignalRealScale1(FIXP_DBL *hybOutputRealDry,
+ FIXP_DBL *hybOutputRealWet, FIXP_DBL scaleX,
+ int bands) {
+ int n;
+
+ for (n = bands - 1; n >= 0; n--) {
+ *hybOutputRealDry =
+ *hybOutputRealDry +
+ (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
+ hybOutputRealDry++, hybOutputRealWet++;
+ }
+}
+
+inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry,
+ FIXP_DBL *hybOutputImagDry,
+ FIXP_DBL *hybOutputRealWet,
+ FIXP_DBL *hybOutputImagWet, int bands) {
+ int n;
+
+ for (n = bands - 1; n >= 0; n--) {
+ *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
+ *hybOutputImagDry = *hybOutputImagDry + *hybOutputImagWet;
+ hybOutputRealDry++, hybOutputRealWet++;
+ hybOutputImagDry++, hybOutputImagWet++;
+ }
+}
+
+inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
+ FIXP_DBL *hybOutputImagDry,
+ FIXP_DBL *hybOutputRealWet,
+ FIXP_DBL *hybOutputImagWet,
+ const FIXP_CFG *pBP, FIXP_DBL scaleX,
+ int bands) {
+ int n;
+ FIXP_DBL scaleY;
+ for (n = bands - 1; n >= 0; n--) {
+ scaleY = fMultDiv2(scaleX, *pBP);
+ *hybOutputRealDry =
+ *hybOutputRealDry +
+ (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 2));
+ *hybOutputImagDry =
+ *hybOutputImagDry +
+ (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 2));
+ hybOutputRealDry++, hybOutputRealWet++;
+ hybOutputImagDry++, hybOutputImagWet++;
+ pBP++;
+ }
+}
+
+inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
+ FIXP_DBL *hybOutputImagDry,
+ FIXP_DBL *hybOutputRealWet,
+ FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
+ int bands) {
+ int n;
+
+ for (n = bands - 1; n >= 0; n--) {
+ *hybOutputRealDry =
+ *hybOutputRealDry +
+ (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
+ *hybOutputImagDry =
+ *hybOutputImagDry +
+ (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
+ hybOutputRealDry++, hybOutputRealWet++;
+ hybOutputImagDry++, hybOutputImagWet++;
+ }
+}
+
+/*******************************************************************************
+ Functionname: subbandTPCreate
+ ******************************************************************************/
+SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
+ HANDLE_STP_DEC self = NULL;
+ FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
+ if (hStpDec != NULL) {
+ *hStpDec = self;
+ }
+
+ return MPS_OK;
+bail:
+ return MPS_OUTOFMEMORY;
+}
+
+SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
+ SACDEC_ERROR err = MPS_OK;
+ int ch;
+
+ for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
+ self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
+ self->oldWetEnerLD64[ch] =
+ FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */
+ }
+ for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
+ self->oldDryEnerLD64[ch] =
+ FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */
+ }
+
+ self->BP = BP__FDK;
+ self->BP_GF = BP_GF__FDK;
+
+ self->update_old_ener = 0;
+
+ return err;
+}
+
+/*******************************************************************************
+ Functionname: subbandTPDestroy
+ ******************************************************************************/
+void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
+ if (hStpDec != NULL) {
+ FDK_FREE_MEMORY_1D(*hStpDec);
+ }
+}
+
+/*******************************************************************************
+ Functionname: subbandTPApply
+ ******************************************************************************/
+SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
+ FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
+ FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
+ FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
+ FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
+
+ FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
+ FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
+
+ FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
+ FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
+
+ FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
+ FIXP_DBL WetEnerX, damp, tmp;
+ FIXP_DBL dmxReal0, dmxImag0;
+ int skipChannels[MAX_OUTPUT_CHANNELS];
+ int n, ch, cplxBands, cplxHybBands;
+ int dry_scale_dmx, wet_scale_dmx;
+ int i_LF, i_RF;
+ HANDLE_STP_DEC hStpDec;
+ const FIXP_CFG *pBP;
+
+ int nrgScale = (2 * self->clipProtectGainSF__FDK);
+
+ hStpDec = self->hStpDec;
+
+ /* set scalefactor and loop counter */
+ FDK_ASSERT(SF_DRY >= 1);
+ {
+ cplxBands = BP_GF_SIZE;
+ cplxHybBands = self->hybridBands;
+ dry_scale_dmx = (2 * SF_DRY) - 2;
+ wet_scale_dmx = 2;
+ }
+
+ /* setup pointer for forming the direct downmix signal */
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
+ qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
+ qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
+ qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
+ }
+
+ /* clear skipping flag for all output channels */
+ FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
+
+ /* set scale values to zero */
+ FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
+
+ /* update normalisation energy with latest smoothed energy */
+ if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
+ hStpDec->update_old_ener = 1;
+ for (ch = 0; ch < self->numInputChannels; ch++) {
+ hStpDec->oldDryEnerLD64[ch] =
+ CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
+ }
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ hStpDec->oldWetEnerLD64[ch] =
+ CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
+ }
+ } else {
+ hStpDec->update_old_ener++;
+ }
+
+ /* get channel configuration */
+ switch (self->treeConfig) {
+ case TREE_212:
+ i_LF = 0;
+ i_RF = 1;
+ break;
+ default:
+ return MPS_WRONG_TREECONFIG;
+ }
+
+ /* form the 'direct' downmix signal */
+ pBP = hStpDec->BP_GF - BP_GF_START;
+ switch (self->treeConfig) {
+ case TREE_212:
+ for (n = BP_GF_START; n < cplxBands; n++) {
+ dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n];
+ dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n];
+ DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n);
+ }
+ DRY_ENER_WEIGHT(DryEner0);
+ break;
+ default:;
+ }
+ DryEner[0] = DryEner0;
+
+ /* normalise the 'direct' signals */
+ for (ch = 0; ch < self->numInputChannels; ch++) {
+ DryEner[ch] = DryEner[ch] << (nrgScale);
+ hStpDec->runDryEner[ch] =
+ fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
+ fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
+ if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
+ DryEnerLD64[ch] =
+ fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
+ FL2FXCONST_DBL(-0.484375f));
+ } else {
+ DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
+ }
+ }
+ if (self->treeConfig == TREE_212) {
+ for (; ch < MAX_INPUT_CHANNELS; ch++) {
+ DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
+ }
+ }
+
+ /* normalise the 'diffuse' signals */
+ pBP = hStpDec->BP_GF - BP_GF_START;
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ if (skipChannels[ch]) {
+ continue;
+ }
+
+ WetEnerX = FL2FXCONST_DBL(0.0f);
+ for (n = BP_GF_START; n < cplxBands; n++) {
+ tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET);
+ tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET);
+ WetEnerX += fMultDiv2(tmp, pBP[n]);
+ }
+ WET_ENER_WEIGHT(WetEnerX);
+
+ WetEnerX = WetEnerX << (nrgScale);
+ hStpDec->runWetEner[ch] =
+ fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
+ fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
+
+ if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
+ WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
+ } else {
+ WetEnerLD64[ch] =
+ fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
+ FL2FXCONST_DBL(-0.484375f));
+ }
+ }
+
+ /* compute scale factor for the 'diffuse' signals */
+ switch (self->treeConfig) {
+ case TREE_212:
+ if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
+ CALC_WET_SCALE(0, i_LF);
+ CALC_WET_SCALE(0, i_RF);
+ }
+ break;
+ default:;
+ }
+
+ damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ /* damp the scaling factor */
+ scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
+
+ /* limiting the scale factor */
+ if (scale[ch] > STP_SCALE_LIMIT__FDK) {
+ scale[ch] = STP_SCALE_LIMIT__FDK;
+ }
+ if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
+ scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
+ }
+
+ /* low pass filter the scaling factor */
+ scale[ch] =
+ fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
+ fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
+ hStpDec->prev_tp_scale[ch] = scale[ch];
+ }
+
+ /* combine 'direct' and scaled 'diffuse' signal */
+ FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
+ const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
+
+ for (ch = 0; ch < self->numOutputChannels; ch++) {
+ int no_scaling;
+
+ no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
+ if (no_scaling) {
+ combineSignalCplx(
+ &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
+ cplxHybBands - self->tp_hybBandBorder);
+
+ } else {
+ FIXP_DBL scaleX;
+ scaleX = scale[ch];
+ pBP = hStpDec->BP - self->tp_hybBandBorder;
+ /* Band[HP_SIZE-3+10-1] needs not to be processed in
+ combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
+ combineSignalCplxScale1(
+ &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
+ &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
+ &pBP[self->tp_hybBandBorder], scaleX,
+ (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
+
+ {
+ combineSignalCplxScale2(
+ &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
+ &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
+ &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
+ &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
+ cplxHybBands - (HP_SIZE - 3 + 10 - 1));
+ }
+ }
+ }
+
+ return (SACDEC_ERROR)MPS_OK;
+ ;
+}
diff --git a/libSACdec/src/sac_stp.h b/libSACdec/src/sac_stp.h
new file mode 100644
index 0000000..18471bd
--- /dev/null
+++ b/libSACdec/src/sac_stp.h
@@ -0,0 +1,115 @@
+/* -----------------------------------------------------------------------------
+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 subband processing
+
+*******************************************************************************/
+
+#ifndef SAC_STP_H
+#define SAC_STP_H
+
+#include "sac_dec.h"
+
+SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec);
+
+SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self);
+
+SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame);
+void subbandTPDestroy(HANDLE_STP_DEC *hStpDec);
+
+#endif
diff --git a/libSACdec/src/sac_tsd.cpp b/libSACdec/src/sac_tsd.cpp
new file mode 100644
index 0000000..30acca8
--- /dev/null
+++ b/libSACdec/src/sac_tsd.cpp
@@ -0,0 +1,353 @@
+/* -----------------------------------------------------------------------------
+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): Matthias Hildenbrand
+
+ Description: USAC MPS212 Transient Steering Decorrelator (TSD)
+
+*******************************************************************************/
+
+#include "sac_tsd.h"
+
+#define TSD_START_BAND (7)
+#define SIZE_S (4)
+#define SIZE_C (5)
+
+/*** Tables ***/
+RAM_ALIGN
+LNK_SECTION_CONSTDATA
+static const UCHAR nBitsTsdCW_32slots[32] = {
+ 5, 9, 13, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 29, 30, 30,
+ 30, 29, 29, 28, 27, 26, 25, 24, 22, 20, 18, 16, 13, 9, 5, 0};
+
+RAM_ALIGN
+LNK_SECTION_CONSTDATA
+static const UCHAR nBitsTsdCW_64slots[64] = {
+ 6, 11, 16, 20, 23, 27, 30, 33, 35, 38, 40, 42, 44, 46, 48, 49,
+ 51, 52, 53, 55, 56, 57, 58, 58, 59, 60, 60, 60, 61, 61, 61, 61,
+ 61, 61, 61, 60, 60, 60, 59, 58, 58, 57, 56, 55, 53, 52, 51, 49,
+ 48, 46, 44, 42, 40, 38, 35, 33, 30, 27, 23, 20, 16, 11, 6, 0};
+
+RAM_ALIGN
+LNK_SECTION_CONSTDATA
+static const FIXP_STP phiTsd[8] = {
+ STCP(0x7fffffff, 0x00000000), STCP(0x5a82799a, 0x5a82799a),
+ STCP(0x00000000, 0x7fffffff), STCP(0xa57d8666, 0x5a82799a),
+ STCP(0x80000000, 0x00000000), STCP(0xa57d8666, 0xa57d8666),
+ STCP(0x00000000, 0x80000000), STCP(0x5a82799a, 0xa57d8666),
+};
+
+/*** Static Functions ***/
+static void longmult1(USHORT a[], USHORT b, USHORT d[], int len) {
+ int k;
+ ULONG tmp;
+ ULONG b0 = (ULONG)b;
+
+ tmp = ((ULONG)a[0]) * b0;
+ d[0] = (USHORT)tmp;
+
+ for (k = 1; k < len; k++) {
+ tmp = (tmp >> 16) + ((ULONG)a[k]) * b0;
+ d[k] = (USHORT)tmp;
+ }
+}
+
+static void longdiv(USHORT b[], USHORT a, USHORT d[], USHORT *pr, int len) {
+ ULONG r;
+ ULONG tmp;
+ int k;
+
+ FDK_ASSERT(a != 0);
+
+ r = 0;
+
+ for (k = len - 1; k >= 0; k--) {
+ tmp = ((ULONG)b[k]) + (r << 16);
+
+ if (tmp) {
+ d[k] = (USHORT)(tmp / a);
+ r = tmp - d[k] * a;
+ } else {
+ d[k] = 0;
+ }
+ }
+ *pr = (USHORT)r;
+}
+
+static void longsub(USHORT a[], USHORT b[], int lena, int lenb) {
+ int h;
+ LONG carry = 0;
+
+ FDK_ASSERT(lena >= lenb);
+ for (h = 0; h < lenb; h++) {
+ carry += ((LONG)a[h]) - ((LONG)b[h]);
+ a[h] = (USHORT)carry;
+ carry = carry >> 16;
+ }
+
+ for (; h < lena; h++) {
+ carry = ((LONG)a[h]) + carry;
+ a[h] = (USHORT)carry;
+ carry = carry >> 16;
+ }
+
+ FDK_ASSERT(carry ==
+ 0); /* carry != 0 indicates subtraction underflow, e.g. b > a */
+ return;
+}
+
+static int longcompare(USHORT a[], USHORT b[], int len) {
+ int i;
+
+ for (i = len - 1; i > 0; i--) {
+ if (a[i] != b[i]) break;
+ }
+ return (a[i] >= b[i]) ? 1 : 0;
+}
+
+FDK_INLINE int isTrSlot(const TSD_DATA *pTsdData, const int ts) {
+ return (pTsdData->bsTsdTrPhaseData[ts] >= 0);
+}
+
+/*** Public Functions ***/
+int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData) {
+ int nBitsTrSlots = 0;
+ int bsTsdNumTrSlots;
+ const UCHAR *nBitsTsdCW_tab = NULL;
+
+ switch (numSlots) {
+ case 32:
+ nBitsTrSlots = 4;
+ nBitsTsdCW_tab = nBitsTsdCW_32slots;
+ break;
+ case 64:
+ nBitsTrSlots = 5;
+ nBitsTsdCW_tab = nBitsTsdCW_64slots;
+ break;
+ default:
+ return 1;
+ }
+
+ /*** Read TempShapeData for bsTempShapeConfig == 3 ***/
+ pTsdData->bsTsdEnable = FDKreadBit(hBs);
+ if (!pTsdData->bsTsdEnable) {
+ return 0;
+ }
+
+ /*** Parse/Decode TsdData() ***/
+ pTsdData->numSlots = numSlots;
+
+ bsTsdNumTrSlots = FDKreadBits(hBs, nBitsTrSlots);
+
+ /* Decode transient slot positions */
+ {
+ int nBitsTsdCW = (int)nBitsTsdCW_tab[bsTsdNumTrSlots];
+ SCHAR *phaseData = pTsdData->bsTsdTrPhaseData;
+ int p = bsTsdNumTrSlots + 1;
+ int k, h;
+ USHORT s[SIZE_S] = {0};
+ USHORT c[SIZE_C] = {0};
+ USHORT r[1];
+
+ /* Init with TsdSepData[k] = 0 */
+ for (k = 0; k < numSlots; k++) {
+ phaseData[k] = -1; /* means TsdSepData[] = 0 */
+ }
+
+ for (h = (SIZE_S - 1); h >= 0; h--) {
+ if (nBitsTsdCW > h * 16) {
+ s[h] = (USHORT)FDKreadBits(hBs, nBitsTsdCW - h * 16);
+ nBitsTsdCW = h * 16;
+ }
+ }
+
+ /* c = prod_{h=1}^{p} (k-p+h)/h */
+ k = numSlots - 1;
+ c[0] = k - p + 1;
+ for (h = 2; h <= p; h++) {
+ longmult1(c, (k - p + h), c, 5); /* c *= k - p + h; */
+ longdiv(c, h, c, r, 5); /* c /= h; */
+ FDK_ASSERT(*r == 0);
+ }
+
+ /* go through all slots */
+ for (; k >= 0; k--) {
+ if (p > k) {
+ for (; k >= 0; k--) {
+ phaseData[k] = 1; /* means TsdSepData[] = 1 */
+ }
+ break;
+ }
+ if (longcompare(s, c, 4)) { /* (s >= c) */
+ longsub(s, c, 4, 4); /* s -= c; */
+ phaseData[k] = 1; /* means TsdSepData[] = 1 */
+ if (p == 1) {
+ break;
+ }
+ /* Update c for next iteration: c_new = c_old * p / k */
+ longmult1(c, p, c, 5);
+ p--;
+ } else {
+ /* Update c for next iteration: c_new = c_old * (k-p) / k */
+ longmult1(c, (k - p), c, 5);
+ }
+ longdiv(c, k, c, r, 5);
+ FDK_ASSERT(*r == 0);
+ }
+
+ /* Read phase data */
+ for (k = 0; k < numSlots; k++) {
+ if (phaseData[k] == 1) {
+ phaseData[k] = FDKreadBits(hBs, 3);
+ }
+ }
+ }
+
+ return 0;
+}
+
+void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData,
+ const int ts, FIXP_DBL *pVdirectReal,
+ FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal,
+ FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal,
+ FIXP_DBL **ppDecorrInImag) {
+ int k = 0;
+
+ if (!isTrSlot(pTsdData, ts)) {
+ /* Let allpass based decorrelator read from direct input. */
+ *ppDecorrInReal = pVdirectReal;
+ *ppDecorrInImag = pVdirectImag;
+ return;
+ }
+
+ /* Generate nonTr input signal for allpass based decorrelator */
+ for (; k < TSD_START_BAND; k++) {
+ pVnonTrReal[k] = pVdirectReal[k];
+ pVnonTrImag[k] = pVdirectImag[k];
+ }
+ for (; k < numHybridBands; k++) {
+ pVnonTrReal[k] = (FIXP_DBL)0;
+ pVnonTrImag[k] = (FIXP_DBL)0;
+ }
+ *ppDecorrInReal = pVnonTrReal;
+ *ppDecorrInImag = pVnonTrImag;
+}
+
+void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs,
+ const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag,
+ FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag) {
+ const int ts = *pTsdTs;
+
+ if (isTrSlot(pTsdData, ts)) {
+ int k;
+ const FIXP_STP *phi = &phiTsd[pTsdData->bsTsdTrPhaseData[ts]];
+ FDK_ASSERT((pTsdData->bsTsdTrPhaseData[ts] >= 0) &&
+ (pTsdData->bsTsdTrPhaseData[ts] < 8));
+
+ /* d = d_nonTr + v_direct * exp(j * bsTsdTrPhaseData[ts]/4 * pi ) */
+ for (k = TSD_START_BAND; k < numHybridBands; k++) {
+ FIXP_DBL tempReal, tempImag;
+ cplxMult(&tempReal, &tempImag, pVdirectReal[k], pVdirectImag[k], *phi);
+ pDnonTrReal[k] += tempReal;
+ pDnonTrImag[k] += tempImag;
+ }
+ }
+
+ /* The modulo MAX_TSD_TIME_SLOTS operation is to avoid illegal memory accesses
+ * in case of errors. */
+ *pTsdTs = (ts + 1) & (MAX_TSD_TIME_SLOTS - 1);
+ return;
+}
diff --git a/libSACdec/src/sac_tsd.h b/libSACdec/src/sac_tsd.h
new file mode 100644
index 0000000..2521e27
--- /dev/null
+++ b/libSACdec/src/sac_tsd.h
@@ -0,0 +1,167 @@
+/* -----------------------------------------------------------------------------
+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): Matthias Hildenbrand
+
+ Description: USAC MPS212 Transient Steering Decorrelator (TSD)
+
+*******************************************************************************/
+
+#ifndef SAC_TSD_H
+#define SAC_TSD_H
+
+#include "FDK_bitstream.h"
+#include "common_fix.h"
+
+#define MAX_TSD_TIME_SLOTS (64)
+
+/** Structure which holds the data needed to apply TSD to current frame. */
+typedef struct {
+ UCHAR bsTsdEnable; /**< for current frame TSD is (0:disabled, 1:enabled) */
+ UCHAR numSlots; /**< total number of QMF slots per frame */
+ SCHAR
+ bsTsdTrPhaseData[MAX_TSD_TIME_SLOTS]; /**< -1 => TsdSepData[ts]=0; 0-7:
+ values of bsTsdTrPhaseData[ts]
+ and TsdSepData[ts]=1 */
+} TSD_DATA;
+
+FDK_INLINE int isTsdActive(const TSD_DATA *pTsdData) {
+ return (int)pTsdData->bsTsdEnable;
+}
+
+/**
+ * \brief Parse and Decode TSD data.
+ * \param[in] hBs bitstream handle to read data from.
+ * \param[in] numSlots number of QMF slots per frame.
+ * \param[out] pTsdData pointer to TSD data structure.
+ * \return 0 on succes, 1 on error.
+ */
+int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData);
+
+/**
+ * \brief Perform transient seperation (v_{x,nonTr} signal).
+ * \param[in] numHybridBands number of hybrid bands.
+ * \param[in] pTsdData pointer to TSD data structure.
+ * \param[in] pVdirectReal pointer to array with direct signal.
+ * \param[in] pVdirectImag pointer to array with direct signal.
+ * \param[out] pVnonTrReal pointer to array with nonTr signal.
+ * \param[out] pVnonTrImag pointer to array with nonTr signal.
+ * \param[out] ppDecorrInReal handle to array where allpass based decorrelator
+ * should read from (modified by this function).
+ * \param[out] ppDecorrInImag handle to array where allpass based decorrelator
+ * should read from (modified by this function).
+ */
+void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData,
+ const int ts, FIXP_DBL *pVdirectReal,
+ FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal,
+ FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal,
+ FIXP_DBL **ppDecorrInImag);
+
+/**
+ * \brief Generate d_{x,Tr} signal and add to d_{x,nonTr} signal
+ * \param[in] numHybridBands
+ * \param[in,out] pTsdData
+ * \param pTsdTs pointer to persistent time slot counter
+ * \param[in] pVdirectReal
+ * \param[in] pVdirectImag
+ * \param[out] pDnonTrReal
+ * \param[out] pDnonTrImag
+ */
+void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs,
+ const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag,
+ FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag);
+
+#endif /* #ifndef SAC_TSD_H */