Snap for 8426163 from 76104a5431c7753df108e410c805aefefac16cf1 to mainline-tzdata2-release

Change-Id: I4cfc66299eafb434f52b1ae513a51f126b7714de
diff --git a/Android.bp b/Android.bp
index 0c67186..3f42c19 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,40 +1,6 @@
-// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS.  PLEASE
-//     CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
-//     DEPENDING ON IT IN YOUR PROJECT. ***
-package {
-    default_applicable_licenses: ["external_aac_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
-    name: "external_aac_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-        "legacy_by_exception_only", // by exception only
-    ],
-    license_text: [
-        "NOTICE",
-    ],
-}
-
 cc_library_static {
     name: "libFraunhoferAAC",
     vendor_available: true,
-    host_supported: true,
     srcs: [
         "libAACdec/src/*.cpp",
         "libAACenc/src/*.cpp",
@@ -60,12 +26,13 @@
         "-DSUPPRESS_BUILD_DATE_INFO",
     ],
     sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-            "bounds",
+        misc_undefined:[
+           "unsigned-integer-overflow",
+           "signed-integer-overflow",
+           "bounds",
         ],
-        cfi: true,
+        // Enable CFI if this becomes a shared library.
+        // cfi: true,
     },
     shared_libs: [
         "liblog",
@@ -86,12 +53,6 @@
         "libSACenc/include",
     ],
 
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-
     apex_available: [
         "//apex_available:platform",
         "com.android.bluetooth.updatable",
diff --git a/METADATA b/METADATA
deleted file mode 100644
index 5c12860..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
-  license_type: BY_EXCEPTION_ONLY
-}
diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf
index 3d4699e..cc7cf41 100644
--- a/documentation/aacDecoder.pdf
+++ b/documentation/aacDecoder.pdf
Binary files differ
diff --git a/documentation/aacEncoder.pdf b/documentation/aacEncoder.pdf
index a47708a..77b8f4c 100644
--- a/documentation/aacEncoder.pdf
+++ b/documentation/aacEncoder.pdf
Binary files differ
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
deleted file mode 100644
index 6739798..0000000
--- a/fuzzer/Android.bp
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *****************************************************************************
- * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
- */
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_aac_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_aac_license"],
-}
-
-cc_defaults {
-    name: "aac_fuzz_defaults",
-    host_supported: true,
-
-    static_libs: [
-        "libFraunhoferAAC",
-    ],
-
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-
-    fuzz_config: {
-        cc: [
-            "android-media-fuzzing-reports@google.com",
-        ],
-        componentid: 155276,
-    },
-}
-
-cc_fuzz {
-    name: "aac_dec_fuzzer",
-
-    srcs: [
-        "aac_dec_fuzzer.cpp",
-    ],
-
-    static_libs: [
-        "liblog",
-    ],
-
-    defaults: [
-        "aac_fuzz_defaults"
-    ],
-}
-
-cc_fuzz {
-    name: "aac_enc_fuzzer",
-
-    srcs: [
-        "aac_enc_fuzzer.cpp",
-    ],
-
-    defaults: [
-        "aac_fuzz_defaults"
-    ],
-
-    include_dirs: [
-        "external/aac/libAACenc/"
-    ],
-}
diff --git a/fuzzer/README.md b/fuzzer/README.md
deleted file mode 100644
index b8cc260..0000000
--- a/fuzzer/README.md
+++ /dev/null
@@ -1,150 +0,0 @@
-# Fuzzer for libFraunhoferAAC decoder
-
-## Plugin Design Considerations
-The fuzzer plugin for aac decoder is designed based on the understanding of the
-codec and tries to achieve the following:
-
-##### Maximize code coverage
-
-This fuzzer makes use of the following config parameters:
-1. Transport type (parameter name: `TRANSPORT_TYPE`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-| `TRANSPORT_TYPE` | 0.`TT_UNKNOWN  ` 1.`TT_MP4_RAW ` 2.`TT_MP4_ADIF ` 3.`TT_MP4_ADTS ` 4.`TT_MP4_LATM_MCP1 ` 5.`TT_MP4_LATM_MCP0  ` 6.`TT_MP4_LOAS ` 7.`TT_DRM ` | `TT_MP4_ADIF ` |
-
-Note: Value of `TRANSPORT_TYPE` could be set to any of these values.
-It is set to `TT_MP4_ADIF` in the fuzzer plugin.
-
-##### Maximize utilization of input data
-The plugin feeds the entire input data to the codec using a loop.
- * If the decode operation was successful, the input is advanced by an
-   offset calculated using valid bytes.
- * If the decode operation was un-successful, the input is advanced by 1 byte
-   till it reaches a valid frame or end of stream.
-
-This ensures that the plugin tolerates any kind of input (empty, huge,
-malformed, etc) and doesnt `exit()` on any input and thereby increasing the
-chance of identifying vulnerabilities.
-
-## Build
-
-This describes steps to build aac_dec_fuzzer binary.
-
-## Android
-
-### Steps to build
-Build the fuzzer
-```
-  $ mm -j$(nproc) aac_dec_fuzzer
-```
-
-### Steps to run
-Create a directory CORPUS_DIR and copy some aac files to that folder.
-Push this directory to device.
-
-To run on device
-```
-  $ adb sync data
-  $ adb shell /data/fuzz/arm64/aac_dec_fuzzer/aac_dec_fuzzer CORPUS_DIR
-```
-To run on host
-```
-  $ $ANDROID_HOST_OUT/fuzz/x86_64/aac_dec_fuzzer/aac_dec_fuzzer CORPUS_DIR
-```
-
-# Fuzzer for libFraunhoferAAC encoder
-
-## Plugin Design Considerations
-The fuzzer plugin for aac encoder is designed based on the understanding of the
-codec and tries to achieve the following:
-
-##### Maximize code coverage
-
-The configuration parameters are not hardcoded, but instead selected based on
-incoming data. This ensures more code paths are reached by the fuzzer.
-
-Following arguments are passed to aacEncoder_SetParam to set the respective AACENC_PARAM parameter:
-
-| AACENC_PARAM param| Valid Values| Configured Value|
-|-------------| ----- |----- |
-|`AACENC_SBR_MODE` | `-1 ` `0 ` `1 ` `2 ` | Calculated using first byte of data |
-|`AACENC_AOT` |`AOT_NONE ` `AOT_NULL_OBJECT ` `AOT_AAC_MAIN ` `AOT_AAC_LC ` `AOT_AAC_SSR ` `AOT_AAC_LTP ` `AOT_SBR ` `AOT_AAC_SCAL ` `AOT_TWIN_VQ ` `AOT_CELP ` `AOT_HVXC ` `AOT_RSVD_10 ` `AOT_RSVD_11 ` `AOT_TTSI ` `AOT_MAIN_SYNTH ` `AOT_WAV_TAB_SYNTH ` `AOT_GEN_MIDI ` `AOT_ALG_SYNTH_AUD_FX ` `AOT_ER_AAC_LC ` `AOT_RSVD_18 ` `AOT_ER_AAC_LTP ` `AOT_ER_AAC_SCAL ` `AOT_ER_TWIN_VQ ` `AOT_ER_BSAC ` `AOT_ER_AAC_LD ` `AOT_ER_CELP ` `AOT_ER_HVXC ` `AOT_ER_HILN ` `AOT_ER_PARA ` `AOT_RSVD_28 ` `AOT_PS ` `AOT_MPEGS ` `AOT_ESCAPE ` `AOT_MP3ONMP4_L1 ` `AOT_MP3ONMP4_L2 ` `AOT_MP3ONMP4_L3 ` `AOT_RSVD_35 ` `AOT_RSVD_36 ` `AOT_AAC_SLS ` `AOT_SLS ` `AOT_ER_AAC_ELD ` `AOT_USAC ` `AOT_SAOC ` `AOT_LD_MPEGS ` `AOT_MP2_AAC_LC ` `AOT_MP2_SBR ` `AOT_DRM_AAC ` `AOT_DRM_SBR ` `AOT_DRM_MPEG_PS ` `AOT_DRM_SURROUND ` `AOT_DRM_USAC `  | Calculated using second byte of data  |
-|`AACENC_SAMPLERATE` |  `8000 ` `11025 ` `12000 ` `16000 ` `22050 ` `24000 ` `32000 ` `44100 ` `48000 ` `64000 ` `88200 ` `96000 `| Calculated using third byte of data  |
-|`AACENC_BITRATE` | In range `8000 ` to `960000 ` | Calculated using fourth, fifth and sixth byte of data  |
-|`AACENC_CHANNELMODE` | `MODE_1 ` `MODE_2 ` `MODE_1_2 ` `MODE_1_2_1 ` `MODE_1_2_2 ` `MODE_1_2_2_1 ` `MODE_1_2_2_2_1 ` `MODE_6_1 `  `MODE_7_1_BACK ` `MODE_7_1_TOP_FRONT ` `MODE_7_1_REAR_SURROUND ` `MODE_7_1_FRONT_CENTER ` `MODE_212 ` | Calculated using seventh byte of data |
-|`AACENC_TRANSMUX` | `TT_MP4_RAW ` `TT_MP4_ADIF ` `TT_MP4_ADTS ` `TT_MP4_LATM_MCP1 ` `TT_MP4_LATM_MCP0 ` `TT_MP4_LOAS ` `TT_DRM `  | Calculated using eight byte of data  |`AACENC_SBR_RATIO` |`-1 ` `0 ` `1 ` `2 ` | Calculated using ninth byte of data |
-|`AACENC_BITRATEMODE` |`AACENC_BR_MODE_INVALID ` `AACENC_BR_MODE_CBR ` `AACENC_BR_MODE_VBR_1 ` `AACENC_BR_MODE_VBR_2 ` `AACENC_BR_MODE_VBR_3 ` `AACENC_BR_MODE_VBR_4 ` `AACENC_BR_MODE_VBR_5 ` `AACENC_BR_MODE_FF ` `AACENC_BR_MODE_SFR `  | Calculated using thirty-fourth byte of data |
-|`AACENC_GRANULE_LENGTH` |`120 ` `128 ` `240 ` `256 ` `480 ` `512 ` `1024 ` | Calculated using thirty-fifth byte of data |
-|`AACENC_CHANNELORDER` |`CH_ORDER_MPEG ` `CH_ORDER_WAV ` | Calculated using thirty-sixth byte of data |
-|`AACENC_AFTERBURNER` |`0 ` `1 ` | Calculated using thirty-seventh byte of data |
-|`AACENC_BANDWIDTH` |`0 ` `1`  | Calculated using thirty-eigth byte of data |
-|` AACENC_IDX_PEAK_BITRATE` | In range `8000 ` to `960000 ` | Calculated using thirty-ninth byte of data |
-|` AACENC_HEADER_PERIOD` |In range `0 ` to `255 ` | Calculated using fortieth byte of data |
-|` AACENC_SIGNALING_MODE` |`-1 ` `0 ` `1 ` `2 ` `3 `  | Calculated using forty-first byte of data |
-|` AACENC_TPSUBFRAMES` |In range `0 ` to `255 ` | Calculated using forty-second byte of data |
-|` AACENC_AUDIOMUXVER` |`-1 ` `0 ` `1 ` `2 ` | Calculated using forty-third byte of data |
-|` AACENC_PROTECTION` |`0 ` `1 ` | Calculated using forty-fourth of data |
-|`AACENC_ANCILLARY_BITRATE` |In range `0 ` to `960000 `| Calculated using forty-fifth byte of data |
-|`AACENC_METADATA_MODE ` |`0 ` `1 ` `2 ` `3 ` | Calculated using forty-sixth byte of data |
-
-Following values are configured to set up the meta data represented by the class variable `mMetaData ` :
-
-| Variable name| Possible Values| Configured Value|
-|------------- | ----- |----- |
-| `drc_profile`   | `AACENC_METADATA_DRC_NONE ` `AACENC_METADATA_DRC_FILMSTANDARD ` `AACENC_METADATA_DRC_FILMLIGHT ` `AACENC_METADATA_DRC_MUSICSTANDARD ` `AACENC_METADATA_DRC_MUSICLIGHT ` `AACENC_METADATA_DRC_SPEECH ` `AACENC_METADATA_DRC_NOT_PRESENT `  | Calculated using tenth byte of data |
-| `comp_profile`   | `AACENC_METADATA_DRC_NONE ` `AACENC_METADATA_DRC_FILMSTANDARD ` `AACENC_METADATA_DRC_FILMLIGHT ` `AACENC_METADATA_DRC_MUSICSTANDARD ` `AACENC_METADATA_DRC_MUSICLIGHT ` `AACENC_METADATA_DRC_SPEECH ` `AACENC_METADATA_DRC_NOT_PRESENT `  | Calculated using eleventh byte of data |
-| `drc_TargetRefLevel`   | In range `0 ` to `255 `  | Calculated using twelfth byte of data |
-| `comp_TargetRefLevel`   | In range `0 ` to `255 `  | Calculated using thirteenth byte of data |
-| `prog_ref_level_present`   | `0 ` `1 `  | Calculated using fourteenth byte of data |
-| `prog_ref_level`   | In range `0 ` to `255 `  | Calculated using fifteenth byte of data |
-| `PCE_mixdown_idx_present`   | `0 ` `1 `   | Calculated using sixteenth byte of data |
-| `ETSI_DmxLvl_present`   | `0 ` `1 `   | Calculated using seventeenth byte of data |
-| `centerMixLevel`   | In range `0 ` to `7 `  | Calculated using eighteenth byte of data |
-| `surroundMixLevel`   | In range `0 ` to `7 `  | Calculated using nineteenth byte of data |
-| `dolbySurroundMode`   | In range `0 ` to `2 `   | Calculated using twentieth byte of data |
-| `drcPresentationMode`   | In range `0 ` to `2 `   | Calculated using twenty-first byte of data |
-| `extAncDataEnable`   | `0 ` `1 `  | Calculated using twenty-second byte of data |
-| `extDownmixLevelEnable`   | `0 ` `1 `  | Calculated using twenty-third byte of data |
-| `extDownmixLevel_A`   | In range `0 ` to `7 `  | Calculated using twenty-fourth byte of data |
-| `extDownmixLevel_B`   | In range `0 ` to `7 `  | Calculated using twenty-fifth byte of data |
-| `dmxGainEnable`   |  `0 ` `1 `   | Calculated using twenty-sixth byte of data |
-| `dmxGain5`   | In range `0 ` to `255 `  | Calculated using twenty-seventh byte of data |
-| `dmxGain2`   | In range `0 ` to `255 `  | Calculated using twenty-eighth byte of data |
-| `lfeDmxEnable`   | `0 ` `1 `  | Calculated using twenty-ninth byte of data |
-| `lfeDmxLevel`   | In range `0 ` to `15 `  | Calculated using thirtieth byte of data |
-
-Indexes `mInBufferIdx_1`, `mInBufferIdx_2`  and `mInBufferIdx_3`(in range `0 ` to `2`) are calculated using the thirty-first, thirty-second and thirty-third byte respectively.
-
-##### Maximize utilization of input data
-The plugin feeds the entire input data to the codec and continues with the encoding even on a failure. This ensures that the plugin tolerates any kind of input (empty, huge, malformed, etc) and doesnt `exit()` on any input and thereby increasing the chance of identifying vulnerabilities.
-
-## Build
-
-This describes steps to build aac_enc_fuzzer binary.
-
-## Android
-
-### Steps to build
-Build the fuzzer
-```
-  $ mm -j$(nproc) aac_enc_fuzzer
-```
-
-### Steps to run
-Create a directory CORPUS_DIR and copy some raw files to that folder.
-Push this directory to device.
-
-To run on device
-```
-  $ adb sync data
-  $ adb shell /data/fuzz/arm64/aac_enc_fuzzer/aac_enc_fuzzer CORPUS_DIR
-```
-To run on host
-```
-  $ $ANDROID_HOST_OUT/fuzz/x86_64/aac_enc_fuzzer/aac_enc_fuzzer CORPUS_DIR
-```
-
-## References:
- * http://llvm.org/docs/LibFuzzer.html
- * https://github.com/google/oss-fuzz
diff --git a/fuzzer/aac_dec_fuzzer.cpp b/fuzzer/aac_dec_fuzzer.cpp
deleted file mode 100644
index c970197..0000000
--- a/fuzzer/aac_dec_fuzzer.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *****************************************************************************
- * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <algorithm>
-#include "aacdecoder_lib.h"
-
-constexpr uint8_t kNumberOfLayers = 1;
-constexpr uint8_t kMaxChannelCount = 8;
-constexpr uint32_t kMaxConfigurationSize = 1024;
-constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount;
-
-// Value indicating the start of AAC Header Segment
-constexpr const char *kAacSegStartSeq = "AAC_STRT";
-constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq);
-// Value indicating the end of AAC Header Segment
-constexpr const char *kAacSegEndSeq = "AAC_ENDS";
-constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq);
-
-// Number of bytes used to signal the length of the header
-constexpr uint8_t kHeaderLengthBytes = 2;
-// Minimum size of an AAC header is 2
-// Minimum data required is
-// strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2;
-constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2;
-
-UINT getHeaderSize(UCHAR *data, UINT size) {
-  if (size < kMinDataSize) {
-    return 0;
-  }
-
-  int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen);
-  if (result) {
-    return 0;
-  }
-  data += kAacSegStartSeqLen;
-  size -= kAacSegStartSeqLen;
-
-  uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF;
-  data += kHeaderLengthBytes;
-  size -= kHeaderLengthBytes;
-
-  if (headerLengthInBytes + kAacSegEndSeqLen > size) {
-    return 0;
-  }
-
-  data += headerLengthInBytes;
-  size -= headerLengthInBytes;
-  result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen);
-  if (result) {
-    return 0;
-  }
-
-  return std::min(headerLengthInBytes, kMaxConfigurationSize);
-}
-
-class Codec {
- public:
-  Codec() = default;
-  ~Codec() { deInitDecoder(); }
-  bool initDecoder();
-  void decodeFrames(UCHAR *data, UINT size);
-  void deInitDecoder();
-
- private:
-  HANDLE_AACDECODER mAacDecoderHandle = nullptr;
-  AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
-};
-
-bool Codec::initDecoder() {
-  mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
-  if (!mAacDecoderHandle) {
-    return false;
-  }
-  return true;
-}
-
-void Codec::deInitDecoder() {
-  aacDecoder_Close(mAacDecoderHandle);
-  mAacDecoderHandle = nullptr;
-}
-
-void Codec::decodeFrames(UCHAR *data, UINT size) {
-  UINT headerSize = getHeaderSize(data, size);
-  if (headerSize != 0) {
-    data += kAacSegStartSeqLen + kHeaderLengthBytes;
-    size -= kAacSegStartSeqLen + kHeaderLengthBytes;
-    aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize);
-    data += headerSize + kAacSegEndSeqLen;
-    size -= headerSize + kAacSegEndSeqLen;
-  }
-  while (size > 0) {
-    UINT inputSize = size;
-    UINT valid = size;
-    mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
-    if (mErrorCode != AAC_DEC_OK) {
-      ++data;
-      --size;
-    } else {
-      INT_PCM outputBuf[kMaxOutBufferSize];
-      do {
-        mErrorCode =
-            aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
-                    kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0);
-      } while (mErrorCode == AAC_DEC_OK);
-      UINT offset = inputSize - valid;
-      data += offset;
-      size = valid;
-    }
-  }
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  Codec *codec = new Codec();
-  if (!codec) {
-    return 0;
-  }
-  if (codec->initDecoder()) {
-    codec->decodeFrames((UCHAR *)(data), static_cast<UINT>(size));
-  }
-  delete codec;
-  return 0;
-}
diff --git a/fuzzer/aac_enc_fuzzer.cpp b/fuzzer/aac_enc_fuzzer.cpp
deleted file mode 100644
index 5a35d70..0000000
--- a/fuzzer/aac_enc_fuzzer.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *****************************************************************************
- * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
- */
-
-#include <string>
-#include "aacenc_lib.h"
-#include "src/aacenc.h"
-
-using namespace std;
-
-// IN_AUDIO_DATA, IN_ANCILLRY_DATA and IN_METADATA_SETUP
-constexpr size_t kMaxBuffers = 3;
-
-constexpr size_t kMaxOutputBufferSize = 8192;
-
-constexpr uint32_t kMinBitRate = 8000;
-constexpr uint32_t kMaxBitRate = 960000;
-
-constexpr int32_t kSampleRates[] = {8000,  11025, 12000, 16000, 22050, 24000,
-                                    32000, 44100, 48000, 64000, 88200, 96000};
-constexpr size_t kSampleRatesSize = size(kSampleRates);
-
-constexpr CHANNEL_MODE kChannelModes[] = {MODE_1,
-                                          MODE_2,
-                                          MODE_1_2,
-                                          MODE_1_2_1,
-                                          MODE_1_2_2,
-                                          MODE_1_2_2_1,
-                                          MODE_1_2_2_2_1,
-                                          MODE_6_1,
-                                          MODE_7_1_BACK,
-                                          MODE_7_1_TOP_FRONT,
-                                          MODE_7_1_REAR_SURROUND,
-                                          MODE_7_1_FRONT_CENTER,
-                                          MODE_212};
-constexpr size_t kChannelModesSize = size(kChannelModes);
-
-constexpr TRANSPORT_TYPE kIdentifiers[] = {
-    TT_MP4_RAW, TT_MP4_ADIF, TT_MP4_ADTS, TT_MP4_LATM_MCP1, TT_MP4_LATM_MCP0, TT_MP4_LOAS, TT_DRM};
-constexpr size_t kIdentifiersSize = size(kIdentifiers);
-
-constexpr AUDIO_OBJECT_TYPE kAudioObjectTypes[] = {AOT_NONE,        AOT_NULL_OBJECT,
-                                                   AOT_AAC_MAIN,    AOT_AAC_LC,
-                                                   AOT_AAC_SSR,     AOT_AAC_LTP,
-                                                   AOT_SBR,         AOT_AAC_SCAL,
-                                                   AOT_TWIN_VQ,     AOT_CELP,
-                                                   AOT_HVXC,        AOT_RSVD_10,
-                                                   AOT_RSVD_11,     AOT_TTSI,
-                                                   AOT_MAIN_SYNTH,  AOT_WAV_TAB_SYNTH,
-                                                   AOT_GEN_MIDI,    AOT_ALG_SYNTH_AUD_FX,
-                                                   AOT_ER_AAC_LC,   AOT_RSVD_18,
-                                                   AOT_ER_AAC_LTP,  AOT_ER_AAC_SCAL,
-                                                   AOT_ER_TWIN_VQ,  AOT_ER_BSAC,
-                                                   AOT_ER_AAC_LD,   AOT_ER_CELP,
-                                                   AOT_ER_HVXC,     AOT_ER_HILN,
-                                                   AOT_ER_PARA,     AOT_RSVD_28,
-                                                   AOT_PS,          AOT_MPEGS,
-                                                   AOT_ESCAPE,      AOT_MP3ONMP4_L1,
-                                                   AOT_MP3ONMP4_L2, AOT_MP3ONMP4_L3,
-                                                   AOT_RSVD_35,     AOT_RSVD_36,
-                                                   AOT_AAC_SLS,     AOT_SLS,
-                                                   AOT_ER_AAC_ELD,  AOT_USAC,
-                                                   AOT_SAOC,        AOT_LD_MPEGS,
-                                                   AOT_MP2_AAC_LC,  AOT_MP2_SBR,
-                                                   AOT_DRM_AAC,     AOT_DRM_SBR,
-                                                   AOT_DRM_MPEG_PS, AOT_DRM_SURROUND,
-                                                   AOT_DRM_USAC};
-
-constexpr size_t kAudioObjectTypesSize = size(kAudioObjectTypes);
-
-constexpr int32_t kSbrRatios[] = {-1, 0, 1, 2};
-constexpr size_t kSbrRatiosSize = size(kSbrRatios);
-
-constexpr int32_t kBitRateModes[] = {
-    AACENC_BR_MODE_INVALID, AACENC_BR_MODE_CBR,   AACENC_BR_MODE_VBR_1,
-    AACENC_BR_MODE_VBR_2,   AACENC_BR_MODE_VBR_3, AACENC_BR_MODE_VBR_4,
-    AACENC_BR_MODE_VBR_5,   AACENC_BR_MODE_FF,    AACENC_BR_MODE_SFR};
-constexpr size_t kBitRateModesSize = size(kBitRateModes);
-
-constexpr int32_t kGranuleLengths[] = {120, 128, 240, 256, 480, 512, 1024};
-constexpr size_t kGranuleLengthsSize = size(kGranuleLengths);
-
-constexpr int32_t kChannelOrder[] = {CH_ORDER_MPEG, CH_ORDER_WAV};
-constexpr size_t kChannelOrderSize = size(kChannelOrder);
-
-constexpr int32_t kSignalingModes[] = {-1, 0, 1, 2, 3};
-constexpr size_t kSignalingModesSize = size(kSignalingModes);
-
-constexpr int32_t kAudioMuxVer[] = {-1, 0, 1, 2};
-constexpr size_t kAudioMuxVerSize = size(kAudioMuxVer);
-
-constexpr int32_t kSbrModes[] = {-1, 0, 1, 2};
-constexpr size_t kSbrModesSize = size(kSbrModes);
-
-constexpr AACENC_METADATA_DRC_PROFILE kMetaDataDrcProfiles[] = {
-    AACENC_METADATA_DRC_NONE,       AACENC_METADATA_DRC_FILMSTANDARD,
-    AACENC_METADATA_DRC_FILMLIGHT,  AACENC_METADATA_DRC_MUSICSTANDARD,
-    AACENC_METADATA_DRC_MUSICLIGHT, AACENC_METADATA_DRC_SPEECH,
-    AACENC_METADATA_DRC_NOT_PRESENT};
-constexpr size_t kMetaDataDrcProfilesSize = size(kMetaDataDrcProfiles);
-
-enum {
-    IDX_SBR_MODE = 0,
-    IDX_AAC_AOT,
-    IDX_SAMPLE_RATE,
-    IDX_BIT_RATE_1,
-    IDX_BIT_RATE_2,
-    IDX_BIT_RATE_3,
-    IDX_CHANNEL,
-    IDX_IDENTIFIER,
-    IDX_SBR_RATIO,
-    IDX_METADATA_DRC_PROFILE,
-    IDX_METADATA_COMP_PROFILE,
-    IDX_METADATA_DRC_TARGET_REF_LEVEL,
-    IDX_METADATA_COMP_TARGET_REF_LEVEL,
-    IDX_METADATA_PROG_LEVEL_PRESENT,
-    IDX_METADATA_PROG_LEVEL,
-    IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT,
-    IDX_METADATA_ETSI_DMXLVL_PRESENT,
-    IDX_METADATA_CENTER_MIX_LEVEL,
-    IDX_METADATA_SURROUND_MIX_LEVEL,
-    IDX_METADATA_DOLBY_SURROUND_MODE,
-    IDX_METADATA_DRC_PRESENTATION_MODE,
-    IDX_METADATA_EXT_ANC_DATA_ENABLE,
-    IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE,
-    IDX_METADATA_EXT_DOWNMIX_LEVEL_A,
-    IDX_METADATA_EXT_DOWNMIX_LEVEL_B,
-    IDX_METADATA_DMX_GAIN_ENABLE,
-    IDX_METADATA_DMX_GAIN_5,
-    IDX_METADATA_DMX_GAIN_2,
-    IDX_METADATA_LFE_DMX_ENABLE,
-    IDX_METADATA_LFE_DMX_LEVEL,
-    IDX_IN_BUFFER_INDEX_1,
-    IDX_IN_BUFFER_INDEX_2,
-    IDX_IN_BUFFER_INDEX_3,
-    IDX_BIT_RATE_MODE,
-    IDX_GRANULE_LENGTH,
-    IDX_CHANNELORDER,
-    IDX_AFTERBURNER,
-    IDX_BANDWIDTH,
-    IDX_PEAK_BITRATE,
-    IDX_HEADER_PERIOD,
-    IDX_SIGNALING_MODE,
-    IDX_TPSUBFRAMES,
-    IDX_AUDIOMUXVER,
-    IDX_PROTECTION,
-    IDX_ANCILLARY_BITRATE,
-    IDX_METADATA_MODE,
-    IDX_LAST
-};
-
-template <typename type1, typename type2, typename type3>
-auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) {
-    return (data % (1 + max - min)) + min;
-}
-
-class Codec {
-   public:
-    ~Codec() { deInitEncoder(); }
-    bool initEncoder(uint8_t **dataPtr, size_t *sizePtr);
-    void encodeFrames(const uint8_t *data, size_t size);
-    void deInitEncoder();
-
-   private:
-    template <typename type1, typename type2, typename type3>
-    void setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max,
-                     const type3 *array = nullptr);
-    void setupMetaData(uint8_t *data);
-
-    HANDLE_AACENCODER mEncoder = nullptr;
-    AACENC_MetaData mMetaData = {};
-    uint32_t mInBufferIdx_1 = 0;
-    uint32_t mInBufferIdx_2 = 0;
-    uint32_t mInBufferIdx_3 = 0;
-};
-
-void Codec::setupMetaData(uint8_t *data) {
-    uint32_t drcProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_DRC_PROFILE], 0,
-                                                             kMetaDataDrcProfilesSize - 1);
-    AACENC_METADATA_DRC_PROFILE drcProfile = kMetaDataDrcProfiles[drcProfileIndex];
-    mMetaData.drc_profile = drcProfile;
-
-    uint32_t compProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_COMP_PROFILE], 0,
-                                                              kMetaDataDrcProfilesSize - 1);
-    AACENC_METADATA_DRC_PROFILE compProfile = kMetaDataDrcProfiles[compProfileIndex];
-    mMetaData.comp_profile = compProfile;
-
-    INT drcTargetRefLevel =
-        generateNumberInRangeFromData(data[IDX_METADATA_DRC_TARGET_REF_LEVEL], 0, UINT8_MAX);
-    mMetaData.drc_TargetRefLevel = drcTargetRefLevel;
-
-    INT compTargetRefLevel =
-        generateNumberInRangeFromData(data[IDX_METADATA_COMP_TARGET_REF_LEVEL], 0, UINT8_MAX);
-    mMetaData.comp_TargetRefLevel = compTargetRefLevel;
-
-    INT isProgRefLevelPresent =
-        generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL_PRESENT], 0, 1);
-    mMetaData.prog_ref_level_present = isProgRefLevelPresent;
-
-    INT progRefLevel = generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL], 0, UINT8_MAX);
-    mMetaData.prog_ref_level = progRefLevel;
-
-    UCHAR isPCEMixdownIdxPresent =
-        generateNumberInRangeFromData(data[IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT], 0, 1);
-    mMetaData.PCE_mixdown_idx_present = isPCEMixdownIdxPresent;
-
-    UCHAR isETSIDmxLvlPresent =
-        generateNumberInRangeFromData(data[IDX_METADATA_ETSI_DMXLVL_PRESENT], 0, 1);
-    mMetaData.ETSI_DmxLvl_present = isETSIDmxLvlPresent;
-
-    SCHAR centerMixLevel = generateNumberInRangeFromData(data[IDX_METADATA_CENTER_MIX_LEVEL], 0, 7);
-    mMetaData.centerMixLevel = centerMixLevel;
-
-    SCHAR surroundMixLevel =
-        generateNumberInRangeFromData(data[IDX_METADATA_SURROUND_MIX_LEVEL], 0, 7);
-    mMetaData.surroundMixLevel = surroundMixLevel;
-
-    UCHAR dolbySurroundMode =
-        generateNumberInRangeFromData(data[IDX_METADATA_DOLBY_SURROUND_MODE], 0, 2);
-    mMetaData.dolbySurroundMode = dolbySurroundMode;
-
-    UCHAR drcPresentationMode =
-        generateNumberInRangeFromData(data[IDX_METADATA_DRC_PRESENTATION_MODE], 0, 2);
-    mMetaData.drcPresentationMode = drcPresentationMode;
-
-    UCHAR extAncDataEnable =
-        generateNumberInRangeFromData(data[IDX_METADATA_EXT_ANC_DATA_ENABLE], 0, 1);
-    mMetaData.ExtMetaData.extAncDataEnable = extAncDataEnable;
-
-    UCHAR extDownmixLevelEnable =
-        generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE], 0, 1);
-    mMetaData.ExtMetaData.extDownmixLevelEnable = extDownmixLevelEnable;
-
-    UCHAR extDownmixLevel_A =
-        generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_A], 0, 7);
-    mMetaData.ExtMetaData.extDownmixLevel_A = extDownmixLevel_A;
-
-    UCHAR extDownmixLevel_B =
-        generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_B], 0, 7);
-    mMetaData.ExtMetaData.extDownmixLevel_B = extDownmixLevel_B;
-
-    UCHAR dmxGainEnable = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_ENABLE], 0, 1);
-    mMetaData.ExtMetaData.dmxGainEnable = dmxGainEnable;
-
-    INT dmxGain5 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_5], 0, UINT8_MAX);
-    mMetaData.ExtMetaData.dmxGain5 = dmxGain5;
-
-    INT dmxGain2 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_2], 0, UINT8_MAX);
-    mMetaData.ExtMetaData.dmxGain2 = dmxGain2;
-
-    UCHAR lfeDmxEnable = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_ENABLE], 0, 1);
-    mMetaData.ExtMetaData.lfeDmxEnable = lfeDmxEnable;
-
-    UCHAR lfeDmxLevel = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_LEVEL], 0, 15);
-    mMetaData.ExtMetaData.lfeDmxLevel = lfeDmxLevel;
-}
-
-template <typename type1, typename type2, typename type3>
-void Codec::setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max,
-                        const type3 *array) {
-    auto value = 0;
-    if (array) {
-        uint32_t index = generateNumberInRangeFromData(data, min, max);
-        value = array[index];
-    } else {
-        value = generateNumberInRangeFromData(data, min, max);
-    }
-    aacEncoder_SetParam(mEncoder, aacParam, value);
-    (void)aacEncoder_GetParam(mEncoder, aacParam);
-}
-
-bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) {
-    uint8_t *data = *dataPtr;
-
-    if (AACENC_OK != aacEncOpen(&mEncoder, 0, 0)) {
-        return false;
-    }
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_MODE], AACENC_SBR_MODE, 0, kSbrModesSize - 1,
-                                          kSbrModes);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_RATIO], AACENC_SBR_RATIO, 0,
-                                          kSbrRatiosSize - 1, kSbrRatios);
-
-    setAACParam<uint8_t, size_t, AUDIO_OBJECT_TYPE>(data[IDX_AAC_AOT], AACENC_AOT, 0,
-                                                    kAudioObjectTypesSize - 1, kAudioObjectTypes);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_SAMPLE_RATE], AACENC_SAMPLERATE, 0,
-                                          kSampleRatesSize - 1, kSampleRates);
-
-    uint32_t tempValue =
-        (data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3];
-    setAACParam<uint8_t, uint32_t, uint32_t>(tempValue, AACENC_BITRATE, kMinBitRate, kMaxBitRate);
-
-    setAACParam<uint8_t, size_t, CHANNEL_MODE>(data[IDX_CHANNEL], AACENC_CHANNELMODE, 0,
-                                               kChannelModesSize - 1, kChannelModes);
-
-    setAACParam<uint8_t, size_t, TRANSPORT_TYPE>(data[IDX_IDENTIFIER], AACENC_TRANSMUX, 0,
-                                                 kIdentifiersSize - 1, kIdentifiers);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_BIT_RATE_MODE], AACENC_BITRATEMODE, 0,
-                                          kBitRateModesSize - 1, kBitRateModes);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_GRANULE_LENGTH], AACENC_GRANULE_LENGTH, 0,
-                                          kGranuleLengthsSize - 1, kGranuleLengths);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_CHANNELORDER], AACENC_CHANNELORDER, 0,
-                                          kChannelOrderSize - 1, kChannelOrder);
-
-    setAACParam<uint8_t, int32_t, int32_t>(data[IDX_AFTERBURNER], AACENC_AFTERBURNER, 0, 1);
-
-    setAACParam<uint8_t, int32_t, int32_t>(data[IDX_BANDWIDTH], AACENC_BANDWIDTH, 0, 1);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PEAK_BITRATE], AACENC_PEAK_BITRATE,
-                                             kMinBitRate, kMinBitRate);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_HEADER_PERIOD], AACENC_HEADER_PERIOD, 0,
-                                             UINT8_MAX);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_SIGNALING_MODE], AACENC_SIGNALING_MODE, 0,
-                                          kSignalingModesSize - 1, kSignalingModes);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_TPSUBFRAMES], AACENC_TPSUBFRAMES, 0,
-                                             UINT8_MAX);
-
-    setAACParam<uint8_t, size_t, int32_t>(data[IDX_AUDIOMUXVER], AACENC_AUDIOMUXVER, 0,
-                                          kAudioMuxVerSize - 1, kAudioMuxVer);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PROTECTION], AACENC_PROTECTION, 0, 1);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_ANCILLARY_BITRATE], AACENC_ANCILLARY_BITRATE,
-                                             0, kMaxBitRate);
-
-    setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_METADATA_MODE], AACENC_METADATA_MODE, 0, 3);
-
-    AACENC_InfoStruct encInfo;
-    aacEncInfo(mEncoder, &encInfo);
-
-    mInBufferIdx_1 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_1], 0, kMaxBuffers - 1);
-    mInBufferIdx_2 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_2], 0, kMaxBuffers - 1);
-    mInBufferIdx_3 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_3], 0, kMaxBuffers - 1);
-
-    setupMetaData(data);
-
-    // Not re-using the data which was used for configuration for encoding
-    *dataPtr += IDX_LAST;
-    *sizePtr -= IDX_LAST;
-
-    return true;
-}
-
-static void deleteBuffers(uint8_t **buffers, size_t size) {
-    for (size_t n = 0; n < size; ++n) {
-        delete[] buffers[n];
-    }
-    delete[] buffers;
-}
-
-void Codec::encodeFrames(const uint8_t *data, size_t size) {
-    uint8_t *audioData = (uint8_t *)data;
-    uint8_t *ancData = (uint8_t *)data;
-    size_t audioSize = size;
-    size_t ancSize = size;
-
-    while ((audioSize > 0) && (ancSize > 0)) {
-        AACENC_InArgs inargs;
-        memset(&inargs, 0, sizeof(inargs));
-        inargs.numInSamples = audioSize / sizeof(int16_t);
-        inargs.numAncBytes = ancSize;
-
-        void *buffers[] = {(void *)audioData, (void *)ancData, &mMetaData};
-        INT bufferIds[] = {IN_AUDIO_DATA, IN_ANCILLRY_DATA, IN_METADATA_SETUP};
-        INT bufferSizes[] = {static_cast<INT>(audioSize), static_cast<INT>(ancSize),
-                             static_cast<INT>(sizeof(mMetaData))};
-        INT bufferElSizes[] = {sizeof(int16_t), sizeof(UCHAR), sizeof(AACENC_MetaData)};
-
-        void *inBuffer[kMaxBuffers] = {};
-        INT inBufferIds[kMaxBuffers] = {};
-        INT inBufferSize[kMaxBuffers] = {};
-        INT inBufferElSize[kMaxBuffers] = {};
-        for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) {
-            uint32_t Idxs[] = {mInBufferIdx_1, mInBufferIdx_2, mInBufferIdx_3};
-            inBuffer[buffer] = buffers[Idxs[buffer]];
-            inBufferIds[buffer] = bufferIds[Idxs[buffer]];
-            inBufferSize[buffer] = bufferSizes[Idxs[buffer]];
-            inBufferElSize[buffer] = bufferElSizes[Idxs[buffer]];
-        }
-
-        AACENC_BufDesc inBufDesc;
-        inBufDesc.numBufs = kMaxBuffers;
-        inBufDesc.bufs = (void **)&inBuffer;
-        inBufDesc.bufferIdentifiers = inBufferIds;
-        inBufDesc.bufSizes = inBufferSize;
-        inBufDesc.bufElSizes = inBufferElSize;
-
-        uint8_t **outPtrRef = new uint8_t *[kMaxBuffers];
-        for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) {
-            outPtrRef[buffer] = new uint8_t[kMaxOutputBufferSize];
-        }
-
-        void *outBuffer[kMaxBuffers];
-        INT outBufferIds[kMaxBuffers];
-        INT outBufferSize[kMaxBuffers];
-        INT outBufferElSize[kMaxBuffers];
-
-        for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) {
-            outBuffer[buffer] = outPtrRef[buffer];
-            outBufferIds[buffer] = OUT_BITSTREAM_DATA;
-            outBufferSize[buffer] = (INT)kMaxOutputBufferSize;
-            outBufferElSize[buffer] = sizeof(UCHAR);
-        }
-
-        AACENC_BufDesc outBufDesc;
-        outBufDesc.numBufs = kMaxBuffers;
-        outBufDesc.bufs = (void **)&outBuffer;
-        outBufDesc.bufferIdentifiers = outBufferIds;
-        outBufDesc.bufSizes = outBufferSize;
-        outBufDesc.bufElSizes = outBufferElSize;
-
-        AACENC_OutArgs outargs = {};
-        aacEncEncode(mEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs);
-
-        if (outargs.numOutBytes == 0) {
-            if (audioSize > 0) {
-                ++audioData;
-                --audioSize;
-            }
-            if (ancSize > 0) {
-                ++ancData;
-                --ancSize;
-            }
-        } else {
-            size_t audioConsumed = outargs.numInSamples * sizeof(int16_t);
-            audioData += audioConsumed;
-            audioSize -= audioConsumed;
-
-            size_t ancConsumed = outargs.numAncBytes;
-            ancData += ancConsumed;
-            ancSize -= ancConsumed;
-        }
-        deleteBuffers(outPtrRef, kMaxBuffers);
-
-        // break out of loop if only metadata was sent in all the input buffers
-        // as sending it multiple times in a loop is redundant.
-        if ((mInBufferIdx_1 == kMaxBuffers - 1) && (mInBufferIdx_2 == kMaxBuffers - 1) &&
-            (mInBufferIdx_3 == kMaxBuffers - 1)) {
-            break;
-        }
-    }
-}
-
-void Codec::deInitEncoder() { aacEncClose(&mEncoder); }
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    if (size < IDX_LAST) {
-        return 0;
-    }
-    Codec encoder;
-    if (encoder.initEncoder(const_cast<uint8_t **>(&data), &size)) {
-        encoder.encodeFrames(data, size);
-    }
-    return 0;
-}
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
index d7928c0..56f4ec1 100644
--- a/libAACdec/include/aacdecoder_lib.h
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -1032,7 +1032,7 @@
  * \param self          AAC decoder handle.
  * \param pTimeData     Pointer to external output buffer where the decoded PCM
  * samples will be stored into.
