DO NOT MERGE - Merge pi-platform-release (PPRL.190205.001) into stage-aosp-master

Bug: 124234733
Change-Id: I7ed72a237fd7f0aa984b8077a369a1ddb5ba253b
diff --git a/Android.bp b/Android.bp
index c89a95c..dce6fdd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,9 +22,14 @@
         "-Wno-#warnings",
         "-Wuninitialized",
         "-Wno-self-assign",
+        "-Wno-implicit-fallthrough",
     ],
     sanitize: {
-        misc_undefined:["unsigned-integer-overflow", "signed-integer-overflow"],
+        misc_undefined:[
+           "unsigned-integer-overflow",
+           "signed-integer-overflow",
+           "bounds",
+        ],
         cfi: true,
     },
     shared_libs: [
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
index 1d5aa27..d2bc867 100644
--- a/libAACdec/src/aacdec_hcrs.cpp
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -367,7 +367,10 @@
   UINT tempWord;
   USHORT numValidSegment;
 
-  *pNumWordForBitfield = ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1;
+  *pNumWordForBitfield =
+      (*pNumSegment == 0)
+          ? 0
+          : ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1;
 
   /* loop over all words, which are completely used or only partial */
   /* bit in pSegmentBitfield is zero if segment is empty; bit in
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 24907ee..8f03328 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -234,7 +234,8 @@
               MODE_HQ))) { /* MPS decoder does support the requested mode. */
           break;
         }
-      } /* Fall-through: */
+      }
+        FDK_FALLTHROUGH;
       default:
         if (self->qmfModeUser == NOT_DEFINED) {
           /* Revert in case mpegSurroundDecoder_SetParam() fails. */
@@ -538,13 +539,7 @@
                     sizeof(CProgramConfig)); /* Store the complete PCE */
           pceStatus = 1; /* New PCE but no change of config */
           break;
-        case 2: /* The number of channels are identical but not the config */
-          if (channelConfig == 0) {
-            FDKmemcpy(pce, tmpPce,
-                      sizeof(CProgramConfig)); /* Store the complete PCE */
-            pceStatus = 2; /* Decoder needs re-configuration */
-          }
-          break;
+        case 2:  /* The number of channels are identical but not the config */
         case -1: /* The channel configuration is completely different */
           pceStatus = -1; /* Not supported! */
           break;
@@ -775,7 +770,7 @@
     /* For every AU get length and offset in the bitstream */
     prerollAULength[i] = escapedValue(hBs, 16, 16, 0);
     if (prerollAULength[i] > 0) {
-      prerollAUOffset[i] = auStartAnchor - FDKgetValidBits(hBs);
+      prerollAUOffset[i] = auStartAnchor - (INT)FDKgetValidBits(hBs);
       independencyFlag = FDKreadBit(hBs);
       if (i == 0 && !independencyFlag) {
         *numPrerollAU = 0;
@@ -938,6 +933,7 @@
 
     case EXT_SBR_DATA_CRC:
       crcFlag = 1;
+      FDK_FALLTHROUGH;
     case EXT_SBR_DATA:
       if (IS_CHANNEL_ELEMENT(previous_element)) {
         SBR_ERROR sbrError;
@@ -1076,6 +1072,7 @@
          * intentional. */
         break;
       }
+      FDK_FALLTHROUGH;
 
     case EXT_FIL:
 
@@ -1108,12 +1105,13 @@
   /* get the remaining bits of this frame */
   bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
 
-  if ((bitCnt > 0) && (self->flags[0] & AC_SBR_PRESENT) &&
+  if ((self->flags[0] & AC_SBR_PRESENT) &&
       (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD | AC_DRM))) {
     SBR_ERROR err = SBRDEC_OK;
     int chElIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE] +
                                  el_cnt[ID_LFE] + el_cnt[ID_USAC_SCE] +
                                  el_cnt[ID_USAC_CPE] + el_cnt[ID_USAC_LFE];
+    INT bitCntTmp = bitCnt;
 
     if (self->flags[0] & AC_USAC) {
       chElIdx = numChElements - 1;
@@ -1123,6 +1121,7 @@
 
     for (; chElIdx < numChElements; chElIdx += 1) {
       MP4_ELEMENT_ID sbrType;
+      SBR_ERROR errTmp;
       if (self->flags[0] & (AC_USAC)) {
         FDK_ASSERT((self->elements[element_index] == ID_USAC_SCE) ||
                    (self->elements[element_index] == ID_USAC_CPE));
@@ -1132,19 +1131,21 @@
                       : ID_SCE;
       } else
         sbrType = self->elements[chElIdx];
-      err = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer,
-                             self->drmBsBufferSize, &bitCnt, -1,
-                             self->flags[0] & AC_SBRCRC, sbrType, chElIdx,
-                             self->flags[0], self->elFlags);
-      if (err != SBRDEC_OK) {
-        break;
+      errTmp = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer,
+                                self->drmBsBufferSize, &bitCnt, -1,
+                                self->flags[0] & AC_SBRCRC, sbrType, chElIdx,
+                                self->flags[0], self->elFlags);
+      if (errTmp != SBRDEC_OK) {
+        err = errTmp;
+        bitCntTmp = bitCnt;
+        bitCnt = 0;
       }
     }
     switch (err) {
       case SBRDEC_PARSE_ERROR:
         /* Can not go on parsing because we do not
             know the length of the SBR extension data. */
-        FDKpushFor(bs, bitCnt);
+        FDKpushFor(bs, bitCntTmp);
         bitCnt = 0;
         break;
       case SBRDEC_OK:
@@ -1495,11 +1496,13 @@
   switch (asc->m_aot) {
     case AOT_AAC_LC:
       self->streamInfo.profile = 1;
+      FDK_FALLTHROUGH;
     case AOT_ER_AAC_SCAL:
       if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) {
         /* aac_scalable_extension_element() currently not supported. */
         return AAC_DEC_UNSUPPORTED_FORMAT;
       }
+      FDK_FALLTHROUGH;
     case AOT_SBR:
     case AOT_PS:
     case AOT_ER_AAC_LC:
@@ -3024,9 +3027,11 @@
     aacChannels = 0;
   }
 
-  if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) {
-    ErrorStatus = AAC_DEC_CRC_ERROR;
-    self->frameOK = 0;
+  if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
+    if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) {
+      ErrorStatus = AAC_DEC_CRC_ERROR;
+      self->frameOK = 0;
+    }
   }
 
   /* Ensure that in case of concealment a proper error status is set. */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index d98cf5a..c214ba1 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -368,9 +368,26 @@
   return errTp;
 }
 
+static INT aacDecoder_SbrCallback(
+    void *handle, HANDLE_FDK_BITSTREAM hBs, const INT sampleRateIn,
+    const INT sampleRateOut, const INT samplesPerFrame,
+    const AUDIO_OBJECT_TYPE coreCodec, const MP4_ELEMENT_ID elementID,
+    const INT elementIndex, const UCHAR harmonicSBR,
+    const UCHAR stereoConfigIndex, const UCHAR configMode, UCHAR *configChanged,
+    const INT downscaleFactor) {
+  HANDLE_SBRDECODER self = (HANDLE_SBRDECODER)handle;
+
+  INT errTp = sbrDecoder_Header(self, hBs, sampleRateIn, sampleRateOut,
+                                samplesPerFrame, coreCodec, elementID,
+                                elementIndex, harmonicSBR, stereoConfigIndex,
+                                configMode, configChanged, downscaleFactor);
+
+  return errTp;
+}
+
 static INT aacDecoder_SscCallback(void *handle, HANDLE_FDK_BITSTREAM hBs,
                                   const AUDIO_OBJECT_TYPE coreCodec,
-                                  const INT samplingRate,
+                                  const INT samplingRate, const INT frameSize,
                                   const INT stereoConfigIndex,
                                   const INT coreSbrFrameLengthIndex,
                                   const INT configBytes, const UCHAR configMode,
@@ -381,8 +398,8 @@
 
   err = mpegSurroundDecoder_Config(
       (CMpegSurroundDecoder *)hAacDecoder->pMpegSurroundDecoder, hBs, coreCodec,
-      samplingRate, stereoConfigIndex, coreSbrFrameLengthIndex, configBytes,
-      configMode, configChanged);
+      samplingRate, frameSize, stereoConfigIndex, coreSbrFrameLengthIndex,
+      configBytes, configMode, configChanged);
 
   switch (err) {
     case MPS_UNSUPPORTED_CONFIG:
@@ -617,6 +634,7 @@
     switch (err) {
       case PCMDMX_INVALID_HANDLE:
         errorStatus = AAC_DEC_INVALID_HANDLE;
+        break;
       case PCMDMX_OK:
         break;
       default:
@@ -959,7 +977,7 @@
     goto bail;
   }
   aacDec->qmfModeUser = NOT_DEFINED;
-  transportDec_RegisterSbrCallback(aacDec->hInput, (cbSbr_t)sbrDecoder_Header,
+  transportDec_RegisterSbrCallback(aacDec->hInput, aacDecoder_SbrCallback,
                                    (void *)aacDec->hSbrDecoder);
 
   if (mpegSurroundDecoder_Open(
@@ -1380,9 +1398,13 @@
         mpegSurroundDecoder_ConfigureQmfDomain(
             (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface,
             (UINT)self->streamInfo.aacSampleRate, self->streamInfo.aot);
-        self->qmfDomain.globalConf.nQmfTimeSlots_requested =
-            self->streamInfo.aacSamplesPerFrame /
-            self->qmfDomain.globalConf.nBandsAnalysis_requested;
+        if (self->qmfDomain.globalConf.nBandsAnalysis_requested > 0) {
+          self->qmfDomain.globalConf.nQmfTimeSlots_requested =
+              self->streamInfo.aacSamplesPerFrame /
+              self->qmfDomain.globalConf.nBandsAnalysis_requested;
+        } else {
+          self->qmfDomain.globalConf.nQmfTimeSlots_requested = 0;
+        }
       }
 
       self->qmfDomain.globalConf.TDinput = pTimeData;
@@ -1865,7 +1887,7 @@
 
     } /* USAC DASH IPF flushing possible end */
     if (accessUnit < numPrerollAU) {
-      FDKpushBack(hBsAu, auStartAnchor - FDKgetValidBits(hBsAu));
+      FDKpushBack(hBsAu, auStartAnchor - (INT)FDKgetValidBits(hBsAu));
     } else {
       if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) ||
           (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) ||
diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp
index 7d2a4b9..b3d09a6 100644
--- a/libAACdec/src/block.cpp
+++ b/libAACdec/src/block.cpp
@@ -127,9 +127,11 @@
   The function reads the escape sequence from the bitstream,
   if the absolute value of the quantized coefficient has the
   value 16.
-  A limitation is implemented to maximal 31 bits to prevent endless loops.
-  If it strikes, MAX_QUANTIZED_VALUE + 1 is returned, independent of the sign of
-  parameter q.
+  A limitation is implemented to maximal 21 bits according to
+  ISO/IEC 14496-3:2009(E) 4.6.3.3.
+  This limits the escape prefix to a maximum of eight 1's.
+  If more than eight 1's are read, MAX_QUANTIZED_VALUE + 1 is
+  returned, independent of the sign of parameter q.
 
   \return  quantized coefficient
 */
@@ -139,11 +141,11 @@
   if (fAbs(q) != 16) return (q);
 
   LONG i, off;
-  for (i = 4; i < 32; i++) {
+  for (i = 4; i < 13; i++) {
     if (FDKreadBit(bs) == 0) break;
   }
 
-  if (i == 32) return (MAX_QUANTIZED_VALUE + 1);
+  if (i == 13) return (MAX_QUANTIZED_VALUE + 1);
 
   off = FDKreadBits(bs, i);
   i = off + (1 << i);
diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp
index cfffd57..a020034 100644
--- a/libAACdec/src/channel.cpp
+++ b/libAACdec/src/channel.cpp
@@ -592,6 +592,7 @@
                                             line: ~599 */
         /* Note: The missing "break" is intentional here, since we need to call
          * CBlock_ReadScaleFactorData(). */
+        FDK_FALLTHROUGH;
 
       case scale_factor_data:
         if (flags & AC_ER_RVLC) {
diff --git a/libAACdec/src/channelinfo.h b/libAACdec/src/channelinfo.h
index 45a288f..4523400 100644
--- a/libAACdec/src/channelinfo.h
+++ b/libAACdec/src/channelinfo.h
@@ -359,7 +359,7 @@
   shouldBeUnion {
     struct {
       FIXP_DBL fac_data0[LFAC];
-      UCHAR fac_data_e[4];
+      SCHAR fac_data_e[4];
       FIXP_DBL
       *fac_data[4]; /* Pointers to unused parts of pSpectralCoefficient */
 
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
index 569d672..5895cb8 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -1894,6 +1894,7 @@
     case ConcealState_FadeIn:
       idx = cntFadeFrames;
       idx -= TDFadeInStopBeforeFullLevel;
+      FDK_FALLTHROUGH;
     case ConcealState_Ok:
       fadeFactor = pConcealParams->fadeInFactor;
       idx = (concealState == ConcealState_Ok) ? -1 : idx;
diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp
index 66a5914..c7d2928 100644
--- a/libAACdec/src/ldfiltbank.cpp
+++ b/libAACdec/src/ldfiltbank.cpp
@@ -216,6 +216,7 @@
   int scale = mdctData_e + MDCT_OUT_HEADROOM -
               LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside
                                 multE2_DinvF_fdk() below */
+  int i;
 
   /* Select LD window slope */
   switch (N) {
@@ -261,10 +262,11 @@
   }
 
   if (gain != (FIXP_DBL)0) {
-    scaleValuesWithFactor(mdctData, gain, N, scale);
-  } else {
-    scaleValues(mdctData, N, scale);
+    for (i = 0; i < N; i++) {
+      mdctData[i] = fMult(mdctData[i], gain);
+    }
   }
+  scaleValuesSaturate(mdctData, N, scale);
 
   /* Since all exponent and factors have been applied, current exponent is zero.
    */
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index af1f488..c836c6a 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -309,7 +309,7 @@
   ener_exc = (FIXP_DBL)0;
   for (int i = 0; i < L_SUBFR; i++) {
     ener_exc += fPow2Div2(exc[i]) >> s;
-    if (ener_exc > FL2FXCONST_DBL(0.5f)) {
+    if (ener_exc >= FL2FXCONST_DBL(0.5f)) {
       ener_exc >>= 1;
       s++;
     }
@@ -579,11 +579,11 @@
     L_tmp = (FIXP_DBL)0;
 
     for (j = 0; j < M_LP_FILTER_ORDER; j++) {
-      L_tmp -= fMultDiv2(a[j], y[i - (j + 1)]);
+      L_tmp -= fMultDiv2(a[j], y[i - (j + 1)]) >> (LP_FILTER_SCALE - 1);
     }
 
-    L_tmp = scaleValue(L_tmp, a_exp + 1);
-    y[i] = L_tmp + x[i];
+    L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE);
+    y[i] = fAddSaturate(L_tmp, x[i]);
   }
 
   return;
@@ -631,10 +631,10 @@
     s = (FIXP_DBL)0;
 
     for (j = 0; j < M_LP_FILTER_ORDER; j++) {
-      s += fMultDiv2(a[j], x[i - j - 1]);
+      s += fMultDiv2(a[j], x[i - j - 1]) >> (LP_FILTER_SCALE - 1);
     }
 
-    s = scaleValue(s, a_exp + 1);
+    s = scaleValue(s, a_exp + LP_FILTER_SCALE);
     y[i] = fAddSaturate(s, x[i]);
   }
 
diff --git a/libAACdec/src/usacdec_const.h b/libAACdec/src/usacdec_const.h
index c7dbae7..f68e808 100644
--- a/libAACdec/src/usacdec_const.h
+++ b/libAACdec/src/usacdec_const.h
@@ -115,6 +115,7 @@
 
 /* definitions which are independent of coreCoderFrameLength */
 #define M_LP_FILTER_ORDER 16 /* LP filter order */
+#define LP_FILTER_SCALE 4    /* LP filter scale */
 
 #define PIT_MIN_12k8 34    /* Minimum pitch lag with resolution 1/4 */
 #define PIT_MAX_12k8 231   /* Maximum pitch lag for fs=12.8kHz */
diff --git a/libAACdec/src/usacdec_fac.cpp b/libAACdec/src/usacdec_fac.cpp
index 71ce4a9..0d3d844 100644
--- a/libAACdec/src/usacdec_fac.cpp
+++ b/libAACdec/src/usacdec_fac.cpp
@@ -142,7 +142,7 @@
   return ptr;
 }
 
-int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, UCHAR *pFacScale,
+int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale,
                   int length, int use_gain, int frame) {
   FIXP_DBL fac_gain;
   int fac_gain_e = 0;
@@ -191,13 +191,11 @@
     L_tmp = (FIXP_DBL)0;
 
     for (j = 0; j < fMin(i, M_LP_FILTER_ORDER); j++) {
-      L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]);
+      L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]) >> (LP_FILTER_SCALE - 1);
     }
 
-    L_tmp = scaleValue(L_tmp, a_exp + 1);
-
-    x[i] = scaleValueSaturate((x[i] >> 1) + (L_tmp >> 1),
-                              1); /* Avoid overflow issues and saturate. */
+    L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE);
+    x[i] = fAddSaturate(x[i], L_tmp);
   }
 }
 
