Fix HE-AAC using MPEG-D DRC with implicit SBR signaling.
am: e970ac4c95

Change-Id: I03a32ac0868171f3239424a39ac7dc7e55c9df9b
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index 4046d66..86ec899 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1676,6 +1676,13 @@
             reverseOutChannelMap[ch] = ch;
           }
 
+          /* Update sampleRate and frameSize. This may be necessary in case of
+           * implicit SBR signaling */
+          FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_SAMPLE_RATE,
+                              self->streamInfo.sampleRate);
+          FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_FRAME_SIZE,
+                              self->streamInfo.frameSize);
+
           /* If SBR and/or MPS is active, the DRC gains are aligned to the QMF
              domain signal before the QMF synthesis. Therefore the DRC gains
              need to be delayed by the QMF synthesis delay. */
diff --git a/libDRCdec/include/FDK_drcDecLib.h b/libDRCdec/include/FDK_drcDecLib.h
index 9a99ed1..2d28d23 100644
--- a/libDRCdec/include/FDK_drcDecLib.h
+++ b/libDRCdec/include/FDK_drcDecLib.h
@@ -142,6 +142,8 @@
                                              choosing an appropriate
                                              downmixInstruction */
   DRC_DEC_BASE_CHANNEL_COUNT,
+  DRC_DEC_FRAME_SIZE,
+  DRC_DEC_SAMPLE_RATE,
   /* get only system parameters */
   DRC_DEC_IS_MULTIBAND_DRC_1,
   DRC_DEC_IS_MULTIBAND_DRC_2,
diff --git a/libDRCdec/src/FDK_drcDecLib.cpp b/libDRCdec/src/FDK_drcDecLib.cpp
index 8f3faa0..4f8ebc7 100644
--- a/libDRCdec/src/FDK_drcDecLib.cpp
+++ b/libDRCdec/src/FDK_drcDecLib.cpp
@@ -336,7 +336,13 @@
   }
 
   if (hDrcDec->functionalRange & DRC_DEC_GAIN) {
-    dErr = drcDec_GainDecoder_Init(hDrcDec->hGainDec, frameSize, sampleRate);
+    dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE,
+                                       frameSize);
+    if (dErr) return DRC_DEC_NOT_OK;
+    dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE,
+                                       sampleRate);
+    if (dErr) return DRC_DEC_NOT_OK;
+    dErr = drcDec_GainDecoder_Init(hDrcDec->hGainDec);
     if (dErr) return DRC_DEC_NOT_OK;
   }
 
@@ -377,79 +383,99 @@
 FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec,
                     const DRC_DEC_USERPARAM requestType,
                     const FIXP_DBL requestValue) {
+  DRC_ERROR dErr = DE_OK;
   DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR;
+  int invalidParameter = 0;
 
   if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED;
 
-  if (hDrcDec->functionalRange == DRC_DEC_GAIN)
-    return DRC_DEC_NOT_OK; /* not supported for DRC_DEC_GAIN. All parameters are
-                              handed over to selection process lib. */
-
-  switch (requestType) {
-    case DRC_DEC_BOOST:
-      sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
-                                              SEL_PROC_BOOST, requestValue,
-                                              &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_COMPRESS:
-      sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
-                                              SEL_PROC_COMPRESS, requestValue,
-                                              &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_LOUDNESS_NORMALIZATION_ON:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON,
-          requestValue, &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_TARGET_LOUDNESS:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_TARGET_LOUDNESS, requestValue,
-          &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_EFFECT_TYPE:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_EFFECT_TYPE, requestValue,
-          &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_DOWNMIX_ID:
-      sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
-                                              SEL_PROC_DOWNMIX_ID, requestValue,
-                                              &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_TARGET_CHANNEL_COUNT, requestValue,
-          &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_BASE_CHANNEL_COUNT:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, requestValue,
-          &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_NOT_OK;
-      break;
-    case DRC_DEC_LOUDNESS_MEASUREMENT_METHOD:
-      sErr = drcDec_SelectionProcess_SetParam(
-          hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_MEASUREMENT_METHOD,
-          requestValue, &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    case DRC_DEC_ALBUM_MODE:
-      sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
-                                              SEL_PROC_ALBUM_MODE, requestValue,
-                                              &(hDrcDec->selProcInputDiff));
-      if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
-      break;
-    default:
-      return DRC_DEC_INVALID_PARAM;
+  if (hDrcDec->functionalRange & DRC_DEC_GAIN) {
+    switch (requestType) {
+      case DRC_DEC_SAMPLE_RATE:
+        dErr = drcDec_GainDecoder_SetParam(
+            hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE, (int)requestValue);
+        if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_FRAME_SIZE:
+        dErr = drcDec_GainDecoder_SetParam(
+            hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE, (int)requestValue);
+        if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      default:
+        invalidParameter |= DRC_DEC_GAIN;
+    }
   }
 
+  if (hDrcDec->functionalRange & DRC_DEC_SELECTION) {
+    switch (requestType) {
+      case DRC_DEC_BOOST:
+        sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
+                                                SEL_PROC_BOOST, requestValue,
+                                                &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_COMPRESS:
+        sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc,
+                                                SEL_PROC_COMPRESS, requestValue,
+                                                &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_LOUDNESS_NORMALIZATION_ON:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON,
+            requestValue, &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_TARGET_LOUDNESS:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_TARGET_LOUDNESS, requestValue,
+            &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_EFFECT_TYPE:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_EFFECT_TYPE, requestValue,
+            &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_DOWNMIX_ID:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_DOWNMIX_ID, requestValue,
+            &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_TARGET_CHANNEL_COUNT,
+            requestValue, &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_BASE_CHANNEL_COUNT:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, requestValue,
+            &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_NOT_OK;
+        break;
+      case DRC_DEC_LOUDNESS_MEASUREMENT_METHOD:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_MEASUREMENT_METHOD,
+            requestValue, &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      case DRC_DEC_ALBUM_MODE:
+        sErr = drcDec_SelectionProcess_SetParam(
+            hDrcDec->hSelectionProc, SEL_PROC_ALBUM_MODE, requestValue,
+            &(hDrcDec->selProcInputDiff));
+        if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE;
+        break;
+      default:
+        invalidParameter |= DRC_DEC_SELECTION;
+    }
+  }
+
+  if (invalidParameter == hDrcDec->functionalRange)
+    return DRC_DEC_INVALID_PARAM;
+
   /* All parameters need a new start of the selection process */
   startSelectionProcess(hDrcDec);
 
diff --git a/libDRCdec/src/drcDec_gainDecoder.cpp b/libDRCdec/src/drcDec_gainDecoder.cpp
index ca81fad..9d91267 100644
--- a/libDRCdec/src/drcDec_gainDecoder.cpp
+++ b/libDRCdec/src/drcDec_gainDecoder.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -170,11 +170,10 @@
 }
 
 DRC_ERROR
-drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize,
-                        const int sampleRate) {
+drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec) {
   DRC_ERROR err = DE_OK;
 
-  err = initGainDec(hGainDec, frameSize, sampleRate);
+  err = initGainDec(hGainDec);
   if (err) return err;
 
   initDrcGainBuffers(hGainDec->frameSize, &hGainDec->drcGainBuffers);
@@ -183,6 +182,25 @@
 }
 
 DRC_ERROR
+drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec,
+                            const GAIN_DEC_PARAM paramType,
+                            const int paramValue) {
+  switch (paramType) {
+    case GAIN_DEC_FRAME_SIZE:
+      if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE;
+      hGainDec->frameSize = paramValue;
+      break;
+    case GAIN_DEC_SAMPLE_RATE:
+      if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE;
+      hGainDec->deltaTminDefault = getDeltaTmin(paramValue);
+      break;
+    default:
+      return DE_PARAM_INVALID;
+  }
+  return DE_OK;
+}
+
+DRC_ERROR
 drcDec_GainDecoder_SetCodecDependentParameters(
     HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode,
     const int timeDomainSupported,
diff --git a/libDRCdec/src/drcDec_gainDecoder.h b/libDRCdec/src/drcDec_gainDecoder.h
index 2f4df4c..394b455 100644
--- a/libDRCdec/src/drcDec_gainDecoder.h
+++ b/libDRCdec/src/drcDec_gainDecoder.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -134,6 +134,8 @@
   GAIN_DEC_DRC2_DRC3
 } GAIN_DEC_LOCATION;
 
+typedef enum { GAIN_DEC_FRAME_SIZE, GAIN_DEC_SAMPLE_RATE } GAIN_DEC_PARAM;
+
 typedef struct {
   FIXP_DBL gainLin; /* e = 7 */
   SHORT time;
@@ -195,8 +197,12 @@
 drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec);
 
 DRC_ERROR
-drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize,
-                        const int sampleRate);
+drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec);
+
+DRC_ERROR
+drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec,
+                            const GAIN_DEC_PARAM paramType,
+                            const int paramValue);
 
 DRC_ERROR
 drcDec_GainDecoder_SetCodecDependentParameters(
diff --git a/libDRCdec/src/drcGainDec_init.cpp b/libDRCdec/src/drcGainDec_init.cpp
index c9f87d7..89d0f55 100644
--- a/libDRCdec/src/drcGainDec_init.cpp
+++ b/libDRCdec/src/drcGainDec_init.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -184,24 +184,11 @@
 }
 
 DRC_ERROR
-initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize,
-            const int sampleRate) {
+initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec) {
   int i, j, k;
 
-  if (frameSize < 1) {
-    return DE_NOT_OK;
-  }
-
-  hGainDec->frameSize = frameSize;
-
-  if (hGainDec->frameSize * 1000 < sampleRate) {
-    return DE_NOT_OK;
-  }
-
-  hGainDec->deltaTminDefault = getDeltaTmin(sampleRate);
-  if (hGainDec->deltaTminDefault > hGainDec->frameSize) {
-    return DE_NOT_OK;
-  }
+  /* sanity check */
+  if (hGainDec->deltaTminDefault > hGainDec->frameSize) return DE_NOT_OK;
 
   for (i = 0; i < MAX_ACTIVE_DRCS; i++) {
     for (j = 0; j < 8; j++) {
diff --git a/libDRCdec/src/drcGainDec_init.h b/libDRCdec/src/drcGainDec_init.h
index 9215bc3..c0b9853 100644
--- a/libDRCdec/src/drcGainDec_init.h
+++ b/libDRCdec/src/drcGainDec_init.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -104,8 +104,7 @@
 #define DRCGAINDEC_INIT_H
 
 DRC_ERROR
-initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize,
-            const int sampleRate);
+initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec);
 
 void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers);