diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index aa8f6a6..fac1540 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.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 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -148,7 +148,7 @@ C_ALLOC_MEM(CplxPredictionData, CCplxPredictionData, 1)
 /*! The buffer holds time samples for the crossfade in case of an USAC DASH IPF
    config change Dimension: (8)
  */
-C_ALLOC_MEM2(TimeDataFlush, INT_PCM, TIME_DATA_FLUSH_SIZE, (8))
+C_ALLOC_MEM2(TimeDataFlush, PCM_DEC, TIME_DATA_FLUSH_SIZE, (8))
 
 /* @} */
 
diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h
index b9b95b7..395b2b2 100644
--- a/libAACdec/src/aac_ram.h
+++ b/libAACdec/src/aac_ram.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 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -132,7 +132,7 @@ H_ALLOC_MEM(CplxPredictionData, CCplxPredictionData)
 H_ALLOC_MEM(SpectralCoeffs, FIXP_DBL)
 H_ALLOC_MEM(SpecScale, SHORT)
 
-H_ALLOC_MEM(TimeDataFlush, INT_PCM)
+H_ALLOC_MEM(TimeDataFlush, PCM_DEC)
 
 H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
 H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index c6d1832..c18e5e9 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -568,7 +568,7 @@ static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,
   \return  Error code
 */
 LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
-    const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved) {
   int i, ch, s1, s2;
   AAC_DECODER_ERROR ErrorStatus;
@@ -584,7 +584,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
   }
 
   for (ch = 0; ch < numChannels; ch++) {
-    const INT_PCM *pIn = &pTimeData[ch * s1];
+    const PCM_DEC *pIn = &pTimeData[ch * s1];
     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
       pTimeDataFlush[ch][i] = *pIn;
       pIn += s2;
@@ -606,7 +606,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
   \return  Error code
 */
 LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
-    INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved) {
   int i, ch, s1, s2;
   AAC_DECODER_ERROR ErrorStatus;
@@ -622,15 +622,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
   }
 
   for (ch = 0; ch < numChannels; ch++) {
-    INT_PCM *pIn = &pTimeData[ch * s1];
+    PCM_DEC *pIn = &pTimeData[ch * s1];
     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
       FIXP_SGL alpha = (FIXP_SGL)i
                        << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF);
-      FIXP_DBL time = FX_PCM2FX_DBL(*pIn);
-      FIXP_DBL timeFlush = FX_PCM2FX_DBL(pTimeDataFlush[ch][i]);
+      FIXP_DBL time = PCM_DEC2FIXP_DBL(*pIn);
+      FIXP_DBL timeFlush = PCM_DEC2FIXP_DBL(pTimeDataFlush[ch][i]);
 
-      *pIn = (INT_PCM)(FIXP_PCM)FX_DBL2FX_PCM(
-          timeFlush - fMult(timeFlush, alpha) + fMult(time, alpha));
+      *pIn = FIXP_DBL2PCM_DEC(timeFlush - fMult(timeFlush, alpha) +
+                              fMult(time, alpha));
       pIn += s2;
     }
   }
@@ -753,7 +753,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse(
     /* We are interested in preroll AUs if an explicit or an implicit config
      * change is signalized in other words if the build up status is set. */
     if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) {
-      self->applyCrossfade |= FDKreadBit(hBs);
+      UCHAR applyCrossfade = FDKreadBit(hBs);
+      if (applyCrossfade) {
+        self->applyCrossfade |= AACDEC_CROSSFADE_BITMASK_PREROLL;
+      } else {
+        self->applyCrossfade &= ~AACDEC_CROSSFADE_BITMASK_PREROLL;
+      }
       FDKreadBit(hBs); /* reserved */
       /* Read num preroll AU's */
       *numPrerollAU = escapedValue(hBs, 2, 4, 0);
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index bd1f38f..002807f 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.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 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -172,6 +172,12 @@ enum {
   AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5
 };
 
+#define AACDEC_CROSSFADE_BITMASK_OFF                                    \
+  ((UCHAR)0) /*!< No cross-fade between frames shall be applied at next \
+                config change. */
+#define AACDEC_CROSSFADE_BITMASK_PREROLL \
+  ((UCHAR)1 << 1) /*!< applyCrossfade is signaled in AudioPreRoll */
+
 typedef struct {
   /* Usac Extension Elements */
   USAC_EXT_ELEMENT_TYPE usacExtElementType[(3)];
@@ -325,7 +331,7 @@ This structure is allocated once for each CPE. */
   UINT loudnessInfoSetPosition[3];
   SCHAR defaultTargetLoudness;
 
-  INT_PCM
+  PCM_DEC
   *pTimeDataFlush[((8) * 2)]; /*!< Pointer to the flushed time data which
                                  will be used for the crossfade in case of
                                  an USAC DASH IPF config change */
@@ -341,8 +347,8 @@ This structure is allocated once for each CPE. */
                                                           start position in the
                                                           bitstream */
   INT accessUnit; /*!< Number of the actual processed preroll accessUnit */
-  UCHAR applyCrossfade; /*!< if set crossfade for seamless stream switching is
-                           applied */
+  UCHAR applyCrossfade; /*!< If any bit is set, cross-fade for seamless stream
+                           switching is applied */
 
   FDK_SignalDelay usacResidualDelay; /*!< Delay residual signal to compensate
                                         for eSBR delay of DMX signal in case of
@@ -439,12 +445,12 @@ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self,
 
 /* Prepare crossfade for USAC DASH IPF config change */
 LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
-    const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved);
 
 /* Apply crossfade for USAC DASH IPF config change */
 LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
-    INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved);
 
 /* Set flush and build up mode */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index 6fb7bf1..5efa369 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1155,6 +1155,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
   int applyCrossfade = 1;    /* flag indicates if flushing was possible */
   PCM_DEC *pTimeData2;
   PCM_AAC *pTimeData3;
+  INT pcmLimiterScale = 0;
+  INT interleaved = 0;
 
   if (self == NULL) {
     return AAC_DEC_INVALID_HANDLE;
@@ -1800,8 +1802,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
       }
 
       if (self->streamInfo.extAot != AOT_AAC_SLS) {
-        INT pcmLimiterScale = 0;
-        INT interleaved = 0;
+        interleaved = 0;
         interleaved |= (self->sbrEnabled) ? 1 : 0;
         interleaved |= (self->mpsEnableCurr) ? 1 : 0;
         PCMDMX_ERROR dmxErr = PCMDMX_OK;
@@ -1832,145 +1833,38 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
            * predictable behavior and thus maybe produce strange output. */
           ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
         }