- * \param timeDataSize  Size of external output buffer in PCM samples.
+ * \param timeDataSize  Size of external output buffer.
  * \param flags         Bit field with flags for the decoder: \n
  *                      (flags & AACDEC_CONCEAL) == 1: Do concealment. \n
  *                      (flags & AACDEC_FLUSH) == 2: Discard input data. Flush
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index d5f0cea..c18e5e9 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -494,75 +494,6 @@
   return error;
 }
 
-static INT findElementInstanceTag(
-    INT elementTag, MP4_ELEMENT_ID elementId,
-    CAacDecoderChannelInfo **pAacDecoderChannelInfo, INT nChannels,
-    MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
-  int el, chCnt = 0;
-
-  for (el = 0; el < nElements; el++) {
-    switch (pElementIdTab[el]) {
-      case ID_CPE:
-      case ID_SCE:
-      case ID_LFE:
-        if ((elementTag == pAacDecoderChannelInfo[chCnt]->ElementInstanceTag) &&
-            (elementId == pElementIdTab[el])) {
-          return 1; /* element instance tag found */
-        }
-        chCnt += (pElementIdTab[el] == ID_CPE) ? 2 : 1;
-        break;
-      default:
-        break;
-    }
-    if (chCnt >= nChannels) break;
-    if (pElementIdTab[el] == ID_END) break;
-  }
-
-  return 0; /* element instance tag not found */
-}
-
-static INT validateElementInstanceTags(
-    CProgramConfig *pce, CAacDecoderChannelInfo **pAacDecoderChannelInfo,
-    INT nChannels, MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
-  if (nChannels >= pce->NumChannels) {
-    for (int el = 0; el < pce->NumFrontChannelElements; el++) {
-      if (!findElementInstanceTag(pce->FrontElementTagSelect[el],
-                                  pce->FrontElementIsCpe[el] ? ID_CPE : ID_SCE,
-                                  pAacDecoderChannelInfo, nChannels,
-                                  pElementIdTab, nElements)) {
-        return 0; /* element instance tag not in raw_data_block() */
-      }
-    }
-    for (int el = 0; el < pce->NumSideChannelElements; el++) {
-      if (!findElementInstanceTag(pce->SideElementTagSelect[el],
-                                  pce->SideElementIsCpe[el] ? ID_CPE : ID_SCE,
-                                  pAacDecoderChannelInfo, nChannels,
-                                  pElementIdTab, nElements)) {
-        return 0; /* element instance tag not in raw_data_block() */
-      }
-    }
-    for (int el = 0; el < pce->NumBackChannelElements; el++) {
-      if (!findElementInstanceTag(pce->BackElementTagSelect[el],
-                                  pce->BackElementIsCpe[el] ? ID_CPE : ID_SCE,
-                                  pAacDecoderChannelInfo, nChannels,
-                                  pElementIdTab, nElements)) {
-        return 0; /* element instance tag not in raw_data_block() */
-      }
-    }
-    for (int el = 0; el < pce->NumLfeChannelElements; el++) {
-      if (!findElementInstanceTag(pce->LfeElementTagSelect[el], ID_LFE,
-                                  pAacDecoderChannelInfo, nChannels,
-                                  pElementIdTab, nElements)) {
-        return 0; /* element instance tag not in raw_data_block() */
-      }
-    }
-  } else {
-    return 0; /* too less decoded audio channels */
-  }
-
-  return 1; /* all element instance tags found in raw_data_block() */
-}
-
 /*!
   \brief Read Program Config Element
 
@@ -1486,7 +1417,11 @@
                                     const CSAudioSpecificConfig *asc,
                                     UINT flags, UINT *elFlags, int streamIndex,
                                     int elementOffset) {
-  FDKmemcpy(self->elFlags, elFlags, sizeof(self->elFlags));
+  {
+    FDKmemcpy(
+        self->elFlags, elFlags,
+        sizeof(*elFlags) * (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1));
+  }
 
   self->flags[streamIndex] = flags;
 }
@@ -1589,14 +1524,8 @@
   INT flushChannels = 0;
 
   UINT flags;
-  /* elFlags[(3*MAX_CHANNELS + (MAX_CHANNELS)/2 + 4 * (MAX_TRACKS) + 1]
-     where MAX_CHANNELS is (8*2) and MAX_TRACKS is 1 */
   UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)];
 