@@ -536,10 +534,12 @@
 
   /* Optional scaling of time domain - no yet windowed - of current spectrum */
   if (total_gain != (FIXP_DBL)0) {
-    scaleValuesWithFactor(pSpec, total_gain, tl, spec_scale[0] + scale);
-  } else {
-    scaleValues(pSpec, tl, spec_scale[0] + scale);
+    for (i = 0; i < tl; i++) {
+      pSpec[i] = fMult(pSpec[i], total_gain);
+    }
   }
+  int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1);
+  scaleValuesSaturate(pSpec, tl, loc_scale);
 
   pOut1 += fl / 2 - 1;
   pCurr = pSpec + tl - fl / 2;
@@ -625,10 +625,12 @@
      */
     /* and de-scale current spectrum signal (time domain, no yet windowed) */
     if (total_gain != (FIXP_DBL)0) {
-      scaleValuesWithFactor(pSpec, total_gain, tl, spec_scale[w] + scale);
-    } else {
-      scaleValues(pSpec, tl, spec_scale[w] + scale);
+      for (i = 0; i < tl; i++) {
+        pSpec[i] = fMult(pSpec[i], total_gain);
+      }
     }
+    loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1);
+    scaleValuesSaturate(pSpec, tl, loc_scale);
 
     if (noOutSamples <= nrSamples) {
       /* Divert output first half to overlap buffer if we already got enough
diff --git a/libAACdec/src/usacdec_fac.h b/libAACdec/src/usacdec_fac.h
index bf13552..100a6fa 100644
--- a/libAACdec/src/usacdec_fac.h
+++ b/libAACdec/src/usacdec_fac.h
@@ -131,7 +131,7 @@
  * Always 0 for FD case.
  * \return 0 on success, -1 on error.
  */
-int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, UCHAR *pFacScale,
+int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale,
                   int length, int use_gain, int frame);
 
 /**
diff --git a/libAACdec/src/usacdec_lpd.cpp b/libAACdec/src/usacdec_lpd.cpp
index 22069a6..2110172 100644
--- a/libAACdec/src/usacdec_lpd.cpp
+++ b/libAACdec/src/usacdec_lpd.cpp
@@ -418,6 +418,7 @@
     FIXP_DBL tmp_pow2[32];
 
     s = s * 2 + ALFDPOW2_SCALE;
+    s = fMin(31, s);
 
     k = 8;
     i_max = lg / 4; /* ALFD range = 1600Hz (lg = 6400Hz) */
@@ -1221,8 +1222,7 @@
       (INT)(samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM -
       (INT)PIT_MIN_12k8;
 
-  if (pSamplingRateInfo->samplingRate >
-      FAC_FSCALE_MAX /* maximum allowed core sampling frequency */) {
+  if ((samplingRate < FAC_FSCALE_MIN) || (samplingRate > FAC_FSCALE_MAX)) {
     error = AAC_DEC_PARSE_ERROR;
     goto bail;
   }
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index 11db3da..08cd57a 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -907,6 +907,7 @@
     case AOT_MP2_AAC_LC:
     case AOT_MP2_SBR:
       hAacConfig->usePns = 0;
+      FDK_FALLTHROUGH;
     case AOT_AAC_LC:
     case AOT_SBR:
     case AOT_PS:
@@ -1215,7 +1216,8 @@
 
 INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs,
                        const AUDIO_OBJECT_TYPE coreCodec,
-                       const INT samplingRate, const INT stereoConfigIndex,
+                       const INT samplingRate, const INT frameSize,
+                       const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged) {
   HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self;
@@ -1733,9 +1735,10 @@
   }
 
   /* check if buffer descriptors are filled out properly. */
-  if ((AACENC_OK != validateBufDesc(inBufDesc)) ||
-      (AACENC_OK != validateBufDesc(outBufDesc)) || (inargs == NULL) ||
-      (outargs == NULL)) {
+  if ((inargs == NULL) || (outargs == NULL) ||
+      ((AACENC_OK != validateBufDesc(inBufDesc)) &&
+       (inargs->numInSamples > 0)) ||
+      (AACENC_OK != validateBufDesc(outBufDesc))) {
     err = AACENC_UNSUPPORTED_PARAMETER;
     goto bail;
   }
@@ -2090,12 +2093,14 @@
               err = AACENC_INVALID_CONFIG;
               goto bail;
             }
+            FDK_FALLTHROUGH;
           case AOT_SBR:
           case AOT_MP2_SBR:
             if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) {
               err = AACENC_INVALID_CONFIG;
               goto bail;
             }
+            FDK_FALLTHROUGH;
           case AOT_AAC_LC:
           case AOT_MP2_AAC_LC:
           case AOT_ER_AAC_LD:
diff --git a/libAACenc/src/bitenc.cpp b/libAACenc/src/bitenc.cpp
index 652d1fd..957e821 100644
--- a/libAACenc/src/bitenc.cpp
+++ b/libAACenc/src/bitenc.cpp
@@ -643,6 +643,7 @@
           FDKwriteBits(hBitStream, *extPayloadData++, 4); /* nibble */
         }
         extBitsUsed += 4;
+        FDK_FALLTHROUGH;
       case EXT_DYNAMIC_RANGE:
       case EXT_SBR_DATA:
       case EXT_SBR_DATA_CRC:
@@ -690,6 +691,7 @@
 
       case EXT_FILL_DATA:
         fillByte = 0xA5;
+        FDK_FALLTHROUGH;
       case EXT_FIL:
       default:
         if (hBitStream != NULL) {
diff --git a/libArithCoding/src/ac_arith_coder.cpp b/libArithCoding/src/ac_arith_coder.cpp
index b791f39..a433b08 100644
--- a/libArithCoding/src/ac_arith_coder.cpp
+++ b/libArithCoding/src/ac_arith_coder.cpp
@@ -609,13 +609,16 @@
   return (j & 0x3F);
 }
 
-static void decode2(HANDLE_FDK_BITSTREAM bbuf, UCHAR *RESTRICT c_prev,
-                    FIXP_DBL *RESTRICT pSpectralCoefficient, INT n, INT nt) {
+static ARITH_CODING_ERROR decode2(HANDLE_FDK_BITSTREAM bbuf,
+                                  UCHAR *RESTRICT c_prev,
+                                  FIXP_DBL *RESTRICT pSpectralCoefficient,
+                                  INT n, INT nt) {
   Tastat as;
   int i, l, r;
   INT lev, esc_nb, pki;
   USHORT state_inc;
   UINT s;
+  ARITH_CODING_ERROR ErrorStatus = ARITH_CODER_OK;
 
   int c_3 = 0; /* context of current frame 3 time steps ago */
   int c_2 = 0; /* context of current frame 2 time steps ago */
@@ -655,6 +658,8 @@
 
       lev++;
 
+      if (lev > 23) return ARITH_CODER_ERROR;
+
       if (esc_nb < 7) {
         esc_nb++;
       }
@@ -721,6 +726,8 @@
   }
 
   FDKmemset(&c_prev[i], 1, sizeof(c_prev[0]) * (nt - i));
+
+  return ErrorStatus;
 }
 
 CArcoData *CArco_Create(void) { return GetArcoData(); }
