AAC/SBR decoder improvements and bugfixes

* AAC-Decoder

   - Add support for AOT 20 (ER-AAC scalable) (base layer only)
   - Add support for AAC as used in Digital Radio Mondiale (DRM30/DRM+)
     Modified file(s):
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp
        libFDK/src/FDK_core.cpp
        libFDK/src/FDK_tools_rom.cpp
        libMpegTPDec/src/tpdec_asc.cpp
        libMpegTPDec/src/tpdec_lib.cpp
        libMpegTPDec/src/version
        libSBRdec/include/sbrdecoder.h
        libSBRdec/src/env_extr.h
        libSBRdec/src/sbrdecoder.cpp
     Added file(s):
        libMpegTPDec/src/tpdec_drm.cpp
        libMpegTPDec/src/tpdec_drm.h

   - Fix sanity check in HCR module that was performed at the wrong point in time.
     Modified file(s):
        libAACdec/src/aacdecoder_lib.cpp
        libAACdec/src/block.cpp

   - Extend core sampling rate support up to 96 kHz.
     Modified file(s):
        libAACdec/src/aac_rom.cpp
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp

   - Return correct audio output channel description according number of output
     channels.
     Modified file(s):
        libAACdec/src/aacdecoder_lib.cpp

   - Indroduce decoder intern output buffer. This change allows to use framework
     output buffer with the actual size of the deocder output channels.
     Modified file(s):
        libAACdec/include/aacdecoder_lib.h
        libAACdec/src/aacdecoder.h
        libAACdec/src/aacdecoder_lib.cpp

* SBR-Decoder

   - Increase robustness for erroneous input data.
   - Improve error concealment performance.
   - Fix handling of lowest sub-band for LD-SBR
     Modified file(s):
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp
        libSBRdec/src/env_calc.cpp
        libSBRdec/src/env_dec.cpp
        libSBRdec/src/env_extr.cpp
        libSBRdec/src/env_extr.h
        libSBRdec/src/sbr_dec.cpp
        libSBRdec/src/sbr_rom.cpp
        libSBRdec/src/sbr_rom.h
        libSBRdec/src/sbrdecoder.cpp

   - Add QMF delay compensation for ELD v2 streams decoded with the complex
     low delay filter-bank.
     Modified file(s):
        libSBRdec/src/sbr_dec.cpp
        libSBRdec/src/sbr_dec.h
        libSBRdec/src/sbrdecoder.cpp

   - Introduce a different handling of frames to be flushed
     dependent on whether there are delayed frames available or not.
     Modified file(s):
        libSBRdec/src/sbr_ram.h
        libSBRdec/src/sbrdecoder.cpp

   - Calculate the correct number of samples for dual-mono copy in case of no
     available PS data.
     Modified file(s):
        libSBRdec/src/sbrdecoder.cpp

* SYS-Library

   - Change include order of genericStds.h to prevent conflict with definitions
     which are also used in math.h.
     Modified file(s):
        libSYS/src/genericStds.cpp

Change-Id: I3ecffbad85f39b056213107955cfadbeb3f4b6e1
diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf
index d388576..458fda1 100644
--- a/documentation/aacDecoder.pdf
+++ b/documentation/aacDecoder.pdf
Binary files differ
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
index a0c0854..7ab60f1 100644
--- a/libAACdec/include/aacdecoder_lib.h
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -378,6 +378,7 @@
                                                          not exist. */
   AAC_DEC_NEED_TO_RESTART                = 0x200B,  /*!< The decoder needs to be restarted, since the requiered configuration change cannot be
                                                          performed. */
+  AAC_DEC_OUTPUT_BUFFER_TOO_SMALL        = 0x200C,  /*!< The provided output buffer is too small. */
   aac_dec_init_error_end                 = 0x2FFF,
 
   /* Decode errors. Output buffer is valid but concealed. */
diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp
index 607cb3b..f3c9b5a 100644
--- a/libAACdec/src/aac_rom.cpp
+++ b/libAACdec/src/aac_rom.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -167,6 +167,36 @@
 } ;
 
 
+/* 41 scfbands */
+static const SHORT sfb_96_1024[42] =
+{
+     0,    4,    8,   12,   16,   20,   24,   28,   32,   36,   40,   44,
+    48,   52,   56,   64,   72,   80,   88,   96,  108,  120,  132,  144,
+   156,  172,  188,  212,  240,  276,  320,  384,  448,  512,  576,  640,
+   704,  768,  832,  896,  960, 1024
+};
+/* 12 scfbands */
+static const SHORT sfb_96_128[13] =
+{
+     0,    4,    8,   12,   16,   20,   24,   32,   40,   48,    64,  92,
+   128
+};
+
+/* 47 scfbands*/
+static const SHORT sfb_64_1024[48] =
+{
+     0,   4,   8,  12,  16,  20,  24,   28,  32,  36,  40,  44,  48,  52,
+    56,  64,  72,  80,  88, 100, 112,  124, 140, 156, 172, 192, 216, 240,
+   268, 304, 344, 384, 424, 464, 504,  544, 584, 624, 664, 704, 744, 784,
+   824, 864, 904, 944, 984,1024
+};
+
+/* 12 scfbands */
+static const SHORT sfb_64_128[13] =
+{
+     0,   4,   8,  12,  16,  20,  24,
+    32,  40,  48,  64,  92, 128
+};
 
 /* 49 scfbands */
 static const SHORT sfb_48_1024[50] = {
@@ -239,6 +269,35 @@
 };
 
 
+static const SHORT sfb_96_960[42] =
+{
+  0,      4,      8,      12,     16,     20,     24,     28,     32,     36,
+  40,     44,     48,     52,     56,     64,     72,     80,     88,     96,
+  108,    120,    132,    144,    156,    172,    188,    212,    240,    276,
+  320,    384,    448,    512,    576,    640,    704,    768,    832,    896,
+  960
+};   /* 40 scfbands */
+
+static const SHORT sfb_96_120[13] =
+{
+  0,      4,      8,      12,     16,     20,     24,     32,     40,     48,
+  64,     92,     120
+};   /* 12 scfbands */
+
+static const SHORT sfb_64_960[47] =
+{
+  0,      4,      8,      12,     16,     20,     24,     28,     32,     36,
+  40,     44,     48,     52,     56,     64,     72,     80,     88,     100,
+  112,    124,    140,    156,    172,    192,    216,    240,    268,    304,
+  344,    384,    424,    464,    504,    544,    584,    624,    664,    704,
+  744,    784,    824,    864,    904,    944,    960
+};   /* 46 scfbands */
+
+static const SHORT sfb_64_120[13] =
+{
+  0,      4,      8,      12,     16,     20,     24,     32,     40,     48,
+  64,     92,     120
+};   /* 12 scfbands */
 
 static const SHORT sfb_48_960[50] =
 {
@@ -358,9 +417,9 @@
 const SFB_INFO sfbOffsetTables[5][16] =
 {
   {
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
+    { sfb_96_1024, sfb_96_128, 41, 12 },
+    { sfb_96_1024, sfb_96_128, 41, 12 },
+    { sfb_64_1024, sfb_64_128, 47, 12 },
     { sfb_48_1024, sfb_48_128, 49, 14 },
     { sfb_48_1024, sfb_48_128, 49, 14 },
     { sfb_32_1024, sfb_48_128, 51, 14 },
@@ -372,9 +431,9 @@
     { sfb_8_1024, sfb_8_128, 40, 15 },
     { sfb_8_1024, sfb_8_128, 40, 15 },
   }, {
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
+    { sfb_96_960, sfb_96_120, 40, 12 },
+    { sfb_96_960, sfb_96_120, 40, 12 },
+    { sfb_64_960, sfb_64_120, 46, 12 },
     { sfb_48_960, sfb_48_120, 49, 14 },
     { sfb_48_960, sfb_48_120, 49, 14 },
     { sfb_32_960, sfb_48_120, 49, 14 },
@@ -388,9 +447,9 @@
   }, {
     { NULL, NULL, 0, 0 },
   }, {
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
+    { sfb_48_512,  NULL, 36, 0 },
+    { sfb_48_512,  NULL, 36, 0 },
+    { sfb_48_512,  NULL, 36, 0 },
     { sfb_48_512,  NULL, 36, 0 },
     { sfb_48_512, NULL, 36, 0},
     { sfb_32_512, NULL, 37, 0 },
@@ -402,9 +461,9 @@
     { sfb_24_512, NULL, 31, 0 },
     { sfb_24_512, NULL, 31, 0 },
   }, {
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
-    { NULL, NULL, 0, 0 },
+    { sfb_48_480, NULL, 35, 0 },
+    { sfb_48_480, NULL, 35, 0 },
+    { sfb_48_480, NULL, 35, 0 },
     { sfb_48_480, NULL, 35, 0 },
     { sfb_48_480, NULL, 35, 0 },
     { sfb_32_480, NULL, 37, 0 },
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 8270f69..579e470 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -157,6 +157,7 @@
 
 #include "conceal.h"
 
+  #include "FDK_crc.h"
 
 
 void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self)
@@ -537,8 +538,9 @@
                 previous_element,
                 elIndex,
                 self->flags & AC_INDEP );
-        /* Enable SBR for implicit SBR signalling. */
-        if (sbrError == SBRDEC_OK) {
+        /* Enable SBR for implicit SBR signalling but only if no severe error happend. */
+        if ( (sbrError == SBRDEC_OK)
+          || (sbrError == SBRDEC_PARSE_ERROR) ) {
           self->sbrEnabled = 1;
         }
       } else {
@@ -553,7 +555,7 @@
         FDKpushBiDirectional(hBs, *count);
         *count = 0;
       } else {
-        /* If this is not a fill element with a known length, we are screwed an no further parsing makes sense. */
+        /* If this is not a fill element with a known length, we are screwed and further parsing makes no sense. */
         if (sbrError != SBRDEC_OK) {
           self->frameOK = 0;
         }
@@ -832,12 +834,18 @@
   switch (asc->m_aot) {
   case AOT_AAC_LC:
     self->streamInfo.profile = 1;
-    break;
+
+  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;
+    }
 
   case AOT_SBR:
   case AOT_PS:
   case AOT_ER_AAC_LD:
   case AOT_ER_AAC_ELD:
+  case AOT_DRM_AAC:
     break;
 
   default:
@@ -957,11 +965,20 @@
 
   if (asc->m_aot == AOT_ER_AAC_ELD) {
     self->flags |=  AC_ELD;
+    self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;  /* Need to set the SBR flag for backward-compatibility
+                                                                     reasons. Even if SBR is not supported. */
     self->flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
     self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 0;
   }
   self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
   self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
+  if ( asc->m_aot == AOT_DRM_AAC ) {
+    self->flags |= AC_DRM|AC_SBRCRC|AC_SCALABLE;
+  }
+  if ( (asc->m_aot == AOT_AAC_SCAL)
+    || (asc->m_aot == AOT_ER_AAC_SCAL) ) {
+    self->flags |= AC_SCALABLE;
+  }
 
 
   if (asc->m_sbrPresentFlag) {
@@ -1147,6 +1164,9 @@
 
   /* Check sampling frequency  */
   switch ( self->streamInfo.aacSampleRate ) {
+    case 96000:
+    case 88200:
+    case 64000:
     case 16000:
     case 12000:
    case 11025:
@@ -1475,7 +1495,7 @@
           /* get the remaining bits of this frame */
           bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
 
-          if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD)) )
+          if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_DRM)) )
           {
             SBR_ERROR err = SBRDEC_OK;
             int  elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE];