-  UCHAR sbrEnabled = self->sbrEnabled;
-  UCHAR sbrEnabledPrev = self->sbrEnabledPrev;
-  UCHAR mpsEnableCurr = self->mpsEnableCurr;
-
   if (!self) return AAC_DEC_INVALID_HANDLE;
 
   UCHAR downscaleFactor = self->downscaleFactor;
@@ -1780,7 +1709,7 @@
             asc->m_sc.m_usacConfig.m_usacNumElements;
       }
 
-      mpsEnableCurr = 0;
+      self->mpsEnableCurr = 0;
       for (int _el = 0;
            _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
            _el++) {
@@ -1800,7 +1729,7 @@
           self->usacStereoConfigIndex[el] =
               asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex;
           if (self->elements[el] == ID_USAC_CPE) {
-            mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
+            self->mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
           }
         }
 
@@ -1936,7 +1865,7 @@
       self->useLdQmfTimeAlign =
           asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
     }
-    if (sbrEnabled != asc->m_sbrPresentFlag) {
+    if (self->sbrEnabled != asc->m_sbrPresentFlag) {
       ascChanged = 1;
     }
   }
@@ -1952,13 +1881,13 @@
   flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
   flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
   if (asc->m_sbrPresentFlag) {
-    sbrEnabled = 1;
-    sbrEnabledPrev = 1;
+    self->sbrEnabled = 1;
+    self->sbrEnabledPrev = 1;
   } else {
-    sbrEnabled = 0;
-    sbrEnabledPrev = 0;
+    self->sbrEnabled = 0;
+    self->sbrEnabledPrev = 0;
   }