@@ -763,7 +770,8 @@
   pArcoData->m_numberLinesPrev = lg_max;
 
   if (lg > 0) {
-    decode2(hBs, pArcoData->c_prev + 2, mdctSpectrum, lg >> 1, lg_max >> 1);
+    ErrorStatus =
+        decode2(hBs, pArcoData->c_prev + 2, mdctSpectrum, lg >> 1, lg_max >> 1);
   } else {
     FDKmemset(&pArcoData->c_prev[2], 1,
               sizeof(pArcoData->c_prev[2]) * (lg_max >> 1));
diff --git a/libDRCdec/src/drcDec_selectionProcess.cpp b/libDRCdec/src/drcDec_selectionProcess.cpp
index 54b731d..9228197 100644
--- a/libDRCdec/src/drcDec_selectionProcess.cpp
+++ b/libDRCdec/src/drcDec_selectionProcess.cpp
@@ -1006,15 +1006,23 @@
   return DRCDEC_SELECTION_PROCESS_NO_ERROR;
 }
 
-static void _setSelectionDataInfo(DRCDEC_SELECTION_DATA* pData,
-                                  FIXP_DBL loudness,
-                                  FIXP_DBL loudnessNormalizationGainDb,
-                                  FIXP_DBL loudnessNormalizationGainDbMax,
-                                  FIXP_DBL loudnessDeviationMax,
-                                  FIXP_DBL signalPeakLevel,
-                                  FIXP_DBL outputPeakLevelMax,
-                                  int applyAdjustment) {
-  FIXP_DBL adjustment = 0;
+static void _setSelectionDataInfo(
+    DRCDEC_SELECTION_DATA* pData, FIXP_DBL loudness, /* e = 7 */
+    FIXP_DBL loudnessNormalizationGainDb,            /* e = 7 */
+    FIXP_DBL loudnessNormalizationGainDbMax,         /* e = 7 */
+    FIXP_DBL loudnessDeviationMax,                   /* e = 7 */
+    FIXP_DBL signalPeakLevel,                        /* e = 7 */
+    FIXP_DBL outputPeakLevelMax,                     /* e = 7 */
+    int applyAdjustment) {
+  FIXP_DBL adjustment = 0; /* e = 8 */
+
+  /* use e = 8 for all function parameters to prevent overflow */
+  loudness >>= 1;
+  loudnessNormalizationGainDb >>= 1;
+  loudnessNormalizationGainDbMax >>= 1;
+  loudnessDeviationMax >>= 1;
+  signalPeakLevel >>= 1;
+  outputPeakLevelMax >>= 1;
 
   if (applyAdjustment) {
     adjustment =
@@ -1028,6 +1036,14 @@
   pData->outputLoudness = loudness + pData->loudnessNormalizationGainDbAdjusted;
   pData->outputPeakLevel =
       signalPeakLevel + pData->loudnessNormalizationGainDbAdjusted;
+
+  /* shift back to e = 7 using saturation */
+  pData->loudnessNormalizationGainDbAdjusted = SATURATE_LEFT_SHIFT(
+      pData->loudnessNormalizationGainDbAdjusted, 1, DFRACT_BITS);
+  pData->outputLoudness =
+      SATURATE_LEFT_SHIFT(pData->outputLoudness, 1, DFRACT_BITS);
+  pData->outputPeakLevel =
+      SATURATE_LEFT_SHIFT(pData->outputPeakLevel, 1, DFRACT_BITS);
 }
 
 static int _targetLoudnessInRange(
diff --git a/libDRCdec/src/drcGainDec_preprocess.cpp b/libDRCdec/src/drcGainDec_preprocess.cpp
index 7919589..c543c53 100644
--- a/libDRCdec/src/drcGainDec_preprocess.cpp
+++ b/libDRCdec/src/drcGainDec_preprocess.cpp
@@ -300,8 +300,9 @@
   FIXP_SGL exp = pCChar->exp;
   DRC_ERROR err = DE_OK;
 
-  tmp = fMultDiv2(DRC_INPUT_LOUDNESS_TARGET - inLevelDb, pCChar->ioRatio);
-  tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1, DFRACT_BITS);
+  tmp = fMultDiv2((DRC_INPUT_LOUDNESS_TARGET >> 1) - (inLevelDb >> 1),
+                  pCChar->ioRatio);
+  tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1 + 1, DFRACT_BITS);
   if (exp < (FIXP_SGL)MAXVAL_SGL) {
     /* x = tmp / gainDbLimit; */
     /* *outGainDb = tmp / pow(1.0f + pow(x, exp), 1.0f/exp); */
diff --git a/libFDK/include/scale.h b/libFDK/include/scale.h
index 07bd3af..30fa089 100644
--- a/libFDK/include/scale.h
+++ b/libFDK/include/scale.h
@@ -268,11 +268,11 @@
  * to avoid problems when inverting the sign of the result.
  */
 #ifndef SATURATE_LEFT_SHIFT_ALT
-#define SATURATE_LEFT_SHIFT_ALT(src, scale, dBits)                       \
-  (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale)))        \
-       ? (LONG)(((1U) << ((dBits)-1)) - 1)                               \
-       : ((LONG)(src) < ~((LONG)(((1U) << ((dBits)-1)) - 2) >> (scale))) \
-             ? ~((LONG)(((1U) << ((dBits)-1)) - 2))                      \
+#define SATURATE_LEFT_SHIFT_ALT(src, scale, dBits)                        \
+  (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale)))         \
+       ? (LONG)(((1U) << ((dBits)-1)) - 1)                                \
+       : ((LONG)(src) <= ~((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \
+             ? ~((LONG)(((1U) << ((dBits)-1)) - 2))                       \
              : ((LONG)(src) << (scale)))
 #endif
 
diff --git a/libFDK/src/FDK_decorrelate.cpp b/libFDK/src/FDK_decorrelate.cpp
index 8e665b7..c5de79a 100644
--- a/libFDK/src/FDK_decorrelate.cpp
+++ b/libFDK/src/FDK_decorrelate.cpp
@@ -1086,8 +1086,9 @@
     pb = SpatialDecGetProcessingBand(maxHybBand, self->mapHybBands2ProcBands);
     for (qs = startHybBand; qs <= maxHybBand; qs++) {
       pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
-      energy[pb] +=
-          (fPow2Div2(inputReal[qs] << clz) + fPow2Div2(inputImag[qs] << clz));
+      energy[pb] =
+          fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) +
+                                       fPow2Div2(inputImag[qs] << clz));
     }
     pb++;
 
@@ -1100,7 +1101,7 @@
       FIXP_DBL nrg = 0;
       qs_next = (int)self->qs_next[pb];
       for (; qs < qs_next; qs++) {
-        nrg += fPow2Div2(inputReal[qs] << clz);
+        nrg = fAddSaturate(nrg, fPow2Div2(inputReal[qs] << clz));
       }
       energy[pb] = nrg;
     }
@@ -1138,13 +1139,14 @@
 #else
     for (qs = startHybBand; qs <= maxHybBand; qs++) {
       int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
-      energy[pb] +=
-          (fPow2Div2(inputReal[qs] << clz) + fPow2Div2(inputImag[qs] << clz));
+      energy[pb] =
+          fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) +
+                                       fPow2Div2(inputImag[qs] << clz));
     }
 
     for (; qs <= maxHybridBand; qs++) {
       int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
-      energy[pb] += fPow2Div2(inputReal[qs] << clz);
+      energy[pb] = fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz));
     }
 #endif /* FUNCTION_DuckerCalcEnergy_func4 */
   }
@@ -1237,9 +1239,9 @@
 
       tmp1 = scaleValue(tmp1, scaleSmoothDirRevNrg_asExponent);
       tmp2 = scaleValue(tmp2, scaleSmoothDirRevNrg_asExponent);
-      tmp1 = fMultAddDiv2(tmp1, directNrg[pb] >> scaleDirectNrg,
+      tmp1 = fMultAddDiv2(tmp1, scaleValue(directNrg[pb], -scaleDirectNrg),
                           DUCK_ONE_MINUS_ALPHA_X4_FDK);
-      tmp2 = fMultAddDiv2(tmp2, reverbNrg[pb] >> scaleReverbNrg,
+      tmp2 = fMultAddDiv2(tmp2, scaleValue(reverbNrg[pb], -scaleReverbNrg),
                           DUCK_ONE_MINUS_ALPHA_X4_FDK);
     } else {
       tmp1 = fMultAddDiv2(tmp1, directNrg[pb], DUCK_ONE_MINUS_ALPHA_X4_FDK);
diff --git a/libFDK/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp
index 043a372..3245deb 100644
--- a/libFDK/src/FDK_qmf_domain.cpp
+++ b/libFDK/src/FDK_qmf_domain.cpp
@@ -786,6 +786,7 @@
   hgc->flags_requested = 0;
   hgc->nInputChannels_requested = 0;
   hgc->nOutputChannels_requested = 0;
+  hgc->parkChannel_requested = 0;
   hgc->nBandsAnalysis_requested = 0;
   hgc->nBandsSynthesis_requested = 0;
   hgc->nQmfTimeSlots_requested = 0;
@@ -798,6 +799,7 @@
   hgc->flags = 0;
   hgc->nInputChannels = 0;
   hgc->nOutputChannels = 0;
+  hgc->parkChannel = 0;
   hgc->nBandsAnalysis = 0;
   hgc->nBandsSynthesis = 0;
   hgc->nQmfTimeSlots = 0;
@@ -887,10 +889,6 @@
         !(hgc->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) {
       hgc->flags_requested |= QMF_FLAG_DOWNSAMPLED;
     }
-    if ((hgc->flags_requested & QMF_FLAG_MPSLDFB) &&
-        (hgc->flags_requested & QMF_FLAG_CLDFB)) {
-      hgc->flags_requested &= ~QMF_FLAG_CLDFB;
-    }
 
     hasChanged = 1;
   }
@@ -899,6 +897,10 @@
 
   /* 5. set requested flags */
   if (hgc->flags != hgc->flags_requested) {
+    if ((hgc->flags_requested & QMF_FLAG_MPSLDFB) &&
+        (hgc->flags_requested & QMF_FLAG_CLDFB)) {
+      hgc->flags_requested &= ~QMF_FLAG_CLDFB;
+    }
     hgc->flags = hgc->flags_requested;
     hasChanged = 1;
   }
@@ -981,9 +983,8 @@
   }
 
 bail:
-  if (err == QMF_DOMAIN_OUT_OF_MEMORY) {
-    FDK_QmfDomain_FreePersistentMemory(hqd);
-    FDK_QmfDomain_ClearConfigured(&hqd->globalConf);
+  if (err) {
+    FDK_QmfDomain_FreeMem(hqd);
   }
   return err;
 }
