FDKv2 ubsan patches

Bug: 80053205
Test: see bug for repro with FB "wow"
   atest DecoderTestAacDrc

Fix signed integer overflows in CLpc_SynthesisLattice()

Change-Id: Icbddfcc8c5fc73382ae5bf8c2a7703802c688e06

Fix signed integer overflows in imlt

Change-Id: I687834fca2f1aab6210ed9862576b4f38fcdeb24

Fix overflow in addLowbandEnergies()

Change-Id: Iaa9fdf9deb49c33ec6ca7ed3081c4ddaa920e9aa

Concealment fix for audio frames containing acelp components

Change-Id: Ibe5e83a6efa75a48f729984a161a76b826878f4e

Fix out-of-bounds access in PS concealment

Change-Id: I08809a03a40d1feaf00e41278db314d67e1efe88

Fix potential memory leak in setup of qmf domain

Change-Id: Id9fc2448354dc7f1b439469128407305efa3def2

Reject channel config 13

Change-Id: Idf5236f6cd054df994e69c9c972c97f6768cf9e5

Fix unsigned integer overflow in configExtension()

Change-Id: I8a1668810b85e6237c3892891444ff08f04b019b

Fix unsigned integer overflow in CAacDecoder_DecodeFrame()

Change-Id: I79678c571690178e6c37680f70a9b94dd3cbc439

Fix unsigned integer overflow in aacDecoder_UpdateBitStreamCounters()

Change-Id: I3bff959da9f53fabb18cd0ae6c260e6256194526

Fix unsigned integer overflow in transportDec_readStream()

Change-Id: I6a6f9f4acaa32fae0b5de9641f8787bbc7f8286b
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 3cbdffd..b8b1327 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1589,9 +1589,6 @@
     case 14:
       ascChannels = 8;
       break;
-    case 13: /* 22.2 setup */
-      ascChannels = 24;
-      break;
     default:
       return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
   }
@@ -2837,7 +2834,7 @@
               /* usacExtElementStop = 1; */
             }
 
-            usacExtBitPos = FDKgetValidBits(bs);
+            usacExtBitPos = (INT)FDKgetValidBits(bs);
 
             USAC_EXT_ELEMENT_TYPE usacExtElementType =
                 self->pUsacConfig[streamIndex]
@@ -2862,7 +2859,7 @@
 
             /* Skip any remaining bits of extension payload */
             usacExtBitPos = (usacExtElementPayloadLength * 8) -
-                            (usacExtBitPos - FDKgetValidBits(bs));
+                            (usacExtBitPos - (INT)FDKgetValidBits(bs));
             if (usacExtBitPos < 0) {
               self->frameOK = 0;
               ErrorStatus = AAC_DEC_PARSE_ERROR;
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index e62d187..cd112b6 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1082,15 +1082,15 @@
 
   /* bit/byte counters */
   {
-    int nBytes;
+    INT nBytes;
 
     nBytes = nBits >> 3;
-    pSi->numTotalBytes += nBytes;
+    pSi->numTotalBytes = (UINT)((INT)pSi->numTotalBytes + nBytes);
     if (IS_OUTPUT_VALID(ErrorStatus)) {
       pSi->numTotalAccessUnits++;
     }
     if (IS_DECODE_ERROR(ErrorStatus)) {
-      pSi->numBadBytes += nBytes;
+      pSi->numBadBytes = (UINT)((INT)pSi->numBadBytes + nBytes);
       pSi->numBadAccessUnits++;
     }
   }
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
index 91ba488..a6064b6 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -158,8 +158,8 @@
 #define CONCEAL_NOT_DEFINED ((UCHAR)-1)
 
 /* default settings */
-#define CONCEAL_DFLT_FADEOUT_FRAMES (0)
-#define CONCEAL_DFLT_FADEIN_FRAMES (0)
+#define CONCEAL_DFLT_FADEOUT_FRAMES (6)
+#define CONCEAL_DFLT_FADEIN_FRAMES (5)
 #define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0)
 
 #define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index ec4437f..af1f488 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -1116,7 +1116,8 @@
                                   const FIXP_LPC *A_new, const INT A_new_exp,
                                   const FIXP_LPC *A_old, const INT A_old_exp,
                                   CAcelpStaticMem *acelp_mem,
-                                  INT coreCoderFrameLength, UCHAR lpd_mode) {
+                                  INT coreCoderFrameLength, INT clearOldExc,
+                                  UCHAR lpd_mode) {
   int l_div =
       coreCoderFrameLength / NB_DIV; /* length of one ACELP/TCX20 frame */
   int l_div_partial;
@@ -1154,6 +1155,13 @@
             &syn[PIT_MAX_MAX + L_INTERPOL - M_LP_FILTER_ORDER],
             M_LP_FILTER_ORDER * sizeof(FIXP_DBL));
 