-  if (sbrEnabled && asc->m_extensionSamplingFrequency) {
+  if (self->sbrEnabled && asc->m_extensionSamplingFrequency) {
     if (downscaleFactor != 1 && (downscaleFactor)&1) {
       return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale
                                                   factor */
@@ -1985,7 +1914,7 @@
   flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
 
   if (asc->m_aot == AOT_ER_AAC_ELD) {
-    mpsEnableCurr = 0;
+    self->mpsEnableCurr = 0;
     flags |= AC_ELD;
     flags |= (asc->m_sbrPresentFlag)
                  ? AC_SBR_PRESENT
@@ -1996,7 +1925,7 @@
                  ? AC_MPS_PRESENT
                  : 0;
     if (self->mpsApplicable) {
-      mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
+      self->mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
     }
   }
   flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
@@ -2077,7 +2006,7 @@
   /* set AC_USAC_SCFGI3 globally if any usac element uses */
   switch (asc->m_aot) {
     case AOT_USAC:
-      if (sbrEnabled) {
+      if (self->sbrEnabled) {
         for (int _el = 0;
              _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
              _el++) {
@@ -2114,7 +2043,7 @@
     */
     switch (asc->m_aot) {
       case AOT_USAC:
-        if (sbrEnabled) {
+        if (self->sbrEnabled) {
           const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32};
 
           FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0);
@@ -2142,11 +2071,11 @@
         }
         break;
       case AOT_ER_AAC_ELD:
-        if (mpsEnableCurr &&
+        if (self->mpsEnableCurr &&
             asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
-          SAC_INPUT_CONFIG sac_interface = (sbrEnabled && self->hSbrDecoder)
-                                               ? SAC_INTERFACE_QMF
-                                               : SAC_INTERFACE_TIME;
+          SAC_INPUT_CONFIG sac_interface =
+              (self->sbrEnabled && self->hSbrDecoder) ? SAC_INTERFACE_QMF
+                                                      : SAC_INTERFACE_TIME;
           mpegSurroundDecoder_ConfigureQmfDomain(
               (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface,
               (UINT)self->streamInfo.aacSampleRate, asc->m_aot);
@@ -2501,9 +2430,6 @@
 
   CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
                           elementOffset);
-  self->sbrEnabled = sbrEnabled;
-  self->sbrEnabledPrev = sbrEnabledPrev;
-  self->mpsEnableCurr = mpsEnableCurr;
 
   /* Update externally visible copy of flags */
   self->streamInfo.flags = self->flags[0];
@@ -3042,24 +2968,6 @@
 
   } /* while ( (type != ID_END) ... ) */
 
-  if (!(self->flags[streamIndex] &
-        (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_BSAC | AC_LD | AC_ELD | AC_ER |
-         AC_SCALABLE)) &&
-      (self->streamInfo.channelConfig == 0) && pce->isValid &&
-      (ErrorStatus == AAC_DEC_OK) && self->frameOK &&
-      !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
-    /* Check whether all PCE listed element instance tags are present in
-     * raw_data_block() */
-    if (!validateElementInstanceTags(
-            &self->pce, self->pAacDecoderChannelInfo, aacChannels,
-            channel_elements,
-            fMin(channel_element_count, (int)(sizeof(channel_elements) /
-                                              sizeof(*channel_elements))))) {
-      ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
-      self->frameOK = 0;
-    }
-  }
-
   if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
     /* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are
      * byteAligned with respect to the first bit */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index 0c83191..9d36d10 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -1626,11 +1626,6 @@
         /* set params */
         sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY,
                             self->sbrParams.bsDelay);
-        sbrDecoder_SetParam(
-            self->hSbrDecoder, SBR_FLUSH_DATA,
-            (flags & AACDEC_FLUSH) |
-                ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
-                                                                  : 0));
 
         sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
 
diff --git a/libAACdec/src/rvlc.cpp b/libAACdec/src/rvlc.cpp
index 0b80364..b7a9be1 100644
--- a/libAACdec/src/rvlc.cpp
+++ b/libAACdec/src/rvlc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -628,7 +628,7 @@
 
   SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
   SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
-  UCHAR escEscCnt = pRvlc->numDecodedEscapeWordsEsc;
+  UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc);
   UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd);
 
   pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd);
@@ -636,7 +636,7 @@
 
   *pEscBwdCnt = 0;
   pRvlc->direction = BWD;
-  pScfEsc += escEscCnt - 1; /* set pScfEsc to last entry */
+  pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */
   pRvlc->firstScf = 0;
   pRvlc->firstNrg = 0;
   pRvlc->firstIs = 0;
@@ -651,7 +651,7 @@
     }
     dpcm -= TABLE_OFFSET;
     if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
-      if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
+      if (pRvlc->length_of_rvlc_escapes) {
         pRvlc->conceal_min = bnds;
         return;
       } else {
@@ -694,7 +694,7 @@
           }
           dpcm -= TABLE_OFFSET;
           if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
-            if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
+            if (pRvlc->length_of_rvlc_escapes) {
               pScfBwd[bnds] = position;
               pRvlc->conceal_min = fMax(0, bnds - offset);
               return;
@@ -731,8 +731,7 @@
             }
             dpcm -= TABLE_OFFSET;
             if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
-              if ((pRvlc->length_of_rvlc_escapes) ||
-                  (*pEscBwdCnt >= escEscCnt)) {
+              if (pRvlc->length_of_rvlc_escapes) {
                 pScfBwd[bnds] = noisenrg;
                 pRvlc->conceal_min = fMax(0, bnds - offset);
                 return;
@@ -763,7 +762,7 @@
           }
           dpcm -= TABLE_OFFSET;
           if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
-            if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
+            if (pRvlc->length_of_rvlc_escapes) {
               pScfBwd[bnds] = factor;
               pRvlc->conceal_min = fMax(0, bnds - offset);
               return;
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index ca1a6a2..a8dadc0 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -719,7 +719,7 @@
   UCHAR *pold_T0_frac = &acelp_mem->old_T0_frac;
 
   if ((int)*pold_T0 >= PIT_MAX) {
-    *pold_T0 = (USHORT)(PIT_MAX - 5);
+    *pold_T0 = (UCHAR)(PIT_MAX - 5);
   }
   *pT0 = (int)*pold_T0;
   *pT0_frac = (int)*pold_T0_frac;
diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h
index f0f23b4..71f7556 100644
--- a/libAACenc/include/aacenc_lib.h
+++ b/libAACenc/include/aacenc_lib.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -1643,7 +1643,7 @@
  *
  * \return
  *          - AACENC_OK, on succes.
- *          - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure.
+ *          - AACENC_INIT_ERROR, on failure.
  */
 AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder,
                         AACENC_InfoStruct *pInfo);
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index c11db27..caa62c5 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -2521,11 +2521,6 @@
                         AACENC_InfoStruct *pInfo) {
   AACENC_ERROR err = AACENC_OK;
 
-  if ((hAacEncoder == NULL) || (pInfo == NULL)) {
-    err = AACENC_INVALID_HANDLE;
-    goto bail;
-  }
-
   FDKmemclear(pInfo, sizeof(AACENC_InfoStruct));
   pInfo->confSize = 64; /* pre-initialize */
 
diff --git a/libDRCdec/src/drcDec_reader.cpp b/libDRCdec/src/drcDec_reader.cpp
index b080f50..b3ec187 100644
--- a/libDRCdec/src/drcDec_reader.cpp
+++ b/libDRCdec/src/drcDec_reader.cpp
@@ -917,7 +917,7 @@
       firFilterOrder;
   int uniqueEqSubbandGainsCount, eqSubbandGainRepresentation,
       eqSubbandGainCount;
-  int eqSubbandGainFormat;
+  EQ_SUBBAND_GAIN_FORMAT eqSubbandGainFormat;
 
   eqDelayMaxPresent = FDKreadBits(hBs, 1);
   if (eqDelayMaxPresent) {
@@ -958,7 +958,7 @@
   uniqueEqSubbandGainsCount = FDKreadBits(hBs, 6);
   if (uniqueEqSubbandGainsCount > 0) {
     eqSubbandGainRepresentation = FDKreadBits(hBs, 1);
-    eqSubbandGainFormat = FDKreadBits(hBs, 4);
+    eqSubbandGainFormat = (EQ_SUBBAND_GAIN_FORMAT)FDKreadBits(hBs, 4);
     switch (eqSubbandGainFormat) {
       case GF_QMF32:
         eqSubbandGainCount = 32;
diff --git a/libFDK/include/nlc_dec.h b/libFDK/include/nlc_dec.h
index aded569..cca97f1 100644
--- a/libFDK/include/nlc_dec.h
+++ b/libFDK/include/nlc_dec.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -159,6 +159,9 @@
 #ifndef HUFFDEC_PARAMS
 #define HUFFDEC_PARMS
 
+#define PAIR_SHIFT 4
+#define PAIR_MASK 0xf
+
 #define MAX_ENTRIES 168
 #define HANDLE_HUFF_NODE const SHORT(*)[MAX_ENTRIES][2]
 
diff --git a/libFDK/src/autocorr2nd.cpp b/libFDK/src/autocorr2nd.cpp
index 8c5673c..718a555 100644
--- a/libFDK/src/autocorr2nd.cpp
+++ b/libFDK/src/autocorr2nd.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -102,6 +102,11 @@
 
 #include "autocorr2nd.h"
 
+/*  If the accumulator does not provide enough overflow bits,
+    products have to be shifted down in the autocorrelation below. */
+#define SHIFT_FACTOR (5)
+#define SHIFT >> (SHIFT_FACTOR)
+
 /*!
  *
  * \brief Calculate second order autocorrelation using 2 accumulators
@@ -121,49 +126,45 @@
 
   const FIXP_DBL *realBuf = reBuffer;
 
-  const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)(len / 2)), 1);
   /*
     r11r,r22r
     r01r,r12r
     r02r
   */
   pReBuf = realBuf - 2;
-  accu5 =
-      ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >>
-       len_scale);
+  accu5 = ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3]))
+               SHIFT);
   pReBuf++;
 
   /* len must be even */
-  accu1 = fPow2Div2(pReBuf[0]) >> len_scale;
-  accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) >> len_scale;
+  accu1 = fPow2Div2(pReBuf[0]) SHIFT;
+  accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) SHIFT;
   pReBuf++;
 
   for (j = (len - 2) >> 1; j != 0; j--, pReBuf += 2) {
-    accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) >> len_scale);
+    accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) SHIFT);
 
