Merge "Adjust eqSubbandGainFormat data type to prevent load of invalid value in _skipEqCoefficients()." into sc-dev
diff --git a/documentation/aacEncoder.pdf b/documentation/aacEncoder.pdf
index 77b8f4c..a47708a 100644
--- a/documentation/aacEncoder.pdf
+++ b/documentation/aacEncoder.pdf
Binary files differ
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index 9d36d10..0c83191 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1626,6 +1626,11 @@
         /* set params */
         sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY,
                             self->sbrParams.bsDelay);
+        sbrDecoder_SetParam(
+            self->hSbrDecoder, SBR_FLUSH_DATA,
+            (flags & AACDEC_FLUSH) |
+                ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
+                                                                  : 0));
 
         sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
 
diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h
index 71f7556..f0f23b4 100644
--- a/libAACenc/include/aacenc_lib.h
+++ b/libAACenc/include/aacenc_lib.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1643,7 +1643,7 @@
  *
  * \return
  *          - AACENC_OK, on succes.
- *          - AACENC_INIT_ERROR, on failure.
+ *          - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure.
  */
 AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder,
                         AACENC_InfoStruct *pInfo);
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index caa62c5..c11db27 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -2521,6 +2521,11 @@
                         AACENC_InfoStruct *pInfo) {
   AACENC_ERROR err = AACENC_OK;
 
+  if ((hAacEncoder == NULL) || (pInfo == NULL)) {
+    err = AACENC_INVALID_HANDLE;
+    goto bail;
+  }
+
   FDKmemclear(pInfo, sizeof(AACENC_InfoStruct));
   pInfo->confSize = 64; /* pre-initialize */
 
diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp
index 22091a9..33a1647 100644
--- a/libSACdec/src/sac_process.cpp
+++ b/libSACdec/src/sac_process.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -517,12 +517,11 @@
       maxVal = fAbs(iReal0) | fAbs(iImag0);
       maxVal |= fAbs(iReal1);
 
-      s = fMax(CntLeadingZeros(maxVal) - 1, 0);
-      s = fMin(s, scale_param_m2);
+      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
 
-      mReal0 = iReal0 << s;
-      mImag0 = iImag0 << s;
-      mReal1 = iReal1 << s;
+      mReal0 = scaleValue(iReal0, s);
+      mImag0 = scaleValue(iImag0, s);
+      mReal1 = scaleValue(iReal1, s);
 
       s = scale_param_m2 - s;
 
@@ -562,12 +561,11 @@
       maxVal = fAbs(iReal0) | fAbs(iImag0);
       maxVal |= fAbs(iReal1);
 
-      s = fMax(CntLeadingZeros(maxVal) - 1, 0);
-      s = fMin(s, scale_param_m2);
+      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
 
-      mReal0 = FX_DBL2FX_SGL(iReal0 << s);
-      mImag0 = FX_DBL2FX_SGL(iImag0 << s);
-      mReal1 = FX_DBL2FX_SGL(iReal1 << s);
+      mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
+      mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
+      mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
 
       s = scale_param_m2 - s;
 
diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp
index 272d009..72f4e58 100644
--- a/libSACdec/src/sac_reshapeBBEnv.cpp
+++ b/libSACdec/src/sac_reshapeBBEnv.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -241,29 +241,56 @@
   }
 }
 
-static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
-                           FIXP_DBL *RESTRICT slotAmp_wet,
-                           FIXP_DBL *RESTRICT pHybOutputRealDry,
-                           FIXP_DBL *RESTRICT pHybOutputImagDry,
-                           FIXP_DBL *RESTRICT pHybOutputRealWet,
-                           FIXP_DBL *RESTRICT pHybOutputImagWet, INT cplxBands,
-                           INT hybBands) {
-  INT qs;
+static inline void slotAmp(
+    FIXP_DBL *RESTRICT slotAmp_dry, INT *RESTRICT slotAmp_dry_e,
+    FIXP_DBL *RESTRICT slotAmp_wet, INT *RESTRICT slotAmp_wet_e,
+    FIXP_DBL *RESTRICT pHybOutputRealDry, FIXP_DBL *RESTRICT pHybOutputImagDry,
+    FIXP_DBL *RESTRICT pHybOutputRealWet, FIXP_DBL *RESTRICT pHybOutputImagWet,
+    INT cplxBands, INT hybBands) {
+  INT qs, s1, s2, headroom_dry, headroom_wet;
   FIXP_DBL dry, wet;
 
+  /* headroom can be reduced by 1 bit due to use of fPow2Div2 */
+  s1 = DFRACT_BITS - 1 - CntLeadingZeros(hybBands + cplxBands);
+  headroom_dry = fMin(getScalefactor(pHybOutputRealDry, hybBands),
+                      getScalefactor(pHybOutputImagDry, cplxBands));
+  headroom_wet = fMin(getScalefactor(pHybOutputRealWet, hybBands),
+                      getScalefactor(pHybOutputImagWet, cplxBands));
+
   dry = wet = FL2FXCONST_DBL(0.0f);
   for (qs = 0; qs < cplxBands; qs++) {
-    dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) +
-                                fPow2Div2(pHybOutputImagDry[qs] << (1)));
-    wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) +
-                                fPow2Div2(pHybOutputImagWet[qs] << (1)));
+    /* sum up dry part */
+    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
+    dry += (fPow2Div2(pHybOutputImagDry[qs] << headroom_dry) >> s1);
+    /* sum up wet part */
+    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
+    wet += (fPow2Div2(pHybOutputImagWet[qs] << headroom_wet) >> s1);
   }
   for (; qs < hybBands; qs++) {
-    dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)));
-    wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)));
+    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
+    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
   }