@@ -1513,6 +1533,13 @@
           }
 
 
+          if (self->flags & AC_DRM)
+          {
+            if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) {
+              FDKpushBiDirectional(bs, bitCnt);
+            }
+          }
+
           if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) )
           {
             while ( bitCnt > 7 ) {
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index 3541773..25bc35d 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -226,6 +226,8 @@
   FIXP_DBL     extGain[1];                           /*!< Gain that must be applied to the output signal. */
   UINT         extGainDelay;                         /*!< Delay that must be accounted for extGain. */
 
+  INT_PCM      pcmOutputBuffer[(8)*(2048)];
+
 };
 
 
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index b501eb9..8863da5 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -110,7 +110,7 @@
 /* Decoder library info */
 #define AACDECODER_LIB_VL0 2
 #define AACDECODER_LIB_VL1 5
-#define AACDECODER_LIB_VL2 11
+#define AACDECODER_LIB_VL2 17
 #define AACDECODER_LIB_TITLE "AAC Decoder Lib"
 #ifdef __ANDROID__
 #define AACDECODER_LIB_BUILD_DATE ""
@@ -181,8 +181,9 @@
           break;
         }
         /* if baselayer is OK we continue decoding */
-        if(layer  >= 1){
+        if(layer >= 1){
           self->nrOfLayers = layer;
+          err = AAC_DEC_OK;
         }
         break;
       }
@@ -785,8 +786,8 @@
 
 LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
         HANDLE_AACDECODER  self,
-        INT_PCM           *pTimeData,
-        const INT          timeDataSize,
+        INT_PCM           *pTimeData_extern,
+        const INT          timeDataSize_extern,
         const UINT         flags)
 {
     AAC_DECODER_ERROR ErrorStatus;
@@ -796,12 +797,17 @@
     HANDLE_FDK_BITSTREAM hBs;
     int fTpInterruption = 0;  /* Transport originated interruption detection. */
     int fTpConceal = 0;       /* Transport originated concealment. */
+    INT_PCM *pTimeData = NULL;
+    INT timeDataSize = 0;
 
 
     if (self == NULL) {
       return AAC_DEC_INVALID_HANDLE;
     }
 
+    pTimeData = self->pcmOutputBuffer;
+    timeDataSize = sizeof(self->pcmOutputBuffer)/sizeof(*self->pcmOutputBuffer);
+
     if (flags & AACDEC_INTR) {
       self->streamInfo.numLostAccessUnits = 0;
     }
@@ -918,7 +924,8 @@
     if (self->sbrEnabled)
     {
       SBR_ERROR sbrError = SBRDEC_OK;
-      int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex;
+      int chIdx, numCoreChannel = self->streamInfo.numChannels;
+      int chOutMapIdx = ((self->chMapIndex==0) && (numCoreChannel<7)) ? numCoreChannel : self->chMapIndex;
 
       /* set params */
       sbrDecoder_SetParam ( self->hSbrDecoder,
@@ -978,10 +985,10 @@
 
        if (self->psPossible) {
          self->flags |= AC_PS_PRESENT;
-         self->channelType[0] = ACT_FRONT;
-         self->channelType[1] = ACT_FRONT;
-         self->channelIndices[0] = 0;
-         self->channelIndices[1] = 1;
+       }
+       for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; chIdx+=1) {
+         self->channelType[chIdx] = ACT_FRONT;
+         self->channelIndices[chIdx] = chIdx;
        }
      }
    }
@@ -1006,7 +1013,8 @@
             self->channelOutputMapping,
             (self->limiterEnableCurr) ? &pcmLimiterScale : NULL
       );
-    if (dmxErr == PCMDMX_INVALID_MODE) {
+    if ( (ErrorStatus == AAC_DEC_OK)
+      && (dmxErr == PCMDMX_INVALID_MODE) ) {
       /* Announce the framework that the current combination of channel configuration and downmix
        * settings are not know to produce a predictable behavior and thus maybe produce strange output. */
       ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
@@ -1051,6 +1059,19 @@
     /* Update Statistics */
     aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus);
 
+    /* Check whether external output buffer is large enough. */
+    if (timeDataSize_extern < self->streamInfo.numChannels*self->streamInfo.frameSize) {
+      ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+    }
+
+    /* Update external output buffer. */
+    if ( IS_OUTPUT_VALID(ErrorStatus) ) {
+      FDKmemcpy(pTimeData_extern, pTimeData, self->streamInfo.numChannels*self->streamInfo.frameSize*sizeof(*pTimeData));
+    }
+    else {
+      FDKmemclear(pTimeData_extern, timeDataSize_extern*sizeof(*pTimeData_extern));
+    }
+
     return ErrorStatus;
 }
 
@@ -1120,6 +1141,7 @@
   /* Set flags */
   info->flags = 0
       | CAPF_AAC_LC
+      | CAPF_ER_AAC_SCAL
       | CAPF_AAC_VCB11
       | CAPF_AAC_HCR
       | CAPF_AAC_RVLC
@@ -1130,6 +1152,7 @@
 
       | CAPF_AAC_MPEG4
 
+      | CAPF_AAC_DRM_BSFORMAT
 
       | CAPF_AAC_1024
       | CAPF_AAC_960
diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp
index 9d703cc..2965fa6 100644
--- a/libAACdec/src/block.cpp
+++ b/libAACdec/src/block.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -324,11 +324,11 @@
 
       if (flags & AC_ER_HCR) {
         /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */
-        pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
-        numLinesInSecIdx++;
         if (numLinesInSecIdx >= MAX_SFB_HCR) {
           return AAC_DEC_PARSE_ERROR;
         }
+        pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
+        numLinesInSecIdx++;
         if (
              (sect_cb == BOOKSCL) )
         {
diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp
index f4b510d..1d8ac7b 100644
--- a/libFDK/src/FDK_core.cpp
+++ b/libFDK/src/FDK_core.cpp
@@ -93,7 +93,7 @@
 /* FDK tools library info */
 #define FDK_TOOLS_LIB_VL0 2
 #define FDK_TOOLS_LIB_VL1 3
-#define FDK_TOOLS_LIB_VL2 5
+#define FDK_TOOLS_LIB_VL2 6
 #define FDK_TOOLS_LIB_TITLE "FDK Tools"
 #ifdef __ANDROID__
 #define FDK_TOOLS_LIB_BUILD_DATE ""
diff --git a/libFDK/src/FDK_tools_rom.cpp b/libFDK/src/FDK_tools_rom.cpp
index 49f0ee1..29e37f2 100644
--- a/libFDK/src/FDK_tools_rom.cpp
+++ b/libFDK/src/FDK_tools_rom.cpp
@@ -2236,7 +2236,7 @@
   ics_info,
   ms,
   ltp_data_present,
-  ltp_data,
+  /* ltp_data, */
   global_gain,
   section_data,
   scale_factor_data,
@@ -2247,7 +2247,7 @@
   next_channel,
 
   ltp_data_present,
-  ltp_data,
+  /* ltp_data, */
   global_gain,
   section_data,
   scale_factor_data,
@@ -2290,7 +2290,178 @@
   { &node_aac_cpe0_epc1, &node_aac_cpe1_epc1 }
 };
 
+/*
+ * AOT = 20
+ * epConfig = 0
+ */
+static const rbd_id_t el_scal_sce_epc0[] = {
+  ics_info,            /* ESC 1 */
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  esc2_rvlc,           /* ESC 2 */
+  tns_data,            /* ESC 3 */
+  spectral_data,       /* ESC 4 */
+  end_of_sequence
+};
 
+static const struct element_list node_scal_sce_epc0 = {
+  el_scal_sce_epc0,
+  { NULL, NULL }
+};
+
+static const rbd_id_t el_scal_cpe_epc0[] = {
+  ics_info,            /* ESC 0 */
+  ms,
+  tns_data_present,    /* ESC 1 (ch 0) */
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  esc2_rvlc,           /* ESC 2 (ch 0) */
+  tns_data,            /* ESC 3 (ch 0) */
+  spectral_data,       /* ESC 4 (ch 0) */
+  next_channel,
+  tns_data_present,    /* ESC 1 (ch 1) */
+  ltp_data_present,
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  esc2_rvlc,           /* ESC 2 (ch 1) */
+  tns_data,            /* ESC 3 (ch 1) */
+  spectral_data,       /* ESC 4 (ch 1) */
+  end_of_sequence
+};
+
+static const struct element_list node_scal_cpe_epc0 = {
+  el_scal_cpe_epc0,
+  { NULL, NULL }
+};
+
+/*
+ * AOT = 20
+ * epConfig = 1
+ */
+static const rbd_id_t el_scal_sce_epc1[] = {
+  ics_info,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  tns_data,
+  spectral_data,
+  end_of_sequence
+};
+
+static const struct element_list node_scal_sce_epc1 = {
+  el_scal_sce_epc1,
+  { NULL, NULL }
+};
+
+static const rbd_id_t el_scal_cpe_epc1[] = {
+  ics_info,
+  ms,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  next_channel,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  next_channel,
+  tns_data,
+  next_channel,
+  tns_data,
+  next_channel,
+  spectral_data,
+  next_channel,
+  spectral_data,
+  end_of_sequence
+};
+
+static const struct element_list node_scal_cpe_epc1 = {
+  el_scal_cpe_epc1,
+  { NULL, NULL }
+};
+
+/*
+ * Pseudo AOT for DRM/DRM+ (similar to AOT 20)
+ * Derived from epConfig = 1
+ */
+static const rbd_id_t el_drm_sce[] = {
+  drmcrc_start_reg,
+  ics_info,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  tns_data,
+  drmcrc_end_reg,
+  spectral_data,
+  end_of_sequence
+};
+
+static const struct element_list node_drm_sce = {
+  el_drm_sce,
+  { NULL, NULL }
+};
+
+static const rbd_id_t el_drm_cpe[] = {
+  drmcrc_start_reg,
+  ics_info,
+  ms,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  next_channel,
+  tns_data_present,
+  ltp_data_present,
+  /* ltp_data, */
+  global_gain,
+  section_data,
+  scale_factor_data,
+  esc1_hcr,
+  next_channel,
+  tns_data,
+  next_channel,
+  tns_data,
+  drmcrc_end_reg,
+  next_channel,
+  spectral_data,
+  next_channel,
+  spectral_data,
+  end_of_sequence
+};
+
+static const struct element_list node_drm_cpe = {
+  el_drm_cpe,
+  { NULL, NULL }
+};
 
 /*
  * AOT = 39
@@ -2405,6 +2576,19 @@
           return &node_aac_cpe_epc1;
       }
       break;
+    case AOT_ER_AAC_SCAL:
+      if (nChannels == 1) {
+        if (epConfig <= 0)
+          return &node_scal_sce_epc0;
+        else
+          return &node_scal_sce_epc1;
+      } else {
+        if (epConfig <= 0)
+          return &node_scal_cpe_epc0;
+        else
+          return &node_scal_cpe_epc1;
+      }
+      break;
     case AOT_ER_AAC_ELD:
       if (nChannels == 1) {
         if (epConfig <= 0)
@@ -2417,6 +2601,16 @@
         else
           return &node_eld_cpe_epc1;
       }
+    case AOT_DRM_AAC:
+    case AOT_DRM_SBR:
+    case AOT_DRM_MPEG_PS:
+      FDK_ASSERT(epConfig == 1);
+      if (nChannels == 1) {
+        return &node_drm_sce;
+      } else {
+        return &node_drm_cpe;
+      }
+      break;
     default:
       break;
   }
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index bae271e..96a1b35 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -1126,6 +1126,8 @@
       if ( 0 != ld_sbr_header(asc, hBs, cb) ) {
         return TRANSPORTDEC_PARSE_ERROR;
       }
+    } else {
+      return TRANSPORTDEC_UNSUPPORTED_FORMAT;
     }
   }
   esc->m_useLdQmfTimeAlign = 0;
@@ -1146,7 +1148,7 @@
 
     switch (eldExtType) {
       default:
-        for(cnt=0; cnt<len; cnt++) {
+        for(cnt=0; cnt<eldExtLen; cnt++) {
           FDKreadBits(hBs, 8 );
         }
         break;
@@ -1372,4 +1374,133 @@
   return (ErrorStatus);
 }
 
+TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse(
+        CSAudioSpecificConfig *self,
+        HANDLE_FDK_BITSTREAM   bs
+        )
+{
+  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
+
+  AudioSpecificConfig_Init(self);
+
+  if ((INT)FDKgetValidBits(bs) < 20) {
+    ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
+    goto bail;
+  }
+  else {
+    /* DRM - Audio information data entity - type 9
+       - Short Id            2 bits
+       - Stream Id           2 bits
+       - audio coding        2 bits
+       - SBR flag            1 bit
+       - audio mode          2 bits
+       - audio sampling rate 3 bits
+       - text flag           1 bit
+       - enhancement flag    1 bit
+       - coder field         5 bits
+       - rfa                 1 bit  */
+
+    int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag;
+
+    /* Read the SDC field */
+    FDKreadBits(bs,4);   /* Short and Stream Id */
+
+    audioCoding   = FDKreadBits(bs, 2);
+    sbrFlag       = FDKreadBits(bs, 1);
+    audioMode     = FDKreadBits(bs, 2);
+    cSamplingFreq = FDKreadBits(bs, 3);    /* audio sampling rate */
+
+    FDKreadBits(bs, 2);  /* Text and enhancement flag */
+    coderField   = FDKreadBits(bs, 5);
+    FDKreadBits(bs, 1);  /* rfa */
+
+    /* Evaluate configuration and fill the ASC */
+    switch (cSamplingFreq) {
+    case 0: /*  8 kHz */
+      sfIdx = 11;
+      break;
+    case 1: /* 12 kHz */
+      sfIdx = 9;
+      break;
+    case 2: /* 16 kHz */
+      sfIdx = 8;
+      break;
+    case 3: /* 24 kHz */
+      sfIdx = 6;
+      break;
+    case 5: /* 48 kHz */
+      sfIdx = 3;
+      break;
+    case 4: /* reserved */
+    case 6: /* reserved */
+    case 7: /* reserved */
+    default:
+      ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
+      goto bail;
+    }
+
+    self->m_samplingFrequencyIndex = sfIdx;
+    self->m_samplingFrequency = SamplingRateTable[sfIdx];
+
+    if ( sbrFlag ) {
+      UINT i;
+      int tmp = -1;
+      self->m_sbrPresentFlag = 1;
+      self->m_extensionAudioObjectType = AOT_SBR;
+      self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1;
+      for (i=0; i<(sizeof(SamplingRateTable)/sizeof(SamplingRateTable[0])); i++){
+        if (SamplingRateTable[i] == self->m_extensionSamplingFrequency){
+          tmp = i;
+          break;
+        }
+      }
+      self->m_extensionSamplingFrequencyIndex = tmp;
+    }
+
+    switch (audioCoding) {
+      case 0: /* AAC */
+          self->m_aot = AOT_DRM_AAC     ;  /* Set pseudo AOT for Drm AAC */
+
+        switch (audioMode) {
+        case 1: /* parametric stereo */
+          self->m_psPresentFlag = 1;
+        case 0: /* mono */
+          self->m_channelConfiguration = 1;
+          break;
+        case 2: /* stereo */
+          self->m_channelConfiguration = 2;
+          break;
+        default:
+          ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
+          goto bail;
+        }
+        self->m_vcb11Flag = 1;
+        self->m_hcrFlag = 1;
+        self->m_samplesPerFrame = 960;
+        self->m_epConfig = 1;
+        break;
+      case 1: /* CELP */
+        self->m_aot = AOT_ER_CELP;
+        self->m_channelConfiguration = 1;
+        break;
+      case 2: /* HVXC */
+        self->m_aot = AOT_ER_HVXC;
+        self->m_channelConfiguration = 1;
+        break;
+      case 3: /* reserved */
+      default:
+        ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
+        self->m_aot = AOT_NONE;
+        break;
+    }
+
+    if (self->m_psPresentFlag && !self->m_sbrPresentFlag) {
+      ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
+      goto bail;
+    }
+  }
+
+bail:
+  return (ErrorStatus);
+}
 