-
-        pcmLimiterScale += PCM_OUT_HEADROOM;
-
-        if (flags & AACDEC_CLRHIST) {
-          if (!(self->flags[0] & AC_USAC)) {
-            /* Reset DRC data */
-            aacDecoder_drcReset(self->hDrcInfo);
-            /* Delete the delayed signal. */
-            pcmLimiter_Reset(self->hLimiter);
-          }
-        }
-
-        /* Set applyExtGain if DRC processing is enabled and if
-           progRefLevelPresent is present for the first time. Consequences: The
-           headroom of the output signal can be set to AACDEC_DRC_GAIN_SCALING
-           only for audio formats which support legacy DRC Level Normalization.
-                         For all other audio formats the headroom of the output
-           signal is set to PCM_OUT_HEADROOM. */
-        if (self->hDrcInfo->enable &&
-            (self->hDrcInfo->progRefLevelPresent == 1)) {
-          self->hDrcInfo->applyExtGain |= 1;
-        }
-
-        /* Check whether time data buffer is large enough. */
-        if (timeDataSize <
-            (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
-          ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
-          goto bail;
-        }
-
-        if (self->limiterEnableCurr) {
-          /* use workBufferCore2 buffer for interleaving */
-          PCM_LIM *pInterleaveBuffer;
-          int blockLength = self->streamInfo.frameSize;
-
-          /* Set actual signal parameters */
-          pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
-          pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
-
-          if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
-              (self->mpsEnableCurr)) {
-            pInterleaveBuffer = (PCM_LIM *)pTimeData2;
-          } else {
-            pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
-
-            /* applyLimiter requests for interleaved data */
-            /* Interleave ouput buffer */
-            FDK_interleave(pTimeData2, pInterleaveBuffer,
-                           self->streamInfo.numChannels, blockLength,
-                           self->streamInfo.frameSize);
-          }
-
-          FIXP_DBL *pGainPerSample = NULL;
-
-          if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
-            pGainPerSample = self->workBufferCore1;
-
-            if ((INT)GetRequiredMemWorkBufferCore1() <
-                (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
-              ErrorStatus = AAC_DEC_UNKNOWN;
-              goto bail;
-            }
-
-            pcmLimiterScale = applyDrcLevelNormalization(
-                self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
-                pGainPerSample, pcmLimiterScale, self->extGainDelay,
-                self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
-          }
-
-          pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
-                           pGainPerSample, pcmLimiterScale,
-                           self->streamInfo.frameSize);
-
-          {
-            /* Announce the additional limiter output delay */
-            self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
-          }
-        } else {
-          if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
-            pcmLimiterScale = applyDrcLevelNormalization(
-                self->hDrcInfo, pTimeData2, self->extGain, NULL,
-                pcmLimiterScale, self->extGainDelay, self->streamInfo.frameSize,
-                self->streamInfo.numChannels,
-                (interleaved || (self->streamInfo.numChannels == 1))
-                    ? 1
-                    : self->streamInfo.frameSize,
-                0);
-          }
-
-          /* If numChannels = 1 we do not need interleaving. The same applies if
-          SBR or MPS are used, since their output is interleaved already
-          (resampled or not) */
-          if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
-              (self->mpsEnableCurr)) {
-            scaleValuesSaturate(
-                pTimeData, pTimeData2,
-                self->streamInfo.frameSize * self->streamInfo.numChannels,
-                pcmLimiterScale);
-
-          } else {
-            scaleValuesSaturate(
-                (INT_PCM *)self->workBufferCore2, pTimeData2,
-                self->streamInfo.frameSize * self->streamInfo.numChannels,
-                pcmLimiterScale);
-            /* Interleave ouput buffer */
-            FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
-                           self->streamInfo.numChannels,
-                           self->streamInfo.frameSize,
-                           self->streamInfo.frameSize);
-          }
-        }
-      } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+      }
 
       if (self->flags[0] & AC_USAC) {
         if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON &&
             !(flags & AACDEC_CONCEAL)) {
-          CAacDecoder_PrepareCrossFade(pTimeData, self->pTimeDataFlush,
+          CAacDecoder_PrepareCrossFade(pTimeData2, self->pTimeDataFlush,
                                        self->streamInfo.numChannels,
-                                       self->streamInfo.frameSize, 1);
+                                       self->streamInfo.frameSize, interleaved);
         }
 
         /* prepare crossfade buffer for fade in */