+  if (clearOldExc) {
+    FDKmemclear(old_exc_mem, (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL));
+    C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL,
+                        PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER);
+    return;
+  }
+
   /* update past [PIT_MAX_MAX+L_INTERPOL] samples of exc memory */
   if (last_lpd_mode == 1) {        /* last frame was TCX20 */
     if (last_last_lpd_mode == 0) { /* ACELP -> TCX20 -> ACELP transition */
@@ -1170,7 +1178,6 @@
     int exc_A_new_length = (coreCoderFrameLength / 2 > PIT_MAX_MAX + L_INTERPOL)
                                ? PIT_MAX_MAX + L_INTERPOL
                                : coreCoderFrameLength / 2;
-
     int exc_A_old_length = PIT_MAX_MAX + L_INTERPOL - exc_A_new_length;
     E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, exc_A_old_length);
     E_UTIL_residu(A_new, A_new_exp, &syn[exc_A_old_length],
diff --git a/libAACdec/src/usacdec_acelp.h b/libAACdec/src/usacdec_acelp.h
index 593a073..9de41ff 100644
--- a/libAACdec/src/usacdec_acelp.h
+++ b/libAACdec/src/usacdec_acelp.h
@@ -238,7 +238,8 @@
                                   const FIXP_LPC *A_new, const INT A_new_exp,
                                   const FIXP_LPC *A_old, const INT A_old_exp,
                                   CAcelpStaticMem *acelp_mem,
-                                  INT coreCoderFrameLength, UCHAR lpd_mode);
+                                  INT coreCoderFrameLength, INT clearOldExc,
+                                  UCHAR lpd_mode);
 
 /**
  * \brief Calculate zero input response (zir) of the acelp synthesis filter
diff --git a/libAACdec/src/usacdec_lpd.cpp b/libAACdec/src/usacdec_lpd.cpp
index 4ce6699..22069a6 100644
--- a/libAACdec/src/usacdec_lpd.cpp
+++ b/libAACdec/src/usacdec_lpd.cpp
@@ -1776,7 +1776,7 @@
               pAacDecoderChannelInfo->data.usac.lp_coeff[k],
               pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], lp_prev,
               lp_prev_exp, &pAacDecoderStaticChannelInfo->acelp, lFrame,
-              mod[k]);
+              (last_frame_lost && k < 2), mod[k]);
         }
       } else {
         if (k == 0 && pAacDecoderStaticChannelInfo->IMdct.ov_offset !=
diff --git a/libFDK/include/cplx_mul.h b/libFDK/include/cplx_mul.h
index 9c5da57..eb1afce 100644
--- a/libFDK/include/cplx_mul.h
+++ b/libFDK/include/cplx_mul.h
@@ -260,26 +260,6 @@
 }
 #endif
 
-#if !defined(FUNCTION_cplxMult_nIm)
-#define FUNCTION_cplxMult_nIm
-
-/* Same as cplxMult, but
-   a_Im must be negated, when used
-   c_re must be negated, when output
-*/
-inline void cplxMult_nIm(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re,
-                         const FIXP_DBL a_Im, const FIXP_SPK w) {
-  *c_Re = -(fMult(a_Re, w.v.re) + fMult(a_Im, w.v.im));
-  *c_Im = fMult(a_Re, w.v.im) - fMult(a_Im, w.v.re);
-}
-
-inline void cplxMult_nIm(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re,
-                         const FIXP_DBL a_Im, const FIXP_DPK w) {
-  *c_Re = -(fMult(a_Re, w.v.re) + fMult(a_Im, w.v.im));
-  *c_Im = fMult(a_Re, w.v.im) - fMult(a_Im, w.v.re);
-}
-#endif
-
   /* #############################################################################
    */
 