diff --git a/libMpegTPDec/src/tpdec_drm.cpp b/libMpegTPDec/src/tpdec_drm.cpp
new file mode 100644
index 0000000..df319e5
--- /dev/null
+++ b/libMpegTPDec/src/tpdec_drm.cpp
@@ -0,0 +1,146 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+  All rights reserved.
+
+ 1.    INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
+the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
+This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
+audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
+independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
+of the MPEG specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
+may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
+individually for the purpose of encoding or decoding bit streams in products that are compliant with
+the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
+these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
+software may already be covered under those patent licenses when it is used for those licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
+are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
+applications information and documentation.
+
+2.    COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification, are permitted without
+payment of copyright license fees provided that you satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
+your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation and/or other materials
+provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
+You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived from this library without
+prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
+software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
+and the date of any change. For modified versions of the FDK AAC Codec, the term
+"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
+"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+
+3.    NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
+ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
+respect to this software.
+
+You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
+by appropriate patent licenses.
+
+4.    DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
+"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
+of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
+including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
+or business interruption, however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of this software, even if
+advised of the possibility of such damage.
+
+5.    CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------------------------------------- */
+
+/*****************************  MPEG-4 AAC Decoder  **************************
+
+   Author(s):   Christian Griebel
+   Description: DRM transport stuff
+
+******************************************************************************/
+
+#include "tpdec_drm.h"
+
+
+#include "FDK_bitstream.h"
+
+
+
+void drmRead_CrcInit(HANDLE_DRM pDrm)      /*!< pointer to drm crc info stucture */
+{
+  FDK_ASSERT(pDrm != NULL);
+
+  FDKcrcInit(&pDrm->crcInfo, 0x001d, 0xFFFF, 8);
+}
+
+int drmRead_CrcStartReg(
+                     HANDLE_DRM pDrm,            /*!< pointer to drm stucture */
+                     HANDLE_FDK_BITSTREAM hBs,   /*!< handle to current bit buffer structure */
+                     int mBits                   /*!< number of bits in crc region */
+                   )
+{
+  FDK_ASSERT(pDrm != NULL);
+
+  FDKcrcReset(&pDrm->crcInfo);
+
+  pDrm->crcReadValue = FDKreadBits(hBs, 8);
+
+  return ( FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits) );
+
+}
+
+void drmRead_CrcEndReg(
+                    HANDLE_DRM pDrm,             /*!< pointer to drm crc info stucture */
+                    HANDLE_FDK_BITSTREAM hBs,    /*!< handle to current bit buffer structure */
+                    int reg                      /*!< crc region */
+                  )
+{
+  FDK_ASSERT(pDrm != NULL);
+
+  FDKcrcEndReg(&pDrm->crcInfo, hBs, reg);
+}
+
+TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm )
+{
+  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
+  USHORT crc;
+
+  crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF;
+  if (crc != pDrm->crcReadValue)
+  {
+    return (TRANSPORTDEC_CRC_ERROR);
+  }
+
+  return (ErrorStatus);
+}
+
+
diff --git a/libMpegTPDec/src/tpdec_drm.h b/libMpegTPDec/src/tpdec_drm.h
new file mode 100644
index 0000000..2161b4c
--- /dev/null
+++ b/libMpegTPDec/src/tpdec_drm.h
@@ -0,0 +1,194 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+  All rights reserved.
+
+ 1.    INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
+the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
+This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
+audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
+independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
+of the MPEG specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
+may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
+individually for the purpose of encoding or decoding bit streams in products that are compliant with
+the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
+these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
+software may already be covered under those patent licenses when it is used for those licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
+are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
+applications information and documentation.
+
+2.    COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification, are permitted without
+payment of copyright license fees provided that you satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
+your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation and/or other materials
+provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
+You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived from this library without
+prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
+software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
+and the date of any change. For modified versions of the FDK AAC Codec, the term
+"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
+"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+
+3.    NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
+ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
+respect to this software.
+
+You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
+by appropriate patent licenses.
+
+4.    DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
+"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
+of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
+including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
+or business interruption, however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of this software, even if
+advised of the possibility of such damage.
+
+5.    CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------------------------------------- */
+
+/*****************************  MPEG-4 AAC Decoder  **************************
+
+   Author(s):   Josef Hoepfl
+   Description: DRM interface
+
+******************************************************************************/
+
+#ifndef TPDEC_DRM_H
+#define TPDEC_DRM_H
+
+#include "tpdec_lib.h"
+
+
+#include "FDK_crc.h"
+
+typedef struct {
+
+  FDK_CRCINFO crcInfo;             /* CRC state info */
+  USHORT      crcReadValue;        /* CRC value read from bitstream data */
+
+} STRUCT_DRM;
+
+typedef STRUCT_DRM *HANDLE_DRM;
+
+/*!
+  \brief Initialize DRM CRC
+
+  The function initialzes the crc buffer and the crc lookup table.
+
+  \return  none
+*/
+void drmRead_CrcInit( HANDLE_DRM pDrm );
+
+/**
+ * \brief Starts CRC region with a maximum number of bits
+ *        If mBits is positive zero padding will be used for CRC calculation, if there
+ *        are less than mBits bits available.
+ *        If mBits is negative no zero padding is done.
+ *        If mBits is zero the memory for the buffer is allocated dynamically, the
+ *        number of bits is not limited.
+ *
+ * \param pDrm DRM data handle
+ * \param hBs bitstream handle, on which the CRC region referes to
+ * \param mBits max number of bits in crc region to be considered
+ *
+ * \return  ID for the created region, -1 in case of an error
+ */
+int drmRead_CrcStartReg(
+        HANDLE_DRM pDrm,
+        HANDLE_FDK_BITSTREAM hBs,
+        int mBits
+        );
+
+/**
+ * \brief Ends CRC region identified by reg
+ *
+ * \param pDrm DRM data handle
+ * \param hBs bitstream handle, on which the CRC region referes to
+ * \param reg CRC regions ID returned by drmRead_CrcStartReg()
+ *
+ * \return  none
+ */
+void drmRead_CrcEndReg(
+        HANDLE_DRM pDrm,
+        HANDLE_FDK_BITSTREAM hBs,
+        int reg
+        );
+
+/**
+ * \brief Check CRC
+ *
+ * Checks if the currently calculated CRC matches the CRC field read from the bitstream
+ * Deletes all CRC regions.
+ *
+ * \param pDrm DRM data handle
+ *
+ * \return Returns 0 if they are identical otherwise 1
+ */
+TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm );
+
+/**
+ * \brief Check if we have a valid DRM frame at the current bitbuffer position
+ *
+ * This function assumes enough bits in buffer for the current frame.
+ * It reads out the header bits to prepare the bitbuffer for the decode loop.
+ * In case the header bits show an invalid bitstream/frame, the whole frame is skipped.
+ *
+ * \param pDrm DRM data handle which is filled with parsed DRM header data
+ * \param bs handle of bitstream from whom the DRM header is read
+ *
+ * \return  error status
+ */
+TRANSPORTDEC_ERROR drmRead_DecodeHeader(
+        HANDLE_DRM            pDrm,
+        HANDLE_FDK_BITSTREAM  bs
+        );
+
+/**
+ * \brief   Parse a Drm specific SDC audio config from a given bitstream handle.
+ *
+ * \param pAsc                         A pointer to an allocated CSAudioSpecificConfig struct.
+ * \param hBs                          Bitstream handle.
+ *
+ * \return  Total element count including all SCE, CPE and LFE.
+ */
+TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( CSAudioSpecificConfig *pAsc,
+                                               HANDLE_FDK_BITSTREAM hBs );
+
+
+
+#endif /* TPDEC_DRM_H */
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp
index 950af64..24f755b 100644
--- a/libMpegTPDec/src/tpdec_lib.cpp
+++ b/libMpegTPDec/src/tpdec_lib.cpp
@@ -102,6 +102,7 @@
 
 #include "tpdec_latm.h"
 
+#include "tpdec_drm.h"
 
 
 #define MODULE_NAME "transportDec"
@@ -113,6 +114,7 @@
 
   CLatmDemux latm;
 
+  STRUCT_DRM drm;
 
 } transportdec_parser_t;
 
@@ -182,6 +184,9 @@
     hInput->numberOfRawDataBlocks = 0;
     break;
 
+  case TT_DRM:
+    drmRead_CrcInit(&hInput->parser.drm);
+    break;
 
   case TT_MP4_LATM_MCP0:
   case TT_MP4_LATM_MCP1:
@@ -253,6 +258,18 @@
         }
       }
       break;
+    case TT_DRM:
+      fConfigFound = 1;
+      err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs);
+      if (err == TRANSPORTDEC_OK) {
+        int errC;
+
+        errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]);
+        if (errC != 0) {
+          err = TRANSPORTDEC_PARSE_ERROR;
+        }
+      }
+      break;
   }
 
   if (err == TRANSPORTDEC_OK && fConfigFound) {
@@ -1083,6 +1100,7 @@
       break;
 
     case TT_MP4_RAW:
+    case TT_DRM:
       /* One Access Unit was filled into buffer.
          So get the length out of the buffer. */
       hTp->auLength[layer] = FDKgetValidBits(hBs);
@@ -1283,6 +1301,7 @@
     | CAPF_LATM
     | CAPF_LOAS
     | CAPF_RAWPACKETS
+    | CAPF_DRM
     ;
 
   return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */
@@ -1294,6 +1313,8 @@
   switch (pTp->transportFmt) {
   case TT_MP4_ADTS:
     return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits);
+  case TT_DRM:
+    return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits);
   default:
     return 0;
   }