diff --git a/libFDK/src/arm/dct_arm.cpp b/libFDK/src/arm/dct_arm.cpp
deleted file mode 100644
index dd66109..0000000
--- a/libFDK/src/arm/dct_arm.cpp
+++ /dev/null
@@ -1,572 +0,0 @@
-/* -----------------------------------------------------------------------------
-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
------------------------------------------------------------------------------ */
-
-/******************* Library for basic calculation routines ********************
-
-   Author(s):
-
-   Description:
-
-*******************************************************************************/
-
-#ifdef FUNCTION_dct_IV_func1
-
-/*
-   Note: This assembler routine is here, because the ARM926 compiler does
-         not encode the inline assembler with optimal speed.
-         With this version, we save 2 cycles per loop iteration.
-*/
-
-__asm void dct_IV_func1(int i, const FIXP_SPK *twiddle,
-                        FIXP_DBL *RESTRICT pDat_0, FIXP_DBL *RESTRICT pDat_1) {
-  /* Register map:
-     r0   i
-     r1   twiddle
-     r2   pDat_0
-     r3   pDat_1
-     r4   accu1
-     r5   accu2
-     r6   accu3
-     r7   accu4
-     r8   val_tw
-     r9   accuX
-  */
-  PUSH{r4 - r9}
-
-  /* 44 cycles for 2 iterations = 22 cycles/iteration */
-  dct_IV_loop1_start
-      /*  First iteration */
-      LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++;
-      LDR r5,
-      [ r2, #0 ]  // accu2 = pDat_0[0]
-      LDR r4,
-      [ r3, #0 ]  // accu1 = pDat_1[0]
-
-      SMULWT r9,
-      r5,
-      r8  // accuX = accu2*val_tw.l
-          SMULWB r5,
-      r5,
-      r8  // accu2 = accu2*val_tw.h
-          RSB r9,
-      r9,
-# 0 // accuX =-accu2*val_tw.l
-      SMLAWT r5, r4, r8,
-      r5  // accu2 = accu2*val_tw.h + accu1*val_tw.l
-          SMLAWB r4,
-      r4, r8,
-      r9  // accu1 = accu1*val_tw.h - accu2*val_tw.l
-
-          LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++;
-      LDR r7,
-      [ r3, # - 4 ]  // accu4 = pDat_1[-1]
-      LDR r6,
-      [ r2, #4 ]  // accu3 = pDat_0[1]
-
-      SMULWB r9,
-      r7,
-      r8  // accuX = accu4*val_tw.h
-          SMULWT r7,
-      r7,
-      r8  // accu4 = accu4*val_tw.l
-          RSB r9,
-      r9,
-# 0 // accuX =-accu4*val_tw.h
-      SMLAWB r7, r6, r8,
-      r7  // accu4 = accu4*val_tw.l+accu3*val_tw.h
-          SMLAWT r6,
-      r6, r8,
-      r9  // accu3 = accu3*val_tw.l-accu4*val_tw.h
-
-          STR r5,
-      [r2],
-# 4 // *pDat_0++ = accu2
-      STR r4, [r2],
-# 4 // *pDat_0++ = accu1
-      STR r6, [r3],
-#- 4 // *pDat_1-- = accu3
-      STR r7, [r3],
-#- 4 // *pDat_1-- = accu4
-
-      /*  Second iteration */
-      LDR r8, [r1],
-# 4 // val_tw = *twiddle++;
-      LDR r5,
-      [ r2, #0 ]  // accu2 = pDat_0[0]
-      LDR r4,
-      [ r3, #0 ]  // accu1 = pDat_1[0]
-
-      SMULWT r9,
-      r5,
-      r8  // accuX = accu2*val_tw.l
-          SMULWB r5,
-      r5,
-      r8  // accu2 = accu2*val_tw.h
-          RSB r9,
-      r9,
-# 0 // accuX =-accu2*val_tw.l
-      SMLAWT r5, r4, r8,
-      r5  // accu2 = accu2*val_tw.h + accu1*val_tw.l
-          SMLAWB r4,
-      r4, r8,
-      r9  // accu1 = accu1*val_tw.h - accu2*val_tw.l
-
-          LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++;
-      LDR r7,
-      [ r3, # - 4 ]  // accu4 = pDat_1[-1]
-      LDR r6,
-      [ r2, #4 ]  // accu3 = pDat_0[1]
-
-      SMULWB r9,
-      r7,
-      r8  // accuX = accu4*val_tw.h
-          SMULWT r7,
-      r7,
-      r8  // accu4 = accu4*val_tw.l
-          RSB r9,
-      r9,
-# 0 // accuX =-accu4*val_tw.h
-      SMLAWB r7, r6, r8,
-      r7  // accu4 = accu4*val_tw.l+accu3*val_tw.h
-          SMLAWT r6,
-      r6, r8,
-      r9  // accu3 = accu3*val_tw.l-accu4*val_tw.h
-
-          STR r5,
-      [r2],
-# 4 // *pDat_0++ = accu2
-      STR r4, [r2],
-# 4 // *pDat_0++ = accu1
-      STR r6, [r3],
-#- 4 // *pDat_1-- = accu3
-      STR r7, [r3],
-#- 4 // *pDat_1-- = accu4
-
-      SUBS r0, r0,
-# 1 BNE dct_IV_loop1_start
-
-      POP { r4 - r9 }
-
-  BX lr
-}
-
-#endif /* FUNCTION_dct_IV_func1 */
-
-#ifdef FUNCTION_dct_IV_func2
-
-/* __attribute__((noinline)) */
-static inline void dct_IV_func2(int i, const FIXP_SPK *twiddle,
-                                FIXP_DBL *pDat_0, FIXP_DBL *pDat_1, int inc) {
-  FIXP_DBL accu1, accu2, accu3, accu4, accuX;
-  LONG val_tw;
-
-  accu1 = pDat_1[-2];
-  accu2 = pDat_1[-1];
-
-  *--pDat_1 = -(pDat_0[1] >> 1);
-  *pDat_0++ = (pDat_0[0] >> 1);
-
-  twiddle += inc;
-
-  __asm {
-    LDR     val_tw, [twiddle], inc, LSL #2  // val_tw = *twiddle; twiddle += inc
-    B       dct_IV_loop2_2nd_part
-
-        /* 42 cycles for 2 iterations = 21 cycles/iteration */
-dct_IV_loop2:
-    SMULWT  accuX, accu2, val_tw
-    SMULWB  accu2, accu2, val_tw
-    RSB     accuX, accuX, #0
-    SMLAWB  accuX, accu1, val_tw, accuX
-    SMLAWT  accu2, accu1, val_tw, accu2
-    STR     accuX, [pDat_0], #4
-    STR     accu2, [pDat_1, #-4] !
-
-    LDR     accu4, [pDat_0, #4]
-    LDR     accu3, [pDat_0]
-    SMULWB  accuX, accu4, val_tw
-    SMULWT  accu4, accu4, val_tw
-    RSB     accuX, accuX, #0
-    SMLAWT  accuX, accu3, val_tw, accuX
-    SMLAWB  accu4, accu3, val_tw, accu4
-
-    LDR     accu1, [pDat_1, #-8]
-    LDR     accu2, [pDat_1, #-4]
-
-    LDR     val_tw, [twiddle], inc, LSL #2  // val_tw = *twiddle; twiddle += inc
-
-    STR     accuX, [pDat_1, #-4] !
-    STR     accu4, [pDat_0], #4
-
-dct_IV_loop2_2nd_part:
-    SMULWT  accuX, accu2, val_tw
-    SMULWB  accu2, accu2, val_tw
-    RSB     accuX, accuX, #0
-    SMLAWB  accuX, accu1, val_tw, accuX
-    SMLAWT  accu2, accu1, val_tw, accu2
-    STR     accuX, [pDat_0], #4
-    STR     accu2, [pDat_1, #-4] !
-
-    LDR     accu4, [pDat_0, #4]
-    LDR     accu3, [pDat_0]
-    SMULWB  accuX, accu4, val_tw
-    SMULWT  accu4, accu4, val_tw
-    RSB     accuX, accuX, #0
-    SMLAWT  accuX, accu3, val_tw, accuX
-    SMLAWB  accu4, accu3, val_tw, accu4
-
-    LDR     accu1, [pDat_1, #-8]
-    LDR     accu2, [pDat_1, #-4]
-
-    STR     accuX, [pDat_1, #-4] !
-    STR     accu4, [pDat_0], #4
-
-    LDR     val_tw, [twiddle], inc, LSL #2  // val_tw = *twiddle; twiddle += inc
-
-    SUBS    i, i, #1
-    BNE     dct_IV_loop2
-  }
-
-  /* Last Sin and Cos value pair are the same */
-  accu1 = fMultDiv2(accu1, WTC(0x5a82799a));
-  accu2 = fMultDiv2(accu2, WTC(0x5a82799a));
-
-  *--pDat_1 = accu1 + accu2;
-  *pDat_0++ = accu1 - accu2;
-}
-#endif /* FUNCTION_dct_IV_func2 */
-
-#ifdef FUNCTION_dst_IV_func1
-
-__asm void dst_IV_func1(int i, const FIXP_SPK *twiddle, FIXP_DBL *pDat_0,
-                        FIXP_DBL *pDat_1) {
-  /* Register map:
-     r0   i
-     r1   twiddle
-     r2   pDat_0
-     r3   pDat_1
-     r4   accu1
-     r5   accu2
-     r6   accu3
-     r7   accu4
-     r8   val_tw
-     r9   accuX
-  */
-  PUSH{r4 - r9}
-
-  dst_IV_loop1 LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++
-      LDR r5,
-      [r2]  // accu2 = pDat_0[0]
-      LDR r6,
-      [ r2, #4 ]  // accu3 = pDat_0[1]
-      RSB r5,
-      r5,
-# 0 // accu2 = -accu2
-      SMULWT r9, r5,
-      r8  // accuX = (-accu2)*val_tw.l
-          LDR r4,
-      [ r3, # - 4 ]  // accu1 = pDat_1[-1]
-      RSB r9,
-      r9,
-# 0 // accuX = -(-accu2)*val_tw.l
-      SMLAWB r9, r4, r8,
-      r9  // accuX = accu1*val_tw.h-(-accu2)*val_tw.l
-          SMULWT r4,
-      r4,
-      r8  // accu1 = accu1*val_tw.l
-          LDR r7,
-      [ r3, # - 8 ]  // accu4 = pDat_1[-2]
-      SMLAWB r5,
-      r5, r8,
-      r4  // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l
-          LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++
-      STR r5, [r2],
-# 4 // *pDat_0++ = accu2
-      STR r9, [r2],
-# 4 // *pDat_0++ = accu1 (accuX)
-      RSB r7, r7,
-# 0 // accu4 = -accu4
-      SMULWB r5, r7,
-      r8  // accu2 = (-accu4)*val_tw.h
-          SMULWB r4,
-      r6,
-      r8  // accu1 = (-accu4)*val_tw.l
-          RSB r5,
-      r5,
-# 0 // accu2 = -(-accu4)*val_tw.h
-      SMLAWT r6, r6, r8,
-      r5  // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
-          SMLAWT r7,
-      r7, r8,
-      r4  // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
-          STR r6,
-      [ r3, # - 4 ] !  // *--pDat_1 = accu3
-      STR r7,
-      [ r3, # - 4 ] !  // *--pDat_1 = accu4
-
-      LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++
-      LDR r5,
-      [r2]  // accu2 = pDat_0[0]
-      LDR r6,
-      [ r2, #4 ]  // accu3 = pDat_0[1]
-      RSB r5,
-      r5,
-# 0 // accu2 = -accu2
-      SMULWT r9, r5,
-      r8  // accuX = (-accu2)*val_tw.l
-          LDR r4,
-      [ r3, # - 4 ]  // accu1 = pDat_1[-1]
-      RSB r9,
-      r9,
-# 0 // accuX = -(-accu2)*val_tw.l
-      SMLAWB r9, r4, r8,
-      r9  // accuX = accu1*val_tw.h-(-accu2)*val_tw.l
-          SMULWT r4,
-      r4,
-      r8  // accu1 = accu1*val_tw.l
-          LDR r7,
-      [ r3, # - 8 ]  // accu4 = pDat_1[-2]
-      SMLAWB r5,
-      r5, r8,
-      r4  // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l
-          LDR r8,
-      [r1],
-# 4 // val_tw = *twiddle++
-      STR r5, [r2],
-# 4 // *pDat_0++ = accu2
-      STR r9, [r2],
-# 4 // *pDat_0++ = accu1 (accuX)
-      RSB r7, r7,
-# 0 // accu4 = -accu4
-      SMULWB r5, r7,
-      r8  // accu2 = (-accu4)*val_tw.h
-          SMULWB r4,
-      r6,
-      r8  // accu1 = (-accu4)*val_tw.l
-          RSB r5,
-      r5,
-# 0 // accu2 = -(-accu4)*val_tw.h
-      SMLAWT r6, r6, r8,
-      r5  // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
-          SMLAWT r7,
-      r7, r8,
-      r4  // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
-          STR r6,
-      [ r3, # - 4 ] !  // *--pDat_1 = accu3
-      STR r7,
-      [ r3, # - 4 ] !  // *--pDat_1 = accu4
-
-      SUBS r0,
-      r0,
-# 4 // i-= 4
-      BNE dst_IV_loop1
-
-          POP{r4 - r9} BX lr
-}
-#endif /* FUNCTION_dst_IV_func1 */
-
-#ifdef FUNCTION_dst_IV_func2
-
-/* __attribute__((noinline)) */
-static inline void dst_IV_func2(int i, const FIXP_SPK *twiddle,
-                                FIXP_DBL *RESTRICT pDat_0,
-                                FIXP_DBL *RESTRICT pDat_1, int inc) {
-  FIXP_DBL accu1, accu2, accu3, accu4;
-  LONG val_tw;
-
-  accu4 = pDat_0[0];
-  accu3 = pDat_0[1];
-  accu4 >>= 1;
-  accu3 >>= 1;
-  accu4 = -accu4;
-
-  accu1 = pDat_1[-1];
-  accu2 = pDat_1[0];
-
-  *pDat_0++ = accu3;
-  *pDat_1-- = accu4;
-
-  __asm {
-    B       dst_IV_loop2_2nd_part
-
-        /* 50 cycles for 2 iterations = 25 cycles/iteration */
-
-dst_IV_loop2:
-
-    LDR     val_tw, [twiddle], inc, LSL #2  // val_tw = *twiddle; twiddle += inc
-
-    RSB     accu2, accu2, #0  // accu2 = -accu2
-    RSB     accu1, accu1, #0  // accu1 = -accu1
-    SMULWT  accu3, accu2, val_tw  // accu3 = (-accu2)*val_tw.l
-    SMULWT  accu4, accu1, val_tw  // accu4 = (-accu1)*val_tw.l
-    RSB     accu3, accu3, #0  // accu3 = -accu2*val_tw.l
-    SMLAWB  accu1, accu1, val_tw, accu3  // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l
-    SMLAWB  accu2, accu2, val_tw, accu4  // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h
-    STR     accu1, [pDat_1], #-4  // *pDat_1-- = accu1
-    STR     accu2, [pDat_0], #4  // *pDat_0++ = accu2
-
-    LDR     accu4, [pDat_0]  // accu4 = pDat_0[0]
-    LDR     accu3, [pDat_0, #4]  // accu3 = pDat_0[1]
-
-    RSB     accu4, accu4, #0  // accu4 = -accu4
-    RSB     accu3, accu3, #0  // accu3 = -accu3
-
-    SMULWB  accu1, accu3, val_tw  // accu1 = (-accu3)*val_tw.h
-    SMULWT  accu2, accu3, val_tw  // accu2 = (-accu3)*val_tw.l
-    RSB     accu1, accu1, #0  // accu1 = -(-accu3)*val_tw.h
-    SMLAWT  accu3, accu4, val_tw, accu1  // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
-    SMLAWB  accu4, accu4, val_tw, accu2  // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
-
-    LDR     accu1, [pDat_1, #-4]  // accu1 = pDat_1[-1]
-    LDR     accu2, [pDat_1]  // accu2 = pDat_1[0]
-
-    STR     accu3, [pDat_0], #4  // *pDat_0++ = accu3
-    STR     accu4, [pDat_1], #-4  // *pDat_1-- = accu4
-
-dst_IV_loop2_2nd_part:
-
-    LDR     val_tw, [twiddle], inc, LSL #2  // val_tw = *twiddle; twiddle += inc
-
-    RSB     accu2, accu2, #0  // accu2 = -accu2
-    RSB     accu1, accu1, #0  // accu1 = -accu1
-    SMULWT  accu3, accu2, val_tw  // accu3 = (-accu2)*val_tw.l
-    SMULWT  accu4, accu1, val_tw  // accu4 = (-accu1)*val_tw.l
-    RSB     accu3, accu3, #0  // accu3 = -accu2*val_tw.l
-    SMLAWB  accu1, accu1, val_tw, accu3  // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l
-    SMLAWB  accu2, accu2, val_tw, accu4  // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h
-    STR     accu1, [pDat_1], #-4  // *pDat_1-- = accu1
-    STR     accu2, [pDat_0], #4  // *pDat_0++ = accu2
-
-    LDR     accu4, [pDat_0]  // accu4 = pDat_0[0]
-    LDR     accu3, [pDat_0, #4]  // accu3 = pDat_0[1]
-
-    RSB     accu4, accu4, #0  // accu4 = -accu4
-    RSB     accu3, accu3, #0  // accu3 = -accu3
-
-    SMULWB  accu1, accu3, val_tw  // accu1 = (-accu3)*val_tw.h
-    SMULWT  accu2, accu3, val_tw  // accu2 = (-accu3)*val_tw.l
-    RSB     accu1, accu1, #0  // accu1 = -(-accu3)*val_tw.h
-    SMLAWT  accu3, accu4, val_tw, accu1  // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
-    SMLAWB  accu4, accu4, val_tw, accu2  // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
-
-    LDR     accu1, [pDat_1, #-4]  // accu1 = pDat_1[-1]
-    LDR     accu2, [pDat_1]  // accu2 = pDat_1[0]
-
-    STR     accu3, [pDat_0], #4  // *pDat_0++ = accu3
-    STR     accu4, [pDat_1], #-4  // *pDat_1-- = accu4
-
-    SUBS    i, i, #1
-    BNE     dst_IV_loop2
-  }
-
-  /* Last Sin and Cos value pair are the same */
-  accu1 = fMultDiv2(-accu1, WTC(0x5a82799a));
-  accu2 = fMultDiv2(-accu2, WTC(0x5a82799a));
-
-  *pDat_0 = accu1 + accu2;
-  *pDat_1 = accu1 - accu2;
-}
-#endif /* FUNCTION_dst_IV_func2 */
diff --git a/libFDK/src/dct.cpp b/libFDK/src/dct.cpp
index a451331..776493e 100644
--- a/libFDK/src/dct.cpp
+++ b/libFDK/src/dct.cpp
@@ -124,10 +124,6 @@
 #include "FDK_tools_rom.h"
 #include "fft.h"
 
-#if defined(__arm__)
-#include "arm/dct_arm.cpp"
-#endif
-
 void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle,
                    int *sin_step, int length) {
   const FIXP_WTP *twiddle;
@@ -387,12 +383,6 @@
 
   dct_getTables(&twiddle, &sin_twiddle, &sin_step, L);
 
-#ifdef FUNCTION_dct_IV_func1
-  if (M >= 4 && (M & 3) == 0) {
-    /* ARM926: 44 cycles for 2 iterations = 22 cycles/iteration */
-    dct_IV_func1(M >> 2, twiddle, &pDat[0], &pDat[L - 1]);
-  } else
-#endif /* FUNCTION_dct_IV_func1 */
   {
     FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
     FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
@@ -410,10 +400,10 @@
       cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
       cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]);
 
-      pDat_0[0] = accu2;
-      pDat_0[1] = accu1;
-      pDat_1[0] = accu4;
-      pDat_1[1] = -accu3;
+      pDat_0[0] = accu2 >> 1;
+      pDat_0[1] = accu1 >> 1;
+      pDat_1[0] = accu4 >> 1;
+      pDat_1[1] = -(accu3 >> 1);
     }
     if (M & 1) {
       FIXP_DBL accu1, accu2;
@@ -423,19 +413,13 @@
 
       cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
 
-      pDat_0[0] = accu2;
-      pDat_0[1] = accu1;
+      pDat_0[0] = accu2 >> 1;
+      pDat_0[1] = accu1 >> 1;
     }
   }
 
   fft(M, pDat, pDat_e);
 
-#ifdef FUNCTION_dct_IV_func2
-  if (M >= 4 && (M & 3) == 0) {
-    /* ARM926: 42 cycles for 2 iterations = 21 cycles/iteration */
-    dct_IV_func2(M >> 2, sin_twiddle, &pDat[0], &pDat[L], sin_step);
-  } else
-#endif /* FUNCTION_dct_IV_func2 */
   {
     FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
     FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
@@ -446,20 +430,19 @@
     accu1 = pDat_1[0];
     accu2 = pDat_1[1];
 
-    pDat_1[1] = -(pDat_0[1] >> 1);
-    pDat_0[0] = (pDat_0[0] >> 1);
+    pDat_1[1] = -pDat_0[1];
 
     /* 28 cycles for ARM926 */
     for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) {
       FIXP_STP twd = sin_twiddle[idx];
-      cplxMultDiv2(&accu3, &accu4, accu1, accu2, twd);
+      cplxMult(&accu3, &accu4, accu1, accu2, twd);
       pDat_0[1] = accu3;
       pDat_1[0] = accu4;
 
       pDat_0 += 2;
       pDat_1 -= 2;
 
-      cplxMultDiv2(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
+      cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
 
       accu1 = pDat_1[0];
       accu2 = pDat_1[1];
@@ -470,8 +453,8 @@
 
     if ((M & 1) == 0) {
       /* Last Sin and Cos value pair are the same */
-      accu1 = fMultDiv2(accu1, WTC(0x5a82799a));
-      accu2 = fMultDiv2(accu2, WTC(0x5a82799a));
+      accu1 = fMult(accu1, WTC(0x5a82799a));
+      accu2 = fMult(accu2, WTC(0x5a82799a));
 
       pDat_1[0] = accu1 + accu2;
       pDat_0[1] = accu1 - accu2;
@@ -497,11 +480,6 @@
 
   dct_getTables(&twiddle, &sin_twiddle, &sin_step, L);
 
-#ifdef FUNCTION_dst_IV_func1
-  if ((M >= 4) && ((M & 3) == 0)) {
-    dst_IV_func1(M, twiddle, &pDat[0], &pDat[L]);
-  } else
-#endif
   {
     FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
     FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
@@ -519,10 +497,10 @@
       cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
       cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]);
 
-      pDat_0[0] = accu2;
-      pDat_0[1] = accu1;
-      pDat_1[0] = accu4;
-      pDat_1[1] = -accu3;
+      pDat_0[0] = accu2 >> 1;
+      pDat_0[1] = accu1 >> 1;
+      pDat_1[0] = accu4 >> 1;
+      pDat_1[1] = -(accu3 >> 1);
     }
     if (M & 1) {
       FIXP_DBL accu1, accu2;
@@ -532,19 +510,13 @@
 
       cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
 
-      pDat_0[0] = accu2;
-      pDat_0[1] = accu1;
+      pDat_0[0] = accu2 >> 1;
+      pDat_0[1] = accu1 >> 1;
     }
   }
 
   fft(M, pDat, pDat_e);
 
-#ifdef FUNCTION_dst_IV_func2
-  if ((M >= 4) && ((M & 3) == 0)) {
-    dst_IV_func2(M >> 2, sin_twiddle + sin_step, &pDat[0], &pDat[L - 1],
-                 sin_step);
-  } else
-#endif /* FUNCTION_dst_IV_func2 */
   {
     FIXP_DBL *RESTRICT pDat_0;
     FIXP_DBL *RESTRICT pDat_1;
@@ -558,20 +530,20 @@
     accu1 = pDat_1[0];
     accu2 = pDat_1[1];
 
-    pDat_1[1] = -(pDat_0[0] >> 1);
-    pDat_0[0] = (pDat_0[1] >> 1);
+    pDat_1[1] = -pDat_0[0];
+    pDat_0[0] = pDat_0[1];
 
     for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) {
       FIXP_STP twd = sin_twiddle[idx];
 
-      cplxMultDiv2(&accu3, &accu4, accu1, accu2, twd);
+      cplxMult(&accu3, &accu4, accu1, accu2, twd);
       pDat_1[0] = -accu3;
       pDat_0[1] = -accu4;
 
       pDat_0 += 2;
       pDat_1 -= 2;
 
-      cplxMultDiv2(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
+      cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
 
       accu1 = pDat_1[0];
       accu2 = pDat_1[1];
@@ -582,8 +554,8 @@
 
     if ((M & 1) == 0) {
       /* Last Sin and Cos value pair are the same */
-      accu1 = fMultDiv2(accu1, WTC(0x5a82799a));
-      accu2 = fMultDiv2(accu2, WTC(0x5a82799a));
+      accu1 = fMult(accu1, WTC(0x5a82799a));
+      accu2 = fMult(accu2, WTC(0x5a82799a));
 
       pDat_0[1] = -accu1 - accu2;
       pDat_1[0] = accu2 - accu1;
diff --git a/libFDK/src/nlc_dec.cpp b/libFDK/src/nlc_dec.cpp
index 8a8ccfd..6e98ce0 100644
--- a/libFDK/src/nlc_dec.cpp
+++ b/libFDK/src/nlc_dec.cpp
@@ -647,6 +647,10 @@
             }
             df_rest_flag_1 = num_val_1_int % 2;
             if (df_rest_flag_1) num_val_1_int -= 1;
+            if (num_val_1_int < 0) {
+              err = HUFFDEC_NOTOK;
+              goto bail;
+            }
           }
           if (out_data_2 != NULL) {
             if (diff_type_2 == DIFF_FREQ) {
@@ -658,6 +662,10 @@
             }
             df_rest_flag_2 = num_val_2_int % 2;
             if (df_rest_flag_2) num_val_2_int -= 1;
+            if (num_val_2_int < 0) {
+              err = HUFFDEC_NOTOK;
+              goto bail;
+            }
           }
 
           if (out_data_1 != NULL) {
diff --git a/libMpegTPDec/include/tp_data.h b/libMpegTPDec/include/tp_data.h
index b4ab802..b015332 100644
--- a/libMpegTPDec/include/tp_data.h
+++ b/libMpegTPDec/include/tp_data.h
@@ -367,7 +367,8 @@
 typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *);
 typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
                        const AUDIO_OBJECT_TYPE coreCodec,
-                       const INT samplingRate, const INT stereoConfigIndex,
+                       const INT samplingRate, const INT frameSize,
+                       const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged);
 
diff --git a/libMpegTPDec/src/tpdec_adts.cpp b/libMpegTPDec/src/tpdec_adts.cpp
index 6dc0275..1a4e3fd 100644
--- a/libMpegTPDec/src/tpdec_adts.cpp
+++ b/libMpegTPDec/src/tpdec_adts.cpp
@@ -180,7 +180,11 @@
      have channelConfig=0 and no PCE in this frame. */
   FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig));
 
-  valBits = FDKgetValidBits(hBs);
+  valBits = FDKgetValidBits(hBs) + ADTS_SYNCLENGTH;
+
+  if (valBits < ADTS_HEADERLENGTH) {
+    return TRANSPORTDEC_NOT_ENOUGH_BITS;
+  }
 
   /* adts_fixed_header */
   bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id);
@@ -205,6 +209,10 @@
 
   adtsHeaderLength = ADTS_HEADERLENGTH;
 
+  if (valBits < bs.frame_length * 8) {
+    goto bail;
+  }
+
   if (!bs.protection_absent) {
     FDKcrcReset(&pAdts->crcInfo);
     FDKpushBack(hBs, 56); /* complete fixed and variable header! */
@@ -213,6 +221,9 @@
   }
 
   if (!bs.protection_absent && bs.num_raw_blocks > 0) {
+    if ((INT)FDKgetValidBits(hBs) < bs.num_raw_blocks * 16) {
+      goto bail;
+    }
     for (i = 0; i < bs.num_raw_blocks; i++) {
       pAdts->rawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16);
       adtsHeaderLength += 16;
@@ -230,6 +241,11 @@
     USHORT crc_check;
 
     FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg);
+
+    if ((INT)FDKgetValidBits(hBs) < Adts_Length_CrcCheck) {
+      goto bail;
+    }
+
     crc_check = FDKreadBits(hBs, Adts_Length_CrcCheck);
     adtsHeaderLength += Adts_Length_CrcCheck;
 
@@ -343,6 +359,10 @@
   FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS));
 
   return TRANSPORTDEC_OK;
+
+bail:
+  FDKpushBack(hBs, adtsHeaderLength);
+  return TRANSPORTDEC_NOT_ENOUGH_BITS;
 }
 
 int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum) {
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index 8d411e8..28bc22d 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -139,7 +139,7 @@
     ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_LFE, ID_SCE,
     ID_CPE, ID_CPE, ID_SCE, ID_CPE, ID_SCE, ID_SCE, ID_CPE, ID_NONE};
 static const MP4_ELEMENT_ID channel_configuration_14[] = {
-    ID_SCE, ID_CPE, ID_CPE, ID_LAST, ID_CPE, ID_NONE};
+    ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_NONE};
 
 static const MP4_ELEMENT_ID *channel_configuration_array[] = {
     channel_configuration_0,  channel_configuration_1,
@@ -467,6 +467,7 @@
       pPce->BackElementIsCpe[1] = 1;
       pPce->NumChannels += 1;
       pPce->NumEffectiveChannels += 1;
+      FDK_FALLTHROUGH;
     case 11: /* 3/0/3.1ch */
       pPce->NumFrontChannelElements += 2;
       pPce->FrontElementIsCpe[0] = 0;
@@ -482,25 +483,30 @@
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     case 14:                               /* 2/0/0-3/0/2-0.1ch front height */
       pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */
-    case 7:                                /* 5/0/2.1ch front */
+      FDK_FALLTHROUGH;
+    case 7: /* 5/0/2.1ch front */
       pPce->NumFrontChannelElements += 1;
       pPce->FrontElementIsCpe[2] = 1;
       pPce->NumChannels += 2;
       pPce->NumEffectiveChannels += 2;
+      FDK_FALLTHROUGH;
     case 6: /* 3/0/2.1ch */
       pPce->NumLfeChannelElements += 1;
       pPce->NumChannels += 1;
+      FDK_FALLTHROUGH;
     case 5: /* 3/0/2.0ch */
     case 4: /* 3/0/1.0ch */
       pPce->NumBackChannelElements += 1;
       pPce->BackElementIsCpe[0] = (channelConfig > 4) ? 1 : 0;
       pPce->NumChannels += (channelConfig > 4) ? 2 : 1;
       pPce->NumEffectiveChannels += (channelConfig > 4) ? 2 : 1;
+      FDK_FALLTHROUGH;
     case 3: /* 3/0/0.0ch */
       pPce->NumFrontChannelElements += 1;
       pPce->FrontElementIsCpe[1] = 1;
       pPce->NumChannels += 2;
       pPce->NumEffectiveChannels += 2;
+      FDK_FALLTHROUGH;
     case 1: /* 1/0/0.0ch */
       pPce->NumFrontChannelElements += 1;
       pPce->FrontElementIsCpe[0] = 0;
@@ -713,6 +719,7 @@
       switch (elType) {
         case ID_CPE:
           isCpe = 1;
+          FDK_FALLTHROUGH;
         case ID_SCE:
           /* search in front channels */
           for (i = 0; i < pPce->NumFrontChannelElements; i++) {
@@ -1293,7 +1300,11 @@
   /* read elements of the passed channel_configuration until there is ID_NONE */
   while ((element = channel_configuration_array[channelConfiguration][j]) !=
          ID_NONE) {
-    if (element == ID_SCE || element == ID_CPE) {
+    /* Setup LFE element for upsampling too. This is essential especially for
+     * channel configs where the LFE element is not at the last position for
+     * example in channel config 13 or 14. It leads to memory leaks if the setup
+     * of the LFE element would be done later in the core. */
+    if (element == ID_SCE || element == ID_CPE || element == ID_LFE) {
       error |= cb->cbSbr(
           cb->cbSbrData, hBs, asc->m_samplingFrequency / dsFactor,
           asc->m_extensionSamplingFrequency / dsFactor,
@@ -1402,17 +1413,23 @@
         esc->m_useLdQmfTimeAlign = 1;
         if (cb->cbSsc != NULL) {
           ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc(
-              cb->cbSscData, hBs, asc->m_aot, asc->m_extensionSamplingFrequency,
+              cb->cbSscData, hBs, asc->m_aot,
+              asc->m_samplingFrequency << esc->m_sbrSamplingRate,
+              asc->m_samplesPerFrame << esc->m_sbrSamplingRate,
               1,  /* stereoConfigIndex */
               -1, /* nTimeSlots: read from bitstream */
               eldExtLen, asc->configMode, &asc->SacConfigChanged);
           if (ErrorStatus != TRANSPORTDEC_OK) {
             return TRANSPORTDEC_PARSE_ERROR;
           }
+          if (esc->m_downscaledSamplingFrequency != asc->m_samplingFrequency) {
+            return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled
+                                                       mode not allowed */
+          }
           break;
         }
 
-      /* fall-through */
+        FDK_FALLTHROUGH;
       default:
         for (cnt = 0; cnt < eldExtLen; cnt++) {
           FDKreadBits(hBs, 8);
@@ -1430,6 +1447,10 @@
         if (downscale_fill_nibble != 0x0) {
           return TRANSPORTDEC_PARSE_ERROR;
         }
+        if (esc->m_useLdQmfTimeAlign == 1) {
+          return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled
+                                                     mode not allowed */
+        }
         break;
     }
   }
@@ -1793,9 +1814,16 @@
 
           if (usc->element[i].m_stereoConfigIndex > 0) {
             if (cb->cbSsc != NULL) {
+              int samplesPerFrame = asc->m_samplesPerFrame;
+
+              if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2;
+              if (usc->m_sbrRatioIndex == 2)
+                samplesPerFrame = (samplesPerFrame * 8) / 3;
+              if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1;
+
               /* Mps212Config() ISO/IEC FDIS 23003-3 */
               if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot,
-                            asc->m_extensionSamplingFrequency,
+                            asc->m_extensionSamplingFrequency, samplesPerFrame,
                             usc->element[i].m_stereoConfigIndex,
                             usc->m_coreSbrFrameLengthIndex,
                             0, /* don't know the length */
@@ -2022,6 +2050,7 @@
         break;
       case ASCEXT_MPS: /* 0x76a */
         if (self->m_extensionAudioObjectType == AOT_MPEGS) break;
+        FDK_FALLTHROUGH;
       case ASCEXT_LDMPS: /* 0x7cc */
         if ((ascExtId == ASCEXT_LDMPS) &&
             (self->m_extensionAudioObjectType == AOT_LD_MPEGS))
@@ -2161,8 +2190,9 @@
     case AOT_MPEGS:
       if (cb->cbSsc != NULL) {
         if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency,
-                      1, -1, /* nTimeSlots: read from bitstream */
-                      0,     /* don't know the length */
+                      self->m_samplesPerFrame, 1,
+                      -1, /* nTimeSlots: read from bitstream */
+                      0,  /* don't know the length */
                       self->configMode, &self->SacConfigChanged)) {
           return TRANSPORTDEC_UNSUPPORTED_FORMAT;
         }
@@ -2345,10 +2375,17 @@
         /*usc->element[elemIdx].m_stereoConfigIndex =*/FDKreadBits(hBs, 2);
         if (usc->element[elemIdx].m_stereoConfigIndex > 0) {
           if (cb->cbSsc != NULL) {
+            int samplesPerFrame = asc->m_samplesPerFrame;
+
+            if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2;
+            if (usc->m_sbrRatioIndex == 2)
+              samplesPerFrame = (samplesPerFrame * 8) / 3;
+            if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1;
+
             ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc(
                 cb->cbSscData, hBs,
                 AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */
-                asc->m_extensionSamplingFrequency,
+                asc->m_extensionSamplingFrequency, samplesPerFrame,
                 usc->element[elemIdx].m_stereoConfigIndex,
                 usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */
                 asc->configMode, &asc->SacConfigChanged);
@@ -2498,6 +2535,7 @@
         switch (audioMode) {
           case 1: /* parametric stereo */
             self->m_psPresentFlag = 1;
+            FDK_FALLTHROUGH;
           case 0: /* mono */
             self->m_channelConfiguration = 1;
             break;
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp
index 1d8b7b3..1976cb9 100644
--- a/libMpegTPDec/src/tpdec_lib.cpp
+++ b/libMpegTPDec/src/tpdec_lib.cpp
@@ -736,9 +736,9 @@
             hTp->parser.latm.m_audioMuxLengthBytes > 0) {
           int loasOffset;
 
-          loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes * 8 +
-                        FDKgetValidBits(hBs)) -
-                       hTp->globalFramePos;
+          loasOffset = ((INT)hTp->parser.latm.m_audioMuxLengthBytes * 8 +
+                        (INT)FDKgetValidBits(hBs)) -
+                       (INT)hTp->globalFramePos;
           if (loasOffset != 0) {
             FDKpushBiDirectional(hBs, loasOffset);
             /* For ELD and other payloads there is an unknown amount of padding,
@@ -871,7 +871,7 @@
   int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0;
   int startPos;
 
-  startPos = FDKgetValidBits(hBs);
+  startPos = (INT)FDKgetValidBits(hBs);
 
   switch (hTp->transportFmt) {
     case TT_MP4_ADTS:
@@ -941,7 +941,7 @@
           fTraverseMoreFrames = 0;
         }
         syncLayerFrameBits = (hTp->parser.adts.bs.frame_length << 3) -
-                             ((INT)startPos - (INT)FDKgetValidBits(hBs)) -
+                             (startPos - (INT)FDKgetValidBits(hBs)) -
                              syncLength;
         if (syncLayerFrameBits <= 0) {
           err = TRANSPORTDEC_SYNC_ERROR;
@@ -952,10 +952,11 @@
       break;
     case TT_MP4_LOAS:
       if (hTp->numberOfRawDataBlocks <= 0) {
-        syncLayerFrameBits = FDKreadBits(hBs, 13);
+        syncLayerFrameBits = (INT)FDKreadBits(hBs, 13);
         hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
         syncLayerFrameBits <<= 3;
       }
+      FDK_FALLTHROUGH;
     case TT_MP4_LATM_MCP1:
     case TT_MP4_LATM_MCP0:
       if (hTp->numberOfRawDataBlocks <= 0) {
@@ -974,7 +975,7 @@
           hTp->numberOfRawDataBlocks =
               CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
           if (hTp->transportFmt == TT_MP4_LOAS) {
-            syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13);
+            syncLayerFrameBits -= startPos - (INT)FDKgetValidBits(hBs) - (13);
           }
         }
       } else {
diff --git a/libMpegTPEnc/include/tp_data.h b/libMpegTPEnc/include/tp_data.h
index 6f032d1..00de356 100644
--- a/libMpegTPEnc/include/tp_data.h
+++ b/libMpegTPEnc/include/tp_data.h
@@ -367,7 +367,8 @@
 typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *);
 typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
                        const AUDIO_OBJECT_TYPE coreCodec,
-                       const INT samplingRate, const INT stereoConfigIndex,
+                       const INT samplingRate, const INT frameSize,
+                       const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged);
 
diff --git a/libMpegTPEnc/src/tpenc_asc.cpp b/libMpegTPEnc/src/tpenc_asc.cpp
index ce4e364..0b484a0 100644
--- a/libMpegTPEnc/src/tpenc_asc.cpp
+++ b/libMpegTPEnc/src/tpenc_asc.cpp
@@ -795,7 +795,7 @@
 
     const INT eldExtLen =
         (cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0,
-                   0, 0, 0, NULL) +
+                   0, 0, 0, 0, NULL) +
          7) >>
         3;
     INT cnt = eldExtLen;
@@ -818,7 +818,7 @@
     }
 
     cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0,
-              0, NULL);
+              0, 0, NULL);
   }
 
   if (config->downscaleSamplingRate != 0 &&
diff --git a/libMpegTPEnc/src/tpenc_lib.cpp b/libMpegTPEnc/src/tpenc_lib.cpp
index a8567b9..14ea5fe 100644
--- a/libMpegTPEnc/src/tpenc_lib.cpp
+++ b/libMpegTPEnc/src/tpenc_lib.cpp
@@ -212,6 +212,7 @@
                                                  for potential matrix mixdown */
               break;
             }
+            FDK_FALLTHROUGH;
           case TT_MP4_LOAS:      /* PCE in ASC if chChonfig==0 */
           case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */
           default:
diff --git a/libPCMutils/src/pcmdmx_lib.cpp b/libPCMutils/src/pcmdmx_lib.cpp
index b09a848..2070dbc 100644
--- a/libPCMutils/src/pcmdmx_lib.cpp
+++ b/libPCMutils/src/pcmdmx_lib.cpp
@@ -1043,6 +1043,7 @@
       case CH_MODE_3_2_1_0:
         isValidCfg = FALSE;
         err = PCMDMX_INVALID_MODE;
+        FDK_FALLTHROUGH;
       case CH_MODE_3_0_3_1: /* chCfg 11 */
         /* 6.1ch:  C' = C;  L' = L;  R' = R;  LFE' = LFE;
                    Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx;
@@ -1080,9 +1081,11 @@
                       LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1);
         dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL,
                       LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1);
+        FDK_FALLTHROUGH;
       case CH_MODE_5_2_1_0:
         isValidCfg = FALSE;
         err = PCMDMX_INVALID_MODE;
+        FDK_FALLTHROUGH;
       case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */
         if (inChCfg == 14) {
           /* 7.1ch Front Height:  C' = C;  Ls' = Ls;  Rs' = Rs;  LFE' = LFE;
diff --git a/libSACdec/include/sac_dec_lib.h b/libSACdec/include/sac_dec_lib.h
index 2797a10..9913279 100644
--- a/libSACdec/include/sac_dec_lib.h
+++ b/libSACdec/include/sac_dec_lib.h
@@ -315,9 +315,9 @@
  */
 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);
+    AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
+    INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
+    const UCHAR configMode, UCHAR *configChanged);
 
 SACDEC_ERROR
 mpegSurroundDecoder_ConfigureQmfDomain(
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
index 37e0cf2..883e1e8 100644
--- a/libSACdec/src/sac_bitdec.cpp
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -291,13 +291,13 @@
   if (sacHeaderLen == 127) {
     sacHeaderLen += FDKreadBits(bitstream, 16);
   }
-  numFillBits = FDKgetValidBits(bitstream);
+  numFillBits = (INT)FDKgetValidBits(bitstream);
 
   err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig,
                                       sacHeaderLen, coreCodec);
 
   numFillBits -=
-      FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */
+      (INT)FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */
   numFillBits = (8 * sacHeaderLen) - numFillBits;
   if (numFillBits < 0) {
     /* Parsing went wrong */
@@ -325,6 +325,8 @@
     INT coreSbrFrameLengthIndex) {
   int i;
 
+  FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG));
+
   pSpatialSpecificConfig->stereoConfigIndex = stereoConfigIndex;
   pSpatialSpecificConfig->coreSbrFrameLengthIndex = coreSbrFrameLengthIndex;
   pSpatialSpecificConfig->freqRes =
@@ -447,6 +449,8 @@
   int numHeaderBits;
   int cfgStartPos, bitsAvailable;
 
+  FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG));
+
   cfgStartPos = FDKgetValidBits(bitstream);
   /* It might be that we do not know the SSC length beforehand. */
   if (sacHeaderLen == 0) {
@@ -513,6 +517,10 @@
 
   pSpatialSpecificConfig->tempShapeConfig =
       (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2);
+  if (pSpatialSpecificConfig->tempShapeConfig > 2) {
+    return MPS_PARSE_ERROR; /* reserved value */
+  }
+
   pSpatialSpecificConfig->decorrConfig =
       (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2);
   if (pSpatialSpecificConfig->decorrConfig > 2) {
@@ -568,16 +576,18 @@
 
   numHeaderBits = cfgStartPos - (INT)FDKgetValidBits(bitstream);
   bitsAvailable -= numHeaderBits;
+  if (bitsAvailable < 0) {
+    err = MPS_PARSE_ERROR;
+    goto bail;
+  }
 
   pSpatialSpecificConfig->sacExtCnt = 0;
   pSpatialSpecificConfig->bResidualCoding = 0;
 
-  if ((err == MPS_OK) && (bitsAvailable > 0)) {
-    err = SpatialDecParseExtensionConfig(
-        bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes,
-        pSpatialSpecificConfig->nTttBoxes,
-        pSpatialSpecificConfig->nOutputChannels, bitsAvailable);
-  }
+  err = SpatialDecParseExtensionConfig(
+      bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes,
+      pSpatialSpecificConfig->nTttBoxes,
+      pSpatialSpecificConfig->nOutputChannels, bitsAvailable);
 
   FDKbyteAlign(
       bitstream,
@@ -1864,6 +1874,16 @@
     frame->numParameterSets =
         fixMin(MAX_PARAMETER_SETS, frame->numParameterSets + 1);
     frame->paramSlot[frame->numParameterSets - 1] = self->timeSlots - 1;
+
+    for (int p = 0; p < frame->numParameterSets; p++) {
+      if (frame->paramSlot[p] > self->timeSlots - 1) {
+        frame->paramSlot[p] = self->timeSlots - 1;
+        err = MPS_PARSE_ERROR;
+      }
+    }
+    if (err != MPS_OK) {
+      goto bail;
+    }
   }
 
 bail:
diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp
index ebf9bee..bf6dedf 100644
--- a/libSACdec/src/sac_dec_lib.cpp
+++ b/libSACdec/src/sac_dec_lib.cpp
@@ -237,6 +237,11 @@
   SPATIAL_DEC_CONFIG decConfig;
 };
 
+SACDEC_ERROR
+static sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc,
+                         const INT coreCodec, const INT sampleRate,
+                         const INT frameSize);
+
 static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc);
 
 /**
@@ -694,11 +699,13 @@
  **/
 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) {
+    AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
+    INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
+    const UCHAR configMode, UCHAR *configChanged) {
   SACDEC_ERROR err = MPS_OK;
   SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig;
+  SPATIAL_SPECIFIC_CONFIG *pSsc =
+      &pMpegSurroundDecoder->spatialSpecificConfigBackup;
 
   switch (coreCodec) {
     case AOT_DRM_USAC:
@@ -709,6 +716,7 @@
         err = SpatialDecParseMps212Config(
             hBs, &spatialSpecificConfig, samplingRate, coreCodec,
             stereoConfigIndex, coreSbrFrameLengthIndex);
+        pSsc = &spatialSpecificConfig;
       } else {
         err = SpatialDecParseMps212Config(
             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
@@ -723,6 +731,7 @@
          * into temporarily allocated structure */
         err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig,
                                             configBytes, coreCodec);
+        pSsc = &spatialSpecificConfig;
       } else {
         err = SpatialDecParseSpecificConfig(
             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
@@ -738,14 +747,21 @@
     goto bail;
   }
 
+  err = sscCheckOutOfBand(pSsc, coreCodec, samplingRate, frameSize);
+
+  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))) {
+      err = mpegSurroundDecoder_Open(&pMpegSurroundDecoder, stereoConfigIndex,
+                                     NULL);
+      if (err) {
         return err;
       }
     }
@@ -815,29 +831,9 @@
  * \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;
   }
@@ -846,17 +842,9 @@
     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;
+  return MPS_OK;
 }
 
 /**
@@ -1024,6 +1012,11 @@
 
   FDK_ASSERT(pSsc != NULL);
 
+  /* check ssc for parse errors */
+  if (sscParseCheck(pSsc) != MPS_OK) {
+    err = MPS_PARSE_ERROR;
+  }
+
   /* core fs and mps fs must match */
   if (pSsc->samplingFreq != sampleRate) {
     err = MPS_PARSE_ERROR /* MPEGSDEC_SSC_PARSE_ERROR */;
@@ -1087,12 +1080,90 @@
 
   if (coreCodec == AOT_ER_AAC_ELD) {
     pGC->flags_requested |= QMF_FLAG_MPSLDFB;
+    pGC->flags_requested &= ~QMF_FLAG_CLDFB;
   }
 
   return err;
 }
 
 /**
+ * \brief  Check out-of-band config
+ *
+ * \param pSsc         spatial specific config handle.
+ * \param coreCodec    core codec.
+ * \param sampleRate   sampling frequency.
+ *
+ * \return  errorStatus
+ */
+SACDEC_ERROR
+sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, const INT coreCodec,
+                  const INT sampleRate, const INT frameSize) {
+  FDK_ASSERT(pSsc != NULL);
+  int qmfBands = 0;
+
+  /* check ssc for parse errors */
+  if (sscParseCheck(pSsc) != MPS_OK) {
+    return MPS_PARSE_ERROR;
+  }
+
+  switch (coreCodec) {
+    case AOT_USAC:
+    case AOT_DRM_USAC:
+      /* ISO/IEC 23003-1:2007(E), Chapter 6.3.3, Support for lower and higher
+       * sampling frequencies */
+      if (pSsc->samplingFreq >= 55426) {
+        return MPS_PARSE_ERROR;
+      }
+      break;
+    case AOT_ER_AAC_LD:
+    case AOT_ER_AAC_ELD:
+      /* core fs and mps fs must match */
+      if (pSsc->samplingFreq != sampleRate) {
+        return MPS_PARSE_ERROR;
+      }
+
+      /* ISO/IEC 14496-3:2009 FDAM 3: Chapter 1.5.2.3, Levels for the Low Delay
+       * AAC v2 profile */
+      if (pSsc->samplingFreq > 48000) {
+        return MPS_PARSE_ERROR;
+      }
+
+      qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq);
+      switch (frameSize) {
+        case 480:
+          if (!((qmfBands == 32) && (pSsc->nTimeSlots == 15))) {
+            return MPS_PARSE_ERROR;
+          }
+          break;
+        case 960:
+          if (!((qmfBands == 64) && (pSsc->nTimeSlots == 15))) {
+            return MPS_PARSE_ERROR;
+          }
+          break;
+        case 512:
+          if (!(((qmfBands == 32) && (pSsc->nTimeSlots == 16)) ||
+                ((qmfBands == 64) && (pSsc->nTimeSlots == 8)))) {
+            return MPS_PARSE_ERROR;
+          }
+          break;
+        case 1024:
+          if (!((qmfBands == 64) && (pSsc->nTimeSlots == 16))) {
+            return MPS_PARSE_ERROR;
+          }
+          break;
+        default:
+          return MPS_PARSE_ERROR;
+      }
+      break;
+    default:
+      return MPS_PARSE_ERROR;
+      break;
+  }
+
+  return MPS_OK;
+}
+
+/**
  * \brief Decode MPEG Surround frame.
  **/
 int mpegSurroundDecoder_ParseNoHeader(
@@ -1232,7 +1303,7 @@
 
   FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
 
-  mpsBsBits = FDKgetValidBits(hBs);
+  mpsBsBits = (INT)FDKgetValidBits(hBs);
 
   sscParse = &pMpegSurroundDecoder
                   ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
@@ -1308,14 +1379,14 @@
                   pMpegSurroundDecoder->spatialSpecificConfigBackup;
 
               /* Parse spatial specific config */
-              bitsRead = FDKgetValidBits(hMpsBsData);
+              bitsRead = (INT)FDKgetValidBits(hMpsBsData);
 
               err = SpatialDecParseSpecificConfigHeader(
                   hMpsBsData,
                   &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec,
                   pMpegSurroundDecoder->upmixType);
 
-              bitsRead = (bitsRead - FDKgetValidBits(hMpsBsData));
+              bitsRead = (bitsRead - (INT)FDKgetValidBits(hMpsBsData));
               parseResult = ((err == MPS_OK) ? bitsRead : -bitsRead);
 
               if (parseResult < 0) {
@@ -1349,6 +1420,7 @@
                 pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 0;
               }
             }
+              FDK_FALLTHROUGH;
             case MPEGS_ANCTYPE_FRAME:
 
               if (pMpegSurroundDecoder
@@ -1429,7 +1501,7 @@
 
 bail:
 
-  *pMpsDataBits -= (mpsBsBits - FDKgetValidBits(hBs));
+  *pMpsDataBits -= (mpsBsBits - (INT)FDKgetValidBits(hBs));
 
   return err;
 }
@@ -1586,6 +1658,10 @@
   initControlFlags = controlFlags;
 
   /* Check that provided output buffer is large enough. */
+  if (pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis == 0) {
+    err = MPS_UNSUPPORTED_FORMAT;
+    goto bail;
+  }
   timeDataRequiredSize =
       (timeDataFrameSize *
        pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT *
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index d7a8bb5..cb1474f 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -626,7 +626,8 @@
         total_power_low >>= diff;
         total_power_low_sf = new_summand_sf;
       } else if (new_summand_sf < total_power_low_sf) {
-        new_summand >>= total_power_low_sf - new_summand_sf;
+        new_summand >>=
+            fMin(DFRACT_BITS - 1, total_power_low_sf - new_summand_sf);
       }
 
       total_power_low += (new_summand >> preShift2);
@@ -638,7 +639,8 @@
             fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_sf);
         total_power_high_sf = new_summand_sf;
       } else if (new_summand_sf < total_power_high_sf) {
-        new_summand >>= total_power_high_sf - new_summand_sf;
+        new_summand >>=
+            fMin(DFRACT_BITS - 1, total_power_high_sf - new_summand_sf);
       }
 
       total_power_high += (new_summand >> preShift2);
@@ -1561,13 +1563,14 @@
             adjustTimeSlotHQ_GainAndNoise(
                 &analysBufferReal[j][lowSubband],
                 &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs,
-                lowSubband, noSubbands, scale_change, smooth_ratio, noNoiseFlag,
-                filtBufferNoiseShift);
+                lowSubband, noSubbands, fMin(scale_change, DFRACT_BITS - 1),
+                smooth_ratio, noNoiseFlag, filtBufferNoiseShift);
           } else {
             adjustTimeSlotHQ(&analysBufferReal[j][lowSubband],
                              &analysBufferImag[j][lowSubband], h_sbr_cal_env,
-                             pNrgs, lowSubband, noSubbands, scale_change,
-                             smooth_ratio, noNoiseFlag, filtBufferNoiseShift);
+                             pNrgs, lowSubband, noSubbands,
+                             fMin(scale_change, DFRACT_BITS - 1), smooth_ratio,
+                             noNoiseFlag, filtBufferNoiseShift);
           }
         } else {
           FDK_ASSERT(!iTES_enable); /* not supported */
@@ -1575,13 +1578,14 @@
             /* FDKmemset(analysBufferReal[j], 0, 64 * sizeof(FIXP_DBL)); */
             adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], pNrgs,
                                    &h_sbr_cal_env->harmIndex, lowSubband,
-                                   noSubbands, scale_change, noNoiseFlag,
-                                   &h_sbr_cal_env->phaseIndex,
+                                   noSubbands,
+                                   fMin(scale_change, DFRACT_BITS - 1),
+                                   noNoiseFlag, &h_sbr_cal_env->phaseIndex,
                                    EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale);
           } else {
             adjustTimeSlotLC(&analysBufferReal[j][lowSubband], pNrgs,
                              &h_sbr_cal_env->harmIndex, lowSubband, noSubbands,
-                             scale_change, noNoiseFlag,
+                             fMin(scale_change, DFRACT_BITS - 1), noNoiseFlag,
                              &h_sbr_cal_env->phaseIndex);
           }
         }
diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp
index 88c92cd..95807c9 100644
--- a/libSBRdec/src/env_dec.cpp
+++ b/libSBRdec/src/env_dec.cpp
@@ -435,8 +435,8 @@
   /* Noisefloor levels are always cleared ... */
 
   h_sbr_data->domain_vec_noise[0] = 1;
-  for (i = 0; i < hHeaderData->freqBandData.nNfb; i++)
-    h_sbr_data->sbrNoiseFloorLevel[i] = FL2FXCONST_SGL(0.0f);
+  FDKmemclear(h_sbr_data->sbrNoiseFloorLevel,
+              sizeof(h_sbr_data->sbrNoiseFloorLevel));
 
   /* ... and so are the sines */
   FDKmemclear(h_sbr_data->addHarmonics,
@@ -506,15 +506,20 @@
          */
         for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) {
           /* Former Level-Channel will be used for both channels */
-          if (h_prev_data->coupling == COUPLING_BAL)
-            h_prev_data->sfb_nrg_prev[i] = otherChannel->sfb_nrg_prev[i];
+          if (h_prev_data->coupling == COUPLING_BAL) {
+            h_prev_data->sfb_nrg_prev[i] =
+                (otherChannel != NULL) ? otherChannel->sfb_nrg_prev[i]
+                                       : (FIXP_SGL)SBR_ENERGY_PAN_OFFSET;
+          }
           /* Former L/R will be combined as the new Level-Channel */
-          else if (h_sbr_data->coupling == COUPLING_LEVEL)
+          else if (h_sbr_data->coupling == COUPLING_LEVEL &&
+                   otherChannel != NULL) {
             h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] +
                                             otherChannel->sfb_nrg_prev[i]) >>
                                            1;
-          else if (h_sbr_data->coupling == COUPLING_BAL)
+          } else if (h_sbr_data->coupling == COUPLING_BAL) {
             h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET;
+          }
         }
       }
     }
diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp
index e6ae6dc..c72a7b6 100644
--- a/libSBRdec/src/env_extr.cpp
+++ b/libSBRdec/src/env_extr.cpp
@@ -1145,10 +1145,10 @@
   \brief    Generates frame info for FIXFIXonly frame class used for low delay
  version
 
-  \return   nothing
+  \return   zero for error, one for correct.
  ****************************************************************************/
-static void generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal,
-                               int numberTimeSlots, const UINT flags) {
+static int generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal,
+                              int numberTimeSlots, const UINT flags) {
   int nEnv, i, tranIdx;
   const int *pTable;
 
@@ -1159,12 +1159,11 @@
     case 15:
       pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal];
       break;
-    default:
-      FDK_ASSERT(0);
-      /* fall through */
     case 16:
       pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal];
       break;
+    default:
+      return 0;
   }
 
   /* look number of envelopes in table */
@@ -1187,6 +1186,8 @@
   /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2)
    */
   hSbrFrameInfo->nNoiseEnvelopes = 2;
+
+  return 1;
 }
 
 /*!
@@ -1230,7 +1231,9 @@
   }
 
   /* calculate borders according to the transient position */
-  generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags);
+  if (!generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags)) {
+    return 0;
+  }
 
   /* decode freq res: */
   for (k = 0; k < pFrameInfo->nEnvelopes; k++) {
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp
index 53b21c9..1141e9c 100644
--- a/libSBRdec/src/hbe.cpp
+++ b/libSBRdec/src/hbe.cpp
@@ -1056,6 +1056,10 @@
     const FIXP_QTW* tmp_t_sin;
 
     hQmfTransposer->startBand = FreqBandTable[0][0];
+    FDK_ASSERT((!hQmfTransposer->bSbr41 && hQmfTransposer->startBand <= 32) ||
+               (hQmfTransposer->bSbr41 &&
+                hQmfTransposer->startBand <=
+                    16)); /* is checked by resetFreqBandTables() */
     hQmfTransposer->stopBand = FreqBandTable[0][NSfb[0]];
 
     hQmfTransposer->synthSize =
diff --git a/libSBRdec/src/psbitdec.cpp b/libSBRdec/src/psbitdec.cpp
index f40a156..82bb65b 100644
--- a/libSBRdec/src/psbitdec.cpp
+++ b/libSBRdec/src/psbitdec.cpp
@@ -312,6 +312,7 @@
 
     if (pBsData->bEnableIid) {
       pBsData->bFineIidQ = h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ;
+      pBsData->freqResIid = h_ps_d->specificTo.mpeg.prevFreqResIid;
       for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) {
         pBsData->aaIidIndex[pBsData->noEnv - 1][gr] =
             h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr];
@@ -323,6 +324,7 @@
     }
 
     if (pBsData->bEnableIcc) {
+      pBsData->freqResIcc = h_ps_d->specificTo.mpeg.prevFreqResIcc;
       for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) {
         pBsData->aaIccIndex[pBsData->noEnv - 1][gr] =
             h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr];