diff --git a/libFDK/include/mdct.h b/libFDK/include/mdct.h
index e671da9..1382374 100644
--- a/libFDK/include/mdct.h
+++ b/libFDK/include/mdct.h
@@ -119,6 +119,7 @@
 #define IMDCT_SCALE(x) SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, PCM_OUT_BITS)
 #endif
 #define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x)
+#define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS)
 
 #define MLT_FLAG_CURR_ALIAS_SYMMETRY 1
 
diff --git a/libFDK/src/FDK_lpc.cpp b/libFDK/src/FDK_lpc.cpp
index 2ba7707..7d7e691 100644
--- a/libFDK/src/FDK_lpc.cpp
+++ b/libFDK/src/FDK_lpc.cpp
@@ -184,12 +184,19 @@
   for (i = signal_size; i != 0; i--) {
     FIXP_DBL *pState = state + order - 1;
     const FIXP_DBL *pCoeff = coeff + order - 1;
-    FIXP_DBL tmp;
+    FIXP_DBL tmp, accu;
 
-    tmp = scaleValue(*pSignal, signal_e) - fMult(*pCoeff--, *pState--);
+    accu =
+        fMultSubDiv2(scaleValue(*pSignal, signal_e - 1), *pCoeff--, *pState--);
+    tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
+
     for (j = order - 1; j != 0; j--) {
-      tmp = tmp - fMult(pCoeff[0], pState[0]);
-      pState[1] = pState[0] + fMult(*pCoeff--, tmp);
+      accu = fMultSubDiv2(tmp >> 1, pCoeff[0], pState[0]);
+      tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
+
+      accu = fMultAddDiv2(pState[0] >> 1, *pCoeff--, tmp);
+      pState[1] = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
+
       pState--;
     }
 
diff --git a/libFDK/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp
index 4b78931..043a372 100644
--- a/libFDK/src/FDK_qmf_domain.cpp
+++ b/libFDK/src/FDK_qmf_domain.cpp
@@ -274,17 +274,28 @@
     size = gc->nBandsAnalysis * 10;
     if (size > 0) {
       if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_16) {
-        if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates16(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates16(ch)))
+            goto bail;
+        }
       } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_24) {
-        if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates24(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates24(ch)))
+            goto bail;
+        }
       } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_32) {
-        if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates32(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates32(ch)))
+            goto bail;
+        }
       } else {
-        if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) {
+          if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates(ch)))
+            goto bail;
+        }
       }
     } else {
       qd->QmfDomainIn[ch].pAnaQmfStates = NULL;
@@ -293,20 +304,36 @@
     size = gc->nQmfOvTimeSlots + gc->nQmfTimeSlots;
     if (size > 0) {
       if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) {
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal16(ch)))
-          goto bail;
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag16(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal16(ch)))
+            goto bail;
+        }
+        if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag16(ch)))
+            goto bail;
+        }
       } else if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) {
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal32(ch)))
-          goto bail;
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag32(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal32(ch)))
+            goto bail;
+        }
+        if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag32(ch)))
+            goto bail;
+        }
       } else {
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal(ch)))
-          goto bail;
-        if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) {
+          if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal(ch)))
+            goto bail;
+        }
+        if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) {
+          if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag(ch)))
+            goto bail;
+        }
       }
     } else {
       qd->QmfDomainIn[ch].hQmfSlotsReal = NULL;
@@ -316,17 +343,23 @@
     size = gc->nQmfOvTimeSlots * gc->nQmfProcBands * CMPLX_MOD;
     if (size > 0) {
       if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_16) {
-        if (NULL ==
-            (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer16(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer16(ch)))
+            goto bail;
+        }
       } else if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_32) {
-        if (NULL ==
-            (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer32(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer32(ch)))
+            goto bail;
+        }
       } else {
-        if (NULL ==
-            (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer(ch)))
-          goto bail;
+        if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) {
+          if (NULL ==
+              (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer(ch)))
+            goto bail;
+        }
       }
     } else {
       qd->QmfDomainIn[ch].pOverlapBuffer = NULL;
@@ -336,8 +369,10 @@
   for (ch = 0; ch < gc->nOutputChannels; ch++) {
     int size = gc->nBandsSynthesis * 9;
     if (size > 0) {
-      if (NULL == (qd->QmfDomainOut[ch].pSynQmfStates = GetSynQmfStates(ch)))
-        goto bail;
+      if (qd->QmfDomainOut[ch].pSynQmfStates == NULL) {
+        if (NULL == (qd->QmfDomainOut[ch].pSynQmfStates = GetSynQmfStates(ch)))
+          goto bail;
+      }
     } else {
       qd->QmfDomainOut[ch].pSynQmfStates = NULL;
     }
diff --git a/libFDK/src/mdct.cpp b/libFDK/src/mdct.cpp
index 6a6604c..d697cfb 100644
--- a/libFDK/src/mdct.cpp
+++ b/libFDK/src/mdct.cpp
@@ -541,11 +541,16 @@
      */
     /* and de-scale current spectrum signal (time domain, no yet windowed) */
     if (gain != (FIXP_DBL)0) {
-      scaleValuesWithFactor(pSpec, gain, tl, scalefactor[w] + specShiftScale);
-    } else {
-      int loc_scale = scalefactor[w] + specShiftScale;
+      for (i = 0; i < tl; i++) {
+        pSpec[i] = fMult(pSpec[i], gain);
+      }
+    }
+
+    {
+      int loc_scale =
+          fixmin_I(scalefactor[w] + specShiftScale, (INT)DFRACT_BITS - 1);
       DWORD_ALIGNED(pSpec);
-      scaleValues(pSpec, tl, loc_scale);
+      scaleValuesSaturate(pSpec, tl, loc_scale);
     }
 
     if (noOutSamples <= nrSamples) {
@@ -614,59 +619,34 @@
         if (!hMdct->pAsymOvlp) {
           for (i = 0; i < fl / 2; i++) {
             FIXP_DBL x0, x1;
-#ifdef FUNCTION_cplxMult_nIm
-            /* This macro negates 4th parameter (*pOvl--) */
-            /* and inverts the sign of result x1          */
-
-            /* This subroutine calculates the two output segments (C,D) from the
-            two availabe  DCT IV data blocks, namely, (-D-Cr,A-Br) and
-            (-F-Er,C-Dr). "pOvl" is the pointer to the overlap block and points
-            to the end of the (-D-Cr) part of the overlap buffer (-D-Cr,A-Br).
-            It points to the end of the (-D-Cr) because it will read this part
-            in a flipped order. "pCurr" is the pointer to the current block
-            (-F-Er,C-Dr) and points to the beginning of the (C-Dr) block,
-            because this block will be read consequitively. "pWindow" is a
-            pointer to the used window coefficients. In pointer "x1" we get the
-            already computed from the function "Dr" segment. In pointer "x0" we
-            get the "C" segment. Since we have to output them sequentially the
-            "x0" pointer points to the beginnig of the output buffer (X,X), and
-            pointer "x1" points to the end of the output buffer (X,X). When we
-            get the output of the cplxMult_nIm function we write it sequentially
-            in the output buffer from the left to right ("x0"=>C) and right to
-            left ("x1"=>Dr) implementing flipping. At the end we get an output
-            in the form (C,D).      */
-            cplxMult_nIm(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
-            *pOut0++ = IMDCT_SCALE_DBL(x0);
-            *pOut1-- = IMDCT_SCALE_DBL(x1);
-#else
-            cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
-            *pOut0 = IMDCT_SCALE_DBL(x0);
-            *pOut1 = IMDCT_SCALE_DBL(-x1);
+            cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
+            *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+            *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
             pOut0++;
             pOut1--;
-#endif /* #ifdef FUNCTION_cplxMult_nIm */
           }
         } else {
           FIXP_DBL *pAsymOvl = hMdct->pAsymOvlp + fl / 2 - 1;
           for (i = 0; i < fl / 2; i++) {
             FIXP_DBL x0, x1;
-            x1 = -fMult(*pCurr, pWindow[i].v.re) +
-                 fMult(*pAsymOvl, pWindow[i].v.im);
-            x0 = fMult(*pCurr, pWindow[i].v.im) - fMult(*pOvl, pWindow[i].v.re);
+            x1 = -fMultDiv2(*pCurr, pWindow[i].v.re) +
+                 fMultDiv2(*pAsymOvl, pWindow[i].v.im);
+            x0 = fMultDiv2(*pCurr, pWindow[i].v.im) -
+                 fMultDiv2(*pOvl, pWindow[i].v.re);
             pCurr++;
             pOvl--;
             pAsymOvl--;
-            *pOut0++ = IMDCT_SCALE_DBL(x0);
-            *pOut1-- = IMDCT_SCALE_DBL(x1);
+            *pOut0++ = IMDCT_SCALE_DBL_LSH1(x0);
+            *pOut1-- = IMDCT_SCALE_DBL_LSH1(x1);
           }
           hMdct->pAsymOvlp = NULL;
         }
       } else { /* prevAliasingSymmetry == 1 */
         for (i = 0; i < fl / 2; i++) {
           FIXP_DBL x0, x1;
-          cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
-          *pOut0 = IMDCT_SCALE_DBL(x0);
-          *pOut1 = IMDCT_SCALE_DBL(x1);
+          cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]);
+          *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+          *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
           pOut0++;
           pOut1--;
         }
@@ -675,18 +655,18 @@
       if (hMdct->prevAliasSymmetry == 0) {
         for (i = 0; i < fl / 2; i++) {
           FIXP_DBL x0, x1;
-          cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
-          *pOut0 = IMDCT_SCALE_DBL(x0);
-          *pOut1 = IMDCT_SCALE_DBL(-x1);
+          cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
+          *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+          *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
           pOut0++;
           pOut1--;
         }
       } else { /* prevAliasingSymmetry == 1 */
         for (i = 0; i < fl / 2; i++) {
           FIXP_DBL x0, x1;
-          cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
-          *pOut0 = IMDCT_SCALE_DBL(x0);
-          *pOut1 = IMDCT_SCALE_DBL(x1);
+          cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]);
+          *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+          *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
           pOut0++;
           pOut1--;
         }
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index b7fd2a1..b0f1c6a 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1618,7 +1618,7 @@
     usacConfigExtLength = (int)escapedValue(hBs, 4, 8, 16);
 
     /* Start bit position of config extension */
-    nbits = FDKgetValidBits(hBs);
+    nbits = (INT)FDKgetValidBits(hBs);
 
     /* Return an error in case the bitbuffer fill level is too low. */
     if (nbits < usacConfigExtLength * 8) {
@@ -1650,7 +1650,7 @@
 
     /* Skip remaining bits. If too many bits were parsed, assume error. */
     usacConfigExtLength =
-        8 * usacConfigExtLength - (nbits - FDKgetValidBits(hBs));
+        8 * usacConfigExtLength - (nbits - (INT)FDKgetValidBits(hBs));
     if (usacConfigExtLength < 0) {
       return TRANSPORTDEC_PARSE_ERROR;
     }
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp
index 5eeb7fc..1d8b7b3 100644
--- a/libMpegTPDec/src/tpdec_lib.cpp
+++ b/libMpegTPDec/src/tpdec_lib.cpp
@@ -1337,9 +1337,9 @@
   INT bitDistance, bfDelta;
 
   /* Obtain distance to next synch word */
-  bitDistance = FDKgetValidBits(hBs);
+  bitDistance = (INT)FDKgetValidBits(hBs);
   error = synchronization(hTp, &headerBits);
-  bitDistance -= FDKgetValidBits(hBs);
+  bitDistance -= (INT)FDKgetValidBits(hBs);
 
   FDK_ASSERT(bitDistance >= 0);
 
@@ -1380,7 +1380,7 @@
         int num, denom;
 
         /* Obtain estimate of number of lost frames */
-        num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) +
+        num = (INT)hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) +
               hTp->remainder;
         denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame;
         if (num > 0) {
diff --git a/libSBRdec/src/psbitdec.cpp b/libSBRdec/src/psbitdec.cpp
index 1521178..f40a156 100644
--- a/libSBRdec/src/psbitdec.cpp
+++ b/libSBRdec/src/psbitdec.cpp
@@ -311,6 +311,7 @@
     pBsData->noEnv = 1;
 
     if (pBsData->bEnableIid) {
+      pBsData->bFineIidQ = h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ;
       for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) {
         pBsData->aaIidIndex[pBsData->noEnv - 1][gr] =
             h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr];
@@ -333,6 +334,9 @@
     }
   }
 