@@ -1305,6 +1326,9 @@
   case TT_MP4_ADTS:
     adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg);
     break;
+  case TT_DRM:
+    drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg);
+    break;
   default:
     break;
   }
@@ -1321,6 +1345,9 @@
       transportDec_AdjustEndOfAccessUnit(pTp);
     }
     return adtsRead_CrcCheck(&pTp->parser.adts);
+  case TT_DRM:
+    return drmRead_CrcCheck(&pTp->parser.drm);
+    break;
   default:
     return TRANSPORTDEC_OK;
   }
diff --git a/libMpegTPDec/src/version b/libMpegTPDec/src/version
index 18fc9ba..75e22c9 100644
--- a/libMpegTPDec/src/version
+++ b/libMpegTPDec/src/version
@@ -2,7 +2,7 @@
 /* library info */
 #define TP_LIB_VL0 2
 #define TP_LIB_VL1 3
-#define TP_LIB_VL2 5
+#define TP_LIB_VL2 7
 #define TP_LIB_TITLE "MPEG Transport"
 #ifdef __ANDROID__
 #define TP_LIB_BUILD_DATE ""
diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h
index 174fb5c..3bb9ba3 100644
--- a/libSBRdec/include/sbrdecoder.h
+++ b/libSBRdec/include/sbrdecoder.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -262,6 +262,7 @@
  *         into *count if a payload length is given (byPayLen > 0). If no SBR payload length is
  *         given (bsPayLen < 0) then the bit stream position on return will be random after this
  *         function call in case of errors, and any further decoding will be completely pointless.
+ *         This function accepts either normal ordered SBR data or reverse ordered DRM SBR data.
  *
  * \param self           SBR decoder handle.
  * \param hBs            Bit stream handle as data source.
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index ade57fc..fa5330a 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -151,13 +151,13 @@
 }
 ENV_CALC_NRGS;
 
-/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
+static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
                                   SCHAR   *filtBuffer_e,
                                   FIXP_DBL *NrgGain,
                                   SCHAR   *NrgGain_e,
                                   int    subbands);
 
-/*static*/ void calcNrgPerSubband(FIXP_DBL  **analysBufferReal,
+static void calcNrgPerSubband(FIXP_DBL  **analysBufferReal,
                               FIXP_DBL  **analysBufferImag,
                               int       lowSubband, int highSubband,
                               int       start_pos,  int next_pos,
@@ -165,7 +165,7 @@
                               FIXP_DBL *nrgEst,
                               SCHAR    *nrgEst_e );
 
-/*static*/ void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,
+static void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,
                           FIXP_DBL  **analysBufferImag,
                           int       nSfb,
                           UCHAR    *freqBandTable,
@@ -174,13 +174,13 @@
                           FIXP_DBL *nrg_est,
                           SCHAR    *nrg_est_e );
 
-/*static*/ void calcSubbandGain(FIXP_DBL  nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c,
+static void calcSubbandGain(FIXP_DBL  nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c,
                             FIXP_DBL  tmpNoise, SCHAR tmpNoise_e,
                             UCHAR     sinePresentFlag,
                             UCHAR     sineMapped,
                             int       noNoiseFlag);
 
-/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs,
+static void calcAvgGain(ENV_CALC_NRGS* nrgs,
                         int        lowSubband,
                         int        highSubband,
                         FIXP_DBL  *sumRef_m,
@@ -188,7 +188,7 @@
                         FIXP_DBL  *ptrAvgGain_m,
                         SCHAR     *ptrAvgGain_e);
 
-/*static*/ void adjustTimeSlotLC(FIXP_DBL  *ptrReal,
+static void adjustTimeSlot_EldGrid(FIXP_DBL  *ptrReal,
                            ENV_CALC_NRGS* nrgs,
                            UCHAR *ptrHarmIndex,
                            int    lowSubbands,
@@ -196,8 +196,17 @@
                            int    scale_change,
                            int    noNoiseFlag,
                            int   *ptrPhaseIndex,
-                           int    fCldfb);
-/*static*/ void adjustTimeSlotHQ(FIXP_DBL  *ptrReal,
+                           int    scale_diff_low);
+
+static void adjustTimeSlotLC(FIXP_DBL  *ptrReal,
+                           ENV_CALC_NRGS* nrgs,
+                           UCHAR *ptrHarmIndex,
+                           int    lowSubbands,
+                           int    noSubbands,
+                           int    scale_change,
+                           int    noNoiseFlag,
+                           int   *ptrPhaseIndex);
+static void adjustTimeSlotHQ(FIXP_DBL  *ptrReal,
                            FIXP_DBL  *ptrImag,
                            HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
                            ENV_CALC_NRGS* nrgs,
@@ -224,7 +233,7 @@
   Additionally, the flags in harmFlagsPrev are being updated by this function
   for the next frame.
 */
-/*static*/ void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */
+static void mapSineFlags(UCHAR *freqBandTable,         /*!< Band borders (there's only 1 flag per band) */
                          int nSfb,                     /*!< Number of bands in the table */
                          UCHAR *addHarmonics,           /*!< vector with 1 flag per sfb */
                          int *harmFlagsPrev,           /*!< Packed 'addHarmonics' */
@@ -990,7 +999,6 @@
           /* Prevent the smoothing filter from running on constant levels */
           if (j-start_pos < smooth_length)
             smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos];
-
           else
             smooth_ratio = FL2FXCONST_SGL(0.0f);
 
@@ -1007,7 +1015,8 @@
         }
         else
         {
-          adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
+          if (flags & SBRDEC_ELD_GRID) {
+            adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband],
                            pNrgs,
                           &h_sbr_cal_env->harmIndex,
                            lowSubband,
@@ -1015,7 +1024,18 @@
                            scale_change,
                            noNoiseFlag,
                           &h_sbr_cal_env->phaseIndex,
-                           (flags & SBRDEC_ELD_GRID));
+                           EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale);
+          } else
+          {
+            adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
+                           pNrgs,
+                          &h_sbr_cal_env->harmIndex,
+                           lowSubband,
+                           noSubbands,
+                           scale_change,
+                           noNoiseFlag,
+                          &h_sbr_cal_env->phaseIndex);
+          }
         }
       } // for
 
@@ -1176,7 +1196,7 @@
   can be performed.
   This function is called once for each envelope before adjusting.
 */
-/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,     /*!< bufferd gains */
+static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,     /*!< bufferd gains */
                                   SCHAR    *filtBuffer_e,   /*!< exponents of bufferd gains */
                                   FIXP_DBL *nrgGain,        /*!< gains for current envelope */
                                   SCHAR    *nrgGain_e,      /*!< exponents of gains for current envelope */
@@ -1331,7 +1351,7 @@
 
   This function is used when interpolFreq is true.
 */