-  *slotAmp_dry = dry >> (2 * (1));
-  *slotAmp_wet = wet >> (2 * (1));
+
+  /* consider fPow2Div2() */
+  s1 += 1;
+
+  /* normalize dry part, ensure that exponent is even */
+  s2 = fixMax(0, CntLeadingZeros(dry) - 1);
+  *slotAmp_dry = dry << s2;
+  *slotAmp_dry_e = s1 - s2 - 2 * headroom_dry;
+  if (*slotAmp_dry_e & 1) {
+    *slotAmp_dry = *slotAmp_dry >> 1;
+    *slotAmp_dry_e += 1;
+  }
+
+  /* normalize wet part, ensure that exponent is even */
+  s2 = fixMax(0, CntLeadingZeros(wet) - 1);
+  *slotAmp_wet = wet << s2;
+  *slotAmp_wet_e = s1 - s2 - 2 * headroom_wet;
+  if (*slotAmp_wet_e & 1) {
+    *slotAmp_wet = *slotAmp_wet >> 1;
+    *slotAmp_wet_e += 1;
+  }
 }
 
 #if defined(__aarch64__)
@@ -533,6 +560,7 @@
                             INT ts) {
   INT ch, scale;
   INT dryFacSF, slotAmpSF;
+  INT slotAmp_dry_e, slotAmp_wet_e;
   FIXP_DBL tmp, dryFac, envShape;
   FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio;
   FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2];
@@ -594,22 +622,25 @@
         dryFacSF = SF_SHAPE + 2 * dryFacSF;
       }
 
+      slotAmp_dry_e = slotAmp_wet_e = 0;
+
       /* calculate slotAmp_dry and slotAmp_wet */
-      slotAmp(&slotAmp_dry, &slotAmp_wet, &self->hybOutputRealDry__FDK[ch][6],
+      slotAmp(&slotAmp_dry, &slotAmp_dry_e, &slotAmp_wet, &slotAmp_wet_e,
+              &self->hybOutputRealDry__FDK[ch][6],
               &self->hybOutputImagDry__FDK[ch][6],
               &self->hybOutputRealWet__FDK[ch][6],
               &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands);
 
+      /* exponents must be even due to subsequent square root calculation */
+      FDK_ASSERT(((slotAmp_dry_e & 1) == 0) && ((slotAmp_wet_e & 1) == 0));
+
       /* slotAmp_ratio will be scaled by slotAmpSF bits */
       if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) {
-        sc = fixMax(0, CntLeadingZeros(slotAmp_wet) - 1);
-        sc = sc - (sc & 1);
-
-        slotAmp_wet = sqrtFixp(slotAmp_wet << sc);
+        slotAmp_wet = sqrtFixp(slotAmp_wet);
         slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF);
 
         slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry);
-        slotAmpSF = slotAmpSF - (sc >> 1);
+        slotAmpSF = slotAmpSF + (slotAmp_wet_e >> 1) - (slotAmp_dry_e >> 1);
       }
 
       /* calculate common scale factor */
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
index be332c7..0e6affa 100644
--- a/libSACdec/src/sac_stp.cpp
+++ b/libSACdec/src/sac_stp.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -229,15 +229,13 @@
   int n;
   FIXP_DBL scaleY;
   for (n = bands - 1; n >= 0; n--) {
-    scaleY = fMultDiv2(scaleX, *pBP);
+    scaleY = fMult(scaleX, *pBP);
     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputRealDry >> 1) +
-            (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 1)),
-        1, DFRACT_BITS);
+        (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleY),
+        SF_SCALE, DFRACT_BITS);
     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputImagDry >> 1) +
-            (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 1)),
-        1, DFRACT_BITS);
+        (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleY),
+        SF_SCALE, DFRACT_BITS);
     hybOutputRealDry++, hybOutputRealWet++;
     hybOutputImagDry++, hybOutputImagWet++;
     pBP++;
@@ -253,14 +251,11 @@
 
   for (n = bands - 1; n >= 0; n--) {
     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputRealDry >> 1) +
-            (fMultDiv2(*hybOutputRealWet, scaleX) << SF_SCALE),
-        1, DFRACT_BITS);
+        (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleX),
+        SF_SCALE, DFRACT_BITS);
     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputImagDry >> 1) +
-            (fMultDiv2(*hybOutputImagWet, scaleX) << SF_SCALE),
-        1, DFRACT_BITS);
-    ;
+        (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleX),
+        SF_SCALE, DFRACT_BITS);
     hybOutputRealDry++, hybOutputRealWet++;
     hybOutputImagDry++, hybOutputImagWet++;
   }
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index ad5edfe..cefa612 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -664,7 +664,7 @@
         gain_sf[i] = mult_sf - total_power_low_sf + sf2;
         gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]);
         if (gain_sf[i] < 0) {
-          gain[i] >>= -gain_sf[i];
+          gain[i] >>= fMin(DFRACT_BITS - 1, -gain_sf[i]);
           gain_sf[i] = 0;
         }
       } else {
@@ -683,11 +683,6 @@
 
     /* gain[i] = g_inter[i] */
     for (i = 0; i < nbSubsample; ++i) {
-      if (gain_sf[i] < 0) {
-        gain[i] >>= -gain_sf[i];
-        gain_sf[i] = 0;
-      }
-
       /* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */
       FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >>
                      gain_sf[i]; /* to substract this from gain[i] */
@@ -755,23 +750,15 @@
     int gain_adj_sf = gain_adj_2_sf;
 
     for (i = 0; i < nbSubsample; ++i) {
-      gain[i] = fMult(gain[i], gain_adj);
-      gain_sf[i] += gain_adj_sf;
-
-      /* limit gain */
-      if (gain_sf[i] > INTER_TES_SF_CHANGE) {
-        gain[i] = (FIXP_DBL)MAXVAL_DBL;
-        gain_sf[i] = INTER_TES_SF_CHANGE;
-      }
-    }
-
-    for (i = 0; i < nbSubsample; ++i) {
-      /* equalize gain[]'s scale factors */
-      gain[i] >>= INTER_TES_SF_CHANGE - gain_sf[i];
+      int gain_e = fMax(
+          fMin(gain_sf[i] + gain_adj_sf - INTER_TES_SF_CHANGE, DFRACT_BITS - 1),
+          -(DFRACT_BITS - 1));
+      FIXP_DBL gain_final = fMult(gain[i], gain_adj);
+      gain_final = scaleValueSaturate(gain_final, gain_e);
 
       for (j = lowSubband; j < highSubband; j++) {
-        qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain[i]);
-        qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain[i]);
+        qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain_final);
+        qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain_final);
       }
     }
   } else { /* gamma_idx == 0 */
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp
index d210bb6..f2452ea 100644
--- a/libSBRdec/src/hbe.cpp
+++ b/libSBRdec/src/hbe.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1400,42 +1400,27 @@
 
   if (shift_ov != 0) {
     for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) {
-      for (band = 0; band < QMF_SYNTH_CHANNELS; band++) {
-        if (shift_ov >= 0) {
-          hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov;
-          hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov;
-        } else {
-          hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov);
-          hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov);
-        }
-      }
-    }
-  }
-
-  if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) {
-    for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
-      for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand;
-           band++) {
-        if (shift_ov >= 0) {
-          ppQmfBufferOutReal_F[i][band] <<= shift_ov;
-          ppQmfBufferOutImag_F[i][band] <<= shift_ov;
-        } else {
-          ppQmfBufferOutReal_F[i][band] >>= (-shift_ov);
-          ppQmfBufferOutImag_F[i][band] >>= (-shift_ov);
-        }
-      }
+      scaleValuesSaturate(&hQmfTransposer->qmfHBEBufReal_F[i][0],
+                          QMF_SYNTH_CHANNELS, shift_ov);
+      scaleValuesSaturate(&hQmfTransposer->qmfHBEBufImag_F[i][0],
+                          QMF_SYNTH_CHANNELS, shift_ov);
     }
 
-    /* shift lpc filterstates */
-    for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
-      for (band = 0; band < (64); band++) {
-        if (shift_ov >= 0) {
-          lpcFilterStatesReal[i][band] <<= shift_ov;
-          lpcFilterStatesImag[i][band] <<= shift_ov;
-        } else {
-          lpcFilterStatesReal[i][band] >>= (-shift_ov);
-          lpcFilterStatesImag[i][band] >>= (-shift_ov);
-        }
+    if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) {
+      int nBands =
+          fMax(0, hQmfTransposer->stopBand - hQmfTransposer->startBand);
+
+      for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
+        scaleValuesSaturate(&ppQmfBufferOutReal_F[i][hQmfTransposer->startBand],
+                            nBands, shift_ov);
+        scaleValuesSaturate(&ppQmfBufferOutImag_F[i][hQmfTransposer->startBand],
+                            nBands, shift_ov);
+      }
+
+      /* shift lpc filterstates */
+      for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
+        scaleValuesSaturate(&lpcFilterStatesReal[i][0], (64), shift_ov);
+        scaleValuesSaturate(&lpcFilterStatesImag[i][0], (64), shift_ov);
       }
     }
   }