+  /* Update previous frame Iid quantization */
+  h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ = pBsData->bFineIidQ;
+
   /* 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 b6d9a12..6ae1473 100644
--- a/libSBRdec/src/psdec.h
+++ b/libSBRdec/src/psdec.h
@@ -274,7 +274,9 @@
                                                        previous frame */
       SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for
                                                        previous frame */
-      UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */
+      UCHAR
+      bPrevFrameFineIidQ; /*!< The IID quantization of the previous frame */
+      UCHAR lastUsb; /*!< uppermost WMF delay band of last frame          */
 
       FIXP_DBL pHybridAnaStatesLFdmx
           [2 * 13 * NO_QMF_BANDS_HYBRID20]; /*!< Memory used in hybrid analysis
diff --git a/libSBRenc/src/tran_det.cpp b/libSBRenc/src/tran_det.cpp
index b6f1b9f..3b6765a 100644
--- a/libSBRenc/src/tran_det.cpp
+++ b/libSBRenc/src/tran_det.cpp
@@ -269,23 +269,33 @@
   FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f);
   FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f);
   int tran_offdiv2 = tran_off >> nrgSzShift;
+  const int sc1 =
+      DFRACT_BITS -
+      fNormz((FIXP_DBL)fMax(
+          1, (freqBandTable[0] * (YBufferWriteOffset - tran_offdiv2) - 1)));
+  const int sc2 =
+      DFRACT_BITS -
+      fNormz((FIXP_DBL)fMax(
+          1, (freqBandTable[0] *
+                  (tran_offdiv2 + (slots >> nrgSzShift) - YBufferWriteOffset) -
+              1)));
   int ts, k;
 
   /* Sum up lowband energy from one frame at offset tran_off */
   /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */
   for (ts = tran_offdiv2; ts < YBufferWriteOffset; ts++) {
     for (k = 0; k < freqBandTable[0]; k++) {
-      accu1 += Energies[ts][k] >> 6;
+      accu1 += Energies[ts][k] >> sc1;
     }
   }
   for (; ts < tran_offdiv2 + (slots >> nrgSzShift); ts++) {
     for (k = 0; k < freqBandTable[0]; k++) {
-      accu2 += Energies[ts][k] >> 9;
+      accu2 += Energies[ts][k] >> sc2;
     }
   }
 
-  nrgTotal_m = fAddNorm(accu1, 1 - scaleEnergies[0], accu2,
-                        4 - scaleEnergies[1], &nrgTotal_e);
+  nrgTotal_m = fAddNorm(accu1, (sc1 - 5) - scaleEnergies[0], accu2,
+                        (sc2 - 5) - scaleEnergies[1], &nrgTotal_e);
   nrgTotal_m = scaleValueSaturate(nrgTotal_m, nrgTotal_e);
 
   return (nrgTotal_m);