-/*static*/ void calcNrgPerSubband(FIXP_DBL  **analysBufferReal, /*!< Real part of subband samples */
+static void calcNrgPerSubband(FIXP_DBL  **analysBufferReal, /*!< Real part of subband samples */
                               FIXP_DBL  **analysBufferImag, /*!< Imaginary part of subband samples */
                               int       lowSubband,           /*!< Begin of the SBR frequency range */
                               int       highSubband,          /*!< High end of the SBR frequency range */
@@ -1452,7 +1472,7 @@
 
   This function is used when interpolFreq is false.
 */
-/*static*/ void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,  /*!< Real part of subband samples */
+static void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,  /*!< Real part of subband samples */
                           FIXP_DBL  **analysBufferImag,  /*!< Imaginary part of subband samples */
                           int       nSfb,                /*!< Number of scale factor bands */
                           UCHAR    *freqBandTable,       /*!< First Subband for each Sfb */
@@ -1585,7 +1605,7 @@
 
   The resulting energy gain is given by mantissa and exponent.
 */
-/*static*/ void calcSubbandGain(FIXP_DBL  nrgRef,            /*!< Reference Energy according to envelope data */
+static void calcSubbandGain(FIXP_DBL  nrgRef,            /*!< Reference Energy according to envelope data */
                             SCHAR     nrgRef_e,          /*!< Reference Energy according to envelope data (exponent) */
                             ENV_CALC_NRGS* nrgs,
                             int       i,
@@ -1689,7 +1709,7 @@
   The result is used as a relative limit for all gains within the
   current "limiter band" (a certain frequency range).
 */
-/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs,
+static void calcAvgGain(ENV_CALC_NRGS* nrgs,
                         int        lowSubband,    /*!< Begin of the limiter band */
                         int        highSubband,   /*!< High end of the limiter band */
                         FIXP_DBL  *ptrSumRef,
@@ -1728,21 +1748,101 @@
   *ptrSumRef_e = sumRef_e;
 }
 
+static void adjustTimeSlot_EldGrid(
+                              FIXP_DBL *ptrReal,        /*!< Subband samples to be adjusted, real part */
+                              ENV_CALC_NRGS* nrgs,
+                              UCHAR    *ptrHarmIndex,   /*!< Harmonic index */
+                              int       lowSubband,     /*!< Lowest QMF-channel in the currently used SBR range. */
+                              int       noSubbands,     /*!< Number of QMF subbands */
+                              int       scale_change,   /*!< Number of bits to shift adjusted samples */
+                              int       noNoiseFlag,    /*!< Flag to suppress noise addition */
+                              int      *ptrPhaseIndex,  /*!< Start index to random number array */
+                              int       scale_diff_low) /*!<  */
+{
+  int k;
+  FIXP_DBL  signalReal, sbNoise;
+  int tone_count = 0;
+
+  FIXP_DBL *pGain       = nrgs->nrgGain;     /*!< Gains of current envelope */
+  FIXP_DBL *pNoiseLevel = nrgs->noiseLevel;  /*!< Noise levels of current envelope */
+  FIXP_DBL *pSineLevel  = nrgs->nrgSine;     /*!< Sine levels */
+
+  int    phaseIndex = *ptrPhaseIndex;
+  UCHAR  harmIndex  = *ptrHarmIndex;
+
+  static const INT harmonicPhase [2][4] = {
+    { 1, 0, -1,  0},
+    { 0, 1,  0, -1}
+  };
+
+  static const FIXP_DBL harmonicPhaseX [2][4] = {
+    { FL2FXCONST_DBL(2.0*1.245183154539139e-001),  FL2FXCONST_DBL(2.0*-1.123767859325028e-001),  FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) },
+    { FL2FXCONST_DBL(2.0*1.245183154539139e-001),  FL2FXCONST_DBL(2.0* 1.123767859325028e-001),  FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) }
+  };
+
+  for (k=0; k < noSubbands; k++) {
+
+    phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
+
+    if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){
+      sbNoise = FL2FXCONST_DBL(0.0f);
+    } else {
+      sbNoise = pNoiseLevel[0];
+    }
+
+    signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change);
+
+    signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4);
+
+    signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex];
+
+    *ptrReal = signalReal;
+
+    if (k == 0) {
+      *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low)  ;
+      if (k < noSubbands - 1) {
+        *(ptrReal)   += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]);
+      }
+    }
+    if (k > 0 && k < noSubbands - 1 && tone_count < 16) {
+      *(ptrReal)   += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1]  [harmIndex]);
+      *(ptrReal)   += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]);
+    }
+    if (k == noSubbands - 1 && tone_count < 16) {
+      if (k > 0) {
+        *(ptrReal)   += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]);
+      }
+      if (k + lowSubband + 1< 63) {
+        *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]);
+      }
+    }
+
+    if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){
+      tone_count++;
+    }
+    ptrReal++;
+    pNoiseLevel++;
+    pGain++;
+    pSineLevel++;
+  }
+
+  *ptrHarmIndex = (harmIndex + 1) & 3;
+  *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1);
+}
 
 /*!
   \brief   Amplify one timeslot of the signal with the calculated gains
            and add the noisefloor.
 */
 
-/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal,       /*!< Subband samples to be adjusted, real part */
+static void adjustTimeSlotLC(FIXP_DBL *ptrReal,       /*!< Subband samples to be adjusted, real part */
                              ENV_CALC_NRGS* nrgs,
                              UCHAR    *ptrHarmIndex,  /*!< Harmonic index */
                              int       lowSubband,    /*!< Lowest QMF-channel in the currently used SBR range. */
                              int       noSubbands,    /*!< Number of QMF subbands */
                              int       scale_change,  /*!< Number of bits to shift adjusted samples */
                              int       noNoiseFlag,   /*!< Flag to suppress noise addition */
-                             int      *ptrPhaseIndex, /*!< Start index to random number array */
-                             int       fCldfb)        /*!< CLDFB 80 flag */
+                             int      *ptrPhaseIndex) /*!< Start index to random number array */
 {
   FIXP_DBL *pGain       = nrgs->nrgGain;     /*!< Gains of current envelope */
   FIXP_DBL *pNoiseLevel = nrgs->noiseLevel;  /*!< Noise levels of current envelope */
@@ -1775,41 +1875,10 @@
   sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
 
   if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++;
-
   else if (!noNoiseFlag)
         /* Add noisefloor to the amplified signal */
         signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
 
-  if (fCldfb) {
-
-    if (!(harmIndex&0x1)) {
-      /* harmIndex 0,2 */
-      signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel;
-      *ptrReal++ = signalReal;
-    }
-    else {
-      /* harmIndex 1,3 in combination with freqInvFlag */
-      int shift = (int) (scale_change+1);
-      shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift);
-
-      FIXP_DBL tmp1 = scaleValue( fMultDiv2(C1_CLDFB, sineLevel), -shift );
-
-      FIXP_DBL tmp2 = fMultDiv2(C1_CLDFB, sineLevelNext);
-
-
-      /* save switch and compare operations and reduce to XOR statement */
-      if ( ((harmIndex>>1)&0x1)^freqInvFlag) {
-          *(ptrReal-1) += tmp1;
-          signalReal   -= tmp2;
-      } else {
-          *(ptrReal-1) -= tmp1;
-          signalReal   += tmp2;
-      }
-      *ptrReal++ = signalReal;
-      freqInvFlag = !freqInvFlag;
-    }
-
-  } else
   {
     if (!(harmIndex&0x1)) {
       /* harmIndex 0,2 */
@@ -1933,8 +2002,9 @@
   *ptrHarmIndex = (harmIndex + 1) & 3;
   *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1);
 }
-void adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal,           /*!< Subband samples to be adjusted, real part */
-                      FIXP_DBL *RESTRICT ptrImag,               /*!< Subband samples to be adjusted, imag part */
+static void adjustTimeSlotHQ(
+                      FIXP_DBL *RESTRICT ptrReal,      /*!< Subband samples to be adjusted, real part */
+                      FIXP_DBL *RESTRICT ptrImag,      /*!< Subband samples to be adjusted, imag part */
                       HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
                       ENV_CALC_NRGS* nrgs,
                       int       lowSubband,            /*!< Lowest QMF-channel in the currently used SBR range. */
@@ -2137,7 +2207,6 @@
   UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1];
   int patchBorders[MAX_NUM_PATCHES + 1];
   int kx, k2;
-  FIXP_DBL temp;
 
   int lowSubband = freqBandTable[0];
   int highSubband = freqBandTable[noFreqBands];
@@ -2169,13 +2238,32 @@
 
 
     while (hiLimIndex <= tempNoLim) {
+      FIXP_DBL div_m, oct_m, temp;
+      INT div_e  = 0, oct_e  = 0, temp_e = 0;
+
       k2 = workLimiterBandTable[hiLimIndex] + lowSubband;
       kx = workLimiterBandTable[loLimIndex] + lowSubband;
 
-      temp = FX_SGL2FX_DBL(FDK_getNumOctavesDiv8(kx,k2)); /* Number of octaves */
-      temp = fMult(temp, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[limiterBands]);
+      div_m  = fDivNorm(k2, kx, &div_e);
 
-      if (temp < FL2FXCONST_DBL (0.49f)>>5) {
+      /* calculate number of octaves */
+      oct_m  = fLog2(div_m, div_e, &oct_e);
+
+      /* multiply with limiterbands per octave    */
+      /* values 1, 1.2, 2, 3 -> scale factor of 2 */
+      temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e);
+
+      /* overall scale factor of temp ist addition of scalefactors from log2 calculation,
+         limiter bands scalefactor (2) and limiter bands multiplication */
+      temp_e += oct_e + 2;
+
+      /*    div can be a maximum of 64 (k2 = 64 and kx = 1)
+         -> oct can be a maximum of 6
+         -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3)
+         -> we need a scale factor of 5 for comparisson
+      */
+      if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) {
+
         if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) {
           workLimiterBandTable[hiLimIndex] = highSubband;
           nBands--;
diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp
index 24b2d3b..c65c169 100644
--- a/libSBRdec/src/env_dec.cpp
+++ b/libSBRdec/src/env_dec.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -369,7 +369,7 @@
   FIXP_SGL step;    /* speed of fade */
   int i;
 
-  int currentStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots;
+  int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots);
   int currentStopPos = hHeaderData->numberTimeSlots;
 
 
diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp
index 6cb0b99..dacd951 100644
--- a/libSBRdec/src/env_extr.cpp
+++ b/libSBRdec/src/env_extr.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -327,7 +327,7 @@
   }
 
   /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */
-  if(hHeaderData->syncState != SBR_ACTIVE ||
+  if(hHeaderData->syncState < SBR_HEADER ||
      lastHeader.startFreq   != pBsData->startFreq   ||
      lastHeader.stopFreq    != pBsData->stopFreq    ||
      lastHeader.freqScale   != pBsData->freqScale   ||
diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h
index ab6b704..0518ea9 100644
--- a/libSBRdec/src/env_extr.h
+++ b/libSBRdec/src/env_extr.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -125,6 +125,7 @@
 typedef enum
 {
   HEADER_NOT_PRESENT,
+  HEADER_ERROR,
   HEADER_OK,
   HEADER_RESET
 }
@@ -132,10 +133,10 @@
 
 typedef enum
 {
-  SBR_NOT_INITIALIZED,
-  UPSAMPLING,
-  SBR_HEADER,
-  SBR_ACTIVE
+  SBR_NOT_INITIALIZED = 0,
+  UPSAMPLING = 1,
+  SBR_HEADER = 2,
+  SBR_ACTIVE = 3
 }
 SBR_SYNC_STATE;
 
@@ -179,6 +180,7 @@
 #define SBRDEC_LOW_POWER      16  /* Flag indicating that Low Power QMF mode shall be used. */
 #define SBRDEC_PS_DECODED     32  /* Flag indicating that PS was decoded and rendered. */
 #define SBRDEC_LD_MPS_QMF    512  /* Flag indicating that the LD-MPS QMF shall be used. */
+#define SBRDEC_SYNTAX_DRM   2048  /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */
 #define SBRDEC_DOWNSAMPLE   8192  /* Flag indicating that the downsampling mode is used. */
 #define SBRDEC_FLUSH       16384  /* Flag is used to flush all elements in use. */
 #define SBRDEC_FORCE_RESET 32768  /* Flag is used to force a reset of all elements in use. */
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index 1282338..0864348 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -225,7 +225,14 @@
   }
 
   if (resetAnaQmf) {
-    int qmfErr = qmfInitAnalysisFilterBank (
+    QMF_FILTER_BANK prvAnaQmf;
+    int  qmfErr;
+
+    /* Store current configuration */
+    FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK));
+
+    /* Reset analysis QMF */
+    qmfErr = qmfInitAnalysisFilterBank (
            &hSbrDec->AnalysiscQMF,
             hSbrDec->anaQmfStates,
             hSbrDec->AnalysiscQMF.no_col,
@@ -234,13 +241,22 @@
             hSbrDec->AnalysiscQMF.no_channels,
             anaQmfFlags | QMF_FLAG_KEEP_STATES
             );
+
     if (qmfErr != 0) {
-      FDK_ASSERT(0);
+      /* Restore old configuration of analysis QMF */
+      FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK));
     }
   }
 
   if (resetSynQmf) {
-    int qmfErr = qmfInitSynthesisFilterBank (
+    QMF_FILTER_BANK prvSynQmf;
+    int  qmfErr;
+
+    /* Store current configuration */
+    FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK));
+
+    /* Reset synthesis QMF */
+    qmfErr = qmfInitSynthesisFilterBank (
            &hSbrDec->SynthesisQMF,
             hSbrDec->pSynQmfStates,
             hSbrDec->SynthesisQMF.no_col,
@@ -251,7 +267,8 @@
             );
 
     if (qmfErr != 0) {
-      FDK_ASSERT(0);
+      /* Restore old configuration of synthesis QMF */
+      FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK));
     }
   }
 }
@@ -321,7 +338,8 @@
           HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,  /*!< Some control data of last frame */
           const int applyProcessing,         /*!< Flag for SBR operation */
           HANDLE_PS_DEC h_ps_d,
-          const UINT flags
+          const UINT flags,
+          const int codecFrameSize
          )
 {
   int i, slot, reserve;
@@ -348,6 +366,33 @@
   if (flags & SBRDEC_ELD_GRID) {
     /* Choose the right low delay filter bank */
     changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 );
+
+    /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate)
+     * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */
+    if ( (flags & SBRDEC_LD_MPS_QMF)
+      && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) )
+    {
+      INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf;  /* DLYBUF */
+      int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0);
+      /* Create TMPBUF */
+      C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96));
+      /* Copy delay samples from INBUF to TMPBUF */
+      for (smpl = 0; smpl < delay; smpl += 1) {
+        pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn];
+      }
+      /* Move input signal remainder to the very end of INBUF */
+      for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) {
+        timeIn[smpl+delay] = timeIn[smpl];
+      }
+      /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */
+      for (smpl = 0; smpl < delay; smpl += 1) {
+        timeIn[smpl*strideIn] = pDlyBuf[smpl];
+      }
+      /* Copy TMPBUF to DLYBUF */
+      FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM));
+      /* Destory TMPBUF */
+      C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96));
+    }
   }
 
   /*
@@ -761,7 +806,7 @@
   {
     int qmfErr;
     /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */
-    const UINT downSampledFlag = (downsampleFac==2) ? QMF_FLAG_DOWNSAMPLED : 0;
+    const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0;
 
     qmfErr = qmfInitAnalysisFilterBank (
                     &hs->AnalysiscQMF,
@@ -836,6 +881,9 @@
     }
   }
 
+  /* Clear input delay line */
+  FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM));
+
   /* assign qmf time slots */
   assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP);
 
diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h
index 175e7b2..edde637 100644
--- a/libSBRdec/src/sbr_dec.h
+++ b/libSBRdec/src/sbr_dec.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -118,6 +118,9 @@
   FIXP_DBL * WorkBuffer1;
   FIXP_DBL * WorkBuffer2;
 
+  /* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */
+  INT_PCM    coreDelayBuf[(96)];
+
   /* QMF filter states */
   FIXP_QAS   anaQmfStates[(320)];
   FIXP_QSS * pSynQmfStates;
@@ -182,7 +185,8 @@
          HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,  /*!< Some control data of last frame */
          const int applyProcessing,         /*!< Flag for SBR operation */
          HANDLE_PS_DEC h_ps_d,
-         const UINT flags
+         const UINT flags,
+         const int codecFrameSize
         );
 
 
diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h
index f12631d..7ab5044 100644
--- a/libSBRdec/src/sbr_ram.h
+++ b/libSBRdec/src/sbr_ram.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -135,6 +135,7 @@
   USHORT codecFrameSize;
   UCHAR synDownsampleFac;
   UCHAR numDelayFrames;        /* The current number of additional delay frames used for processing. */
+  UCHAR numFlushedFrames;      /* The variable counts the number of frames which are flushed consecutively. */
 
   UINT flags;
 
diff --git a/libSBRdec/src/sbr_rom.cpp b/libSBRdec/src/sbr_rom.cpp
index e84c3cd..c48ce35 100644
--- a/libSBRdec/src/sbr_rom.cpp
+++ b/libSBRdec/src/sbr_rom.cpp
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -189,6 +189,15 @@
   FL2FXCONST_SGL(3.0f / 4.0f)
 };
 
+/*! Constants for calculating the number of limiter bands */
+const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] =
+{
+  FL2FXCONST_DBL(1.0f / 4.0f),
+  FL2FXCONST_DBL(1.2f / 4.0f),
+  FL2FXCONST_DBL(2.0f / 4.0f),
+  FL2FXCONST_DBL(3.0f / 4.0f)
+};
+
 /*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */
 const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = {
   FL2FXCONST_SGL(0.66666666666666f),
diff --git a/libSBRdec/src/sbr_rom.h b/libSBRdec/src/sbr_rom.h
index c318870..1f800bc 100644
--- a/libSBRdec/src/sbr_rom.h
+++ b/libSBRdec/src/sbr_rom.h
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
   All rights reserved.
 
  1.    INTRODUCTION
@@ -124,6 +124,7 @@
 extern const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4];
 extern const UCHAR    FDK_sbrDecoder_sbr_limGains_e[4];
 extern const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4];
+extern const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4];
 extern const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4];
 extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2];
 extern const FIXP_SGL harmonicPhaseX [2][4];
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index e15145a..f9ded54 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -128,6 +128,7 @@
 #include "lpp_tran.h"
 #include "transcendent.h"
 
+#include "FDK_crc.h"
 
 #include "sbrdec_drc.h"
 
@@ -137,7 +138,7 @@
 /* Decoder library info */
 #define SBRDECODER_LIB_VL0 2
 #define SBRDECODER_LIB_VL1 2
-#define SBRDECODER_LIB_VL2 7
+#define SBRDECODER_LIB_VL2 12
 #define SBRDECODER_LIB_TITLE "SBR Decoder"
 #ifdef __ANDROID__
 #define SBRDECODER_LIB_BUILD_DATE ""
@@ -194,6 +195,33 @@
   hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi;
 }
 
+static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 )
+{
+  int result = 0;
+
+  /* compare basic data */
+  result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0;
+  result |= (hHdr1->status != hHdr2->status) ? 1 : 0;
+  result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0;
+  result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0;
+  result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0;
+  result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0;
+  result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0;
+
+  /* compare bitstream data */
+  result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) );
+  result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) );
+
+  /* compare frequency band data */
+  result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) );
+  result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) );
+  result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
+  result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) );
+  result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
+
+  return result;
+}
+
 
 /*!
   \brief Reset SBR decoder.
@@ -391,6 +419,7 @@
     case AOT_PS:
     case AOT_ER_AAC_SCAL:
     case AOT_ER_AAC_ELD:
+    case AOT_DRM_AAC:
       return 1;
     default:
       return 0;
@@ -463,6 +492,8 @@
 
   self->flags = 0;
   self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0;
+  self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0;
+  self->flags |= (coreCodec == AOT_DRM_AAC)     ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0;
 
   /* Init SBR elements */
   {
@@ -928,24 +959,73 @@
         )
 {
   SBR_DECODER_ELEMENT   *hSbrElement;
-  HANDLE_SBR_HEADER_DATA hSbrHeader;
+  HANDLE_SBR_HEADER_DATA hSbrHeader = NULL;
   HANDLE_SBR_CHANNEL    *pSbrChannel;
 
   SBR_FRAME_DATA *hFrameDataLeft;
   SBR_FRAME_DATA *hFrameDataRight;
 
   SBR_ERROR errorStatus = SBRDEC_OK;
-  SBR_SYNC_STATE initialSyncState;
   SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
 
   INT  startPos;
   INT  CRCLen = 0;
+  HANDLE_FDK_BITSTREAM hBsOriginal = hBs;
+  FDK_CRCINFO  crcInfo;         /* shall be used for all other CRCs in the future (TBD) */
+  INT          crcReg = 0;
+  USHORT       drmSbrCrc = 0;
 
   int  stereo;
   int  fDoDecodeSbrData = 1;
 
   int lastSlot, lastHdrSlot = 0, thisHdrSlot;
 
+  /* Reverse bits of DRM SBR payload */
+  if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 )
+  {
+    UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1;
+    HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512));
+    int dataBytes, dataBits;
+
+    dataBits = *count;
+
+    if (dataBits > ((512)*8)) {
+      /* do not flip more data than needed */
+      dataBits = (512)*8;
+    }
+
+    dataBytes = (dataBits+7)>>3;
+
+    int j;
+
+    if ((j = (int)FDKgetValidBits(hBs)) != 8) {
+      FDKpushBiDirectional(hBs, (j-8));
+    }
+
+    j = 0;
+    for ( ; dataBytes > 0; dataBytes--)
+    {
+      int i;
+      UCHAR tmpByte;
+      UCHAR buffer = 0x00;
+
+      tmpByte = (UCHAR) FDKreadBits(hBs, 8);
+      for (i = 0; i < 4; i++) {
+        int shift = 2 * i + 1;
+        buffer |= (tmpByte & (0x08>>i)) << shift;
+        buffer |= (tmpByte & (0x10<<i)) >> shift;
+      }
+      bsBufferDrm[j++] = buffer;
+      FDKpushBack(hBs, 16);
+    }
+
+    FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER);
+
+    /* Use reversed data */
+    hBs = hBsBwd;
+    bsPayLen = *count;
+  }
+
   /* Remember start position of  SBR element */
   startPos = FDKgetValidBits(hBs);
 
@@ -970,7 +1050,6 @@
   hFrameDataLeft  = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
   hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
 
-  initialSyncState = hSbrHeader->syncState;
 
   /* reset PS flag; will be set after PS was found */
   self->flags &= ~SBRDEC_PS_DECODED;
@@ -1006,12 +1085,19 @@
   */
   if (fDoDecodeSbrData)
   {
-    if (crcFlag == 1) {
+    if (crcFlag) {
       switch (self->coreCodec) {
       case AOT_ER_AAC_ELD:
         FDKpushFor (hBs, 10);
         /* check sbrcrc later: we don't know the payload length now */
         break;
+      case AOT_DRM_AAC:
+        drmSbrCrc = (USHORT)FDKreadBits(hBs, 8);
+        /* Setup CRC decoder */
+        FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8);
+        /* Start CRC region */
+        crcReg = FDKcrcStartReg(&crcInfo, hBs, 0);
+        break;
       default:
         CRCLen = bsPayLen - 10;                     /* change: 0 => i */
         if (CRCLen < 0) {
@@ -1056,6 +1142,7 @@
         hSbrHeader->syncState = SBR_HEADER;
       } else {
         hSbrHeader->syncState = SBR_NOT_INITIALIZED;
+        headerStatus = HEADER_ERROR;
       }
     }
 
@@ -1105,7 +1192,7 @@
         valBits = (INT)FDKgetValidBits(hBs);
       }
 
-      if ( crcFlag == 1 ) {
+      if ( crcFlag ) {
         switch (self->coreCodec) {
         case AOT_ER_AAC_ELD:
           {
@@ -1117,6 +1204,14 @@
             FDKpushFor(hBs, crcLen);
           }
           break;
+        case AOT_DRM_AAC:
+          /* End CRC region */
+          FDKcrcEndReg(&crcInfo, hBs, crcReg);
+          /* Check CRC */
+          if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) {
+            fDoDecodeSbrData = 0;
+          }
+          break;
         default:
           break;
         }
@@ -1167,8 +1262,25 @@
   }
 
 bail:
-  if (errorStatus == SBRDEC_OK) {
-    if (headerStatus == HEADER_NOT_PRESENT) {
+
+  if ( self->flags & SBRDEC_SYNTAX_DRM )
+  {
+    hBs = hBsOriginal;
+  }
+
+  if ( (errorStatus == SBRDEC_OK)
+    || ( (errorStatus == SBRDEC_PARSE_ERROR)
+      && (headerStatus != HEADER_ERROR) ) )
+  {
+    int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT)
+                   || (headerStatus == HEADER_ERROR) ) ? 1 : 0;
+
+    if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) {
+      useOldHdr |= ( compareSbrHeader( hSbrHeader,
+                                      &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0;
+    }
+
+    if (useOldHdr != 0) {
       /* Use the old header for this frame */
       hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
     } else {
@@ -1229,12 +1341,21 @@
   int  numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
 
   if (self->flags & SBRDEC_FLUSH) {
-    /* Move frame pointer to the next slot which is up to be decoded/applied next */
-    hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
-    /* Update header and frame data pointer because they have already been set */
-    hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
-    hFrameDataLeft  = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
-    hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+    if ( self->numFlushedFrames > self->numDelayFrames ) {
+      int hdrIdx;
+      /* No valid SBR payload available, hence switch to upsampling (in all headers) */
+      for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) {
+        self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
+      }
+    }
+    else {
+      /* Move frame pointer to the next slot which is up to be decoded/applied next */
+      hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
+      /* Update header and frame data pointer because they have already been set */
+      hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
+      hFrameDataLeft  = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
+      hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+    }
   }
 
   /* Update the header error flag */
@@ -1354,7 +1475,8 @@
            &pSbrChannel[0]->prevFrameData,
             (hSbrHeader->syncState == SBR_ACTIVE),
             h_ps_d,
-            self->flags
+            self->flags,
+            codecFrameSize
           );
 
   if (stereo) {
@@ -1371,7 +1493,8 @@
              &pSbrChannel[1]->prevFrameData,
               (hSbrHeader->syncState == SBR_ACTIVE),
               NULL,
-              self->flags
+              self->flags,
+              codecFrameSize
             );
   }
 
@@ -1387,20 +1510,21 @@
     if ( !(self->flags & SBRDEC_PS_DECODED) ) {
       /* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */
       /* So copy left channel to right channel.                                                              */
+      int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac;
       if (interleaved) {
         INT_PCM *ptr;
         INT i;
         FDK_ASSERT(strideOut == 2);
 
         ptr = timeData;
-        for (i = codecFrameSize; i--; ) 
+        for (i = copyFrameSize>>1; i--; )
         {
           INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */
           tmp = *ptr++; *ptr++ = tmp;
           tmp = *ptr++; *ptr++ = tmp;
         }
       } else {
-        FDKmemcpy( timeData+2*codecFrameSize, timeData, 2*codecFrameSize*sizeof(INT_PCM) );
+        FDKmemcpy( timeData+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) );
       }
     }
     *numOutChannels = 2;  /* Output minimum two channels when PS is enabled. */
@@ -1464,14 +1588,23 @@
     self->flags &= ~SBRDEC_PS_DECODED;
   }
 
+  if ( self->flags & SBRDEC_FLUSH ) {
+    /* flushing is signalized, hence increment the flush frame counter */
+    self->numFlushedFrames++;
+  }
+  else {
+    /* no flushing is signalized, hence reset the flush frame counter */
+    self->numFlushedFrames = 0;
+  }
+
   /* Loop over SBR elements */
   for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++)
   {
     int numElementChan;
 
     if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
-      errorStatus = SBRDEC_UNSUPPORTED_CONFIG;
-      goto bail;
+      /* Disable PS and try decoding SBR mono. */
+      psPossible = 0;
     }
 
     numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
@@ -1579,6 +1712,7 @@
     | CAPF_SBR_HQ
     | CAPF_SBR_LP
     | CAPF_SBR_PS_MPEG
+    | CAPF_SBR_DRM_BS
     | CAPF_SBR_CONCEALMENT
     | CAPF_SBR_DRC
       ;
@@ -1607,6 +1741,9 @@
         /* Low delay SBR: */
         {
           outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64;   /* QMF synthesis */
+          if (flags & SBRDEC_LD_MPS_QMF) {
+            outputDelay += 32;
+          }
         }
       }
       else if (!IS_USAC(self->coreCodec)) {
diff --git a/libSYS/src/genericStds.cpp b/libSYS/src/genericStds.cpp
index 53abe06..89c422c 100644
--- a/libSYS/src/genericStds.cpp
+++ b/libSYS/src/genericStds.cpp
@@ -92,14 +92,14 @@
 
 #define _CRT_SECURE_NO_WARNINGS
 
-#include "genericStds.h"
-
 #include <math.h>
 
+#include "genericStds.h"
+
 /* library info */
 #define SYS_LIB_VL0 1
 #define SYS_LIB_VL1 3
-#define SYS_LIB_VL2 7
+#define SYS_LIB_VL2 8
 #define SYS_LIB_TITLE "System Integration Library"
 #ifdef __ANDROID__
 #define SYS_LIB_BUILD_DATE ""