-    accu3 +=
-        ((fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pReBuf[1], pReBuf[2])) >>
-         len_scale);
+    accu3 += ((fMultDiv2(pReBuf[0], pReBuf[1]) +
+               fMultDiv2(pReBuf[1], pReBuf[2])) SHIFT);
 
-    accu5 +=
-        ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >>
-         len_scale);
+    accu5 += ((fMultDiv2(pReBuf[0], pReBuf[2]) +
+               fMultDiv2(pReBuf[1], pReBuf[3])) SHIFT);
   }
 
-  accu2 = (fPow2Div2(realBuf[-2]) >> len_scale);
+  accu2 = (fPow2Div2(realBuf[-2]) SHIFT);
   accu2 += accu1;
 
-  accu1 += (fPow2Div2(realBuf[len - 2]) >> len_scale);
+  accu1 += (fPow2Div2(realBuf[len - 2]) SHIFT);
 
-  accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) >> len_scale);
+  accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) SHIFT);
   accu4 += accu3;
 
-  accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) >> len_scale);
+  accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) SHIFT);
 
   mScale = CntLeadingZeros(
                (accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5))) -
            1;
-  autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/
+  autoCorrScaling = mScale - 1 - SHIFT_FACTOR; /* -1 because of fMultDiv2*/
 
   /* Scale to common scale factor */
   ac->r11r = accu1 << mScale;
@@ -189,7 +190,7 @@
     const FIXP_DBL *imBuffer, /*!< Pointer to imag part of input samples */
     const int len /*!< Number of input samples (should be smaller than 128) */
 ) {
-  int j, autoCorrScaling, mScale;
+  int j, autoCorrScaling, mScale, len_scale;
 
   FIXP_DBL accu0, accu1, accu2, accu3, accu4, accu5, accu6, accu7, accu8;
 
@@ -198,7 +199,7 @@
   const FIXP_DBL *realBuf = reBuffer;
   const FIXP_DBL *imagBuf = imBuffer;
 
-  const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)len), 1);
+  (len > 64) ? (len_scale = 6) : (len_scale = 5);
   /*
     r00r,
     r11r,r22r
diff --git a/libFDK/src/nlc_dec.cpp b/libFDK/src/nlc_dec.cpp
index 3733d98..6e98ce0 100644
--- a/libFDK/src/nlc_dec.cpp
+++ b/libFDK/src/nlc_dec.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -568,12 +568,12 @@
 static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1,
                            SCHAR* out_data_2, DATA_TYPE data_type,
                            DIFF_TYPE diff_type_1, DIFF_TYPE diff_type_2,
-                           int num_val, PAIRING* pairing_scheme, int ldMode) {
+                           int num_val, CODING_SCHEME* cdg_scheme, int ldMode) {
   ERROR_t err = HUFFDEC_OK;
-  CODING_SCHEME coding_scheme = HUFF_1D;
   DIFF_TYPE diff_type;
 
   int i = 0;
+  ULONG data = 0;
 
   SCHAR pair_vec[28][2];
 
@@ -596,13 +596,15 @@
   int hufYY;
 
   /* Coding scheme */
-  coding_scheme = (CODING_SCHEME)FDKreadBits(strm, 1);
+  data = FDKreadBits(strm, 1);
+  *cdg_scheme = (CODING_SCHEME)(data << PAIR_SHIFT);
 
-  if (coding_scheme == HUFF_2D) {
+  if (*cdg_scheme >> PAIR_SHIFT == HUFF_2D) {
     if ((out_data_1 != NULL) && (out_data_2 != NULL) && (ldMode == 0)) {
-      *pairing_scheme = (PAIRING)FDKreadBits(strm, 1);
+      data = FDKreadBits(strm, 1);
+      *cdg_scheme = (CODING_SCHEME)(*cdg_scheme | data);
     } else {
-      *pairing_scheme = FREQ_PAIR;
+      *cdg_scheme = (CODING_SCHEME)(*cdg_scheme | FREQ_PAIR);
     }
   }
 
@@ -611,7 +613,7 @@
     hufYY2 = diff_type_2;
   }
 