-        if (!applyCrossfade && self->applyCrossfade &&
+        if (!applyCrossfade &&
+            (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
             !(flags & AACDEC_CONCEAL)) {
           for (int ch = 0; ch < self->streamInfo.numChannels; ch++) {
             for (int i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
-              self->pTimeDataFlush[ch][i] = 0;
+              self->pTimeDataFlush[ch][i] = (PCM_DEC)0;
             }
           }
           applyCrossfade = 1;
         }
 
-        if (applyCrossfade && self->applyCrossfade &&
+        if (applyCrossfade &&
+            (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
             !(accessUnit < numPrerollAU) &&
             (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) {
-          CAacDecoder_ApplyCrossFade(pTimeData, self->pTimeDataFlush,
+          CAacDecoder_ApplyCrossFade(pTimeData2, self->pTimeDataFlush,
                                      self->streamInfo.numChannels,
-                                     self->streamInfo.frameSize, 1);
-          self->applyCrossfade = 0;
+                                     self->streamInfo.frameSize, interleaved);
+          self->applyCrossfade =
+              AACDEC_CROSSFADE_BITMASK_OFF; /* disable cross-fade between frames
+                                               at nect config change */
         }
       }
 
@@ -2012,6 +1906,116 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
            ((self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) &&
             !(flags & AACDEC_CONCEAL)));
 
+  if (self->streamInfo.extAot != AOT_AAC_SLS) {
+    pcmLimiterScale += PCM_OUT_HEADROOM;
+
+    if (flags & AACDEC_CLRHIST) {
+      if (!(self->flags[0] & AC_USAC)) {
+        /* Reset DRC data */
+        aacDecoder_drcReset(self->hDrcInfo);
+        /* Delete the delayed signal. */
+        pcmLimiter_Reset(self->hLimiter);
+      }
+    }
+
+    /* Set applyExtGain if DRC processing is enabled and if progRefLevelPresent
+       is present for the first time. Consequences: The headroom of the output
+       signal can be set to AACDEC_DRC_GAIN_SCALING only for audio formats which
+       support legacy DRC Level Normalization. For all other audio formats the
+       headroom of the output signal is set to PCM_OUT_HEADROOM. */
+    if (self->hDrcInfo->enable && (self->hDrcInfo->progRefLevelPresent == 1)) {
+      self->hDrcInfo->applyExtGain |= 1;
+    }
+
+    /* Check whether time data buffer is large enough. */
+    if (timeDataSize <
+        (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
+      ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+      goto bail;
+    }
+
+    if (self->limiterEnableCurr) {
+      /* use workBufferCore2 buffer for interleaving */
+      PCM_LIM *pInterleaveBuffer;
+      int blockLength = self->streamInfo.frameSize;
+
+      /* Set actual signal parameters */
+      pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
+      pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
+
+      if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
+          (self->mpsEnableCurr)) {
+        pInterleaveBuffer = (PCM_LIM *)pTimeData2;
+      } else {
+        pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
+
+        /* applyLimiter requests for interleaved data */
+        /* Interleave ouput buffer */
+        FDK_interleave(pTimeData2, pInterleaveBuffer,
+                       self->streamInfo.numChannels, blockLength,
+                       self->streamInfo.frameSize);
+      }
+
+      FIXP_DBL *pGainPerSample = NULL;
+
+      if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+        pGainPerSample = self->workBufferCore1;
+
+        if ((INT)GetRequiredMemWorkBufferCore1() <
+            (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
+          ErrorStatus = AAC_DEC_UNKNOWN;
+          goto bail;
+        }
+
+        pcmLimiterScale = applyDrcLevelNormalization(
+            self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
+            pGainPerSample, pcmLimiterScale, self->extGainDelay,
+            self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
+      }
+
+      pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
+                       pGainPerSample, pcmLimiterScale,
+                       self->streamInfo.frameSize);
+
+      {
+        /* Announce the additional limiter output delay */
+        self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
+      }
+    } else {
+      if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+        pcmLimiterScale = applyDrcLevelNormalization(
+            self->hDrcInfo, pTimeData2, self->extGain, NULL, pcmLimiterScale,
+            self->extGainDelay, self->streamInfo.frameSize,
+            self->streamInfo.numChannels,
+            (interleaved || (self->streamInfo.numChannels == 1))
+                ? 1
+                : self->streamInfo.frameSize,
+            0);
+      }
+
+      /* If numChannels = 1 we do not need interleaving. The same applies if SBR
+      or MPS are used, since their output is interleaved already (resampled or
+      not) */
+      if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
+          (self->mpsEnableCurr)) {
+        scaleValuesSaturate(
+            pTimeData, pTimeData2,
+            self->streamInfo.frameSize * self->streamInfo.numChannels,
+            pcmLimiterScale);
+
+      } else {
+        scaleValuesSaturate(
+            (INT_PCM *)self->workBufferCore2, pTimeData2,
+            self->streamInfo.frameSize * self->streamInfo.numChannels,
+            pcmLimiterScale);
+        /* Interleave ouput buffer */
+        FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
+                       self->streamInfo.numChannels, self->streamInfo.frameSize,
+                       self->streamInfo.frameSize);
+      }
+    }
+  } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+
 bail:
 
   /* error in renderer part occurred, ErrorStatus was set to invalid output */