@@ -337,6 +339,12 @@
   /* Update previous frame Iid quantization */
   h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ = pBsData->bFineIidQ;
 
+  /* Update previous frequency resolution for IID */
+  h_ps_d->specificTo.mpeg.prevFreqResIid = pBsData->freqResIid;
+
+  /* Update previous frequency resolution for ICC */
+  h_ps_d->specificTo.mpeg.prevFreqResIcc = pBsData->freqResIcc;
+
   /* Update previous frame index buffers */
   for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) {
     h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr] =
diff --git a/libSBRdec/src/psdec.h b/libSBRdec/src/psdec.h
index 6ae1473..029eac4 100644
--- a/libSBRdec/src/psdec.h
+++ b/libSBRdec/src/psdec.h
@@ -275,7 +275,11 @@
       SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for
                                                        previous frame */
       UCHAR
-      bPrevFrameFineIidQ; /*!< The IID quantization of the previous frame */
+      bPrevFrameFineIidQ;   /*!< The IID quantization of the previous frame */
+      UCHAR prevFreqResIid; /*!< Frequency resolution for IID of the previous
+                               frame            */
+      UCHAR prevFreqResIcc; /*!< Frequency resolution for ICC of the previous
+                               frame            */
       UCHAR lastUsb; /*!< uppermost WMF delay band of last frame          */
 
       FIXP_DBL pHybridAnaStatesLFdmx
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index 2e18e6c..30611e7 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.cpp
@@ -1248,7 +1248,7 @@
 
   hSbrDec->savedStates = 0;
 
-  if (flags & SBRDEC_USAC_HARMONICSBR) {
+  if ((flags & SBRDEC_USAC_HARMONICSBR) && applySbrProc) {
     sbrError = QmfTransposerReInit(hSbrDec->hHBE,
                                    hHeaderData->freqBandData.freqBandTable,
                                    hHeaderData->freqBandData.nSfb);
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index e2455da..4bc6f69 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -1150,6 +1150,11 @@
 
   int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0;
 
+  if (*count <= 0) {
+    setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
+    return SBRDEC_OK;
+  }
+
   /* SBR sanity checks */
   if (self == NULL) {
     errorStatus = SBRDEC_NOT_INITIALIZED;
@@ -1677,6 +1682,9 @@
   /* reset */
   if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) {
     int ch;
+    int applySbrProc = (hSbrHeader->syncState == SBR_ACTIVE ||
+                        (hSbrHeader->frameErrorFlag == 0 &&
+                         hSbrHeader->syncState == SBR_HEADER));
     for (ch = 0; ch < numElementChannels; ch++) {
       SBR_ERROR errorStatusTmp = SBRDEC_OK;
 
@@ -1688,7 +1696,9 @@
         hSbrHeader->syncState = UPSAMPLING;
       }
     }
-    hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET;
+    if (applySbrProc) {
+      hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET;
+    }
   }
 
   /* decoding */
diff --git a/libSYS/include/machine_type.h b/libSYS/include/machine_type.h
index be8de37..b66d5ad 100644
--- a/libSYS/include/machine_type.h
+++ b/libSYS/include/machine_type.h
@@ -379,6 +379,17 @@
 #define LNK_SECTION_L1_DATA_A
 #define LNK_SECTION_L1_DATA_B
 
+/**************************************************
+ * Macros regarding static code analysis
+ **************************************************/
+#if defined(__clang__)
+#define FDK_FALLTHROUGH [[clang::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+#define FDK_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define FDK_FALLTHROUGH
+#endif
+
 #ifdef _MSC_VER
 /*
  * Sometimes certain features are excluded from compilation and therefore the