-  switch (coding_scheme) {
+  switch (*cdg_scheme >> PAIR_SHIFT) {
     case HUFF_1D:
       p0_flag[0] = (diff_type_1 == DIFF_FREQ);
       p0_flag[1] = (diff_type_2 == DIFF_FREQ);
@@ -632,7 +634,7 @@
 
     case HUFF_2D:
 
-      switch (*pairing_scheme) {
+      switch (*cdg_scheme & PAIR_MASK) {
         case FREQ_PAIR:
 
           if (out_data_1 != NULL) {
@@ -841,7 +843,7 @@
   SCHAR* pDataVec[2] = {NULL, NULL};
 
   DIFF_TYPE diff_type[2] = {DIFF_FREQ, DIFF_FREQ};
-  PAIRING pairing = FREQ_PAIR;
+  CODING_SCHEME cdg_scheme = HUFF_1D;
   DIRECTION direction = BACKWARDS;
 
   switch (data_type) {
@@ -957,7 +959,7 @@
     }
     /* Huffman decoding */
     err = huff_decode(strm, pDataVec[0], pDataVec[1], data_type, diff_type[0],
-                      diff_type[1], dataBands, &pairing,
+                      diff_type[1], dataBands, &cdg_scheme,
                       (DECODER == SAOC_DECODER));
     if (err != HUFFDEC_OK) {
       return HUFFDEC_NOTOK;
@@ -984,8 +986,8 @@
         }
       }
 
-      mixed_time_pair =
-          (diff_type[0] != diff_type[1]) && (pairing == TIME_PAIR);
+      mixed_time_pair = (diff_type[0] != diff_type[1]) &&
+                        ((cdg_scheme & PAIR_MASK) == TIME_PAIR);
 
       if (direction == BACKWARDS) {
         if (diff_type[0] == DIFF_FREQ) {
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index 8f77017..e46cb32 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1694,7 +1694,8 @@
                                            const AUDIO_OBJECT_TYPE aot) {
   TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
 
-  UINT usacExtElementType = escapedValue(hBs, 4, 8, 16);
+  USAC_EXT_ELEMENT_TYPE usacExtElementType =
+      (USAC_EXT_ELEMENT_TYPE)escapedValue(hBs, 4, 8, 16);
 
   /* recurve extension elements which are invalid for USAC */
   if (aot == AOT_USAC) {
@@ -1711,6 +1712,7 @@
     }
   }
 
+  extElement->usacExtElementType = usacExtElementType;
   int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16);
   extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength;
   INT bsAnchor;
@@ -1744,10 +1746,8 @@
       }
     } break;
     default:
-      usacExtElementType = ID_EXT_ELE_UNKNOWN;
       break;
   }
-  extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType;
 
   /* Adjust bit stream position. This is required because of byte alignment and
    * unhandled extensions. */
@@ -1776,7 +1776,7 @@
   TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
 
   int numConfigExtensions;
-  UINT usacConfigExtType;
+  CONFIG_EXT_ID usacConfigExtType;
   int usacConfigExtLength;
   int loudnessInfoSetIndex =
       -1; /* index of loudnessInfoSet config extension. -1 if not contained. */
@@ -1787,7 +1787,7 @@
   for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) {
     INT nbits;
     int loudnessInfoSetConfigExtensionPosition = FDKgetValidBits(hBs);
-    usacConfigExtType = escapedValue(hBs, 4, 8, 16);
+    usacConfigExtType = (CONFIG_EXT_ID)escapedValue(hBs, 4, 8, 16);
     usacConfigExtLength = (int)escapedValue(hBs, 4, 8, 16);
 
     /* Start bit position of config extension */
diff --git a/libMpegTPDec/src/tpdec_latm.cpp b/libMpegTPDec/src/tpdec_latm.cpp
index c32be54..3b71db8 100644
--- a/libMpegTPDec/src/tpdec_latm.cpp
+++ b/libMpegTPDec/src/tpdec_latm.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -591,18 +591,6 @@
   return (ErrorStatus);
 }
 
-static int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) {
-  int len = 0, tmp = 255;
-  int validBytes = (int)FDKgetValidBits(bs) >> 3;
-
-  while (tmp == 255 && validBytes-- > 0) {
-    tmp = (int)FDKreadBits(bs, 8);
-    len += tmp;
-  }
-
-  return ((tmp == 255) ? -1 : (len << 3));
-}
-
 TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs,
                                                     CLatmDemux *pLatmDemux) {
   TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
@@ -614,17 +602,11 @@
       FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER);
       for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) {
         LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay];
-        int auChunkLengthInfo = 0;
 
         switch (p_linfo->m_frameLengthType) {
           case 0:
-            auChunkLengthInfo = CLatmDemux_ReadAuChunkLengthInfo(bs);
-            if (auChunkLengthInfo >= 0) {
-              p_linfo->m_frameLengthInBits = (UINT)auChunkLengthInfo;
-              totalPayloadBits += p_linfo->m_frameLengthInBits;
-            } else {
-              return TRANSPORTDEC_PARSE_ERROR;
-            }
+            p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs);
+            totalPayloadBits += p_linfo->m_frameLengthInBits;
             break;
           case 3:
           case 5:
@@ -645,6 +627,23 @@
   return (ErrorStatus);
 }
 
+int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) {
+  UCHAR endFlag;
+  int len = 0;
+
+  do {
+    UCHAR tmp = (UCHAR)FDKreadBits(bs, 8);
+    endFlag = (tmp < 255);
+
+    len += tmp;
+
+  } while (endFlag == 0);
+
+  len <<= 3; /* convert from bytes to bits */
+
+  return len;
+}
+
 UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog,
                                      const UINT layer) {
   UINT nFrameLenBits = 0;
diff --git a/libMpegTPDec/src/tpdec_latm.h b/libMpegTPDec/src/tpdec_latm.h
index 8b8c971..6af553d 100644
--- a/libMpegTPDec/src/tpdec_latm.h
+++ b/libMpegTPDec/src/tpdec_latm.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -151,6 +151,8 @@
                                   AudioPreRoll */
 } CLatmDemux;
 
+int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs);
+
 TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs,
                                    CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt,
                                    CSTpCallBacks *pTpDecCallbacks,
diff --git a/libPCMutils/src/pcmdmx_lib.cpp b/libPCMutils/src/pcmdmx_lib.cpp
index fca12ce..2070dbc 100644
--- a/libPCMutils/src/pcmdmx_lib.cpp
+++ b/libPCMutils/src/pcmdmx_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -494,40 +494,13 @@
   return plainChMode;
 }
 
-/** Validates the channel indices of all channels present in the bitstream.
- * The channel indices have to be consecutive and unique for each audio channel
- *type.
- * @param [in] The total number of channels of the given configuration.
- * @param [in] The total number of channels of the current audio channel type of
- *the given configuration.
- * @param [in] Audio channel type to be examined.
- * @param [in] Array holding the corresponding channel types for each channel.
- * @param [in] Array holding the corresponding channel type indices for each
- *channel.
- * @returns Returns 1 on success, returns 0 on error.
- **/
-static UINT validateIndices(UINT numChannels, UINT numChannelsPlaneAndGrp,
-                            AUDIO_CHANNEL_TYPE aChType,
-                            const AUDIO_CHANNEL_TYPE channelType[],
-                            const UCHAR channelIndices[]) {
-  for (UINT reqValue = 0; reqValue < numChannelsPlaneAndGrp; reqValue++) {
-    int found = FALSE;
-    for (UINT i = 0; i < numChannels; i++) {
-      if (channelType[i] == aChType) {
-        if (channelIndices[i] == reqValue) {
-          if (found == TRUE) {
-            return 0; /* Found channel index a second time */
-          } else {
-            found = TRUE; /* Found channel index */
-          }
-        }
-      }
-    }
-    if (found == FALSE) {
-      return 0; /* Did not find channel index */
-    }
+static inline UINT getIdxSum(UCHAR numCh) {
+  UINT result = 0;
+  int i;
+  for (i = 1; i < numCh; i += 1) {
+    result += i;
   }
-  return 1; /* Successfully validated channel indices */
+  return result;
 }
 
 /** Evaluate a given channel configuration and extract a packed channel mode. In
@@ -550,6 +523,7 @@
     UCHAR offsetTable[(8)],                 /* out */
     PCM_DMX_CHANNEL_MODE *chMode            /* out */
 ) {
+  UINT idxSum[(3)][(4)];
   UCHAR numCh[(3)][(4)];
   UCHAR mapped[(8)];
   PCM_DMX_SPEAKER_POSITION spkrPos[(8)];
@@ -564,6 +538,7 @@
   FDK_ASSERT(chMode != NULL);
 
   /* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */
+  FDKmemclear(idxSum, (3) * (4) * sizeof(UINT));
   FDKmemclear(numCh, (3) * (4) * sizeof(UCHAR));
   FDKmemclear(mapped, (8) * sizeof(UCHAR));
   FDKmemclear(spkrPos, (8) * sizeof(PCM_DMX_SPEAKER_POSITION));
@@ -577,22 +552,19 @@
         (channelType[ch] & 0x0F) - 1,
         0); /* Assign all undefined channels (ACT_NONE) to front channels. */
     numCh[channelType[ch] >> 4][chGrp] += 1;
+    idxSum[channelType[ch] >> 4][chGrp] += channelIndices[ch];
   }
-
-  {
+  if (numChannels > TWO_CHANNEL) {
     int chGrp;
     /* Sanity check on the indices */
     for (chGrp = 0; chGrp < (4); chGrp += 1) {
       int plane;
       for (plane = 0; plane < (3); plane += 1) {
-        if (numCh[plane][chGrp] == 0) continue;
-        AUDIO_CHANNEL_TYPE aChType =
-            (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF));
-        if (!validateIndices(numChannels, numCh[plane][chGrp], aChType,
-                             channelType, channelIndices)) {
+        if (idxSum[plane][chGrp] != getIdxSum(numCh[plane][chGrp])) {
           unsigned idxCnt = 0;
           for (ch = 0; ch < numChannels; ch += 1) {
-            if (channelType[ch] == aChType) {
+            if (channelType[ch] ==
+                (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF))) {
               channelIndices[ch] = idxCnt++;
             }
           }
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
index 25b3d9e..4485ccf 100644
--- a/libSACdec/src/sac_bitdec.cpp
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -488,17 +488,12 @@
   pSpatialSpecificConfig->freqRes =
       (SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes];
 
-  {
-    UINT treeConfig = FDKreadBits(bitstream, 4);
+  pSpatialSpecificConfig->treeConfig =
+      (SPATIALDEC_TREE_CONFIG)FDKreadBits(bitstream, 4);
 
-    switch (treeConfig) {
-      case SPATIALDEC_MODE_RSVD7:
-        pSpatialSpecificConfig->treeConfig = (SPATIALDEC_TREE_CONFIG)treeConfig;
-        break;
-      default:
-        err = MPS_UNSUPPORTED_CONFIG;
-        goto bail;
-    }
+  if (pSpatialSpecificConfig->treeConfig != SPATIALDEC_MODE_RSVD7) {
+    err = MPS_UNSUPPORTED_CONFIG;
+    goto bail;
   }
 
   {
diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp
index 33a1647..22091a9 100644
--- a/libSACdec/src/sac_process.cpp
+++ b/libSACdec/src/sac_process.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -517,11 +517,12 @@
       maxVal = fAbs(iReal0) | fAbs(iImag0);
       maxVal |= fAbs(iReal1);
 
-      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
+      s = fMax(CntLeadingZeros(maxVal) - 1, 0);
+      s = fMin(s, scale_param_m2);
 
-      mReal0 = scaleValue(iReal0, s);
-      mImag0 = scaleValue(iImag0, s);
-      mReal1 = scaleValue(iReal1, s);
+      mReal0 = iReal0 << s;
+      mImag0 = iImag0 << s;
+      mReal1 = iReal1 << s;
 
       s = scale_param_m2 - s;
 
@@ -561,11 +562,12 @@
       maxVal = fAbs(iReal0) | fAbs(iImag0);
       maxVal |= fAbs(iReal1);
 
-      s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
+      s = fMax(CntLeadingZeros(maxVal) - 1, 0);
+      s = fMin(s, scale_param_m2);
 
-      mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
-      mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
-      mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
+      mReal0 = FX_DBL2FX_SGL(iReal0 << s);
+      mImag0 = FX_DBL2FX_SGL(iImag0 << s);
+      mReal1 = FX_DBL2FX_SGL(iReal1 << s);
 
       s = scale_param_m2 - s;
 
diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp
index 72f4e58..272d009 100644
--- a/libSACdec/src/sac_reshapeBBEnv.cpp
+++ b/libSACdec/src/sac_reshapeBBEnv.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -241,56 +241,29 @@
   }
 }
 
-static inline void slotAmp(
-    FIXP_DBL *RESTRICT slotAmp_dry, INT *RESTRICT slotAmp_dry_e,
-    FIXP_DBL *RESTRICT slotAmp_wet, INT *RESTRICT slotAmp_wet_e,
-    FIXP_DBL *RESTRICT pHybOutputRealDry, FIXP_DBL *RESTRICT pHybOutputImagDry,
-    FIXP_DBL *RESTRICT pHybOutputRealWet, FIXP_DBL *RESTRICT pHybOutputImagWet,
-    INT cplxBands, INT hybBands) {
-  INT qs, s1, s2, headroom_dry, headroom_wet;
+static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
+                           FIXP_DBL *RESTRICT slotAmp_wet,
+                           FIXP_DBL *RESTRICT pHybOutputRealDry,
+                           FIXP_DBL *RESTRICT pHybOutputImagDry,
+                           FIXP_DBL *RESTRICT pHybOutputRealWet,
+                           FIXP_DBL *RESTRICT pHybOutputImagWet, INT cplxBands,
+                           INT hybBands) {
+  INT qs;
   FIXP_DBL dry, wet;
 
-  /* headroom can be reduced by 1 bit due to use of fPow2Div2 */
-  s1 = DFRACT_BITS - 1 - CntLeadingZeros(hybBands + cplxBands);
-  headroom_dry = fMin(getScalefactor(pHybOutputRealDry, hybBands),
-                      getScalefactor(pHybOutputImagDry, cplxBands));
-  headroom_wet = fMin(getScalefactor(pHybOutputRealWet, hybBands),
-                      getScalefactor(pHybOutputImagWet, cplxBands));
-
   dry = wet = FL2FXCONST_DBL(0.0f);
   for (qs = 0; qs < cplxBands; qs++) {
-    /* sum up dry part */
-    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
-    dry += (fPow2Div2(pHybOutputImagDry[qs] << headroom_dry) >> s1);
-    /* sum up wet part */
-    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
-    wet += (fPow2Div2(pHybOutputImagWet[qs] << headroom_wet) >> s1);
+    dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) +
+                                fPow2Div2(pHybOutputImagDry[qs] << (1)));
+    wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) +
+                                fPow2Div2(pHybOutputImagWet[qs] << (1)));
   }
   for (; qs < hybBands; qs++) {
-    dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
-    wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
+    dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)));
+    wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)));
   }
-
-  /* consider fPow2Div2() */
-  s1 += 1;
-
-  /* normalize dry part, ensure that exponent is even */
-  s2 = fixMax(0, CntLeadingZeros(dry) - 1);
-  *slotAmp_dry = dry << s2;
-  *slotAmp_dry_e = s1 - s2 - 2 * headroom_dry;
-  if (*slotAmp_dry_e & 1) {
-    *slotAmp_dry = *slotAmp_dry >> 1;
-    *slotAmp_dry_e += 1;
-  }
-
-  /* normalize wet part, ensure that exponent is even */
-  s2 = fixMax(0, CntLeadingZeros(wet) - 1);
-  *slotAmp_wet = wet << s2;
-  *slotAmp_wet_e = s1 - s2 - 2 * headroom_wet;
-  if (*slotAmp_wet_e & 1) {
-    *slotAmp_wet = *slotAmp_wet >> 1;
-    *slotAmp_wet_e += 1;
-  }
+  *slotAmp_dry = dry >> (2 * (1));
+  *slotAmp_wet = wet >> (2 * (1));
 }
 
 #if defined(__aarch64__)
@@ -560,7 +533,6 @@
                             INT ts) {
   INT ch, scale;
   INT dryFacSF, slotAmpSF;
-  INT slotAmp_dry_e, slotAmp_wet_e;
   FIXP_DBL tmp, dryFac, envShape;
   FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio;
   FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2];
@@ -622,25 +594,22 @@
         dryFacSF = SF_SHAPE + 2 * dryFacSF;
       }
 
-      slotAmp_dry_e = slotAmp_wet_e = 0;
-
       /* calculate slotAmp_dry and slotAmp_wet */
-      slotAmp(&slotAmp_dry, &slotAmp_dry_e, &slotAmp_wet, &slotAmp_wet_e,
-              &self->hybOutputRealDry__FDK[ch][6],
+      slotAmp(&slotAmp_dry, &slotAmp_wet, &self->hybOutputRealDry__FDK[ch][6],
               &self->hybOutputImagDry__FDK[ch][6],
               &self->hybOutputRealWet__FDK[ch][6],
               &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands);
 
-      /* exponents must be even due to subsequent square root calculation */
-      FDK_ASSERT(((slotAmp_dry_e & 1) == 0) && ((slotAmp_wet_e & 1) == 0));
-
       /* slotAmp_ratio will be scaled by slotAmpSF bits */
       if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) {
-        slotAmp_wet = sqrtFixp(slotAmp_wet);
+        sc = fixMax(0, CntLeadingZeros(slotAmp_wet) - 1);
+        sc = sc - (sc & 1);
+
+        slotAmp_wet = sqrtFixp(slotAmp_wet << sc);
         slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF);
 
         slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry);
-        slotAmpSF = slotAmpSF + (slotAmp_wet_e >> 1) - (slotAmp_dry_e >> 1);
+        slotAmpSF = slotAmpSF - (sc >> 1);
       }
 
       /* calculate common scale factor */
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
index 0e6affa..b328c82 100644
--- a/libSACdec/src/sac_stp.cpp
+++ b/libSACdec/src/sac_stp.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -229,13 +229,15 @@
   int n;
   FIXP_DBL scaleY;
   for (n = bands - 1; n >= 0; n--) {
-    scaleY = fMult(scaleX, *pBP);
+    scaleY = fMultDiv2(scaleX, *pBP);
     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleY),
-        SF_SCALE, DFRACT_BITS);
+        (*hybOutputRealDry >> 1) +
+            (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 1)),
+        1, DFRACT_BITS);
     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleY),
-        SF_SCALE, DFRACT_BITS);
+        (*hybOutputImagDry >> 1) +
+            (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 1)),
+        1, DFRACT_BITS);
     hybOutputRealDry++, hybOutputRealWet++;
     hybOutputImagDry++, hybOutputImagWet++;
     pBP++;
@@ -250,12 +252,12 @@
   int n;
 
   for (n = bands - 1; n >= 0; n--) {
-    *hybOutputRealDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleX),
-        SF_SCALE, DFRACT_BITS);
-    *hybOutputImagDry = SATURATE_LEFT_SHIFT(
-        (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleX),
-        SF_SCALE, DFRACT_BITS);
+    *hybOutputRealDry =
+        *hybOutputRealDry +
+        (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
+    *hybOutputImagDry =
+        *hybOutputImagDry +
+        (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
     hybOutputRealDry++, hybOutputRealWet++;
     hybOutputImagDry++, hybOutputImagWet++;
   }
diff --git a/libSBRdec/src/arm/lpp_tran_arm.cpp b/libSBRdec/src/arm/lpp_tran_arm.cpp
new file mode 100644
index 0000000..db1948f
--- /dev/null
+++ b/libSBRdec/src/arm/lpp_tran_arm.cpp
@@ -0,0 +1,159 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright  1995 - 2018 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
+----------------------------------------------------------------------------- */
+
+/**************************** SBR decoder library ******************************
+
+   Author(s):   Arthur Tritthart
+
+   Description: (ARM optimised) LPP transposer subroutines
+
+*******************************************************************************/
+
+#if defined(__arm__)
+
+#define FUNCTION_LPPTRANSPOSER_func1
+
+#ifdef FUNCTION_LPPTRANSPOSER_func1
+
+/* Note: This code requires only 43 cycles per iteration instead of 61 on
+ * ARM926EJ-S */
+static void lppTransposer_func1(FIXP_DBL *lowBandReal, FIXP_DBL *lowBandImag,
+                                FIXP_DBL **qmfBufferReal,
+                                FIXP_DBL **qmfBufferImag, int loops, int hiBand,
+                                int dynamicScale, int descale, FIXP_SGL a0r,
+                                FIXP_SGL a0i, FIXP_SGL a1r, FIXP_SGL a1i,
+                                const int fPreWhitening,
+                                FIXP_DBL preWhiteningGain,
+                                int preWhiteningGains_sf) {
+  FIXP_DBL real1, real2, imag1, imag2, accu1, accu2;
+
+  real2 = lowBandReal[-2];
+  real1 = lowBandReal[-1];
+  imag2 = lowBandImag[-2];
+  imag1 = lowBandImag[-1];
+  for (int i = 0; i < loops; i++) {
+    accu1 = fMultDiv2(a0r, real1);
+    accu2 = fMultDiv2(a0i, imag1);
+    accu1 = fMultAddDiv2(accu1, a1r, real2);
+    accu2 = fMultAddDiv2(accu2, a1i, imag2);
+    real2 = fMultDiv2(a1i, real2);
+    accu1 = accu1 - accu2;
+    accu1 = accu1 >> dynamicScale;
+
+    accu2 = fMultAddDiv2(real2, a1r, imag2);
+    real2 = real1;
+    imag2 = imag1;
+    accu2 = fMultAddDiv2(accu2, a0i, real1);
+    real1 = lowBandReal[i];
+    accu2 = fMultAddDiv2(accu2, a0r, imag1);
+    imag1 = lowBandImag[i];
+    accu2 = accu2 >> dynamicScale;
+
+    accu1 <<= 1;
+    accu2 <<= 1;
+    accu1 += (real1 >> descale);
+    accu2 += (imag1 >> descale);
+    if (fPreWhitening) {
+      accu1 = scaleValueSaturate(fMultDiv2(accu1, preWhiteningGain),
+                                 preWhiteningGains_sf);
+      accu2 = scaleValueSaturate(fMultDiv2(accu2, preWhiteningGain),
+                                 preWhiteningGains_sf);
+    }
+    qmfBufferReal[i][hiBand] = accu1;
+    qmfBufferImag[i][hiBand] = accu2;
+  }
+}
+#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */
+
+#endif /* __arm__ */
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index cefa612..ad5edfe 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -664,7 +664,7 @@
         gain_sf[i] = mult_sf - total_power_low_sf + sf2;
         gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]);
         if (gain_sf[i] < 0) {
-          gain[i] >>= fMin(DFRACT_BITS - 1, -gain_sf[i]);
+          gain[i] >>= -gain_sf[i];
           gain_sf[i] = 0;
         }
       } else {
@@ -683,6 +683,11 @@
 
     /* gain[i] = g_inter[i] */
     for (i = 0; i < nbSubsample; ++i) {
+      if (gain_sf[i] < 0) {
+        gain[i] >>= -gain_sf[i];
+        gain_sf[i] = 0;
+      }
+
       /* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */
       FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >>
                      gain_sf[i]; /* to substract this from gain[i] */
@@ -750,15 +755,23 @@
     int gain_adj_sf = gain_adj_2_sf;
 
     for (i = 0; i < nbSubsample; ++i) {
-      int gain_e = fMax(
-          fMin(gain_sf[i] + gain_adj_sf - INTER_TES_SF_CHANGE, DFRACT_BITS - 1),
-          -(DFRACT_BITS - 1));
-      FIXP_DBL gain_final = fMult(gain[i], gain_adj);
-      gain_final = scaleValueSaturate(gain_final, gain_e);
+      gain[i] = fMult(gain[i], gain_adj);
+      gain_sf[i] += gain_adj_sf;
+
+      /* limit gain */
+      if (gain_sf[i] > INTER_TES_SF_CHANGE) {
+        gain[i] = (FIXP_DBL)MAXVAL_DBL;
+        gain_sf[i] = INTER_TES_SF_CHANGE;
+      }
+    }
+
+    for (i = 0; i < nbSubsample; ++i) {
+      /* equalize gain[]'s scale factors */
+      gain[i] >>= INTER_TES_SF_CHANGE - gain_sf[i];
 
       for (j = lowSubband; j < highSubband; j++) {
-        qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain_final);
-        qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain_final);
+        qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain[i]);
+        qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain[i]);
       }
     }
   } else { /* gamma_idx == 0 */
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp
index f2452ea..d210bb6 100644
--- a/libSBRdec/src/hbe.cpp
+++ b/libSBRdec/src/hbe.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -1400,27 +1400,42 @@
 
   if (shift_ov != 0) {
     for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) {
-      scaleValuesSaturate(&hQmfTransposer->qmfHBEBufReal_F[i][0],
-                          QMF_SYNTH_CHANNELS, shift_ov);
-      scaleValuesSaturate(&hQmfTransposer->qmfHBEBufImag_F[i][0],
-                          QMF_SYNTH_CHANNELS, shift_ov);
+      for (band = 0; band < QMF_SYNTH_CHANNELS; band++) {
+        if (shift_ov >= 0) {
+          hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov;
+          hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov;
+        } else {
+          hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov);
+          hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov);
+        }
+      }
+    }
+  }
+
+  if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) {
+    for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
+      for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand;
+           band++) {
+        if (shift_ov >= 0) {
+          ppQmfBufferOutReal_F[i][band] <<= shift_ov;
+          ppQmfBufferOutImag_F[i][band] <<= shift_ov;
+        } else {
+          ppQmfBufferOutReal_F[i][band] >>= (-shift_ov);
+          ppQmfBufferOutImag_F[i][band] >>= (-shift_ov);
+        }
+      }
     }
 
-    if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) {
-      int nBands =
-          fMax(0, hQmfTransposer->stopBand - hQmfTransposer->startBand);
-
-      for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
-        scaleValuesSaturate(&ppQmfBufferOutReal_F[i][hQmfTransposer->startBand],
-                            nBands, shift_ov);
-        scaleValuesSaturate(&ppQmfBufferOutImag_F[i][hQmfTransposer->startBand],
-                            nBands, shift_ov);
-      }
-
-      /* shift lpc filterstates */
-      for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
-        scaleValuesSaturate(&lpcFilterStatesReal[i][0], (64), shift_ov);
-        scaleValuesSaturate(&lpcFilterStatesImag[i][0], (64), shift_ov);
+    /* shift lpc filterstates */
+    for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
+      for (band = 0; band < (64); band++) {
+        if (shift_ov >= 0) {
+          lpcFilterStatesReal[i][band] <<= shift_ov;
+          lpcFilterStatesImag[i][band] <<= shift_ov;
+        } else {
+          lpcFilterStatesReal[i][band] >>= (-shift_ov);
+          lpcFilterStatesImag[i][band] >>= (-shift_ov);
+        }
       }
     }
   }
diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp
index 68a25bf..93e1158 100644
--- a/libSBRdec/src/lpp_tran.cpp
+++ b/libSBRdec/src/lpp_tran.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -132,6 +132,10 @@
 
 #include "HFgen_preFlat.h"
 
+#if defined(__arm__)
+#include "arm/lpp_tran_arm.cpp"
+#endif
+
 #define LPC_SCALE_FACTOR 2
 
 /*!
@@ -216,21 +220,19 @@
                                       const FIXP_DBL *const lowBandReal,
                                       const int startSample,
                                       const int stopSample, const UCHAR hiBand,
-                                      const int dynamicScale,
+                                      const int dynamicScale, const int descale,
                                       const FIXP_SGL a0r, const FIXP_SGL a1r) {
-  const int dynscale = fixMax(0, dynamicScale - 1) + 1;
-  const int rescale = -fixMin(0, dynamicScale - 1) + 1;
-  const int descale =
-      fixMin(DFRACT_BITS - 1, LPC_SCALE_FACTOR + dynamicScale + rescale);
+  FIXP_DBL accu1, accu2;
+  int i;
 
-  for (int i = 0; i < stopSample - startSample; i++) {
-    FIXP_DBL accu;
+  for (i = 0; i < stopSample - startSample; i++) {
+    accu1 = fMultDiv2(a1r, lowBandReal[i]);
+    accu1 = (fMultDiv2(a0r, lowBandReal[i + 1]) + accu1);
+    accu1 = accu1 >> dynamicScale;
 
-    accu = fMultDiv2(a1r, lowBandReal[i]) + fMultDiv2(a0r, lowBandReal[i + 1]);
-    accu = (lowBandReal[i + 2] >> descale) + (accu >> dynscale);
-
-    qmfBufferReal[i + startSample][hiBand] =
-        SATURATE_LEFT_SHIFT(accu, rescale, DFRACT_BITS);
+    accu1 <<= 1;
+    accu2 = (lowBandReal[i + 2] >> descale);
+    qmfBufferReal[i + startSample][hiBand] = accu1 + accu2;
   }
 }
 
@@ -527,7 +529,7 @@
         if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
           resetLPCCoeffs = 1;
         } else {
-          alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
+          alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
             alphar[1] = -alphar[1];
           }
@@ -555,7 +557,7 @@
                scale)) {
             resetLPCCoeffs = 1;
           } else {
-            alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
+            alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
             if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
               alphai[1] = -alphai[1];
             }
@@ -594,7 +596,7 @@
       } else {
         INT scale;
         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
-        alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
+        alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
 
         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
           alphar[0] = -alphar[0];
@@ -614,7 +616,7 @@
         } else {
           INT scale;
           FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
-          alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
+          alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
           if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
             alphai[0] = -alphai[0];
         }
@@ -657,7 +659,7 @@
           INT scale;
           FIXP_DBL result =
               fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale);
-          k1 = scaleValueSaturate(result, scale);
+          k1 = scaleValue(result, scale);
 
           if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) {
             k1 = -k1;
@@ -769,50 +771,52 @@
       } else { /* bw <= 0 */
 
         if (!useLP) {
-          const int dynscale = fixMax(0, dynamicScale - 2) + 1;
-          const int rescale = -fixMin(0, dynamicScale - 2) + 1;
-          const int descale = fixMin(DFRACT_BITS - 1,
-                                     LPC_SCALE_FACTOR + dynamicScale + rescale);
-
+          int descale =
+              fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+#ifdef FUNCTION_LPPTRANSPOSER_func1
+          lppTransposer_func1(
+              lowBandReal + LPC_ORDER + startSample,
+              lowBandImag + LPC_ORDER + startSample,
+              qmfBufferReal + startSample, qmfBufferImag + startSample,
+              stopSample - startSample, (int)hiBand, dynamicScale, descale, a0r,
+              a0i, a1r, a1i, fPreWhitening, preWhiteningGains[loBand],
+              preWhiteningGains_exp[loBand] + 1);
+#else
           for (i = startSample; i < stopSample; i++) {
             FIXP_DBL accu1, accu2;
 
-            accu1 = ((fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
-                      fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1])) >>
-                     1) +
-                    ((fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
-                      fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
-                     1);
-            accu2 = ((fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
-                      fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1])) >>
-                     1) +
-                    ((fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
-                      fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
-                     1);
+            accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
+                     fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) +
+                     fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
+                     fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
+                    dynamicScale;
+            accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
+                     fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) +
+                     fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
+                     fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
+                    dynamicScale;
 
-            accu1 =
-                (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 >> dynscale);
-            accu2 =
-                (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 >> dynscale);
+            accu1 = (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1);
+            accu2 = (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1);
             if (fPreWhitening) {
-              qmfBufferReal[i][hiBand] = scaleValueSaturate(
+              accu1 = scaleValueSaturate(
                   fMultDiv2(accu1, preWhiteningGains[loBand]),
-                  preWhiteningGains_exp[loBand] + 1 + rescale);
-              qmfBufferImag[i][hiBand] = scaleValueSaturate(
+                  preWhiteningGains_exp[loBand] + 1);
+              accu2 = scaleValueSaturate(
                   fMultDiv2(accu2, preWhiteningGains[loBand]),
-                  preWhiteningGains_exp[loBand] + 1 + rescale);
-            } else {
-              qmfBufferReal[i][hiBand] =
-                  SATURATE_LEFT_SHIFT(accu1, rescale, DFRACT_BITS);
-              qmfBufferImag[i][hiBand] =
-                  SATURATE_LEFT_SHIFT(accu2, rescale, DFRACT_BITS);
+                  preWhiteningGains_exp[loBand] + 1);
             }
+            qmfBufferReal[i][hiBand] = accu1;
+            qmfBufferImag[i][hiBand] = accu2;
           }
+#endif
         } else {
           FDK_ASSERT(dynamicScale >= 0);
           calc_qmfBufferReal(
               qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]),
-              startSample, stopSample, hiBand, dynamicScale, a0r, a1r);
+              startSample, stopSample, hiBand, dynamicScale,
+              fMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)), a0r,
+              a1r);
         }
       } /* bw <= 0 */
 
@@ -1062,7 +1066,7 @@
         if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
           resetLPCCoeffs = 1;
         } else {
-          alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
+          alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
             alphar[1] = -alphar[1];
           }
@@ -1088,7 +1092,7 @@
             (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) {
           resetLPCCoeffs = 1;
         } else {
-          alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
+          alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
             alphai[1] = -alphai[1];
           }
@@ -1117,7 +1121,7 @@
       } else {
         INT scale;
         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
-        alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
+        alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
 
         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
           alphar[0] = -alphar[0];
@@ -1136,7 +1140,7 @@
       } else {
         INT scale;
         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
-        alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
+        alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) {
           alphai[0] = -alphai[0];
         }
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index 919e9bb..b1fb0da 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -713,8 +713,7 @@
 
   } else { /* (flags & SBRDEC_PS_DECODED) */
     INT sdiff;
-    INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov,
-        outScalefactor, outScalefactorR, outScalefactorL;
+    INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov;
 
     HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb;
     HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb;
@@ -745,7 +744,7 @@
       */
       FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <=
                  QMF_MAX_SYNTHESIS_BANDS);
-      synQmfRight->outScalefactor = synQmf->outScalefactor;
+      qmfChangeOutScalefactor(synQmfRight, -(8));
       FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates,
                 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis *
                     sizeof(FIXP_QSS));
@@ -789,12 +788,10 @@
       FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel,
                 sizeof(SBRDEC_DRC_CHANNEL));
 
-      outScalefactor = maxShift - (8);
-      outScalefactorL = outScalefactorR =
-          sbrInDataHeadroom + 1; /* +1: psDiffScale! (MPEG-PS) */
-
       for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
 
+        INT outScalefactorR, outScalefactorL;
+
         /* qmf timeslot of right channel */
         FIXP_DBL *rQmfReal = pWorkBuffer;
         FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels;
@@ -818,20 +815,27 @@
                   ? scaleFactorLowBand_ov
                   : scaleFactorLowBand_no_ov,
               scaleFactorHighBand, synQmf->lsb, synQmf->usb);
+
+          outScalefactorL = outScalefactorR =
+              1 + sbrInDataHeadroom; /* psDiffScale! (MPEG-PS) */
         }
 
         sbrDecoder_drcApplySlot(/* right channel */
                                 &hSbrDecRight->sbrDrcChannel, rQmfReal,
                                 rQmfImag, i, synQmfRight->no_col, maxShift);
 
+        outScalefactorR += maxShift;
+
         sbrDecoder_drcApplySlot(/* left channel */
                                 &hSbrDec->sbrDrcChannel, *(pLowBandReal + i),
                                 *(pLowBandImag + i), i, synQmf->no_col,
                                 maxShift);
 
+        outScalefactorL += maxShift;
+
         if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
-          qmfChangeOutScalefactor(synQmf, outScalefactor);
-          qmfChangeOutScalefactor(synQmfRight, outScalefactor);
+          qmfChangeOutScalefactor(synQmf, -(8));
+          qmfChangeOutScalefactor(synQmfRight, -(8));
 
           qmfSynthesisFilteringSlot(
               synQmfRight, rQmfReal, /* QMF real buffer */
diff --git a/libSBRdec/src/sbrdec_freq_sca.cpp b/libSBRdec/src/sbrdec_freq_sca.cpp
index daa3554..e187656 100644
--- a/libSBRdec/src/sbrdec_freq_sca.cpp
+++ b/libSBRdec/src/sbrdec_freq_sca.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 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
@@ -765,6 +765,9 @@
   sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1],
                     nBandsHi);
 
+  hFreq->nSfb[0] = nBandsLo;
+  hFreq->nSfb[1] = nBandsHi;
+
   /* Check index to freqBandTable[0] */
   if (!(nBandsLo > 0) ||
       (nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16)
@@ -774,9 +777,6 @@
     return SBRDEC_UNSUPPORTED_CONFIG;
   }
 
-  hFreq->nSfb[0] = nBandsLo;
-  hFreq->nSfb[1] = nBandsHi;
-
   lsb = hFreq->freqBandTable[0][0];
   usb = hFreq->freqBandTable[0][nBandsLo];
 
@@ -814,15 +814,15 @@
 
     if (intTemp == 0) intTemp = 1;
 
-    if (intTemp > MAX_NOISE_COEFFS) {
-      return SBRDEC_UNSUPPORTED_CONFIG;
-    }
-
     hFreq->nNfb = intTemp;
   }
 
   hFreq->nInvfBands = hFreq->nNfb;
 
+  if (hFreq->nNfb > MAX_NOISE_COEFFS) {
+    return SBRDEC_UNSUPPORTED_CONFIG;
+  }
+
   /* Get noise bands */
   sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb,
                         hFreq->freqBandTable[0], nBandsLo);
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index 7718695..b101a4a 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -961,10 +961,8 @@
 
           /* Set sync state UPSAMPLING for the corresponding slot.
              This switches off bitstream parsing until a new header arrives. */
-          if (hSbrHeader->syncState != SBR_NOT_INITIALIZED) {
-            hSbrHeader->syncState = UPSAMPLING;
-            hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
-          }
+          hSbrHeader->syncState = UPSAMPLING;
+          hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
         }
       }
     } break;
@@ -1373,9 +1371,7 @@
       }
       if (headerStatus == HEADER_ERROR) {
         /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */
-        hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING
-                                    ? UPSAMPLING
-                                    : hSbrHeader->syncState;
+        hSbrHeader->syncState = UPSAMPLING;
         fDoDecodeSbrData = 0;
         sbrHeaderPresent = 0;
       }
@@ -1614,9 +1610,7 @@
       /* No valid SBR payload available, hence switch to upsampling (in all
        * headers) */
       for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) {
-        if (self->sbrHeader[elementIndex][hdrIdx].syncState > UPSAMPLING) {
-          self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
-        }
+        self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
       }
     } else {
       /* Move frame pointer to the next slot which is up to be decoded/applied