Revert "[ACM] iSAC audio codec removed"

This reverts commit b46c4bf27ba5c417fcba7f200d80fa4634e7e1a1.

Reason for revert: breaks a downstream project

Original change's description:
> [ACM] iSAC audio codec removed
>
> Note: this CL has to leave behind one part of iSAC, which is its VAD
> currently used by AGC1 in APM. The target visibility has been
> restricted and the VAD will be removed together with AGC1 when the
> time comes.
>
> Tested: see https://chromium-review.googlesource.com/c/chromium/src/+/4013319
>
> Bug: webrtc:14450
> Change-Id: I69cc518b16280eae62a1f1977cdbfa24c08cf5f9
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/282421
> Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
> Reviewed-by: Sam Zackrisson <saza@webrtc.org>
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#38652}

Bug: webrtc:14450
Change-Id: Ice138004e84e8c5f896684e8d01133d4b2a77bb7
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/283800
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Auto-Submit: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Owners-Override: Mirko Bonadei <mbonadei@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#38655}
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 65c849d..0d67cfa 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -381,8 +381,50 @@
   absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
 }
 
+rtc_source_set("isac_common") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/audio_decoder_isac_t.h",
+    "codecs/isac/audio_decoder_isac_t_impl.h",
+    "codecs/isac/audio_encoder_isac_t.h",
+    "codecs/isac/audio_encoder_isac_t_impl.h",
+  ]
+  deps = [
+    ":isac_bwinfo",
+    "../../api:scoped_refptr",
+    "../../api/audio_codecs:audio_codecs_api",
+    "../../api/units:time_delta",
+    "../../rtc_base:checks",
+    "../../rtc_base:safe_minmax",
+    "../../system_wrappers:field_trial",
+  ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
+rtc_library("isac") {
+  visibility += [ "*" ]
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/main/include/audio_decoder_isac.h",
+    "codecs/isac/main/include/audio_encoder_isac.h",
+    "codecs/isac/main/source/audio_decoder_isac.cc",
+    "codecs/isac/main/source/audio_encoder_isac.cc",
+  ]
+
+  deps = [
+    ":isac_common",
+    "../../api/audio_codecs:audio_codecs_api",
+  ]
+  public_deps = [ ":isac_c" ]  # no-presubmit-check TODO(webrtc:8603)
+}
+
+rtc_source_set("isac_bwinfo") {
+  sources = [ "codecs/isac/bandwidth_info.h" ]
+  deps = []
+}
+
 rtc_library("isac_vad") {
-  visibility += [ "../audio_processing/vad:*" ]
+  visibility += webrtc_default_visibility
   sources = [
     "codecs/isac/main/source/filter_functions.c",
     "codecs/isac/main/source/filter_functions.h",
@@ -405,9 +447,247 @@
   ]
 }
 
-rtc_source_set("isac_bwinfo") {
-  sources = [ "codecs/isac/bandwidth_info.h" ]
-  deps = []
+rtc_library("isac_c") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/main/include/isac.h",
+    "codecs/isac/main/source/arith_routines.c",
+    "codecs/isac/main/source/arith_routines.h",
+    "codecs/isac/main/source/arith_routines_hist.c",
+    "codecs/isac/main/source/arith_routines_logist.c",
+    "codecs/isac/main/source/bandwidth_estimator.c",
+    "codecs/isac/main/source/bandwidth_estimator.h",
+    "codecs/isac/main/source/codec.h",
+    "codecs/isac/main/source/crc.c",
+    "codecs/isac/main/source/crc.h",
+    "codecs/isac/main/source/decode.c",
+    "codecs/isac/main/source/decode_bwe.c",
+    "codecs/isac/main/source/encode.c",
+    "codecs/isac/main/source/encode_lpc_swb.c",
+    "codecs/isac/main/source/encode_lpc_swb.h",
+    "codecs/isac/main/source/entropy_coding.c",
+    "codecs/isac/main/source/entropy_coding.h",
+    "codecs/isac/main/source/filterbanks.c",
+    "codecs/isac/main/source/intialize.c",
+    "codecs/isac/main/source/isac.c",
+    "codecs/isac/main/source/isac_float_type.h",
+    "codecs/isac/main/source/lattice.c",
+    "codecs/isac/main/source/lpc_analysis.c",
+    "codecs/isac/main/source/lpc_analysis.h",
+    "codecs/isac/main/source/lpc_gain_swb_tables.c",
+    "codecs/isac/main/source/lpc_gain_swb_tables.h",
+    "codecs/isac/main/source/lpc_shape_swb12_tables.c",
+    "codecs/isac/main/source/lpc_shape_swb12_tables.h",
+    "codecs/isac/main/source/lpc_shape_swb16_tables.c",
+    "codecs/isac/main/source/lpc_shape_swb16_tables.h",
+    "codecs/isac/main/source/lpc_tables.c",
+    "codecs/isac/main/source/lpc_tables.h",
+    "codecs/isac/main/source/pitch_gain_tables.c",
+    "codecs/isac/main/source/pitch_gain_tables.h",
+    "codecs/isac/main/source/pitch_lag_tables.c",
+    "codecs/isac/main/source/pitch_lag_tables.h",
+    "codecs/isac/main/source/spectrum_ar_model_tables.c",
+    "codecs/isac/main/source/spectrum_ar_model_tables.h",
+    "codecs/isac/main/source/transform.c",
+  ]
+
+  if (is_linux || is_chromeos) {
+    libs = [ "m" ]
+  }
+
+  deps = [
+    ":isac_bwinfo",
+    ":isac_vad",
+    "../../common_audio",
+    "../../common_audio:common_audio_c",
+    "../../rtc_base:checks",
+    "../../rtc_base:compile_assert_c",
+    "../../rtc_base/system:arch",
+    "../third_party/fft",
+  ]
+}
+
+rtc_library("isac_fix") {
+  visibility += [ "*" ]
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/fix/source/audio_decoder_isacfix.cc",
+    "codecs/isac/fix/source/audio_encoder_isacfix.cc",
+  ]
+
+  deps = [
+    ":isac_common",
+    "../../api/audio_codecs:audio_codecs_api",
+    "../../common_audio",
+    "../../system_wrappers",
+  ]
+  public_deps = [ ":isac_fix_c" ]  # no-presubmit-check TODO(webrtc:8603)
+
+  if (rtc_build_with_neon) {
+    deps += [ ":isac_neon" ]
+  }
+}
+
+rtc_library("isac_fix_common") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/fix/source/codec.h",
+    "codecs/isac/fix/source/entropy_coding.h",
+    "codecs/isac/fix/source/fft.c",
+    "codecs/isac/fix/source/fft.h",
+    "codecs/isac/fix/source/filterbank_internal.h",
+    "codecs/isac/fix/source/settings.h",
+    "codecs/isac/fix/source/structs.h",
+    "codecs/isac/fix/source/transform_tables.c",
+  ]
+  deps = [
+    ":isac_bwinfo",
+    "../../common_audio",
+    "../../common_audio:common_audio_c",
+  ]
+}
+
+rtc_source_set("isac_fix_c_arm_asm") {
+  poisonous = [ "audio_codecs" ]
+  sources = []
+  if (current_cpu == "arm" && arm_version >= 7) {
+    sources += [
+      "codecs/isac/fix/source/lattice_armv7.S",
+      "codecs/isac/fix/source/pitch_filter_armv6.S",
+    ]
+    deps = [
+      ":isac_fix_common",
+      "../../rtc_base/system:asm_defines",
+    ]
+  }
+}
+
+rtc_library("isac_fix_c") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "codecs/isac/fix/include/audio_decoder_isacfix.h",
+    "codecs/isac/fix/include/audio_encoder_isacfix.h",
+    "codecs/isac/fix/include/isacfix.h",
+    "codecs/isac/fix/source/arith_routines.c",
+    "codecs/isac/fix/source/arith_routines_hist.c",
+    "codecs/isac/fix/source/arith_routines_logist.c",
+    "codecs/isac/fix/source/arith_routins.h",
+    "codecs/isac/fix/source/bandwidth_estimator.c",
+    "codecs/isac/fix/source/bandwidth_estimator.h",
+    "codecs/isac/fix/source/decode.c",
+    "codecs/isac/fix/source/decode_bwe.c",
+    "codecs/isac/fix/source/decode_plc.c",
+    "codecs/isac/fix/source/encode.c",
+    "codecs/isac/fix/source/entropy_coding.c",
+    "codecs/isac/fix/source/filterbank_tables.c",
+    "codecs/isac/fix/source/filterbank_tables.h",
+    "codecs/isac/fix/source/filterbanks.c",
+    "codecs/isac/fix/source/filters.c",
+    "codecs/isac/fix/source/initialize.c",
+    "codecs/isac/fix/source/isac_fix_type.h",
+    "codecs/isac/fix/source/isacfix.c",
+    "codecs/isac/fix/source/lattice.c",
+    "codecs/isac/fix/source/lattice_c.c",
+    "codecs/isac/fix/source/lpc_masking_model.c",
+    "codecs/isac/fix/source/lpc_masking_model.h",
+    "codecs/isac/fix/source/lpc_tables.c",
+    "codecs/isac/fix/source/lpc_tables.h",
+    "codecs/isac/fix/source/pitch_estimator.c",
+    "codecs/isac/fix/source/pitch_estimator.h",
+    "codecs/isac/fix/source/pitch_estimator_c.c",
+    "codecs/isac/fix/source/pitch_filter.c",
+    "codecs/isac/fix/source/pitch_filter_c.c",
+    "codecs/isac/fix/source/pitch_gain_tables.c",
+    "codecs/isac/fix/source/pitch_gain_tables.h",
+    "codecs/isac/fix/source/pitch_lag_tables.c",
+    "codecs/isac/fix/source/pitch_lag_tables.h",
+    "codecs/isac/fix/source/spectrum_ar_model_tables.c",
+    "codecs/isac/fix/source/spectrum_ar_model_tables.h",
+    "codecs/isac/fix/source/transform.c",
+  ]
+
+  deps = [
+    ":isac_bwinfo",
+    ":isac_common",
+    ":isac_fix_common",
+    "../../api/audio_codecs:audio_codecs_api",
+    "../../common_audio",
+    "../../common_audio:common_audio_c",
+    "../../rtc_base:checks",
+    "../../rtc_base:compile_assert_c",
+    "../../rtc_base:sanitizer",
+    "../../system_wrappers",
+    "../third_party/fft",
+  ]
+
+  if (rtc_build_with_neon) {
+    deps += [ ":isac_neon" ]
+
+    # TODO(bugs.webrtc.org/9579): Consider moving the usage of NEON from
+    # pitch_estimator_c.c into the "isac_neon" target and delete this flag:
+    if (current_cpu != "arm64") {
+      suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+      cflags = [ "-mfpu=neon" ]
+    }
+  }
+
+  if (current_cpu == "arm" && arm_version >= 7) {
+    sources -= [
+      "codecs/isac/fix/source/lattice_c.c",
+      "codecs/isac/fix/source/pitch_filter_c.c",
+    ]
+    deps += [ ":isac_fix_c_arm_asm" ]
+  }
+
+  if (current_cpu == "mipsel") {
+    sources += [
+      "codecs/isac/fix/source/entropy_coding_mips.c",
+      "codecs/isac/fix/source/filters_mips.c",
+      "codecs/isac/fix/source/lattice_mips.c",
+      "codecs/isac/fix/source/pitch_estimator_mips.c",
+      "codecs/isac/fix/source/transform_mips.c",
+    ]
+    sources -= [
+      "codecs/isac/fix/source/lattice_c.c",
+      "codecs/isac/fix/source/pitch_estimator_c.c",
+    ]
+    if (mips_dsp_rev > 0) {
+      sources += [ "codecs/isac/fix/source/filterbanks_mips.c" ]
+    }
+    if (mips_dsp_rev > 1) {
+      sources += [
+        "codecs/isac/fix/source/lpc_masking_model_mips.c",
+        "codecs/isac/fix/source/pitch_filter_mips.c",
+      ]
+      sources -= [ "codecs/isac/fix/source/pitch_filter_c.c" ]
+    }
+  }
+}
+
+if (rtc_build_with_neon) {
+  rtc_library("isac_neon") {
+    poisonous = [ "audio_codecs" ]
+    sources = [
+      "codecs/isac/fix/source/entropy_coding_neon.c",
+      "codecs/isac/fix/source/filterbanks_neon.c",
+      "codecs/isac/fix/source/filters_neon.c",
+      "codecs/isac/fix/source/lattice_neon.c",
+      "codecs/isac/fix/source/transform_neon.c",
+    ]
+
+    if (current_cpu != "arm64") {
+      # Enable compilation for the NEON instruction set.
+      suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+      cflags = [ "-mfpu=neon" ]
+    }
+
+    deps = [
+      ":isac_fix_common",
+      "../../common_audio",
+      "../../common_audio:common_audio_c",
+      "../../rtc_base:checks",
+    ]
+  }
 }
 
 rtc_library("pcm16b") {
@@ -1011,6 +1291,11 @@
   if (rtc_include_opus) {
     audio_coding_deps += [ ":webrtc_opus" ]
   }
+  if (current_cpu == "arm") {
+    audio_coding_deps += [ ":isac_fix" ]
+  } else {
+    audio_coding_deps += [ ":isac" ]
+  }
   if (!build_with_mozilla && !build_with_chromium) {
     audio_coding_deps += [ ":red" ]
   }
@@ -1042,7 +1327,11 @@
         ":g711_test",
         ":g722_test",
         ":ilbc_test",
+        ":isac_api_test",
+        ":isac_switch_samprate_test",
+        ":isac_test",
         ":neteq_ilbc_quality_test",
+        ":neteq_isac_quality_test",
         ":neteq_opus_quality_test",
         ":neteq_pcm16b_quality_test",
         ":neteq_pcmu_quality_test",
@@ -1082,6 +1371,8 @@
       "test/Tester.cc",
       "test/TwoWayCommunication.cc",
       "test/TwoWayCommunication.h",
+      "test/iSACTest.cc",
+      "test/iSACTest.h",
       "test/target_delay_unittest.cc",
     ]
     deps = [
@@ -1106,6 +1397,8 @@
       "../../api/audio_codecs/g722:audio_encoder_g722",
       "../../api/audio_codecs/ilbc:audio_decoder_ilbc",
       "../../api/audio_codecs/ilbc:audio_encoder_ilbc",
+      "../../api/audio_codecs/isac:audio_decoder_isac_float",
+      "../../api/audio_codecs/isac:audio_encoder_isac_float",
       "../../api/audio_codecs/opus:audio_decoder_opus",
       "../../api/audio_codecs/opus:audio_encoder_opus",
       "../../common_audio",
@@ -1220,6 +1513,8 @@
 
       deps = [
                ":ilbc",
+               ":isac",
+               ":isac_fix",
                ":neteq",
                ":neteq_input_audio_tools",
                ":neteq_tools",
@@ -1324,10 +1619,12 @@
       testonly = true
       defines = []
       deps = [
+        ":isac_fix_common",
         "../../rtc_base:macromagic",
         "../../test:fileutils",
       ]
       sources = [
+        "codecs/isac/fix/test/isac_speed_test.cc",
         "codecs/opus/opus_speed_test.cc",
         "codecs/tools/audio_codec_speed_test.cc",
         "codecs/tools/audio_codec_speed_test.h",
@@ -1350,6 +1647,7 @@
       }
 
       deps += [
+        ":isac_fix",
         ":webrtc_opus",
         "../../rtc_base:checks",
         "../../test:test_main",
@@ -1425,6 +1723,7 @@
         "../../api/audio_codecs/g711:audio_encoder_g711",
         "../../api/audio_codecs/g722:audio_encoder_g722",
         "../../api/audio_codecs/ilbc:audio_encoder_ilbc",
+        "../../api/audio_codecs/isac:audio_encoder_isac",
         "../../api/audio_codecs/opus:audio_encoder_opus",
         "../../rtc_base:safe_conversions",
         "//third_party/abseil-cpp/absl/flags:flag",
@@ -1533,6 +1832,21 @@
       ]
     }
 
+    rtc_executable("neteq_isac_quality_test") {
+      testonly = true
+
+      sources = [ "neteq/test/neteq_isac_quality_test.cc" ]
+
+      deps = [
+        ":isac_fix",
+        ":neteq",
+        ":neteq_quality_test_support",
+        "../../test:test_main",
+        "//testing/gtest",
+        "//third_party/abseil-cpp/absl/flags:flag",
+      ]
+    }
+
     rtc_executable("neteq_pcmu_quality_test") {
       testonly = true
 
@@ -1570,6 +1884,28 @@
     }
   }
 
+  rtc_library("isac_test_util") {
+    testonly = true
+    sources = [
+      "codecs/isac/main/util/utility.c",
+      "codecs/isac/main/util/utility.h",
+    ]
+  }
+
+  if (!build_with_chromium) {
+    rtc_executable("isac_test") {
+      testonly = true
+
+      sources = [ "codecs/isac/main/test/simpleKenny.c" ]
+
+      deps = [
+        ":isac",
+        ":isac_test_util",
+        "../../rtc_base:macromagic",
+      ]
+    }
+  }
+
   rtc_executable("g711_test") {
     testonly = true
 
@@ -1587,6 +1923,32 @@
   }
 
   if (!build_with_chromium) {
+    rtc_executable("isac_api_test") {
+      testonly = true
+
+      sources = [ "codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc" ]
+
+      deps = [
+        ":isac",
+        ":isac_test_util",
+        "../../rtc_base:macromagic",
+      ]
+    }
+
+    rtc_executable("isac_switch_samprate_test") {
+      testonly = true
+
+      sources =
+          [ "codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc" ]
+
+      deps = [
+        ":isac",
+        ":isac_test_util",
+        "../../common_audio",
+        "../../common_audio:common_audio_c",
+      ]
+    }
+
     rtc_executable("ilbc_test") {
       testonly = true
 
@@ -1635,6 +1997,13 @@
         "codecs/cng/audio_encoder_cng_unittest.cc",
         "codecs/cng/cng_unittest.cc",
         "codecs/ilbc/ilbc_unittest.cc",
+        "codecs/isac/fix/source/filterbanks_unittest.cc",
+        "codecs/isac/fix/source/filters_unittest.cc",
+        "codecs/isac/fix/source/lpc_masking_model_unittest.cc",
+        "codecs/isac/fix/source/transform_unittest.cc",
+        "codecs/isac/isac_webrtc_api_test.cc",
+        "codecs/isac/main/source/audio_encoder_isac_unittest.cc",
+        "codecs/isac/main/source/isac_unittest.cc",
         "codecs/legacy_encoded_audio_frame_unittest.cc",
         "codecs/opus/audio_decoder_multi_channel_opus_unittest.cc",
         "codecs/opus/audio_encoder_multi_channel_opus_unittest.cc",
@@ -1701,6 +2070,11 @@
         ":default_neteq_factory",
         ":g711",
         ":ilbc",
+        ":isac",
+        ":isac_c",
+        ":isac_common",
+        ":isac_fix",
+        ":isac_fix_common",
         ":legacy_encoded_audio_frame",
         ":mocks",
         ":neteq",
@@ -1720,6 +2094,10 @@
         "../../api/audio_codecs:audio_codecs_api",
         "../../api/audio_codecs:builtin_audio_decoder_factory",
         "../../api/audio_codecs:builtin_audio_encoder_factory",
+        "../../api/audio_codecs/isac:audio_decoder_isac_fix",
+        "../../api/audio_codecs/isac:audio_decoder_isac_float",
+        "../../api/audio_codecs/isac:audio_encoder_isac_fix",
+        "../../api/audio_codecs/isac:audio_encoder_isac_float",
         "../../api/audio_codecs/opus:audio_decoder_multiopus",
         "../../api/audio_codecs/opus:audio_decoder_opus",
         "../../api/audio_codecs/opus:audio_encoder_multiopus",
diff --git a/modules/audio_coding/acm2/acm_receiver_unittest.cc b/modules/audio_coding/acm2/acm_receiver_unittest.cc
index 6dd44b6..e73acc2 100644
--- a/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -13,7 +13,6 @@
 #include <algorithm>  // std::min
 #include <memory>
 
-#include "absl/types/optional.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
@@ -65,14 +64,12 @@
                             const SdpAudioFormat& format,
                             const std::map<int, int> cng_payload_types = {}) {
     // Create the speech encoder.
-    absl::optional<AudioCodecInfo> info =
-        encoder_factory_->QueryAudioEncoder(format);
-    RTC_CHECK(info.has_value());
+    AudioCodecInfo info = encoder_factory_->QueryAudioEncoder(format).value();
     std::unique_ptr<AudioEncoder> enc =
         encoder_factory_->MakeAudioEncoder(payload_type, format, absl::nullopt);
 
     // If we have a compatible CN specification, stack a CNG on top.
-    auto it = cng_payload_types.find(info->sample_rate_hz);
+    auto it = cng_payload_types.find(info.sample_rate_hz);
     if (it != cng_payload_types.end()) {
       AudioEncoderCngConfig config;
       config.speech_encoder = std::move(enc);
@@ -84,7 +81,7 @@
 
     // Actually start using the new encoder.
     acm_->SetEncoder(std::move(enc));
-    return *info;
+    return info;
   }
 
   int InsertOnePacketOfSilence(const AudioCodecInfo& info) {
@@ -151,7 +148,8 @@
 #define MAYBE_SampleRate SampleRate
 #endif
 TEST_F(AcmReceiverTestOldApi, MAYBE_SampleRate) {
-  const std::map<int, SdpAudioFormat> codecs = {{0, {"OPUS", 48000, 2}}};
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"ISAC", 32000, 1}}};
   receiver_->SetCodecs(codecs);
 
   constexpr int kOutSampleRateHz = 8000;  // Different than codec sample rate.
@@ -235,6 +233,15 @@
 }
 
 #if defined(WEBRTC_ANDROID)
+#define MAYBE_VerifyAudioFrameISAC DISABLED_VerifyAudioFrameISAC
+#else
+#define MAYBE_VerifyAudioFrameISAC VerifyAudioFrameISAC
+#endif
+TEST_F(AcmReceiverTestFaxModeOldApi, MAYBE_VerifyAudioFrameISAC) {
+  RunVerifyAudioFrame({"ISAC", 16000, 1});
+}
+
+#if defined(WEBRTC_ANDROID)
 #define MAYBE_VerifyAudioFrameOpus DISABLED_VerifyAudioFrameOpus
 #else
 #define MAYBE_VerifyAudioFrameOpus VerifyAudioFrameOpus
@@ -303,10 +310,12 @@
 #else
 #define MAYBE_LastAudioCodec LastAudioCodec
 #endif
-#if defined(WEBRTC_CODEC_OPUS)
+#if defined(WEBRTC_CODEC_ISAC)
 TEST_F(AcmReceiverTestOldApi, MAYBE_LastAudioCodec) {
-  const std::map<int, SdpAudioFormat> codecs = {
-      {0, {"PCMU", 8000, 1}}, {1, {"PCMA", 8000, 1}}, {2, {"L16", 32000, 1}}};
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"PCMA", 8000, 1}},
+                                                {2, {"ISAC", 32000, 1}},
+                                                {3, {"L16", 32000, 1}}};
   const std::map<int, int> cng_payload_types = {
       {8000, 100}, {16000, 101}, {32000, 102}};
   {
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index f1eb81c..7e4b764 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -30,6 +30,7 @@
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
@@ -301,6 +302,44 @@
   EXPECT_EQ(AudioFrameType::kAudioFrameSpeech, packet_cb_.last_frame_type());
 }
 
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+// Verifies that the RTP timestamp series is not reset when the codec is
+// changed.
+TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
+  RegisterCodec();  // This registers the default codec.
+  uint32_t expected_ts = input_frame_.timestamp_;
+  int blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
+  // Encode 5 packets of the first codec type.
+  const int kNumPackets1 = 5;
+  for (int j = 0; j < kNumPackets1; ++j) {
+    for (int i = 0; i < blocks_per_packet; ++i) {
+      EXPECT_EQ(j, packet_cb_.num_calls());
+      InsertAudio();
+    }
+    EXPECT_EQ(j + 1, packet_cb_.num_calls());
+    EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
+    expected_ts += pac_size_;
+  }
+
+  // Change codec.
+  audio_format_ = SdpAudioFormat("ISAC", kSampleRateHz, 1);
+  pac_size_ = 480;
+  RegisterCodec();
+  blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
+  // Encode another 5 packets.
+  const int kNumPackets2 = 5;
+  for (int j = 0; j < kNumPackets2; ++j) {
+    for (int i = 0; i < blocks_per_packet; ++i) {
+      EXPECT_EQ(kNumPackets1 + j, packet_cb_.num_calls());
+      InsertAudio();
+    }
+    EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
+    EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
+    expected_ts += pac_size_;
+  }
+}
+#endif
+
 // Introduce this class to set different expectations on the number of encoded
 // bytes. This class expects all encoded packets to be 9 bytes (matching one
 // CNG SID frame) or 0 bytes. This test depends on `input_frame_` containing
@@ -381,7 +420,8 @@
   DoTest(k10MsBlocksPerPacket, kCngPayloadType);
 }
 
-// A multi-threaded test for ACM that uses the PCM16b 16 kHz codec.
+// A multi-threaded test for ACM. This base class is using the PCM16b 16 kHz
+// codec, while the derive class AcmIsacMtTest is using iSAC.
 class AudioCodingModuleMtTestOldApi : public AudioCodingModuleTestOldApi {
  protected:
   static const int kNumPackets = 500;
@@ -520,6 +560,272 @@
   EXPECT_TRUE(RunTest());
 }
 
+// This is a multi-threaded ACM test using iSAC. The test encodes audio
+// from a PCM file. The most recent encoded frame is used as input to the
+// receiving part. Depending on timing, it may happen that the same RTP packet
+// is inserted into the receiver multiple times, but this is a valid use-case,
+// and simplifies the test code a lot.
+class AcmIsacMtTestOldApi : public AudioCodingModuleMtTestOldApi {
+ protected:
+  static const int kNumPackets = 500;
+  static const int kNumPullCalls = 500;
+
+  AcmIsacMtTestOldApi()
+      : AudioCodingModuleMtTestOldApi(), last_packet_number_(0) {}
+
+  ~AcmIsacMtTestOldApi() {}
+
+  void SetUp() override {
+    AudioCodingModuleTestOldApi::SetUp();
+    RegisterCodec();  // Must be called before the threads start below.
+
+    // Set up input audio source to read from specified file, loop after 5
+    // seconds, and deliver blocks of 10 ms.
+    const std::string input_file_name =
+        webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
+    audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
+
+    // Generate one packet to have something to insert.
+    int loop_counter = 0;
+    while (packet_cb_.last_payload_len_bytes() == 0) {
+      InsertAudio();
+      ASSERT_LT(loop_counter++, 10);
+    }
+    // Set `last_packet_number_` to one less that `num_calls` so that the packet
+    // will be fetched in the next InsertPacket() call.
+    last_packet_number_ = packet_cb_.num_calls() - 1;
+
+    StartThreads();
+  }
+
+  void RegisterCodec() override {
+    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
+    audio_format_ = SdpAudioFormat("isac", kSampleRateHz, 1);
+    pac_size_ = 480;
+
+    // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
+    // registered in AudioCodingModuleTestOldApi::SetUp();
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_}});
+    acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
+        kPayloadType, *audio_format_, absl::nullopt));
+  }
+
+  void InsertPacket() override {
+    int num_calls = packet_cb_.num_calls();  // Store locally for thread safety.
+    if (num_calls > last_packet_number_) {
+      // Get the new payload out from the callback handler.
+      // Note that since we swap buffers here instead of directly inserting
+      // a pointer to the data in `packet_cb_`, we avoid locking the callback
+      // for the duration of the IncomingPacket() call.
+      packet_cb_.SwapBuffers(&last_payload_vec_);
+      ASSERT_GT(last_payload_vec_.size(), 0u);
+      rtp_utility_->Forward(&rtp_header_);
+      last_packet_number_ = num_calls;
+    }
+    ASSERT_GT(last_payload_vec_.size(), 0u);
+    ASSERT_EQ(0, acm_->IncomingPacket(&last_payload_vec_[0],
+                                      last_payload_vec_.size(), rtp_header_));
+  }
+
+  void InsertAudio() override {
+    // TODO(kwiberg): Use std::copy here. Might be complications because AFAICS
+    // this call confuses the number of samples with the number of bytes, and
+    // ends up copying only half of what it should.
+    memcpy(input_frame_.mutable_data(), audio_loop_.GetNextBlock().data(),
+           kNumSamples10ms);
+    AudioCodingModuleTestOldApi::InsertAudio();
+  }
+
+  // Override the verification function with no-op, since iSAC produces variable
+  // payload sizes.
+  void VerifyEncoding() override {}
+
+  // This method is the same as AudioCodingModuleMtTestOldApi::TestDone(), but
+  // here it is using the constants defined in this class (i.e., shorter test
+  // run).
+  bool TestDone() override {
+    if (packet_cb_.num_calls() > kNumPackets) {
+      MutexLock lock(&mutex_);
+      if (pull_audio_count_ > kNumPullCalls) {
+        // Both conditions for completion are met. End the test.
+        return true;
+      }
+    }
+    return false;
+  }
+
+  int last_packet_number_;
+  std::vector<uint8_t> last_payload_vec_;
+  test::AudioLoop audio_loop_;
+};
+
+#if defined(WEBRTC_IOS)
+#define MAYBE_DoTest DISABLED_DoTest
+#else
+#define MAYBE_DoTest DoTest
+#endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+TEST_F(AcmIsacMtTestOldApi, MAYBE_DoTest) {
+  EXPECT_TRUE(RunTest());
+}
+#endif
+
+class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi {
+ protected:
+  static const int kRegisterAfterNumPackets = 5;
+  static const int kNumPackets = 10;
+  static const int kPacketSizeMs = 30;
+  static const int kPacketSizeSamples = kPacketSizeMs * 16;
+
+  AcmReRegisterIsacMtTestOldApi()
+      : AudioCodingModuleTestOldApi(),
+        codec_registered_(false),
+        receive_packet_count_(0),
+        next_insert_packet_time_ms_(0),
+        fake_clock_(new SimulatedClock(0)) {
+    AudioEncoderIsacFloatImpl::Config config;
+    config.payload_type = kPayloadType;
+    isac_encoder_.reset(new AudioEncoderIsacFloatImpl(config));
+    clock_ = fake_clock_.get();
+  }
+
+  void SetUp() override {
+    AudioCodingModuleTestOldApi::SetUp();
+    // Set up input audio source to read from specified file, loop after 5
+    // seconds, and deliver blocks of 10 ms.
+    const std::string input_file_name =
+        webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
+    audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
+    RegisterCodec();  // Must be called before the threads start below.
+    StartThreads();
+  }
+
+  void RegisterCodec() override {
+    // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
+    // registered in AudioCodingModuleTestOldApi::SetUp();
+    // Only register the decoder for now. The encoder is registered later.
+    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
+    acm_->SetReceiveCodecs({{kPayloadType, {"ISAC", kSampleRateHz, 1}}});
+  }
+
+  void StartThreads() {
+    quit_.store(false);
+    const auto attributes =
+        rtc::ThreadAttributes().SetPriority(rtc::ThreadPriority::kRealtime);
+    receive_thread_ = rtc::PlatformThread::SpawnJoinable(
+        [this] {
+          while (!quit_.load() && CbReceiveImpl()) {
+          }
+        },
+        "receive", attributes);
+    codec_registration_thread_ = rtc::PlatformThread::SpawnJoinable(
+        [this] {
+          while (!quit_.load()) {
+            CbCodecRegistrationImpl();
+          }
+        },
+        "codec_registration", attributes);
+  }
+
+  void TearDown() override {
+    AudioCodingModuleTestOldApi::TearDown();
+    quit_.store(true);
+    receive_thread_.Finalize();
+    codec_registration_thread_.Finalize();
+  }
+
+  bool RunTest() { return test_complete_.Wait(TimeDelta::Minutes(10)); }
+
+  bool CbReceiveImpl() {
+    SleepMs(1);
+    rtc::Buffer encoded;
+    AudioEncoder::EncodedInfo info;
+    {
+      MutexLock lock(&mutex_);
+      if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
+        return true;
+      }
+      next_insert_packet_time_ms_ += kPacketSizeMs;
+      ++receive_packet_count_;
+
+      // Encode new frame.
+      uint32_t input_timestamp = rtp_header_.timestamp;
+      while (info.encoded_bytes == 0) {
+        info = isac_encoder_->Encode(input_timestamp,
+                                     audio_loop_.GetNextBlock(), &encoded);
+        input_timestamp += 160;  // 10 ms at 16 kHz.
+      }
+      EXPECT_EQ(rtp_header_.timestamp + kPacketSizeSamples, input_timestamp);
+      EXPECT_EQ(rtp_header_.timestamp, info.encoded_timestamp);
+      EXPECT_EQ(rtp_header_.payloadType, info.payload_type);
+    }
+    // Now we're not holding the crit sect when calling ACM.
+
+    // Insert into ACM.
+    EXPECT_EQ(0, acm_->IncomingPacket(encoded.data(), info.encoded_bytes,
+                                      rtp_header_));
+
+    // Pull audio.
+    for (int i = 0; i < rtc::CheckedDivExact(kPacketSizeMs, 10); ++i) {
+      AudioFrame audio_frame;
+      bool muted;
+      EXPECT_EQ(0, acm_->PlayoutData10Ms(-1 /* default output frequency */,
+                                         &audio_frame, &muted));
+      if (muted) {
+        ADD_FAILURE();
+        return false;
+      }
+      fake_clock_->AdvanceTimeMilliseconds(10);
+    }
+    rtp_utility_->Forward(&rtp_header_);
+    return true;
+  }
+
+  void CbCodecRegistrationImpl() {
+    SleepMs(1);
+    if (HasFatalFailure()) {
+      // End the test early if a fatal failure (ASSERT_*) has occurred.
+      test_complete_.Set();
+    }
+    MutexLock lock(&mutex_);
+    if (!codec_registered_ &&
+        receive_packet_count_ > kRegisterAfterNumPackets) {
+      // Register the iSAC encoder.
+      acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
+          kPayloadType, *audio_format_, absl::nullopt));
+      codec_registered_ = true;
+    }
+    if (codec_registered_ && receive_packet_count_ > kNumPackets) {
+      test_complete_.Set();
+    }
+  }
+
+  rtc::PlatformThread receive_thread_;
+  rtc::PlatformThread codec_registration_thread_;
+  // Used to force worker threads to stop looping.
+  std::atomic<bool> quit_;
+
+  rtc::Event test_complete_;
+  Mutex mutex_;
+  bool codec_registered_ RTC_GUARDED_BY(mutex_);
+  int receive_packet_count_ RTC_GUARDED_BY(mutex_);
+  int64_t next_insert_packet_time_ms_ RTC_GUARDED_BY(mutex_);
+  std::unique_ptr<AudioEncoderIsacFloatImpl> isac_encoder_;
+  std::unique_ptr<SimulatedClock> fake_clock_;
+  test::AudioLoop audio_loop_;
+};
+
+#if defined(WEBRTC_IOS)
+#define MAYBE_DoTest DISABLED_DoTest
+#else
+#define MAYBE_DoTest DoTest
+#endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+TEST_F(AcmReRegisterIsacMtTestOldApi, MAYBE_DoTest) {
+  EXPECT_TRUE(RunTest());
+}
+#endif
+
 // Disabling all of these tests on iOS until file support has been added.
 // See https://code.google.com/p/webrtc/issues/detail?id=4752 for details.
 #if !defined(WEBRTC_IOS)
@@ -719,6 +1025,38 @@
 
 class AcmSenderBitExactnessNewApi : public AcmSenderBitExactnessOldApi {};
 
+// Run bit exactness tests only for release builds.
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
+    defined(NDEBUG) && defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64)
+TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
+  ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480));
+  Run(/*audio_checksum_ref=*/"37ecdabad1698a857cf811e6d1fa91df",
+      /*payload_checksum_ref=*/"3c79f16f34218271f3dca4e2b1dfe1bb",
+      /*expected_packets=*/33,
+      /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput);
+}
+
+TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
+  ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
+  Run(/*audio_checksum_ref=*/"0e9078d23454901496a88362ba0740c3",
+      /*payload_checksum_ref=*/"9e0a0ab743ad987b55b8e14802769c56",
+      /*expected_packets=*/16,
+      /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput);
+}
+#endif
+
+// Run bit exactness test only for release build.
+#if defined(WEBRTC_CODEC_ISAC) && defined(NDEBUG) && defined(WEBRTC_LINUX) && \
+    defined(WEBRTC_ARCH_X86_64)
+TEST_F(AcmSenderBitExactnessOldApi, IsacSwb30ms) {
+  ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 32000, 1, 104, 960, 960));
+  Run(/*audio_checksum_ref=*/"f4cf577f28a0dcbac33358b757518e0c",
+      /*payload_checksum_ref=*/"ce86106a93419aefb063097108ec94ab",
+      /*expected_packets=*/33,
+      /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput);
+}
+#endif
+
 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
   Run(/*audio_checksum_ref=*/"69118ed438ac76252d023e0463819471",
diff --git a/modules/audio_coding/audio_coding.gni b/modules/audio_coding/audio_coding.gni
index 3b14709..bf67d9c 100644
--- a/modules/audio_coding/audio_coding.gni
+++ b/modules/audio_coding/audio_coding.gni
@@ -20,6 +20,11 @@
 } else {
   audio_codec_defines += [ "WEBRTC_OPUS_SUPPORT_120MS_PTIME=0" ]
 }
+if (current_cpu == "arm") {
+  audio_codec_defines += [ "WEBRTC_CODEC_ISACFX" ]
+} else {
+  audio_codec_defines += [ "WEBRTC_CODEC_ISAC" ]
+}
 
 audio_coding_defines = audio_codec_defines
 neteq_defines = audio_codec_defines
diff --git a/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc b/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc
index 4a2b261..109da78 100644
--- a/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc
+++ b/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc
@@ -75,6 +75,31 @@
       adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 16000, 1), absl::nullopt));
 }
 
+TEST(AudioDecoderFactoryTest, CreateIsac) {
+  rtc::scoped_refptr<AudioDecoderFactory> adf =
+      CreateBuiltinAudioDecoderFactory();
+  ASSERT_TRUE(adf);
+  // iSAC supports 16 kHz, 1 channel. The float implementation additionally
+  // supports 32 kHz, 1 channel.
+  EXPECT_FALSE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 0), absl::nullopt));
+  EXPECT_TRUE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 1), absl::nullopt));
+  EXPECT_FALSE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 2), absl::nullopt));
+  EXPECT_FALSE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 8000, 1), absl::nullopt));
+  EXPECT_FALSE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 48000, 1), absl::nullopt));
+#ifdef WEBRTC_ARCH_ARM
+  EXPECT_FALSE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
+#else
+  EXPECT_TRUE(
+      adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
+#endif
+}
+
 TEST(AudioDecoderFactoryTest, CreateL16) {
   rtc::scoped_refptr<AudioDecoderFactory> adf =
       CreateBuiltinAudioDecoderFactory();
@@ -100,6 +125,9 @@
 #ifdef WEBRTC_CODEC_OPUS
     "opus",
 #endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+    "isac",
+#endif
 #ifdef WEBRTC_CODEC_ILBC
     "ilbc",
 #endif
diff --git a/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
new file mode 100644
index 0000000..aae708f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_decoder.h"
+#include "api/scoped_refptr.h"
+
+namespace webrtc {
+
+template <typename T>
+class AudioDecoderIsacT final : public AudioDecoder {
+ public:
+  struct Config {
+    bool IsOk() const;
+    int sample_rate_hz = 16000;
+  };
+  explicit AudioDecoderIsacT(const Config& config);
+  virtual ~AudioDecoderIsacT() override;
+
+  AudioDecoderIsacT(const AudioDecoderIsacT&) = delete;
+  AudioDecoderIsacT& operator=(const AudioDecoderIsacT&) = delete;
+
+  bool HasDecodePlc() const override;
+  size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
+  void Reset() override;
+  int ErrorCode() override;
+  int SampleRateHz() const override;
+  size_t Channels() const override;
+  int DecodeInternal(const uint8_t* encoded,
+                     size_t encoded_len,
+                     int sample_rate_hz,
+                     int16_t* decoded,
+                     SpeechType* speech_type) override;
+
+ private:
+  typename T::instance_type* isac_state_;
+  int sample_rate_hz_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
diff --git a/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h b/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h
new file mode 100644
index 0000000..9aa4988
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+template <typename T>
+bool AudioDecoderIsacT<T>::Config::IsOk() const {
+  return (sample_rate_hz == 16000 || sample_rate_hz == 32000);
+}
+
+template <typename T>
+AudioDecoderIsacT<T>::AudioDecoderIsacT(const Config& config)
+    : sample_rate_hz_(config.sample_rate_hz) {
+  RTC_CHECK(config.IsOk()) << "Unsupported sample rate "
+                           << config.sample_rate_hz;
+  RTC_CHECK_EQ(0, T::Create(&isac_state_));
+  T::DecoderInit(isac_state_);
+  RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz_));
+}
+
+template <typename T>
+AudioDecoderIsacT<T>::~AudioDecoderIsacT() {
+  RTC_CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
+                                         size_t encoded_len,
+                                         int sample_rate_hz,
+                                         int16_t* decoded,
+                                         SpeechType* speech_type) {
+  RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz);
+  int16_t temp_type = 1;  // Default is speech.
+  int ret =
+      T::DecodeInternal(isac_state_, encoded, encoded_len, decoded, &temp_type);
+  *speech_type = ConvertSpeechType(temp_type);
+  return ret;
+}
+
+template <typename T>
+bool AudioDecoderIsacT<T>::HasDecodePlc() const {
+  return false;
+}
+
+template <typename T>
+size_t AudioDecoderIsacT<T>::DecodePlc(size_t num_frames, int16_t* decoded) {
+  return T::DecodePlc(isac_state_, decoded, num_frames);
+}
+
+template <typename T>
+void AudioDecoderIsacT<T>::Reset() {
+  T::DecoderInit(isac_state_);
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::ErrorCode() {
+  return T::GetErrorCode(isac_state_);
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::SampleRateHz() const {
+  return sample_rate_hz_;
+}
+
+template <typename T>
+size_t AudioDecoderIsacT<T>::Channels() const {
+  return 1;
+}
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
new file mode 100644
index 0000000..c382ea0
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -0,0 +1,108 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
+
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/scoped_refptr.h"
+#include "api/units/time_delta.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+template <typename T>
+class AudioEncoderIsacT final : public AudioEncoder {
+ public:
+  // Allowed combinations of sample rate, frame size, and bit rate are
+  //  - 16000 Hz, 30 ms, 10000-32000 bps
+  //  - 16000 Hz, 60 ms, 10000-32000 bps
+  //  - 32000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
+  struct Config {
+    bool IsOk() const;
+    int payload_type = 103;
+    int sample_rate_hz = 16000;
+    int frame_size_ms = 30;
+    int bit_rate = kDefaultBitRate;  // Limit on the short-term average bit
+                                     // rate, in bits/s.
+    int max_payload_size_bytes = -1;
+    int max_bit_rate = -1;
+  };
+
+  explicit AudioEncoderIsacT(const Config& config);
+  ~AudioEncoderIsacT() override;
+
+  AudioEncoderIsacT(const AudioEncoderIsacT&) = delete;
+  AudioEncoderIsacT& operator=(const AudioEncoderIsacT&) = delete;
+
+  int SampleRateHz() const override;
+  size_t NumChannels() const override;
+  size_t Num10MsFramesInNextPacket() const override;
+  size_t Max10MsFramesInAPacket() const override;
+  int GetTargetBitrate() const override;
+  void SetTargetBitrate(int target_bps) override;
+  void OnReceivedTargetAudioBitrate(int target_bps) override;
+  void OnReceivedUplinkBandwidth(
+      int target_audio_bitrate_bps,
+      absl::optional<int64_t> bwe_period_ms) override;
+  void OnReceivedUplinkAllocation(BitrateAllocationUpdate update) override;
+  void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
+  EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+                         rtc::ArrayView<const int16_t> audio,
+                         rtc::Buffer* encoded) override;
+  void Reset() override;
+  absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+      const override;
+
+ private:
+  // This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
+  // STREAM_MAXW16_60MS for iSAC fix (60 ms).
+  static const size_t kSufficientEncodeBufferSizeBytes = 400;
+
+  static constexpr int kDefaultBitRate = 32000;
+  static constexpr int kMinBitrateBps = 10000;
+  static constexpr int MaxBitrateBps(int sample_rate_hz) {
+    return sample_rate_hz == 32000 ? 56000 : 32000;
+  }
+
+  void SetTargetBitrate(int target_bps, bool subtract_per_packet_overhead);
+
+  // Recreate the iSAC encoder instance with the given settings, and save them.
+  void RecreateEncoderInstance(const Config& config);
+
+  Config config_;
+  typename T::instance_type* isac_state_ = nullptr;
+
+  // Have we accepted input but not yet emitted it in a packet?
+  bool packet_in_progress_ = false;
+
+  // Timestamp of the first input of the currently in-progress packet.
+  uint32_t packet_timestamp_;
+
+  // Timestamp of the previously encoded packet.
+  uint32_t last_encoded_timestamp_;
+
+  // Cache the value of the "WebRTC-SendSideBwe-WithOverhead" field trial.
+  const bool send_side_bwe_with_overhead_ =
+      !field_trial::IsDisabled("WebRTC-SendSideBwe-WithOverhead");
+
+  // When we send a packet, expect this many bytes of headers to be added to it.
+  // Start out with a reasonable default that we can use until we receive a real
+  // value.
+  DataSize overhead_per_packet_ = DataSize::Bytes(28);
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
new file mode 100644
index 0000000..1bd27cf
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -0,0 +1,225 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_minmax.h"
+
+namespace webrtc {
+
+template <typename T>
+bool AudioEncoderIsacT<T>::Config::IsOk() const {
+  if (max_bit_rate < 32000 && max_bit_rate != -1)
+    return false;
+  if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
+    return false;
+
+  switch (sample_rate_hz) {
+    case 16000:
+      if (max_bit_rate > 53400)
+        return false;
+      if (max_payload_size_bytes > 400)
+        return false;
+      return (frame_size_ms == 30 || frame_size_ms == 60) &&
+             (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000));
+    case 32000:
+      if (max_bit_rate > 160000)
+        return false;
+      if (max_payload_size_bytes > 600)
+        return false;
+      return T::has_swb &&
+             (frame_size_ms == 30 &&
+              (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000)));
+    default:
+      return false;
+  }
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
+  RecreateEncoderInstance(config);
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
+  RTC_CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::SampleRateHz() const {
+  return T::EncSampRate(isac_state_);
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::NumChannels() const {
+  return 1;
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
+  const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
+  return static_cast<size_t>(rtc::CheckedDivExact(
+      samples_in_next_packet, rtc::CheckedDivExact(SampleRateHz(), 100)));
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
+  return 6;  // iSAC puts at most 60 ms in a packet.
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::GetTargetBitrate() const {
+  return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::SetTargetBitrate(int target_bps) {
+  // Set target bitrate directly without subtracting per-packet overhead,
+  // because that's what AudioEncoderOpus does.
+  SetTargetBitrate(target_bps,
+                   /*subtract_per_packet_overhead=*/false);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedTargetAudioBitrate(int target_bps) {
+  // Set target bitrate directly without subtracting per-packet overhead,
+  // because that's what AudioEncoderOpus does.
+  SetTargetBitrate(target_bps,
+                   /*subtract_per_packet_overhead=*/false);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedUplinkBandwidth(
+    int target_audio_bitrate_bps,
+    absl::optional<int64_t> /*bwe_period_ms*/) {
+  // Set target bitrate, subtracting the per-packet overhead if
+  // WebRTC-SendSideBwe-WithOverhead is enabled, because that's what
+  // AudioEncoderOpus does.
+  SetTargetBitrate(
+      target_audio_bitrate_bps,
+      /*subtract_per_packet_overhead=*/send_side_bwe_with_overhead_);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedUplinkAllocation(
+    BitrateAllocationUpdate update) {
+  // Set target bitrate, subtracting the per-packet overhead if
+  // WebRTC-SendSideBwe-WithOverhead is enabled, because that's what
+  // AudioEncoderOpus does.
+  SetTargetBitrate(
+      update.target_bitrate.bps<int>(),
+      /*subtract_per_packet_overhead=*/send_side_bwe_with_overhead_);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedOverhead(
+    size_t overhead_bytes_per_packet) {
+  overhead_per_packet_ = DataSize::Bytes(overhead_bytes_per_packet);
+}
+
+template <typename T>
+AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeImpl(
+    uint32_t rtp_timestamp,
+    rtc::ArrayView<const int16_t> audio,
+    rtc::Buffer* encoded) {
+  if (!packet_in_progress_) {
+    // Starting a new packet; remember the timestamp for later.
+    packet_in_progress_ = true;
+    packet_timestamp_ = rtp_timestamp;
+  }
+  size_t encoded_bytes = encoded->AppendData(
+      kSufficientEncodeBufferSizeBytes, [&](rtc::ArrayView<uint8_t> encoded) {
+        int r = T::Encode(isac_state_, audio.data(), encoded.data());
+
+        if (T::GetErrorCode(isac_state_) == 6450) {
+          // Isac is not able to effectively compress all types of signals. This
+          // is a limitation of the codec that cannot be easily fixed.
+          r = 0;
+        }
+        RTC_CHECK_GE(r, 0) << "Encode failed (error code "
+                           << T::GetErrorCode(isac_state_) << ")";
+
+        return static_cast<size_t>(r);
+      });
+
+  if (encoded_bytes == 0)
+    return EncodedInfo();
+
+  // Got enough input to produce a packet. Return the saved timestamp from
+  // the first chunk of input that went into the packet.
+  packet_in_progress_ = false;
+  EncodedInfo info;
+  info.encoded_bytes = encoded_bytes;
+  info.encoded_timestamp = packet_timestamp_;
+  info.payload_type = config_.payload_type;
+  info.encoder_type = CodecType::kIsac;
+  return info;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::Reset() {
+  RecreateEncoderInstance(config_);
+}
+
+template <typename T>
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderIsacT<T>::GetFrameLengthRange() const {
+  return {{TimeDelta::Millis(config_.frame_size_ms),
+           TimeDelta::Millis(config_.frame_size_ms)}};
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::SetTargetBitrate(int target_bps,
+                                            bool subtract_per_packet_overhead) {
+  if (subtract_per_packet_overhead) {
+    const DataRate overhead_rate =
+        overhead_per_packet_ / TimeDelta::Millis(config_.frame_size_ms);
+    target_bps -= overhead_rate.bps();
+  }
+  target_bps = rtc::SafeClamp(target_bps, kMinBitrateBps,
+                              MaxBitrateBps(config_.sample_rate_hz));
+  int result = T::Control(isac_state_, target_bps, config_.frame_size_ms);
+  RTC_DCHECK_EQ(result, 0);
+  config_.bit_rate = target_bps;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
+  RTC_CHECK(config.IsOk());
+  packet_in_progress_ = false;
+  if (isac_state_)
+    RTC_CHECK_EQ(0, T::Free(isac_state_));
+  RTC_CHECK_EQ(0, T::Create(&isac_state_));
+  RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, /*coding_mode=*/1));
+  RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
+  const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
+  RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
+
+  if (config.max_payload_size_bytes != -1)
+    RTC_CHECK_EQ(
+        0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
+  if (config.max_bit_rate != -1)
+    RTC_CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
+
+  // Set the decoder sample rate even though we just use the encoder. This
+  // doesn't appear to be necessary to produce a valid encoding, but without it
+  // we get an encoding that isn't bit-for-bit identical with what a combined
+  // encoder+decoder object produces.
+  RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
+
+  config_ = config;
+}
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
diff --git a/modules/audio_coding/codecs/isac/empty.cc b/modules/audio_coding/codecs/isac/empty.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/empty.cc
diff --git a/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h b/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h
new file mode 100644
index 0000000..0b4eadd
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h"
+
+namespace webrtc {
+
+using AudioDecoderIsacFixImpl = AudioDecoderIsacT<IsacFix>;
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
diff --git a/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h b/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h
new file mode 100644
index 0000000..f0cc038
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h"
+
+namespace webrtc {
+
+using AudioEncoderIsacFixImpl = AudioEncoderIsacT<IsacFix>;
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
diff --git a/modules/audio_coding/codecs/isac/fix/include/isacfix.h b/modules/audio_coding/codecs/isac/fix/include/isacfix.h
new file mode 100644
index 0000000..dcc7b09
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/include/isacfix.h
@@ -0,0 +1,486 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+
+typedef struct {
+  void* dummy;
+} ISACFIX_MainStruct;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcIsacfix_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ *      - *ISAC_main_inst   : a pointer to the coder instance.
+ *
+ * Return value             : 0 - Ok
+ *                           -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Create(ISACFIX_MainStruct** ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ *      - ISAC_main_inst    : a ISAC instance.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Free(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ *     - ISAC_main_inst     : ISAC instance.
+ *     - CodingMode         : 0 - Bit rate and frame length are automatically
+ *                                adjusted to available bandwidth on
+ *                                transmission channel.
+ *                            1 - User sets a frame length and a target bit
+ *                                rate which is taken as the maximum short-term
+ *                                average bit rate.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct* ISAC_main_inst,
+                                  int16_t CodingMode);
+
+/****************************************************************************
+ * WebRtcIsacfix_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - speechIn          : input speech vector.
+ *
+ * Output:
+ *      - encoded           : the encoded data vector
+ *
+ * Return value             : >0 - Length (in bytes) of coded data
+ *                             0 - The buffer didn't reach the chosen framesize
+ *                                 so it keeps buffering speech samples.
+ *                            -1 - Error
+ */
+
+int WebRtcIsacfix_Encode(ISACFIX_MainStruct* ISAC_main_inst,
+                         const int16_t* speechIn,
+                         uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ *  - ISAC_main_inst : ISAC instance.
+ */
+
+void WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s).
+ *      - packet_size       : size of the packet in bytes.
+ *      - rtp_seq_number    : the RTP number of the packet.
+ *      - arr_ts            : the arrival time of the packet (from NetEq)
+ *                            in samples.
+ *
+ * Return value             : 0 - Ok
+ *                           -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct* ISAC_main_inst,
+                                        const uint8_t* encoded,
+                                        size_t packet_size,
+                                        uint16_t rtp_seq_number,
+                                        uint32_t arr_ts);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s).
+ *      - packet_size       : size of the packet in bytes.
+ *      - rtp_seq_number    : the RTP number of the packet.
+ *      - send_ts           : the send time of the packet from RTP header,
+ *                            in samples.
+ *      - arr_ts            : the arrival time of the packet (from NetEq)
+ *                            in samples.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct* ISAC_main_inst,
+                                       const uint8_t* encoded,
+                                       size_t packet_size,
+                                       uint16_t rtp_seq_number,
+                                       uint32_t send_ts,
+                                       uint32_t arr_ts);
+
+/****************************************************************************
+ * WebRtcIsacfix_Decode(...)
+ *
+ * This function decodes an ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s)
+ *      - len               : bytes in encoded vector
+ *
+ * Output:
+ *      - decoded           : The decoded vector
+ *
+ * Return value             : >0 - number of samples in decoded vector
+ *                            -1 - Error
+ */
+
+int WebRtcIsacfix_Decode(ISACFIX_MainStruct* ISAC_main_inst,
+                         const uint8_t* encoded,
+                         size_t len,
+                         int16_t* decoded,
+                         int16_t* speechType);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length  will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - noOfLostFrames    : Number of PLC frames (480sample = 30ms)
+ *                            to produce
+ *                            NOTE! Maximum number is 2 (960 samples = 60ms)
+ *
+ * Output:
+ *      - decoded           : The decoded vector
+ *
+ * Return value             : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct* ISAC_main_inst,
+                               int16_t* decoded,
+                               size_t noOfLostFrames);
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ *      - encoded           : Encoded bitstream
+ *      - encoded_len_bytes : Length of the bitstream in bytes.
+ *
+ * Output:
+ *      - frameLength       : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadFrameLen(const uint8_t* encoded,
+                                   size_t encoded_len_bytes,
+                                   size_t* frameLength);
+
+/****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - rate              : limit on the short-term average bit rate,
+ *                            in bits/second (between 10000 and 32000)
+ *      - framesize         : number of milliseconds per frame (30 or 60)
+ *
+ * Return value             : 0  - ok
+ *                           -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct* ISAC_main_inst,
+                              int16_t rate,
+                              int framesize);
+
+void WebRtcIsacfix_SetInitialBweBottleneck(ISACFIX_MainStruct* ISAC_main_inst,
+                                           int bottleneck_bits_per_second);
+
+/****************************************************************************
+ * WebRtcIsacfix_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - rateBPS           : initial value of bottleneck in bits/second
+ *                            10000 <= rateBPS <= 32000 is accepted
+ *      - frameSizeMs       : number of milliseconds per frame (30 or 60)
+ *      - enforceFrameSize  : 1 to enforce the given frame-size through out
+ *                            the adaptation process, 0 to let iSAC change
+ *                            the frame-size if required.
+ *
+ * Return value             : 0  - ok
+ *                           -1 - Error
+ */
+
+int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct* ISAC_main_inst,
+                                 int16_t rateBPS,
+                                 int frameSizeMs,
+                                 int16_t enforceFrameSize);
+
+/****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ *      - version      : Pointer to character string
+ *
+ */
+
+void WebRtcIsacfix_version(char* version);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occured in the
+ * specified instance.
+ *
+ * Input:
+ *  - ISAC_main_inst        : ISAC instance
+ *
+ * Return value             : Error code
+ */
+
+int16_t WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function return iSAC send bitrate
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *
+ * Return value             : <0 Error code
+ *                            else bitrate
+ */
+
+int32_t WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *      - maxPayloadBytes   : maximum size of the payload in bytes
+ *                            valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value             : 0 if sucessful
+ *                           -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct* ISAC_main_inst,
+                                        int16_t maxPayloadBytes);
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *      - maxRateInBytes    : maximum rate in bits per second,
+ *                            valid values are 32000 to 53400 bits
+ *
+ * Return value             : 0 if sucessful
+ *                           -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct* ISAC_main_inst,
+                                 int32_t maxRate);
+
+/****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ *      - *ISAC_main_inst   : a pointer to the coder instance.
+ *
+ * Return value             : 0 - Ok
+ *                           -1 - Error
+ */
+
+int16_t WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ *      - ISAC_main_inst        : an ISAC instance.
+ *
+ * Return value                 :  0 - Ok
+ *                                -1 - Error
+ */
+
+int16_t WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - bweIndex          : index of bandwidth estimate to put in new
+ * bitstream - scale             : factor for rate change (0.4 ~=> half the
+ * rate, 1 no change).
+ *
+ * Output:
+ *      - encoded           : the encoded data vector
+ *
+ * Return value             : >0 - Length (in bytes) of coded data
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct* ISAC_main_inst,
+                                      int16_t bweIndex,
+                                      float scale,
+                                      uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC struct
+ *
+ * Output:
+ *      - rateIndex         : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+                                         int16_t* rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC struct
+ *      - rateIndex         : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+                                     int16_t rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ *      - encoded           : Encoded bitstream
+ *      - encoded_len_bytes : Length of the bitstream in bytes.
+ *
+ * Output:
+ *      - rateIndex         : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadBwIndex(const uint8_t* encoded,
+                                  size_t encoded_len_bytes,
+                                  int16_t* rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ *      -ISAC_main_inst     : iSAC instance
+ *
+ * Return value             : frame lenght in samples
+ */
+
+int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct* ISAC_main_inst);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/arith_routines.c b/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
new file mode 100644
index 0000000..eaeef50
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routins.c
+ *
+ * This C file contains a function for finalizing the bitstream
+ * after arithmetic coding.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *
+ * Return value             : number of bytes in the stream
+ */
+int16_t WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData)
+{
+  uint16_t *streamPtr;
+  uint16_t negCarry;
+
+  /* point to the right place in the stream buffer */
+  streamPtr = streamData->stream + streamData->stream_index;
+
+  /* find minimum length (determined by current interval width) */
+  if ( streamData->W_upper > 0x01FFFFFF )
+  {
+    streamData->streamval += 0x01000000;
+
+    /* if result is less than the added value we must take care of the carry */
+    if (streamData->streamval < 0x01000000)
+    {
+      /* propagate carry */
+      if (streamData->full == 0) {
+        /* Add value to current value */
+        negCarry = *streamPtr;
+        negCarry += 0x0100;
+        *streamPtr = negCarry;
+
+        /* if value is too big, propagate carry to next byte, and so on */
+        while (!(negCarry))
+        {
+          negCarry = *--streamPtr;
+          negCarry++;
+          *streamPtr = negCarry;
+        }
+      } else {
+        /* propagate carry by adding one to the previous byte in the
+         * stream if that byte is 0xFFFF we need to propagate the carry
+         * furhter back in the stream */
+        while ( !(++(*--streamPtr)) );
+      }
+
+      /* put pointer back to the old value */
+      streamPtr = streamData->stream + streamData->stream_index;
+    }
+    /* write remaining data to bitstream, if "full == 0" first byte has data */
+    if (streamData->full == 0) {
+      *streamPtr++ += (uint16_t)(streamData->streamval >> 24);
+      streamData->full = 1;
+    } else {
+      *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+      streamData->full = 0;
+    }
+  }
+  else
+  {
+    streamData->streamval += 0x00010000;
+
+    /* if result is less than the added value we must take care of the carry */
+    if (streamData->streamval < 0x00010000)
+    {
+      /* propagate carry */
+      if (streamData->full == 0) {
+        /* Add value to current value */
+        negCarry = *streamPtr;
+        negCarry += 0x0100;
+        *streamPtr = negCarry;
+
+        /* if value to big, propagate carry to next byte, and so on */
+        while (!(negCarry))
+        {
+          negCarry = *--streamPtr;
+          negCarry++;
+          *streamPtr = negCarry;
+        }
+      } else {
+        /* Add carry to previous byte */
+        while ( !(++(*--streamPtr)) );
+      }
+
+      /* put pointer back to the old value */
+      streamPtr = streamData->stream + streamData->stream_index;
+    }
+    /* write remaining data (2 bytes) to bitstream */
+    if (streamData->full) {
+      *streamPtr++ = (uint16_t)(streamData->streamval >> 16);
+    } else {
+      *streamPtr++ |= (uint16_t)(streamData->streamval >> 24);
+      *streamPtr = (uint16_t)(streamData->streamval >> 8) & 0xFF00;
+    }
+  }
+
+  /* calculate stream length in bytes */
+  return (((streamPtr - streamData->stream)<<1) + !(streamData->full));
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c b/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
new file mode 100644
index 0000000..cad3056
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
@@ -0,0 +1,401 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routinshist.c
+ *
+ * This C file contains arithmetic encoding and decoding.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - data              : data vector
+ *      - cdf               : array of cdf arrays
+ *      - lenData           : data vector length
+ *
+ * Return value             : 0 if ok
+ *                            <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
+                               const int16_t *data,
+                               const uint16_t *const *cdf,
+                               const int16_t lenData)
+{
+  uint32_t W_lower;
+  uint32_t W_upper;
+  uint32_t W_upper_LSB;
+  uint32_t W_upper_MSB;
+  uint16_t *streamPtr;
+  uint16_t negCarry;
+  uint16_t *maxStreamPtr;
+  uint16_t *streamPtrCarry;
+  uint32_t cdfLo;
+  uint32_t cdfHi;
+  int k;
+
+
+  /* point to beginning of stream buffer
+   * and set maximum streamPtr value */
+  streamPtr = streamData->stream + streamData->stream_index;
+  maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+
+  W_upper = streamData->W_upper;
+
+  for (k = lenData; k > 0; k--)
+  {
+    /* fetch cdf_lower and cdf_upper from cdf tables */
+    cdfLo = (uint32_t) *(*cdf + (uint32_t)*data);
+    cdfHi = (uint32_t) *(*cdf++ + (uint32_t)*data++ + 1);
+
+    /* update interval */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+    W_lower = WEBRTC_SPL_UMUL(W_upper_MSB, cdfLo);
+    W_lower += ((W_upper_LSB * cdfLo) >> 16);
+    W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
+    W_upper += ((W_upper_LSB * cdfHi) >> 16);
+
+    /* shift interval such that it begins at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamData->streamval += W_lower;
+
+    /* handle carry */
+    if (streamData->streamval < W_lower)
+    {
+      /* propagate carry */
+      streamPtrCarry = streamPtr;
+      if (streamData->full == 0) {
+        negCarry = *streamPtrCarry;
+        negCarry += 0x0100;
+        *streamPtrCarry = negCarry;
+        while (!(negCarry))
+        {
+          negCarry = *--streamPtrCarry;
+          negCarry++;
+          *streamPtrCarry = negCarry;
+        }
+      } else {
+        while ( !(++(*--streamPtrCarry)) );
+      }
+    }
+
+    /* renormalize interval, store most significant byte of streamval and update streamval
+     * W_upper < 2^24 */
+    while ( !(W_upper & 0xFF000000) )
+    {
+      W_upper <<= 8;
+      if (streamData->full == 0) {
+        *streamPtr++ += (uint16_t)(streamData->streamval >> 24);
+        streamData->full = 1;
+      } else {
+        *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+        streamData->full = 0;
+      }
+
+      if( streamPtr > maxStreamPtr ) {
+        return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+      }
+      streamData->streamval <<= 8;
+    }
+  }
+
+  /* calculate new stream_index */
+  streamData->stream_index = streamPtr - streamData->stream;
+  streamData->W_upper = W_upper;
+
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, using
+ * method of bisection cdf tables should be of size 2^k-1 (which corresponds
+ * to an alphabet size of 2^k-2)
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - cdf               : array of cdf arrays
+ *      - cdfSize           : array of cdf table sizes+1 (power of two: 2^k)
+ *      - lenData           : data vector length
+ *
+ * Output:
+ *      - data              : data vector
+ *
+ * Return value             : number of bytes in the stream
+ *                            <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
+                                         Bitstr_dec *streamData,
+                                         const uint16_t *const *cdf,
+                                         const uint16_t *cdfSize,
+                                         const int16_t lenData)
+{
+  uint32_t    W_lower = 0;
+  uint32_t    W_upper;
+  uint32_t    W_tmp;
+  uint32_t    W_upper_LSB;
+  uint32_t    W_upper_MSB;
+  uint32_t    streamval;
+  const uint16_t *streamPtr;
+  const uint16_t *cdfPtr;
+  int16_t     sizeTmp;
+  int             k;
+
+
+  streamPtr = streamData->stream + streamData->stream_index;
+  W_upper = streamData->W_upper;
+
+  /* Error check: should not be possible in normal operation */
+  if (W_upper == 0) {
+    return -2;
+  }
+
+  /* first time decoder is called for this stream */
+  if (streamData->stream_index == 0)
+  {
+    /* read first word from bytestream */
+    streamval = (uint32_t)*streamPtr++ << 16;
+    streamval |= *streamPtr++;
+  } else {
+    streamval = streamData->streamval;
+  }
+
+  for (k = lenData; k > 0; k--)
+  {
+    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+
+    /* start halfway the cdf range */
+    sizeTmp = *cdfSize++ / 2;
+    cdfPtr = *cdf + (sizeTmp - 1);
+
+    /* method of bisection */
+    for ( ;; )
+    {
+      W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+      W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+      sizeTmp /= 2;
+      if (sizeTmp == 0) {
+        break;
+      }
+
+      if (streamval > W_tmp)
+      {
+        W_lower = W_tmp;
+        cdfPtr += sizeTmp;
+      } else {
+        W_upper = W_tmp;
+        cdfPtr -= sizeTmp;
+      }
+    }
+    if (streamval > W_tmp)
+    {
+      W_lower = W_tmp;
+      *data++ = cdfPtr - *cdf++;
+    } else {
+      W_upper = W_tmp;
+      *data++ = cdfPtr - *cdf++ - 1;
+    }
+
+    /* shift interval to start at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamval -= W_lower;
+
+    /* renormalize interval and update streamval */
+    /* W_upper < 2^24 */
+    while ( !(W_upper & 0xFF000000) )
+    {
+      /* read next byte from stream */
+      if (streamData->full == 0) {
+        streamval = (streamval << 8) | (*streamPtr++ & 0x00FF);
+        streamData->full = 1;
+      } else {
+        streamval = (streamval << 8) | (*streamPtr >> 8);
+        streamData->full = 0;
+      }
+      W_upper <<= 8;
+    }
+
+
+    /* Error check: should not be possible in normal operation */
+    if (W_upper == 0) {
+      return -2;
+    }
+
+  }
+
+  streamData->stream_index = streamPtr - streamData->stream;
+  streamData->W_upper = W_upper;
+  streamData->streamval = streamval;
+
+  if ( W_upper > 0x01FFFFFF ) {
+    return (streamData->stream_index*2 - 3 + !streamData->full);
+  } else {
+    return (streamData->stream_index*2 - 2 + !streamData->full);
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, taking
+ * single step up or down at a time.
+ * cdf tables can be of arbitrary size, but large tables may take a lot of
+ * iterations.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - cdf               : array of cdf arrays
+ *      - initIndex         : vector of initial cdf table search entries
+ *      - lenData           : data vector length
+ *
+ * Output:
+ *      - data              : data vector
+ *
+ * Return value             : number of bytes in original stream
+ *                            <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
+                                          Bitstr_dec *streamData,
+                                          const uint16_t *const *cdf,
+                                          const uint16_t *initIndex,
+                                          const int16_t lenData)
+{
+  uint32_t    W_lower;
+  uint32_t    W_upper;
+  uint32_t    W_tmp;
+  uint32_t    W_upper_LSB;
+  uint32_t    W_upper_MSB;
+  uint32_t    streamval;
+  const uint16_t *streamPtr;
+  const uint16_t *cdfPtr;
+  int             k;
+
+
+  streamPtr = streamData->stream + streamData->stream_index;
+  W_upper = streamData->W_upper;
+  /* Error check: Should not be possible in normal operation */
+  if (W_upper == 0) {
+    return -2;
+  }
+
+  /* Check if it is the first time decoder is called for this stream */
+  if (streamData->stream_index == 0)
+  {
+    /* read first word from bytestream */
+    streamval = (uint32_t)(*streamPtr++) << 16;
+    streamval |= *streamPtr++;
+  } else {
+    streamval = streamData->streamval;
+  }
+
+  for (k = lenData; k > 0; k--)
+  {
+    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+    /* start at the specified table entry */
+    cdfPtr = *cdf + (*initIndex++);
+    W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+    W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+    if (streamval > W_tmp)
+    {
+      for ( ;; )
+      {
+        W_lower = W_tmp;
+
+        /* range check */
+        if (cdfPtr[0] == 65535) {
+          return -3;
+        }
+
+        W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
+        W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+        if (streamval <= W_tmp) {
+          break;
+        }
+      }
+      W_upper = W_tmp;
+      *data++ = cdfPtr - *cdf++ - 1;
+    } else {
+      for ( ;; )
+      {
+        W_upper = W_tmp;
+        --cdfPtr;
+
+        /* range check */
+        if (cdfPtr < *cdf) {
+          return -3;
+        }
+
+        W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+        W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+        if (streamval > W_tmp) {
+          break;
+        }
+      }
+      W_lower = W_tmp;
+      *data++ = cdfPtr - *cdf++;
+    }
+
+    /* shift interval to start at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamval -= W_lower;
+
+    /* renormalize interval and update streamval */
+    /* W_upper < 2^24 */
+    while ( !(W_upper & 0xFF000000) )
+    {
+      /* read next byte from stream */
+      if (streamData->full == 0) {
+        streamval = (streamval << 8) | (*streamPtr++ & 0x00FF);
+        streamData->full = 1;
+      } else {
+        streamval = (streamval << 8) | (*streamPtr >> 8);
+        streamData->full = 0;
+      }
+      W_upper <<= 8;
+    }
+  }
+
+  streamData->stream_index = streamPtr - streamData->stream;
+  streamData->W_upper = W_upper;
+  streamData->streamval = streamval;
+
+  /* find number of bytes in original stream (determined by current interval width) */
+  if ( W_upper > 0x01FFFFFF ) {
+    return (streamData->stream_index*2 - 3 + !streamData->full);
+  } else {
+    return (streamData->stream_index*2 - 2 + !streamData->full);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c b/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
new file mode 100644
index 0000000..8e97960
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
@@ -0,0 +1,413 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routinslogist.c
+ *
+ * This C file contains arithmetic encode and decode logistic
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+/* Tables for piecewise linear cdf functions: y = k*x */
+
+/* x Points for function piecewise() in Q15 */
+static const int32_t kHistEdges[51] = {
+  -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+  -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858,  -91751,  -78644,
+  -65536,  -52429,  -39322,  -26215,  -13108,       0,   13107,   26214,   39321,   52428,
+  65536,   78643,   91750,  104857,  117964,  131072,  144179,  157286,  170393,  183500,
+  196608,  209715,  222822,  235929,  249036,  262144,  275251,  288358,  301465,  314572,
+  327680
+};
+
+
+/* k Points for function piecewise() in Q0 */
+static const uint16_t kCdfSlope[51] = {
+  5,    5,     5,     5,     5,     5,     5,     5,    5,    5,
+  5,    5,    13,    23,    47,    87,   154,   315,  700, 1088,
+  2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
+  1095,  660,   316,   145,    86,    41,    32,     5,    5,    5,
+  5,    5,     5,     5,     5,     5,     5,     5,    5,    2,
+  0
+};
+
+/* y Points for function piecewise() in Q0 */
+static const uint16_t kCdfLogistic[51] = {
+  0,     2,     4,     6,     8,    10,    12,    14,    16,    18,
+  20,    22,    24,    29,    38,    57,    92,   153,   279,   559,
+  994,  1983,  4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
+  64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
+  65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
+  65535
+};
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Piecewise(...)
+ *
+ * Piecewise linear function
+ *
+ * Input:
+ *      - xinQ15           : input value x in Q15
+ *
+ * Return value            : korresponding y-value in Q0
+ */
+
+
+static __inline uint16_t WebRtcIsacfix_Piecewise(int32_t xinQ15) {
+  int32_t ind;
+  int32_t qtmp1;
+  uint16_t qtmp2;
+
+  /* Find index for x-value */
+  qtmp1 = WEBRTC_SPL_SAT(kHistEdges[50],xinQ15,kHistEdges[0]);
+  ind = WEBRTC_SPL_MUL(5, qtmp1 - kHistEdges[0]);
+  ind >>= 16;
+
+  /* Calculate corresponding y-value ans return*/
+  qtmp1 = qtmp1 - kHistEdges[ind];
+  qtmp2 = (uint16_t)WEBRTC_SPL_RSHIFT_U32(
+      WEBRTC_SPL_UMUL_32_16(qtmp1,kCdfSlope[ind]), 15);
+  return (kCdfLogistic[ind] + qtmp2);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - dataQ7            : data vector in Q7
+ *      - envQ8             : side info vector defining the width of the pdf
+ *                            in Q8
+ *      - lenData           : data vector length
+ *
+ * Return value             :  0 if ok,
+ *                            <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc *streamData,
+                                   int16_t *dataQ7,
+                                   const uint16_t *envQ8,
+                                   const int16_t lenData)
+{
+  uint32_t W_lower;
+  uint32_t W_upper;
+  uint16_t W_upper_LSB;
+  uint16_t W_upper_MSB;
+  uint16_t *streamPtr;
+  uint16_t *maxStreamPtr;
+  uint16_t *streamPtrCarry;
+  uint16_t negcarry;
+  uint32_t cdfLo;
+  uint32_t cdfHi;
+  int k;
+
+  /* point to beginning of stream buffer
+   * and set maximum streamPtr value */
+  streamPtr = streamData->stream + streamData->stream_index;
+  maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+  W_upper = streamData->W_upper;
+
+  for (k = 0; k < lenData; k++)
+  {
+    /* compute cdf_lower and cdf_upper by evaluating the
+     * WebRtcIsacfix_Piecewise linear cdf */
+    cdfLo = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+    cdfHi = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+
+    /* test and clip if probability gets too small */
+    while ((cdfLo + 1) >= cdfHi) {
+      /* clip */
+      if (*dataQ7 > 0) {
+        *dataQ7 -= 128;
+        cdfHi = cdfLo;
+        cdfLo = WebRtcIsacfix_Piecewise(
+            WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+      } else {
+        *dataQ7 += 128;
+        cdfLo = cdfHi;
+        cdfHi = WebRtcIsacfix_Piecewise(
+            WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+      }
+    }
+
+    dataQ7++;
+    /* increment only once per 4 iterations */
+    envQ8 += (k & 1) & (k >> 1);
+
+
+    /* update interval */
+    W_upper_LSB = (uint16_t)W_upper;
+    W_upper_MSB = (uint16_t)WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+    W_lower = WEBRTC_SPL_UMUL_32_16(cdfLo, W_upper_MSB);
+    W_lower += (cdfLo * W_upper_LSB) >> 16;
+    W_upper = WEBRTC_SPL_UMUL_32_16(cdfHi, W_upper_MSB);
+    W_upper += (cdfHi * W_upper_LSB) >> 16;
+
+    /* shift interval such that it begins at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamData->streamval += W_lower;
+
+    /* handle carry */
+    if (streamData->streamval < W_lower)
+    {
+      /* propagate carry */
+      streamPtrCarry = streamPtr;
+      if (streamData->full == 0) {
+        negcarry = *streamPtrCarry;
+        negcarry += 0x0100;
+        *streamPtrCarry = negcarry;
+        while (!(negcarry))
+        {
+          negcarry = *--streamPtrCarry;
+          negcarry++;
+          *streamPtrCarry = negcarry;
+        }
+      } else {
+        while (!(++(*--streamPtrCarry)));
+      }
+    }
+
+    /* renormalize interval, store most significant byte of streamval and update streamval
+     * W_upper < 2^24 */
+    while ( !(W_upper & 0xFF000000) )
+    {
+      W_upper <<= 8;
+      if (streamData->full == 0) {
+        *streamPtr++ += (uint16_t) WEBRTC_SPL_RSHIFT_U32(
+            streamData->streamval, 24);
+        streamData->full = 1;
+      } else {
+        *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+        streamData->full = 0;
+      }
+
+      if( streamPtr > maxStreamPtr )
+        return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+
+      streamData->streamval <<= 8;
+    }
+  }
+
+  /* calculate new stream_index */
+  streamData->stream_index = streamPtr - streamData->stream;
+  streamData->W_upper = W_upper;
+
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - envQ8             : side info vector defining the width of the pdf
+ *                            in Q8
+ *      - lenData           : data vector length
+ *
+ * Input/Output:
+ *      - dataQ7            : input: dither vector, output: data vector
+ *
+ * Return value             : number of bytes in the stream so far
+ *                            -1 if error detected
+ */
+int WebRtcIsacfix_DecLogisticMulti2(int16_t *dataQ7,
+                                    Bitstr_dec *streamData,
+                                    const int32_t *envQ8,
+                                    const int16_t lenData)
+{
+  uint32_t    W_lower;
+  uint32_t    W_upper;
+  uint32_t    W_tmp;
+  uint16_t    W_upper_LSB;
+  uint16_t    W_upper_MSB;
+  uint32_t    streamVal;
+  uint16_t    cdfTmp;
+  int32_t     res;
+  int32_t     inSqrt;
+  int32_t     newRes;
+  const uint16_t *streamPtr;
+  int16_t     candQ7;
+  int16_t     envCount;
+  uint16_t    tmpARSpecQ8 = 0;
+  int             k, i;
+  int offset = 0;
+
+  /* point to beginning of stream buffer */
+  streamPtr = streamData->stream + streamData->stream_index;
+  W_upper = streamData->W_upper;
+
+  /* Check if it is first time decoder is called for this stream */
+  if (streamData->stream_index == 0)
+  {
+    /* read first word from bytestream */
+    streamVal = (uint32_t)(*streamPtr++) << 16;
+    streamVal |= *streamPtr++;
+
+  } else {
+    streamVal = streamData->streamval;
+  }
+
+
+  res = 1 << (WebRtcSpl_GetSizeInBits(envQ8[0]) >> 1);
+  envCount = 0;
+
+  /* code assumes lenData%4 == 0 */
+  for (k = 0; k < lenData; k += 4)
+  {
+    int k4;
+
+    /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+    inSqrt = envQ8[envCount];
+    i = 10;
+
+    /* For safty reasons */
+    if (inSqrt < 0)
+      inSqrt=-inSqrt;
+
+    newRes = (inSqrt / res + res) >> 1;
+    do
+    {
+      res = newRes;
+      newRes = (inSqrt / res + res) >> 1;
+    } while (newRes != res && i-- > 0);
+
+    tmpARSpecQ8 = (uint16_t)newRes;
+
+    for(k4 = 0; k4 < 4; k4++)
+    {
+      /* find the integer *data for which streamVal lies in [W_lower+1, W_upper] */
+      W_upper_LSB = (uint16_t) (W_upper & 0x0000FFFF);
+      W_upper_MSB = (uint16_t) WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+      /* find first candidate by inverting the logistic cdf
+       * Input dither value collected from io-stream */
+      candQ7 = - *dataQ7 + 64;
+      cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+      W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+      W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+      if (streamVal > W_tmp)
+      {
+        W_lower = W_tmp;
+        candQ7 += 128;
+        cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+        W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+        W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+        while (streamVal > W_tmp)
+        {
+          W_lower = W_tmp;
+          candQ7 += 128;
+          cdfTmp = WebRtcIsacfix_Piecewise(
+              WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+          W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+          W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+          /* error check */
+          if (W_lower == W_tmp) {
+            return -1;
+          }
+        }
+        W_upper = W_tmp;
+
+        /* Output value put in dataQ7: another sample decoded */
+        *dataQ7 = candQ7 - 64;
+      }
+      else
+      {
+        W_upper = W_tmp;
+        candQ7 -= 128;
+        cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+        W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+        W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+        while ( !(streamVal > W_tmp) )
+        {
+          W_upper = W_tmp;
+          candQ7 -= 128;
+          cdfTmp = WebRtcIsacfix_Piecewise(
+              WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+          W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+          W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+          /* error check */
+          if (W_upper == W_tmp){
+            return -1;
+          }
+        }
+        W_lower = W_tmp;
+
+        /* Output value put in dataQ7: another sample decoded */
+        *dataQ7 = candQ7 + 64;
+      }
+
+      dataQ7++;
+
+      /* shift interval to start at zero */
+      W_upper -= ++W_lower;
+
+      /* add integer to bitstream */
+      streamVal -= W_lower;
+
+      /* renormalize interval and update streamVal
+       * W_upper < 2^24 */
+      while ( !(W_upper & 0xFF000000) )
+      {
+        if (streamPtr < streamData->stream + streamData->stream_size) {
+          /* read next byte from stream */
+          if (streamData->full == 0) {
+            streamVal = (streamVal << 8) | (*streamPtr++ & 0x00FF);
+            streamData->full = 1;
+          } else {
+            streamVal = (streamVal << 8) | (*streamPtr >> 8);
+            streamData->full = 0;
+          }
+        } else {
+          /* Intending to read outside the stream. This can happen for the last
+           * two or three bytes. It is how the algorithm is implemented. Do
+           * not read from the bit stream and insert zeros instead. */
+          streamVal <<= 8;
+          if (streamData->full == 0) {
+            offset++;  // We would have incremented the pointer in this case.
+            streamData->full = 1;
+          } else {
+            streamData->full = 0;
+          }
+        }
+        W_upper <<= 8;
+      }
+    }
+    envCount++;
+  }
+
+  streamData->stream_index = streamPtr + offset - streamData->stream;
+  streamData->W_upper = W_upper;
+  streamData->streamval = streamVal;
+
+  /* find number of bytes in original stream (determined by current interval width) */
+  if ( W_upper > 0x01FFFFFF )
+    return (streamData->stream_index*2 - 3 + !streamData->full);
+  else
+    return (streamData->stream_index*2 - 2 + !streamData->full);
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/arith_routins.h b/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
new file mode 100644
index 0000000..d112bfe
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routins.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - dataQ7            : data vector in Q7
+ *      - envQ8             : side info vector defining the width of the pdf
+ *                            in Q8
+ *      - lenData           : data vector length
+ *
+ * Return value             :  0 if ok,
+ *                             <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc* streamData,
+                                    int16_t* dataQ7,
+                                    const uint16_t* env,
+                                    int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *
+ * Return value             : number of bytes in the stream
+ */
+int16_t WebRtcIsacfix_EncTerminate(Bitstr_enc* streamData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - envQ8             : side info vector defining the width of the pdf
+ *                            in Q8
+ *      - lenData           : data vector length
+ *
+ * Input/Output:
+ *      - dataQ7            : input: dither vector, output: data vector, in Q7
+ *
+ * Return value             : number of bytes in the stream so far
+ *                            <0 if error detected
+ */
+int WebRtcIsacfix_DecLogisticMulti2(int16_t* data,
+                                    Bitstr_dec* streamData,
+                                    const int32_t* env,
+                                    int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - data              : data vector
+ *      - cdf               : array of cdf arrays
+ *      - lenData           : data vector length
+ *
+ * Return value             : 0 if ok
+ *                            <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(Bitstr_enc* streamData,
+                               const int16_t* data,
+                               const uint16_t* const* cdf,
+                               int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, using
+ * method of bisection.
+ * C df tables should be of size 2^k-1 (which corresponds to an
+ * alphabet size of 2^k-2)
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - cdf               : array of cdf arrays
+ *      - cdfSize           : array of cdf table sizes+1 (power of two: 2^k)
+ *      - lenData           : data vector length
+ *
+ * Output:
+ *      - data              : data vector
+ *
+ * Return value             : number of bytes in the stream
+ *                            <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t* data,
+                                         Bitstr_dec* streamData,
+                                         const uint16_t* const* cdf,
+                                         const uint16_t* cdfSize,
+                                         int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, taking
+ * single step up or down at a time.
+ * cdf tables can be of arbitrary size, but large tables may take a lot of
+ * iterations.
+ *
+ * Input:
+ *      - streamData        : in-/output struct containing bitstream
+ *      - cdf               : array of cdf arrays
+ *      - initIndex         : vector of initial cdf table search entries
+ *      - lenData           : data vector length
+ *
+ * Output:
+ *      - data              : data vector
+ *
+ * Return value             : number of bytes in original stream
+ *                            <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t* data,
+                                          Bitstr_dec* streamData,
+                                          const uint16_t* const* cdf,
+                                          const uint16_t* initIndex,
+                                          int16_t lenData);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc b/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc
new file mode 100644
index 0000000..21259ee
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioDecoderIsacT<IsacFix>;
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc b/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
new file mode 100644
index 0000000..0190ab9
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h"
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioEncoderIsacT<IsacFix>;
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c b/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
new file mode 100644
index 0000000..8845357
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
@@ -0,0 +1,1021 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ * NOTE! Castings needed for C55, do not remove!
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/checks.h"
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const int16_t kQRateTable[12] = {
+  10000, 11115, 12355, 13733, 15265, 16967,
+  18860, 20963, 23301, 25900, 28789, 32000
+};
+
+/* 0.1 times the values in the table kQRateTable */
+/* values are in Q16                                         */
+static const int32_t KQRate01[12] = {
+  65536000,  72843264,  80969728,  90000589,  100040704, 111194931,
+  123600896, 137383117, 152705434, 169738240, 188671590, 209715200
+};
+
+/* Bits per Bytes Seconds
+ * 8 bits/byte * 1000 msec/sec * 1/framelength (in msec)->bits/byte*sec
+ * frame length will either be 30 or 60 msec. 8738 is 1/60 in Q19 and 1/30 in Q18
+ * The following number is either in Q15 or Q14 depending on the current frame length */
+static const int32_t kBitsByteSec = 4369000;
+
+/* Received header rate. First value is for 30 ms packets and second for 60 ms */
+static const int16_t kRecHeaderRate[2] = {
+  9333, 4666
+};
+
+/* Inverted minimum and maximum bandwidth in Q30.
+   minBwInv 30 ms, maxBwInv 30 ms,
+   minBwInv 60 ms, maxBwInv 69 ms
+*/
+static const int32_t kInvBandwidth[4] = {
+  55539, 25978,
+  73213, 29284
+};
+
+/* Number of samples in 25 msec */
+static const int32_t kSamplesIn25msec = 400;
+
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ *      - bweStr        : Struct containing bandwidth information.
+ *
+ * Return value            : 0
+ */
+int32_t WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr *bweStr)
+{
+  bweStr->prevFrameSizeMs       = INIT_FRAME_LEN;
+  bweStr->prevRtpNumber         = 0;
+  bweStr->prevSendTime          = 0;
+  bweStr->prevArrivalTime       = 0;
+  bweStr->prevRtpRate           = 1;
+  bweStr->lastUpdate            = 0;
+  bweStr->lastReduction         = 0;
+  bweStr->countUpdates          = -9;
+
+  /* INIT_BN_EST = 20000
+   * INIT_BN_EST_Q7 = 2560000
+   * INIT_HDR_RATE = 4666
+   * INIT_REC_BN_EST_Q5 = 789312
+   *
+   * recBwInv = 1/(INIT_BN_EST + INIT_HDR_RATE) in Q30
+   * recBwAvg = INIT_BN_EST + INIT_HDR_RATE in Q5
+   */
+  bweStr->recBwInv              = 43531;
+  bweStr->recBw                 = INIT_BN_EST;
+  bweStr->recBwAvgQ             = INIT_BN_EST_Q7;
+  bweStr->recBwAvg              = INIT_REC_BN_EST_Q5;
+  bweStr->recJitter             = (int32_t) 327680;   /* 10 in Q15 */
+  bweStr->recJitterShortTerm    = 0;
+  bweStr->recJitterShortTermAbs = (int32_t) 40960;    /* 5 in Q13 */
+  bweStr->recMaxDelay           = (int32_t) 10;
+  bweStr->recMaxDelayAvgQ       = (int32_t) 5120;     /* 10 in Q9 */
+  bweStr->recHeaderRate         = INIT_HDR_RATE;
+  bweStr->countRecPkts          = 0;
+  bweStr->sendBwAvg             = INIT_BN_EST_Q7;
+  bweStr->sendMaxDelayAvg       = (int32_t) 5120;     /* 10 in Q9 */
+
+  bweStr->countHighSpeedRec     = 0;
+  bweStr->highSpeedRec          = 0;
+  bweStr->countHighSpeedSent    = 0;
+  bweStr->highSpeedSend         = 0;
+  bweStr->inWaitPeriod          = 0;
+
+  /* Find the inverse of the max bw and min bw in Q30
+   *  (1 / (MAX_ISAC_BW + INIT_HDR_RATE) in Q30
+   *  (1 / (MIN_ISAC_BW + INIT_HDR_RATE) in Q30
+   */
+  bweStr->maxBwInv              = kInvBandwidth[3];
+  bweStr->minBwInv              = kInvBandwidth[2];
+
+  bweStr->external_bw_info.in_use = 0;
+
+  return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ *      - bweStr           : struct containing bandwidth information.
+ *      - rtpNumber        : value from RTP packet, from NetEq
+ *      - frameSize        : length of signal frame in ms, from iSAC decoder
+ *      - sendTime         : value in RTP header giving send time in samples
+ *      - arrivalTime      : value given by timeGetTime() time of arrival in
+ *                           samples of packet from NetEq
+ *      - pksize           : size of packet in bytes, from NetEq
+ *      - Index            : integer (range 0...23) indicating bottle neck &
+ *                           jitter as estimated by other side
+ *
+ * Return value            : 0 if everything went fine,
+ *                           -1 otherwise
+ */
+int32_t WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bweStr,
+                                         const uint16_t rtpNumber,
+                                         const int16_t  frameSize,
+                                         const uint32_t sendTime,
+                                         const uint32_t arrivalTime,
+                                         const size_t   pksize,
+                                         const uint16_t Index)
+{
+  uint16_t  weight = 0;
+  uint32_t  currBwInv = 0;
+  uint16_t  recRtpRate;
+  uint32_t  arrTimeProj;
+  int32_t   arrTimeDiff;
+  int32_t   arrTimeNoise;
+  int32_t   arrTimeNoiseAbs;
+  int32_t   sendTimeDiff;
+
+  int32_t delayCorrFactor = DELAY_CORRECTION_MED;
+  int32_t lateDiff = 0;
+  int16_t immediateSet = 0;
+  int32_t frameSizeSampl;
+
+  int32_t  temp;
+  int32_t  msec;
+  uint32_t exponent;
+  uint32_t reductionFactor;
+  uint32_t numBytesInv;
+  int32_t  sign;
+
+  uint32_t byteSecondsPerBit;
+  uint32_t tempLower;
+  uint32_t tempUpper;
+  int32_t recBwAvgInv;
+  int32_t numPktsExpected;
+
+  int16_t errCode;
+
+  RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+  /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+  /* The function also checks if Index has a valid value */
+  errCode = WebRtcIsacfix_UpdateUplinkBwRec(bweStr, Index);
+  if (errCode <0) {
+    return(errCode);
+  }
+
+
+  /* UPDATE ESTIMATES ON THIS SIDE */
+
+  /* Bits per second per byte * 1/30 or 1/60 */
+  if (frameSize == 60) {
+    /* If frameSize changed since last call, from 30 to 60, recalculate some values */
+    if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+      bweStr->countUpdates = 10;
+      bweStr->recHeaderRate = kRecHeaderRate[1];
+
+      bweStr->maxBwInv = kInvBandwidth[3];
+      bweStr->minBwInv = kInvBandwidth[2];
+      bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+    }
+
+    /* kBitsByteSec is in Q15 */
+    recRtpRate = (int16_t)((kBitsByteSec * pksize) >> 15) +
+        bweStr->recHeaderRate;
+
+  } else {
+    /* If frameSize changed since last call, from 60 to 30, recalculate some values */
+    if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+      bweStr->countUpdates = 10;
+      bweStr->recHeaderRate = kRecHeaderRate[0];
+
+      bweStr->maxBwInv = kInvBandwidth[1];
+      bweStr->minBwInv = kInvBandwidth[0];
+      bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+    }
+
+    /* kBitsByteSec is in Q14 */
+    recRtpRate = (uint16_t)((kBitsByteSec * pksize) >> 14) +
+        bweStr->recHeaderRate;
+  }
+
+
+  /* Check for timer wrap-around */
+  if (arrivalTime < bweStr->prevArrivalTime) {
+    bweStr->prevArrivalTime = arrivalTime;
+    bweStr->lastUpdate      = arrivalTime;
+    bweStr->lastReduction   = arrivalTime + FS3;
+
+    bweStr->countRecPkts      = 0;
+
+    /* store frame size */
+    bweStr->prevFrameSizeMs = frameSize;
+
+    /* store far-side transmission rate */
+    bweStr->prevRtpRate = recRtpRate;
+
+    /* store far-side RTP time stamp */
+    bweStr->prevRtpNumber = rtpNumber;
+
+    return 0;
+  }
+
+  bweStr->countRecPkts++;
+
+  /* Calculate framesize in msec */
+  frameSizeSampl = SAMPLES_PER_MSEC * frameSize;
+
+  /* Check that it's not one of the first 9 packets */
+  if ( bweStr->countUpdates > 0 ) {
+
+    /* Stay in Wait Period for 1.5 seconds (no updates in wait period) */
+    if(bweStr->inWaitPeriod) {
+      if ((arrivalTime - bweStr->startWaitPeriod)> FS_1_HALF) {
+        bweStr->inWaitPeriod = 0;
+      }
+    }
+
+    /* If not been updated for a long time, reduce the BN estimate */
+
+    /* Check send time difference between this packet and previous received      */
+    sendTimeDiff = sendTime - bweStr->prevSendTime;
+    if (sendTimeDiff <= frameSizeSampl * 2) {
+
+      /* Only update if 3 seconds has past since last update */
+      if ((arrivalTime - bweStr->lastUpdate) > FS3) {
+
+        /* Calculate expected number of received packets since last update */
+        numPktsExpected = (arrivalTime - bweStr->lastUpdate) / frameSizeSampl;
+
+        /* If received number of packets is more than 90% of expected (922 = 0.9 in Q10): */
+        /* do the update, else not                                                        */
+        if ((int32_t)bweStr->countRecPkts << 10 > 922 * numPktsExpected) {
+          /* Q4 chosen to approx dividing by 16 */
+          msec = (arrivalTime - bweStr->lastReduction);
+
+          /* the number below represents 13 seconds, highly unlikely
+             but to insure no overflow when reduction factor is multiplied by recBw inverse */
+          if (msec > 208000) {
+            msec = 208000;
+          }
+
+          /* Q20 2^(negative number: - 76/1048576) = .99995
+             product is Q24 */
+          exponent = WEBRTC_SPL_UMUL(0x0000004C, msec);
+
+          /* do the approx with positive exponent so that value is actually rf^-1
+             and multiply by bw inverse */
+          reductionFactor = WEBRTC_SPL_RSHIFT_U32(0x01000000 | (exponent & 0x00FFFFFF),
+                                                  WEBRTC_SPL_RSHIFT_U32(exponent, 24));
+
+          /* reductionFactor in Q13 */
+          reductionFactor = WEBRTC_SPL_RSHIFT_U32(reductionFactor, 11);
+
+          if ( reductionFactor != 0 ) {
+            bweStr->recBwInv = WEBRTC_SPL_MUL((int32_t)bweStr->recBwInv, (int32_t)reductionFactor);
+            bweStr->recBwInv = (int32_t)bweStr->recBwInv >> 13;
+
+          } else {
+            static const uint32_t kInitRate = INIT_BN_EST + INIT_HDR_RATE;
+            /* recBwInv = 1 / kInitRate  in Q26 (Q30??)*/
+            bweStr->recBwInv = (1073741824 + kInitRate / 2) / kInitRate;
+          }
+
+          /* reset time-since-update counter */
+          bweStr->lastReduction = arrivalTime;
+        } else {
+          /* Delay last reduction with 3 seconds */
+          bweStr->lastReduction = arrivalTime + FS3;
+          bweStr->lastUpdate    = arrivalTime;
+          bweStr->countRecPkts  = 0;
+        }
+      }
+    } else {
+      bweStr->lastReduction = arrivalTime + FS3;
+      bweStr->lastUpdate    = arrivalTime;
+      bweStr->countRecPkts  = 0;
+    }
+
+
+    /*   update only if previous packet was not lost */
+    if ( rtpNumber == bweStr->prevRtpNumber + 1 ) {
+      arrTimeDiff = arrivalTime - bweStr->prevArrivalTime;
+
+      if (!(bweStr->highSpeedSend && bweStr->highSpeedRec)) {
+        if (arrTimeDiff > frameSizeSampl) {
+          if (sendTimeDiff > 0) {
+            lateDiff = arrTimeDiff - sendTimeDiff - frameSizeSampl * 2;
+          } else {
+            lateDiff = arrTimeDiff - frameSizeSampl;
+          }
+
+          /* 8000 is 1/2 second (in samples at FS) */
+          if (lateDiff > 8000) {
+            delayCorrFactor = (int32_t) DELAY_CORRECTION_MAX;
+            bweStr->inWaitPeriod = 1;
+            bweStr->startWaitPeriod = arrivalTime;
+            immediateSet = 1;
+          } else if (lateDiff > 5120) {
+            delayCorrFactor = (int32_t) DELAY_CORRECTION_MED;
+            immediateSet = 1;
+            bweStr->inWaitPeriod = 1;
+            bweStr->startWaitPeriod = arrivalTime;
+          }
+        }
+      }
+
+      if ((bweStr->prevRtpRate > (int32_t)bweStr->recBwAvg >> 5) &&
+          (recRtpRate > (int32_t)bweStr->recBwAvg >> 5) &&
+          !bweStr->inWaitPeriod) {
+
+        /* test if still in initiation period and increment counter */
+        if (bweStr->countUpdates++ > 99) {
+          /* constant weight after initiation part, 0.01 in Q13 */
+          weight = (uint16_t) 82;
+        } else {
+          /* weight decreases with number of updates, 1/countUpdates in Q13  */
+          weight = (uint16_t) WebRtcSpl_DivW32W16(
+              8192 + (bweStr->countUpdates >> 1),
+              (int16_t)bweStr->countUpdates);
+        }
+
+        /* Bottle Neck Estimation */
+
+        /* limit outliers, if more than 25 ms too much */
+        if (arrTimeDiff > frameSizeSampl + kSamplesIn25msec) {
+          arrTimeDiff = frameSizeSampl + kSamplesIn25msec;
+        }
+
+        /* don't allow it to be less than frame rate - 10 ms */
+        if (arrTimeDiff < frameSizeSampl - FRAMESAMPLES_10ms) {
+          arrTimeDiff = frameSizeSampl - FRAMESAMPLES_10ms;
+        }
+
+        /* compute inverse receiving rate for last packet, in Q19 */
+        numBytesInv = (uint16_t) WebRtcSpl_DivW32W16(
+            (int32_t)(524288 + ((pksize + HEADER_SIZE) >> 1)),
+            (int16_t)(pksize + HEADER_SIZE));
+
+        /* 8389 is  ~ 1/128000 in Q30 */
+        byteSecondsPerBit = (uint32_t)(arrTimeDiff * 8389);
+
+        /* get upper N bits */
+        tempUpper = WEBRTC_SPL_RSHIFT_U32(byteSecondsPerBit, 15);
+
+        /* get lower 15 bits */
+        tempLower = byteSecondsPerBit & 0x00007FFF;
+
+        tempUpper = WEBRTC_SPL_MUL(tempUpper, numBytesInv);
+        tempLower = WEBRTC_SPL_MUL(tempLower, numBytesInv);
+        tempLower = WEBRTC_SPL_RSHIFT_U32(tempLower, 15);
+
+        currBwInv = tempUpper + tempLower;
+        currBwInv = WEBRTC_SPL_RSHIFT_U32(currBwInv, 4);
+
+        /* Limit inv rate. Note that minBwInv > maxBwInv! */
+        if(currBwInv < bweStr->maxBwInv) {
+          currBwInv = bweStr->maxBwInv;
+        } else if(currBwInv > bweStr->minBwInv) {
+          currBwInv = bweStr->minBwInv;
+        }
+
+        /* update bottle neck rate estimate */
+        bweStr->recBwInv = WEBRTC_SPL_UMUL(weight, currBwInv) +
+            WEBRTC_SPL_UMUL((uint32_t) 8192 - weight, bweStr->recBwInv);
+
+        /* Shift back to Q30 from Q40 (actual used bits shouldn't be more than 27 based on minBwInv)
+           up to 30 bits used with Q13 weight */
+        bweStr->recBwInv = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwInv, 13);
+
+        /* reset time-since-update counter */
+        bweStr->lastUpdate    = arrivalTime;
+        bweStr->lastReduction = arrivalTime + FS3;
+        bweStr->countRecPkts  = 0;
+
+        /* to save resolution compute the inverse of recBwAvg in Q26 by left shifting numerator to 2^31
+           and NOT right shifting recBwAvg 5 bits to an integer
+           At max 13 bits are used
+           shift to Q5 */
+        recBwAvgInv = (0x80000000 + bweStr->recBwAvg / 2) / bweStr->recBwAvg;
+
+        /* Calculate Projected arrival time difference */
+
+        /* The numerator of the quotient can be 22 bits so right shift inv by 4 to avoid overflow
+           result in Q22 */
+        arrTimeProj = WEBRTC_SPL_MUL((int32_t)8000, recBwAvgInv);
+        /* shift to Q22 */
+        arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 4);
+        /* complete calulation */
+        arrTimeProj = WEBRTC_SPL_MUL(((int32_t)pksize + HEADER_SIZE), arrTimeProj);
+        /* shift to Q10 */
+        arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 12);
+
+        /* difference between projected and actual arrival time differences */
+        /* Q9 (only shift arrTimeDiff by 5 to simulate divide by 16 (need to revisit if change sampling rate) DH */
+        if ((arrTimeDiff << 6) > (int32_t)arrTimeProj) {
+          arrTimeNoise = (arrTimeDiff << 6) - arrTimeProj;
+          sign = 1;
+        } else {
+          arrTimeNoise = arrTimeProj - (arrTimeDiff << 6);
+          sign = -1;
+        }
+
+        /* Q9 */
+        arrTimeNoiseAbs = arrTimeNoise;
+
+        /* long term averaged absolute jitter, Q15 */
+        weight >>= 3;
+        bweStr->recJitter = weight * (arrTimeNoiseAbs << 5) +
+            (1024 - weight) * bweStr->recJitter;
+
+        /* remove the fractional portion */
+        bweStr->recJitter >>= 10;
+
+        /* Maximum jitter is 10 msec in Q15 */
+        if (bweStr->recJitter > (int32_t)327680) {
+          bweStr->recJitter = (int32_t)327680;
+        }
+
+        /* short term averaged absolute jitter */
+        /* Calculation in Q13 products in Q23 */
+        bweStr->recJitterShortTermAbs = 51 * (arrTimeNoiseAbs << 3) +
+            WEBRTC_SPL_MUL(973, bweStr->recJitterShortTermAbs);
+        bweStr->recJitterShortTermAbs >>= 10;
+
+        /* short term averaged jitter */
+        /* Calculation in Q13 products in Q23 */
+        bweStr->recJitterShortTerm = 205 * (arrTimeNoise << 3) * sign +
+            WEBRTC_SPL_MUL(3891, bweStr->recJitterShortTerm);
+
+        if (bweStr->recJitterShortTerm < 0) {
+          temp = -bweStr->recJitterShortTerm;
+          temp >>= 12;
+          bweStr->recJitterShortTerm = -temp;
+        } else {
+          bweStr->recJitterShortTerm >>= 12;
+        }
+      }
+    }
+  } else {
+    /* reset time-since-update counter when receiving the first 9 packets */
+    bweStr->lastUpdate    = arrivalTime;
+    bweStr->lastReduction = arrivalTime + FS3;
+    bweStr->countRecPkts  = 0;
+    bweStr->countUpdates++;
+  }
+
+  /* Limit to minimum or maximum bottle neck rate (in Q30) */
+  if (bweStr->recBwInv > bweStr->minBwInv) {
+    bweStr->recBwInv = bweStr->minBwInv;
+  } else if (bweStr->recBwInv < bweStr->maxBwInv) {
+    bweStr->recBwInv = bweStr->maxBwInv;
+  }
+
+
+  /* store frame length */
+  bweStr->prevFrameSizeMs = frameSize;
+
+  /* store far-side transmission rate */
+  bweStr->prevRtpRate = recRtpRate;
+
+  /* store far-side RTP time stamp */
+  bweStr->prevRtpNumber = rtpNumber;
+
+  /* Replace bweStr->recMaxDelay by the new value (atomic operation) */
+  if (bweStr->prevArrivalTime != 0xffffffff) {
+    bweStr->recMaxDelay = WEBRTC_SPL_MUL(3, bweStr->recJitter);
+  }
+
+  /* store arrival time stamp */
+  bweStr->prevArrivalTime = arrivalTime;
+  bweStr->prevSendTime = sendTime;
+
+  /* Replace bweStr->recBw by the new value */
+  bweStr->recBw = 1073741824 / bweStr->recBwInv - bweStr->recHeaderRate;
+
+  if (immediateSet) {
+    /* delay correction factor is in Q10 */
+    bweStr->recBw = WEBRTC_SPL_UMUL(delayCorrFactor, bweStr->recBw);
+    bweStr->recBw = WEBRTC_SPL_RSHIFT_U32(bweStr->recBw, 10);
+
+    if (bweStr->recBw < (int32_t) MIN_ISAC_BW) {
+      bweStr->recBw = (int32_t) MIN_ISAC_BW;
+    }
+
+    bweStr->recBwAvg = (bweStr->recBw + bweStr->recHeaderRate) << 5;
+
+    bweStr->recBwAvgQ = bweStr->recBw << 7;
+
+    bweStr->recJitterShortTerm = 0;
+
+    bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+
+    immediateSet = 0;
+  }
+
+
+  return 0;
+}
+
+/* This function updates the send bottle neck rate                                                   */
+/* Index         - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise                                                   */
+int16_t WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bweStr,
+                                        const int16_t Index)
+{
+  uint16_t RateInd;
+
+  RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+  if ( (Index < 0) || (Index > 23) ) {
+    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+  }
+
+  /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+  if ( Index > 11 ) {
+    RateInd = Index - 12;
+    /* compute the jitter estimate as decoded on the other side in Q9 */
+    /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MAX_ISAC_MD */
+    bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+        51 * (MAX_ISAC_MD << 9);
+    bweStr->sendMaxDelayAvg >>= 9;
+
+  } else {
+    RateInd = Index;
+    /* compute the jitter estimate as decoded on the other side in Q9 */
+    /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MIN_ISAC_MD */
+    bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+        51 * (MIN_ISAC_MD << 9);
+    bweStr->sendMaxDelayAvg >>= 9;
+
+  }
+
+
+  /* compute the BN estimate as decoded on the other side */
+  /* sendBwAvg = 0.9 * sendBwAvg + 0.1 * kQRateTable[RateInd]; */
+  bweStr->sendBwAvg = 461 * bweStr->sendBwAvg +
+      51 * ((uint32_t)kQRateTable[RateInd] << 7);
+  bweStr->sendBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 9);
+
+
+  if (WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7) > 28000 && !bweStr->highSpeedSend) {
+    bweStr->countHighSpeedSent++;
+
+    /* approx 2 seconds with 30ms frames */
+    if (bweStr->countHighSpeedSent >= 66) {
+      bweStr->highSpeedSend = 1;
+    }
+  } else if (!bweStr->highSpeedSend) {
+    bweStr->countHighSpeedSent = 0;
+  }
+
+  return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ *      - bweStr       : BWE struct
+ *
+ * Return:
+ *      bandwith and jitter index (0..23)
+ */
+uint16_t WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bweStr)
+{
+  int32_t  rate;
+  int32_t  maxDelay;
+  uint16_t rateInd;
+  uint16_t maxDelayBit;
+  int32_t  tempTerm1;
+  int32_t  tempTerm2;
+  int32_t  tempTermX;
+  int32_t  tempTermY;
+  int32_t  tempMin;
+  int32_t  tempMax;
+
+  if (bweStr->external_bw_info.in_use)
+    return bweStr->external_bw_info.bottleneck_idx;
+
+  /* Get Rate Index */
+
+  /* Get unquantized rate. Always returns 10000 <= rate <= 32000 */
+  rate = WebRtcIsacfix_GetDownlinkBandwidth(bweStr);
+
+  /* Compute the averaged BN estimate on this side */
+
+  /* recBwAvg = 0.9 * recBwAvg + 0.1 * (rate + bweStr->recHeaderRate), 0.9 and 0.1 in Q9 */
+  bweStr->recBwAvg = 922 * bweStr->recBwAvg +
+      102 * (((uint32_t)rate + bweStr->recHeaderRate) << 5);
+  bweStr->recBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 10);
+
+  /* Find quantization index that gives the closest rate after averaging.
+   * Note that we don't need to check the last value, rate <= kQRateTable[11],
+   * because we will use rateInd = 11 even if rate > kQRateTable[11]. */
+  for (rateInd = 1; rateInd < 11; rateInd++) {
+    if (rate <= kQRateTable[rateInd]){
+      break;
+    }
+  }
+
+  /* find closest quantization index, and update quantized average by taking: */
+  /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+  /* 0.9 times recBwAvgQ in Q16 */
+  /* 461/512 - 25/65536 =0.900009 */
+  tempTerm1 = WEBRTC_SPL_MUL(bweStr->recBwAvgQ, 25);
+  tempTerm1 >>= 7;
+  tempTermX = WEBRTC_SPL_UMUL(461, bweStr->recBwAvgQ) - tempTerm1;
+
+  /* rate in Q16 */
+  tempTermY = rate << 16;
+
+  /* 0.1 * kQRateTable[rateInd] = KQRate01[rateInd] */
+  tempTerm1 = tempTermX + KQRate01[rateInd] - tempTermY;
+  tempTerm2 = tempTermY - tempTermX - KQRate01[rateInd-1];
+
+  /* Compare (0.9 * recBwAvgQ + 0.1 * kQRateTable[rateInd] - rate) >
+     (rate - 0.9 * recBwAvgQ - 0.1 * kQRateTable[rateInd-1]) */
+  if (tempTerm1  > tempTerm2) {
+    rateInd--;
+  }
+
+  /* Update quantized average by taking:                  */
+  /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+  /* Add 0.1 times kQRateTable[rateInd], in Q16 */
+  tempTermX += KQRate01[rateInd];
+
+  /* Shift back to Q7 */
+  bweStr->recBwAvgQ = tempTermX >> 9;
+
+  /* Count consecutive received bandwidth above 28000 kbps (28000 in Q7 = 3584000) */
+  /* If 66 high estimates in a row, set highSpeedRec to one */
+  /* 66 corresponds to ~2 seconds in 30 msec mode */
+  if ((bweStr->recBwAvgQ > 3584000) && !bweStr->highSpeedRec) {
+    bweStr->countHighSpeedRec++;
+    if (bweStr->countHighSpeedRec >= 66) {
+      bweStr->highSpeedRec = 1;
+    }
+  } else if (!bweStr->highSpeedRec)    {
+    bweStr->countHighSpeedRec = 0;
+  }
+
+  /* Get Max Delay Bit */
+
+  /* get unquantized max delay */
+  maxDelay = WebRtcIsacfix_GetDownlinkMaxDelay(bweStr);
+
+  /* Update quantized max delay average */
+  tempMax = 652800; /* MAX_ISAC_MD * 0.1 in Q18 */
+  tempMin = 130560; /* MIN_ISAC_MD * 0.1 in Q18 */
+  tempTermX = WEBRTC_SPL_MUL((int32_t)bweStr->recMaxDelayAvgQ, (int32_t)461);
+  tempTermY = maxDelay << 18;
+
+  tempTerm1 = tempTermX + tempMax - tempTermY;
+  tempTerm2 = tempTermY - tempTermX - tempMin;
+
+  if ( tempTerm1 > tempTerm2) {
+    maxDelayBit = 0;
+    tempTerm1 = tempTermX + tempMin;
+
+    /* update quantized average, shift back to Q9 */
+    bweStr->recMaxDelayAvgQ = tempTerm1 >> 9;
+  } else {
+    maxDelayBit = 12;
+    tempTerm1 =  tempTermX + tempMax;
+
+    /* update quantized average, shift back to Q9 */
+    bweStr->recMaxDelayAvgQ = tempTerm1 >> 9;
+  }
+
+  /* Return bandwitdh and jitter index (0..23) */
+  return (uint16_t)(rateInd + maxDelayBit);
+}
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+uint16_t WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bweStr)
+{
+  uint32_t  recBw;
+  int32_t   jitter_sign; /* Q8 */
+  int32_t   bw_adjust;   /* Q16 */
+  int32_t   rec_jitter_short_term_abs_inv; /* Q18 */
+  int32_t   temp;
+
+  RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+  /* Q18  rec jitter short term abs is in Q13, multiply it by 2^13 to save precision
+     2^18 then needs to be shifted 13 bits to 2^31 */
+  rec_jitter_short_term_abs_inv = 0x80000000u / bweStr->recJitterShortTermAbs;
+
+  /* Q27 = 9 + 18 */
+  jitter_sign = (bweStr->recJitterShortTerm >> 4) *
+      rec_jitter_short_term_abs_inv;
+
+  if (jitter_sign < 0) {
+    temp = -jitter_sign;
+    temp >>= 19;
+    jitter_sign = -temp;
+  } else {
+    jitter_sign >>= 19;
+  }
+
+  /* adjust bw proportionally to negative average jitter sign */
+  //bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+  //Q8 -> Q16 .15 +.15 * jitter^2 first term is .15 in Q16 latter term is Q8*Q8*Q8
+  //38 in Q8 ~.15 9830 in Q16 ~.15
+  temp = 9830 + ((38 * jitter_sign * jitter_sign) >> 8);
+
+  if (jitter_sign < 0) {
+    temp = WEBRTC_SPL_MUL(jitter_sign, temp);
+    temp = -temp;
+    temp >>= 8;
+    bw_adjust = (uint32_t)65536 + temp; /* (1 << 16) + temp; */
+  } else {
+    /* (1 << 16) - ((jitter_sign * temp) >> 8); */
+    bw_adjust = 65536 - ((jitter_sign * temp) >> 8);
+  }
+
+  //make sure following multiplication won't overflow
+  //bw adjust now Q14
+  bw_adjust >>= 2;  // See if good resolution is maintained.
+
+  /* adjust Rate if jitter sign is mostly constant */
+  recBw = WEBRTC_SPL_UMUL(bweStr->recBw, bw_adjust);
+
+  recBw >>= 14;
+
+  /* limit range of bottle neck rate */
+  if (recBw < MIN_ISAC_BW) {
+    recBw = MIN_ISAC_BW;
+  } else if (recBw > MAX_ISAC_BW) {
+    recBw = MAX_ISAC_BW;
+  }
+
+  return  (uint16_t) recBw;
+}
+
+/* Returns the mmax delay (in ms) */
+int16_t WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bweStr)
+{
+  int16_t recMaxDelay = (int16_t)(bweStr->recMaxDelay >> 15);
+
+  RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+  /* limit range of jitter estimate */
+  if (recMaxDelay < MIN_ISAC_MD) {
+    recMaxDelay = MIN_ISAC_MD;
+  } else if (recMaxDelay > MAX_ISAC_MD) {
+    recMaxDelay = MAX_ISAC_MD;
+  }
+
+  return recMaxDelay;
+}
+
+/* Clamp val to the closed interval [min,max]. */
+static int16_t clamp(int16_t val, int16_t min, int16_t max) {
+  RTC_DCHECK_LE(min, max);
+  return val < min ? min : (val > max ? max : val);
+}
+
+int16_t WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr* bweStr) {
+  return bweStr->external_bw_info.in_use
+             ? bweStr->external_bw_info.send_bw_avg
+             : clamp(bweStr->sendBwAvg >> 7, MIN_ISAC_BW, MAX_ISAC_BW);
+}
+
+int16_t WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr* bweStr) {
+  return bweStr->external_bw_info.in_use
+             ? bweStr->external_bw_info.send_max_delay_avg
+             : clamp(bweStr->sendMaxDelayAvg >> 9, MIN_ISAC_MD, MAX_ISAC_MD);
+}
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+uint16_t WebRtcIsacfix_GetMinBytes(RateModel *State,
+                                   int16_t StreamSize,                    /* bytes in bitstream */
+                                   const int16_t FrameSamples,            /* samples per frame */
+                                   const int16_t BottleNeck,        /* bottle neck rate; excl headers (bps) */
+                                   const int16_t DelayBuildUp)      /* max delay from bottle neck buffering (ms) */
+{
+  int32_t MinRate = 0;
+  uint16_t    MinBytes;
+  int16_t TransmissionTime;
+  int32_t inv_Q12;
+  int32_t den;
+
+
+  /* first 10 packets @ low rate, then INIT_BURST_LEN packets @ fixed rate of INIT_RATE bps */
+  if (State->InitCounter > 0) {
+    if (State->InitCounter-- <= INIT_BURST_LEN) {
+      MinRate = INIT_RATE;
+    } else {
+      MinRate = 0;
+    }
+  } else {
+    /* handle burst */
+    if (State->BurstCounter) {
+      if (State->StillBuffered <
+          (((512 - 512 / BURST_LEN) * DelayBuildUp) >> 9)) {
+        /* max bps derived from BottleNeck and DelayBuildUp values */
+        inv_Q12 = 4096 / (BURST_LEN * FrameSamples);
+        MinRate = (512 + SAMPLES_PER_MSEC * ((DelayBuildUp * inv_Q12) >> 3)) *
+            BottleNeck;
+      } else {
+        /* max bps derived from StillBuffered and DelayBuildUp values */
+        inv_Q12 = 4096 / FrameSamples;
+        if (DelayBuildUp > State->StillBuffered) {
+          MinRate = (512 + SAMPLES_PER_MSEC * (((DelayBuildUp -
+              State->StillBuffered) * inv_Q12) >> 3)) * BottleNeck;
+        } else if ((den = WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, (State->StillBuffered - DelayBuildUp))) >= FrameSamples) {
+          /* MinRate will be negative here */
+          MinRate = 0;
+        } else {
+          MinRate = (512 - ((den * inv_Q12) >> 3)) * BottleNeck;
+        }
+        //if (MinRate < 1.04 * BottleNeck)
+        //    MinRate = 1.04 * BottleNeck;
+        //Q9
+        if (MinRate < WEBRTC_SPL_MUL(532, BottleNeck)) {
+          MinRate += WEBRTC_SPL_MUL(22, BottleNeck);
+        }
+      }
+
+      State->BurstCounter--;
+    }
+  }
+
+
+  /* convert rate from bits/second to bytes/packet */
+  //round and shift before conversion
+  MinRate += 256;
+  MinRate >>= 9;
+  MinBytes = MinRate * FrameSamples / FS8;
+
+  /* StreamSize will be adjusted if less than MinBytes */
+  if (StreamSize < MinBytes) {
+    StreamSize = MinBytes;
+  }
+
+  /* keep track of when bottle neck was last exceeded by at least 1% */
+  //517/512 ~ 1.01
+  if ((StreamSize * (int32_t)FS8) / FrameSamples > (517 * BottleNeck) >> 9) {
+    if (State->PrevExceed) {
+      /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+      State->ExceedAgo -= BURST_INTERVAL / (BURST_LEN - 1);
+      if (State->ExceedAgo < 0) {
+        State->ExceedAgo = 0;
+      }
+    } else {
+      State->ExceedAgo += FrameSamples / SAMPLES_PER_MSEC;  /* ms */
+      State->PrevExceed = 1;
+    }
+  } else {
+    State->PrevExceed = 0;
+    State->ExceedAgo += FrameSamples / SAMPLES_PER_MSEC;  /* ms */
+  }
+
+  /* set burst flag if bottle neck not exceeded for long time */
+  if ((State->ExceedAgo > BURST_INTERVAL) && (State->BurstCounter == 0)) {
+    if (State->PrevExceed) {
+      State->BurstCounter = BURST_LEN - 1;
+    } else {
+      State->BurstCounter = BURST_LEN;
+    }
+  }
+
+
+  /* Update buffer delay */
+  TransmissionTime = (StreamSize * 8000) / BottleNeck;  /* ms */
+  State->StillBuffered += TransmissionTime;
+  State->StillBuffered -= FrameSamples / SAMPLES_PER_MSEC;   /* ms */
+  if (State->StillBuffered < 0) {
+    State->StillBuffered = 0;
+  }
+
+  if (State->StillBuffered > 2000) {
+    State->StillBuffered = 2000;
+  }
+
+  return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(RateModel *State,
+                                   int16_t StreamSize,                    /* bytes in bitstream */
+                                   const int16_t FrameSamples,            /* samples per frame */
+                                   const int16_t BottleNeck)        /* bottle neck rate; excl headers (bps) */
+{
+  const int16_t TransmissionTime = (StreamSize * 8000) / BottleNeck;  /* ms */
+
+  /* avoid the initial "high-rate" burst */
+  State->InitCounter = 0;
+
+  /* Update buffer delay */
+  State->StillBuffered += TransmissionTime;
+  State->StillBuffered -= FrameSamples >> 4;  /* ms */
+  if (State->StillBuffered < 0) {
+    State->StillBuffered = 0;
+  }
+
+}
+
+
+void WebRtcIsacfix_InitRateModel(RateModel *State)
+{
+  State->PrevExceed      = 0;                        /* boolean */
+  State->ExceedAgo       = 0;                        /* ms */
+  State->BurstCounter    = 0;                        /* packets */
+  State->InitCounter     = INIT_BURST_LEN + 10;    /* packets */
+  State->StillBuffered   = 1;                    /* ms */
+}
+
+
+
+
+
+int16_t WebRtcIsacfix_GetNewFrameLength(int16_t bottle_neck, int16_t current_framesamples)
+{
+  int16_t new_framesamples;
+
+  new_framesamples = current_framesamples;
+
+  /* find new framelength */
+  switch(current_framesamples) {
+    case 480:
+      if (bottle_neck < Thld_30_60) {
+        new_framesamples = 960;
+      }
+      break;
+    case 960:
+      if (bottle_neck >= Thld_60_30) {
+        new_framesamples = 480;
+      }
+      break;
+    default:
+      new_framesamples = -1; /* Error */
+  }
+
+  return new_framesamples;
+}
+
+int16_t WebRtcIsacfix_GetSnr(int16_t bottle_neck, int16_t framesamples)
+{
+  int16_t s2nr = 0;
+
+  /* find new SNR value */
+  //consider BottleNeck to be in Q10 ( * 1 in Q10)
+  switch(framesamples) {
+  // TODO(bjornv): The comments below confuses me. I don't know if there is a
+  // difference between frame lengths (in which case the implementation is
+  // wrong), or if it is frame length independent in which case we should
+  // correct the comment and simplify the implementation.
+    case 480:
+      /*s2nr = -1*(a_30 << 10) + ((b_30 * bottle_neck) >> 10);*/
+      s2nr = -22500 + (int16_t)(500 * bottle_neck >> 10);
+      break;
+    case 960:
+      /*s2nr = -1*(a_60 << 10) + ((b_60 * bottle_neck) >> 10);*/
+      s2nr = -22500 + (int16_t)(500 * bottle_neck >> 10);
+      break;
+    default:
+      s2nr = -1; /* Error */
+  }
+
+  return s2nr; //return in Q10
+
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h b/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
new file mode 100644
index 0000000..f106746
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ *      - bwest_str        : Struct containing bandwidth information.
+ *
+ * Return value            : 0
+ */
+
+int32_t WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr* bwest_str);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ *      - bweStr           : struct containing bandwidth information.
+ *      - rtpNumber        : value from RTP packet, from NetEq
+ *      - frameSize        : length of signal frame in ms, from iSAC decoder
+ *      - sendTime         : value in RTP header giving send time in samples
+ *      - arrivalTime      : value given by timeGetTime() time of arrival in
+ *                           samples of packet from NetEq
+ *      - pksize           : size of packet in bytes, from NetEq
+ *      - Index            : integer (range 0...23) indicating bottle neck &
+ *                           jitter as estimated by other side
+ *
+ * Return value            : 0 if everything went fine,
+ *                           -1 otherwise
+ */
+
+int32_t WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr* bwest_str,
+                                         uint16_t rtp_number,
+                                         int16_t frameSize,
+                                         uint32_t send_ts,
+                                         uint32_t arr_ts,
+                                         size_t pksize,
+                                         uint16_t Index);
+
+/* Update receiving estimates. Used when we only receive BWE index, no iSAC data
+ * packet. */
+int16_t WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr* bwest_str,
+                                        int16_t Index);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ *      - bweStr       : BWE struct
+ *
+ * Return:
+ *      bandwith and jitter index (0..23)
+ */
+uint16_t WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth estimation (in bps) */
+uint16_t WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth that iSAC should send with in bps */
+int16_t WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay (in ms) */
+int16_t WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay value from the other side in ms */
+int16_t WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+uint16_t WebRtcIsacfix_GetMinBytes(
+    RateModel* State,
+    int16_t StreamSize,    /* bytes in bitstream */
+    int16_t FrameLen,      /* ms per frame */
+    int16_t BottleNeck,    /* bottle neck rate; excl headers (bps) */
+    int16_t DelayBuildUp); /* max delay from bottle neck buffering (ms) */
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(
+    RateModel* State,
+    int16_t StreamSize,   /* bytes in bitstream */
+    int16_t FrameSamples, /* samples per frame */
+    int16_t BottleNeck);  /* bottle neck rate; excl headers (bps) */
+
+void WebRtcIsacfix_InitRateModel(RateModel* State);
+
+/* Returns the new framelength value (input argument: bottle_neck) */
+int16_t WebRtcIsacfix_GetNewFrameLength(int16_t bottle_neck,
+                                        int16_t current_framelength);
+
+/* Returns the new SNR value (input argument: bottle_neck) */
+// returns snr in Q10
+int16_t WebRtcIsacfix_GetSnr(int16_t bottle_neck, int16_t framesamples);
+
+#endif /*  MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_ \
+        */
diff --git a/modules/audio_coding/codecs/isac/fix/source/codec.h b/modules/audio_coding/codecs/isac/fix/source/codec.h
new file mode 100644
index 0000000..01d6fb9
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/codec.h
@@ -0,0 +1,212 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr* bwest_str,
+                                    Bitstr_dec* streamdata,
+                                    size_t packet_size,
+                                    uint16_t rtp_seq_number,
+                                    uint32_t send_ts,
+                                    uint32_t arr_ts);
+
+int WebRtcIsacfix_DecodeImpl(int16_t* signal_out16,
+                             IsacFixDecoderInstance* ISACdec_obj,
+                             size_t* current_framesamples);
+
+void WebRtcIsacfix_DecodePlcImpl(int16_t* decoded,
+                                 IsacFixDecoderInstance* ISACdec_obj,
+                                 size_t* current_framesample);
+
+int WebRtcIsacfix_EncodeImpl(int16_t* in,
+                             IsacFixEncoderInstance* ISACenc_obj,
+                             BwEstimatorstr* bw_estimatordata,
+                             int16_t CodingMode);
+
+int WebRtcIsacfix_EncodeStoredData(IsacFixEncoderInstance* ISACenc_obj,
+                                   int BWnumber,
+                                   float scale);
+
+/* initialization functions */
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc* maskdata);
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec* maskdata);
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr* prefiltdata);
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr* postfiltdata);
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr* pitchfiltdata);
+
+void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct* State);
+
+void WebRtcIsacfix_InitPlc(PLCstr* State);
+
+/* transform functions */
+
+void WebRtcIsacfix_InitTransform(void);
+
+typedef void (*Time2Spec)(int16_t* inre1Q9,
+                          int16_t* inre2Q9,
+                          int16_t* outre,
+                          int16_t* outim);
+typedef void (*Spec2Time)(int16_t* inreQ7,
+                          int16_t* inimQ7,
+                          int32_t* outre1Q16,
+                          int32_t* outre2Q16);
+
+extern Time2Spec WebRtcIsacfix_Time2Spec;
+extern Spec2Time WebRtcIsacfix_Spec2Time;
+
+void WebRtcIsacfix_Time2SpecC(int16_t* inre1Q9,
+                              int16_t* inre2Q9,
+                              int16_t* outre,
+                              int16_t* outim);
+void WebRtcIsacfix_Spec2TimeC(int16_t* inreQ7,
+                              int16_t* inimQ7,
+                              int32_t* outre1Q16,
+                              int32_t* outre2Q16);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
+                                 int16_t* inre2Q9,
+                                 int16_t* outre,
+                                 int16_t* outim);
+void WebRtcIsacfix_Spec2TimeNeon(int16_t* inreQ7,
+                                 int16_t* inimQ7,
+                                 int32_t* outre1Q16,
+                                 int32_t* outre2Q16);
+#endif
+
+#if defined(MIPS32_LE)
+void WebRtcIsacfix_Time2SpecMIPS(int16_t* inre1Q9,
+                                 int16_t* inre2Q9,
+                                 int16_t* outre,
+                                 int16_t* outim);
+void WebRtcIsacfix_Spec2TimeMIPS(int16_t* inreQ7,
+                                 int16_t* inimQ7,
+                                 int32_t* outre1Q16,
+                                 int32_t* outre2Q16);
+#endif
+
+/* filterbank functions */
+
+void WebRtcIsacfix_SplitAndFilter1(int16_t* in,
+                                   int16_t* LP16,
+                                   int16_t* HP16,
+                                   PreFiltBankstr* prefiltdata);
+
+void WebRtcIsacfix_FilterAndCombine1(int16_t* tempin_ch1,
+                                     int16_t* tempin_ch2,
+                                     int16_t* out16,
+                                     PostFiltBankstr* postfiltdata);
+
+/* normalized lattice filters */
+
+void WebRtcIsacfix_NormLatticeFilterMa(size_t orderCoef,
+                                       int32_t* stateGQ15,
+                                       int16_t* lat_inQ0,
+                                       int16_t* filt_coefQ15,
+                                       int32_t* gain_lo_hiQ17,
+                                       int16_t lo_hi,
+                                       int16_t* lat_outQ9);
+
+void WebRtcIsacfix_NormLatticeFilterAr(size_t orderCoef,
+                                       int16_t* stateGQ0,
+                                       int32_t* lat_inQ25,
+                                       int16_t* filt_coefQ15,
+                                       int32_t* gain_lo_hiQ17,
+                                       int16_t lo_hi,
+                                       int16_t* lat_outQ0);
+
+/* TODO(kma): Remove the following functions into individual header files. */
+
+/* Internal functions in both C and ARM Neon versions */
+
+int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
+                            const int16_t* __restrict x,
+                            int16_t N,
+                            int16_t order,
+                            int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0,
+                                 int16_t input1,
+                                 int32_t input2,
+                                 int32_t* ptr0,
+                                 int32_t* ptr1,
+                                 int32_t* ptr2);
+
+#if defined(WEBRTC_HAS_NEON)
+int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
+                               const int16_t* __restrict x,
+                               int16_t N,
+                               int16_t order,
+                               int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
+                                    int16_t input1,
+                                    int32_t input2,
+                                    int32_t* ptr0,
+                                    int32_t* ptr1,
+                                    int32_t* ptr2);
+#endif
+
+#if defined(MIPS32_LE)
+int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
+                               const int16_t* __restrict x,
+                               int16_t N,
+                               int16_t order,
+                               int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopMIPS(int16_t input0,
+                                    int16_t input1,
+                                    int32_t input2,
+                                    int32_t* ptr0,
+                                    int32_t* ptr1,
+                                    int32_t* ptr2);
+#endif
+
+/* Function pointers associated with the above functions. */
+
+typedef int (*AutocorrFix)(int32_t* __restrict r,
+                           const int16_t* __restrict x,
+                           int16_t N,
+                           int16_t order,
+                           int16_t* __restrict scale);
+extern AutocorrFix WebRtcIsacfix_AutocorrFix;
+
+typedef void (*FilterMaLoopFix)(int16_t input0,
+                                int16_t input1,
+                                int32_t input2,
+                                int32_t* ptr0,
+                                int32_t* ptr1,
+                                int32_t* ptr2);
+extern FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/decode.c b/modules/audio_coding/codecs/isac/fix/source/decode.c
new file mode 100644
index 0000000..1442088
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/decode.c
@@ -0,0 +1,221 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode.c
+ *
+ * This C file contains the internal decoding function.
+ *
+ */
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+
+
+int WebRtcIsacfix_DecodeImpl(int16_t* signal_out16,
+                             IsacFixDecoderInstance* ISACdec_obj,
+                             size_t* current_framesamples)
+{
+  int k;
+  int err;
+  int16_t BWno;
+  int len = 0;
+
+  int16_t model;
+
+
+  int16_t Vector_Word16_1[FRAMESAMPLES/2];
+  int16_t Vector_Word16_2[FRAMESAMPLES/2];
+
+  int32_t Vector_Word32_1[FRAMESAMPLES/2];
+  int32_t Vector_Word32_2[FRAMESAMPLES/2];
+
+  int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+  int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+  int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+  int16_t PitchLags_Q7[PITCH_SUBFRAMES];
+  int16_t PitchGains_Q12[PITCH_SUBFRAMES];
+  int16_t AvgPitchGain_Q12;
+
+  int16_t tmp_1, tmp_2;
+  int32_t tmp32a;
+  int16_t gainQ13;
+
+
+  size_t frame_nb; /* counter */
+  size_t frame_mode; /* 0 for 30ms, 1 for 60ms */
+  static const size_t kProcessedSamples = 480; /* 480 (for both 30, 60 ms) */
+
+  /* PLC */
+  int16_t overlapWin[ 240 ];
+
+  (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
+  (ISACdec_obj->bitstr_obj).streamval = 0;
+  (ISACdec_obj->bitstr_obj).stream_index = 0;
+  (ISACdec_obj->bitstr_obj).full = 1;
+
+
+  /* decode framelength and BW estimation - not used, only for stream pointer*/
+  err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples);
+  if (err<0)  // error check
+    return err;
+
+  frame_mode = *current_framesamples / MAX_FRAMESAMPLES;  /* 0, or 1 */
+
+  err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno);
+  if (err<0)  // error check
+    return err;
+
+  /* one loop if it's one frame (30ms), two loops if two frames bundled together
+   * (60ms) */
+  for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+
+    /* decode & dequantize pitch parameters */
+    err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12);
+    if (err<0)  // error check
+      return err;
+
+    err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7);
+    if (err<0)  // error check
+      return err;
+
+    AvgPitchGain_Q12 = (int16_t)(((int32_t)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2);
+
+    /* decode & dequantize FiltCoef */
+    err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+                                  &ISACdec_obj->bitstr_obj, &model);
+
+    if (err<0)  // error check
+      return err;
+
+    /* decode & dequantize spectrum */
+    len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12);
+    if (len < 0)  // error check
+      return len;
+
+    // Why does this need Q16 in and out? /JS
+    WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2);
+
+    for (k=0; k<FRAMESAMPLES/2; k++) {
+      // Q16 -> Q9.
+      Vector_Word16_1[k] = (int16_t)((Vector_Word32_1[k] + 64) >> 7);
+    }
+
+    /* ----  If this is recovery frame ---- */
+    if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED )
+    {
+      (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED;
+      if( (ISACdec_obj->plcstr_obj).B < 1000 )
+      {
+        (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000;
+      }
+
+      ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX;    /* DECAY_RATE is in Q15 */
+      ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX;    /* DECAY_RATE is in Q15 */
+      ISACdec_obj->plcstr_obj.pitchCycles = 0;
+
+      PitchGains_Q12[0] = (int16_t)(PitchGains_Q12[0] * 700 >> 10);
+
+      /* ---- Add-overlap ---- */
+      WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP );
+      for( k = 0; k < RECOVERY_OVERLAP; k++ )
+        Vector_Word16_1[k] = WebRtcSpl_AddSatW16(
+            (int16_t)(ISACdec_obj->plcstr_obj.overlapLP[k] *
+                overlapWin[RECOVERY_OVERLAP - k - 1] >> 14),
+            (int16_t)(Vector_Word16_1[k] * overlapWin[k] >> 14));
+
+
+
+    }
+
+    /* --- Store side info --- */
+    if( frame_nb == frame_mode )
+    {
+      /* --- LPC info */
+      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO );
+      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI );
+      (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2];
+      (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1];
+
+      /* --- LTP info */
+      (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3];
+      (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3];
+      (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3];
+
+      if( PitchLags_Q7[3] < 3000 )
+        (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3];
+
+      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 );
+
+    }
+    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    /* inverse pitch filter */
+    WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4);
+
+    if( frame_nb == frame_mode )
+    {
+      WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG );
+    }
+
+
+    /* reduce gain to compensate for pitch enhancer */
+    /* gain = 1.0f - 0.45f * AvgPitchGain; */
+    tmp32a = AvgPitchGain_Q12 * 29;  // Q18
+    gainQ13 = (int16_t)((262144 - tmp32a) >> 5);  // Q18 -> Q13.
+
+    for (k = 0; k < FRAMESAMPLES/2; k++)
+    {
+      Vector_Word32_1[k] = (Vector_Word16_2[k] * gainQ13) * (1 << 3);  // Q25
+    }
+
+
+    /* perceptual post-filtering (using normalized lattice filter) */
+    WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+                                      Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+    /* --- Store Highpass Residual --- */
+    for (k = 0; k < FRAMESAMPLES/2; k++)
+      Vector_Word32_1[k] = Vector_Word32_2[k] * (1 << 9);  // Q16 -> Q25
+
+    for( k = 0; k < PITCH_MAX_LAG + 10; k++ )
+      (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k];
+
+
+    WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+                                      Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+    /* recombine the 2 bands */
+
+    /* Form the polyphase signals, and compensate for DC offset */
+    for (k=0;k<FRAMESAMPLES/2;k++) {
+      tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/
+      tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/
+      Vector_Word16_1[k] = tmp_1;
+      Vector_Word16_2[k] = tmp_2;
+    }
+
+    WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
+                                    Vector_Word16_2,
+                                    signal_out16 + frame_nb * kProcessedSamples,
+                                    &ISACdec_obj->postfiltbankstr_obj);
+
+  }
+  return len;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c b/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
new file mode 100644
index 0000000..9967650
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_bwe.c
+ *
+ * This C file contains the internal decode bandwidth estimate function.
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr *bwest_str,
+                                    Bitstr_dec  *streamdata,
+                                    size_t packet_size,
+                                    uint16_t rtp_seq_number,
+                                    uint32_t send_ts,
+                                    uint32_t arr_ts)
+{
+  int16_t index;
+  size_t frame_samples;
+  int err;
+
+  /* decode framelength */
+  err = WebRtcIsacfix_DecodeFrameLen(streamdata, &frame_samples);
+  /* error check */
+  if (err<0) {
+    return err;
+  }
+
+  /* decode BW estimation */
+  err = WebRtcIsacfix_DecodeSendBandwidth(streamdata, &index);
+  /* error check */
+  if (err<0) {
+    return err;
+  }
+
+  /* Update BWE with received data */
+  err = WebRtcIsacfix_UpdateUplinkBwImpl(
+      bwest_str,
+      rtp_seq_number,
+      (int16_t)(frame_samples * 1000 / FS),
+      send_ts,
+      arr_ts,
+      packet_size,  /* in bytes */
+      index);
+
+  /* error check */
+  if (err<0) {
+    return err;
+  }
+
+  /* Succesful */
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/decode_plc.c b/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
new file mode 100644
index 0000000..873cf95
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
@@ -0,0 +1,805 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_plc.c
+ *
+ * Packet Loss Concealment.
+ *
+ */
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+
+#define NO_OF_PRIMES 8
+#define NOISE_FILTER_LEN 30
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+
+static int16_t plc_filterma_Fast(
+    int16_t *In,  /* (i)   Vector to be filtered. InOut[-orderCoef+1]
+                           to InOut[-1] contains state */
+    int16_t *Out,  /* (o)   Filtered vector */
+    int16_t *B,   /* (i)   The filter coefficients (in Q0) */
+    int16_t Blen,  /* (i)   Number of B coefficients */
+    int16_t len,   /* (i)  Number of samples to be filtered */
+    int16_t reduceDecay,
+    int16_t decay,
+    int16_t rshift )
+{
+  int i, j;
+  int32_t o;
+  int32_t lim = (1 << (15 + rshift)) - 1;
+
+  for (i = 0; i < len; i++)
+  {
+    const int16_t *b_ptr = &B[0];
+    const int16_t *x_ptr = &In[i];
+
+    o = (int32_t)0;
+
+    for (j = 0;j < Blen; j++)
+    {
+      o = WebRtcSpl_AddSatW32(o, *b_ptr * *x_ptr);
+      b_ptr++;
+      x_ptr--;
+    }
+
+    /* to round off correctly */
+    o = WebRtcSpl_AddSatW32(o, 1 << (rshift - 1));
+
+    /* saturate according to the domain of the filter coefficients */
+    o = WEBRTC_SPL_SAT((int32_t)lim, o, (int32_t)-lim);
+
+    /* o should be in the range of int16_t */
+    o >>= rshift;
+
+    /* decay the output signal; this is specific to plc */
+    *Out++ = (int16_t)((int16_t)o * decay >> 15);
+
+    /* change the decay */
+    decay -= reduceDecay;
+    if( decay < 0 )
+      decay = 0;
+  }
+  return( decay );
+}
+
+
+
+
+
+
+
+
+static __inline int32_t log2_Q8_T( uint32_t x ) {
+
+  int32_t zeros;
+  int16_t frac;
+
+  zeros=WebRtcSpl_NormU32(x);
+  frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+
+  /* log2(magn(i)) */
+  return ((31 - zeros) << 8) + frac;
+}
+
+static __inline int16_t  exp2_Q10_T(int16_t x) { // Both in and out in Q10
+
+  int16_t tmp16_1, tmp16_2;
+
+  tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+  tmp16_1 = -(x >> 10);
+  if(tmp16_1>0)
+    return tmp16_2 >> tmp16_1;
+  else
+    return tmp16_2 << -tmp16_1;
+
+}
+
+
+/*
+  This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
+  hard-coded. The values 700 and 5000 were experimentally obtained.
+
+  The function implements membership values for two sets. The mebership functions are
+  of second orders corresponding to half-bell-shapped pulses.
+*/
+static void MemshipValQ15( int16_t in, int16_t *A, int16_t *B )
+{
+  int16_t x;
+
+  in -= 700;    /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
+
+  if( in <= 2150 )
+  {
+    if( in > 0 )
+    {
+      /* b = in^2 / (2 * M^2), a = 1 - b in Q0.
+         We have to compute in Q15 */
+
+      /* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
+         x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999     */
+
+      /* we are sure that x is in the range of int16_t            */
+      x = (int16_t)(in * 15 + (in * 983 >> 12));
+      /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+         be in correct domain and one more for the division by 2 */
+      *B = (int16_t)((x * x + 0x00010000) >> 17);
+      *A = WEBRTC_SPL_WORD16_MAX - *B;
+    }
+    else
+    {
+      *B = 0;
+      *A = WEBRTC_SPL_WORD16_MAX;
+    }
+  }
+  else
+  {
+    if( in < 4300 )
+    {
+      /* This is a mirror case of the above */
+      in = 4300 - in;
+      x = (int16_t)(in * 15 + (in * 983 >> 12));
+      /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+         be in correct domain and one more for the division by 2 */
+      *A = (int16_t)((x * x + 0x00010000) >> 17);
+      *B = WEBRTC_SPL_WORD16_MAX - *A;
+
+    }
+    else
+    {
+      *A = 0;
+      *B = WEBRTC_SPL_WORD16_MAX;
+    }
+  }
+}
+
+
+
+
+static void LinearResampler(int16_t* in,
+                            int16_t* out,
+                            size_t lenIn,
+                            size_t lenOut)
+{
+  size_t n = (lenIn - 1) * RESAMP_RES;
+  int16_t resOut, relativePos, diff; /* */
+  size_t i, j;
+  uint16_t udiff;
+
+  if( lenIn == lenOut )
+  {
+    WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
+    return;
+  }
+
+  resOut = WebRtcSpl_DivW32W16ResW16( (int32_t)n, (int16_t)(lenOut-1) );
+
+  out[0] = in[0];
+  for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
+  {
+
+    relativePos += resOut;
+    while( relativePos > RESAMP_RES )
+    {
+      j++;
+      relativePos -= RESAMP_RES;
+    }
+
+
+    /* an overflow may happen and the differce in sample values may
+     * require more than 16 bits. We like to avoid 32 bit arithmatic
+     * as much as possible */
+
+    if( (in[ j ] > 0) && (in[j + 1] < 0) )
+    {
+      udiff = (uint16_t)(in[ j ] - in[j + 1]);
+      out[ i ] = in[ j ] - (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
+    }
+    else
+    {
+      if( (in[j] < 0) && (in[j+1] > 0) )
+      {
+        udiff = (uint16_t)( in[j + 1] - in[ j ] );
+        out[ i ] = in[ j ] + (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
+      }
+      else
+      {
+        diff = in[ j + 1 ] - in[ j ];
+        out[i] = in[j] + (int16_t)(diff * relativePos >> RESAMP_RES_BIT);
+      }
+    }
+  }
+}
+
+
+
+
+
+void WebRtcIsacfix_DecodePlcImpl(int16_t *signal_out16,
+                                 IsacFixDecoderInstance *ISACdec_obj,
+                                 size_t *current_framesamples )
+{
+  int subframecnt;
+
+  int16_t* Vector_Word16_1;
+  int16_t  Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+  int16_t* Vector_Word16_2;
+  int16_t  Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+
+  int32_t Vector_Word32_1[FRAMESAMPLES_HALF];
+  int32_t Vector_Word32_2[FRAMESAMPLES_HALF];
+
+  int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+  int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+
+  int16_t pitchLags_Q7[PITCH_SUBFRAMES];
+  int16_t pitchGains_Q12[PITCH_SUBFRAMES];
+
+  int16_t tmp_1, tmp_2;
+  int32_t tmp32a, tmp32b;
+  int16_t gainQ13;
+
+  int16_t myDecayRate;
+
+  /* ---------- PLC variables ------------ */
+  size_t lag0, i, k;
+  int16_t noiseIndex;
+  int16_t stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
+
+  int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+  int16_t nLP, pLP, wNoisyLP, wPriodicLP, tmp16;
+  size_t minIdx;
+  int32_t nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
+  int16_t noise1, rshift;
+
+
+  int16_t ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
+  int32_t varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
+  int rightShiftIn, rightShiftOut;
+
+
+  /* ------------------------------------- */
+
+
+  myDecayRate = (DECAY_RATE);
+  Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
+  Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
+
+
+  /* ----- Simply Copy Previous LPC parameters ------ */
+  for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
+  {
+    /* lower Band */
+    WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
+                          (ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
+    gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
+
+    /* Upper Band */
+    WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
+                          (ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
+    gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
+  }
+
+
+
+
+  lag0 = (size_t)(((ISACdec_obj->plcstr_obj.lastPitchLag_Q7 + 64) >> 7) + 1);
+
+
+  if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
+  {
+    (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+
+    (ISACdec_obj->plcstr_obj).lastPitchLP =
+        &((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
+    minCorr = WEBRTC_SPL_WORD32_MAX;
+
+    if ((FRAMESAMPLES_HALF - 10) > 2 * lag0)
+    {
+      minIdx = 11;
+      for( i = 0; i < 21; i++ )
+      {
+        corr = 0;
+        for( k = 0; k < lag0; k++ )
+        {
+          corr = WebRtcSpl_AddSatW32(corr, WEBRTC_SPL_ABS_W32(
+              WebRtcSpl_SubSatW16(
+                  (ISACdec_obj->plcstr_obj).lastPitchLP[k],
+                  (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+                      FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
+        }
+        if( corr < minCorr )
+        {
+          minCorr = corr;
+          minIdx = i;
+        }
+      }
+      (ISACdec_obj->plcstr_obj).prevPitchLP =
+          &( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+              FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
+    }
+    else
+    {
+      (ISACdec_obj->plcstr_obj).prevPitchLP =
+          (ISACdec_obj->plcstr_obj).lastPitchLP;
+    }
+    pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
+
+    WebRtcSpl_AutoCorrelation(
+        &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
+        lag0, 0, &varIn, &rightShiftIn);
+    WebRtcSpl_AutoCorrelation(
+        &(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
+        lag0, 0, &varOut, &rightShiftOut);
+
+    maxAbs = 0;
+    for( i = 0; i< lag0; i++)
+    {
+      myAbs = WEBRTC_SPL_ABS_W16(
+          (ISACdec_obj->plcstr_obj).prevPitchInvOut[
+              PITCH_MAX_LAG + 10 - lag0 + i] );
+      maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
+    }
+    logVarIn = log2_Q8_T( (uint32_t)( varIn ) ) +
+        (int32_t)(rightShiftIn << 8);
+    logVarOut = log2_Q8_T( (uint32_t)( varOut ) ) +
+        (int32_t)(rightShiftOut << 8);
+    logMaxAbs = log2_Q8_T( (uint32_t)( maxAbs ) );
+
+    ltpGain = (int16_t)(logVarOut - logVarIn);
+    Q = 2 * logMaxAbs - ( logVarOut - 1512 );
+
+    /*
+     * ---
+     * We are computing sqrt( (VarIn/lag0) / var( noise ) )
+     * var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
+     * so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) )  ).
+     * Note that put log function is in Q8 but the exponential function is in Q10.
+     * --
+     */
+
+    logVarIn -= log2_Q8_T( (uint32_t)( lag0 ) );
+    tmp16 = (int16_t)((logVarIn<<1) - (4<<10) );
+    rightShiftIn = 0;
+    if( tmp16 > 4096 )
+    {
+      tmp16 -= 4096;
+      tmp16 = exp2_Q10_T( tmp16 );
+      tmp16 >>= 6;
+    }
+    else
+      tmp16 = exp2_Q10_T( tmp16 )>>10;
+
+    (ISACdec_obj->plcstr_obj).std = tmp16 - 4;
+
+    if( (ltpGain < 110) || (ltpGain > 230) )
+    {
+      if( ltpGain < 100 && (pitchGain < 1800) )
+      {
+        (ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
+      }
+      else
+      {
+        (ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
+                                       )? WEBRTC_SPL_WORD16_MAX:0;
+      }
+      (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+          (ISACdec_obj->plcstr_obj).A;
+    }
+    else
+    {
+      if( (pitchGain < 450) || (pitchGain > 1600) )
+      {
+        (ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
+                                       )? WEBRTC_SPL_WORD16_MAX:0;
+        (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+            (ISACdec_obj->plcstr_obj).A;
+      }
+      else
+      {
+        myVoiceIndicator = ltpGain * 2 + pitchGain;
+        MemshipValQ15( myVoiceIndicator,
+                       &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+      }
+    }
+
+
+
+    myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
+    MemshipValQ15( myVoiceIndicator,
+                   &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+
+
+
+    (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+    (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+
+  }
+  else
+  {
+    myDecayRate = (DECAY_RATE<<2);
+  }
+
+  if( (ISACdec_obj->plcstr_obj).B < 1000 )
+  {
+    myDecayRate += (DECAY_RATE<<3);
+  }
+
+  /* ------------ reconstructing the residual signal ------------------ */
+
+  LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+                   stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+  /* inverse pitch filter */
+
+  pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
+      (int16_t)((ISACdec_obj->plcstr_obj).stretchLag<<7);
+  pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
+  pitchGains_Q12[2] = (int16_t)(pitchGains_Q12[3] * 1010 >> 10);
+  pitchGains_Q12[1] = (int16_t)(pitchGains_Q12[2] * 1010 >> 10);
+  pitchGains_Q12[0] = (int16_t)(pitchGains_Q12[1] * 1010 >> 10);
+
+
+  /* most of the time either B or A are zero so seperating */
+  if( (ISACdec_obj->plcstr_obj).B == 0 )
+  {
+    for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+    {
+      /* --- Low Pass                                             */
+      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+          (ISACdec_obj->plcstr_obj).seed );
+      Vector_Word16_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+      /* --- Highpass                                              */
+      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+          (ISACdec_obj->plcstr_obj).seed );
+      Vector_Word16_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+    }
+    for( i = 1; i < NOISE_FILTER_LEN; i++ )
+    {
+      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+          (ISACdec_obj->plcstr_obj).seed );
+      Vector_Word16_Extended_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+          (ISACdec_obj->plcstr_obj).seed );
+      Vector_Word16_Extended_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+    }
+    plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
+                      &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
+                                                                NOISE_FILTER_LEN], (int16_t) NOISE_FILTER_LEN,
+                      (int16_t) FRAMESAMPLES_HALF, (int16_t)(5),
+                      (ISACdec_obj->plcstr_obj).decayCoeffNoise, (int16_t)(6));
+
+    maxCoeff = WebRtcSpl_MaxAbsValueW32(
+        &(ISACdec_obj->plcstr_obj).prevHP[
+            PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
+
+    rshift = 0;
+    while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
+    {
+      maxCoeff >>= 1;
+      rshift++;
+    }
+    for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
+      Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =(int16_t)(
+          ISACdec_obj->plcstr_obj.prevHP[PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN +
+                                         i] >> rshift);
+    }
+    (ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
+        Vector_Word16_2,
+        Vector_Word16_Extended_2,
+        &Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
+        (int16_t) NOISE_FILTER_LEN,
+        (int16_t) FRAMESAMPLES_HALF,
+        (int16_t) (5),
+        (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+        (int16_t) (7) );
+
+    for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+      Vector_Word32_2[i] = Vector_Word16_Extended_2[i] << rshift;
+
+    Vector_Word16_1 = Vector_Word16_Extended_1;
+  }
+  else
+  {
+    if( (ISACdec_obj->plcstr_obj).A == 0 )
+    {
+      /* ------ Periodic Vector ---                                */
+      for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+      {
+        /* --- Lowpass                                               */
+        pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
+            ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+
+        /* --- Highpass                                              */
+        pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+            (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+            (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+                                             (ISACdec_obj->plcstr_obj).stretchLag +
+                                             (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+        /* --- lower the muliplier (more decay at next sample) --- */
+        (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+        if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+          (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+
+        (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+        if( (ISACdec_obj->plcstr_obj).pitchIndex ==
+            (ISACdec_obj->plcstr_obj).stretchLag )
+        {
+          (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+          (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+          if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+          {
+            (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+          }
+          else
+          {
+            (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+          }
+
+          (ISACdec_obj->plcstr_obj).stretchLag = (
+              (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+                                                  )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+
+          LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+                           stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+          LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
+                           stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+          switch( (ISACdec_obj->plcstr_obj).pitchCycles )
+          {
+            case 1:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)((
+                      (int32_t)stretchPitchLP[k]* 3 +
+                      (int32_t)stretchPitchLP1[k])>>2);
+                }
+                break;
+              }
+            case 2:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)((
+                      (int32_t)stretchPitchLP[k] +
+                      (int32_t)stretchPitchLP1[k] )>>1);
+                }
+                break;
+              }
+            case 3:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)((stretchPitchLP[k] +
+                                                       (int32_t)stretchPitchLP1[k]*3 )>>2);
+                }
+                break;
+              }
+          }
+
+          if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+          {
+            myDecayRate += 35; //(myDecayRate>>1);
+            (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+          }
+
+        }
+
+        /* ------ Sum the noisy and periodic signals  ------ */
+        Vector_Word16_1[i] = pLP;
+        Vector_Word32_2[i] = pHP;
+      }
+    }
+    else
+    {
+      for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+      {
+
+        (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+            (ISACdec_obj->plcstr_obj).seed );
+
+        noise1 = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+        nLP = (int16_t)((int16_t)(noise1 * ISACdec_obj->plcstr_obj.std) *
+            ISACdec_obj->plcstr_obj.decayCoeffNoise >> 15);
+
+        /* --- Highpass                                              */
+        (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+            (ISACdec_obj->plcstr_obj).seed );
+        noise1 = (ISACdec_obj->plcstr_obj.seed >> 11) - 8;
+
+        nHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+            (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+            (int32_t)(noise1*(ISACdec_obj->plcstr_obj).std) );
+
+        /* --- lower the muliplier (more decay at next sample) --- */
+        (ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
+        if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
+          (ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
+
+        /* ------ Periodic Vector ---                                */
+        /* --- Lowpass                                               */
+        pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
+            ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+
+        /* --- Highpass                                              */
+        pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+            (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+            (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+                                             (ISACdec_obj->plcstr_obj).stretchLag +
+                                             (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+        /* --- lower the muliplier (more decay at next sample) --- */
+        (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+        if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+        {
+          (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+        }
+
+        /* ------ Weighting the noisy and periodic vectors -------   */
+        wNoisyLP = (int16_t)(ISACdec_obj->plcstr_obj.A * nLP >> 15);
+        wNoisyHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
+            (ISACdec_obj->plcstr_obj).A, (nHP) ) );
+
+        wPriodicLP = (int16_t)(ISACdec_obj->plcstr_obj.B * pLP >> 15);
+        wPriodicHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
+            (ISACdec_obj->plcstr_obj).B, pHP));
+
+        (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+        if((ISACdec_obj->plcstr_obj).pitchIndex ==
+           (ISACdec_obj->plcstr_obj).stretchLag)
+        {
+          (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+          (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+          if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+            (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+          else
+            (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+
+          (ISACdec_obj->plcstr_obj).stretchLag = (
+              (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+                                                  )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+          LinearResampler(
+              (ISACdec_obj->plcstr_obj).lastPitchLP,
+              stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+          LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
+                          stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+          switch((ISACdec_obj->plcstr_obj).pitchCycles)
+          {
+            case 1:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)((
+                      (int32_t)stretchPitchLP[k]* 3 +
+                      (int32_t)stretchPitchLP1[k] )>>2);
+                }
+                break;
+              }
+            case 2:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)((
+                      (int32_t)stretchPitchLP[k] +
+                      (int32_t)stretchPitchLP1[k])>>1);
+                }
+                break;
+              }
+            case 3:
+              {
+                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+                {
+                  stretchPitchLP[k] = (int16_t)(
+                      (stretchPitchLP[k] +
+                       (int32_t)stretchPitchLP1[k]*3 )>>2);
+                }
+                break;
+              }
+          }
+
+          if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+          {
+            myDecayRate += 55; //(myDecayRate>>1);
+            (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+          }
+        }
+
+        /* ------ Sum the noisy and periodic signals  ------ */
+        Vector_Word16_1[i] = WebRtcSpl_AddSatW16(wNoisyLP, wPriodicLP);
+        Vector_Word32_2[i] = WebRtcSpl_AddSatW32(wNoisyHP, wPriodicHP);
+      }
+    }
+  }
+  /* ----------------- residual signal is reconstructed ------------------ */
+
+  k = (ISACdec_obj->plcstr_obj).pitchIndex;
+  /* --- Write one pitch cycle for recovery block --- */
+
+  for( i = 0; i < RECOVERY_OVERLAP; i++ )
+  {
+    ISACdec_obj->plcstr_obj.overlapLP[i] = (int16_t)(
+        stretchPitchLP[k] * ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+    k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
+  }
+
+  (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 =
+      (int16_t)((ISACdec_obj->plcstr_obj).stretchLag << 7);
+
+
+  /* --- Inverse Pitch Filter --- */
+  WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
+                            &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
+
+  /* reduce gain to compensate for pitch enhancer */
+  /* gain = 1.0f - 0.45f * AvgPitchGain; */
+  tmp32a = ISACdec_obj->plcstr_obj.AvgPitchGain_Q12 * 29;  // Q18
+  tmp32b = 262144 - tmp32a;  // Q18
+  gainQ13 = (int16_t) (tmp32b >> 5); // Q13
+
+  /* perceptual post-filtering (using normalized lattice filter) */
+  for (k = 0; k < FRAMESAMPLES_HALF; k++)
+    Vector_Word32_1[k] = (Vector_Word16_2[k] * gainQ13) << 3;  // Q25
+
+
+  WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
+                                    (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+                                    Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+  WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
+                                    (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+                                    Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+  /* recombine the 2 bands */
+
+  /* Form the polyphase signals, and compensate for DC offset */
+  for (k=0;k<FRAMESAMPLES_HALF;k++)
+  {
+    /* Construct a new upper channel signal*/
+    tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(
+                                           ((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
+    /* Construct a new lower channel signal*/
+    tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(
+                                           ((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k]));
+    Vector_Word16_1[k] = tmp_1;
+    Vector_Word16_2[k] = tmp_2;
+  }
+
+
+  WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
+                                  Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
+
+  (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
+  *current_framesamples = 480;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/encode.c b/modules/audio_coding/codecs/isac/fix/source/encode.c
new file mode 100644
index 0000000..ef3e320
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/encode.c
@@ -0,0 +1,635 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * Encoding function for the iSAC coder.
+ *
+ */
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+#include <stdio.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+int WebRtcIsacfix_EncodeImpl(int16_t      *in,
+                             IsacFixEncoderInstance  *ISACenc_obj,
+                             BwEstimatorstr      *bw_estimatordata,
+                             int16_t         CodingMode)
+{
+  int16_t stream_length = 0;
+  int16_t usefulstr_len = 0;
+  int k;
+  int16_t BWno;
+
+  int16_t lofilt_coefQ15[(ORDERLO)*SUBFRAMES];
+  int16_t hifilt_coefQ15[(ORDERHI)*SUBFRAMES];
+  int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+  int16_t LPandHP[FRAMESAMPLES/2 + QLOOKAHEAD];
+  int16_t LP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+  int16_t HP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+
+  int16_t PitchLags_Q7[PITCH_SUBFRAMES];
+  int16_t PitchGains_Q12[PITCH_SUBFRAMES];
+  int16_t AvgPitchGain_Q12;
+
+  int16_t frame_mode; /* 0 for 30ms, 1 for 60ms */
+  int16_t processed_samples;
+  int status;
+
+  int32_t bits_gainsQ11;
+  int16_t MinBytes;
+  int16_t bmodel;
+
+  transcode_obj transcodingParam;
+  int16_t payloadLimitBytes;
+  int16_t arithLenBeforeEncodingDFT;
+  int16_t iterCntr;
+
+  /* copy new frame length and bottle neck rate only for the first 10 ms data */
+  if (ISACenc_obj->buffer_index == 0) {
+    /* set the framelength for the next packet */
+    ISACenc_obj->current_framesamples = ISACenc_obj->new_framelength;
+  }
+
+  frame_mode = ISACenc_obj->current_framesamples/MAX_FRAMESAMPLES; /* 0 (30 ms) or 1 (60 ms)  */
+  processed_samples = ISACenc_obj->current_framesamples/(frame_mode+1); /* 480 (30, 60 ms) */
+
+  /* buffer speech samples (by 10ms packet) until the framelength is reached (30 or 60 ms) */
+  /**************************************************************************************/
+  /* fill the buffer with 10ms input data */
+  for(k=0; k<FRAMESAMPLES_10ms; k++) {
+    ISACenc_obj->data_buffer_fix[k + ISACenc_obj->buffer_index] = in[k];
+  }
+  /* if buffersize is not equal to current framesize, and end of file is not reached yet, */
+  /* increase index and go back to main to get more speech samples */
+  if (ISACenc_obj->buffer_index + FRAMESAMPLES_10ms != processed_samples) {
+    ISACenc_obj->buffer_index = ISACenc_obj->buffer_index + FRAMESAMPLES_10ms;
+    return 0;
+  }
+  /* if buffer reached the right size, reset index and continue with encoding the frame */
+  ISACenc_obj->buffer_index = 0;
+
+  /* end of buffer function */
+  /**************************/
+
+  /* encoding */
+  /************/
+
+  if (frame_mode == 0 || ISACenc_obj->frame_nb == 0 )
+  {
+    /* reset bitstream */
+    ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+    ISACenc_obj->bitstr_obj.streamval = 0;
+    ISACenc_obj->bitstr_obj.stream_index = 0;
+    ISACenc_obj->bitstr_obj.full = 1;
+
+    if (CodingMode == 0) {
+      ISACenc_obj->BottleNeck =  WebRtcIsacfix_GetUplinkBandwidth(bw_estimatordata);
+      ISACenc_obj->MaxDelay =  WebRtcIsacfix_GetUplinkMaxDelay(bw_estimatordata);
+    }
+    if (CodingMode == 0 && frame_mode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+      ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+                                                                     ISACenc_obj->current_framesamples);
+    }
+
+    // multiply the bottleneck by 0.88 before computing SNR, 0.88 is tuned by experimenting on TIMIT
+    // 901/1024 is 0.87988281250000
+    ISACenc_obj->s2nr = WebRtcIsacfix_GetSnr(
+        (int16_t)(ISACenc_obj->BottleNeck * 901 >> 10),
+        ISACenc_obj->current_framesamples);
+
+    /* encode frame length */
+    status = WebRtcIsacfix_EncodeFrameLen(ISACenc_obj->current_framesamples, &ISACenc_obj->bitstr_obj);
+    if (status < 0)
+    {
+      /* Wrong frame size */
+      if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+      {
+        // If this is the second 30ms of a 60ms frame reset this such that in the next call
+        // encoder starts fresh.
+        ISACenc_obj->frame_nb = 0;
+      }
+      return status;
+    }
+
+    /* Save framelength for multiple packets memory */
+    if (ISACenc_obj->SaveEnc_ptr != NULL) {
+      (ISACenc_obj->SaveEnc_ptr)->framelength=ISACenc_obj->current_framesamples;
+    }
+
+    /* bandwidth estimation and coding */
+    BWno = WebRtcIsacfix_GetDownlinkBwIndexImpl(bw_estimatordata);
+    status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+    if (status < 0)
+    {
+      if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+      {
+        // If this is the second 30ms of a 60ms frame reset this such that in the next call
+        // encoder starts fresh.
+        ISACenc_obj->frame_nb = 0;
+      }
+      return status;
+    }
+  }
+
+  /* split signal in two bands */
+  WebRtcIsacfix_SplitAndFilter1(ISACenc_obj->data_buffer_fix, LP16a, HP16a, &ISACenc_obj->prefiltbankstr_obj );
+
+  /* estimate pitch parameters and pitch-filter lookahead signal */
+  WebRtcIsacfix_PitchAnalysis(LP16a+QLOOKAHEAD, LPandHP,
+                              &ISACenc_obj->pitchanalysisstr_obj,  PitchLags_Q7, PitchGains_Q12); /* LPandHP = LP_lookahead_pfQ0, */
+
+  /* Set where to store data in multiple packets memory */
+  if (ISACenc_obj->SaveEnc_ptr != NULL) {
+    if (frame_mode == 0 || ISACenc_obj->frame_nb == 0)
+    {
+      (ISACenc_obj->SaveEnc_ptr)->startIdx = 0;
+    }
+    else
+    {
+      (ISACenc_obj->SaveEnc_ptr)->startIdx = 1;
+    }
+  }
+
+  /* quantize & encode pitch parameters */
+  status = WebRtcIsacfix_EncodePitchGain(PitchGains_Q12, &ISACenc_obj->bitstr_obj,  ISACenc_obj->SaveEnc_ptr);
+  if (status < 0)
+  {
+    if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+    {
+      // If this is the second 30ms of a 60ms frame reset this such that in the next call
+      // encoder starts fresh.
+      ISACenc_obj->frame_nb = 0;
+    }
+    return status;
+  }
+  status = WebRtcIsacfix_EncodePitchLag(PitchLags_Q7 , PitchGains_Q12, &ISACenc_obj->bitstr_obj,  ISACenc_obj->SaveEnc_ptr);
+  if (status < 0)
+  {
+    if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+    {
+      // If this is the second 30ms of a 60ms frame reset this such that in the next call
+      // encoder starts fresh.
+      ISACenc_obj->frame_nb = 0;
+    }
+    return status;
+  }
+  AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+      PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+  /* find coefficients for perceptual pre-filters */
+  WebRtcIsacfix_GetLpcCoef(LPandHP, HP16a+QLOOKAHEAD, &ISACenc_obj->maskfiltstr_obj,
+                           ISACenc_obj->s2nr, PitchGains_Q12,
+                           gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15); /*LPandHP = LP_lookahead_pfQ0*/
+
+  // record LPC Gains for possible bit-rate reduction
+  for(k = 0; k < KLT_ORDER_GAIN; k++)
+  {
+    transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+  }
+
+  /* code LPC model and shape - gains not quantized yet */
+  status = WebRtcIsacfix_EncodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+                                   &bmodel, &bits_gainsQ11, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr, &transcodingParam);
+  if (status < 0)
+  {
+    if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+    {
+      // If this is the second 30ms of a 60ms frame reset this such that in the next call
+      // encoder starts fresh.
+      ISACenc_obj->frame_nb = 0;
+    }
+    return status;
+  }
+  arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+
+  /* low-band filtering */
+  WebRtcIsacfix_NormLatticeFilterMa(ORDERLO, ISACenc_obj->maskfiltstr_obj.PreStateLoGQ15,
+                                    LP16a, lofilt_coefQ15, gain_lo_hiQ17, 0, LPandHP);/* LPandHP = LP16b */
+
+  /* pitch filter */
+  WebRtcIsacfix_PitchFilter(LPandHP, LP16a, &ISACenc_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 1);/* LPandHP = LP16b */
+
+  /* high-band filtering */
+  WebRtcIsacfix_NormLatticeFilterMa(ORDERHI, ISACenc_obj->maskfiltstr_obj.PreStateHiGQ15,
+                                    HP16a, hifilt_coefQ15, gain_lo_hiQ17, 1, LPandHP);/*LPandHP = HP16b*/
+
+  /* transform */
+  WebRtcIsacfix_Time2Spec(LP16a, LPandHP, LP16a, LPandHP); /*LPandHP = HP16b*/
+
+  /* Save data for multiple packets memory */
+  if (ISACenc_obj->SaveEnc_ptr != NULL) {
+    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+      (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+      (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+    }
+    (ISACenc_obj->SaveEnc_ptr)->AvgPitchGain[(ISACenc_obj->SaveEnc_ptr)->startIdx] = AvgPitchGain_Q12;
+  }
+
+  /* quantization and lossless coding */
+  status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+  if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+  {
+    if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+    {
+      // If this is the second 30ms of a 60ms frame reset this such that in the next call
+      // encoder starts fresh.
+      ISACenc_obj->frame_nb = 0;
+    }
+    return status;
+  }
+
+  if((frame_mode == 1) && (ISACenc_obj->frame_nb == 0))
+  {
+    // it is a 60ms and we are in the first 30ms
+    // then the limit at this point should be half of the assigned value
+    payloadLimitBytes = ISACenc_obj->payloadLimitBytes60 >> 1;
+  }
+  else if (frame_mode == 0)
+  {
+    // it is a 30ms frame
+    payloadLimitBytes = (ISACenc_obj->payloadLimitBytes30) - 3;
+  }
+  else
+  {
+    // this is the second half of a 60ms frame.
+    payloadLimitBytes = ISACenc_obj->payloadLimitBytes60 - 3; // subract 3 because termination process may add 3 bytes
+  }
+
+  iterCntr = 0;
+  while((((ISACenc_obj->bitstr_obj.stream_index) << 1) > payloadLimitBytes) ||
+        (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH))
+  {
+    int16_t arithLenDFTByte;
+    int16_t bytesLeftQ5;
+    int16_t ratioQ5[8] = {0, 6, 9, 12, 16, 19, 22, 25};
+
+    // According to experiments on TIMIT the following is proper for audio, but it is not agressive enough for tonal inputs
+    // such as DTMF, sweep-sine, ...
+    //
+    // (0.55 - (0.8 - ratio[i]/32) * 5 / 6) * 2^14
+    // int16_t scaleQ14[8] = {0, 648, 1928, 3208, 4915, 6195, 7475, 8755};
+
+
+    // This is a supper-agressive scaling passed the tests (tonal inputs) tone with one iteration for payload limit
+    // of 120 (32kbps bottleneck), number of frames needed a rate-reduction was 58403
+    //
+    int16_t scaleQ14[8] = {0, 348, 828, 1408, 2015, 3195, 3500, 3500};
+    int16_t idx;
+
+    if(iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION)
+    {
+      // We were not able to limit the payload size
+
+      if((frame_mode == 1) && (ISACenc_obj->frame_nb == 0))
+      {
+        // This was the first 30ms of a 60ms frame. Although the payload is larger than it
+        // should be but we let the second 30ms be encoded. Maybe togetehr we won't exceed
+        // the limit.
+        ISACenc_obj->frame_nb = 1;
+        return 0;
+      }
+      else if((frame_mode == 1) && (ISACenc_obj->frame_nb == 1))
+      {
+        ISACenc_obj->frame_nb = 0;
+      }
+
+      if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+      {
+        return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+      }
+      else
+      {
+        return status;
+      }
+    }
+    if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+    {
+      arithLenDFTByte = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full) - arithLenBeforeEncodingDFT;
+      bytesLeftQ5 = (payloadLimitBytes - arithLenBeforeEncodingDFT) << 5;
+
+      // bytesLeft / arithLenDFTBytes indicates how much scaling is required a rough estimate (agressive)
+      // scale = 0.55 - (0.8 - bytesLeft / arithLenDFTBytes) * 5 / 6
+      // bytesLeft / arithLenDFTBytes below 0.2 will have a scale of zero and above 0.8 are treated as 0.8
+      // to avoid division we do more simplification.
+      //
+      // values of (bytesLeft / arithLenDFTBytes)*32 between ratioQ5[i] and ratioQ5[i+1] are rounded to ratioQ5[i]
+      // and the corresponding scale is chosen
+
+      // we compare bytesLeftQ5 with ratioQ5[]*arithLenDFTByte;
+      idx = 4;
+      idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 2 : -2;
+      idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 1 : -1;
+      idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 0 : -1;
+    }
+    else
+    {
+      // we are here because the bit-stream did not fit into the buffer, in this case, the stream_index is not
+      // trustable, especially if the is the first 30ms of a packet. Thereforem, we will go for the most agressive
+      // case.
+      idx = 0;
+    }
+    // scale FFT coefficients to reduce the bit-rate
+    for(k = 0; k < FRAMESAMPLES_HALF; k++)
+    {
+      LP16a[k] = (int16_t)(LP16a[k] * scaleQ14[idx] >> 14);
+      LPandHP[k] = (int16_t)(LPandHP[k] * scaleQ14[idx] >> 14);
+    }
+
+    // Save data for multiple packets memory
+    if (ISACenc_obj->SaveEnc_ptr != NULL)
+    {
+      for(k = 0; k < FRAMESAMPLES_HALF; k++)
+      {
+        (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+        (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+      }
+    }
+
+    // scale the unquantized LPC gains and save the scaled version for the future use
+    for(k = 0; k < KLT_ORDER_GAIN; k++)
+    {
+      gain_lo_hiQ17[k] = WEBRTC_SPL_MUL_16_32_RSFT14(scaleQ14[idx], transcodingParam.lpcGains[k]);//transcodingParam.lpcGains[k]; //
+      transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+    }
+
+    // reset the bit-stream object to the state which it had before encoding LPC Gains
+    ISACenc_obj->bitstr_obj.full = transcodingParam.full;
+    ISACenc_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+    ISACenc_obj->bitstr_obj.streamval = transcodingParam.streamval;
+    ISACenc_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+    ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index-1] = transcodingParam.beforeLastWord;
+    ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index] = transcodingParam.lastWord;
+
+
+    // quantize and encode LPC gain
+    WebRtcIsacfix_EstCodeLpcGain(gain_lo_hiQ17, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+    arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+    status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+    if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+    {
+      if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+      {
+        // If this is the second 30ms of a 60ms frame reset this such that in the next call
+        // encoder starts fresh.
+        ISACenc_obj->frame_nb = 0;
+      }
+      return status;
+    }
+    iterCntr++;
+  }
+
+  if (frame_mode == 1 && ISACenc_obj->frame_nb == 0)
+    /* i.e. 60 ms framesize and just processed the first 30ms, */
+    /* go back to main function to buffer the other 30ms speech frame */
+  {
+    ISACenc_obj->frame_nb = 1;
+    return 0;
+  }
+  else if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+  {
+    ISACenc_obj->frame_nb = 0;
+    /* also update the framelength for next packet, in Adaptive mode only */
+    if (CodingMode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+      ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+                                                                     ISACenc_obj->current_framesamples);
+    }
+  }
+
+
+  /* complete arithmetic coding */
+  stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+  /* can this be negative? */
+
+  if(CodingMode == 0)
+  {
+
+    /* update rate model and get minimum number of bytes in this packet */
+    MinBytes = WebRtcIsacfix_GetMinBytes(&ISACenc_obj->rate_data_obj, (int16_t) stream_length,
+                                         ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck, ISACenc_obj->MaxDelay);
+
+    /* if bitstream is too short, add garbage at the end */
+
+    /* Store length of coded data */
+    usefulstr_len = stream_length;
+
+    /* Make sure MinBytes does not exceed packet size limit */
+    if ((ISACenc_obj->frame_nb == 0) && (MinBytes > ISACenc_obj->payloadLimitBytes30)) {
+      MinBytes = ISACenc_obj->payloadLimitBytes30;
+    } else if ((ISACenc_obj->frame_nb == 1) && (MinBytes > ISACenc_obj->payloadLimitBytes60)) {
+      MinBytes = ISACenc_obj->payloadLimitBytes60;
+    }
+
+    /* Make sure we don't allow more than 255 bytes of garbage data.
+       We store the length of the garbage data in 8 bits in the bitstream,
+       255 is the max garbage lenght we can signal using 8 bits. */
+    if( MinBytes > usefulstr_len + 255 ) {
+      MinBytes = usefulstr_len + 255;
+    }
+
+    /* Save data for creation of multiple bitstreams */
+    if (ISACenc_obj->SaveEnc_ptr != NULL) {
+      (ISACenc_obj->SaveEnc_ptr)->minBytes = MinBytes;
+    }
+
+    while (stream_length < MinBytes)
+    {
+      RTC_DCHECK_GE(stream_length, 0);
+      if (stream_length & 0x0001){
+        ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+        ISACenc_obj->bitstr_obj.stream[stream_length / 2] |=
+            (uint16_t)(ISACenc_obj->bitstr_seed & 0xFF);
+      } else {
+        ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+        ISACenc_obj->bitstr_obj.stream[stream_length / 2] =
+            ((uint16_t)ISACenc_obj->bitstr_seed << 8);
+      }
+      stream_length++;
+    }
+
+    /* to get the real stream_length, without garbage */
+    if (usefulstr_len & 0x0001) {
+      ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0xFF00;
+      ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] += (MinBytes - usefulstr_len) & 0x00FF;
+    }
+    else {
+      ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0x00FF;
+      ISACenc_obj->bitstr_obj.stream[usefulstr_len >> 1] +=
+          ((uint16_t)((MinBytes - usefulstr_len) & 0x00FF) << 8);
+    }
+  }
+  else
+  {
+    /* update rate model */
+    WebRtcIsacfix_UpdateRateModel(&ISACenc_obj->rate_data_obj, (int16_t) stream_length,
+                                  ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck);
+  }
+  return stream_length;
+}
+
+/* This function is used to create a new bitstream with new BWE.
+   The same data as previously encoded with the fucntion WebRtcIsacfix_EncodeImpl()
+   is used. The data needed is taken from the struct, where it was stored
+   when calling the encoder. */
+int WebRtcIsacfix_EncodeStoredData(IsacFixEncoderInstance  *ISACenc_obj,
+                                   int     BWnumber,
+                                   float              scale)
+{
+  int ii;
+  int status;
+  int16_t BWno = (int16_t)BWnumber;
+  int stream_length = 0;
+
+  int16_t model;
+  const uint16_t *Q_PitchGain_cdf_ptr[1];
+  const uint16_t **cdf;
+  const IsacSaveEncoderData *SaveEnc_str;
+  int32_t tmpLPCcoeffs_g[KLT_ORDER_GAIN<<1];
+  int16_t tmpLPCindex_g[KLT_ORDER_GAIN<<1];
+  int16_t tmp_fre[FRAMESAMPLES];
+  int16_t tmp_fim[FRAMESAMPLES];
+
+  SaveEnc_str = ISACenc_obj->SaveEnc_ptr;
+
+  /* Check if SaveEnc memory exists */
+  if (SaveEnc_str == NULL) {
+    return (-1);
+  }
+
+  /* Sanity Check - possible values for BWnumber is 0 - 23 */
+  if ((BWnumber < 0) || (BWnumber > 23)) {
+    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+  }
+
+  /* reset bitstream */
+  ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+  ISACenc_obj->bitstr_obj.streamval = 0;
+  ISACenc_obj->bitstr_obj.stream_index = 0;
+  ISACenc_obj->bitstr_obj.full = 1;
+
+  /* encode frame length */
+  status = WebRtcIsacfix_EncodeFrameLen(SaveEnc_str->framelength, &ISACenc_obj->bitstr_obj);
+  if (status < 0) {
+    /* Wrong frame size */
+    return status;
+  }
+
+  /* encode bandwidth estimate */
+  status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+  if (status < 0) {
+    return status;
+  }
+
+  /* Transcoding                                                 */
+  /* If scale < 1, rescale data to produce lower bitrate signal  */
+  if ((0.0 < scale) && (scale < 1.0)) {
+    /* Compensate LPC gain */
+    for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+      tmpLPCcoeffs_g[ii] = (int32_t) ((scale) * (float) SaveEnc_str->LPCcoeffs_g[ii]);
+    }
+
+    /* Scale DFT */
+    for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+      tmp_fre[ii] = (int16_t) ((scale) * (float) SaveEnc_str->fre[ii]) ;
+      tmp_fim[ii] = (int16_t) ((scale) * (float) SaveEnc_str->fim[ii]) ;
+    }
+  } else {
+    for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+      tmpLPCindex_g[ii] =  SaveEnc_str->LPCindex_g[ii];
+    }
+
+    for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+      tmp_fre[ii] = SaveEnc_str->fre[ii];
+      tmp_fim[ii] = SaveEnc_str->fim[ii];
+    }
+  }
+
+  /* Loop over number of 30 msec */
+  for (ii = 0; ii <= SaveEnc_str->startIdx; ii++)
+  {
+
+    /* encode pitch gains */
+    *Q_PitchGain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+    status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->pitchGain_index[ii],
+                                       Q_PitchGain_cdf_ptr, 1);
+    if (status < 0) {
+      return status;
+    }
+
+    /* entropy coding of quantization pitch lags */
+    /* voicing classificiation */
+    if (SaveEnc_str->meanGain[ii] <= 819) {
+      cdf = WebRtcIsacfix_kPitchLagPtrLo;
+    } else if (SaveEnc_str->meanGain[ii] <= 1638) {
+      cdf = WebRtcIsacfix_kPitchLagPtrMid;
+    } else {
+      cdf = WebRtcIsacfix_kPitchLagPtrHi;
+    }
+    status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj,
+                                       &SaveEnc_str->pitchIndex[PITCH_SUBFRAMES*ii], cdf, PITCH_SUBFRAMES);
+    if (status < 0) {
+      return status;
+    }
+
+    /* LPC */
+    /* entropy coding of model number */
+    model = 0;
+    status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj,  &model,
+                                       WebRtcIsacfix_kModelCdfPtr, 1);
+    if (status < 0) {
+      return status;
+    }
+
+    /* entropy coding of quantization indices - LPC shape only */
+    status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->LPCindex_s[KLT_ORDER_SHAPE*ii],
+                                       WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+    if (status < 0) {
+      return status;
+    }
+
+    /* If transcoding, get new LPC gain indices */
+    if (scale < 1.0) {
+      WebRtcIsacfix_TranscodeLpcCoef(&tmpLPCcoeffs_g[KLT_ORDER_GAIN*ii], &tmpLPCindex_g[KLT_ORDER_GAIN*ii]);
+    }
+
+    /* entropy coding of quantization indices - LPC gain */
+    status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN*ii],
+                                       WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+    if (status < 0) {
+      return status;
+    }
+
+    /* quantization and lossless coding */
+    status = WebRtcIsacfix_EncodeSpec(&tmp_fre[ii*FRAMESAMPLES_HALF], &tmp_fim[ii*FRAMESAMPLES_HALF],
+                                      &ISACenc_obj->bitstr_obj, SaveEnc_str->AvgPitchGain[ii]);
+    if (status < 0) {
+      return status;
+    }
+  }
+
+  /* complete arithmetic coding */
+  stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+
+  return stream_length;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c b/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
new file mode 100644
index 0000000..842e77f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
@@ -0,0 +1,2056 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This file contains all functions used to arithmetically
+ * encode the iSAC bistream.
+ *
+ */
+
+#include <stddef.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h"
+#include "rtc_base/sanitizer.h"
+
+/*
+ * Eenumerations for arguments to functions WebRtcIsacfix_MatrixProduct1()
+ * and WebRtcIsacfix_MatrixProduct2().
+*/
+
+enum matrix_index_factor {
+  kTIndexFactor1 = 1,
+  kTIndexFactor2 = 2,
+  kTIndexFactor3 = SUBFRAMES,
+  kTIndexFactor4 = LPC_SHAPE_ORDER
+};
+
+enum matrix_index_step {
+  kTIndexStep1 = 1,
+  kTIndexStep2 = SUBFRAMES,
+  kTIndexStep3 = LPC_SHAPE_ORDER
+};
+
+enum matrixprod_loop_count {
+  kTLoopCount1 = SUBFRAMES,
+  kTLoopCount2 = 2,
+  kTLoopCount3 = LPC_SHAPE_ORDER
+};
+
+enum matrix1_shift_value {
+  kTMatrix1_shift0 = 0,
+  kTMatrix1_shift1 = 1,
+  kTMatrix1_shift5 = 5
+};
+
+enum matrixprod_init_case {
+  kTInitCase0 = 0,
+  kTInitCase1 = 1
+};
+
+/*
+  This function implements the fix-point correspondant function to lrint.
+
+  FLP: (int32_t)floor(flt+.499999999999)
+  FIP: (fixVal+roundVal)>>qDomain
+
+  where roundVal = 2^(qDomain-1) = 1<<(qDomain-1)
+
+*/
+static __inline int32_t CalcLrIntQ(int32_t fixVal, int16_t qDomain) {
+  return (fixVal + (1 << (qDomain - 1))) >> qDomain;
+}
+
+/*
+  __inline uint32_t stepwise(int32_t dinQ10) {
+
+  int32_t ind, diQ10, dtQ10;
+
+  diQ10 = dinQ10;
+  if (diQ10 < DPMIN_Q10)
+  diQ10 = DPMIN_Q10;
+  if (diQ10 >= DPMAX_Q10)
+  diQ10 = DPMAX_Q10 - 1;
+
+  dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */
+/* ind = (dtQ10 * 5) >> 10;  */ /* 2^10 / 5 = 0.2 in Q10  */
+/* Q10 -> Q0 */
+
+/* return rpointsFIX_Q10[ind];
+
+   }
+*/
+
+/* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */
+/* The input argument X to logN(X) is 2^17 times higher than the
+   input floating point argument Y to log(Y), since the X value
+   is a Q17 value. This can be compensated for after the call, by
+   subraction a value Z for each Q-step. One Q-step means that
+   X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+   177.445678 should be subtracted (since logN() returns a Q8 value).
+   For a X value in Q17, the value 177.445678*17 = 3017 should be
+   subtracted */
+static int16_t CalcLogN(int32_t arg) {
+  int16_t zeros, log2, frac, logN;
+
+  zeros=WebRtcSpl_NormU32(arg);
+  frac = (int16_t)((uint32_t)((arg << zeros) & 0x7FFFFFFF) >> 23);
+  log2 = (int16_t)(((31 - zeros) << 8) + frac);  // log2(x) in Q8
+  logN = (int16_t)(log2 * 22713 >> 15);  // log(2) = 0.693147 = 22713 in Q15
+  logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x.
+
+  return logN;
+}
+
+
+/*
+  expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695
+
+  Input:  Q8  (int16_t)
+  Output: Q17 (int32_t)
+
+  a = log2(e) = log2(exp(1)) ~= 1.442695  ==>  a = 23637 in Q14 (1.442688)
+  To this value, 700 is added or subtracted in order to get an average error
+  nearer zero, instead of always same-sign.
+*/
+
+static int32_t CalcExpN(int16_t x) {
+  int16_t axINT, axFRAC;
+  int16_t exp16;
+  int32_t exp;
+  int16_t ax = (int16_t)(x * 23637 >> 14);  // Q8
+
+  if (x>=0) {
+    axINT = ax >> 8;  //Q0
+    axFRAC = ax&0x00FF;
+    exp16 = 1 << axINT;  // Q0
+    axFRAC = axFRAC+256; //Q8
+    exp = exp16 * axFRAC;  // Q0*Q8 = Q8
+    exp <<= 9;  // Q17
+  } else {
+    ax = -ax;
+    axINT = 1 + (ax >> 8);  //Q0
+    axFRAC = 0x00FF - (ax&0x00FF);
+    exp16 = (int16_t)(32768 >> axINT);  // Q15
+    axFRAC = axFRAC+256; //Q8
+    exp = exp16 * axFRAC;  // Q15*Q8 = Q23
+    exp >>= 6;  // Q17
+  }
+
+  return exp;
+}
+
+
+/* compute correlation from power spectrum */
+static void CalcCorrelation(int32_t *PSpecQ12, int32_t *CorrQ7)
+{
+  int32_t summ[FRAMESAMPLES/8];
+  int32_t diff[FRAMESAMPLES/8];
+  int32_t sum;
+  int k, n;
+
+  for (k = 0; k < FRAMESAMPLES/8; k++) {
+    summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
+    diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
+  }
+
+  sum = 2;
+  for (n = 0; n < FRAMESAMPLES/8; n++)
+    sum += summ[n];
+  CorrQ7[0] = sum;
+
+  for (k = 0; k < AR_ORDER; k += 2) {
+    sum = 0;
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      sum += (WebRtcIsacfix_kCos[k][n] * diff[n] + 256) >> 9;
+    CorrQ7[k+1] = sum;
+  }
+
+  for (k=1; k<AR_ORDER; k+=2) {
+    sum = 0;
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      sum += (WebRtcIsacfix_kCos[k][n] * summ[n] + 256) >> 9;
+    CorrQ7[k+1] = sum;
+  }
+}
+
+// Some arithmetic operations that are allowed to overflow. (It's still
+// undefined behavior, so not a good idea; this just makes UBSan ignore the
+// violations, so that our old code can continue to do what it's always been
+// doing.)
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+    OverflowingMulS16S32ToS32(int16_t a, int32_t b) {
+  return a * b;
+}
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+    OverflowingAddS32S32ToS32(int32_t a, int32_t b) {
+  return a + b;
+}
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+    OverflowingSubS32S32ToS32(int32_t a, int32_t b) {
+  return a - b;
+}
+
+/* compute inverse AR power spectrum */
+static void CalcInvArSpec(const int16_t *ARCoefQ12,
+                          const int32_t gainQ10,
+                          int32_t *CurveQ16)
+{
+  int32_t CorrQ11[AR_ORDER+1];
+  int32_t sum, tmpGain;
+  int32_t diffQ16[FRAMESAMPLES/8];
+  const int16_t *CS_ptrQ9;
+  int k, n;
+  int16_t round, shftVal = 0, sh;
+
+  sum = 0;
+  for (n = 0; n < AR_ORDER+1; n++)
+    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
+  sum = ((sum >> 6) * 65 + 32768) >> 16;  /* Result in Q8. */
+  CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
+  if(gainQ10>400000){
+    tmpGain = gainQ10 >> 3;
+    round = 32;
+    shftVal = 6;
+  } else {
+    tmpGain = gainQ10;
+    round = 256;
+    shftVal = 9;
+  }
+
+  for (k = 1; k < AR_ORDER+1; k++) {
+    sum = 16384;
+    for (n = k; n < AR_ORDER+1; n++)
+      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
+    sum >>= 15;
+    CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+  }
+  sum = CorrQ11[0] << 7;
+  for (n = 0; n < FRAMESAMPLES/8; n++)
+    CurveQ16[n] = sum;
+
+  for (k = 1; k < AR_ORDER; k += 2) {
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      CurveQ16[n] +=
+          (OverflowingMulS16S32ToS32(WebRtcIsacfix_kCos[k][n], CorrQ11[k + 1]) +
+           2) >>
+          2;
+  }
+
+  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
+
+  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
+  sh=WebRtcSpl_NormW32(CorrQ11[1]);
+  if (CorrQ11[1]==0) /* Use next correlation */
+    sh=WebRtcSpl_NormW32(CorrQ11[2]);
+
+  if (sh<9)
+    shftVal = 9 - sh;
+  else
+    shftVal = 0;
+
+  for (n = 0; n < FRAMESAMPLES/8; n++)
+    diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+  for (k = 2; k < AR_ORDER; k += 2) {
+    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+  }
+
+  for (k=0; k<FRAMESAMPLES/8; k++) {
+    int32_t diff_q16 = diffQ16[k] * (1 << shftVal);
+    CurveQ16[FRAMESAMPLES / 4 - 1 - k] =
+        OverflowingSubS32S32ToS32(CurveQ16[k], diff_q16);
+    CurveQ16[k] = OverflowingAddS32S32ToS32(CurveQ16[k], diff_q16);
+  }
+}
+
+static void CalcRootInvArSpec(const int16_t *ARCoefQ12,
+                              const int32_t gainQ10,
+                              uint16_t *CurveQ8)
+{
+  int32_t CorrQ11[AR_ORDER+1];
+  int32_t sum, tmpGain;
+  int32_t summQ16[FRAMESAMPLES/8];
+  int32_t diffQ16[FRAMESAMPLES/8];
+
+  const int16_t *CS_ptrQ9;
+  int k, n, i;
+  int16_t round, shftVal = 0, sh;
+  int32_t res, in_sqrt, newRes;
+
+  sum = 0;
+  for (n = 0; n < AR_ORDER+1; n++)
+    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
+  sum = ((sum >> 6) * 65 + 32768) >> 16;  /* Result in Q8. */
+  CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
+  if(gainQ10>400000){
+    tmpGain = gainQ10 >> 3;
+    round = 32;
+    shftVal = 6;
+  } else {
+    tmpGain = gainQ10;
+    round = 256;
+    shftVal = 9;
+  }
+
+  for (k = 1; k < AR_ORDER+1; k++) {
+    sum = 16384;
+    for (n = k; n < AR_ORDER+1; n++)
+      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
+    sum >>= 15;
+    CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+  }
+  sum = CorrQ11[0] << 7;
+  for (n = 0; n < FRAMESAMPLES/8; n++)
+    summQ16[n] = sum;
+
+  for (k = 1; k < (AR_ORDER); k += 2) {
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      summQ16[n] += ((CorrQ11[k + 1] * WebRtcIsacfix_kCos[k][n]) + 2) >> 2;
+  }
+
+  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
+
+  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
+  sh=WebRtcSpl_NormW32(CorrQ11[1]);
+  if (CorrQ11[1]==0) /* Use next correlation */
+    sh=WebRtcSpl_NormW32(CorrQ11[2]);
+
+  if (sh<9)
+    shftVal = 9 - sh;
+  else
+    shftVal = 0;
+
+  for (n = 0; n < FRAMESAMPLES/8; n++)
+    diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+  for (k = 2; k < AR_ORDER; k += 2) {
+    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
+    for (n = 0; n < FRAMESAMPLES/8; n++)
+      diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+  }
+
+  in_sqrt = summQ16[0] + (diffQ16[0] << shftVal);
+
+  /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB)  */
+  res = 1 << (WebRtcSpl_GetSizeInBits(in_sqrt) >> 1);
+
+  for (k = 0; k < FRAMESAMPLES/8; k++)
+  {
+    in_sqrt = summQ16[k] + (diffQ16[k] << shftVal);
+    i = 10;
+
+    /* make in_sqrt positive to prohibit sqrt of negative values */
+    if(in_sqrt<0)
+      in_sqrt=-in_sqrt;
+
+    newRes = (in_sqrt / res + res) >> 1;
+    do
+    {
+      res = newRes;
+      newRes = (in_sqrt / res + res) >> 1;
+    } while (newRes != res && i-- > 0);
+
+    CurveQ8[k] = (int16_t)newRes;
+  }
+  for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) {
+
+    in_sqrt = summQ16[FRAMESAMPLES / 4 - 1 - k] -
+        (diffQ16[FRAMESAMPLES / 4 - 1 - k] << shftVal);
+    i = 10;
+
+    /* make in_sqrt positive to prohibit sqrt of negative values */
+    if(in_sqrt<0)
+      in_sqrt=-in_sqrt;
+
+    newRes = (in_sqrt / res + res) >> 1;
+    do
+    {
+      res = newRes;
+      newRes = (in_sqrt / res + res) >> 1;
+    } while (newRes != res && i-- > 0);
+
+    CurveQ8[k] = (int16_t)newRes;
+  }
+
+}
+
+
+
+/* generate array of dither samples in Q7 */
+static void GenerateDitherQ7(int16_t *bufQ7,
+                             uint32_t seed,
+                             int16_t length,
+                             int16_t AvgPitchGain_Q12)
+{
+  int   k;
+  int16_t dither1_Q7, dither2_Q7, dither_gain_Q14, shft;
+
+  if (AvgPitchGain_Q12 < 614)  /* this threshold should be equal to that in decode_spec() */
+  {
+    for (k = 0; k < length-2; k += 3)
+    {
+      /* new random unsigned int32_t */
+      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+      /* fixed-point dither sample between -64 and 64 (Q7) */
+      dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      /* new random unsigned int32_t */
+      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+      /* fixed-point dither sample between -64 and 64 */
+      dither2_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 15);
+      if (shft < 5)
+      {
+        bufQ7[k]   = dither1_Q7;
+        bufQ7[k+1] = dither2_Q7;
+        bufQ7[k+2] = 0;
+      }
+      else if (shft < 10)
+      {
+        bufQ7[k]   = dither1_Q7;
+        bufQ7[k+1] = 0;
+        bufQ7[k+2] = dither2_Q7;
+      }
+      else
+      {
+        bufQ7[k]   = 0;
+        bufQ7[k+1] = dither1_Q7;
+        bufQ7[k+2] = dither2_Q7;
+      }
+    }
+  }
+  else
+  {
+    dither_gain_Q14 = (int16_t)(22528 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12));
+
+    /* dither on half of the coefficients */
+    for (k = 0; k < length-1; k += 2)
+    {
+      /* new random unsigned int32_t */
+      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+      /* fixed-point dither sample between -64 and 64 */
+      dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      /* dither sample is placed in either even or odd index */
+      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1);     /* either 0 or 1 */
+
+      bufQ7[k + shft] = (int16_t)((dither_gain_Q14 * dither1_Q7 + 8192) >> 14);
+      bufQ7[k + 1 - shft] = 0;
+    }
+  }
+}
+
+
+
+
+/*
+ * function to decode the complex spectrum from the bitstream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
+                             int16_t *frQ7,
+                             int16_t *fiQ7,
+                             int16_t AvgPitchGain_Q12)
+{
+  int16_t  data[FRAMESAMPLES];
+  int32_t  invARSpec2_Q16[FRAMESAMPLES/4];
+  int16_t  ARCoefQ12[AR_ORDER+1];
+  int16_t  RCQ15[AR_ORDER];
+  int16_t  gainQ10;
+  int32_t  gain2_Q10;
+  int len;
+  int          k;
+
+  /* create dither signal */
+  GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */
+
+  /* decode model parameters */
+  if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0)
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+
+  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+  if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0)
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+  /* compute inverse AR power spectrum */
+  CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+  /* arithmetic decoding of spectrum */
+  /* 'data' input and output. Input = Dither */
+  len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (int16_t)FRAMESAMPLES);
+
+  if (len<1)
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+  /* subtract dither and scale down spectral samples with low SNR */
+  if (AvgPitchGain_Q12 <= 614)
+  {
+    for (k = 0; k < FRAMESAMPLES; k += 4)
+    {
+      gainQ10 = WebRtcSpl_DivW32W16ResW16(30 << 10,
+          (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2195456) >> 16));
+      *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
+      *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
+      *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
+      *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
+    }
+  }
+  else
+  {
+    for (k = 0; k < FRAMESAMPLES; k += 4)
+    {
+      gainQ10 = WebRtcSpl_DivW32W16ResW16(36 << 10,
+          (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2654208) >> 16));
+      *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
+      *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
+      *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
+      *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
+    }
+  }
+
+  return len;
+}
+
+
+int WebRtcIsacfix_EncodeSpec(const int16_t *fr,
+                             const int16_t *fi,
+                             Bitstr_enc *streamdata,
+                             int16_t AvgPitchGain_Q12)
+{
+  int16_t  dataQ7[FRAMESAMPLES];
+  int32_t  PSpec[FRAMESAMPLES/4];
+  uint16_t invARSpecQ8[FRAMESAMPLES/4];
+  int32_t  CorrQ7[AR_ORDER+1];
+  int32_t  CorrQ7_norm[AR_ORDER+1];
+  int16_t  RCQ15[AR_ORDER];
+  int16_t  ARCoefQ12[AR_ORDER+1];
+  int32_t  gain2_Q10;
+  int16_t  val;
+  int32_t  nrg;
+  uint32_t sum;
+  int16_t  lft_shft;
+  int16_t  status;
+  int          k, n, j;
+
+
+  /* create dither_float signal */
+  GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
+
+  /* add dither and quantize, and compute power spectrum */
+  /* Vector dataQ7 contains Dither in Q7 */
+  for (k = 0; k < FRAMESAMPLES; k += 4)
+  {
+    val = ((*fr++ + dataQ7[k]   + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */
+    dataQ7[k] = val;            /* New value in Data */
+    sum = WEBRTC_SPL_UMUL(val, val);
+
+    val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */
+    dataQ7[k+1] = val;            /* New value in Data */
+    sum += WEBRTC_SPL_UMUL(val, val);
+
+    val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */
+    dataQ7[k+2] = val;            /* New value in Data */
+    sum += WEBRTC_SPL_UMUL(val, val);
+
+    val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */
+    dataQ7[k+3] = val;            /* New value in Data */
+    sum += WEBRTC_SPL_UMUL(val, val);
+
+    PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2);
+  }
+
+  /* compute correlation from power spectrum */
+  CalcCorrelation(PSpec, CorrQ7);
+
+
+  /* find AR coefficients */
+  /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
+  lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+  if (lft_shft > 0) {
+    for (k=0; k<AR_ORDER+1; k++)
+      CorrQ7_norm[k] = CorrQ7[k] << lft_shft;
+  } else {
+    for (k=0; k<AR_ORDER+1; k++)
+      CorrQ7_norm[k] = CorrQ7[k] >> -lft_shft;
+  }
+
+  /* find RC coefficients */
+  WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+  /* quantize & code RC Coef */
+  status = WebRtcIsacfix_EncodeRcCoef(RCQ15, streamdata);
+  if (status < 0) {
+    return status;
+  }
+
+  /* RC -> AR coefficients */
+  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+  /* compute ARCoef' * Corr * ARCoef in Q19 */
+  nrg = 0;
+  for (j = 0; j <= AR_ORDER; j++) {
+    for (n = 0; n <= j; n++)
+      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
+          4) >> 3;
+    for (n = j+1; n <= AR_ORDER; n++)
+      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
+          4) >> 3;
+  }
+
+  if (lft_shft > 0)
+    nrg >>= lft_shft;
+  else
+    nrg <<= -lft_shft;
+
+  if(nrg>131072)
+    gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg);  /* also shifts 31 bits to the left! */
+  else
+    gain2_Q10 = FRAMESAMPLES >> 2;
+
+  /* quantize & code gain2_Q10 */
+  if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata))
+    return -1;
+
+  /* compute inverse AR magnitude spectrum */
+  CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8);
+
+
+  /* arithmetic coding of spectrum */
+  status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (int16_t)FRAMESAMPLES);
+  if ( status )
+    return( status );
+
+  return 0;
+}
+
+
+/* Matlab's LAR definition */
+static void Rc2LarFix(const int16_t *rcQ15, int32_t *larQ17, int16_t order) {
+
+  /*
+
+    This is a piece-wise implemenetation of a rc2lar-function (all values in the comment
+    are Q15 values and  are based on [0 24956/32768 30000/32768 32500/32768], i.e.
+    [0.76159667968750   0.91552734375000   0.99182128906250]
+
+    x0  x1           a                 k              x0(again)         b
+    ==================================================================================
+    0.00 0.76:   0                  2.625997508581   0                  0
+    0.76 0.91:   2.000012018559     7.284502668663   0.761596679688    -3.547841027073
+    0.91 0.99:   3.121320351712    31.115835041229   0.915527343750   -25.366077452148
+    0.99 1.00:   5.495270168700   686.663805654056   0.991821289063  -675.552510708011
+
+    The implementation is y(x)= a + (x-x0)*k, but this can be simplified to
+
+    y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k
+
+    akx=[0                 2.625997508581   0
+    2.000012018559     7.284502668663   0.761596679688
+    3.121320351712    31.115835041229   0.915527343750
+    5.495270168700   686.663805654056   0.991821289063];
+
+    b = akx(:,1) - akx(:,3).*akx(:,2)
+
+    [ 0.0
+    -3.547841027073
+    -25.366077452148
+    -675.552510708011]
+
+  */
+
+  int k;
+  int16_t rc;
+  int32_t larAbsQ17;
+
+  for (k = 0; k < order; k++) {
+
+    rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15
+
+    /* Calculate larAbsQ17 in Q17 from rc in Q15 */
+
+    if (rc<24956) {  //0.7615966 in Q15
+      // (Q15*Q13)>>11 = Q17
+      larAbsQ17 = rc * 21512 >> 11;
+    } else if (rc<30000) { //0.91552734375 in Q15
+      // Q17 + (Q15*Q12)>>10 = Q17
+      larAbsQ17 = -465024 + (rc * 29837 >> 10);
+    } else if (rc<32500) { //0.99182128906250 in Q15
+      // Q17 + (Q15*Q10)>>8 = Q17
+      larAbsQ17 = -3324784 + (rc * 31863 >> 8);
+    } else  {
+      // Q17 + (Q15*Q5)>>3 = Q17
+      larAbsQ17 = -88546020 + (rc * 21973 >> 3);
+    }
+
+    if (rcQ15[k]>0) {
+      larQ17[k] = larAbsQ17;
+    } else {
+      larQ17[k] = -larAbsQ17;
+    }
+  }
+}
+
+
+static void Lar2RcFix(const int32_t *larQ17, int16_t *rcQ15,  int16_t order) {
+
+  /*
+    This is a piece-wise implemenetation of a lar2rc-function
+    See comment in Rc2LarFix() about details.
+  */
+
+  int k;
+  int16_t larAbsQ11;
+  int32_t rc;
+
+  for (k = 0; k < order; k++) {
+
+    larAbsQ11 = (int16_t)WEBRTC_SPL_ABS_W32((larQ17[k] + 32) >> 6);  // Q11
+
+    if (larAbsQ11<4097) { //2.000012018559 in Q11
+      // Q11*Q16>>12 = Q15
+      rc = larAbsQ11 * 24957 >> 12;
+    } else if (larAbsQ11<6393) { //3.121320351712 in Q11
+      // (Q11*Q17 + Q13)>>13 = Q15
+      rc = (larAbsQ11 * 17993 + 130738688) >> 13;
+    } else if (larAbsQ11<11255) { //5.495270168700 in Q11
+      // (Q11*Q19 + Q30)>>15 = Q15
+      rc = (larAbsQ11 * 16850 + 875329820) >> 15;
+    } else  {
+      // (Q11*Q24>>16 + Q19)>>4 = Q15
+      rc = (((larAbsQ11 * 24433) >> 16) + 515804) >> 4;
+    }
+
+    if (larQ17[k]<=0) {
+      rc = -rc;
+    }
+
+    rcQ15[k] = (int16_t) rc;  // Q15
+  }
+}
+
+static void Poly2LarFix(int16_t *lowbandQ15,
+                        int16_t orderLo,
+                        int16_t *hibandQ15,
+                        int16_t orderHi,
+                        int16_t Nsub,
+                        int32_t *larsQ17) {
+
+  int k, n;
+  int32_t *outpQ17;
+  int16_t orderTot;
+  int32_t larQ17[MAX_ORDER];   // Size 7+6 is enough
+
+  orderTot = (orderLo + orderHi);
+  outpQ17 = larsQ17;
+  for (k = 0; k < Nsub; k++) {
+
+    Rc2LarFix(lowbandQ15, larQ17, orderLo);
+
+    for (n = 0; n < orderLo; n++)
+      outpQ17[n] = larQ17[n]; //Q17
+
+    Rc2LarFix(hibandQ15, larQ17, orderHi);
+
+    for (n = 0; n < orderHi; n++)
+      outpQ17[n + orderLo] = larQ17[n]; //Q17;
+
+    outpQ17 += orderTot;
+    lowbandQ15 += orderLo;
+    hibandQ15 += orderHi;
+  }
+}
+
+
+static void Lar2polyFix(int32_t *larsQ17,
+                        int16_t *lowbandQ15,
+                        int16_t orderLo,
+                        int16_t *hibandQ15,
+                        int16_t orderHi,
+                        int16_t Nsub) {
+
+  int k, n;
+  int16_t orderTot;
+  int16_t *outplQ15, *outphQ15;
+  int32_t *inpQ17;
+  int16_t rcQ15[7+6];
+
+  orderTot = (orderLo + orderHi);
+  outplQ15 = lowbandQ15;
+  outphQ15 = hibandQ15;
+  inpQ17 = larsQ17;
+  for (k = 0; k < Nsub; k++) {
+
+    /* gains not handled here as in the FLP version */
+
+    /* Low band */
+    Lar2RcFix(&inpQ17[0], rcQ15, orderLo);
+    for (n = 0; n < orderLo; n++)
+      outplQ15[n] = rcQ15[n]; // Refl. coeffs
+
+    /* High band */
+    Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi);
+    for (n = 0; n < orderHi; n++)
+      outphQ15[n] = rcQ15[n]; // Refl. coeffs
+
+    inpQ17 += orderTot;
+    outplQ15 += orderLo;
+    outphQ15 += orderHi;
+  }
+}
+
+/*
+Function WebRtcIsacfix_MatrixProduct1C() does one form of matrix multiplication.
+It first shifts input data of one matrix, determines the right indexes for the
+two matrixes, multiply them, and write the results into an output buffer.
+
+Note that two factors (or, multipliers) determine the initialization values of
+the variable `matrix1_index` in the code. The relationship is
+`matrix1_index` = `matrix1_index_factor1` * `matrix1_index_factor2`, where
+`matrix1_index_factor1` is given by the argument while `matrix1_index_factor2`
+is determined by the value of argument `matrix1_index_init_case`;
+`matrix1_index_factor2` is the value of the outmost loop counter j (when
+`matrix1_index_init_case` is 0), or the value of the middle loop counter k (when
+`matrix1_index_init_case` is non-zero).
+
+`matrix0_index` is determined the same way.
+
+Arguments:
+  matrix0[]:                 matrix0 data in Q15 domain.
+  matrix1[]:                 matrix1 data.
+  matrix_product[]:          output data (matrix product).
+  matrix1_index_factor1:     The first of two factors determining the
+                             initialization value of matrix1_index.
+  matrix0_index_factor1:     The first of two factors determining the
+                             initialization value of matrix0_index.
+  matrix1_index_init_case:   Case number for selecting the second of two
+                             factors determining the initialization value
+                             of matrix1_index and matrix0_index.
+  matrix1_index_step:        Incremental step for matrix1_index.
+  matrix0_index_step:        Incremental step for matrix0_index.
+  inner_loop_count:          Maximum count of the inner loop.
+  mid_loop_count:            Maximum count of the intermediate loop.
+  shift:                     Left shift value for matrix1.
+*/
+void WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
+                                   const int32_t matrix1[],
+                                   int32_t matrix_product[],
+                                   const int matrix1_index_factor1,
+                                   const int matrix0_index_factor1,
+                                   const int matrix1_index_init_case,
+                                   const int matrix1_index_step,
+                                   const int matrix0_index_step,
+                                   const int inner_loop_count,
+                                   const int mid_loop_count,
+                                   const int shift) {
+  int j = 0, k = 0, n = 0;
+  int matrix0_index = 0, matrix1_index = 0, matrix_prod_index = 0;
+  int* matrix0_index_factor2 = &k;
+  int* matrix1_index_factor2 = &j;
+  if (matrix1_index_init_case != 0) {
+    matrix0_index_factor2 = &j;
+    matrix1_index_factor2 = &k;
+  }
+
+  for (j = 0; j < SUBFRAMES; j++) {
+    matrix_prod_index = mid_loop_count * j;
+    for (k = 0; k < mid_loop_count; k++) {
+      int32_t sum32 = 0;
+      matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
+      matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
+      for (n = 0; n < inner_loop_count; n++) {
+        sum32 += WEBRTC_SPL_MUL_16_32_RSFT16(
+            matrix0[matrix0_index], matrix1[matrix1_index] * (1 << shift));
+        matrix0_index += matrix0_index_step;
+        matrix1_index += matrix1_index_step;
+      }
+      matrix_product[matrix_prod_index] = sum32;
+      matrix_prod_index++;
+    }
+  }
+}
+
+/*
+Function WebRtcIsacfix_MatrixProduct2C() returns the product of two matrixes,
+one of which has two columns. It first has to determine the correct index of
+the first matrix before doing the actual element multiplication.
+
+Arguments:
+  matrix0[]:                 A matrix in Q15 domain.
+  matrix1[]:                 A matrix in Q21 domain.
+  matrix_product[]:          Output data in Q17 domain.
+  matrix0_index_factor:      A factor determining the initialization value
+                             of matrix0_index.
+  matrix0_index_step:        Incremental step for matrix0_index.
+*/
+void WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
+                                   const int32_t matrix1[],
+                                   int32_t matrix_product[],
+                                   const int matrix0_index_factor,
+                                   const int matrix0_index_step) {
+  int j = 0, n = 0;
+  int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    int32_t sum32 = 0, sum32_2 = 0;
+    matrix1_index = 0;
+    matrix0_index = matrix0_index_factor * j;
+    for (n = SUBFRAMES; n > 0; n--) {
+      sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+                                            matrix1[matrix1_index]));
+      sum32_2 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+                                            matrix1[matrix1_index + 1]));
+      matrix1_index += 2;
+      matrix0_index += matrix0_index_step;
+    }
+    matrix_product[matrix_prod_index] = sum32 >> 3;
+    matrix_product[matrix_prod_index + 1] = sum32_2 >> 3;
+    matrix_prod_index += 2;
+  }
+}
+
+int WebRtcIsacfix_DecodeLpc(int32_t *gain_lo_hiQ17,
+                            int16_t *LPCCoef_loQ15,
+                            int16_t *LPCCoef_hiQ15,
+                            Bitstr_dec *streamdata,
+                            int16_t *outmodel) {
+
+  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+  int err;
+
+  err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel);
+  if (err<0)  // error check
+    return -ISAC_RANGE_ERROR_DECODE_LPC;
+
+  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+  return 0;
+}
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
+                                int32_t *LPCCoefQ17,
+                                int32_t *gain_lo_hiQ17,
+                                int16_t *outmodel)
+{
+  int j, k, n;
+  int err;
+  int16_t pos, pos2, posg, poss;
+  int16_t gainpos;
+  int16_t model;
+  int16_t index_QQ[KLT_ORDER_SHAPE];
+  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+  int16_t tmpcoeffs_sQ10[KLT_ORDER_SHAPE];
+  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+  int32_t tmpcoeffs2_sQ18[KLT_ORDER_SHAPE];
+  int32_t sumQQ;
+  int16_t sumQQ16;
+  int32_t tmp32;
+
+
+
+  /* entropy decoding of model number */
+  err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1);
+  if (err<0)  // error check
+    return err;
+
+  /* entropy decoding of quantization indices */
+  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE);
+  if (err<0)  // error check
+    return err;
+  /* find quantization levels for coefficients */
+  for (k=0; k<KLT_ORDER_SHAPE; k++) {
+    tmpcoeffs_sQ10[WebRtcIsacfix_kSelIndShape[k]] = WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[model]+WebRtcIsacfix_kOffsetShape[model][k] + index_QQ[k]];
+  }
+
+  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfGainPtr[model], WebRtcIsacfix_kInitIndexGain[model], KLT_ORDER_GAIN);
+  if (err<0)  // error check
+    return err;
+  /* find quantization levels for coefficients */
+  for (k=0; k<KLT_ORDER_GAIN; k++) {
+    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[model]+ WebRtcIsacfix_kOffsetGain[model][k] + index_QQ[k]];
+  }
+
+
+  /* inverse KLT  */
+
+  /* left transform */  // Transpose matrix!
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1GainQ15[model], tmpcoeffs_gQ17,
+                               tmpcoeffs2_gQ21, kTIndexFactor2, kTIndexFactor2,
+                               kTInitCase0, kTIndexStep1, kTIndexStep1,
+                               kTLoopCount2, kTLoopCount2, kTMatrix1_shift5);
+
+  poss = 0;
+  for (j=0; j<SUBFRAMES; j++) {
+    for (k=0; k<LPC_SHAPE_ORDER; k++) {
+      sumQQ = 0;
+      pos = LPC_SHAPE_ORDER * j;
+      pos2 = LPC_SHAPE_ORDER * k;
+      for (n=0; n<LPC_SHAPE_ORDER; n++) {
+        sumQQ += tmpcoeffs_sQ10[pos] *
+            WebRtcIsacfix_kT1ShapeQ15[model][pos2] >> 7;  // (Q10*Q15)>>7 = Q18
+        pos++;
+        pos2++;
+      }
+      tmpcoeffs2_sQ18[poss] = sumQQ; //Q18
+      poss++;
+    }
+  }
+
+  /* right transform */ // Transpose matrix
+  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[model],
+      tmpcoeffs2_sQ18, tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1,
+      kTInitCase1, kTIndexStep3, kTIndexStep2, kTLoopCount1, kTLoopCount3,
+      kTMatrix1_shift0);
+
+  /* scaling, mean addition, and gain restoration */
+  gainpos = 0;
+  posg = 0;poss = 0;pos=0;
+  for (k=0; k<SUBFRAMES; k++) {
+
+    /* log gains */
+    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+    gainpos++;
+    posg++;
+
+    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+    gainpos++;
+    posg++;
+
+    /* lo band LAR coeffs */
+    for (n=0; n<ORDERLO; n++, pos++, poss++) {
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+      LPCCoefQ17[pos] = tmp32;
+    }
+
+    /* hi band LAR coeffs */
+    for (n=0; n<ORDERHI; n++, pos++, poss++) {
+      // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+      tmp32 =
+          WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) * (1 << 3);
+      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+      LPCCoefQ17[pos] = tmp32;
+    }
+  }
+
+
+  *outmodel=model;
+
+  return 0;
+}
+
+/* estimate codel length of LPC Coef */
+static int EstCodeLpcCoef(int32_t *LPCCoefQ17,
+                          int32_t *gain_lo_hiQ17,
+                          int16_t *model,
+                          int32_t *sizeQ11,
+                          Bitstr_enc *streamdata,
+                          IsacSaveEncoderData* encData,
+                          transcode_obj *transcodingParam) {
+  int j, k, n;
+  int16_t posQQ, pos2QQ, gainpos;
+  int16_t  pos, poss, posg, offsg;
+  int16_t index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE];
+  int16_t index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE];
+  int32_t BitsQQ;
+
+  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs2_sQ17[KLT_ORDER_SHAPE];
+  int32_t sumQQ;
+  int32_t tmp32;
+  int16_t sumQQ16;
+  int status = 0;
+
+  /* write LAR coefficients to statistics file */
+  /* Save data for creation of multiple bitstreams (and transcoding) */
+  if (encData != NULL) {
+    for (k=0; k<KLT_ORDER_GAIN; k++) {
+      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+    }
+  }
+
+  /* log gains, mean removal and scaling */
+  posg = 0;poss = 0;pos=0; gainpos=0;
+
+  for (k=0; k<SUBFRAMES; k++) {
+    /* log gains */
+
+    /* The input argument X to logN(X) is 2^17 times higher than the
+       input floating point argument Y to log(Y), since the X value
+       is a Q17 value. This can be compensated for after the call, by
+       subraction a value Z for each Q-step. One Q-step means that
+       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+       177.445678 should be subtracted (since logN() returns a Q8 value).
+       For a X value in Q17, the value 177.445678*17 = 3017 should be
+       subtracted */
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+
+    /* lo band LAR coeffs */
+    for (n=0; n<ORDERLO; n++, poss++, pos++) {
+      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(17203, tmp32<<3); // tmp32 = 2.1*tmp32
+      tmpcoeffs_sQ17[poss] = tmp32; //Q17
+    }
+
+    /* hi band LAR coeffs */
+    for (n=0; n<ORDERHI; n++, poss++, pos++) {
+      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(14746, tmp32<<1); // tmp32 = 0.45*tmp32
+      tmpcoeffs_sQ17[poss] = tmp32; //Q17
+    }
+
+  }
+
+
+  /* KLT  */
+
+  /* left transform */
+  offsg = 0;
+  posg = 0;
+  for (j=0; j<SUBFRAMES; j++) {
+    // Q21 = Q6 * Q15
+    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
+        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+    tmpcoeffs2_gQ21[posg] = sumQQ;
+    posg++;
+
+    // Q21 = Q6 * Q15
+    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
+        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+    tmpcoeffs2_gQ21[posg] = sumQQ;
+    posg++;
+
+    offsg += 2;
+  }
+
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
+      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor1, kTInitCase0,
+      kTIndexStep1, kTIndexStep3, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
+
+  /* right transform */
+  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
+      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor3, kTInitCase1, kTIndexStep3,
+      kTIndexStep1, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
+
+  /* quantize coefficients */
+
+  BitsQQ = 0;
+  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+  {
+    posQQ = WebRtcIsacfix_kSelIndGain[k];
+    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+    if (index_gQQ[k] < 0) {
+      index_gQQ[k] = 0;
+    }
+    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+    }
+    index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k];
+    posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k];
+
+    /* Save data for creation of multiple bitstreams */
+    if (encData != NULL) {
+      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+    }
+
+    /* determine number of bits */
+    sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11
+    BitsQQ += sumQQ;
+  }
+
+  for (k=0; k<KLT_ORDER_SHAPE; k++) //ATTN: ok?
+  {
+    index_sQQ[k] = (int16_t)(CalcLrIntQ(tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]], 17) + WebRtcIsacfix_kQuantMinShape[k]); //ATTN: ok?
+
+    if (index_sQQ[k] < 0)
+      index_sQQ[k] = 0;
+    else if (index_sQQ[k] > WebRtcIsacfix_kMaxIndShape[k])
+      index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k];
+    index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k];
+
+    posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k];
+    sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11
+    BitsQQ += sumQQ;
+  }
+
+
+
+  *model = 0;
+  *sizeQ11=BitsQQ;
+
+  /* entropy coding of model number */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1);
+  if (status < 0) {
+    return status;
+  }
+
+  /* entropy coding of quantization indices - shape only */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+  if (status < 0) {
+    return status;
+  }
+
+  /* Save data for creation of multiple bitstreams */
+  if (encData != NULL) {
+    for (k=0; k<KLT_ORDER_SHAPE; k++)
+    {
+      encData->LPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k];
+    }
+  }
+  /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */
+  transcodingParam->full         = streamdata->full;
+  transcodingParam->stream_index = streamdata->stream_index;
+  transcodingParam->streamval    = streamdata->streamval;
+  transcodingParam->W_upper      = streamdata->W_upper;
+  transcodingParam->beforeLastWord     = streamdata->stream[streamdata->stream_index-1];
+  transcodingParam->lastWord     = streamdata->stream[streamdata->stream_index];
+
+  /* entropy coding of index */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+  if (status < 0) {
+    return status;
+  }
+
+  /* find quantization levels for shape coefficients */
+  for (k=0; k<KLT_ORDER_SHAPE; k++) {
+    tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]] = WEBRTC_SPL_MUL(128, WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[0]+index_ovr_sQQ[k]]);
+
+  }
+  /* inverse KLT  */
+
+  /* left transform */  // Transpose matrix!
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
+      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor4, kTInitCase0,
+      kTIndexStep1, kTIndexStep1, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
+
+  /* right transform */ // Transpose matrix
+  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
+      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1, kTInitCase1, kTIndexStep3,
+      kTIndexStep2, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
+
+  /* scaling, mean addition, and gain restoration */
+  poss = 0;pos=0;
+  for (k=0; k<SUBFRAMES; k++) {
+
+    /* lo band LAR coeffs */
+    for (n=0; n<ORDERLO; n++, pos++, poss++) {
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+      LPCCoefQ17[pos] = tmp32;
+    }
+
+    /* hi band LAR coeffs */
+    for (n=0; n<ORDERHI; n++, pos++, poss++) {
+      // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) << 3;
+      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+      LPCCoefQ17[pos] = tmp32;
+    }
+
+  }
+
+  //to update tmpcoeffs_gQ17 to the proper state
+  for (k=0; k<KLT_ORDER_GAIN; k++) {
+    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[0]+index_ovr_gQQ[k]];
+  }
+
+
+
+  /* find quantization levels for coefficients */
+
+  /* left transform */
+  offsg = 0;
+  posg = 0;
+  for (j=0; j<SUBFRAMES; j++) {
+    // (Q15 * Q17) >> (16 - 1) = Q17; Q17 << 4 = Q21.
+    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][0],
+                                         tmpcoeffs_gQ17[offsg]) << 1);
+    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][1],
+                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
+    tmpcoeffs2_gQ21[posg] = sumQQ << 4;
+    posg++;
+
+    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][2],
+                                         tmpcoeffs_gQ17[offsg]) << 1);
+    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][3],
+                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
+    tmpcoeffs2_gQ21[posg] = sumQQ << 4;
+    posg++;
+    offsg += 2;
+  }
+
+  /* right transform */ // Transpose matrix
+  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
+
+  /* scaling, mean addition, and gain restoration */
+  posg = 0;
+  gainpos = 0;
+  for (k=0; k<2*SUBFRAMES; k++) {
+
+    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg];
+    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+
+    gainpos++;
+    pos++;posg++;
+  }
+
+  return 0;
+}
+
+int WebRtcIsacfix_EstCodeLpcGain(int32_t *gain_lo_hiQ17,
+                                 Bitstr_enc *streamdata,
+                                 IsacSaveEncoderData* encData) {
+  int j, k;
+  int16_t posQQ, pos2QQ, gainpos;
+  int16_t posg;
+  int16_t index_gQQ[KLT_ORDER_GAIN];
+
+  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+  int32_t sumQQ;
+  int status = 0;
+
+  /* write LAR coefficients to statistics file */
+  /* Save data for creation of multiple bitstreams (and transcoding) */
+  if (encData != NULL) {
+    for (k=0; k<KLT_ORDER_GAIN; k++) {
+      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+    }
+  }
+
+  /* log gains, mean removal and scaling */
+  posg = 0; gainpos = 0;
+
+  for (k=0; k<SUBFRAMES; k++) {
+    /* log gains */
+
+    /* The input argument X to logN(X) is 2^17 times higher than the
+       input floating point argument Y to log(Y), since the X value
+       is a Q17 value. This can be compensated for after the call, by
+       subraction a value Z for each Q-step. One Q-step means that
+       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+       177.445678 should be subtracted (since logN() returns a Q8 value).
+       For a X value in Q17, the value 177.445678*17 = 3017 should be
+       subtracted */
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+  }
+
+
+  /* KLT  */
+
+  /* left transform */
+  posg = 0;
+  for (j=0; j<SUBFRAMES; j++) {
+      // Q21 = Q6 * Q15
+      sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][0] +
+          tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+      tmpcoeffs2_gQ21[posg] = sumQQ;
+      posg++;
+
+      sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][1] +
+          tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+      tmpcoeffs2_gQ21[posg] = sumQQ;
+      posg++;
+  }
+
+  /* right transform */
+  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+  /* quantize coefficients */
+
+  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+  {
+    posQQ = WebRtcIsacfix_kSelIndGain[k];
+    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+    if (index_gQQ[k] < 0) {
+      index_gQQ[k] = 0;
+    }
+    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+    }
+
+    /* Save data for creation of multiple bitstreams */
+    if (encData != NULL) {
+      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+    }
+  }
+
+  /* entropy coding of index */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+  if (status < 0) {
+    return status;
+  }
+
+  return 0;
+}
+
+
+int WebRtcIsacfix_EncodeLpc(int32_t *gain_lo_hiQ17,
+                            int16_t *LPCCoef_loQ15,
+                            int16_t *LPCCoef_hiQ15,
+                            int16_t *model,
+                            int32_t *sizeQ11,
+                            Bitstr_enc *streamdata,
+                            IsacSaveEncoderData* encData,
+                            transcode_obj *transcodeParam)
+{
+  int status = 0;
+  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+  // = (6+12)*6 == 108
+
+  Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17);
+
+  status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11,
+                          streamdata, encData, transcodeParam);
+  if (status < 0) {
+    return (status);
+  }
+
+  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+  return 0;
+}
+
+
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, int16_t *RCQ15)
+{
+  int k, err;
+  int16_t index[AR_ORDER];
+
+  /* entropy decoding of quantization indices */
+  err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER);
+  if (err<0)  // error check
+    return err;
+
+  /* find quantization levels for reflection coefficients */
+  for (k=0; k<AR_ORDER; k++)
+  {
+    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+  }
+
+  return 0;
+}
+
+
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(int16_t *RCQ15, Bitstr_enc *streamdata)
+{
+  int k;
+  int16_t index[AR_ORDER];
+  int status;
+
+  /* quantize reflection coefficients (add noise feedback?) */
+  for (k=0; k<AR_ORDER; k++)
+  {
+    index[k] = WebRtcIsacfix_kRcInitInd[k];
+
+    if (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k]])
+    {
+      while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1])
+        index[k]++;
+    }
+    else
+    {
+      while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ;
+    }
+
+    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+  }
+
+
+  /* entropy coding of quantization indices */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER);
+
+  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+  return status;
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, int32_t *gainQ10)
+{
+  int err;
+  int16_t index;
+
+  /* entropy decoding of quantization index */
+  err = WebRtcIsacfix_DecHistOneStepMulti(
+      &index,
+      streamdata,
+      WebRtcIsacfix_kGainPtr,
+      WebRtcIsacfix_kGainInitInd,
+      1);
+  /* error check */
+  if (err<0) {
+    return err;
+  }
+
+  /* find quantization level */
+  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+  return 0;
+}
+
+
+
+/* quantize & code squared Gain */
+int WebRtcIsacfix_EncodeGain2(int32_t *gainQ10, Bitstr_enc *streamdata)
+{
+  int16_t index;
+  int status = 0;
+
+  /* find quantization index */
+  index = WebRtcIsacfix_kGainInitInd[0];
+  if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index])
+  {
+    while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1])
+      index++;
+  }
+  else
+  {
+    while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ;
+  }
+
+  /* dequantize */
+  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+  /* entropy coding of quantization index */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1);
+
+  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+  return status;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, int16_t *PitchGains_Q12)
+{
+  int err;
+  int16_t index_comb;
+  const uint16_t *pitch_gain_cdf_ptr[1];
+
+  /* entropy decoding of quantization indices */
+  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+  err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 1);
+  /* error check, Q_mean_Gain.. tables are of size 144 */
+  if ((err < 0) || (index_comb < 0) || (index_comb >= 144))
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+
+  /* unquantize back to pitch gains by table look-up */
+  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+  return 0;
+}
+
+
+/* quantize & code Pitch Gains */
+int WebRtcIsacfix_EncodePitchGain(int16_t* PitchGains_Q12,
+                                  Bitstr_enc* streamdata,
+                                  IsacSaveEncoderData* encData) {
+  int k,j;
+  int16_t SQ15[PITCH_SUBFRAMES];
+  int16_t index[3];
+  int16_t index_comb;
+  const uint16_t *pitch_gain_cdf_ptr[1];
+  int32_t CQ17;
+  int status = 0;
+
+
+  /* get the approximate arcsine (almost linear)*/
+  for (k=0; k<PITCH_SUBFRAMES; k++)
+    SQ15[k] = (int16_t)(PitchGains_Q12[k] * 33 >> 2);  // Q15
+
+
+  /* find quantization index; only for the first three transform coefficients */
+  for (k=0; k<3; k++)
+  {
+    /*  transform */
+    CQ17=0;
+    for (j=0; j<PITCH_SUBFRAMES; j++) {
+      CQ17 += WebRtcIsacfix_kTransform[k][j] * SQ15[j] >> 10;  // Q17
+    }
+
+    index[k] = (int16_t)((CQ17 + 8192)>>14); // Rounding and scaling with stepsize (=1/0.125=8)
+
+    /* check that the index is not outside the boundaries of the table */
+    if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k];
+    else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k];
+    index[k] -= WebRtcIsacfix_kLowerlimiGain[k];
+  }
+
+  /* calculate unique overall index */
+  index_comb = (int16_t)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) +
+                               WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]);
+
+  /* unquantize back to pitch gains by table look-up */
+  // (Y)
+  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+
+  /* entropy coding of quantization pitch gains */
+  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+  status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1);
+  if (status < 0) {
+    return status;
+  }
+
+  /* Save data for creation of multiple bitstreams */
+  if (encData != NULL) {
+    encData->pitchGain_index[encData->startIdx] = index_comb;
+  }
+
+  return 0;
+}
+
+
+
+/* Pitch LAG */
+
+
+/* decode & dequantize Pitch Lags */
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
+                                 int16_t *PitchGain_Q12,
+                                 int16_t *PitchLags_Q7)
+{
+  int k, err;
+  int16_t index[PITCH_SUBFRAMES];
+  const int16_t *mean_val2Q10, *mean_val4Q10;
+
+  const int16_t *lower_limit;
+  const uint16_t *init_index;
+  const uint16_t *cdf_size;
+  const uint16_t **cdf;
+
+  int32_t meangainQ12;
+  int32_t CQ11, CQ10,tmp32a,tmp32b;
+  int16_t shft;
+
+  meangainQ12=0;
+  for (k = 0; k < 4; k++)
+    meangainQ12 += PitchGain_Q12[k];
+
+  meangainQ12 >>= 2;  // Get average.
+
+  /* voicing classificiation */
+  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
+    shft = -1;        // StepSize=2.0;
+    cdf = WebRtcIsacfix_kPitchLagPtrLo;
+    cdf_size = WebRtcIsacfix_kPitchLagSizeLo;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+    lower_limit = WebRtcIsacfix_kLowerLimitLo;
+    init_index = WebRtcIsacfix_kInitIndLo;
+  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
+    shft = 0;        // StepSize=1.0;
+    cdf = WebRtcIsacfix_kPitchLagPtrMid;
+    cdf_size = WebRtcIsacfix_kPitchLagSizeMid;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+    lower_limit = WebRtcIsacfix_kLowerLimitMid;
+    init_index = WebRtcIsacfix_kInitIndMid;
+  } else {
+    shft = 1;        // StepSize=0.5;
+    cdf = WebRtcIsacfix_kPitchLagPtrHi;
+    cdf_size = WebRtcIsacfix_kPitchLagSizeHi;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+    lower_limit = WebRtcIsacfix_kLowerLimitHi;
+    init_index = WebRtcIsacfix_kInitIndHi;
+  }
+
+  /* entropy decoding of quantization indices */
+  err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+  if ((err<0) || (index[0]<0))  // error check
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+  err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
+  if (err<0)  // error check
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+
+  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+  CQ11 = ((int32_t)index[0] + lower_limit[0]);  // Q0
+  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11);
+    PitchLags_Q7[k] = (int16_t)(tmp32a >> 5);
+  }
+
+  CQ10 = mean_val2Q10[index[1]];
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
+    PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
+  }
+
+  CQ10 = mean_val4Q10[index[3]];
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
+    PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
+  }
+
+  return 0;
+}
+
+
+
+/* quantize & code Pitch Lags */
+int WebRtcIsacfix_EncodePitchLag(int16_t* PitchLagsQ7,
+                                 int16_t* PitchGain_Q12,
+                                 Bitstr_enc* streamdata,
+                                 IsacSaveEncoderData* encData) {
+  int k, j;
+  int16_t index[PITCH_SUBFRAMES];
+  int32_t meangainQ12, CQ17;
+  int32_t CQ11, CQ10,tmp32a;
+
+  const int16_t *mean_val2Q10,*mean_val4Q10;
+  const int16_t *lower_limit, *upper_limit;
+  const uint16_t **cdf;
+  int16_t shft, tmp16b;
+  int32_t tmp32b;
+  int status = 0;
+
+  /* compute mean pitch gain */
+  meangainQ12=0;
+  for (k = 0; k < 4; k++)
+    meangainQ12 += PitchGain_Q12[k];
+
+  meangainQ12 >>= 2;
+
+  /* Save data for creation of multiple bitstreams */
+  if (encData != NULL) {
+    encData->meanGain[encData->startIdx] = meangainQ12;
+  }
+
+  /* voicing classificiation */
+  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
+    shft = -1;        // StepSize=2.0;
+    cdf = WebRtcIsacfix_kPitchLagPtrLo;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+    lower_limit = WebRtcIsacfix_kLowerLimitLo;
+    upper_limit = WebRtcIsacfix_kUpperLimitLo;
+  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
+    shft = 0;        // StepSize=1.0;
+    cdf = WebRtcIsacfix_kPitchLagPtrMid;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+    lower_limit = WebRtcIsacfix_kLowerLimitMid;
+    upper_limit = WebRtcIsacfix_kUpperLimitMid;
+  } else {
+    shft = 1;        // StepSize=0.5;
+    cdf = WebRtcIsacfix_kPitchLagPtrHi;
+    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+    lower_limit = WebRtcIsacfix_kLowerLimitHi;
+    upper_limit = WebRtcIsacfix_kUpperLimitHi;
+  }
+
+  /* find quantization index */
+  for (k=0; k<4; k++)
+  {
+    /*  transform */
+    CQ17=0;
+    for (j=0; j<PITCH_SUBFRAMES; j++)
+      CQ17 += WebRtcIsacfix_kTransform[k][j] * PitchLagsQ7[j] >> 2;  // Q17
+
+    CQ17 = WEBRTC_SPL_SHIFT_W32(CQ17,shft); // Scale with StepSize
+
+    /* quantize */
+    tmp16b = (int16_t)((CQ17 + 65536) >> 17);
+    index[k] =  tmp16b;
+
+    /* check that the index is not outside the boundaries of the table */
+    if (index[k] < lower_limit[k]) index[k] = lower_limit[k];
+    else if (index[k] > upper_limit[k]) index[k] = upper_limit[k];
+    index[k] -= lower_limit[k];
+
+    /* Save data for creation of multiple bitstreams */
+    if(encData != NULL) {
+      encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
+    }
+  }
+
+  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+  CQ11 = (index[0] + lower_limit[0]);  // Q0
+  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11); // Q12
+    PitchLagsQ7[k] = (int16_t)(tmp32a >> 5);  // Q7.
+  }
+
+  CQ10 = mean_val2Q10[index[1]];
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
+    PitchLagsQ7[k] += (int16_t)(tmp32b >> 5);  // Q7.
+  }
+
+  CQ10 = mean_val4Q10[index[3]];
+  for (k=0; k<PITCH_SUBFRAMES; k++) {
+    tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
+    PitchLagsQ7[k] += (int16_t)(tmp32b >> 5);  // Q7.
+  }
+
+  /* entropy coding of quantization pitch lags */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+
+  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+  return status;
+}
+
+
+
+/* Routines for inband signaling of bandwitdh estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const uint16_t kFrameLenCdf[4] = {
+  0, 21845, 43690, 65535};
+
+/* pointer to cdf array for frame length indicator */
+const uint16_t * const kFrameLenCdfPtr[1] = {kFrameLenCdf};
+
+/* initial cdf index for decoder of frame length indicator */
+const uint16_t kFrameLenInitIndex[1] = {1};
+
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
+                                 size_t *framesamples)
+{
+
+  int err;
+  int16_t frame_mode;
+
+  err = 0;
+  /* entropy decoding of frame length [1:30ms,2:60ms] */
+  err = WebRtcIsacfix_DecHistOneStepMulti(&frame_mode, streamdata, kFrameLenCdfPtr, kFrameLenInitIndex, 1);
+  if (err<0)  // error check
+    return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
+
+  switch(frame_mode) {
+    case 1:
+      *framesamples = 480; /* 30ms */
+      break;
+    case 2:
+      *framesamples = 960; /* 60ms */
+      break;
+    default:
+      err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
+  }
+
+  return err;
+}
+
+
+int WebRtcIsacfix_EncodeFrameLen(int16_t framesamples, Bitstr_enc *streamdata) {
+
+  int status;
+  int16_t frame_mode;
+
+  status = 0;
+  frame_mode = 0;
+  /* entropy coding of frame length [1:480 samples,2:960 samples] */
+  switch(framesamples) {
+    case 480:
+      frame_mode = 1;
+      break;
+    case 960:
+      frame_mode = 2;
+      break;
+    default:
+      status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
+  }
+
+  if (status < 0)
+    return status;
+
+  status = WebRtcIsacfix_EncHistMulti(streamdata, &frame_mode, kFrameLenCdfPtr, 1);
+
+  return status;
+}
+
+/* cdf array for estimated bandwidth */
+const uint16_t kBwCdf[25] = {
+  0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
+  32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
+  62804, 65535};
+
+/* pointer to cdf array for estimated bandwidth */
+const uint16_t * const kBwCdfPtr[1] = {kBwCdf};
+
+/* initial cdf index for decoder of estimated bandwidth*/
+const uint16_t kBwInitIndex[1] = {7};
+
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata, int16_t *BWno) {
+
+  int err;
+  int16_t BWno32;
+
+  /* entropy decoding of sender's BW estimation [0..23] */
+  err = WebRtcIsacfix_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr, kBwInitIndex, 1);
+  if (err<0)  // error check
+    return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+  *BWno = (int16_t)BWno32;
+  return err;
+
+}
+
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(int16_t *BWno, Bitstr_enc *streamdata)
+{
+  int status = 0;
+  /* entropy encoding of receiver's BW estimation [0..23] */
+  status = WebRtcIsacfix_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+
+  return status;
+}
+
+/* estimate codel length of LPC Coef */
+void WebRtcIsacfix_TranscodeLpcCoef(int32_t *gain_lo_hiQ17,
+                                    int16_t *index_gQQ) {
+  int j, k;
+  int16_t posQQ, pos2QQ;
+  int16_t posg, offsg, gainpos;
+  int32_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+  int32_t sumQQ;
+
+
+  /* log gains, mean removal and scaling */
+  posg = 0; gainpos=0;
+
+  for (k=0; k<SUBFRAMES; k++) {
+    /* log gains */
+
+    /* The input argument X to logN(X) is 2^17 times higher than the
+       input floating point argument Y to log(Y), since the X value
+       is a Q17 value. This can be compensated for after the call, by
+       subraction a value Z for each Q-step. One Q-step means that
+       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+       177.445678 should be subtracted (since logN() returns a Q8 value).
+       For a X value in Q17, the value 177.445678*17 = 3017 should be
+       subtracted */
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+
+    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+    posg++; gainpos++;
+
+  }
+
+
+  /* KLT  */
+
+  /* left transform */
+  for (j = 0, offsg = 0; j < SUBFRAMES; j++, offsg += 2) {
+    // Q21 = Q6 * Q15
+    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
+        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+    tmpcoeffs2_gQ21[offsg] = sumQQ;
+
+    // Q21 = Q6 * Q15
+    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
+        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+    tmpcoeffs2_gQ21[offsg + 1] = sumQQ;
+  }
+
+  /* right transform */
+  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+  /* quantize coefficients */
+  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+  {
+    posQQ = WebRtcIsacfix_kSelIndGain[k];
+    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+    if (index_gQQ[k] < 0) {
+      index_gQQ[k] = 0;
+    }
+    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+    }
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h b/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
new file mode 100644
index 0000000..ae11394
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file contains all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/* decode complex spectrum (return number of bytes in stream) */
+int WebRtcIsacfix_DecodeSpec(Bitstr_dec* streamdata,
+                             int16_t* frQ7,
+                             int16_t* fiQ7,
+                             int16_t AvgPitchGain_Q12);
+
+/* encode complex spectrum */
+int WebRtcIsacfix_EncodeSpec(const int16_t* fr,
+                             const int16_t* fi,
+                             Bitstr_enc* streamdata,
+                             int16_t AvgPitchGain_Q12);
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec* streamdata,
+                                int32_t* LPCCoefQ17,
+                                int32_t* gain_lo_hiQ17,
+                                int16_t* outmodel);
+
+int WebRtcIsacfix_DecodeLpc(int32_t* gain_lo_hiQ17,
+                            int16_t* LPCCoef_loQ15,
+                            int16_t* LPCCoef_hiQ15,
+                            Bitstr_dec* streamdata,
+                            int16_t* outmodel);
+
+/* quantize & code LPC Coef */
+int WebRtcIsacfix_EncodeLpc(int32_t* gain_lo_hiQ17,
+                            int16_t* LPCCoef_loQ15,
+                            int16_t* LPCCoef_hiQ15,
+                            int16_t* model,
+                            int32_t* sizeQ11,
+                            Bitstr_enc* streamdata,
+                            IsacSaveEncoderData* encData,
+                            transcode_obj* transcodeParam);
+
+int WebRtcIsacfix_EstCodeLpcGain(int32_t* gain_lo_hiQ17,
+                                 Bitstr_enc* streamdata,
+                                 IsacSaveEncoderData* encData);
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec* streamdata, int16_t* RCQ15);
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(int16_t* RCQ15, Bitstr_enc* streamdata);
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec* streamdata, int32_t* Gain2);
+
+/* quantize & code squared Gain (input is squared gain) */
+int WebRtcIsacfix_EncodeGain2(int32_t* gain2, Bitstr_enc* streamdata);
+
+int WebRtcIsacfix_EncodePitchGain(int16_t* PitchGains_Q12,
+                                  Bitstr_enc* streamdata,
+                                  IsacSaveEncoderData* encData);
+
+int WebRtcIsacfix_EncodePitchLag(int16_t* PitchLagQ7,
+                                 int16_t* PitchGain_Q12,
+                                 Bitstr_enc* streamdata,
+                                 IsacSaveEncoderData* encData);
+
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec* streamdata,
+                                  int16_t* PitchGain_Q12);
+
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec* streamdata,
+                                 int16_t* PitchGain_Q12,
+                                 int16_t* PitchLagQ7);
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec* streamdata, size_t* framelength);
+
+int WebRtcIsacfix_EncodeFrameLen(int16_t framelength, Bitstr_enc* streamdata);
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec* streamdata, int16_t* BWno);
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(int16_t* BWno, Bitstr_enc* streamdata);
+
+void WebRtcIsacfix_TranscodeLpcCoef(int32_t* tmpcoeffs_gQ6, int16_t* index_gQQ);
+
+// Pointer functions for LPC transforms.
+
+typedef void (*MatrixProduct1)(const int16_t matrix0[],
+                               const int32_t matrix1[],
+                               int32_t matrix_product[],
+                               int matrix1_index_factor1,
+                               int matrix0_index_factor1,
+                               int matrix1_index_init_case,
+                               int matrix1_index_step,
+                               int matrix0_index_step,
+                               int inner_loop_count,
+                               int mid_loop_count,
+                               int shift);
+typedef void (*MatrixProduct2)(const int16_t matrix0[],
+                               const int32_t matrix1[],
+                               int32_t matrix_product[],
+                               int matrix0_index_factor,
+                               int matrix0_index_step);
+
+extern MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
+extern MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
+
+void WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
+                                   const int32_t matrix1[],
+                                   int32_t matrix_product[],
+                                   int matrix1_index_factor1,
+                                   int matrix0_index_factor1,
+                                   int matrix1_index_init_case,
+                                   int matrix1_index_step,
+                                   int matrix0_index_step,
+                                   int inner_loop_count,
+                                   int mid_loop_count,
+                                   int shift);
+void WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
+                                   const int32_t matrix1[],
+                                   int32_t matrix_product[],
+                                   int matrix0_index_factor,
+                                   int matrix0_index_step);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      int matrix1_index_factor1,
+                                      int matrix0_index_factor1,
+                                      int matrix1_index_init_case,
+                                      int matrix1_index_step,
+                                      int matrix0_index_step,
+                                      int inner_loop_count,
+                                      int mid_loop_count,
+                                      int shift);
+void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      int matrix0_index_factor,
+                                      int matrix0_index_step);
+#endif
+
+#if defined(MIPS32_LE)
+void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      int matrix1_index_factor1,
+                                      int matrix0_index_factor1,
+                                      int matrix1_index_init_case,
+                                      int matrix1_index_step,
+                                      int matrix0_index_step,
+                                      int inner_loop_count,
+                                      int mid_loop_count,
+                                      int shift);
+
+void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      int matrix0_index_factor,
+                                      int matrix0_index_step);
+#endif
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
diff --git a/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c b/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c
new file mode 100644
index 0000000..a66a43e
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// MIPS optimization of the function WebRtcIsacfix_MatrixProduct1.
+// Bit-exact with the function WebRtcIsacfix_MatrixProduct1C from
+// entropy_coding.c file.
+void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      const int matrix1_index_factor1,
+                                      const int matrix0_index_factor1,
+                                      const int matrix1_index_init_case,
+                                      const int matrix1_index_step,
+                                      const int matrix0_index_step,
+                                      const int inner_loop_count,
+                                      const int mid_loop_count,
+                                      const int shift) {
+  if (matrix1_index_init_case != 0) {
+    int j = SUBFRAMES, k = 0, n = 0;
+    int32_t r0, r1, r2, sum32;
+    int32_t* product_start = matrix_product;
+    int32_t* product_ptr;
+    const uint32_t product_step = 4 * mid_loop_count;
+    const uint32_t matrix0_step = 2 * matrix0_index_step;
+    const uint32_t matrix1_step = 4 * matrix1_index_step;
+    const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
+    const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
+    const int16_t* matrix0_start = matrix0;
+    const int32_t* matrix1_start = matrix1;
+    int16_t* matrix0_ptr;
+    int32_t* matrix1_ptr;
+
+    __asm __volatile (
+      ".set     push                                                       \n\t"
+      ".set     noreorder                                                  \n\t"
+     "1:                                                                   \n\t"
+      "addu     %[product_ptr],     %[product_start],     $0               \n\t"
+      "addu     %[k],               %[product_step],      $0               \n\t"
+      "addiu    %[j],               %[j],                 -1               \n\t"
+      "addu     %[matrix1_start],   %[matrix1],           $0               \n\t"
+     "2:                                                                   \n\t"
+      "addu     %[matrix1_ptr],     %[matrix1_start],     $0               \n\t"
+      "addu     %[matrix0_ptr],     %[matrix0_start],     $0               \n\t"
+      "addu     %[n],               %[inner_loop_count],  $0               \n\t"
+      "mul      %[sum32],           $0,                   $0               \n\t"
+     "3:                                                                   \n\t"
+      "lw       %[r0],              0(%[matrix1_ptr])                      \n\t"
+      "lh       %[r1],              0(%[matrix0_ptr])                      \n\t"
+      "addu     %[matrix1_ptr],     %[matrix1_ptr],       %[matrix1_step]  \n\t"
+      "sllv     %[r0],              %[r0],                %[shift]         \n\t"
+      "andi     %[r2],              %[r0],                0xffff           \n\t"
+      "sra      %[r2],              %[r2],                1                \n\t"
+      "mul      %[r2],              %[r2],                %[r1]            \n\t"
+      "sra      %[r0],              %[r0],                16               \n\t"
+      "mul      %[r0],              %[r0],                %[r1]            \n\t"
+      "addu     %[matrix0_ptr],     %[matrix0_ptr],       %[matrix0_step]  \n\t"
+      "addiu    %[n],               %[n],                 -1               \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "shra_r.w %[r2],              %[r2],                15               \n\t"
+#else
+      "addiu    %[r2],              %[r2],                0x4000           \n\t"
+      "sra      %[r2],              %[r2],                15               \n\t"
+#endif
+      "addu     %[sum32],           %[sum32],             %[r2]            \n\t"
+      "bgtz     %[n],               3b                                     \n\t"
+      " addu    %[sum32],           %[sum32],             %[r0]            \n\t"
+      "addiu    %[k],               %[k],                 -4               \n\t"
+      "addu     %[matrix1_start],   %[matrix1_start],     %[matrix1_step2] \n\t"
+      "sw       %[sum32],           0(%[product_ptr])                      \n\t"
+      "bgtz     %[k],               2b                                     \n\t"
+      " addiu   %[product_ptr],     %[product_ptr],       4                \n\t"
+      "addu     %[matrix0_start],   %[matrix0_start],     %[matrix0_step2] \n\t"
+      "bgtz     %[j],               1b                                     \n\t"
+      " addu    %[product_start],   %[product_start],     %[product_step]  \n\t"
+      ".set     pop                                                        \n\t"
+      : [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
+        [k] "=&r" (k), [j] "+r" (j), [matrix1_start] "=&r"(matrix1_start),
+        [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+        [matrix0_start] "+r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
+        [sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
+      : [product_step] "r" (product_step), [matrix1] "r" (matrix1),
+        [inner_loop_count] "r" (inner_loop_count),
+        [matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
+        [matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
+        [matrix0_step2] "r" (matrix0_step2)
+      : "hi", "lo", "memory"
+    );
+  } else {
+    int j = SUBFRAMES, k = 0, n = 0;
+    int32_t r0, r1, r2, sum32;
+    int32_t* product_start = matrix_product;
+    int32_t* product_ptr;
+    const uint32_t product_step = 4 * mid_loop_count;
+    const uint32_t matrix0_step = 2 * matrix0_index_step;
+    const uint32_t matrix1_step = 4 * matrix1_index_step;
+    const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
+    const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
+    const int16_t* matrix0_start = matrix0;
+    const int32_t* matrix1_start = matrix1;
+    int16_t* matrix0_ptr;
+    int32_t* matrix1_ptr;
+
+    __asm __volatile (
+      ".set     push                                                       \n\t"
+      ".set     noreorder                                                  \n\t"
+     "1:                                                                   \n\t"
+      "addu     %[product_ptr],     %[product_start],     $0               \n\t"
+      "addu     %[k],               %[product_step],      $0               \n\t"
+      "addiu    %[j],               %[j],                 -1               \n\t"
+      "addu     %[matrix0_start],   %[matrix0],           $0               \n\t"
+     "2:                                                                   \n\t"
+      "addu     %[matrix1_ptr],     %[matrix1_start],     $0               \n\t"
+      "addu     %[matrix0_ptr],     %[matrix0_start],     $0               \n\t"
+      "addu     %[n],               %[inner_loop_count],  $0               \n\t"
+      "mul      %[sum32],           $0,                   $0               \n\t"
+     "3:                                                                   \n\t"
+      "lw       %[r0],              0(%[matrix1_ptr])                      \n\t"
+      "lh       %[r1],              0(%[matrix0_ptr])                      \n\t"
+      "addu     %[matrix1_ptr],     %[matrix1_ptr],       %[matrix1_step]  \n\t"
+      "sllv     %[r0],              %[r0],                %[shift]         \n\t"
+      "andi     %[r2],              %[r0],                0xffff           \n\t"
+      "sra      %[r2],              %[r2],                1                \n\t"
+      "mul      %[r2],              %[r2],                %[r1]            \n\t"
+      "sra      %[r0],              %[r0],                16               \n\t"
+      "mul      %[r0],              %[r0],                %[r1]            \n\t"
+      "addu     %[matrix0_ptr],     %[matrix0_ptr],       %[matrix0_step]  \n\t"
+      "addiu    %[n],               %[n],                 -1               \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "shra_r.w %[r2],              %[r2],                15               \n\t"
+#else
+      "addiu    %[r2],              %[r2],                0x4000           \n\t"
+      "sra      %[r2],              %[r2],                15               \n\t"
+#endif
+      "addu     %[sum32],           %[sum32],             %[r2]            \n\t"
+      "bgtz     %[n],               3b                                     \n\t"
+      " addu    %[sum32],           %[sum32],             %[r0]            \n\t"
+      "addiu    %[k],               %[k],                 -4               \n\t"
+      "addu     %[matrix0_start],   %[matrix0_start],     %[matrix0_step2] \n\t"
+      "sw       %[sum32],           0(%[product_ptr])                      \n\t"
+      "bgtz     %[k],               2b                                     \n\t"
+      " addiu   %[product_ptr],     %[product_ptr],       4                \n\t"
+      "addu     %[matrix1_start],   %[matrix1_start],     %[matrix1_step2] \n\t"
+      "bgtz     %[j],               1b                                     \n\t"
+      " addu    %[product_start],   %[product_start],     %[product_step]  \n\t"
+      ".set     pop                                                        \n\t"
+      : [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
+        [k] "=&r" (k), [j] "+r" (j), [matrix1_start] "+r"(matrix1_start),
+        [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+        [matrix0_start] "=&r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
+        [sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
+      : [product_step] "r" (product_step), [matrix0] "r" (matrix0),
+        [inner_loop_count] "r" (inner_loop_count),
+        [matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
+        [matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
+        [matrix0_step2] "r" (matrix0_step2)
+      : "hi", "lo", "memory"
+    );
+  }
+}
+
+// MIPS optimization of the function WebRtcIsacfix_MatrixProduct2.
+// Bit-exact with the function WebRtcIsacfix_MatrixProduct2C from
+// entropy_coding.c file.
+void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      const int matrix0_index_factor,
+                                      const int matrix0_index_step) {
+  int j = 0, n = 0;
+  int loop_count = SUBFRAMES;
+  const int16_t* matrix0_ptr;
+  const int32_t* matrix1_ptr;
+  const int16_t* matrix0_start = matrix0;
+  const int matrix0_step = 2 * matrix0_index_step;
+  const int matrix0_step2 = 2 * matrix0_index_factor;
+  int32_t r0, r1, r2, r3, r4, sum32, sum32_2;
+
+  __asm __volatile (
+    ".set       push                                                   \n\t"
+    ".set       noreorder                                              \n\t"
+    "addu       %[j],              %[loop_count],     $0               \n\t"
+    "addu       %[matrix0_start],  %[matrix0],        $0               \n\t"
+   "1:                                                                 \n\t"
+    "addu       %[matrix1_ptr],    %[matrix1],        $0               \n\t"
+    "addu       %[matrix0_ptr],    %[matrix0_start],  $0               \n\t"
+    "addu       %[n],              %[loop_count],     $0               \n\t"
+    "mul        %[sum32],          $0,                $0               \n\t"
+    "mul        %[sum32_2],        $0,                $0               \n\t"
+   "2:                                                                 \n\t"
+    "lw         %[r0],             0(%[matrix1_ptr])                   \n\t"
+    "lw         %[r1],             4(%[matrix1_ptr])                   \n\t"
+    "lh         %[r2],             0(%[matrix0_ptr])                   \n\t"
+    "andi       %[r3],             %[r0],             0xffff           \n\t"
+    "sra        %[r3],             %[r3],             1                \n\t"
+    "mul        %[r3],             %[r3],             %[r2]            \n\t"
+    "andi       %[r4],             %[r1],             0xffff           \n\t"
+    "sra        %[r4],             %[r4],             1                \n\t"
+    "mul        %[r4],             %[r4],             %[r2]            \n\t"
+    "sra        %[r0],             %[r0],             16               \n\t"
+    "mul        %[r0],             %[r0],             %[r2]            \n\t"
+    "sra        %[r1],             %[r1],             16               \n\t"
+    "mul        %[r1],             %[r1],             %[r2]            \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w   %[r3],             %[r3],             15               \n\t"
+    "shra_r.w   %[r4],             %[r4],             15               \n\t"
+#else
+    "addiu      %[r3],             %[r3],             0x4000           \n\t"
+    "sra        %[r3],             %[r3],             15               \n\t"
+    "addiu      %[r4],             %[r4],             0x4000           \n\t"
+    "sra        %[r4],             %[r4],             15               \n\t"
+#endif
+    "addiu      %[matrix1_ptr],    %[matrix1_ptr],    8                \n\t"
+    "addu       %[matrix0_ptr],    %[matrix0_ptr],    %[matrix0_step]  \n\t"
+    "addiu      %[n],              %[n],              -1               \n\t"
+    "addu       %[sum32],          %[sum32],          %[r3]            \n\t"
+    "addu       %[sum32_2],        %[sum32_2],        %[r4]            \n\t"
+    "addu       %[sum32],          %[sum32],          %[r0]            \n\t"
+    "bgtz       %[n],              2b                                  \n\t"
+    " addu      %[sum32_2],        %[sum32_2],        %[r1]            \n\t"
+    "sra        %[sum32],          %[sum32],          3                \n\t"
+    "sra        %[sum32_2],        %[sum32_2],        3                \n\t"
+    "addiu      %[j],              %[j],              -1               \n\t"
+    "addu       %[matrix0_start],  %[matrix0_start],  %[matrix0_step2] \n\t"
+    "sw         %[sum32],          0(%[matrix_product])                \n\t"
+    "sw         %[sum32_2],        4(%[matrix_product])                \n\t"
+    "bgtz       %[j],              1b                                  \n\t"
+    " addiu     %[matrix_product], %[matrix_product], 8                \n\t"
+    ".set       pop                                                    \n\t"
+    : [j] "=&r" (j), [matrix0_start] "=&r" (matrix0_start),
+      [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+      [n] "=&r" (n), [sum32] "=&r" (sum32), [sum32_2] "=&r" (sum32_2),
+      [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+      [r4] "=&r" (r4), [matrix_product] "+r" (matrix_product)
+    : [loop_count] "r" (loop_count), [matrix0] "r" (matrix0),
+      [matrix1] "r" (matrix1), [matrix0_step] "r" (matrix0_step),
+      [matrix0_step2] "r" (matrix0_step2)
+    : "hi", "lo", "memory"
+  );
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c b/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
new file mode 100644
index 0000000..0200567
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
@@ -0,0 +1,217 @@
+/*
+ *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* This file contains WebRtcIsacfix_MatrixProduct1Neon() and
+ * WebRtcIsacfix_MatrixProduct2Neon() for ARM Neon platform. API's are in
+ * entropy_coding.c. Results are bit exact with the c code for
+ * generic platforms.
+ */
+
+#include <arm_neon.h>
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/checks.h"
+
+void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      const int matrix1_index_factor1,
+                                      const int matrix0_index_factor1,
+                                      const int matrix1_index_init_case,
+                                      const int matrix1_index_step,
+                                      const int matrix0_index_step,
+                                      const int inner_loop_count,
+                                      const int mid_loop_count,
+                                      const int shift) {
+  int j = 0, k = 0, n = 0;
+  int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+  int* matrix1_index_factor2 = &j;
+  int* matrix0_index_factor2 = &k;
+  if (matrix1_index_init_case != 0) {
+    matrix1_index_factor2 = &k;
+    matrix0_index_factor2 = &j;
+  }
+  int32x4_t shift32x4 = vdupq_n_s32(shift);
+  int32x2_t shift32x2 = vdup_n_s32(shift);
+  int32x4_t sum_32x4 =  vdupq_n_s32(0);
+  int32x2_t sum_32x2 =  vdup_n_s32(0);
+
+  RTC_DCHECK_EQ(0, inner_loop_count % 2);
+  RTC_DCHECK_EQ(0, mid_loop_count % 2);
+
+  if (matrix1_index_init_case != 0 && matrix1_index_factor1 == 1) {
+    for (j = 0; j < SUBFRAMES; j++) {
+      matrix_prod_index = mid_loop_count * j;
+      for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
+        sum_32x4 = veorq_s32(sum_32x4, sum_32x4);  // Initialize to zeros.
+        matrix1_index = k;
+        matrix0_index = matrix0_index_factor1 * j;
+        for (n = 0; n < inner_loop_count; n++) {
+          int32x4_t matrix0_32x4 =
+              vdupq_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+          int32x4_t matrix1_32x4 =
+              vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
+          int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+          sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+          matrix1_index += matrix1_index_step;
+          matrix0_index += matrix0_index_step;
+        }
+        vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
+        matrix_prod_index += 4;
+      }
+      if (mid_loop_count % 4 > 1) {
+        sum_32x2 = veor_s32(sum_32x2, sum_32x2);  // Initialize to zeros.
+        matrix1_index = k;
+        k += 2;
+        matrix0_index = matrix0_index_factor1 * j;
+        for (n = 0; n < inner_loop_count; n++) {
+          int32x2_t matrix0_32x2 =
+              vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+          int32x2_t matrix1_32x2 =
+              vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
+          int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
+          sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+          matrix1_index += matrix1_index_step;
+          matrix0_index += matrix0_index_step;
+        }
+        vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+        matrix_prod_index += 2;
+      }
+    }
+  }
+  else if (matrix1_index_init_case == 0 && matrix0_index_factor1 == 1) {
+    int32x2_t multi_32x2 = vdup_n_s32(0);
+    int32x2_t matrix0_32x2 = vdup_n_s32(0);
+    for (j = 0; j < SUBFRAMES; j++) {
+      matrix_prod_index = mid_loop_count * j;
+      for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
+        sum_32x4 = veorq_s32(sum_32x4, sum_32x4);  // Initialize to zeros.
+        matrix1_index = matrix1_index_factor1 * j;
+        matrix0_index = k;
+        for (n = 0; n < inner_loop_count; n++) {
+          int32x4_t matrix1_32x4 = vdupq_n_s32(matrix1[matrix1_index] << shift);
+          int32x4_t matrix0_32x4 =
+              vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
+          int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+          sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+          matrix1_index += matrix1_index_step;
+          matrix0_index += matrix0_index_step;
+        }
+        vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
+        matrix_prod_index += 4;
+      }
+      if (mid_loop_count % 4 > 1) {
+        sum_32x2 = veor_s32(sum_32x2, sum_32x2);  // Initialize to zeros.
+        matrix1_index = matrix1_index_factor1 * j;
+        matrix0_index = k;
+        for (n = 0; n < inner_loop_count; n++) {
+          int32x2_t matrix1_32x2 = vdup_n_s32(matrix1[matrix1_index] << shift);
+          matrix0_32x2 =
+              vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
+          matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
+                                     matrix0_32x2, 1);
+          matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
+          multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
+          sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+          matrix1_index += matrix1_index_step;
+          matrix0_index += matrix0_index_step;
+        }
+        vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+        matrix_prod_index += 2;
+      }
+    }
+  }
+  else if (matrix1_index_init_case == 0 &&
+           matrix1_index_step == 1 &&
+           matrix0_index_step == 1) {
+    int32x2_t multi_32x2 = vdup_n_s32(0);
+    int32x2_t matrix0_32x2 = vdup_n_s32(0);
+    for (j = 0; j < SUBFRAMES; j++) {
+      matrix_prod_index = mid_loop_count * j;
+      for (k = 0; k < mid_loop_count; k++) {
+        sum_32x4 = veorq_s32(sum_32x4, sum_32x4);  // Initialize to zeros.
+        matrix1_index = matrix1_index_factor1 * j;
+        matrix0_index = matrix0_index_factor1 * k;
+        for (n = 0; n < (inner_loop_count >> 2) << 2; n += 4) {
+          int32x4_t matrix1_32x4 =
+              vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
+          int32x4_t matrix0_32x4 =
+              vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
+          int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+          sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+          matrix1_index += 4;
+          matrix0_index += 4;
+        }
+        sum_32x2 = vqadd_s32(vget_low_s32(sum_32x4), vget_high_s32(sum_32x4));
+        if (inner_loop_count % 4 > 1) {
+          int32x2_t matrix1_32x2 =
+              vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
+          matrix0_32x2 =
+              vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
+          matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
+                                     matrix0_32x2, 1);
+          matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
+          multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
+          sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+        }
+        sum_32x2 = vpadd_s32(sum_32x2, sum_32x2);
+        vst1_lane_s32(&matrix_product[matrix_prod_index], sum_32x2, 0);
+        matrix_prod_index++;
+      }
+    }
+  }
+  else {
+    for (j = 0; j < SUBFRAMES; j++) {
+      matrix_prod_index = mid_loop_count * j;
+      for (k=0; k < mid_loop_count; k++) {
+        int32_t sum32 = 0;
+        matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
+        matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
+        for (n = 0; n < inner_loop_count; n++) {
+          sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+              matrix1[matrix1_index] << shift));
+          matrix1_index += matrix1_index_step;
+          matrix0_index += matrix0_index_step;
+        }
+        matrix_product[matrix_prod_index] = sum32;
+        matrix_prod_index++;
+      }
+    }
+  }
+}
+
+void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
+                                      const int32_t matrix1[],
+                                      int32_t matrix_product[],
+                                      const int matrix0_index_factor,
+                                      const int matrix0_index_step) {
+  int j = 0, n = 0;
+  int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+  int32x2_t sum_32x2 = vdup_n_s32(0);
+  for (j = 0; j < SUBFRAMES; j++) {
+    sum_32x2 = veor_s32(sum_32x2, sum_32x2);  // Initialize to zeros.
+    matrix1_index = 0;
+    matrix0_index = matrix0_index_factor * j;
+    for (n = SUBFRAMES; n > 0; n--) {
+      int32x2_t matrix0_32x2 =
+          vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+      int32x2_t matrix1_32x2 = vld1_s32(&matrix1[matrix1_index]);
+      int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
+      sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+      matrix1_index += 2;
+      matrix0_index += matrix0_index_step;
+    }
+    sum_32x2 = vshr_n_s32(sum_32x2, 3);
+    vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+    matrix_prod_index += 2;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/fft.c b/modules/audio_coding/codecs/isac/fix/source/fft.c
new file mode 100644
index 0000000..a0ed3f8
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/fft.c
@@ -0,0 +1,415 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * fft.c
+ *
+ * Fast Fourier Transform
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+
+static const int16_t kSortTabFft[240] = {
+  0, 60, 120, 180, 20, 80, 140, 200, 40, 100, 160, 220,
+  4, 64, 124, 184, 24, 84, 144, 204, 44, 104, 164, 224,
+  8, 68, 128, 188, 28, 88, 148, 208, 48, 108, 168, 228,
+  12, 72, 132, 192, 32, 92, 152, 212, 52, 112, 172, 232,
+  16, 76, 136, 196, 36, 96, 156, 216, 56, 116, 176, 236,
+  1, 61, 121, 181, 21, 81, 141, 201, 41, 101, 161, 221,
+  5, 65, 125, 185, 25, 85, 145, 205, 45, 105, 165, 225,
+  9, 69, 129, 189, 29, 89, 149, 209, 49, 109, 169, 229,
+  13, 73, 133, 193, 33, 93, 153, 213, 53, 113, 173, 233,
+  17, 77, 137, 197, 37, 97, 157, 217, 57, 117, 177, 237,
+  2, 62, 122, 182, 22, 82, 142, 202, 42, 102, 162, 222,
+  6, 66, 126, 186, 26, 86, 146, 206, 46, 106, 166, 226,
+  10, 70, 130, 190, 30, 90, 150, 210, 50, 110, 170, 230,
+  14, 74, 134, 194, 34, 94, 154, 214, 54, 114, 174, 234,
+  18, 78, 138, 198, 38, 98, 158, 218, 58, 118, 178, 238,
+  3, 63, 123, 183, 23, 83, 143, 203, 43, 103, 163, 223,
+  7, 67, 127, 187, 27, 87, 147, 207, 47, 107, 167, 227,
+  11, 71, 131, 191, 31, 91, 151, 211, 51, 111, 171, 231,
+  15, 75, 135, 195, 35, 95, 155, 215, 55, 115, 175, 235,
+  19, 79, 139, 199, 39, 99, 159, 219, 59, 119, 179, 239
+};
+
+/* Cosine table in Q14 */
+static const int16_t kCosTabFfftQ14[240] = {
+  16384,  16378, 16362,   16333,  16294,  16244,  16182,  16110,  16026,  15931,  15826,  15709,
+  15582,  15444, 15296,   15137,  14968,  14788,  14598,  14399,  14189,  13970,  13741,  13502,
+  13255,  12998, 12733,   12458,  12176,  11885,  11585,  11278,  10963,  10641,  10311,   9974,
+  9630,   9280,  8923,    8561,   8192,   7818,   7438,   7053,   6664,   6270,   5872,   5469,
+  5063,   4653,  4240,    3825,   3406,   2986,   2563,   2139,   1713,   1285,    857,    429,
+  0,   -429,  -857,   -1285,  -1713,  -2139,  -2563,  -2986,  -3406,  -3825,  -4240,  -4653,
+  -5063,  -5469, -5872,   -6270,  -6664,  -7053,  -7438,  -7818,  -8192,  -8561,  -8923,  -9280,
+  -9630,  -9974, -10311, -10641, -10963, -11278, -11585, -11885, -12176, -12458, -12733, -12998,
+  -13255, -13502, -13741, -13970, -14189, -14399, -14598, -14788, -14968, -15137, -15296, -15444,
+  -15582, -15709, -15826, -15931, -16026, -16110, -16182, -16244, -16294, -16333, -16362, -16378,
+  -16384, -16378, -16362, -16333, -16294, -16244, -16182, -16110, -16026, -15931, -15826, -15709,
+  -15582, -15444, -15296, -15137, -14968, -14788, -14598, -14399, -14189, -13970, -13741, -13502,
+  -13255, -12998, -12733, -12458, -12176, -11885, -11585, -11278, -10963, -10641, -10311,  -9974,
+  -9630,  -9280,  -8923,  -8561,  -8192,  -7818,  -7438,  -7053,  -6664,  -6270,  -5872,  -5469,
+  -5063,  -4653,  -4240,  -3825,  -3406,  -2986,  -2563,  -2139,  -1713,  -1285,   -857,   -429,
+  0,    429,    857,   1285,   1713,   2139,   2563,   2986,   3406,   3825,   4240,   4653,
+  5063,   5469,   5872,   6270,   6664,   7053,   7438,   7818,   8192,   8561,   8923,   9280,
+  9630,   9974,  10311,  10641,  10963,  11278,  11585,  11885,  12176,  12458,  12733,  12998,
+  13255,  13502,  13741,  13970,  14189,  14399,  14598,  14788,  14968,  15137,  15296,  15444,
+  15582,  15709,  15826,  15931,  16026,  16110,  16182,  16244,  16294,  16333,  16362,  16378
+};
+
+
+
+/* Uses 16x16 mul, without rounding, which is faster. Uses WEBRTC_SPL_MUL_16_16_RSFT */
+int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[], int16_t ImxQx[], int16_t iSign) {
+
+  int16_t dd, ee, ff, gg, hh, ii;
+  int16_t k0, k1, k2, k3, k4, kk;
+  int16_t tmp116, tmp216;
+
+  int16_t ccc1Q14, ccc2Q14, ccc3Q14, sss1Q14, sss2Q14, sss3Q14;
+  int16_t sss60Q14, ccc72Q14, sss72Q14;
+  int16_t aaQx, ajQx, akQx, ajmQx, ajpQx, akmQx, akpQx;
+  int16_t bbQx, bjQx, bkQx, bjmQx, bjpQx, bkmQx, bkpQx;
+
+  int16_t ReDATAQx[240],  ImDATAQx[240];
+
+  sss60Q14 = kCosTabFfftQ14[20];
+  ccc72Q14 = kCosTabFfftQ14[48];
+  sss72Q14 = kCosTabFfftQ14[12];
+
+  if (iSign < 0) {
+    sss72Q14 = -sss72Q14;
+    sss60Q14 = -sss60Q14;
+  }
+  /* Complexity is: 10 cycles */
+
+  /* compute fourier transform */
+
+  // transform for factor of 4
+  for (kk=0; kk<60; kk++) {
+    k0 = kk;
+    k1 = k0 + 60;
+    k2 = k1 + 60;
+    k3 = k2 + 60;
+
+    akpQx = RexQx[k0] + RexQx[k2];
+    akmQx = RexQx[k0] - RexQx[k2];
+    ajpQx = RexQx[k1] + RexQx[k3];
+    ajmQx = RexQx[k1] - RexQx[k3];
+    bkpQx = ImxQx[k0] + ImxQx[k2];
+    bkmQx = ImxQx[k0] - ImxQx[k2];
+    bjpQx = ImxQx[k1] + ImxQx[k3];
+    bjmQx = ImxQx[k1] - ImxQx[k3];
+
+    RexQx[k0] = akpQx + ajpQx;
+    ImxQx[k0] = bkpQx + bjpQx;
+    ajpQx = akpQx - ajpQx;
+    bjpQx = bkpQx - bjpQx;
+    if (iSign < 0) {
+      akpQx = akmQx + bjmQx;
+      bkpQx = bkmQx - ajmQx;
+      akmQx -= bjmQx;
+      bkmQx += ajmQx;
+    } else {
+      akpQx = akmQx - bjmQx;
+      bkpQx = bkmQx + ajmQx;
+      akmQx += bjmQx;
+      bkmQx -= ajmQx;
+    }
+
+    ccc1Q14 = kCosTabFfftQ14[kk];
+    ccc2Q14 = kCosTabFfftQ14[2 * kk];
+    ccc3Q14 = kCosTabFfftQ14[3 * kk];
+    sss1Q14 = kCosTabFfftQ14[kk + 60];
+    sss2Q14 = kCosTabFfftQ14[2 * kk + 60];
+    sss3Q14 = kCosTabFfftQ14[3 * kk + 60];
+    if (iSign==1) {
+      sss1Q14 = -sss1Q14;
+      sss2Q14 = -sss2Q14;
+      sss3Q14 = -sss3Q14;
+    }
+
+    //Do several multiplications like Q14*Q16>>14 = Q16
+    // RexQ16[k1] = akpQ16 * ccc1Q14 - bkpQ16 * sss1Q14;
+    // RexQ16[k2] = ajpQ16 * ccc2Q14 - bjpQ16 * sss2Q14;
+    // RexQ16[k3] = akmQ16 * ccc3Q14 - bkmQ16 * sss3Q14;
+    // ImxQ16[k1] = akpQ16 * sss1Q14 + bkpQ16 * ccc1Q14;
+    // ImxQ16[k2] = ajpQ16 * sss2Q14 + bjpQ16 * ccc2Q14;
+    // ImxQ16[k3] = akmQ16 * sss3Q14 + bkmQ16 * ccc3Q14;
+
+    RexQx[k1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, akpQx, 14) -
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, bkpQx, 14); // 6 non-mul + 2 mul cycles, i.e. 8 cycles (6+2*7=20 cycles if 16x32mul)
+    RexQx[k2] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) -
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjpQx, 14);
+    RexQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, akmQx, 14) -
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, bkmQx, 14);
+    ImxQx[k1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, akpQx, 14) +
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, bkpQx, 14);
+    ImxQx[k2] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajpQx, 14) +
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14);
+    ImxQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, akmQx, 14) +
+        (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, bkmQx, 14);
+    //This mul segment needs 6*8 = 48 cycles for 16x16 muls, but 6*20 = 120 cycles for 16x32 muls
+
+
+  }
+  /* Complexity is: 51+48 = 99 cycles for 16x16 muls, but 51+120 = 171 cycles for 16x32 muls*/
+
+  // transform for factor of 3
+  kk=0;
+  k1=20;
+  k2=40;
+
+  for (hh=0; hh<4; hh++) {
+    for (ii=0; ii<20; ii++) {
+      akQx = RexQx[kk];
+      bkQx = ImxQx[kk];
+      ajQx = RexQx[k1] + RexQx[k2];
+      bjQx = ImxQx[k1] + ImxQx[k2];
+      RexQx[kk] = akQx + ajQx;
+      ImxQx[kk] = bkQx + bjQx;
+      tmp116 = ajQx >> 1;
+      tmp216 = bjQx >> 1;
+      akQx = akQx - tmp116;
+      bkQx = bkQx - tmp216;
+      tmp116 = RexQx[k1] - RexQx[k2];
+      tmp216 = ImxQx[k1] - ImxQx[k2];
+
+      ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp116, 14); // Q14*Qx>>14 = Qx
+      bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp216, 14); // Q14*Qx>>14 = Qx
+      RexQx[k1] = akQx - bjQx;
+      RexQx[k2] = akQx + bjQx;
+      ImxQx[k1] = bkQx + ajQx;
+      ImxQx[k2] = bkQx - ajQx;
+
+      kk++;
+      k1++;
+      k2++;
+    }
+    /* Complexity : (31+6)*20 = 740 cycles for 16x16 muls, but (31+18)*20 = 980 cycles for 16x32 muls*/
+    kk=kk+40;
+    k1=k1+40;
+    k2=k2+40;
+  }
+  /* Complexity : 4*(740+3) = 2972 cycles for 16x16 muls, but 4*(980+3) = 3932 cycles for 16x32 muls*/
+
+  /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+     Same code (duplicated) for both ii=2 and ii=3 */
+  kk = 1;
+  ee = 0;
+  ff = 0;
+
+  for (gg=0; gg<19; gg++) {
+    kk += 20;
+    ff = ff+4;
+    for (hh=0; hh<2; hh++) {
+      ee = ff + hh * ff;
+      dd = ee + 60;
+      ccc2Q14 = kCosTabFfftQ14[ee];
+      sss2Q14 = kCosTabFfftQ14[dd];
+      if (iSign==1) {
+        sss2Q14 = -sss2Q14;
+      }
+      for (ii=0; ii<4; ii++) {
+        akQx = RexQx[kk];
+        bkQx = ImxQx[kk];
+        RexQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) - // Q14*Qx>>14 = Qx
+            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+        ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) + // Q14*Qx>>14 = Qx
+            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+
+        kk += 60;
+      }
+      kk = kk - 220;
+    }
+    // Complexity: 2*(13+5+4*13+2) = 144 for 16x16 muls, but 2*(13+5+4*33+2) = 304 cycles for 16x32 muls
+    kk = kk - 59;
+  }
+  // Complexity: 19*144 = 2736 for 16x16 muls, but 19*304 = 5776 cycles for 16x32 muls
+
+  // transform for factor of 5
+  kk = 0;
+  ccc2Q14 = kCosTabFfftQ14[96];
+  sss2Q14 = kCosTabFfftQ14[84];
+  if (iSign==1) {
+    sss2Q14 = -sss2Q14;
+  }
+
+  for (hh=0; hh<4; hh++) {
+    for (ii=0; ii<12; ii++) {
+      k1 = kk + 4;
+      k2 = k1 + 4;
+      k3 = k2 + 4;
+      k4 = k3 + 4;
+
+      akpQx = RexQx[k1] + RexQx[k4];
+      akmQx = RexQx[k1] - RexQx[k4];
+      bkpQx = ImxQx[k1] + ImxQx[k4];
+      bkmQx = ImxQx[k1] - ImxQx[k4];
+      ajpQx = RexQx[k2] + RexQx[k3];
+      ajmQx = RexQx[k2] - RexQx[k3];
+      bjpQx = ImxQx[k2] + ImxQx[k3];
+      bjmQx = ImxQx[k2] - ImxQx[k3];
+      aaQx = RexQx[kk];
+      bbQx = ImxQx[kk];
+      RexQx[kk] = aaQx + akpQx + ajpQx;
+      ImxQx[kk] = bbQx + bkpQx + bjpQx;
+
+      akQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, akpQx, 14) +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14)  + aaQx;
+      bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bkpQx, 14) +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14)  + bbQx;
+      ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, akmQx, 14) +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajmQx, 14);
+      bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bkmQx, 14) +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjmQx, 14);
+      // 32+4*8=64 or 32+4*20=112
+
+      RexQx[k1] = akQx - bjQx;
+      RexQx[k4] = akQx + bjQx;
+      ImxQx[k1] = bkQx + ajQx;
+      ImxQx[k4] = bkQx - ajQx;
+
+      akQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akpQx, 14)  +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, ajpQx, 14) + aaQx;
+      bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkpQx, 14)  +
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bjpQx, 14) + bbQx;
+      ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akmQx, 14) -
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, ajmQx, 14);
+      bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkmQx, 14) -
+          (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bjmQx, 14);
+      // 8+4*8=40 or 8+4*20=88
+
+      RexQx[k2] = akQx - bjQx;
+      RexQx[k3] = akQx + bjQx;
+      ImxQx[k2] = bkQx + ajQx;
+      ImxQx[k3] = bkQx - ajQx;
+
+      kk = k4 + 4;
+    }
+    // Complexity: 12*(64+40+10) = 1368 for 16x16 muls, but 12*(112+88+10) = 2520 cycles for 16x32 muls
+    kk -= 239;
+  }
+  // Complexity: 4*1368 = 5472 for 16x16 muls, but 4*2520 = 10080 cycles for 16x32 muls
+
+  /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+     Same code (duplicated) for both ii=2 and ii=3 */
+  kk = 1;
+  ee=0;
+
+  for (gg=0; gg<3; gg++) {
+    kk += 4;
+    dd = 12 + 12 * gg;
+    ff = 0;
+    for (hh=0; hh<4; hh++) {
+      ff = ff+dd;
+      ee = ff+60;
+      for (ii=0; ii<12; ii++) {
+        akQx = RexQx[kk];
+        bkQx = ImxQx[kk];
+
+        ccc2Q14 = kCosTabFfftQ14[ff];
+        sss2Q14 = kCosTabFfftQ14[ee];
+
+        if (iSign==1) {
+          sss2Q14 = -sss2Q14;
+        }
+
+        RexQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) -
+            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+        ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) +
+            (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+        kk += 20;
+      }
+      kk = kk - 236;
+      // Complexity: 12*(12+12) = 288 for 16x16 muls, but 12*(12+32) = 528 cycles for 16x32 muls
+    }
+    kk = kk - 19;
+    // Complexity: 4*288+6 for 16x16 muls, but 4*528+6 cycles for 16x32 muls
+  }
+  // Complexity: 3*4*288+6 = 3462 for 16x16 muls, but 3*4*528+6 = 6342 cycles for 16x32 muls
+
+
+  // last transform for factor of 4 */
+  for (kk=0; kk<240; kk=kk+4) {
+    k1 = kk + 1;
+    k2 = k1 + 1;
+    k3 = k2 + 1;
+
+    akpQx = RexQx[kk] + RexQx[k2];
+    akmQx = RexQx[kk] - RexQx[k2];
+    ajpQx = RexQx[k1] + RexQx[k3];
+    ajmQx = RexQx[k1] - RexQx[k3];
+    bkpQx = ImxQx[kk] + ImxQx[k2];
+    bkmQx = ImxQx[kk] - ImxQx[k2];
+    bjpQx = ImxQx[k1] + ImxQx[k3];
+    bjmQx = ImxQx[k1] - ImxQx[k3];
+    RexQx[kk] = akpQx + ajpQx;
+    ImxQx[kk] = bkpQx + bjpQx;
+    ajpQx = akpQx - ajpQx;
+    bjpQx = bkpQx - bjpQx;
+    if (iSign < 0) {
+      akpQx = akmQx + bjmQx;
+      bkpQx = bkmQx - ajmQx;
+      akmQx -= bjmQx;
+      bkmQx += ajmQx;
+    } else {
+      akpQx = akmQx - bjmQx;
+      bkpQx = bkmQx + ajmQx;
+      akmQx += bjmQx;
+      bkmQx -= ajmQx;
+    }
+    RexQx[k1] = akpQx;
+    RexQx[k2] = ajpQx;
+    RexQx[k3] = akmQx;
+    ImxQx[k1] = bkpQx;
+    ImxQx[k2] = bjpQx;
+    ImxQx[k3] = bkmQx;
+  }
+  // Complexity: 60*45 = 2700 for 16x16 muls, but 60*45 = 2700 cycles for 16x32 muls
+
+  /* permute the results to normal order */
+  for (ii=0; ii<240; ii++) {
+    ReDATAQx[ii]=RexQx[ii];
+    ImDATAQx[ii]=ImxQx[ii];
+  }
+  // Complexity: 240*2=480 cycles
+
+  for (ii=0; ii<240; ii++) {
+    RexQx[ii]=ReDATAQx[kSortTabFft[ii]];
+    ImxQx[ii]=ImDATAQx[kSortTabFft[ii]];
+  }
+  // Complexity: 240*2*2=960 cycles
+
+  // Total complexity:
+  //            16x16 16x32
+  // Complexity:   10    10
+  // Complexity:   99   171
+  // Complexity: 2972  3932
+  // Complexity: 2736  5776
+  // Complexity: 5472 10080
+  // Complexity: 3462  6342
+  // Complexity: 2700  2700
+  // Complexity:  480   480
+  // Complexity:  960   960
+  // =======================
+  //            18891 30451
+  //
+  // If this FFT is called 2 time each frame, i.e. 67 times per second, it will correspond to
+  // a C54 complexity of 67*18891/1000000 = 1.27 MIPS with 16x16-muls, and 67*30451/1000000 =
+  // = 2.04 MIPS with 16x32-muls. Note that this routine somtimes is called 6 times during the
+  // encoding of a frame, i.e. the max complexity would be 7/2*1.27 = 4.4 MIPS for the 16x16 mul case.
+
+
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/fft.h b/modules/audio_coding/codecs/isac/fix/source/fft.h
new file mode 100644
index 0000000..4fe9b96
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/fft.h
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*--------------------------------*-C-*---------------------------------*
+ * File:
+ * fft.h
+ * ---------------------------------------------------------------------*
+ * Re[]: real value array
+ * Im[]: imaginary value array
+ * nTotal: total number of complex values
+ * nPass: number of elements involved in this pass of transform
+ * nSpan: nspan/nPass = number of bytes to increment pointer
+ *  in Re[] and Im[]
+ * isign: exponent: +1 = forward  -1 = reverse
+ * scaling: normalizing constant by which the final result is *divided*
+ * scaling == -1, normalize by total dimension of the transform
+ * scaling <  -1, normalize by the square-root of the total dimension
+ *
+ * ----------------------------------------------------------------------
+ * See the comments in the code for correct usage!
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[],
+                                        int16_t ImxQx[],
+                                        int16_t iSign);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h b/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
new file mode 100644
index 0000000..f741e6f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+
+#include <stdint.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Arguments:
+ *   io:  Input/output, in Q0.
+ *   len: Input, sample length.
+ *   coefficient: Input.
+ *   state: Input/output, filter state, in Q4.
+ */
+typedef void (*HighpassFilterFixDec32)(int16_t* io,
+                                       int16_t len,
+                                       const int16_t* coefficient,
+                                       int32_t* state);
+extern HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+
+void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t* io,
+                                           int16_t len,
+                                           const int16_t* coefficient,
+                                           int32_t* state);
+
+#if defined(MIPS_DSP_R1_LE)
+void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
+                                              int16_t len,
+                                              const int16_t* coefficient,
+                                              int32_t* state);
+#endif
+
+typedef void (*AllpassFilter2FixDec16)(
+    int16_t* data_ch1,           // Input and output in channel 1, in Q0
+    int16_t* data_ch2,           // Input and output in channel 2, in Q0
+    const int16_t* factor_ch1,   // Scaling factor for channel 1, in Q15
+    const int16_t* factor_ch2,   // Scaling factor for channel 2, in Q15
+    int length,                  // Length of the data buffers
+    int32_t* filter_state_ch1,   // Filter state for channel 1, in Q16
+    int32_t* filter_state_ch2);  // Filter state for channel 2, in Q16
+extern AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
+
+void WebRtcIsacfix_AllpassFilter2FixDec16C(int16_t* data_ch1,
+                                           int16_t* data_ch2,
+                                           const int16_t* factor_ch1,
+                                           const int16_t* factor_ch2,
+                                           int length,
+                                           int32_t* filter_state_ch1,
+                                           int32_t* filter_state_ch2);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_AllpassFilter2FixDec16Neon(int16_t* data_ch1,
+                                              int16_t* data_ch2,
+                                              const int16_t* factor_ch1,
+                                              const int16_t* factor_ch2,
+                                              int length,
+                                              int32_t* filter_state_ch1,
+                                              int32_t* filter_state_ch2);
+#endif
+
+#if defined(MIPS_DSP_R1_LE)
+void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(int16_t* data_ch1,
+                                              int16_t* data_ch2,
+                                              const int16_t* factor_ch1,
+                                              const int16_t* factor_ch2,
+                                              int length,
+                                              int32_t* filter_state_ch1,
+                                              int32_t* filter_state_ch2);
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif
+/* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
new file mode 100644
index 0000000..f2dec79
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.c
+ *
+ * This file contains variables that are used in
+ * filterbanks.c
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.94895953203325f, 0.94984516000000f,
+ * -0.05101826139794f, 0.05015484000000f};
+ */
+const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8] = {
+  16189, -31932,  /* Q30 lo/hi pair */
+  17243, 15562,  /* Q30 lo/hi pair */
+  -17186, -26748,  /* Q35 lo/hi pair */
+  -27476, 26296  /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.99701049409000f, 0.99714204490000f,
+ * 0.01701049409000f, -0.01704204490000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8] = {
+  -1306, -32719,  /* Q30 lo/hi pair */
+  11486, 16337,  /* Q30 lo/hi pair */
+  26078, 8918,  /* Q35 lo/hi pair */
+  3956, -8935  /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.98645294509837f, 0.98672435560000f,
+ * 0.00645294509837f, -0.00662435560000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8] = {
+  -2953, -32546,  /* Q30 lo/hi pair */
+  32233, 16166,  /* Q30 lo/hi pair */
+  13217, 3383,  /* Q35 lo/hi pair */
+  -4597, -3473  /* Q35 lo/hi pair */
+};
+
+/* The upper channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2] = {
+  1137, 12537
+};
+
+/* The lower channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2] = {
+  5059, 24379
+};
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
new file mode 100644
index 0000000..01e5a7b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.h
+ *
+ * Header file for variables that are defined in
+ * filterbank_tables.c.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+
+#include <stdint.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/********************* Coefficient Tables ************************/
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8];
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8];
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8];
+
+/* The upper channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2];
+
+/* The lower channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2];
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbanks.c b/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
new file mode 100644
index 0000000..57b3e70
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
@@ -0,0 +1,297 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function 
+ * WebRtcIsacfix_SplitAndFilter, and WebRtcIsacfix_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/checks.h"
+
+// Declare a function pointer.
+AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
+
+void WebRtcIsacfix_AllpassFilter2FixDec16C(
+    int16_t *data_ch1,  // Input and output in channel 1, in Q0
+    int16_t *data_ch2,  // Input and output in channel 2, in Q0
+    const int16_t *factor_ch1,  // Scaling factor for channel 1, in Q15
+    const int16_t *factor_ch2,  // Scaling factor for channel 2, in Q15
+    const int length,  // Length of the data buffers
+    int32_t *filter_state_ch1,  // Filter state for channel 1, in Q16
+    int32_t *filter_state_ch2) {  // Filter state for channel 2, in Q16
+  int n = 0;
+  int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
+  int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
+  int16_t in_out = 0;
+  int32_t a = 0, b = 0;
+
+  // Assembly file assumption.
+  RTC_DCHECK_EQ(0, length % 2);
+
+  for (n = 0; n < length; n++) {
+    // Process channel 1:
+    in_out = data_ch1[n];
+    a = factor_ch1[0] * in_out;  // Q15 * Q0 = Q15
+    a *= 1 << 1;  // Q15 -> Q16
+    b = WebRtcSpl_AddSatW32(a, state0_ch1);
+    a = -factor_ch1[0] * (int16_t)(b >> 16);  // Q15
+    state0_ch1 =
+        WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16));  // Q16
+    in_out = (int16_t) (b >> 16);  // Save as Q0
+
+    a = factor_ch1[1] * in_out;  // Q15 * Q0 = Q15
+    a *= 1 << 1; // Q15 -> Q16
+    b = WebRtcSpl_AddSatW32(a, state1_ch1);  // Q16
+    a = -factor_ch1[1] * (int16_t)(b >> 16);  // Q15
+    state1_ch1 =
+        WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16));  // Q16
+    data_ch1[n] = (int16_t) (b >> 16);  // Save as Q0
+
+    // Process channel 2:
+    in_out = data_ch2[n];
+    a = factor_ch2[0] * in_out;  // Q15 * Q0 = Q15
+    a *= 1 << 1;  // Q15 -> Q16
+    b = WebRtcSpl_AddSatW32(a, state0_ch2);  // Q16
+    a = -factor_ch2[0] * (int16_t)(b >> 16);  // Q15
+    state0_ch2 =
+        WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16));  // Q16
+    in_out = (int16_t) (b >> 16);  // Save as Q0
+
+    a = factor_ch2[1] * in_out;  // Q15 * Q0 = Q15
+    a *= (1 << 1);  // Q15 -> Q16
+    b = WebRtcSpl_AddSatW32(a, state1_ch2);  // Q16
+    a = -factor_ch2[1] * (int16_t)(b >> 16);  // Q15
+    state1_ch2 =
+        WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16));  // Q16
+    data_ch2[n] = (int16_t) (b >> 16);  // Save as Q0
+  }
+
+  filter_state_ch1[0] = state0_ch1;
+  filter_state_ch1[1] = state1_ch1;
+  filter_state_ch2[0] = state0_ch2;
+  filter_state_ch2[1] = state1_ch2;
+}
+
+// Declare a function pointer.
+HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+
+void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t *io,
+                                           int16_t len,
+                                           const int16_t *coefficient,
+                                           int32_t *state)
+{
+  int k;
+  int32_t a1 = 0, b1 = 0, c = 0, in = 0;
+  int32_t a2 = 0, b2 = 0;
+  int32_t state0 = state[0];
+  int32_t state1 = state[1];
+
+  for (k=0; k<len; k++) {
+    in = (int32_t)io[k];
+
+#ifdef WEBRTC_ARCH_ARM_V7
+    {
+      register int tmp_coeff0;
+      register int tmp_coeff1;
+      __asm __volatile(
+        "ldr %[tmp_coeff0], [%[coeff]]\n\t"
+        "ldr %[tmp_coeff1], [%[coeff], #4]\n\t"
+        "smmulr %[a2], %[tmp_coeff0], %[state0]\n\t"
+        "smmulr %[b2], %[tmp_coeff1], %[state1]\n\t"
+        "ldr %[tmp_coeff0], [%[coeff], #8]\n\t"
+        "ldr %[tmp_coeff1], [%[coeff], #12]\n\t"
+        "smmulr %[a1], %[tmp_coeff0], %[state0]\n\t"
+        "smmulr %[b1], %[tmp_coeff1], %[state1]\n\t"
+        :[a2]"=&r"(a2),
+         [b2]"=&r"(b2),
+         [a1]"=&r"(a1),
+         [b1]"=r"(b1),
+         [tmp_coeff0]"=&r"(tmp_coeff0),
+         [tmp_coeff1]"=&r"(tmp_coeff1)
+        :[coeff]"r"(coefficient),
+         [state0]"r"(state0),
+         [state1]"r"(state1)
+      );
+    }
+#else
+    /* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */
+    a1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[5], state0) +
+        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[4], state0) >> 16);
+    b1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[7], state1) +
+        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[6], state1) >> 16);
+
+    /* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
+    a2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[1], state0) +
+        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[0], state0) >> 16);
+    b2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[3], state1) +
+        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[2], state1) >> 16);
+#endif
+
+    c = in + ((a1 + b1) >> 7);  // Q0.
+    io[k] = (int16_t)WebRtcSpl_SatW32ToW16(c);  // Write output as Q0.
+
+    c = in * (1 << 2) - a2 - b2;  // In Q2.
+    c = (int32_t)WEBRTC_SPL_SAT(536870911, c, -536870912);
+
+    state1 = state0;
+    state0 = c * (1 << 2);  // Write state as Q4
+  }
+  state[0] = state0;
+  state[1] = state1;
+}
+
+
+void WebRtcIsacfix_SplitAndFilter1(int16_t *pin,
+                                   int16_t *LP16,
+                                   int16_t *HP16,
+                                   PreFiltBankstr *prefiltdata)
+{
+  /* Function WebRtcIsacfix_SplitAndFilter */
+  /* This function creates low-pass and high-pass decimated versions of part of
+     the input signal, and part of the signal in the input 'lookahead buffer'. */
+
+  int k;
+
+  int16_t tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD];
+  int16_t tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD];
+  int32_t tmpState_ch1[2 * (QORDER-1)]; /* 4 */
+  int32_t tmpState_ch2[2 * (QORDER-1)]; /* 4 */
+
+  /* High pass filter */
+  WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
+
+
+  /* First Channel */
+  for (k=0;k<FRAMESAMPLES/2;k++) {
+    tempin_ch1[QLOOKAHEAD + k] = pin[1 + 2 * k];
+  }
+  for (k=0;k<QLOOKAHEAD;k++) {
+    tempin_ch1[k]=prefiltdata->INLABUF1_fix[k];
+    prefiltdata->INLABUF1_fix[k] = pin[FRAMESAMPLES + 1 - 2 * (QLOOKAHEAD - k)];
+  }
+
+  /* Second Channel.  This is exactly like the first channel, except that the
+     even samples are now filtered instead (lower channel). */
+  for (k=0;k<FRAMESAMPLES/2;k++) {
+    tempin_ch2[QLOOKAHEAD + k] = pin[2 * k];
+  }
+  for (k=0;k<QLOOKAHEAD;k++) {
+    tempin_ch2[k]=prefiltdata->INLABUF2_fix[k];
+    prefiltdata->INLABUF2_fix[k] = pin[FRAMESAMPLES - 2 * (QLOOKAHEAD - k)];
+  }
+
+
+  /*obtain polyphase components by forward all-pass filtering through each channel */
+  /* The all pass filtering automatically updates the filter states which are exported in the
+     prefiltdata structure */
+  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
+                                       tempin_ch2,
+                                       WebRtcIsacfix_kUpperApFactorsQ15,
+                                       WebRtcIsacfix_kLowerApFactorsQ15,
+                                       FRAMESAMPLES/2,
+                                       prefiltdata->INSTAT1_fix,
+                                       prefiltdata->INSTAT2_fix);
+
+  for (k = 0; k < 2 * (QORDER - 1); k++) {
+    tmpState_ch1[k] = prefiltdata->INSTAT1_fix[k];
+    tmpState_ch2[k] = prefiltdata->INSTAT2_fix[k];
+  }
+  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2,
+                                       tempin_ch2 + FRAMESAMPLES/2,
+                                       WebRtcIsacfix_kUpperApFactorsQ15,
+                                       WebRtcIsacfix_kLowerApFactorsQ15,
+                                       QLOOKAHEAD,
+                                       tmpState_ch1,
+                                       tmpState_ch2);
+
+  /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+  for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) {
+    int32_t tmp1, tmp2, tmp3;
+    tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
+    tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
+    tmp3 = (tmp1 + tmp2) >> 1;  /* Low pass signal. */
+    LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
+    tmp3 = (tmp1 - tmp2) >> 1;  /* High pass signal. */
+    HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
+  }
+
+}/*end of WebRtcIsacfix_SplitAndFilter */
+
+
+
+//////////////////////////////////////////////////////////
+////////// Combining
+/* Function WebRtcIsacfix_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+   length FRAMESAMPLES/2 input low-pass and
+   high-pass signals and creates a reconstructed fullband
+   output signal of length FRAMESAMPLES. WebRtcIsacfix_FilterAndCombine
+   is the sibling function of WebRtcIsacfix_SplitAndFilter */
+/* INPUTS:
+   inLP: a length FRAMESAMPLES/2 array of input low-pass
+   samples.
+   inHP: a length FRAMESAMPLES/2 array of input high-pass
+   samples.
+   postfiltdata: input data structure containing the filterbank
+   states from the previous decoding iteration.
+   OUTPUTS:
+   Out: a length FRAMESAMPLES array of output reconstructed
+   samples (fullband) based on the input low-pass and
+   high-pass signals.
+   postfiltdata: the input data structure containing the filterbank
+   states is updated for the next decoding iteration */
+void WebRtcIsacfix_FilterAndCombine1(int16_t *tempin_ch1,
+                                     int16_t *tempin_ch2,
+                                     int16_t *out16,
+                                     PostFiltBankstr *postfiltdata)
+{
+  int k;
+  int16_t in[FRAMESAMPLES];
+
+  /* all-pass filter the new upper and lower channel signal.
+     For upper channel, use the all-pass filter factors that were used as a
+     lower channel at the encoding side. So at the decoder, the corresponding
+     all-pass filter factors for each channel are swapped.
+     For lower channel signal, since all-pass filter factors at the decoder are
+     swapped from the ones at the encoder, the 'upper' channel all-pass filter
+     factors (kUpperApFactors) are used to filter this new lower channel signal.
+  */
+  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
+                                       tempin_ch2,
+                                       WebRtcIsacfix_kLowerApFactorsQ15,
+                                       WebRtcIsacfix_kUpperApFactorsQ15,
+                                       FRAMESAMPLES/2,
+                                       postfiltdata->STATE_0_UPPER_fix,
+                                       postfiltdata->STATE_0_LOWER_fix);
+
+  /* Merge outputs to form the full length output signal.*/
+  for (k=0;k<FRAMESAMPLES/2;k++) {
+    in[2 * k] = tempin_ch2[k];
+    in[2 * k + 1] = tempin_ch1[k];
+  }
+
+  /* High pass filter */
+  WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
+  WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
+
+  for (k=0;k<FRAMESAMPLES;k++) {
+    out16[k] = in[k];
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c b/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c
new file mode 100644
index 0000000..949bca7
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c
@@ -0,0 +1,242 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+
+// WebRtcIsacfix_AllpassFilter2FixDec16 function optimized for MIPSDSP platform.
+// Bit-exact with WebRtcIsacfix_AllpassFilter2FixDec16C from filterbanks.c.
+void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(
+    int16_t* data_ch1,            // Input and output in channel 1, in Q0.
+    int16_t* data_ch2,            // Input and output in channel 2, in Q0.
+    const int16_t* factor_ch1,    // Scaling factor for channel 1, in Q15.
+    const int16_t* factor_ch2,    // Scaling factor for channel 2, in Q15.
+    const int length,             // Length of the data buffers.
+    int32_t* filter_state_ch1,    // Filter state for channel 1, in Q16.
+    int32_t* filter_state_ch2) {  // Filter state for channel 2, in Q16.
+
+  int32_t st0_ch1, st1_ch1;                // channel1 state variables.
+  int32_t st0_ch2, st1_ch2;                // channel2 state variables.
+  int32_t f_ch10, f_ch11, f_ch20, f_ch21;  // factor variables.
+  int32_t r0, r1, r2, r3, r4, r5;          // temporary register variables.
+
+  __asm __volatile (
+    ".set           push                                                  \n\t"
+    ".set           noreorder                                             \n\t"
+    // Load all the state and factor variables.
+    "lh             %[f_ch10],      0(%[factor_ch1])                      \n\t"
+    "lh             %[f_ch20],      0(%[factor_ch2])                      \n\t"
+    "lh             %[f_ch11],      2(%[factor_ch1])                      \n\t"
+    "lh             %[f_ch21],      2(%[factor_ch2])                      \n\t"
+    "lw             %[st0_ch1],     0(%[filter_state_ch1])                \n\t"
+    "lw             %[st1_ch1],     4(%[filter_state_ch1])                \n\t"
+    "lw             %[st0_ch2],     0(%[filter_state_ch2])                \n\t"
+    "lw             %[st1_ch2],     4(%[filter_state_ch2])                \n\t"
+    // Allpass filtering loop.
+   "1:                                                                    \n\t"
+    "lh             %[r0],          0(%[data_ch1])                        \n\t"
+    "lh             %[r1],          0(%[data_ch2])                        \n\t"
+    "addiu          %[length],      %[length],              -1            \n\t"
+    "mul            %[r2],          %[r0],                  %[f_ch10]     \n\t"
+    "mul            %[r3],          %[r1],                  %[f_ch20]     \n\t"
+    "sll            %[r0],          %[r0],                  16            \n\t"
+    "sll            %[r1],          %[r1],                  16            \n\t"
+    "sll            %[r2],          %[r2],                  1             \n\t"
+    "addq_s.w       %[r2],          %[r2],                  %[st0_ch1]    \n\t"
+    "sll            %[r3],          %[r3],                  1             \n\t"
+    "addq_s.w       %[r3],          %[r3],                  %[st0_ch2]    \n\t"
+    "sra            %[r2],          %[r2],                  16            \n\t"
+    "mul            %[st0_ch1],     %[f_ch10],              %[r2]         \n\t"
+    "sra            %[r3],          %[r3],                  16            \n\t"
+    "mul            %[st0_ch2],     %[f_ch20],              %[r3]         \n\t"
+    "mul            %[r4],          %[r2],                  %[f_ch11]     \n\t"
+    "mul            %[r5],          %[r3],                  %[f_ch21]     \n\t"
+    "sll            %[st0_ch1],     %[st0_ch1],             1             \n\t"
+    "subq_s.w       %[st0_ch1],     %[r0],                  %[st0_ch1]    \n\t"
+    "sll            %[st0_ch2],     %[st0_ch2],             1             \n\t"
+    "subq_s.w       %[st0_ch2],     %[r1],                  %[st0_ch2]    \n\t"
+    "sll            %[r4],          %[r4],                  1             \n\t"
+    "addq_s.w       %[r4],          %[r4],                  %[st1_ch1]    \n\t"
+    "sll            %[r5],          %[r5],                  1             \n\t"
+    "addq_s.w       %[r5],          %[r5],                  %[st1_ch2]    \n\t"
+    "sra            %[r4],          %[r4],                  16            \n\t"
+    "mul            %[r0],          %[r4],                  %[f_ch11]     \n\t"
+    "sra            %[r5],          %[r5],                  16            \n\t"
+    "mul            %[r1],          %[r5],                  %[f_ch21]     \n\t"
+    "sh             %[r4],          0(%[data_ch1])                        \n\t"
+    "sh             %[r5],          0(%[data_ch2])                        \n\t"
+    "addiu          %[data_ch1],    %[data_ch1],            2             \n\t"
+    "sll            %[r2],          %[r2],                  16            \n\t"
+    "sll            %[r0],          %[r0],                  1             \n\t"
+    "subq_s.w       %[st1_ch1],     %[r2],                  %[r0]         \n\t"
+    "sll            %[r3],          %[r3],                  16            \n\t"
+    "sll            %[r1],          %[r1],                  1             \n\t"
+    "subq_s.w       %[st1_ch2],     %[r3],                  %[r1]         \n\t"
+    "bgtz           %[length],      1b                                    \n\t"
+    " addiu         %[data_ch2],    %[data_ch2],            2             \n\t"
+    // Store channel states.
+    "sw             %[st0_ch1],     0(%[filter_state_ch1])                \n\t"
+    "sw             %[st1_ch1],     4(%[filter_state_ch1])                \n\t"
+    "sw             %[st0_ch2],     0(%[filter_state_ch2])                \n\t"
+    "sw             %[st1_ch2],     4(%[filter_state_ch2])                \n\t"
+    ".set           pop                                                   \n\t"
+    : [f_ch10] "=&r" (f_ch10), [f_ch20] "=&r" (f_ch20),
+      [f_ch11] "=&r" (f_ch11), [f_ch21] "=&r" (f_ch21),
+      [st0_ch1] "=&r" (st0_ch1), [st1_ch1] "=&r" (st1_ch1),
+      [st0_ch2] "=&r" (st0_ch2), [st1_ch2] "=&r" (st1_ch2),
+      [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+      [r3] "=&r" (r3), [r4] "=&r" (r4), [r5] "=&r" (r5)
+    : [factor_ch1] "r" (factor_ch1), [factor_ch2] "r" (factor_ch2),
+      [filter_state_ch1] "r" (filter_state_ch1),
+      [filter_state_ch2] "r" (filter_state_ch2),
+      [data_ch1] "r" (data_ch1), [data_ch2] "r" (data_ch2),
+      [length] "r" (length)
+    : "memory", "hi", "lo"
+  );
+}
+
+// WebRtcIsacfix_HighpassFilterFixDec32 function optimized for MIPSDSP platform.
+// Bit-exact with WebRtcIsacfix_HighpassFilterFixDec32C from filterbanks.c.
+void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
+                                              int16_t len,
+                                              const int16_t* coefficient,
+                                              int32_t* state) {
+  int k;
+  int32_t a1, a2, b1, b2, in;
+  int32_t state0 = state[0];
+  int32_t state1 = state[1];
+
+  int32_t c0, c1, c2, c3;
+  int32_t c4, c5, c6, c7;
+  int32_t state0_lo, state0_hi;
+  int32_t state1_lo, state1_hi;
+  int32_t t0, t1, t2, t3, t4, t5;
+
+  __asm  __volatile (
+    "lh         %[c0],         0(%[coeff_ptr])            \n\t"
+    "lh         %[c1],         2(%[coeff_ptr])            \n\t"
+    "lh         %[c2],         4(%[coeff_ptr])            \n\t"
+    "lh         %[c3],         6(%[coeff_ptr])            \n\t"
+    "sra        %[state0_hi],  %[state0],        16       \n\t"
+    "sra        %[state1_hi],  %[state1],        16       \n\t"
+    "andi       %[state0_lo],  %[state0],        0xFFFF   \n\t"
+    "andi       %[state1_lo],  %[state1],        0xFFFF   \n\t"
+    "lh         %[c4],         8(%[coeff_ptr])            \n\t"
+    "lh         %[c5],         10(%[coeff_ptr])           \n\t"
+    "lh         %[c6],         12(%[coeff_ptr])           \n\t"
+    "lh         %[c7],         14(%[coeff_ptr])           \n\t"
+    "sra        %[state0_lo],  %[state0_lo],     1        \n\t"
+    "sra        %[state1_lo],  %[state1_lo],     1        \n\t"
+    : [c0] "=&r" (c0), [c1] "=&r" (c1), [c2] "=&r" (c2), [c3] "=&r" (c3),
+      [c4] "=&r" (c4), [c5] "=&r" (c5), [c6] "=&r" (c6), [c7] "=&r" (c7),
+      [state0_hi] "=&r" (state0_hi), [state0_lo] "=&r" (state0_lo),
+      [state1_hi] "=&r" (state1_hi), [state1_lo] "=&r" (state1_lo)
+    : [coeff_ptr] "r" (coefficient), [state0] "r" (state0),
+      [state1] "r" (state1)
+    : "memory"
+  );
+
+  for (k = 0; k < len; k++) {
+    in = (int32_t)io[k];
+
+    __asm __volatile (
+      ".set      push                                      \n\t"
+      ".set      noreorder                                 \n\t"
+      "mul       %[t2],        %[c4],        %[state0_lo]  \n\t"
+      "mul       %[t0],        %[c5],        %[state0_lo]  \n\t"
+      "mul       %[t1],        %[c4],        %[state0_hi]  \n\t"
+      "mul       %[a1],        %[c5],        %[state0_hi]  \n\t"
+      "mul       %[t5],        %[c6],        %[state1_lo]  \n\t"
+      "mul       %[t3],        %[c7],        %[state1_lo]  \n\t"
+      "mul       %[t4],        %[c6],        %[state1_hi]  \n\t"
+      "mul       %[b1],        %[c7],        %[state1_hi]  \n\t"
+      "shra_r.w  %[t2],        %[t2],        15            \n\t"
+      "shra_r.w  %[t0],        %[t0],        15            \n\t"
+      "addu      %[t1],        %[t1],        %[t2]         \n\t"
+      "addu      %[a1],        %[a1],        %[t0]         \n\t"
+      "sra       %[t1],        %[t1],        16            \n\t"
+      "addu      %[a1],        %[a1],        %[t1]         \n\t"
+      "shra_r.w  %[t5],        %[t5],        15            \n\t"
+      "shra_r.w  %[t3],        %[t3],        15            \n\t"
+      "addu      %[t4],        %[t4],        %[t5]         \n\t"
+      "addu      %[b1],        %[b1],        %[t3]         \n\t"
+      "sra       %[t4],        %[t4],        16            \n\t"
+      "addu      %[b1],        %[b1],        %[t4]         \n\t"
+      "mul       %[t2],        %[c0],        %[state0_lo]  \n\t"
+      "mul       %[t0],        %[c1],        %[state0_lo]  \n\t"
+      "mul       %[t1],        %[c0],        %[state0_hi]  \n\t"
+      "mul       %[a2],        %[c1],        %[state0_hi]  \n\t"
+      "mul       %[t5],        %[c2],        %[state1_lo]  \n\t"
+      "mul       %[t3],        %[c3],        %[state1_lo]  \n\t"
+      "mul       %[t4],        %[c2],        %[state1_hi]  \n\t"
+      "mul       %[b2],        %[c3],        %[state1_hi]  \n\t"
+      "shra_r.w  %[t2],        %[t2],        15            \n\t"
+      "shra_r.w  %[t0],        %[t0],        15            \n\t"
+      "addu      %[t1],        %[t1],        %[t2]         \n\t"
+      "addu      %[a2],        %[a2],        %[t0]         \n\t"
+      "sra       %[t1],        %[t1],        16            \n\t"
+      "addu      %[a2],        %[a2],        %[t1]         \n\t"
+      "shra_r.w  %[t5],        %[t5],        15            \n\t"
+      "shra_r.w  %[t3],        %[t3],        15            \n\t"
+      "addu      %[t4],        %[t4],        %[t5]         \n\t"
+      "addu      %[b2],        %[b2],        %[t3]         \n\t"
+      "sra       %[t4],        %[t4],        16            \n\t"
+      "addu      %[b2],        %[b2],        %[t4]         \n\t"
+      "addu      %[a1],        %[a1],        %[b1]         \n\t"
+      "sra       %[a1],        %[a1],        7             \n\t"
+      "addu      %[a1],        %[a1],        %[in]         \n\t"
+      "sll       %[t0],        %[in],        2             \n\t"
+      "addu      %[a2],        %[a2],        %[b2]         \n\t"
+      "subu      %[t0],        %[t0],        %[a2]         \n\t"
+      "shll_s.w  %[a1],        %[a1],        16            \n\t"
+      "shll_s.w  %[t0],        %[t0],        2             \n\t"
+      "sra       %[a1],        %[a1],        16            \n\t"
+      "addu      %[state1_hi], %[state0_hi], $0            \n\t"
+      "addu      %[state1_lo], %[state0_lo], $0            \n\t"
+      "sra       %[state0_hi], %[t0],        16            \n\t"
+      "andi      %[state0_lo], %[t0],        0xFFFF        \n\t"
+      "sra       %[state0_lo], %[state0_lo], 1             \n\t"
+      ".set      pop                                       \n\t"
+      : [a1] "=&r" (a1), [b1] "=&r" (b1), [a2] "=&r" (a2), [b2] "=&r" (b2),
+        [state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
+        [state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo),
+        [t0] "=&r" (t0), [t1] "=&r" (t1), [t2] "=&r" (t2),
+        [t3] "=&r" (t3), [t4] "=&r" (t4), [t5] "=&r" (t5)
+      : [c0] "r" (c0), [c1] "r" (c1), [c2] "r" (c2), [c3] "r" (c3),
+        [c4] "r" (c4), [c5] "r" (c5), [c6] "r" (c6), [c7] "r" (c7),
+        [in] "r" (in)
+      : "hi", "lo"
+    );
+    io[k] = (int16_t)a1;
+  }
+  __asm __volatile (
+    ".set            push                                            \n\t"
+    ".set            noreorder                                       \n\t"
+#if !defined(MIPS_DSP_R2_LE)
+    "sll             %[state0_hi],   %[state0_hi],   16              \n\t"
+    "sll             %[state0_lo],   %[state0_lo],   1               \n\t"
+    "sll             %[state1_hi],   %[state1_hi],   16              \n\t"
+    "sll             %[state1_lo],   %[state1_lo],   1               \n\t"
+    "or              %[state0_hi],   %[state0_hi],   %[state0_lo]    \n\t"
+    "or              %[state1_hi],   %[state1_hi],   %[state1_lo]    \n\t"
+#else
+    "sll             %[state0_lo],   %[state0_lo],   1               \n\t"
+    "sll             %[state1_lo],   %[state1_lo],   1               \n\t"
+    "precr_sra.ph.w  %[state0_hi],   %[state0_lo],   0               \n\t"
+    "precr_sra.ph.w  %[state1_hi],   %[state1_lo],   0               \n\t"
+#endif
+    "sw              %[state0_hi],   0(%[state])                     \n\t"
+    "sw              %[state1_hi],   4(%[state])                     \n\t"
+    ".set            pop                                             \n\t"
+    : [state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
+      [state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo)
+    : [state] "r" (state)
+    : "memory"
+  );
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c b/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
new file mode 100644
index 0000000..a31cea6
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
@@ -0,0 +1,278 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// Contains a function for WebRtcIsacfix_AllpassFilter2FixDec16Neon()
+// in iSAC codec, optimized for ARM Neon platform. Bit exact with function
+// WebRtcIsacfix_AllpassFilter2FixDec16C() in filterbanks.c. Prototype
+// C code is at end of this file.
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "rtc_base/checks.h"
+
+void WebRtcIsacfix_AllpassFilter2FixDec16Neon(
+    int16_t* data_ch1,  // Input and output in channel 1, in Q0
+    int16_t* data_ch2,  // Input and output in channel 2, in Q0
+    const int16_t* factor_ch1,  // Scaling factor for channel 1, in Q15
+    const int16_t* factor_ch2,  // Scaling factor for channel 2, in Q15
+    const int length,  // Length of the data buffers
+    int32_t* filter_state_ch1,  // Filter state for channel 1, in Q16
+    int32_t* filter_state_ch2) {  // Filter state for channel 2, in Q16
+  RTC_DCHECK_EQ(0, length % 2);
+  int n = 0;
+  int16x4_t factorv;
+  int16x4_t datav;
+  int32x4_t statev;
+
+  // Load factor_ch1 and factor_ch2.
+  factorv = vld1_dup_s16(factor_ch1);
+  factorv = vld1_lane_s16(factor_ch1 + 1, factorv, 1);
+  factorv = vld1_lane_s16(factor_ch2, factorv, 2);
+  factorv = vld1_lane_s16(factor_ch2 + 1, factorv, 3);
+
+  // Load filter_state_ch1[0] and filter_state_ch2[0].
+  statev = vld1q_dup_s32(filter_state_ch1);
+  statev = vld1q_lane_s32(filter_state_ch2, statev, 2);
+
+  // Loop unrolling preprocessing.
+  int32x4_t a;
+  int16x4_t tmp1, tmp2;
+
+  // Load data_ch1[0] and data_ch2[0].
+  datav = vld1_dup_s16(data_ch1);
+  datav = vld1_lane_s16(data_ch2, datav, 2);
+
+  a = vqdmlal_s16(statev, datav, factorv);
+  tmp1 = vshrn_n_s32(a, 16);
+
+  // Update filter_state_ch1[0] and filter_state_ch2[0].
+  statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+
+  // Load filter_state_ch1[1] and filter_state_ch2[1].
+  statev = vld1q_lane_s32(filter_state_ch1 + 1, statev, 1);
+  statev = vld1q_lane_s32(filter_state_ch2 + 1, statev, 3);
+
+  // Load data_ch1[1] and data_ch2[1].
+  tmp1 = vld1_lane_s16(data_ch1 + 1, tmp1, 1);
+  tmp1 = vld1_lane_s16(data_ch2 + 1, tmp1, 3);
+  datav = vrev32_s16(tmp1);
+
+  // Loop unrolling processing.
+  for (n = 0; n < length - 2; n += 2) {
+    a = vqdmlal_s16(statev, datav, factorv);
+    tmp1 = vshrn_n_s32(a, 16);
+    // Store data_ch1[n] and data_ch2[n].
+    vst1_lane_s16(data_ch1 + n, tmp1, 1);
+    vst1_lane_s16(data_ch2 + n, tmp1, 3);
+
+    // Update filter_state_ch1[0], filter_state_ch1[1]
+    // and filter_state_ch2[0], filter_state_ch2[1].
+    statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+
+    // Load data_ch1[n + 2] and data_ch2[n + 2].
+    tmp1 = vld1_lane_s16(data_ch1 + n + 2, tmp1, 1);
+    tmp1 = vld1_lane_s16(data_ch2 + n + 2, tmp1, 3);
+    datav = vrev32_s16(tmp1);
+
+    a = vqdmlal_s16(statev, datav, factorv);
+    tmp2 = vshrn_n_s32(a, 16);
+    // Store data_ch1[n + 1] and data_ch2[n + 1].
+    vst1_lane_s16(data_ch1 + n + 1, tmp2, 1);
+    vst1_lane_s16(data_ch2 + n + 1, tmp2, 3);
+
+    // Update filter_state_ch1[0], filter_state_ch1[1]
+    // and filter_state_ch2[0], filter_state_ch2[1].
+    statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp2, factorv);
+
+    // Load data_ch1[n + 3] and data_ch2[n + 3].
+    tmp2 = vld1_lane_s16(data_ch1 + n + 3, tmp2, 1);
+    tmp2 = vld1_lane_s16(data_ch2 + n + 3, tmp2, 3);
+    datav = vrev32_s16(tmp2);
+  }
+
+  // Loop unrolling post-processing.
+  a = vqdmlal_s16(statev, datav, factorv);
+  tmp1 = vshrn_n_s32(a, 16);
+  // Store data_ch1[n] and data_ch2[n].
+  vst1_lane_s16(data_ch1 + n, tmp1, 1);
+  vst1_lane_s16(data_ch2 + n, tmp1, 3);
+
+  // Update filter_state_ch1[0], filter_state_ch1[1]
+  // and filter_state_ch2[0], filter_state_ch2[1].
+  statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+  // Store filter_state_ch1[0] and filter_state_ch2[0].
+  vst1q_lane_s32(filter_state_ch1, statev, 0);
+  vst1q_lane_s32(filter_state_ch2, statev, 2);
+
+  datav = vrev32_s16(tmp1);
+  a = vqdmlal_s16(statev, datav, factorv);
+  tmp2 = vshrn_n_s32(a, 16);
+  // Store data_ch1[n + 1] and data_ch2[n + 1].
+  vst1_lane_s16(data_ch1 + n + 1, tmp2, 1);
+  vst1_lane_s16(data_ch2 + n + 1, tmp2, 3);
+
+  // Update filter_state_ch1[1] and filter_state_ch2[1].
+  statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp2, factorv);
+  // Store filter_state_ch1[1] and filter_state_ch2[1].
+  vst1q_lane_s32(filter_state_ch1 + 1, statev, 1);
+  vst1q_lane_s32(filter_state_ch2 + 1, statev, 3);
+}
+
+// This function is the prototype for above neon optimized function.
+//void AllpassFilter2FixDec16BothChannels(
+//    int16_t *data_ch1,  // Input and output in channel 1, in Q0
+//    int16_t *data_ch2,  // Input and output in channel 2, in Q0
+//    const int16_t *factor_ch1,  // Scaling factor for channel 1, in Q15
+//    const int16_t *factor_ch2,  // Scaling factor for channel 2, in Q15
+//    const int length,  // Length of the data buffers
+//    int32_t *filter_state_ch1,  // Filter state for channel 1, in Q16
+//    int32_t *filter_state_ch2) {  // Filter state for channel 2, in Q16
+//  int n = 0;
+//  int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
+//  int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
+//  int16_t sample0_ch1 = 0, sample0_ch2 = 0;
+//  int16_t sample1_ch1 = 0, sample1_ch2  = 0;
+//  int32_t a0_ch1 = 0, a0_ch2 = 0;
+//  int32_t b0_ch1 = 0, b0_ch2 = 0;
+//
+//  int32_t a1_ch1 = 0, a1_ch2 = 0;
+//  int32_t b1_ch1 = 0, b1_ch2 = 0;
+//  int32_t b2_ch1  = 0, b2_ch2 = 0;
+//
+//  // Loop unrolling preprocessing.
+//
+//  sample0_ch1 = data_ch1[n];
+//  sample0_ch2 = data_ch2[n];
+//
+//  a0_ch1 = (factor_ch1[0] * sample0_ch1) << 1;
+//  a0_ch2 = (factor_ch2[0] * sample0_ch2) << 1;
+//
+//  b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
+//  b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
+//
+//  a0_ch1 = -factor_ch1[0] * (int16_t)(b0_ch1 >> 16);
+//  a0_ch2 = -factor_ch2[0] * (int16_t)(b0_ch2 >> 16);
+//
+//  state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1 <<1, (uint32_t)sample0_ch1 << 16);
+//  state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2 <<1, (uint32_t)sample0_ch2 << 16);
+//
+//  sample1_ch1 = data_ch1[n + 1];
+//  sample0_ch1 = (int16_t) (b0_ch1 >> 16); //Save as Q0
+//  sample1_ch2  = data_ch2[n + 1];
+//  sample0_ch2 = (int16_t) (b0_ch2 >> 16); //Save as Q0
+//
+//
+//  for (n = 0; n < length - 2; n += 2) {
+//    a1_ch1 = (factor_ch1[0] * sample1_ch1) << 1;
+//    a0_ch1 = (factor_ch1[1] * sample0_ch1) << 1;
+//    a1_ch2 = (factor_ch2[0] * sample1_ch2) << 1;
+//    a0_ch2 = (factor_ch2[1] * sample0_ch2) << 1;
+//
+//    b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
+//    b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1); //Q16+Q16=Q16
+//    b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2); //Q16+Q16=Q16
+//    b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2); //Q16+Q16=Q16
+//
+//    a1_ch1 = -factor_ch1[0] * (int16_t)(b1_ch1 >> 16);
+//    a0_ch1 = -factor_ch1[1] * (int16_t)(b0_ch1 >> 16);
+//    a1_ch2 = -factor_ch2[0] * (int16_t)(b1_ch2 >> 16);
+//    a0_ch2 = -factor_ch2[1] * (int16_t)(b0_ch2 >> 16);
+//
+//    state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 <<16);
+//    state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 <<16);
+//    state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 <<16);
+//    state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 <<16);
+//
+//    sample0_ch1 = data_ch1[n + 2];
+//    sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
+//    sample0_ch2 = data_ch2[n + 2];
+//    sample1_ch2  = (int16_t) (b1_ch2 >> 16); //Save as Q0
+//
+//    a0_ch1 = (factor_ch1[0] * sample0_ch1) << 1;
+//    a1_ch1 = (factor_ch1[1] * sample1_ch1) << 1;
+//    a0_ch2 = (factor_ch2[0] * sample0_ch2) << 1;
+//    a1_ch2 = (factor_ch2[1] * sample1_ch2) << 1;
+//
+//    b2_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
+//    b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
+//    b2_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
+//    b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
+//
+//    a0_ch1 = -factor_ch1[0] * (int16_t)(b2_ch1 >> 16);
+//    a1_ch1 = -factor_ch1[1] * (int16_t)(b1_ch1 >> 16);
+//    a0_ch2 = -factor_ch2[0] * (int16_t)(b2_ch2 >> 16);
+//    a1_ch2 = -factor_ch2[1] * (int16_t)(b1_ch2 >> 16);
+//
+//    state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1<<16);
+//    state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
+//    state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2<<16);
+//    state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
+//
+//
+//    sample1_ch1 = data_ch1[n + 3];
+//    sample0_ch1 = (int16_t) (b2_ch1  >> 16); //Save as Q0
+//    sample1_ch2 = data_ch2[n + 3];
+//    sample0_ch2 = (int16_t) (b2_ch2 >> 16); //Save as Q0
+//
+//    data_ch1[n]     = (int16_t) (b0_ch1 >> 16); //Save as Q0
+//    data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
+//    data_ch2[n]     = (int16_t) (b0_ch2 >> 16);
+//    data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
+//  }
+//
+//  // Loop unrolling post-processing.
+//
+//  a1_ch1 = (factor_ch1[0] * sample1_ch1) << 1;
+//  a0_ch1 = (factor_ch1[1] * sample0_ch1) << 1;
+//  a1_ch2 = (factor_ch2[0] * sample1_ch2) << 1;
+//  a0_ch2 = (factor_ch2[1] * sample0_ch2) << 1;
+//
+//  b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
+//  b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1);
+//  b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2);
+//  b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2);
+//
+//  a1_ch1 = -factor_ch1[0] * (int16_t)(b1_ch1 >> 16);
+//  a0_ch1 = -factor_ch1[1] * (int16_t)(b0_ch1 >> 16);
+//  a1_ch2 = -factor_ch2[0] * (int16_t)(b1_ch2 >> 16);
+//  a0_ch2 = -factor_ch2[1] * (int16_t)(b0_ch2 >> 16);
+//
+//  state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 << 16);
+//  state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 << 16);
+//  state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 << 16);
+//  state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 << 16);
+//
+//  data_ch1[n] = (int16_t) (b0_ch1 >> 16); //Save as Q0
+//  data_ch2[n] = (int16_t) (b0_ch2 >> 16);
+//
+//  sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
+//  sample1_ch2  = (int16_t) (b1_ch2 >> 16); //Save as Q0
+//
+//  a1_ch1 = (factor_ch1[1] * sample1_ch1) << 1;
+//  a1_ch2 = (factor_ch2[1] * sample1_ch2) << 1;
+//
+//  b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
+//  b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
+//
+//  a1_ch1 = -factor_ch1[1] * (int16_t)(b1_ch1 >> 16);
+//  a1_ch2 = -factor_ch2[1] * (int16_t)(b1_ch2 >> 16);
+//
+//  state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
+//  state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
+//
+//  data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
+//  data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
+//
+//  filter_state_ch1[0] = state0_ch1;
+//  filter_state_ch1[1] = state1_ch1;
+//  filter_state_ch2[0] = state0_ch2;
+//  filter_state_ch2[1] = state1_ch2;
+//}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
new file mode 100644
index 0000000..4a3db23
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/sanitizer.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class FilterBanksTest : public ::testing::Test {
+ protected:
+  // Pass a function pointer to the Tester function.
+  void RTC_NO_SANITIZE("signed-integer-overflow")  // bugs.webrtc.org/5513
+      CalculateResidualEnergyTester(
+          AllpassFilter2FixDec16 AllpassFilter2FixDec16Function) {
+    const int kSamples = QLOOKAHEAD;
+    const int kState = 2;
+    int16_t data_ch1[kSamples] = {0};
+    int16_t data_ch2[kSamples] = {0};
+    int32_t state_ch1[kState] = {0};
+    int32_t state_ch2[kState] = {0};
+    const int32_t out_state_ch1[kState] = {-809122714, 1645972152};
+    const int32_t out_state_ch2[kState] = {428019288, 1057309936};
+    const int32_t out_data_ch1[kSamples] = {
+        0,      0,     347,    10618,  16718,  -7089,  32767, 16913,
+        27042,  8377,  -22973, -28372, -27603, -14804, 398,   -25332,
+        -11200, 18044, 25223,  -6839,  1116,   -23984, 32717, 7364};
+    const int32_t out_data_ch2[kSamples] = {
+        0,      0,      3010,  22351,  21106, 16969, -2095, -664,
+        3513,   -30980, 32767, -23839, 13335, 20289, -6831, 339,
+        -17207, 32767,  4959,  6177,   32767, 16599, -4747, 20504};
+    int sign = 1;
+
+    for (int i = 0; i < kSamples; i++) {
+      sign *= -1;
+      data_ch1[i] = sign * WEBRTC_SPL_WORD32_MAX / (i * i + 1);
+      data_ch2[i] = sign * WEBRTC_SPL_WORD32_MIN / (i * i + 1);
+      // UBSan: -1 * -2147483648 cannot be represented in type 'int'
+    };
+
+    AllpassFilter2FixDec16Function(
+        data_ch1, data_ch2, WebRtcIsacfix_kUpperApFactorsQ15,
+        WebRtcIsacfix_kLowerApFactorsQ15, kSamples, state_ch1, state_ch2);
+
+    for (int i = 0; i < kSamples; i++) {
+      EXPECT_EQ(out_data_ch1[i], data_ch1[i]);
+      EXPECT_EQ(out_data_ch2[i], data_ch2[i]);
+    }
+    for (int i = 0; i < kState; i++) {
+      EXPECT_EQ(out_state_ch1[i], state_ch1[i]);
+      EXPECT_EQ(out_state_ch2[i], state_ch2[i]);
+    }
+  }
+};
+
+TEST_F(FilterBanksTest, AllpassFilter2FixDec16Test) {
+  CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16C);
+#if defined(WEBRTC_HAS_NEON)
+  CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16Neon);
+#endif
+}
+
+TEST_F(FilterBanksTest, HighpassFilterFixDec32Test) {
+  const int kSamples = 20;
+  int16_t in[kSamples];
+  int32_t state[2] = {12345, 987654};
+#ifdef WEBRTC_ARCH_ARM_V7
+  int32_t out[kSamples] = {-1040,  -1035, -22875, -1397, -27604, 20018,  7917,
+                           -1279,  -8552, -14494, -7558, -23537, -27258, -30554,
+                           -32768, -3432, -32768, 25215, -27536, 22436};
+#else
+  int32_t out[kSamples] = {-1040,  -1035, -22875, -1397, -27604, 20017,  7915,
+                           -1280,  -8554, -14496, -7561, -23541, -27263, -30560,
+                           -32768, -3441, -32768, 25203, -27550, 22419};
+#endif
+  HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+#if defined(MIPS_DSP_R1_LE)
+  WebRtcIsacfix_HighpassFilterFixDec32 =
+      WebRtcIsacfix_HighpassFilterFixDec32MIPS;
+#else
+  WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
+#endif
+
+  for (int i = 0; i < kSamples; i++) {
+    in[i] = WEBRTC_SPL_WORD32_MAX / (i + 1);
+  }
+
+  WebRtcIsacfix_HighpassFilterFixDec32(in, kSamples,
+                                       WebRtcIsacfix_kHPStCoeffOut1Q30, state);
+
+  for (int i = 0; i < kSamples; i++) {
+    EXPECT_EQ(out[i], in[i]);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filters.c b/modules/audio_coding/codecs/isac/fix/source/filters.c
new file mode 100644
index 0000000..838ba4b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filters.c
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
+                            const int16_t* __restrict x,
+                            int16_t N,
+                            int16_t order,
+                            int16_t* __restrict scale) {
+  int i = 0;
+  int j = 0;
+  int16_t scaling = 0;
+  int32_t sum = 0;
+  uint32_t temp = 0;
+  int64_t prod = 0;
+
+  // The ARM assembly code assumptoins.
+  RTC_DCHECK_EQ(0, N % 4);
+  RTC_DCHECK_GE(N, 8);
+
+  // Calculate r[0].
+  for (i = 0; i < N; i++) {
+    prod += x[i] * x[i];
+  }
+
+  // Calculate scaling (the value of shifting).
+  temp = (uint32_t)(prod >> 31);
+  if(temp == 0) {
+    scaling = 0;
+  } else {
+    scaling = 32 - WebRtcSpl_NormU32(temp);
+  }
+  r[0] = (int32_t)(prod >> scaling);
+
+  // Perform the actual correlation calculation.
+  for (i = 1; i < order + 1; i++) {
+    prod = 0;
+    for (j = 0; j < N - i; j++) {
+      prod += x[j] * x[i + j];
+    }
+    sum = (int32_t)(prod >> scaling);
+    r[i] = sum;
+  }
+
+  *scale = scaling;
+
+  return(order + 1);
+}
+
+static const int32_t kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
+static const int32_t kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
+
+
+static void AllpassFilterForDec32(int16_t         *InOut16, //Q0
+                                  const int32_t   *APSectionFactors, //Q15
+                                  int16_t         lengthInOut,
+                                  int32_t          *FilterState) //Q16
+{
+  int n, j;
+  int32_t a, b;
+
+  for (j=0; j<ALLPASSSECTIONS; j++) {
+    for (n=0;n<lengthInOut;n+=2){
+      a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
+      a <<= 1;  // Q15 -> Q16
+      b = WebRtcSpl_AddSatW32(a, FilterState[j]);  //Q16+Q16=Q16
+      // `a` in Q15 (Q0*Q31=Q31 shifted 16 gives Q15).
+      a = WEBRTC_SPL_MUL_16_32_RSFT16(b >> 16, -APSectionFactors[j]);
+      // FilterState[j]: Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
+      FilterState[j] = WebRtcSpl_AddSatW32(a << 1, (uint32_t)InOut16[n] << 16);
+      InOut16[n] = (int16_t)(b >> 16);  // Save as Q0.
+    }
+  }
+}
+
+
+
+
+void WebRtcIsacfix_DecimateAllpass32(const int16_t *in,
+                                     int32_t *state_in,        /* array of size: 2*ALLPASSSECTIONS+1 */
+                                     int16_t N,                /* number of input samples */
+                                     int16_t *out)             /* array of size N/2 */
+{
+  int n;
+  int16_t data_vec[PITCH_FRAME_LEN];
+
+  /* copy input */
+  memcpy(data_vec + 1, in, sizeof(int16_t) * (N - 1));
+
+  data_vec[0] = (int16_t)(state_in[2 * ALLPASSSECTIONS] >> 16);  // z^-1 state.
+  state_in[2 * ALLPASSSECTIONS] = (uint32_t)in[N - 1] << 16;
+
+
+
+  AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in);
+  AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS);
+
+  for (n=0;n<N/2;n++) {
+    out[n] = WebRtcSpl_AddSatW16(data_vec[2 * n], data_vec[2 * n + 1]);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filters_mips.c b/modules/audio_coding/codecs/isac/fix/source/filters_mips.c
new file mode 100644
index 0000000..ded3d03
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filters_mips.c
@@ -0,0 +1,365 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// MIPS optimized implementation of the Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
+                               const int16_t* __restrict x,
+                               int16_t N,
+                               int16_t order,
+                               int16_t* __restrict scale) {
+  int i = 0;
+  int16_t scaling = 0;
+  int16_t* in = (int16_t*)x;
+  int loop_size = (int)(N >> 3);
+  int count = (int)(N & 7);
+  // Declare temporary variables used as registry values.
+  int32_t r0, r1, r2, r3;
+#if !defined(MIPS_DSP_R2_LE)
+  // For non-DSPR2 optimizations 4 more registers are used.
+  int32_t r4, r5, r6, r7;
+#endif
+
+  // Calculate r[0] and scaling needed.
+  __asm __volatile (
+    ".set          push                                            \n\t"
+    ".set          noreorder                                       \n\t"
+    "mult          $0,             $0                              \n\t"
+    // Loop is unrolled 8 times, set accumulator to zero in branch delay slot.
+    "beqz          %[loop_size],   2f                              \n\t"
+    " mult         $0,             $0                              \n\t"
+   "1:                                                             \n\t"
+    // Load 8 samples per loop iteration.
+#if defined(MIPS_DSP_R2_LE)
+    "ulw           %[r0],          0(%[in])                        \n\t"
+    "ulw           %[r1],          4(%[in])                        \n\t"
+    "ulw           %[r2],          8(%[in])                        \n\t"
+    "ulw           %[r3],          12(%[in])                       \n\t"
+#else
+    "lh            %[r0],          0(%[in])                        \n\t"
+    "lh            %[r1],          2(%[in])                        \n\t"
+    "lh            %[r2],          4(%[in])                        \n\t"
+    "lh            %[r3],          6(%[in])                        \n\t"
+    "lh            %[r4],          8(%[in])                        \n\t"
+    "lh            %[r5],          10(%[in])                       \n\t"
+    "lh            %[r6],          12(%[in])                       \n\t"
+    "lh            %[r7],          14(%[in])                       \n\t"
+#endif
+    "addiu         %[loop_size],   %[loop_size],   -1              \n\t"
+    // Multiply and accumulate.
+#if defined(MIPS_DSP_R2_LE)
+    "dpa.w.ph      $ac0,           %[r0],          %[r0]           \n\t"
+    "dpa.w.ph      $ac0,           %[r1],          %[r1]           \n\t"
+    "dpa.w.ph      $ac0,           %[r2],          %[r2]           \n\t"
+    "dpa.w.ph      $ac0,           %[r3],          %[r3]           \n\t"
+#else
+    "madd          %[r0],          %[r0]                           \n\t"
+    "madd          %[r1],          %[r1]                           \n\t"
+    "madd          %[r2],          %[r2]                           \n\t"
+    "madd          %[r3],          %[r3]                           \n\t"
+    "madd          %[r4],          %[r4]                           \n\t"
+    "madd          %[r5],          %[r5]                           \n\t"
+    "madd          %[r6],          %[r6]                           \n\t"
+    "madd          %[r7],          %[r7]                           \n\t"
+#endif
+    "bnez          %[loop_size],   1b                              \n\t"
+    " addiu        %[in],          %[in],          16              \n\t"
+   "2:                                                             \n\t"
+    "beqz          %[count],       4f                              \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    " extr.w       %[r0],          $ac0,           31              \n\t"
+#else
+    " mfhi         %[r2]                                           \n\t"
+#endif
+    // Process remaining samples (if any).
+   "3:                                                             \n\t"
+    "lh            %[r0],          0(%[in])                        \n\t"
+    "addiu         %[count],       %[count],       -1              \n\t"
+    "madd          %[r0],          %[r0]                           \n\t"
+    "bnez          %[count],       3b                              \n\t"
+    " addiu        %[in],          %[in],          2               \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "extr.w        %[r0],          $ac0,           31              \n\t"
+#else
+    "mfhi          %[r2]                                           \n\t"
+#endif
+   "4:                                                             \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+    "mflo          %[r3]                                           \n\t"
+    "sll           %[r0],          %[r2],          1               \n\t"
+    "srl           %[r1],          %[r3],          31              \n\t"
+    "addu          %[r0],          %[r0],          %[r1]           \n\t"
+#endif
+    // Calculate scaling (the value of shifting).
+    "clz           %[r1],          %[r0]                           \n\t"
+    "addiu         %[r1],          %[r1],          -32             \n\t"
+    "subu          %[scaling],     $0,             %[r1]           \n\t"
+    "slti          %[r1],          %[r0],          0x1             \n\t"
+    "movn          %[scaling],     $0,             %[r1]           \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "extrv.w       %[r0],          $ac0,           %[scaling]      \n\t"
+    "mfhi          %[r2],          $ac0                            \n\t"
+#else
+    "addiu         %[r1],          %[scaling],     -32             \n\t"
+    "subu          %[r1],          $0,             %[r1]           \n\t"
+    "sllv          %[r1],          %[r2],          %[r1]           \n\t"
+    "srlv          %[r0],          %[r3],          %[scaling]      \n\t"
+    "addu          %[r0],          %[r0],          %[r1]           \n\t"
+#endif
+    "slti          %[r1],          %[scaling],     32              \n\t"
+    "movz          %[r0],          %[r2],          %[r1]           \n\t"
+    ".set          pop                                             \n\t"
+    : [loop_size] "+r" (loop_size), [in] "+r" (in), [r0] "=&r" (r0),
+      [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+#if !defined(MIPS_DSP_R2_LE)
+      [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+      [count] "+r" (count), [scaling] "=r" (scaling)
+    : [N] "r" (N)
+    : "memory", "hi", "lo"
+  );
+  r[0] = r0;
+
+  // Correlation calculation is divided in 3 cases depending on the scaling
+  // value (different accumulator manipulation needed). Three slightly different
+  // loops are written in order to avoid branches inside the loop.
+  if (scaling == 0) {
+    // In this case, the result will be in low part of the accumulator.
+    for (i = 1; i < order + 1; i++) {
+      in = (int16_t*)x;
+      int16_t* in1 = (int16_t*)x + i;
+      count = N - i;
+      loop_size = (count) >> 2;
+      __asm  __volatile (
+        ".set        push                                          \n\t"
+        ".set        noreorder                                     \n\t"
+        "mult        $0,             $0                            \n\t"
+        "beqz        %[loop_size],   2f                            \n\t"
+        " andi       %[count],       %[count],       0x3           \n\t"
+        // Loop processing 4 pairs of samples per iteration.
+       "1:                                                         \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "ulw         %[r0],          0(%[in])                      \n\t"
+        "ulw         %[r1],          0(%[in1])                     \n\t"
+        "ulw         %[r2],          4(%[in])                      \n\t"
+        "ulw         %[r3],          4(%[in1])                     \n\t"
+#else
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "lh          %[r2],          2(%[in])                      \n\t"
+        "lh          %[r3],          2(%[in1])                     \n\t"
+        "lh          %[r4],          4(%[in])                      \n\t"
+        "lh          %[r5],          4(%[in1])                     \n\t"
+        "lh          %[r6],          6(%[in])                      \n\t"
+        "lh          %[r7],          6(%[in1])                     \n\t"
+#endif
+        "addiu       %[loop_size],   %[loop_size],   -1            \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "dpa.w.ph    $ac0,           %[r0],          %[r1]         \n\t"
+        "dpa.w.ph    $ac0,           %[r2],          %[r3]         \n\t"
+#else
+        "madd        %[r0],          %[r1]                         \n\t"
+        "madd        %[r2],          %[r3]                         \n\t"
+        "madd        %[r4],          %[r5]                         \n\t"
+        "madd        %[r6],          %[r7]                         \n\t"
+#endif
+        "addiu       %[in],          %[in],          8             \n\t"
+        "bnez        %[loop_size],   1b                            \n\t"
+        " addiu      %[in1],         %[in1],         8             \n\t"
+       "2:                                                         \n\t"
+        "beqz        %[count],       4f                            \n\t"
+        " mflo       %[r0]                                         \n\t"
+        // Process remaining samples (if any).
+       "3:                                                         \n\t"
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "addiu       %[count],       %[count],       -1            \n\t"
+        "addiu       %[in],          %[in],          2             \n\t"
+        "madd        %[r0],          %[r1]                         \n\t"
+        "bnez        %[count],       3b                            \n\t"
+        " addiu      %[in1],         %[in1],         2             \n\t"
+        "mflo        %[r0]                                         \n\t"
+       "4:                                                         \n\t"
+        ".set        pop                                           \n\t"
+        : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+          [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+          [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+          [count] "+r" (count)
+        :
+        : "memory", "hi", "lo"
+      );
+      r[i] = r0;
+    }
+  } else if (scaling == 32) {
+    // In this case, the result will be high part of the accumulator.
+    for (i = 1; i < order + 1; i++) {
+      in = (int16_t*)x;
+      int16_t* in1 = (int16_t*)x + i;
+      count = N - i;
+      loop_size = (count) >> 2;
+      __asm __volatile (
+        ".set        push                                          \n\t"
+        ".set        noreorder                                     \n\t"
+        "mult        $0,             $0                            \n\t"
+        "beqz        %[loop_size],   2f                            \n\t"
+        " andi       %[count],       %[count],       0x3           \n\t"
+        // Loop processing 4 pairs of samples per iteration.
+       "1:                                                         \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "ulw         %[r0],          0(%[in])                      \n\t"
+        "ulw         %[r1],          0(%[in1])                     \n\t"
+        "ulw         %[r2],          4(%[in])                      \n\t"
+        "ulw         %[r3],          4(%[in1])                     \n\t"
+#else
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "lh          %[r2],          2(%[in])                      \n\t"
+        "lh          %[r3],          2(%[in1])                     \n\t"
+        "lh          %[r4],          4(%[in])                      \n\t"
+        "lh          %[r5],          4(%[in1])                     \n\t"
+        "lh          %[r6],          6(%[in])                      \n\t"
+        "lh          %[r7],          6(%[in1])                     \n\t"
+#endif
+        "addiu       %[loop_size],   %[loop_size],   -1            \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "dpa.w.ph    $ac0,           %[r0],          %[r1]         \n\t"
+        "dpa.w.ph    $ac0,           %[r2],          %[r3]         \n\t"
+#else
+        "madd        %[r0],          %[r1]                         \n\t"
+        "madd        %[r2],          %[r3]                         \n\t"
+        "madd        %[r4],          %[r5]                         \n\t"
+        "madd        %[r6],          %[r7]                         \n\t"
+#endif
+        "addiu       %[in],          %[in],          8             \n\t"
+        "bnez        %[loop_size],   1b                            \n\t"
+        " addiu      %[in1],         %[in1],         8             \n\t"
+       "2:                                                         \n\t"
+        "beqz        %[count],       4f                            \n\t"
+        " mfhi       %[r0]                                         \n\t"
+        // Process remaining samples (if any).
+       "3:                                                         \n\t"
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "addiu       %[count],       %[count],       -1            \n\t"
+        "addiu       %[in],          %[in],          2             \n\t"
+        "madd        %[r0],          %[r1]                         \n\t"
+        "bnez        %[count],       3b                            \n\t"
+        " addiu      %[in1],         %[in1],         2             \n\t"
+        "mfhi        %[r0]                                         \n\t"
+       "4:                                                         \n\t"
+        ".set        pop                                           \n\t"
+        : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+          [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+          [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+          [count] "+r" (count)
+        :
+        : "memory", "hi", "lo"
+      );
+      r[i] = r0;
+    }
+  } else {
+    // In this case, the result is obtained by combining low and high parts
+    // of the accumulator.
+#if !defined(MIPS_DSP_R1_LE)
+    int32_t tmp_shift = 32 - scaling;
+#endif
+    for (i = 1; i < order + 1; i++) {
+      in = (int16_t*)x;
+      int16_t* in1 = (int16_t*)x + i;
+      count = N - i;
+      loop_size = (count) >> 2;
+      __asm __volatile (
+        ".set        push                                          \n\t"
+        ".set        noreorder                                     \n\t"
+        "mult        $0,             $0                            \n\t"
+        "beqz        %[loop_size],   2f                            \n\t"
+        " andi       %[count],       %[count],       0x3           \n\t"
+       "1:                                                         \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "ulw         %[r0],          0(%[in])                      \n\t"
+        "ulw         %[r1],          0(%[in1])                     \n\t"
+        "ulw         %[r2],          4(%[in])                      \n\t"
+        "ulw         %[r3],          4(%[in1])                     \n\t"
+#else
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "lh          %[r2],          2(%[in])                      \n\t"
+        "lh          %[r3],          2(%[in1])                     \n\t"
+        "lh          %[r4],          4(%[in])                      \n\t"
+        "lh          %[r5],          4(%[in1])                     \n\t"
+        "lh          %[r6],          6(%[in])                      \n\t"
+        "lh          %[r7],          6(%[in1])                     \n\t"
+#endif
+        "addiu       %[loop_size],   %[loop_size],   -1            \n\t"
+#if defined(MIPS_DSP_R2_LE)
+        "dpa.w.ph    $ac0,           %[r0],          %[r1]         \n\t"
+        "dpa.w.ph    $ac0,           %[r2],          %[r3]         \n\t"
+#else
+        "madd        %[r0],          %[r1]                         \n\t"
+        "madd        %[r2],          %[r3]                         \n\t"
+        "madd        %[r4],          %[r5]                         \n\t"
+        "madd        %[r6],          %[r7]                         \n\t"
+#endif
+        "addiu       %[in],          %[in],          8             \n\t"
+        "bnez        %[loop_size],   1b                            \n\t"
+        " addiu      %[in1],         %[in1],         8             \n\t"
+       "2:                                                         \n\t"
+        "beqz        %[count],       4f                            \n\t"
+#if defined(MIPS_DSP_R1_LE)
+        " extrv.w    %[r0],          $ac0,           %[scaling]    \n\t"
+#else
+        " mfhi       %[r0]                                         \n\t"
+#endif
+       "3:                                                         \n\t"
+        "lh          %[r0],          0(%[in])                      \n\t"
+        "lh          %[r1],          0(%[in1])                     \n\t"
+        "addiu       %[count],       %[count],       -1            \n\t"
+        "addiu       %[in],          %[in],          2             \n\t"
+        "madd        %[r0],          %[r1]                         \n\t"
+        "bnez        %[count],       3b                            \n\t"
+        " addiu      %[in1],         %[in1],         2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+        "extrv.w     %[r0],          $ac0,           %[scaling]    \n\t"
+#else
+        "mfhi        %[r0]                                         \n\t"
+#endif
+       "4:                                                         \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+        "mflo        %[r1]                                         \n\t"
+        "sllv        %[r0],          %[r0],          %[tmp_shift]  \n\t"
+        "srlv        %[r1],          %[r1],          %[scaling]    \n\t"
+        "addu        %[r0],          %[r0],          %[r1]         \n\t"
+#endif
+        ".set        pop                                           \n\t"
+        : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+          [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+          [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+          [count] "+r" (count)
+        : [scaling] "r" (scaling)
+#if !defined(MIPS_DSP_R1_LE)
+        , [tmp_shift] "r" (tmp_shift)
+#endif
+        : "memory", "hi", "lo"
+      );
+      r[i] = r0;
+    }
+  }
+  *scale = scaling;
+
+  return (order + 1);
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/filters_neon.c b/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
new file mode 100644
index 0000000..1734a96
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
+                               const int16_t* x,
+                               int16_t n,
+                               int16_t order,
+                               int16_t* __restrict scale) {
+  int i = 0;
+  int16_t scaling = 0;
+  uint32_t temp = 0;
+  int64_t prod = 0;
+  int64_t prod_tail = 0;
+
+  RTC_DCHECK_EQ(0, n % 4);
+  RTC_DCHECK_GE(n, 8);
+
+  // Calculate r[0].
+  int16x4_t x0_v;
+  int32x4_t tmpa0_v;
+  int64x2_t tmpb_v;
+
+  tmpb_v = vdupq_n_s64(0);
+  const int16_t* x_start = x;
+  const int16_t* x_end0 = x_start + n;
+  while (x_start < x_end0) {
+    x0_v = vld1_s16(x_start);
+    tmpa0_v = vmull_s16(x0_v, x0_v);
+    tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+    x_start += 4;
+  }
+
+#ifdef WEBRTC_ARCH_ARM64
+  prod = vaddvq_s64(tmpb_v);
+#else
+  prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
+                       0);
+#endif
+  // Calculate scaling (the value of shifting).
+  temp = (uint32_t)(prod >> 31);
+
+  scaling = temp ? 32 - WebRtcSpl_NormU32(temp) : 0;
+  r[0] = (int32_t)(prod >> scaling);
+
+  int16x8_t x1_v;
+  int16x8_t y_v;
+  int32x4_t tmpa1_v;
+  // Perform the actual correlation calculation.
+  for (i = 1; i < order + 1; i++) {
+    tmpb_v = vdupq_n_s64(0);
+    int rest = (n - i) % 8;
+    x_start = x;
+    x_end0 = x_start + n - i - rest;
+    const int16_t* y_start = x_start + i;
+    while (x_start < x_end0) {
+      x1_v = vld1q_s16(x_start);
+      y_v = vld1q_s16(y_start);
+      tmpa0_v = vmull_s16(vget_low_s16(x1_v), vget_low_s16(y_v));
+#ifdef WEBRTC_ARCH_ARM64
+      tmpa1_v = vmull_high_s16(x1_v, y_v);
+#else
+      tmpa1_v = vmull_s16(vget_high_s16(x1_v), vget_high_s16(y_v));
+#endif
+      tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+      tmpb_v = vpadalq_s32(tmpb_v, tmpa1_v);
+      x_start += 8;
+      y_start += 8;
+    }
+    // The remaining calculation.
+    const int16_t* x_end1 = x + n - i;
+    if (rest >= 4) {
+        int16x4_t x2_v = vld1_s16(x_start);
+        int16x4_t y2_v = vld1_s16(y_start);
+        tmpa0_v = vmull_s16(x2_v, y2_v);
+        tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+        x_start += 4;
+        y_start += 4;
+    }
+#ifdef WEBRTC_ARCH_ARM64
+    prod = vaddvq_s64(tmpb_v);
+#else
+    prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
+                         0);
+#endif
+
+    prod_tail = 0;
+    while (x_start < x_end1) {
+      prod_tail += *x_start * *y_start;
+      ++x_start;
+      ++y_start;
+    }
+
+    r[i] = (int32_t)((prod + prod_tail) >> scaling);
+  }
+
+  *scale = scaling;
+
+  return order + 1;
+}
+
diff --git a/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
new file mode 100644
index 0000000..192ef89
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class FiltersTest : public ::testing::Test {
+ protected:
+  // Pass a function pointer to the Tester function.
+  void FiltersTester(AutocorrFix WebRtcIsacfix_AutocorrFixFunction) {
+    const int kOrder = 12;
+    const int kBuffer = 40;
+    int16_t scale = 0;
+    int32_t r_buffer[kOrder + 2] = {0};
+
+    // Test an overflow case.
+    const int16_t x_buffer_0[kBuffer] = {
+        0,      0,      3010,  22351,  21106, 16969,  -2095, -664,
+        3513,   -30980, 32767, -23839, 13335, 20289,  -6831, 339,
+        -17207, 32767,  4959,  6177,   32767, 16599,  -4747, 20504,
+        3513,   -30980, 32767, -23839, 13335, 20289,  0,     -16969,
+        -2095,  -664,   3513,  31981,  32767, -13839, 23336, 30281};
+    const int32_t r_expected_0[kOrder + 2] = {
+        1872498461, -224288754, 203789985, 483400487,  -208272635,
+        2436500,    137785322,  266600814, -208486262, 329510080,
+        137949184,  -161738972, -26894267, 237630192};
+
+    WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_0, kBuffer, kOrder + 1,
+                                      &scale);
+    for (int i = 0; i < kOrder + 2; i++) {
+      EXPECT_EQ(r_expected_0[i], r_buffer[i]);
+    }
+    EXPECT_EQ(3, scale);
+
+    // Test a no-overflow case.
+    const int16_t x_buffer_1[kBuffer] = {
+        0,   0,     300,   21,   206,   169,  -295, -664, 3513, -300,
+        327, -29,   15,    289,  -6831, 339,  -107, 37,   59,   6177,
+        327, 169,   -4747, 204,  313,   -980, 767,  -9,   135,  289,
+        0,   -6969, -2095, -664, 0,     1,    7,    -39,  236,  281};
+    const int32_t r_expected_1[kOrder + 2] = {
+        176253864, 8126617,   1983287,   -26196788, -3487363,
+        -42839676, -24644043, 3469813,   30559879,  31905045,
+        5101567,   29328896,  -55787438, -13163978};
+
+    WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_1, kBuffer, kOrder + 1,
+                                      &scale);
+    for (int i = 0; i < kOrder + 2; i++) {
+      EXPECT_EQ(r_expected_1[i], r_buffer[i]);
+    }
+    EXPECT_EQ(0, scale);
+  }
+};
+
+TEST_F(FiltersTest, AutocorrFixTest) {
+  FiltersTester(WebRtcIsacfix_AutocorrC);
+#if defined(WEBRTC_HAS_NEON)
+  FiltersTester(WebRtcIsacfix_AutocorrNeon);
+#endif
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/initialize.c b/modules/audio_coding/codecs/isac/fix/source/initialize.c
new file mode 100644
index 0000000..1b82958
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/initialize.c
@@ -0,0 +1,173 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * initialize.c
+ *
+ * Internal initfunctions
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc *maskdata) {
+
+  int k;
+
+  for (k = 0; k < WINLEN; k++) {
+    maskdata->DataBufferLoQ0[k] = (int16_t) 0;
+    maskdata->DataBufferHiQ0[k] = (int16_t) 0;
+  }
+  for (k = 0; k < ORDERLO+1; k++) {
+    maskdata->CorrBufLoQQ[k] = (int32_t) 0;
+    maskdata->CorrBufLoQdom[k] = 0;
+
+    maskdata->PreStateLoGQ15[k] = 0;
+
+  }
+  for (k = 0; k < ORDERHI+1; k++) {
+    maskdata->CorrBufHiQQ[k] = (int32_t) 0;
+    maskdata->CorrBufHiQdom[k] = 0;
+    maskdata->PreStateHiGQ15[k] = 0;
+  }
+
+  maskdata->OldEnergy = 10;
+
+  return;
+}
+
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec *maskdata) {
+
+  int k;
+
+  for (k = 0; k < ORDERLO+1; k++)
+  {
+    maskdata->PostStateLoGQ0[k] = 0;
+  }
+  for (k = 0; k < ORDERHI+1; k++)
+  {
+    maskdata->PostStateHiGQ0[k] = 0;
+  }
+
+  maskdata->OldEnergy = 10;
+
+  return;
+}
+
+
+
+
+
+
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr *prefiltdata)
+{
+  int k;
+
+  for (k = 0; k < QLOOKAHEAD; k++) {
+    prefiltdata->INLABUF1_fix[k] = 0;
+    prefiltdata->INLABUF2_fix[k] = 0;
+  }
+  for (k = 0; k < 2 * (QORDER - 1); k++) {
+    prefiltdata->INSTAT1_fix[k] = 0;
+    prefiltdata->INSTAT2_fix[k] = 0;
+  }
+
+  /* High pass filter states */
+  prefiltdata->HPstates_fix[0] = 0;
+  prefiltdata->HPstates_fix[1] = 0;
+
+  return;
+}
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+  int k;
+
+  for (k = 0; k < 2 * POSTQORDER; k++) {
+    postfiltdata->STATE_0_LOWER_fix[k] = 0;
+    postfiltdata->STATE_0_UPPER_fix[k] = 0;
+  }
+
+  /* High pass filter states */
+
+  postfiltdata->HPstates1_fix[0] = 0;
+  postfiltdata->HPstates1_fix[1] = 0;
+
+  postfiltdata->HPstates2_fix[0] = 0;
+  postfiltdata->HPstates2_fix[1] = 0;
+
+  return;
+}
+
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr *pitchfiltdata)
+{
+  int k;
+
+  for (k = 0; k < PITCH_BUFFSIZE; k++)
+    pitchfiltdata->ubufQQ[k] = 0;
+  for (k = 0; k < (PITCH_DAMPORDER); k++)
+    pitchfiltdata->ystateQQ[k] = 0;
+
+  pitchfiltdata->oldlagQ7 = 6400; /* 50.0 in Q7 */
+  pitchfiltdata->oldgainQ12 = 0;
+}
+
+void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct *State)
+{
+  int k;
+
+  for (k = 0; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k++) {
+    State->dec_buffer16[k] = 0;
+  }
+  for (k = 0; k < 2 * ALLPASSSECTIONS + 1; k++) {
+    State->decimator_state32[k] = 0;
+  }
+
+  for (k = 0; k < QLOOKAHEAD; k++)
+    State->inbuf[k] = 0;
+
+  WebRtcIsacfix_InitPitchFilter(&(State->PFstr_wght));
+
+  WebRtcIsacfix_InitPitchFilter(&(State->PFstr));
+}
+
+
+void WebRtcIsacfix_InitPlc( PLCstr *State )
+{
+  State->decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX;
+  State->decayCoeffNoise = WEBRTC_SPL_WORD16_MAX;
+
+  State->used = PLC_WAS_USED;
+
+  WebRtcSpl_ZerosArrayW16(State->overlapLP, RECOVERY_OVERLAP);
+  WebRtcSpl_ZerosArrayW16(State->lofilt_coefQ15, ORDERLO);
+  WebRtcSpl_ZerosArrayW16(State->hifilt_coefQ15, ORDERHI );
+
+  State->AvgPitchGain_Q12 = 0;
+  State->lastPitchGain_Q12 = 0;
+  State->lastPitchLag_Q7 = 0;
+  State->gain_lo_hiQ17[0]=State->gain_lo_hiQ17[1] = 0;
+  WebRtcSpl_ZerosArrayW16(State->prevPitchInvIn, FRAMESAMPLES/2);
+  WebRtcSpl_ZerosArrayW16(State->prevPitchInvOut, PITCH_MAX_LAG + 10 );
+  WebRtcSpl_ZerosArrayW32(State->prevHP, PITCH_MAX_LAG + 10 );
+  State->pitchCycles = 0;
+  State->A = 0;
+  State->B = 0;
+  State->pitchIndex = 0;
+  State->stretchLag = 240;
+  State->seed = 4447;
+
+
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h b/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h
new file mode 100644
index 0000000..512911a
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+class IsacFix {
+ public:
+  using instance_type = ISACFIX_MainStruct;
+  static const bool has_swb = false;
+  static inline int16_t Control(instance_type* inst,
+                                int32_t rate,
+                                int framesize) {
+    return WebRtcIsacfix_Control(inst, rate, framesize);
+  }
+  static inline int16_t ControlBwe(instance_type* inst,
+                                   int32_t rate_bps,
+                                   int frame_size_ms,
+                                   int16_t enforce_frame_size) {
+    return WebRtcIsacfix_ControlBwe(inst, rate_bps, frame_size_ms,
+                                    enforce_frame_size);
+  }
+  static inline int16_t Create(instance_type** inst) {
+    return WebRtcIsacfix_Create(inst);
+  }
+  static inline int DecodeInternal(instance_type* inst,
+                                   const uint8_t* encoded,
+                                   size_t len,
+                                   int16_t* decoded,
+                                   int16_t* speech_type) {
+    return WebRtcIsacfix_Decode(inst, encoded, len, decoded, speech_type);
+  }
+  static inline size_t DecodePlc(instance_type* inst,
+                                 int16_t* decoded,
+                                 size_t num_lost_frames) {
+    return WebRtcIsacfix_DecodePlc(inst, decoded, num_lost_frames);
+  }
+  static inline void DecoderInit(instance_type* inst) {
+    WebRtcIsacfix_DecoderInit(inst);
+  }
+  static inline int Encode(instance_type* inst,
+                           const int16_t* speech_in,
+                           uint8_t* encoded) {
+    return WebRtcIsacfix_Encode(inst, speech_in, encoded);
+  }
+  static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+    return WebRtcIsacfix_EncoderInit(inst, coding_mode);
+  }
+  static inline uint16_t EncSampRate(instance_type* inst) {
+    return kFixSampleRate;
+  }
+
+  static inline int16_t Free(instance_type* inst) {
+    return WebRtcIsacfix_Free(inst);
+  }
+  static inline int16_t GetErrorCode(instance_type* inst) {
+    return WebRtcIsacfix_GetErrorCode(inst);
+  }
+
+  static inline int16_t GetNewFrameLen(instance_type* inst) {
+    return WebRtcIsacfix_GetNewFrameLen(inst);
+  }
+  static inline int16_t SetDecSampRate(instance_type* inst,
+                                       uint16_t sample_rate_hz) {
+    RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+    return 0;
+  }
+  static inline int16_t SetEncSampRate(instance_type* inst,
+                                       uint16_t sample_rate_hz) {
+    RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+    return 0;
+  }
+  static inline void SetEncSampRateInDecoder(instance_type* inst,
+                                             uint16_t sample_rate_hz) {
+    RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+  }
+  static inline void SetInitialBweBottleneck(instance_type* inst,
+                                             int bottleneck_bits_per_second) {
+    WebRtcIsacfix_SetInitialBweBottleneck(inst, bottleneck_bits_per_second);
+  }
+  static inline int16_t SetMaxPayloadSize(instance_type* inst,
+                                          int16_t max_payload_size_bytes) {
+    return WebRtcIsacfix_SetMaxPayloadSize(inst, max_payload_size_bytes);
+  }
+  static inline int16_t SetMaxRate(instance_type* inst, int32_t max_bit_rate) {
+    return WebRtcIsacfix_SetMaxRate(inst, max_bit_rate);
+  }
+
+ private:
+  enum { kFixSampleRate = 16000 };
+};
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
diff --git a/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
new file mode 100644
index 0000000..a7d44e8
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
@@ -0,0 +1,1230 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * isacfix.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+
+#include <stdlib.h>
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+// Declare function pointers.
+FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+Spec2Time WebRtcIsacfix_Spec2Time;
+Time2Spec WebRtcIsacfix_Time2Spec;
+MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
+MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
+
+/* This method assumes that `stream_size_bytes` is in valid range,
+ * i.e. >= 0 && <=  STREAM_MAXW16_60MS
+ */
+static void InitializeDecoderBitstream(size_t stream_size_bytes,
+                                       Bitstr_dec* bitstream) {
+  bitstream->W_upper = 0xFFFFFFFF;
+  bitstream->streamval = 0;
+  bitstream->stream_index = 0;
+  bitstream->full = 1;
+  bitstream->stream_size = (stream_size_bytes + 1) >> 1;
+  memset(bitstream->stream, 0, sizeof(bitstream->stream));
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Create(...)
+ *
+ * This function creates a ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ *      - *ISAC_main_inst   : a pointer to the coder instance.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Create(ISACFIX_MainStruct **ISAC_main_inst)
+{
+  ISACFIX_SubStruct *tempo;
+  tempo = malloc(1 * sizeof(ISACFIX_SubStruct));
+  *ISAC_main_inst = (ISACFIX_MainStruct *)tempo;
+  if (*ISAC_main_inst!=NULL) {
+    (*(ISACFIX_SubStruct**)ISAC_main_inst)->errorcode = 0;
+    (*(ISACFIX_SubStruct**)ISAC_main_inst)->initflag = 0;
+    (*(ISACFIX_SubStruct**)ISAC_main_inst)->ISACenc_obj.SaveEnc_ptr = NULL;
+    WebRtcIsacfix_InitBandwidthEstimator(&tempo->bwestimator_obj);
+    return(0);
+  } else {
+    return(-1);
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ *      - *ISAC_main_inst   : a pointer to the coder instance.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Allocate memory for storing encoder data */
+  ISAC_inst->ISACenc_obj.SaveEnc_ptr = malloc(1 * sizeof(IsacSaveEncoderData));
+
+  if (ISAC_inst->ISACenc_obj.SaveEnc_ptr!=NULL) {
+    return(0);
+  } else {
+    return(-1);
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ *      - ISAC_main_inst    : a ISAC instance.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Free(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  free(ISAC_main_inst);
+  return(0);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ *       - ISAC_main_inst    : a ISAC instance.
+ *
+ * Return value              :  0 - Ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Release memory */
+  free(ISAC_inst->ISACenc_obj.SaveEnc_ptr);
+
+  return(0);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_InitNeon(...)
+ *
+ * This function initializes function pointers for ARM Neon platform.
+ */
+
+#if defined(WEBRTC_HAS_NEON)
+static void WebRtcIsacfix_InitNeon(void) {
+  WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrNeon;
+  WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopNeon;
+  WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeNeon;
+  WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecNeon;
+  WebRtcIsacfix_AllpassFilter2FixDec16 =
+      WebRtcIsacfix_AllpassFilter2FixDec16Neon;
+  WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1Neon;
+  WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2Neon;
+}
+#endif
+
+/****************************************************************************
+ * WebRtcIsacfix_InitMIPS(...)
+ *
+ * This function initializes function pointers for MIPS platform.
+ */
+
+#if defined(MIPS32_LE)
+static void WebRtcIsacfix_InitMIPS(void) {
+  WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrMIPS;
+  WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopMIPS;
+  WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeMIPS;
+  WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecMIPS;
+  WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1MIPS;
+  WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2MIPS;
+#if defined(MIPS_DSP_R1_LE)
+  WebRtcIsacfix_AllpassFilter2FixDec16 =
+      WebRtcIsacfix_AllpassFilter2FixDec16MIPS;
+  WebRtcIsacfix_HighpassFilterFixDec32 =
+      WebRtcIsacfix_HighpassFilterFixDec32MIPS;
+#endif
+#if defined(MIPS_DSP_R2_LE)
+  WebRtcIsacfix_CalculateResidualEnergy =
+      WebRtcIsacfix_CalculateResidualEnergyMIPS;
+#endif
+}
+#endif
+
+static void InitFunctionPointers(void) {
+  WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
+  WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
+  WebRtcIsacfix_CalculateResidualEnergy =
+      WebRtcIsacfix_CalculateResidualEnergyC;
+  WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C;
+  WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
+  WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC;
+  WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC;
+  WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C;
+  WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C;
+
+#if defined(WEBRTC_HAS_NEON)
+  WebRtcIsacfix_InitNeon();
+#endif
+
+#if defined(MIPS32_LE)
+  WebRtcIsacfix_InitMIPS();
+#endif
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_EncoderInit(...)
+ *
+ * This function initializes a ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - CodingMode        : 0 -> Bit rate and frame length are automatically
+ *                                 adjusted to available bandwidth on
+ *                                 transmission channel.
+ *                            1 -> User sets a frame length and a target bit
+ *                                 rate which is taken as the maximum short-term
+ *                                 average bit rate.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
+                                  int16_t  CodingMode)
+{
+  int k;
+  int16_t statusInit;
+  ISACFIX_SubStruct *ISAC_inst;
+
+  statusInit = 0;
+  /* typecast pointer to rela structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* flag encoder init */
+  ISAC_inst->initflag |= 2;
+
+  if (CodingMode == 0)
+    /* Adaptive mode */
+    ISAC_inst->ISACenc_obj.new_framelength  = INITIAL_FRAMESAMPLES;
+  else if (CodingMode == 1)
+    /* Instantaneous mode */
+    ISAC_inst->ISACenc_obj.new_framelength = 480;    /* default for I-mode */
+  else {
+    ISAC_inst->errorcode = ISAC_DISALLOWED_CODING_MODE;
+    statusInit = -1;
+  }
+
+  ISAC_inst->CodingMode = CodingMode;
+
+  WebRtcIsacfix_InitMaskingEnc(&ISAC_inst->ISACenc_obj.maskfiltstr_obj);
+  WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACenc_obj.prefiltbankstr_obj);
+  WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACenc_obj.pitchfiltstr_obj);
+  WebRtcIsacfix_InitPitchAnalysis(&ISAC_inst->ISACenc_obj.pitchanalysisstr_obj);
+
+  WebRtcIsacfix_InitRateModel(&ISAC_inst->ISACenc_obj.rate_data_obj);
+
+
+  ISAC_inst->ISACenc_obj.buffer_index   = 0;
+  ISAC_inst->ISACenc_obj.frame_nb    = 0;
+  ISAC_inst->ISACenc_obj.BottleNeck      = 32000; /* default for I-mode */
+  ISAC_inst->ISACenc_obj.MaxDelay    = 10;    /* default for I-mode */
+  ISAC_inst->ISACenc_obj.current_framesamples = 0;
+  ISAC_inst->ISACenc_obj.s2nr     = 0;
+  ISAC_inst->ISACenc_obj.MaxBits    = 0;
+  ISAC_inst->ISACenc_obj.bitstr_seed   = 4447;
+  ISAC_inst->ISACenc_obj.payloadLimitBytes30  = STREAM_MAXW16_30MS << 1;
+  ISAC_inst->ISACenc_obj.payloadLimitBytes60  = STREAM_MAXW16_60MS << 1;
+  ISAC_inst->ISACenc_obj.maxPayloadBytes      = STREAM_MAXW16_60MS << 1;
+  ISAC_inst->ISACenc_obj.maxRateInBytes       = STREAM_MAXW16_30MS << 1;
+  ISAC_inst->ISACenc_obj.enforceFrameSize     = 0;
+
+  /* Init the bistream data area to zero */
+  for (k=0; k<STREAM_MAXW16_60MS; k++){
+    ISAC_inst->ISACenc_obj.bitstr_obj.stream[k] = 0;
+  }
+
+  InitFunctionPointers();
+
+  return statusInit;
+}
+
+/* Read the given number of bytes of big-endian 16-bit integers from `src` and
+   write them to `dest` in host endian. If `nbytes` is odd, the number of
+   output elements is rounded up, and the least significant byte of the last
+   element is set to 0. */
+static void read_be16(const uint8_t* src, size_t nbytes, uint16_t* dest) {
+  size_t i;
+  for (i = 0; i < nbytes / 2; ++i)
+    dest[i] = src[2 * i] << 8 | src[2 * i + 1];
+  if (nbytes % 2 == 1)
+    dest[nbytes / 2] = src[nbytes - 1] << 8;
+}
+
+/* Read the given number of bytes of host-endian 16-bit integers from `src` and
+   write them to `dest` in big endian. If `nbytes` is odd, the number of source
+   elements is rounded up (but only the most significant byte of the last
+   element is used), and the number of output bytes written will be
+   nbytes + 1. */
+static void write_be16(const uint16_t* src, size_t nbytes, uint8_t* dest) {
+  size_t i;
+  for (i = 0; i < nbytes / 2; ++i) {
+    dest[2 * i] = src[i] >> 8;
+    dest[2 * i + 1] = src[i];
+  }
+  if (nbytes % 2 == 1) {
+    dest[nbytes - 1] = src[nbytes / 2] >> 8;
+    dest[nbytes] = 0;
+  }
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - speechIn          : input speech vector.
+ *
+ * Output:
+ *      - encoded           : the encoded data vector
+ *
+ * Return value:
+ *                          : >0 - Length (in bytes) of coded data
+ *                          :  0 - The buffer didn't reach the chosen framesize
+ *                            so it keeps buffering speech samples.
+ *                          : -1 - Error
+ */
+
+int WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
+                         const int16_t    *speechIn,
+                         uint8_t* encoded)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  int stream_len;
+
+  /* typecast pointer to rela structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+  /* check if encoder initiated */
+  if ((ISAC_inst->initflag & 2) != 2) {
+    ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  stream_len = WebRtcIsacfix_EncodeImpl((int16_t*)speechIn,
+                                        &ISAC_inst->ISACenc_obj,
+                                        &ISAC_inst->bwestimator_obj,
+                                        ISAC_inst->CodingMode);
+  if (stream_len<0) {
+    ISAC_inst->errorcode = -(int16_t)stream_len;
+    return -1;
+  }
+
+  write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, (size_t)stream_len,
+             encoded);
+  return stream_len;
+
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - bweIndex          : index of bandwidth estimate to put in new bitstream
+ *
+ * Output:
+ *      - encoded           : the encoded data vector
+ *
+ * Return value:
+ *                          : >0 - Length (in bytes) of coded data
+ *                          : -1 - Error
+ */
+
+int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst,
+                                      int16_t      bweIndex,
+                                      float              scale,
+                                      uint8_t* encoded)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  int16_t stream_len;
+
+  /* typecast pointer to rela structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+  /* check if encoder initiated */
+  if ((ISAC_inst->initflag & 2) != 2) {
+    ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  stream_len = WebRtcIsacfix_EncodeStoredData(&ISAC_inst->ISACenc_obj,
+                                              bweIndex,
+                                              scale);
+  if (stream_len<0) {
+    ISAC_inst->errorcode = - stream_len;
+    return -1;
+  }
+
+  write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, stream_len, encoded);
+  return stream_len;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecoderInit(...)
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ */
+
+void WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+
+  InitFunctionPointers();
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* flag decoder init */
+  ISAC_inst->initflag |= 1;
+
+  WebRtcIsacfix_InitMaskingDec(&ISAC_inst->ISACdec_obj.maskfiltstr_obj);
+  WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACdec_obj.postfiltbankstr_obj);
+  WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACdec_obj.pitchfiltstr_obj);
+
+  /* TS */
+  WebRtcIsacfix_InitPlc( &ISAC_inst->ISACdec_obj.plcstr_obj );
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s).
+ *      - packet_size       : size of the packet.
+ *      - rtp_seq_number    : the RTP number of the packet.
+ *      - arr_ts            : the arrival time of the packet (from NetEq)
+ *                            in samples.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
+                                        const uint8_t* encoded,
+                                        size_t packet_size,
+                                        uint16_t rtp_seq_number,
+                                        uint32_t arr_ts)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  Bitstr_dec streamdata;
+  int16_t err;
+  const size_t kRequiredEncodedLenBytes = 10;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Sanity check of packet length */
+  if (packet_size == 0) {
+    /* return error code if the packet length is null or less */
+    ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+    return -1;
+  } else if (packet_size > (STREAM_MAXW16<<1)) {
+    /* return error code if length of stream is too long */
+    ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+    return -1;
+  }
+
+  /* check if decoder initiated */
+  if ((ISAC_inst->initflag & 1) != 1) {
+    ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  InitializeDecoderBitstream(packet_size, &streamdata);
+
+  read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+  err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+                                        &streamdata,
+                                        packet_size,
+                                        rtp_seq_number,
+                                        0,
+                                        arr_ts);
+
+
+  if (err < 0)
+  {
+    /* return error code if something went wrong */
+    ISAC_inst->errorcode = -err;
+    return -1;
+  }
+
+
+  return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s).
+ *      - packet_size       : size of the packet.
+ *      - rtp_seq_number    : the RTP number of the packet.
+ *      - send_ts           : Send Time Stamp from RTP header
+ *      - arr_ts            : the arrival time of the packet (from NetEq)
+ *                            in samples.
+ *
+ * Return value             :  0 - Ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
+                                       const uint8_t* encoded,
+                                       size_t packet_size,
+                                       uint16_t rtp_seq_number,
+                                       uint32_t send_ts,
+                                       uint32_t arr_ts)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  Bitstr_dec streamdata;
+  int16_t err;
+  const size_t kRequiredEncodedLenBytes = 10;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Sanity check of packet length */
+  if (packet_size == 0) {
+    /* return error code if the packet length is null  or less */
+    ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+    return -1;
+  } else if (packet_size < kRequiredEncodedLenBytes) {
+    ISAC_inst->errorcode = ISAC_PACKET_TOO_SHORT;
+    return -1;
+  } else if (packet_size > (STREAM_MAXW16<<1)) {
+    /* return error code if length of stream is too long */
+    ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+    return -1;
+  }
+
+  /* check if decoder initiated */
+  if ((ISAC_inst->initflag & 1) != 1) {
+    ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  InitializeDecoderBitstream(packet_size, &streamdata);
+
+  read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+  err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+                                        &streamdata,
+                                        packet_size,
+                                        rtp_seq_number,
+                                        send_ts,
+                                        arr_ts);
+
+  if (err < 0)
+  {
+    /* return error code if something went wrong */
+    ISAC_inst->errorcode = -err;
+    return -1;
+  }
+
+
+  return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Decode(...)
+ *
+ * This function decodes a ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - encoded           : encoded ISAC frame(s)
+ *      - len               : bytes in encoded vector
+ *
+ * Output:
+ *      - decoded           : The decoded vector
+ *
+ * Return value             : >0 - number of samples in decoded vector
+ *                            -1 - Error
+ */
+
+
+int WebRtcIsacfix_Decode(ISACFIX_MainStruct* ISAC_main_inst,
+                         const uint8_t* encoded,
+                         size_t len,
+                         int16_t* decoded,
+                         int16_t* speechType)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  /* number of samples (480 or 960), output from decoder */
+  /* that were actually used in the encoder/decoder (determined on the fly) */
+  size_t number_of_samples;
+  int declen_int = 0;
+  size_t declen;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* check if decoder initiated */
+  if ((ISAC_inst->initflag & 1) != 1) {
+    ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  /* Sanity check of packet length */
+  if (len == 0) {
+    /* return error code if the packet length is null  or less */
+    ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+    return -1;
+  } else if (len > (STREAM_MAXW16<<1)) {
+    /* return error code if length of stream is too long */
+    ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+    return -1;
+  }
+
+  InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj);
+
+  read_be16(encoded, len, ISAC_inst->ISACdec_obj.bitstr_obj.stream);
+
+  /* added for NetEq purposes (VAD/DTX related) */
+  *speechType=1;
+
+  declen_int = WebRtcIsacfix_DecodeImpl(decoded, &ISAC_inst->ISACdec_obj,
+                                        &number_of_samples);
+  if (declen_int < 0) {
+    /* Some error inside the decoder */
+    ISAC_inst->errorcode = -(int16_t)declen_int;
+    memset(decoded, 0, sizeof(int16_t) * MAX_FRAMESAMPLES);
+    return -1;
+  }
+  declen = (size_t)declen_int;
+
+  /* error check */
+
+  if (declen & 1) {
+    if (len != declen &&
+        len != declen +
+            ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) & 0xFF)) {
+      ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+      memset(decoded, 0, sizeof(int16_t) * number_of_samples);
+      return -1;
+    }
+  } else {
+    if (len != declen &&
+        len != declen +
+            ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) >> 8)) {
+      ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+      memset(decoded, 0, sizeof(int16_t) * number_of_samples);
+      return -1;
+    }
+  }
+
+  return (int)number_of_samples;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length  will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - noOfLostFrames    : Number of PLC frames (480sample = 30ms)
+ *                                to produce
+ *
+ * Output:
+ *      - decoded           : The decoded vector
+ *
+ * Return value             : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct* ISAC_main_inst,
+                               int16_t* decoded,
+                               size_t noOfLostFrames)
+{
+
+  size_t no_of_samples, declen, k;
+  int16_t outframe16[MAX_FRAMESAMPLES];
+
+  ISACFIX_SubStruct *ISAC_inst;
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */
+  if (noOfLostFrames > 2) {
+    noOfLostFrames = 2;
+  }
+  k = 0;
+  declen = 0;
+  while( noOfLostFrames > 0 )
+  {
+    WebRtcIsacfix_DecodePlcImpl(&(outframe16[k*480]), &ISAC_inst->ISACdec_obj,
+                                &no_of_samples);
+    declen += no_of_samples;
+    noOfLostFrames--;
+    k++;
+  }
+
+  for (k=0;k<declen;k++) {
+    decoded[k] = outframe16[k];
+  }
+
+  return declen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance.
+ *      - rate              : limit on the short-term average bit rate,
+ *                            in bits/second (between 10000 and 32000)
+ *      - framesize         : number of milliseconds per frame (30 or 60)
+ *
+ * Return value             : 0  - ok
+ *                            -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst,
+                              int16_t rate,
+                              int framesize)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  if (ISAC_inst->CodingMode == 0)
+  {
+    /* in adaptive mode */
+    ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+    return -1;
+  }
+
+
+  if (rate >= 10000 && rate <= 32000)
+    ISAC_inst->ISACenc_obj.BottleNeck = rate;
+  else {
+    ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+    return -1;
+  }
+
+
+
+  if (framesize  == 30 || framesize == 60)
+    ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * framesize);
+  else {
+    ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+    return -1;
+  }
+
+  return 0;
+}
+
+void WebRtcIsacfix_SetInitialBweBottleneck(ISACFIX_MainStruct* ISAC_main_inst,
+                                           int bottleneck_bits_per_second) {
+  ISACFIX_SubStruct* inst = (ISACFIX_SubStruct*)ISAC_main_inst;
+  RTC_DCHECK_GE(bottleneck_bits_per_second, 10000);
+  RTC_DCHECK_LE(bottleneck_bits_per_second, 32000);
+  inst->bwestimator_obj.sendBwAvg = ((uint32_t)bottleneck_bits_per_second) << 7;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ *  - ISAC_main_inst : ISAC instance.
+ *      - rateBPS           : initial value of bottleneck in bits/second
+ *                            10000 <= rateBPS <= 32000 is accepted
+ *                            For default bottleneck set rateBPS = 0
+ *      - frameSizeMs       : number of milliseconds per frame (30 or 60)
+ *      - enforceFrameSize  : 1 to enforce the given frame-size through out
+ *                            the adaptation process, 0 to let iSAC change
+ *                            the frame-size if required.
+ *
+ * Return value    : 0  - ok
+ *         -1 - Error
+ */
+
+int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst,
+                                 int16_t rateBPS,
+                                 int frameSizeMs,
+                                 int16_t enforceFrameSize)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  /* Typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* check if encoder initiated */
+  if ((ISAC_inst->initflag & 2) != 2) {
+    ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+    return (-1);
+  }
+
+  /* Check that we are in channel-adaptive mode, otherwise, return -1 */
+  if (ISAC_inst->CodingMode != 0) {
+    ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+    return (-1);
+  }
+
+  /* Set struct variable if enforceFrameSize is set. ISAC will then keep the */
+  /* chosen frame size.                                                      */
+  ISAC_inst->ISACenc_obj.enforceFrameSize = (enforceFrameSize != 0)? 1:0;
+
+  /* Set initial rate, if value between 10000 and 32000,                */
+  /* if rateBPS is 0, keep the default initial bottleneck value (15000) */
+  if ((rateBPS >= 10000) && (rateBPS <= 32000)) {
+    ISAC_inst->bwestimator_obj.sendBwAvg = (((uint32_t)rateBPS) << 7);
+  } else if (rateBPS != 0) {
+    ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+    return -1;
+  }
+
+  /* Set initial framesize. If enforceFrameSize is set the frame size will not change */
+  if ((frameSizeMs  == 30) || (frameSizeMs == 60)) {
+    ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * frameSizeMs);
+  } else {
+    ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+    return -1;
+  }
+
+  return 0;
+}
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ *      - ISAC_main_inst: iSAC struct
+ *
+ * Output:
+ *      - rateIndex     : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+                                         int16_t*     rateIndex)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Call function to get Bandwidth Estimate */
+  *rateIndex = WebRtcIsacfix_GetDownlinkBwIndexImpl(&ISAC_inst->bwestimator_obj);
+
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ *      - ISAC_main_inst: iSAC struct
+ *      - rateIndex     : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+                                     int16_t     rateIndex)
+{
+  int16_t err = 0;
+  ISACFIX_SubStruct *ISAC_inst;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  /* Call function to update BWE with received Bandwidth Estimate */
+  err = WebRtcIsacfix_UpdateUplinkBwRec(&ISAC_inst->bwestimator_obj, rateIndex);
+  if (err < 0) {
+    ISAC_inst->errorcode = -err;
+    return (-1);
+  }
+
+  return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ *      - encoded       : Encoded bitstream
+ *
+ * Output:
+ *      - frameLength   : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadFrameLen(const uint8_t* encoded,
+                                   size_t encoded_len_bytes,
+                                   size_t* frameLength)
+{
+  Bitstr_dec streamdata;
+  int16_t err;
+  const size_t kRequiredEncodedLenBytes = 10;
+
+  if (encoded_len_bytes < kRequiredEncodedLenBytes) {
+    return -1;
+  }
+
+  InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
+
+  read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+  /* decode frame length */
+  err = WebRtcIsacfix_DecodeFrameLen(&streamdata, frameLength);
+  if (err<0)  // error check
+    return err;
+
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ *      - encoded       : Encoded bitstream
+ *
+ * Output:
+ *      - frameLength   : Length of frame in packet (in samples)
+ *      - rateIndex     : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadBwIndex(const uint8_t* encoded,
+                                  size_t encoded_len_bytes,
+                                  int16_t* rateIndex)
+{
+  Bitstr_dec streamdata;
+  int16_t err;
+  const size_t kRequiredEncodedLenBytes = 10;
+
+  if (encoded_len_bytes < kRequiredEncodedLenBytes) {
+    return -1;
+  }
+
+  InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
+
+  read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+  /* decode frame length, needed to get to the rateIndex in the bitstream */
+  size_t frameLength;
+  err = WebRtcIsacfix_DecodeFrameLen(&streamdata, &frameLength);
+  if (err<0)  // error check
+    return err;
+
+  /* decode BW estimation */
+  err = WebRtcIsacfix_DecodeSendBandwidth(&streamdata, rateIndex);
+  if (err<0)  // error check
+    return err;
+
+  return 0;
+}
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occured in the
+ * specified instance.
+ *
+ * Input:
+ *      - ISAC_main_inst    : ISAC instance
+ *
+ * Return value             : Error code
+ */
+
+int16_t WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  return ISAC_inst->errorcode;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function returns the inst quantized iSAC send bitrate
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *
+ * Return value             : bitrate
+ */
+
+int32_t WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+  BwEstimatorstr * bw = (BwEstimatorstr*)&(ISAC_inst->bwestimator_obj);
+
+  return (int32_t) WebRtcIsacfix_GetUplinkBandwidth(bw);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *
+ * Return value             :  frame lenght in samples
+ */
+
+int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst)
+{
+  ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+  return ISAC_inst->ISACenc_obj.new_framelength;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *      - maxPayloadBytes   : maximum size of the payload in bytes
+ *                            valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value             : 0 if sucessful
+ *                           -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst,
+                                        int16_t maxPayloadBytes)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  if((maxPayloadBytes < 100) || (maxPayloadBytes > 400))
+  {
+    /* maxPayloadBytes is out of valid range */
+    return -1;
+  }
+  else
+  {
+    /* Set new absolute max, which will not change unless this function
+       is called again with a new value */
+    ISAC_inst->ISACenc_obj.maxPayloadBytes = maxPayloadBytes;
+
+    /* Set new maximum values for 30 and 60 msec packets */
+    if (maxPayloadBytes < ISAC_inst->ISACenc_obj.maxRateInBytes) {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxPayloadBytes;
+    } else {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxRateInBytes;
+    }
+
+    if ( maxPayloadBytes < (ISAC_inst->ISACenc_obj.maxRateInBytes << 1)) {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes60 = maxPayloadBytes;
+    } else {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (ISAC_inst->ISACenc_obj.maxRateInBytes << 1);
+    }
+  }
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC instance
+ *      - maxRateInBytes    : maximum rate in bits per second,
+ *                            valid values are 32000 to 53400 bits
+ *
+ * Return value             : 0 if sucessful
+ *                           -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst,
+                                 int32_t maxRate)
+{
+  ISACFIX_SubStruct *ISAC_inst;
+  int16_t maxRateInBytes;
+
+  /* typecast pointer to real structure */
+  ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+  if((maxRate < 32000) || (maxRate > 53400))
+  {
+    /* maxRate is out of valid range */
+    return -1;
+  }
+  else
+  {
+    /* Calculate maximum number of bytes per 30 msec packets for the given
+       maximum rate. Multiply with 30/1000 to get number of bits per 30 msec,
+       divide by 8 to get number of bytes per 30 msec:
+       maxRateInBytes = floor((maxRate * 30/1000) / 8); */
+    maxRateInBytes = (int16_t)( WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_MUL(maxRate, 3), 800) );
+
+    /* Store the value for usage in the WebRtcIsacfix_SetMaxPayloadSize-function */
+    ISAC_inst->ISACenc_obj.maxRateInBytes = maxRateInBytes;
+
+    /* For 30 msec packets: if the new limit is below the maximum
+       payload size, set a new limit */
+    if (maxRateInBytes < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxRateInBytes;
+    } else {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+    }
+
+    /* For 60 msec packets: if the new limit (times 2) is below the
+       maximum payload size, set a new limit */
+    if ( (maxRateInBytes << 1) < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (maxRateInBytes << 1);
+    } else {
+      ISAC_inst->ISACenc_obj.payloadLimitBytes60 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+    }
+  }
+
+  return 0;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ *      - version  : Pointer to character string
+ *
+ */
+
+void WebRtcIsacfix_version(char *version)
+{
+  strcpy(version, "3.6.0");
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice.c b/modules/audio_coding/codecs/isac/fix/source/lattice.c
new file mode 100644
index 0000000..7bbf4e0
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice.c
@@ -0,0 +1,321 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * Contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/sanitizer.h"
+
+#define LATTICE_MUL_32_32_RSFT16(a32a, a32b, b32)                  \
+  ((int32_t)(WEBRTC_SPL_MUL(a32a, b32) + (WEBRTC_SPL_MUL_16_32_RSFT16(a32b, b32))))
+/* This macro is FORBIDDEN to use elsewhere than in a function in this file and
+   its corresponding neon version. It might give unpredictable results, since a
+   general int32_t*int32_t multiplication results in a 64 bit value.
+   The result is then shifted just 16 steps to the right, giving need for 48
+   bits, i.e. in the generel case, it will NOT fit in a int32_t. In the
+   cases used in here, the int32_t will be enough, since (for a good
+   reason) the involved multiplicands aren't big enough to overflow a
+   int32_t after shifting right 16 bits. I have compared the result of a
+   multiplication between t32 and tmp32, done in two ways:
+   1) Using (int32_t) (((float)(tmp32))*((float)(tmp32b))/65536.0);
+   2) Using LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+   By running 25 files, I haven't found any bigger diff than 64 - this was in the
+   case when  method 1) gave 650235648 and 2) gave 650235712.
+*/
+
+/* Function prototype: filtering ar_g_Q0[] and ar_f_Q0[] through an AR filter
+   with coefficients cth_Q15[] and sth_Q15[].
+   Implemented for both generic and ARMv7 platforms.
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0,
+                                int16_t* ar_f_Q0,
+                                int16_t* cth_Q15,
+                                int16_t* sth_Q15,
+                                size_t order_coef);
+
+/* Inner loop used for function WebRtcIsacfix_NormLatticeFilterMa(). It does:
+   for 0 <= n < HALF_SUBFRAMELEN - 1:
+     *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+     *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+   Note, function WebRtcIsacfix_FilterMaLoopNeon and WebRtcIsacfix_FilterMaLoopC
+   are not bit-exact. The accuracy by the ARM Neon function is same or better.
+*/
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0,  // Filter coefficient
+                                 int16_t input1,  // Filter coefficient
+                                 int32_t input2,  // Inverse coeff. (1/input1)
+                                 int32_t* ptr0,   // Sample buffer
+                                 int32_t* ptr1,   // Sample buffer
+                                 int32_t* ptr2) { // Sample buffer
+  int n = 0;
+
+  // Separate the 32-bit variable input2 into two 16-bit integers (high 16 and
+  // low 16 bits), for using LATTICE_MUL_32_32_RSFT16 in the loop.
+  int16_t t16a = (int16_t)(input2 >> 16);
+  int16_t t16b = (int16_t)input2;
+  if (t16b < 0) t16a++;
+
+  // The loop filtering the samples *ptr0, *ptr1, *ptr2 with filter coefficients
+  // input0, input1, and input2.
+  for(n = 0; n < HALF_SUBFRAMELEN - 1; n++, ptr0++, ptr1++, ptr2++) {
+    int32_t tmp32a = 0;
+    int32_t tmp32b = 0;
+
+    // Calculate *ptr2 = input2 * (*ptr2 + input0 * (*ptr0));
+    tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr0); // Q15 * Q15 >> 15 = Q15
+    tmp32b = *ptr2 + tmp32a; // Q15 + Q15 = Q15
+    *ptr2 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+
+    // Calculate *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+    tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input1, *ptr0); // Q15*Q15>>15 = Q15
+    tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr2); // Q15*Q15>>15 = Q15
+    *ptr1 = tmp32a + tmp32b; // Q15 + Q15 = Q15
+  }
+}
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsacfix_NormLatticeFilterMa(size_t orderCoef,
+                                       int32_t *stateGQ15,
+                                       int16_t *lat_inQ0,
+                                       int16_t *filt_coefQ15,
+                                       int32_t *gain_lo_hiQ17,
+                                       int16_t lo_hi,
+                                       int16_t *lat_outQ9)
+{
+  int16_t sthQ15[MAX_AR_MODEL_ORDER];
+  int16_t cthQ15[MAX_AR_MODEL_ORDER];
+
+  int u, n;
+  size_t i, k;
+  int16_t temp2,temp3;
+  size_t ord_1 = orderCoef+1;
+  int32_t inv_cthQ16[MAX_AR_MODEL_ORDER];
+
+  int32_t gain32, fQtmp;
+  int16_t gain16;
+  int16_t gain_sh;
+
+  int32_t tmp32, tmp32b;
+  int32_t fQ15vec[HALF_SUBFRAMELEN];
+  int32_t gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+  int16_t sh;
+  int16_t t16a;
+  int16_t t16b;
+
+  for (u=0;u<SUBFRAMES;u++)
+  {
+    int32_t temp1 = u * HALF_SUBFRAMELEN;
+
+    /* set the Direct Form coefficients */
+    temp2 = (int16_t)(u * orderCoef);
+    temp3 = (int16_t)(2 * u + lo_hi);
+
+    /* compute lattice filter coefficients */
+    memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(int16_t));
+
+    WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+    /* compute the gain */
+    gain32 = gain_lo_hiQ17[temp3];
+    gain_sh = WebRtcSpl_NormW32(gain32);
+    gain32 <<= gain_sh;  // Q(17+gain_sh)
+
+    for (k=0;k<orderCoef;k++)
+    {
+      gain32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], gain32); //Q15*Q(17+gain_sh)>>15 = Q(17+gain_sh)
+      inv_cthQ16[k] = WebRtcSpl_DivW32W16((int32_t)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16
+    }
+    gain16 = (int16_t)(gain32 >> 16);  // Q(1+gain_sh).
+
+    /* normalized lattice filter */
+    /*****************************/
+
+    /* initial conditions */
+    for (i=0;i<HALF_SUBFRAMELEN;i++)
+    {
+      fQ15vec[i] = lat_inQ0[i + temp1] << 15;  // Q15
+      gQ15[0][i] = lat_inQ0[i + temp1] << 15;  // Q15
+    }
+
+
+    fQtmp = fQ15vec[0];
+
+    /* get the state of f&g for the first input, for all orders */
+    for (i=1;i<ord_1;i++)
+    {
+      // Calculate f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], stateGQ15[i-1]);//Q15*Q15>>15 = Q15
+      tmp32b= fQtmp + tmp32; //Q15+Q15=Q15
+      tmp32 = inv_cthQ16[i-1]; //Q16
+      t16a = (int16_t)(tmp32 >> 16);
+      t16b = (int16_t)(tmp32 - (t16a << 16));
+      if (t16b<0) t16a++;
+      tmp32 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+      fQtmp = tmp32; // Q15
+
+      // Calculate g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+      tmp32  = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[i-1], stateGQ15[i-1]); //Q15*Q15>>15 = Q15
+      tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], fQtmp); //Q15*Q15>>15 = Q15
+      tmp32  = tmp32 + tmp32b;//Q15+Q15 = Q15
+      gQ15[i][0] = tmp32; // Q15
+    }
+
+    /* filtering */
+    /* save the states */
+    for(k=0;k<orderCoef;k++)
+    {
+      // for 0 <= n < HALF_SUBFRAMELEN - 1:
+      //   f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
+      //   g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
+      WebRtcIsacfix_FilterMaLoopFix(sthQ15[k], cthQ15[k], inv_cthQ16[k],
+                                    &gQ15[k][0], &gQ15[k+1][1], &fQ15vec[1]);
+    }
+
+    fQ15vec[0] = fQtmp;
+
+    for(n=0;n<HALF_SUBFRAMELEN;n++)
+    {
+      //gain32 >>= gain_sh; // Q(17+gain_sh) -> Q17
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(gain16, fQ15vec[n]); //Q(1+gain_sh)*Q15>>16 = Q(gain_sh)
+      sh = 9-gain_sh; //number of needed shifts to reach Q9
+      t16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh);
+      lat_outQ9[n + temp1] = t16a;
+    }
+
+    /* save the states */
+    for (i=0;i<ord_1;i++)
+    {
+      stateGQ15[i] = gQ15[i][HALF_SUBFRAMELEN-1];
+    }
+    //process next frame
+  }
+
+  return;
+}
+
+// Left shift of an int32_t that's allowed to overflow. (It's still undefined
+// behavior, so not a good idea; this just makes UBSan ignore the violation, so
+// that our old code can continue to do what it's always been doing.)
+static inline int32_t RTC_NO_SANITIZE("shift")
+    OverflowingLShiftS32(int32_t x, int shift) {
+  return x << shift;
+}
+
+/* ----------------AR filter-------------------------*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsacfix_NormLatticeFilterAr(size_t orderCoef,
+                                       int16_t *stateGQ0,
+                                       int32_t *lat_inQ25,
+                                       int16_t *filt_coefQ15,
+                                       int32_t *gain_lo_hiQ17,
+                                       int16_t lo_hi,
+                                       int16_t *lat_outQ0)
+{
+  size_t ii, k, i;
+  int n, u;
+  int16_t sthQ15[MAX_AR_MODEL_ORDER];
+  int16_t cthQ15[MAX_AR_MODEL_ORDER];
+  int32_t tmp32;
+
+
+  int16_t tmpAR;
+  int16_t ARfQ0vec[HALF_SUBFRAMELEN];
+  int16_t ARgQ0vec[MAX_AR_MODEL_ORDER+1];
+
+  int32_t inv_gain32;
+  int16_t inv_gain16;
+  int16_t den16;
+  int16_t sh;
+
+  int16_t temp2,temp3;
+  size_t ord_1 = orderCoef+1;
+
+  for (u=0;u<SUBFRAMES;u++)
+  {
+    int32_t temp1 = u * HALF_SUBFRAMELEN;
+
+    //set the denominator and numerator of the Direct Form
+    temp2 = (int16_t)(u * orderCoef);
+    temp3 = (int16_t)(2 * u + lo_hi);
+
+    for (ii=0; ii<orderCoef; ii++) {
+      sthQ15[ii] = filt_coefQ15[temp2+ii];
+    }
+
+    WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+    // Originally, this line was assumed to never overflow, since "[s]imulation
+    // of the 25 files shows that maximum value in the vector gain_lo_hiQ17[]
+    // is 441344, which means that it is log2((2^31)/441344) = 12.2 shifting
+    // bits from saturation. Therefore, it should be safe to use Q27 instead of
+    // Q17." However, a fuzzer test succeeded in provoking an overflow here,
+    // which we ignore on the theory that only "abnormal" inputs cause
+    // overflow.
+    tmp32 = OverflowingLShiftS32(gain_lo_hiQ17[temp3], 10);  // Q27
+
+    for (k=0;k<orderCoef;k++) {
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], tmp32); // Q15*Q27>>15 = Q27
+    }
+
+    sh = WebRtcSpl_NormW32(tmp32); // tmp32 is the gain
+    den16 = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits)
+    inv_gain32 = WebRtcSpl_DivW32W16((int32_t)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh)
+
+    //initial conditions
+    inv_gain16 = (int16_t)(inv_gain32 >> 2);  // 1/gain in Q(20-sh-2) = Q(18-sh)
+
+    for (i=0;i<HALF_SUBFRAMELEN;i++)
+    {
+      tmp32 = OverflowingLShiftS32(lat_inQ25[i + temp1], 1);  // Q25->Q26
+      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(inv_gain16, tmp32); //lat_in[]*inv_gain in (Q(18-sh)*Q26)>>16 = Q(28-sh)
+      tmp32 = WEBRTC_SPL_SHIFT_W32(tmp32, -(28-sh)); // lat_in[]*inv_gain in Q0
+
+      ARfQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+    }
+
+    // Get the state of f & g for the first input, for all orders.
+    for (i = orderCoef; i > 0; i--)
+    {
+      tmp32 = (cthQ15[i - 1] * ARfQ0vec[0] - sthQ15[i - 1] * stateGQ0[i - 1] +
+               16384) >> 15;
+      tmpAR = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+
+      tmp32 = (sthQ15[i - 1] * ARfQ0vec[0] + cthQ15[i - 1] * stateGQ0[i - 1] +
+               16384) >> 15;
+      ARgQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+      ARfQ0vec[0] = tmpAR;
+    }
+    ARgQ0vec[0] = ARfQ0vec[0];
+
+    // Filter ARgQ0vec[] and ARfQ0vec[] through coefficients cthQ15[] and sthQ15[].
+    WebRtcIsacfix_FilterArLoop(ARgQ0vec, ARfQ0vec, cthQ15, sthQ15, orderCoef);
+
+    for(n=0;n<HALF_SUBFRAMELEN;n++)
+    {
+      lat_outQ0[n + temp1] = ARfQ0vec[n];
+    }
+
+
+    /* cannot use memcpy in the following */
+
+    for (i=0;i<ord_1;i++)
+    {
+      stateGQ0[i] = ARgQ0vec[i];
+    }
+  }
+
+  return;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S b/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
new file mode 100644
index 0000000..4c63227
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
@@ -0,0 +1,77 @@
+@
+@ Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+@
+@ Use of this source code is governed by a BSD-style license
+@ that can be found in the LICENSE file in the root of the source
+@ tree. An additional intellectual property rights grant can be found
+@ in the file PATENTS.  All contributing project authors may
+@ be found in the AUTHORS file in the root of the source tree.
+@
+
+@ Contains a function for the core loop in the normalized lattice AR
+@ filter routine for iSAC codec, optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in lattic_c.c
+@
+@ Register usage:
+@
+@ r0:  &ar_g_Q0
+@ r1:  &ar_f_Q0
+@ r2:  &cth_Q15
+@ r3:  &sth_Q15
+@ r4:  out loop counter
+@ r5:  tmpAR
+@ r9:  inner loop counter
+@ r12: constant #16384
+@ r6, r7, r8, r10, r11: scratch
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/system/asm_defines.h"
+
+GLOBAL_FUNCTION WebRtcIsacfix_FilterArLoop
+.align  2
+DEFINE_FUNCTION WebRtcIsacfix_FilterArLoop
+  push    {r4-r11}
+
+  add     r1, #2                 @ &ar_f_Q0[1]
+  mov     r12, #16384
+  mov     r4, #HALF_SUBFRAMELEN
+  sub     r4, #1                 @ Outer loop counter = HALF_SUBFRAMELEN - 1
+
+HALF_SUBFRAME_LOOP:  @ for (n = 0; n < HALF_SUBFRAMELEN - 1; n++)
+
+  ldr     r9, [sp, #32]          @ Restore the inner loop counter to order_coef
+  ldrh    r5, [r1]               @ tmpAR = ar_f_Q0[n+1]
+  add     r0, r9, asl #1         @ Restore r0 to &ar_g_Q0[order_coef]
+  add     r2, r9, asl #1         @ Restore r2 to &cth_Q15[order_coef]
+  add     r3, r9, asl #1         @ Restore r3 to &sth_Q15[order_coef]
+
+ORDER_COEF_LOOP:  @ for (k = order_coef; k > 0; k--)
+
+  ldrh    r7, [r3, #-2]!         @ sth_Q15[k - 1]
+  ldrh    r6, [r2, #-2]!         @ cth_Q15[k - 1]
+
+  ldrh    r8, [r0, #-2]          @ ar_g_Q0[k - 1]
+  smlabb  r11, r7, r5, r12       @ sth_Q15[k - 1] * tmpAR + 16384
+  smlabb  r10, r6, r5, r12       @ cth_Q15[k - 1] * tmpAR + 16384
+  smulbb  r7, r7, r8             @ sth_Q15[k - 1] * ar_g_Q0[k - 1]
+  smlabb  r11, r6, r8, r11       @ cth_Q15[k - 1] * ar_g_Q0[k - 1] +
+                                 @     (sth_Q15[k - 1] * tmpAR + 16384)
+
+  sub     r10, r10, r7           @ cth_Q15[k - 1] * tmpAR + 16384 -
+                                 @     (sth_Q15[k - 1] * ar_g_Q0[k - 1])
+  ssat    r11, #16, r11, asr #15
+  ssat    r5, #16, r10, asr #15
+  strh    r11, [r0], #-2         @ Output: ar_g_Q0[k]
+
+  subs    r9, #1
+  bgt     ORDER_COEF_LOOP
+
+  strh    r5, [r0]               @ Output: ar_g_Q0[0] = tmpAR;
+  strh    r5, [r1], #2           @ Output: ar_f_Q0[n+1] = tmpAR;
+
+  subs    r4, #1
+  bne     HALF_SUBFRAME_LOOP
+
+  pop     {r4-r11}
+  bx      lr
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_c.c b/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
new file mode 100644
index 0000000..4340661
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * Contains the core loop function for the lattice filter AR routine
+ * for iSAC codec.
+ *
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
+ * cth_Q15[] and sth_Q15[].
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0,     // Input samples
+                                int16_t* ar_f_Q0,     // Input samples
+                                int16_t* cth_Q15,     // Filter coefficients
+                                int16_t* sth_Q15,     // Filter coefficients
+                                size_t order_coef) { // order of the filter
+  int n = 0;
+
+  for (n = 0; n < HALF_SUBFRAMELEN - 1; n++) {
+    size_t k = 0;
+    int16_t tmpAR = 0;
+    int32_t tmp32 = 0;
+    int32_t tmp32_2 = 0;
+
+    tmpAR = ar_f_Q0[n + 1];
+    for (k = order_coef; k > 0; k--) {
+      tmp32 = (cth_Q15[k - 1] * tmpAR - sth_Q15[k - 1] * ar_g_Q0[k - 1] +
+               16384) >> 15;
+      tmp32_2 = (sth_Q15[k - 1] * tmpAR + cth_Q15[k - 1] * ar_g_Q0[k - 1] +
+                 16384) >> 15;
+      tmpAR   = (int16_t)WebRtcSpl_SatW32ToW16(tmp32);
+      ar_g_Q0[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32_2);
+    }
+    ar_f_Q0[n + 1] = tmpAR;
+    ar_g_Q0[0] = tmpAR;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c b/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
new file mode 100644
index 0000000..3189726
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
@@ -0,0 +1,329 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
+// cth_Q15[] and sth_Q15[].
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0,     // Input samples
+                                int16_t* ar_f_Q0,     // Input samples
+                                int16_t* cth_Q15,     // Filter coefficients
+                                int16_t* sth_Q15,     // Filter coefficients
+                                size_t order_coef) { // order of the filter
+  int n = 0;
+
+  for (n = 0; n < HALF_SUBFRAMELEN - 1; n++) {
+    int count = (int)(order_coef - 1);
+    int offset;
+#if !defined(MIPS_DSP_R1_LE)
+    int16_t* tmp_cth;
+    int16_t* tmp_sth;
+    int16_t* tmp_arg;
+    int32_t max_q16 = 0x7fff;
+    int32_t min_q16 = 0xffff8000;
+#endif
+    // Declare variables used as temporary registers.
+    int32_t r0, r1, r2, t0, t1, t2, t_ar;
+
+    __asm __volatile (
+      ".set          push                                                \n\t"
+      ".set          noreorder                                           \n\t"
+      "bltz          %[count],     2f                                    \n\t"
+      " lh           %[t_ar],      0(%[tmp])                             \n\t"
+      // Inner loop
+     "1:                                                                 \n\t"
+      "sll           %[offset],    %[count],               1             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "lhx           %[r0],        %[offset](%[cth_Q15])                 \n\t"
+      "lhx           %[r1],        %[offset](%[sth_Q15])                 \n\t"
+      "lhx           %[r2],        %[offset](%[ar_g_Q0])                 \n\t"
+#else
+      "addu          %[tmp_cth],   %[cth_Q15],             %[offset]     \n\t"
+      "addu          %[tmp_sth],   %[sth_Q15],             %[offset]     \n\t"
+      "addu          %[tmp_arg],   %[ar_g_Q0],             %[offset]     \n\t"
+      "lh            %[r0],        0(%[tmp_cth])                         \n\t"
+      "lh            %[r1],        0(%[tmp_sth])                         \n\t"
+      "lh            %[r2],        0(%[tmp_arg])                         \n\t"
+#endif
+      "mul           %[t0],        %[r0],                  %[t_ar]       \n\t"
+      "mul           %[t1],        %[r1],                  %[t_ar]       \n\t"
+      "mul           %[t2],        %[r1],                  %[r2]         \n\t"
+      "mul           %[r0],        %[r0],                  %[r2]         \n\t"
+      "subu          %[t0],        %[t0],                  %[t2]         \n\t"
+      "addu          %[t1],        %[t1],                  %[r0]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "shra_r.w      %[t1],        %[t1],                  15            \n\t"
+      "shra_r.w      %[t0],        %[t0],                  15            \n\t"
+#else
+      "addiu         %[t1],        %[t1],                  0x4000        \n\t"
+      "sra           %[t1],        %[t1],                  15            \n\t"
+      "addiu         %[t0],        %[t0],                  0x4000        \n\t"
+      "sra           %[t0],        %[t0],                  15            \n\t"
+#endif
+      "addiu         %[offset],    %[offset],              2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "shll_s.w      %[t1],        %[t1],                  16            \n\t"
+      "shll_s.w      %[t_ar],      %[t0],                  16            \n\t"
+#else
+      "slt           %[r0],        %[t1],                  %[max_q16]    \n\t"
+      "slt           %[r1],        %[t0],                  %[max_q16]    \n\t"
+      "movz          %[t1],        %[max_q16],             %[r0]         \n\t"
+      "movz          %[t0],        %[max_q16],             %[r1]         \n\t"
+#endif
+      "addu          %[offset],    %[offset],              %[ar_g_Q0]    \n\t"
+#if defined(MIPS_DSP_R1_LE)
+      "sra           %[t1],        %[t1],                  16            \n\t"
+      "sra           %[t_ar],      %[t_ar],                16            \n\t"
+#else
+      "slt           %[r0],        %[t1],                  %[min_q16]    \n\t"
+      "slt           %[r1],        %[t0],                  %[min_q16]    \n\t"
+      "movn          %[t1],        %[min_q16],             %[r0]         \n\t"
+      "movn          %[t0],        %[min_q16],             %[r1]         \n\t"
+      "addu          %[t_ar],      $zero,                  %[t0]         \n\t"
+#endif
+      "sh            %[t1],        0(%[offset])                          \n\t"
+      "bgtz          %[count],     1b                                    \n\t"
+      " addiu        %[count],     %[count],               -1            \n\t"
+     "2:                                                                 \n\t"
+      "sh            %[t_ar],      0(%[tmp])                             \n\t"
+      "sh            %[t_ar],      0(%[ar_g_Q0])                         \n\t"
+      ".set          pop                                                 \n\t"
+      : [t_ar] "=&r" (t_ar), [count] "+r" (count), [offset] "=&r" (offset),
+        [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [t0] "=&r" (t0),
+#if !defined(MIPS_DSP_R1_LE)
+        [tmp_cth] "=&r" (tmp_cth), [tmp_sth] "=&r" (tmp_sth),
+        [tmp_arg] "=&r" (tmp_arg),
+#endif
+        [t1] "=&r" (t1), [t2] "=&r" (t2)
+      : [tmp] "r" (&ar_f_Q0[n+1]), [cth_Q15] "r" (cth_Q15),
+#if !defined(MIPS_DSP_R1_LE)
+        [max_q16] "r" (max_q16), [min_q16] "r" (min_q16),
+#endif
+        [sth_Q15] "r" (sth_Q15), [ar_g_Q0] "r" (ar_g_Q0)
+      : "memory", "hi", "lo"
+    );
+  }
+}
+
+// MIPS optimization of the inner loop used for function
+// WebRtcIsacfix_NormLatticeFilterMa(). It does:
+//
+// for 0 <= n < HALF_SUBFRAMELEN - 1:
+//   *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+//   *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+//
+// Note, function WebRtcIsacfix_FilterMaLoopMIPS and WebRtcIsacfix_FilterMaLoopC
+// are not bit-exact. The accuracy of the MIPS function is same or better.
+void WebRtcIsacfix_FilterMaLoopMIPS(int16_t input0,  // Filter coefficient
+                                    int16_t input1,  // Filter coefficient
+                                    int32_t input2,  // Inverse coeff (1/input1)
+                                    int32_t* ptr0,   // Sample buffer
+                                    int32_t* ptr1,   // Sample buffer
+                                    int32_t* ptr2) { // Sample buffer
+#if defined(MIPS_DSP_R2_LE)
+  // MIPS DSPR2 version. 4 available accumulators allows loop unrolling 4 times.
+  // This variant is not bit-exact with WebRtcIsacfix_FilterMaLoopC, since we
+  // are exploiting 64-bit accumulators. The accuracy of the MIPS DSPR2 function
+  // is same or better.
+  int n = (HALF_SUBFRAMELEN - 1) >> 2;
+  int m = (HALF_SUBFRAMELEN - 1) & 3;
+
+  int r0, r1, r2, r3;
+  int t0, t1, t2, t3;
+  int s0, s1, s2, s3;
+
+  __asm __volatile (
+    ".set          push                                      \n\t"
+    ".set          noreorder                                 \n\t"
+   "1:                                                       \n\t"
+    "lw            %[r0],        0(%[ptr0])                  \n\t"
+    "lw            %[r1],        4(%[ptr0])                  \n\t"
+    "lw            %[r2],        8(%[ptr0])                  \n\t"
+    "lw            %[r3],        12(%[ptr0])                 \n\t"
+    "mult          $ac0,         %[r0],        %[input0]     \n\t"
+    "mult          $ac1,         %[r1],        %[input0]     \n\t"
+    "mult          $ac2,         %[r2],        %[input0]     \n\t"
+    "mult          $ac3,         %[r3],        %[input0]     \n\t"
+    "lw            %[t0],        0(%[ptr2])                  \n\t"
+    "extr_rs.w     %[s0],        $ac0,         15            \n\t"
+    "extr_rs.w     %[s1],        $ac1,         15            \n\t"
+    "extr_rs.w     %[s2],        $ac2,         15            \n\t"
+    "extr_rs.w     %[s3],        $ac3,         15            \n\t"
+    "lw            %[t1],        4(%[ptr2])                  \n\t"
+    "lw            %[t2],        8(%[ptr2])                  \n\t"
+    "lw            %[t3],        12(%[ptr2])                 \n\t"
+    "addu          %[t0],        %[t0],        %[s0]         \n\t"
+    "addu          %[t1],        %[t1],        %[s1]         \n\t"
+    "addu          %[t2],        %[t2],        %[s2]         \n\t"
+    "addu          %[t3],        %[t3],        %[s3]         \n\t"
+    "mult          $ac0,         %[t0],        %[input2]     \n\t"
+    "mult          $ac1,         %[t1],        %[input2]     \n\t"
+    "mult          $ac2,         %[t2],        %[input2]     \n\t"
+    "mult          $ac3,         %[t3],        %[input2]     \n\t"
+    "addiu         %[ptr0],      %[ptr0],      16            \n\t"
+    "extr_rs.w     %[t0],        $ac0,         16            \n\t"
+    "extr_rs.w     %[t1],        $ac1,         16            \n\t"
+    "extr_rs.w     %[t2],        $ac2,         16            \n\t"
+    "extr_rs.w     %[t3],        $ac3,         16            \n\t"
+    "addiu         %[n],         %[n],         -1            \n\t"
+    "mult          $ac0,         %[r0],        %[input1]     \n\t"
+    "mult          $ac1,         %[r1],        %[input1]     \n\t"
+    "mult          $ac2,         %[r2],        %[input1]     \n\t"
+    "mult          $ac3,         %[r3],        %[input1]     \n\t"
+    "sw            %[t0],        0(%[ptr2])                  \n\t"
+    "extr_rs.w     %[s0],        $ac0,         15            \n\t"
+    "extr_rs.w     %[s1],        $ac1,         15            \n\t"
+    "extr_rs.w     %[s2],        $ac2,         15            \n\t"
+    "extr_rs.w     %[s3],        $ac3,         15            \n\t"
+    "sw            %[t1],        4(%[ptr2])                  \n\t"
+    "sw            %[t2],        8(%[ptr2])                  \n\t"
+    "sw            %[t3],        12(%[ptr2])                 \n\t"
+    "mult          $ac0,         %[t0],        %[input0]     \n\t"
+    "mult          $ac1,         %[t1],        %[input0]     \n\t"
+    "mult          $ac2,         %[t2],        %[input0]     \n\t"
+    "mult          $ac3,         %[t3],        %[input0]     \n\t"
+    "addiu         %[ptr2],      %[ptr2],      16            \n\t"
+    "extr_rs.w     %[t0],        $ac0,         15            \n\t"
+    "extr_rs.w     %[t1],        $ac1,         15            \n\t"
+    "extr_rs.w     %[t2],        $ac2,         15            \n\t"
+    "extr_rs.w     %[t3],        $ac3,         15            \n\t"
+    "addu          %[t0],        %[t0],        %[s0]         \n\t"
+    "addu          %[t1],        %[t1],        %[s1]         \n\t"
+    "addu          %[t2],        %[t2],        %[s2]         \n\t"
+    "addu          %[t3],        %[t3],        %[s3]         \n\t"
+    "sw            %[t0],        0(%[ptr1])                  \n\t"
+    "sw            %[t1],        4(%[ptr1])                  \n\t"
+    "sw            %[t2],        8(%[ptr1])                  \n\t"
+    "sw            %[t3],        12(%[ptr1])                 \n\t"
+    "bgtz          %[n],         1b                          \n\t"
+    " addiu        %[ptr1],      %[ptr1],      16            \n\t"
+    "beq           %[m],         %0,           3f            \n\t"
+    " nop                                                    \n\t"
+   "2:                                                       \n\t"
+    "lw            %[r0],        0(%[ptr0])                  \n\t"
+    "lw            %[t0],        0(%[ptr2])                  \n\t"
+    "addiu         %[ptr0],      %[ptr0],      4             \n\t"
+    "mult          $ac0,         %[r0],        %[input0]     \n\t"
+    "mult          $ac1,         %[r0],        %[input1]     \n\t"
+    "extr_rs.w     %[r1],        $ac0,         15            \n\t"
+    "extr_rs.w     %[t1],        $ac1,         15            \n\t"
+    "addu          %[t0],        %[t0],        %[r1]         \n\t"
+    "mult          $ac0,         %[t0],        %[input2]     \n\t"
+    "extr_rs.w     %[t0],        $ac0,         16            \n\t"
+    "sw            %[t0],        0(%[ptr2])                  \n\t"
+    "mult          $ac0,         %[t0],        %[input0]     \n\t"
+    "addiu         %[ptr2],      %[ptr2],      4             \n\t"
+    "addiu         %[m],         %[m],         -1            \n\t"
+    "extr_rs.w     %[t0],        $ac0,         15            \n\t"
+    "addu          %[t0],        %[t0],        %[t1]         \n\t"
+    "sw            %[t0],        0(%[ptr1])                  \n\t"
+    "bgtz          %[m],         2b                          \n\t"
+    " addiu        %[ptr1],      %[ptr1],      4             \n\t"
+   "3:                                                       \n\t"
+    ".set          pop                                       \n\t"
+    : [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+      [r3] "=&r" (r3), [t0] "=&r" (t0), [t1] "=&r" (t1),
+      [t2] "=&r" (t2), [t3] "=&r" (t3), [s0] "=&r" (s0),
+      [s1] "=&r" (s1), [s2] "=&r" (s2), [s3] "=&r" (s3),
+      [ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1), [m] "+r" (m),
+      [ptr2] "+r" (ptr2), [n] "+r" (n)
+    : [input0] "r" (input0), [input1] "r" (input1),
+      [input2] "r" (input2)
+    : "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi",
+      "$ac2lo", "$ac3hi", "$ac3lo"
+  );
+#else
+  // Non-DSPR2 version of the function. Avoiding the accumulator usage due to
+  // large latencies. This variant is bit-exact with C code.
+  int n = HALF_SUBFRAMELEN - 1;
+  int32_t t16a, t16b;
+  int32_t r0, r1, r2, r3, r4;
+
+  __asm __volatile (
+    ".set          push                                      \n\t"
+    ".set          noreorder                                 \n\t"
+    "sra           %[t16a],      %[input2],     16           \n\t"
+    "andi          %[t16b],      %[input2],     0xFFFF       \n\t"
+#if defined(MIPS32R2_LE)
+    "seh           %[t16b],      %[t16b]                     \n\t"
+    "seh           %[input0],    %[input0]                   \n\t"
+    "seh           %[input1],    %[input1]                   \n\t"
+#else
+    "sll           %[t16b],      %[t16b],       16           \n\t"
+    "sra           %[t16b],      %[t16b],       16           \n\t"
+    "sll           %[input0],    %[input0],     16           \n\t"
+    "sra           %[input0],    %[input0],     16           \n\t"
+    "sll           %[input1],    %[input1],     16           \n\t"
+    "sra           %[input1],    %[input1],     16           \n\t"
+#endif
+    "addiu         %[r0],        %[t16a],       1            \n\t"
+    "slt           %[r1],        %[t16b],       $zero        \n\t"
+    "movn          %[t16a],      %[r0],         %[r1]        \n\t"
+   "1:                                                       \n\t"
+    "lw            %[r0],        0(%[ptr0])                  \n\t"
+    "lw            %[r1],        0(%[ptr2])                  \n\t"
+    "addiu         %[ptr0],      %[ptr0],       4            \n\t"
+    "sra           %[r2],        %[r0],         16           \n\t"
+    "andi          %[r0],        %[r0],         0xFFFF       \n\t"
+    "mul           %[r3],        %[r2],         %[input0]    \n\t"
+    "mul           %[r4],        %[r0],         %[input0]    \n\t"
+    "mul           %[r2],        %[r2],         %[input1]    \n\t"
+    "mul           %[r0],        %[r0],         %[input1]    \n\t"
+    "addiu         %[ptr2],      %[ptr2],       4            \n\t"
+    "sll           %[r3],        %[r3],         1            \n\t"
+    "sra           %[r4],        %[r4],         1            \n\t"
+    "addiu         %[r4],        %[r4],         0x2000       \n\t"
+    "sra           %[r4],        %[r4],         14           \n\t"
+    "addu          %[r3],        %[r3],         %[r4]        \n\t"
+    "addu          %[r1],        %[r1],         %[r3]        \n\t"
+    "sra           %[r3],        %[r1],         16           \n\t"
+    "andi          %[r4],        %[r1],         0xFFFF       \n\t"
+    "sra           %[r4],        %[r4],         1            \n\t"
+    "mul           %[r1],        %[r1],         %[t16a]      \n\t"
+    "mul           %[r3],        %[r3],         %[t16b]      \n\t"
+    "mul           %[r4],        %[r4],         %[t16b]      \n\t"
+    "sll           %[r2],        %[r2],         1            \n\t"
+    "sra           %[r0],        %[r0],         1            \n\t"
+    "addiu         %[r0],        %[r0],         0x2000       \n\t"
+    "sra           %[r0],        %[r0],         14           \n\t"
+    "addu          %[r0],        %[r0],         %[r2]        \n\t"
+    "addiu         %[n],         %[n],          -1           \n\t"
+    "addu          %[r1],        %[r1],         %[r3]        \n\t"
+    "addiu         %[r4],        %[r4],         0x4000       \n\t"
+    "sra           %[r4],        %[r4],         15           \n\t"
+    "addu          %[r1],        %[r1],         %[r4]        \n\t"
+    "sra           %[r2],        %[r1],         16           \n\t"
+    "andi          %[r3],        %[r1],         0xFFFF       \n\t"
+    "mul           %[r3],        %[r3],         %[input0]    \n\t"
+    "mul           %[r2],        %[r2],         %[input0]    \n\t"
+    "sw            %[r1],        -4(%[ptr2])                 \n\t"
+    "sra           %[r3],        %[r3],         1            \n\t"
+    "addiu         %[r3],        %[r3],         0x2000       \n\t"
+    "sra           %[r3],        %[r3],         14           \n\t"
+    "addu          %[r0],        %[r0],         %[r3]        \n\t"
+    "sll           %[r2],        %[r2],         1            \n\t"
+    "addu          %[r0],        %[r0],         %[r2]        \n\t"
+    "sw            %[r0],        0(%[ptr1])                  \n\t"
+    "bgtz          %[n],         1b                          \n\t"
+    " addiu        %[ptr1],      %[ptr1],       4            \n\t"
+    ".set          pop                                       \n\t"
+    : [t16a] "=&r" (t16a), [t16b] "=&r" (t16b), [r0] "=&r" (r0),
+      [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+      [r4] "=&r" (r4), [ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1),
+      [ptr2] "+r" (ptr2), [n] "+r" (n)
+    : [input0] "r" (input0), [input1] "r" (input1),
+      [input2] "r" (input2)
+    : "hi", "lo", "memory"
+  );
+#endif
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c b/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
new file mode 100644
index 0000000..8ea9b63
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
@@ -0,0 +1,195 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Contains a function for the core loop in the normalized lattice MA
+// filter routine for iSAC codec, optimized for ARM Neon platform.
+// It does:
+//  for 0 <= n < HALF_SUBFRAMELEN - 1:
+//    *ptr2 = input2 * ((*ptr2) + input0 * (*ptr0));
+//    *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+// Output is not bit-exact with the reference C code, due to the replacement
+// of WEBRTC_SPL_MUL_16_32_RSFT15 and LATTICE_MUL_32_32_RSFT16 with Neon
+// instructions. The difference should not be bigger than 1.
+void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,  // Filter coefficient
+                                    int16_t input1,  // Filter coefficient
+                                    int32_t input2,  // Inverse coefficient
+                                    int32_t* ptr0,   // Sample buffer
+                                    int32_t* ptr1,   // Sample buffer
+                                    int32_t* ptr2)   // Sample buffer
+{
+  int n = 0;
+  int loop = (HALF_SUBFRAMELEN - 1) >> 3;
+  int loop_tail = (HALF_SUBFRAMELEN - 1) & 0x7;
+
+  int32x4_t input0_v = vdupq_n_s32((int32_t)input0 << 16);
+  int32x4_t input1_v = vdupq_n_s32((int32_t)input1 << 16);
+  int32x4_t input2_v = vdupq_n_s32(input2);
+  int32x4_t tmp0a, tmp1a, tmp2a, tmp3a;
+  int32x4_t tmp0b, tmp1b, tmp2b, tmp3b;
+  int32x4_t ptr0va, ptr1va, ptr2va;
+  int32x4_t ptr0vb, ptr1vb, ptr2vb;
+
+  int64x2_t tmp2al_low, tmp2al_high, tmp2bl_low, tmp2bl_high;
+  // Unroll to process 8 samples at once.
+  for (n = 0; n < loop; n++) {
+    ptr0va = vld1q_s32(ptr0);
+    ptr0vb = vld1q_s32(ptr0 + 4);
+    ptr0 += 8;
+
+    ptr2va = vld1q_s32(ptr2);
+    ptr2vb = vld1q_s32(ptr2 + 4);
+
+    // Calculate tmp0 = (*ptr0) * input0.
+    tmp0a = vqrdmulhq_s32(ptr0va, input0_v);
+    tmp0b = vqrdmulhq_s32(ptr0vb, input0_v);
+
+    // Calculate tmp1 = (*ptr0) * input1.
+    tmp1a = vqrdmulhq_s32(ptr0va, input1_v);
+    tmp1b = vqrdmulhq_s32(ptr0vb, input1_v);
+
+    // Calculate tmp2 = tmp0 + *(ptr2).
+    tmp2a = vaddq_s32(tmp0a, ptr2va);
+    tmp2b = vaddq_s32(tmp0b, ptr2vb);
+
+    // Calculate *ptr2 = input2 * tmp2.
+    tmp2al_low = vmull_s32(vget_low_s32(tmp2a), vget_low_s32(input2_v));
+#if defined(WEBRTC_ARCH_ARM64)
+    tmp2al_high = vmull_high_s32(tmp2a, input2_v);
+#else
+    tmp2al_high = vmull_s32(vget_high_s32(tmp2a), vget_high_s32(input2_v));
+#endif
+    ptr2va = vcombine_s32(vrshrn_n_s64(tmp2al_low, 16),
+                          vrshrn_n_s64(tmp2al_high, 16));
+
+    tmp2bl_low = vmull_s32(vget_low_s32(tmp2b), vget_low_s32(input2_v));
+#if defined(WEBRTC_ARCH_ARM64)
+    tmp2bl_high = vmull_high_s32(tmp2b, input2_v);
+#else
+    tmp2bl_high = vmull_s32(vget_high_s32(tmp2b), vget_high_s32(input2_v));
+#endif
+    ptr2vb = vcombine_s32(vrshrn_n_s64(tmp2bl_low, 16),
+                          vrshrn_n_s64(tmp2bl_high, 16));
+
+    vst1q_s32(ptr2, ptr2va);
+    vst1q_s32(ptr2 + 4, ptr2vb);
+    ptr2 += 8;
+
+    // Calculate tmp3 = ptr2v * input0.
+    tmp3a = vqrdmulhq_s32(ptr2va, input0_v);
+    tmp3b = vqrdmulhq_s32(ptr2vb, input0_v);
+
+    // Calculate *ptr1 = tmp1 + tmp3.
+    ptr1va = vaddq_s32(tmp1a, tmp3a);
+    ptr1vb = vaddq_s32(tmp1b, tmp3b);
+
+    vst1q_s32(ptr1, ptr1va);
+    vst1q_s32(ptr1 + 4, ptr1vb);
+    ptr1 += 8;
+  }
+
+  // Process four more samples.
+  if (loop_tail & 0x4) {
+    ptr0va = vld1q_s32(ptr0);
+    ptr2va = vld1q_s32(ptr2);
+    ptr0 += 4;
+
+    // Calculate tmp0 = (*ptr0) * input0.
+    tmp0a = vqrdmulhq_s32(ptr0va, input0_v);
+
+    // Calculate tmp1 = (*ptr0) * input1.
+    tmp1a = vqrdmulhq_s32(ptr0va, input1_v);
+
+    // Calculate tmp2 = tmp0 + *(ptr2).
+    tmp2a = vaddq_s32(tmp0a, ptr2va);
+
+    // Calculate *ptr2 = input2 * tmp2.
+    tmp2al_low = vmull_s32(vget_low_s32(tmp2a), vget_low_s32(input2_v));
+
+#if defined(WEBRTC_ARCH_ARM64)
+    tmp2al_high = vmull_high_s32(tmp2a, input2_v);
+#else
+    tmp2al_high = vmull_s32(vget_high_s32(tmp2a), vget_high_s32(input2_v));
+#endif
+    ptr2va = vcombine_s32(vrshrn_n_s64(tmp2al_low, 16),
+                          vrshrn_n_s64(tmp2al_high, 16));
+
+    vst1q_s32(ptr2, ptr2va);
+    ptr2 += 4;
+
+    // Calculate tmp3 = *(ptr2) * input0.
+    tmp3a = vqrdmulhq_s32(ptr2va, input0_v);
+
+    // Calculate *ptr1 = tmp1 + tmp3.
+    ptr1va = vaddq_s32(tmp1a, tmp3a);
+
+    vst1q_s32(ptr1, ptr1va);
+    ptr1 += 4;
+  }
+
+  // Process two more samples.
+  if (loop_tail & 0x2) {
+    int32x2_t ptr0v_tail, ptr2v_tail, ptr1v_tail;
+    int32x2_t tmp0_tail, tmp1_tail, tmp2_tail, tmp3_tail;
+    int64x2_t tmp2l_tail;
+    ptr0v_tail = vld1_s32(ptr0);
+    ptr2v_tail = vld1_s32(ptr2);
+    ptr0 += 2;
+
+    // Calculate tmp0 = (*ptr0) * input0.
+    tmp0_tail = vqrdmulh_s32(ptr0v_tail, vget_low_s32(input0_v));
+
+    // Calculate tmp1 = (*ptr0) * input1.
+    tmp1_tail = vqrdmulh_s32(ptr0v_tail, vget_low_s32(input1_v));
+
+    // Calculate tmp2 = tmp0 + *(ptr2).
+    tmp2_tail = vadd_s32(tmp0_tail, ptr2v_tail);
+
+    // Calculate *ptr2 = input2 * tmp2.
+    tmp2l_tail = vmull_s32(tmp2_tail, vget_low_s32(input2_v));
+    ptr2v_tail = vrshrn_n_s64(tmp2l_tail, 16);
+
+    vst1_s32(ptr2, ptr2v_tail);
+    ptr2 += 2;
+
+    // Calculate tmp3 = *(ptr2) * input0.
+    tmp3_tail = vqrdmulh_s32(ptr2v_tail, vget_low_s32(input0_v));
+
+    // Calculate *ptr1 = tmp1 + tmp3.
+    ptr1v_tail = vadd_s32(tmp1_tail, tmp3_tail);
+
+    vst1_s32(ptr1, ptr1v_tail);
+    ptr1 += 2;
+  }
+
+  // Process one more sample.
+  if (loop_tail & 0x1) {
+    int16_t t16a = (int16_t)(input2 >> 16);
+    int16_t t16b = (int16_t)input2;
+    if (t16b < 0) t16a++;
+    int32_t tmp32a;
+    int32_t tmp32b;
+
+    // Calculate *ptr2 = input2 * (*ptr2 + input0 * (*ptr0)).
+    tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr0);
+    tmp32b = *ptr2 + tmp32a;
+    *ptr2 = (int32_t)(WEBRTC_SPL_MUL(t16a, tmp32b) +
+                       (WEBRTC_SPL_MUL_16_32_RSFT16(t16b, tmp32b)));
+
+    // Calculate *ptr1 = input1 * (*ptr0) + input0 * (*ptr2).
+    tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input1, *ptr0);
+    tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr2);
+    *ptr1 = tmp32a + tmp32b;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
new file mode 100644
index 0000000..f151cd1
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
@@ -0,0 +1,949 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_masking_model.c
+ *
+ * LPC analysis and filtering functions
+ *
+ */
+
+#include "lpc_masking_model.h"
+
+#include <limits.h>  /* For LLONG_MAX and LLONG_MIN. */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* The conversion is implemented by the step-down algorithm */
+void WebRtcSpl_AToK_JSK(
+    int16_t *a16, /* Q11 */
+    int16_t useOrder,
+    int16_t *k16  /* Q15 */
+                        )
+{
+  int m, k;
+  int32_t tmp32[MAX_AR_MODEL_ORDER];
+  int32_t tmp32b;
+  int32_t tmp_inv_denum32;
+  int16_t tmp_inv_denum16;
+
+  k16[useOrder-1] = a16[useOrder] << 4;  // Q11<<4 => Q15
+
+  for (m=useOrder-1; m>0; m--) {
+    // (1 - k^2) in Q30
+    tmp_inv_denum32 = 1073741823 - k16[m] * k16[m];
+    tmp_inv_denum16 = (int16_t)(tmp_inv_denum32 >> 15);  // (1 - k^2) in Q15.
+
+    for (k=1; k<=m; k++) {
+      tmp32b = (a16[k] << 16) - ((k16[m] * a16[m - k + 1]) << 1);
+
+      tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12
+    }
+
+    for (k=1; k<m; k++) {
+      a16[k] = (int16_t)(tmp32[k] >> 1);  // Q12>>1 => Q11
+    }
+
+    tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092);
+    k16[m - 1] = (int16_t)(tmp32[m] << 3);  // Q12<<3 => Q15
+  }
+
+  return;
+}
+
+
+
+
+
+int16_t WebRtcSpl_LevinsonW32_JSK(
+    int32_t *R,  /* (i) Autocorrelation of length >= order+1 */
+    int16_t *A,  /* (o) A[0..order] LPC coefficients (Q11) */
+    int16_t *K,  /* (o) K[0...order-1] Reflection coefficients (Q15) */
+    int16_t order /* (i) filter order */
+                                        ) {
+  int16_t i, j;
+  int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
+  /* Aurocorr coefficients in high precision */
+  int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
+  /* LPC coefficients in high precicion */
+  int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
+  /* LPC coefficients for next iteration */
+  int16_t K_hi, K_low;      /* reflection coefficient in high precision */
+  int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
+                                                   and with scale factor */
+  int16_t tmp_hi, tmp_low;
+  int32_t temp1W32, temp2W32, temp3W32;
+  int16_t norm;
+
+  /* Normalize the autocorrelation R[0]...R[order+1] */
+
+  norm = WebRtcSpl_NormW32(R[0]);
+
+  for (i=order;i>=0;i--) {
+    temp1W32 = R[i] << norm;
+    /* Put R in hi and low format */
+    R_hi[i] = (int16_t)(temp1W32 >> 16);
+    R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] << 16)) >> 1);
+  }
+
+  /* K = A[1] = -R[1] / R[0] */
+
+  temp2W32 = (R_hi[1] << 16) + (R_low[1] << 1);  /* R[1] in Q31      */
+  temp3W32  = WEBRTC_SPL_ABS_W32(temp2W32);      /* abs R[1]         */
+  temp1W32  = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */
+  /* Put back the sign on R[1] */
+  if (temp2W32 > 0) {
+    temp1W32 = -temp1W32;
+  }
+
+  /* Put K in hi and low format */
+  K_hi = (int16_t)(temp1W32 >> 16);
+  K_low = (int16_t)((temp1W32 - ((int32_t)K_hi << 16)) >> 1);
+
+  /* Store first reflection coefficient */
+  K[0] = K_hi;
+
+  temp1W32 >>= 4;  /* A[1] in Q27. */
+
+  /* Put A[1] in hi and low format */
+  A_hi[1] = (int16_t)(temp1W32 >> 16);
+  A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] << 16)) >> 1);
+
+  /*  Alpha = R[0] * (1-K^2) */
+
+  temp1W32  = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1;  /* = k^2 in Q31 */
+
+  temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);    /* Guard against <0 */
+  temp1W32 = (int32_t)0x7fffffffL - temp1W32;    /* temp1W32 = (1 - K[0]*K[0]) in Q31 */
+
+  /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
+  tmp_hi = (int16_t)(temp1W32 >> 16);
+  tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1);
+
+  /* Calculate Alpha in Q31 */
+  temp1W32 = (R_hi[0] * tmp_hi + ((R_hi[0] * tmp_low) >> 15) +
+      ((R_low[0] * tmp_hi) >> 15)) << 1;
+
+  /* Normalize Alpha and put it in hi and low format */
+
+  Alpha_exp = WebRtcSpl_NormW32(temp1W32);
+  temp1W32 <<= Alpha_exp;
+  Alpha_hi = (int16_t)(temp1W32 >> 16);
+  Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi<< 16)) >> 1);
+
+  /* Perform the iterative calculations in the
+     Levinson Durbin algorithm */
+
+  for (i=2; i<=order; i++)
+  {
+
+    /*                    ----
+                          \
+        temp1W32 =  R[i] + > R[j]*A[i-j]
+                          /
+                          ----
+                          j=1..i-1
+    */
+
+    temp1W32 = 0;
+
+    for(j=1; j<i; j++) {
+      /* temp1W32 is in Q31 */
+      temp1W32 += ((R_hi[j] * A_hi[i - j]) << 1) +
+          ((((R_hi[j] * A_low[i - j]) >> 15) +
+              ((R_low[j] * A_hi[i - j]) >> 15)) << 1);
+    }
+
+    temp1W32 <<= 4;
+    temp1W32 += (R_hi[i] << 16) + (R_low[i] << 1);
+
+    /* K = -temp1W32 / Alpha */
+    temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* abs(temp1W32) */
+    temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */
+
+    /* Put the sign of temp1W32 back again */
+    if (temp1W32 > 0) {
+      temp3W32 = -temp3W32;
+    }
+
+    /* Use the Alpha shifts from earlier to denormalize */
+    norm = WebRtcSpl_NormW32(temp3W32);
+    if ((Alpha_exp <= norm)||(temp3W32==0)) {
+      temp3W32 <<= Alpha_exp;
+    } else {
+      if (temp3W32 > 0)
+      {
+        temp3W32 = (int32_t)0x7fffffffL;
+      } else
+      {
+        temp3W32 = (int32_t)0x80000000L;
+      }
+    }
+
+    /* Put K on hi and low format */
+    K_hi = (int16_t)(temp3W32 >> 16);
+    K_low = (int16_t)((temp3W32 - ((int32_t)K_hi << 16)) >> 1);
+
+    /* Store Reflection coefficient in Q15 */
+    K[i-1] = K_hi;
+
+    /* Test for unstable filter. If unstable return 0 and let the
+       user decide what to do in that case
+    */
+
+    if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) {
+      return(-i); /* Unstable filter */
+    }
+
+    /*
+      Compute updated LPC coefficient: Anew[i]
+      Anew[j]= A[j] + K*A[i-j]   for j=1..i-1
+      Anew[i]= K
+    */
+
+    for(j=1; j<i; j++)
+    {
+      temp1W32 = (A_hi[j] << 16) + (A_low[j] << 1);  // temp1W32 = A[j] in Q27
+
+      temp1W32 += (K_hi * A_hi[i - j] + ((K_hi * A_low[i - j]) >> 15) +
+          ((K_low * A_hi[i - j]) >> 15)) << 1;  // temp1W32 += K*A[i-j] in Q27.
+
+      /* Put Anew in hi and low format */
+      A_upd_hi[j] = (int16_t)(temp1W32 >> 16);
+      A_upd_low[j] = (int16_t)((temp1W32 - ((int32_t)A_upd_hi[j] << 16)) >> 1);
+    }
+
+    temp3W32 >>= 4;  /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */
+
+    /* Store Anew in hi and low format */
+    A_upd_hi[i] = (int16_t)(temp3W32 >> 16);
+    A_upd_low[i] = (int16_t)((temp3W32 - ((int32_t)A_upd_hi[i] << 16)) >> 1);
+
+    /*  Alpha = Alpha * (1-K^2) */
+
+    temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1;  /* K*K in Q31 */
+
+    temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* Guard against <0 */
+    temp1W32 = (int32_t)0x7fffffffL - temp1W32;      /* 1 - K*K  in Q31 */
+
+    /* Convert 1- K^2 in hi and low format */
+    tmp_hi = (int16_t)(temp1W32 >> 16);
+    tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1);
+
+    /* Calculate Alpha = Alpha * (1-K^2) in Q31 */
+    temp1W32 = (Alpha_hi * tmp_hi + ((Alpha_hi * tmp_low) >> 15) +
+        ((Alpha_low * tmp_hi) >> 15)) << 1;
+
+    /* Normalize Alpha and store it on hi and low format */
+
+    norm = WebRtcSpl_NormW32(temp1W32);
+    temp1W32 <<= norm;
+
+    Alpha_hi = (int16_t)(temp1W32 >> 16);
+    Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi << 16)) >> 1);
+
+    /* Update the total nomalization of Alpha */
+    Alpha_exp = Alpha_exp + norm;
+
+    /* Update A[] */
+
+    for(j=1; j<=i; j++)
+    {
+      A_hi[j] =A_upd_hi[j];
+      A_low[j] =A_upd_low[j];
+    }
+  }
+
+  /*
+    Set A[0] to 1.0 and store the A[i] i=1...order in Q12
+    (Convert from Q27 and use rounding)
+  */
+
+  A[0] = 2048;
+
+  for(i=1; i<=order; i++) {
+    /* temp1W32 in Q27 */
+    temp1W32 = (A_hi[i] << 16) + (A_low[i] << 1);
+    /* Round and store upper word */
+    A[i] = (int16_t)((temp1W32 + 32768) >> 16);
+  }
+  return(1); /* Stable filters */
+}
+
+
+
+
+
+/* window */
+/* Matlab generation of floating point code:
+ *  t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ *  for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ * All values are multiplyed with 2^21 in fixed point code.
+ */
+static const int16_t kWindowAutocorr[WINLEN] = {
+  0,     0,     0,     0,     0,     1,     1,     2,     2,     3,     5,     6,
+  8,    10,    12,    14,    17,    20,    24,    28,    33,    38,    43,    49,
+  56,    63,    71,    79,    88,    98,   108,   119,   131,   143,   157,   171,
+  186,   202,   219,   237,   256,   275,   296,   318,   341,   365,   390,   416,
+  444,   472,   502,   533,   566,   600,   635,   671,   709,   748,   789,   831,
+  875,   920,   967,  1015,  1065,  1116,  1170,  1224,  1281,  1339,  1399,  1461,
+  1525,  1590,  1657,  1726,  1797,  1870,  1945,  2021,  2100,  2181,  2263,  2348,
+  2434,  2523,  2614,  2706,  2801,  2898,  2997,  3099,  3202,  3307,  3415,  3525,
+  3637,  3751,  3867,  3986,  4106,  4229,  4354,  4481,  4611,  4742,  4876,  5012,
+  5150,  5291,  5433,  5578,  5725,  5874,  6025,  6178,  6333,  6490,  6650,  6811,
+  6974,  7140,  7307,  7476,  7647,  7820,  7995,  8171,  8349,  8529,  8711,  8894,
+  9079,  9265,  9453,  9642,  9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199,
+  11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614,
+  13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971,
+  16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030,
+  18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471,
+  19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886,
+  19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793,
+  18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677,
+  15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152,
+  9583,  8998,  8399,  7787,  7162,  6527,  5883,  5231,  4576,  3919,  3265,  2620,
+  1990,  1386,   825,   333
+};
+
+
+/* By using a hearing threshold level in dB of -28 dB (higher value gives more noise),
+   the H_T_H (in float) can be calculated as:
+   H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350
+   In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e.
+   H_T_H = 20872/524288.0, and H_T_HQ19 = 20872;
+*/
+
+
+/* The bandwidth expansion vectors are created from:
+   kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430];
+   kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144];
+   round(kPolyVecLo*32768)
+   round(kPolyVecHi*32768)
+*/
+static const int16_t kPolyVecLo[12] = {
+  29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
+};
+static const int16_t kPolyVecHi[6] = {
+  26214, 20972, 16777, 13422, 10737, 8590
+};
+
+static __inline int32_t log2_Q8_LPC( uint32_t x ) {
+
+  int32_t zeros;
+  int16_t frac;
+
+  zeros=WebRtcSpl_NormU32(x);
+  frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+
+  /* log2(x) */
+  return ((31 - zeros) << 8) + frac;
+}
+
+static const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */
+static const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
+static const int16_t kExp2 = 11819; /* 1/log(2) */
+const int kShiftLowerBand = 11;  /* Shift value for lower band in Q domain. */
+const int kShiftHigherBand = 12;  /* Shift value for higher band in Q domain. */
+
+void WebRtcIsacfix_GetVars(const int16_t *input, const int16_t *pitchGains_Q12,
+                           uint32_t *oldEnergy, int16_t *varscale)
+{
+  int k;
+  uint32_t nrgQ[4];
+  int16_t nrgQlog[4];
+  int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
+  int32_t expPg32;
+  int16_t expPg, divVal;
+  int16_t tmp16_1, tmp16_2;
+
+  /* Calculate energies of first and second frame halfs */
+  nrgQ[0]=0;
+  for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) {
+    nrgQ[0] += (uint32_t)(input[k] * input[k]);
+  }
+  nrgQ[1]=0;
+  for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) {
+    nrgQ[1] += (uint32_t)(input[k] * input[k]);
+  }
+  nrgQ[2]=0;
+  for ( ; k < (FRAMESAMPLES * 3 / 4 + QLOOKAHEAD) / 2; k++) {
+    nrgQ[2] += (uint32_t)(input[k] * input[k]);
+  }
+  nrgQ[3]=0;
+  for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+    nrgQ[3] += (uint32_t)(input[k] * input[k]);
+  }
+
+  for ( k=0; k<4; k++) {
+    nrgQlog[k] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
+  }
+  oldNrgQlog = (int16_t)log2_Q8_LPC(*oldEnergy);
+
+  /* Calculate average level change */
+  chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]);
+  chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]);
+  chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]);
+  chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog);
+  tmp = chng1+chng2+chng3+chng4;
+  chngQ = (int16_t)(tmp * kChngFactor >> 10);  /* Q12 */
+  chngQ += 2926; /* + 1.0/1.4 in Q12 */
+
+  /* Find average pitch gain */
+  pgQ = 0;
+  for (k=0; k<4; k++)
+  {
+    pgQ += pitchGains_Q12[k];
+  }
+
+  pg3 = (int16_t)(pgQ * pgQ >> 11);  // pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17
+  pg3 = (int16_t)(pgQ * pg3 >> 13);  /* Q14*Q17>>13 =>Q18  */
+  /* kMulPitchGain = -25 = -200 in Q-3. */
+  pg3 = (int16_t)(pg3 * kMulPitchGain >> 5);  // Q10
+  tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/
+  if (tmp16<0) {
+    tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+    tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3;  /* Gives result in Q14 */
+    if (tmp16_1<0)
+      expPg = -(tmp16_2 << -tmp16_1);
+    else
+      expPg = -(tmp16_2 >> tmp16_1);
+  } else
+    expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */
+
+  expPg32 = (int32_t)expPg << 8;  /* Q22 */
+  divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
+
+  tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/
+  if (tmp16<0) {
+    tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+    tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3;  /* Gives result in Q14 */
+    if (tmp16_1<0)
+      expPg = tmp16_2 << -tmp16_1;
+    else
+      expPg = tmp16_2 >> tmp16_1;
+  } else
+    expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */
+
+  *varscale = expPg-1;
+  *oldEnergy = nrgQ[3];
+}
+
+
+
+static __inline int16_t  exp2_Q10_T(int16_t x) { // Both in and out in Q10
+
+  int16_t tmp16_1, tmp16_2;
+
+  tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+  tmp16_1 = -(x >> 10);
+  if(tmp16_1>0)
+    return tmp16_2 >> tmp16_1;
+  else
+    return tmp16_2 << -tmp16_1;
+
+}
+
+
+// Declare function pointers.
+AutocorrFix WebRtcIsacfix_AutocorrFix;
+CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+/* This routine calculates the residual energy for LPC.
+ * Formula as shown in comments inside.
+ */
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+                                               int32_t q_val_corr,
+                                               int q_val_polynomial,
+                                               int16_t* a_polynomial,
+                                               int32_t* corr_coeffs,
+                                               int* q_val_residual_energy) {
+  int i = 0, j = 0;
+  int shift_internal = 0, shift_norm = 0;
+  int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
+  int64_t sum64 = 0, sum64_tmp = 0;
+
+  for (i = 0; i <= lpc_order; i++) {
+    for (j = i; j <= lpc_order; j++) {
+      /* For the case of i == 0: residual_energy +=
+       *    a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
+       * For the case of i != 0: residual_energy +=
+       *    a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
+       */
+
+      tmp32 = a_polynomial[j] * a_polynomial[j - i];
+                                   /* tmp32 in Q(q_val_polynomial * 2). */
+      if (i != 0) {
+        tmp32 <<= 1;
+      }
+      sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i];
+      sum64_tmp >>= shift_internal;
+
+      /* Test overflow and sum the result. */
+      if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) ||
+         ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) {
+        /* Shift right for overflow. */
+        shift_internal += 1;
+        sum64 >>= 1;
+        sum64 += sum64_tmp >> 1;
+      } else {
+        sum64 += sum64_tmp;
+      }
+    }
+  }
+
+  word32_high = (int32_t)(sum64 >> 32);
+  word32_low = (int32_t)sum64;
+
+  // Calculate the value of shifting (shift_norm) for the 64-bit sum.
+  if(word32_high != 0) {
+    shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
+    residual_energy = (int32_t)(sum64 >> shift_norm);
+  } else {
+    if((word32_low & 0x80000000) != 0) {
+      shift_norm = 1;
+      residual_energy = (uint32_t)word32_low >> 1;
+    } else {
+      shift_norm = WebRtcSpl_NormW32(word32_low);
+      residual_energy = word32_low << shift_norm;
+      shift_norm = -shift_norm;
+    }
+  }
+
+  /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
+   *   = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
+   */
+  *q_val_residual_energy = q_val_corr - shift_internal - shift_norm
+                           + q_val_polynomial * 2;
+
+  return residual_energy;
+}
+
+void WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0,
+                              int16_t *inHiQ0,
+                              MaskFiltstr_enc *maskdata,
+                              int16_t snrQ10,
+                              const int16_t *pitchGains_Q12,
+                              int32_t *gain_lo_hiQ17,
+                              int16_t *lo_coeffQ15,
+                              int16_t *hi_coeffQ15)
+{
+  int k, n, ii;
+  int pos1, pos2;
+  int sh_lo, sh_hi, sh, ssh, shMem;
+  int16_t varscaleQ14;
+
+  int16_t tmpQQlo, tmpQQhi;
+  int32_t tmp32;
+  int16_t tmp16,tmp16b;
+
+  int16_t polyHI[ORDERHI+1];
+  int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
+
+
+  int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN];
+  int32_t corrloQQ[ORDERLO+2];
+  int32_t corrhiQQ[ORDERHI+1];
+  int32_t corrlo2QQ[ORDERLO+1];
+  int16_t scale;
+  int16_t QdomLO, QdomHI, newQdomHI, newQdomLO;
+
+  int32_t res_nrgQQ;
+  int32_t sqrt_nrg;
+
+  /* less-noise-at-low-frequencies factor */
+  int16_t aaQ14;
+
+  /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to
+     Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032
+  */
+  int16_t snrq;
+  int shft;
+
+  int16_t tmp16a;
+  int32_t tmp32a, tmp32b, tmp32c;
+
+  int16_t a_LOQ11[ORDERLO+1];
+  int16_t k_vecloQ15[ORDERLO];
+  int16_t a_HIQ12[ORDERHI+1];
+  int16_t k_vechiQ15[ORDERHI];
+
+  int16_t stab;
+
+  snrq=snrQ10;
+
+  /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/
+  tmp16 = (int16_t)(snrq * 172 >> 10);  // Q10
+  tmp16b = exp2_Q10_T(tmp16); // Q10
+  snrq = (int16_t)(tmp16b * 285 >> 10);  // Q10
+
+  /* change quallevel depending on pitch gains and level fluctuations */
+  WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14);
+
+  /* less-noise-at-low-frequencies factor */
+  /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint:
+     With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14,
+     we get Q16*Q14>>16 = Q14
+  */
+  aaQ14 = (int16_t)((22938 * (8192 + (varscaleQ14 >> 1)) + 32768) >> 16);
+
+  /* Calculate tmp = (1.0 + aa*aa); in Q12 */
+  tmp16 = (int16_t)(aaQ14 * aaQ14 >> 15);  // Q14*Q14>>15 = Q13
+  tmpQQlo = 4096 + (tmp16 >> 1);  // Q12 + Q13>>1 = Q12.
+
+  /* Calculate tmp = (1.0+aa) * (1.0+aa); */
+  tmp16 = 8192 + (aaQ14 >> 1);  // 1+a in Q13.
+  tmpQQhi = (int16_t)(tmp16 * tmp16 >> 14);  // Q13*Q13>>14 = Q12
+
+  /* replace data in buffer by new look-ahead data */
+  for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) {
+    maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1];
+  }
+
+  for (k = 0; k < SUBFRAMES; k++) {
+
+    /* Update input buffer and multiply signal with window */
+    for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+      maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2];
+      maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2];
+      DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] *
+          kWindowAutocorr[pos1] >> 15);  // Q0*Q21>>15 = Q6
+      DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] *
+          kWindowAutocorr[pos1] >> 15);  // Q0*Q21>>15 = Q6
+    }
+    pos2 = (int16_t)(k * UPDATE / 2);
+    for (n = 0; n < UPDATE/2; n++, pos1++) {
+      maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2];
+      maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++];
+      DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] *
+          kWindowAutocorr[pos1] >> 15);  // Q0*Q21>>15 = Q6
+      DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] *
+          kWindowAutocorr[pos1] >> 15);  // Q0*Q21>>15 = Q6
+    }
+
+    /* Get correlation coefficients */
+    /* The highest absolute value measured inside DataLo in the test set
+       For DataHi, corresponding value was 160.
+
+       This means that it should be possible to represent the input values
+       to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 =
+       19648). Of course, Q0 will also work, but due to the low energy in
+       DataLo and DataHi, the outputted autocorrelation will be more accurate
+       and mimic the floating point code better, by being in an high as possible
+       Q-domain.
+    */
+
+    WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale);
+    QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ
+    sh_lo = WebRtcSpl_NormW32(corrloQQ[0]);
+    QdomLO += sh_lo;
+    for (ii=0; ii<ORDERLO+2; ii++) {
+      corrloQQ[ii] <<= sh_lo;
+    }
+    /* It is investigated whether it was possible to use 16 bits for the
+       32-bit vector corrloQQ, but it didn't work. */
+
+    WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale);
+
+    QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ
+    sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]);
+    QdomHI += sh_hi;
+    for (ii=0; ii<ORDERHI+1; ii++) {
+      corrhiQQ[ii] <<= sh_hi;
+    }
+
+    /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+
+    /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/
+    // `corrlo2QQ` in Q(QdomLO-5).
+    corrlo2QQ[0] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]) >> 1) -
+        (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]) >> 2);
+
+    /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/
+    for (n = 1; n <= ORDERLO; n++) {
+
+      tmp32 = (corrloQQ[n - 1] >> 1) + (corrloQQ[n + 1] >> 1);  // Q(QdomLO-1).
+      corrlo2QQ[n] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]) >> 1) -
+          (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32) >> 2);
+    }
+    QdomLO -= 5;
+
+    /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */
+    for (n = 0; n <= ORDERHI; n++) {
+      corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4)
+    }
+    QdomHI -= 4;
+
+    /* add white noise floor */
+    /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */
+    /* Calculate corrlo2[0] += 9.5367431640625e-7; and
+       corrhi[0]  += 9.5367431640625e-7, where the constant is 1/2^20 */
+
+    tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomLO-20);
+    corrlo2QQ[0] += tmp32;
+    tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomHI-20);
+    corrhiQQ[0]  += tmp32;
+
+    /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following
+       code segment, where we want to make sure we get a 1-bit margin */
+    for (n = 0; n <= ORDERLO; n++) {
+      corrlo2QQ[n] >>= 1;  // Make sure we have a 1-bit margin.
+    }
+    QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin
+
+    for (n = 0; n <= ORDERHI; n++) {
+      corrhiQQ[n] >>= 1;  // Make sure we have a 1-bit margin.
+    }
+    QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin
+
+
+    newQdomLO = QdomLO;
+
+    for (n = 0; n <= ORDERLO; n++) {
+      int32_t tmp, tmpB, tmpCorr;
+      int16_t alpha=328; //0.01 in Q15
+      int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
+      int16_t gamma=32440; //(1-0.01)=0.99 in Q15
+
+      if (maskdata->CorrBufLoQQ[n] != 0) {
+        shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]);
+        sh = QdomLO - maskdata->CorrBufLoQdom[n];
+        if (sh<=shMem) {
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+        } else if ((sh-shMem)<7){
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible
+          // Shift `alpha` the number of times required to get `tmp` in QdomLO.
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp);
+        } else {
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+          // Shift `alpha` as much as possible without overflow the number of
+          // times required to get `tmp` in QdomLO.
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp);
+          tmpCorr = corrloQQ[n] >> (sh - shMem - 6);
+          tmp = tmp + tmpCorr;
+          maskdata->CorrBufLoQQ[n] = tmp;
+          newQdomLO = QdomLO-(sh-shMem-6);
+          maskdata->CorrBufLoQdom[n] = newQdomLO;
+        }
+      } else
+        tmp = 0;
+
+      tmp = tmp + corrlo2QQ[n];
+
+      maskdata->CorrBufLoQQ[n] = tmp;
+      maskdata->CorrBufLoQdom[n] = QdomLO;
+
+      tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+      tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]);
+      corrlo2QQ[n] = tmp + tmpB;
+    }
+    if( newQdomLO!=QdomLO) {
+      for (n = 0; n <= ORDERLO; n++) {
+        if (maskdata->CorrBufLoQdom[n] != newQdomLO)
+          corrloQQ[n] >>= maskdata->CorrBufLoQdom[n] - newQdomLO;
+      }
+      QdomLO = newQdomLO;
+    }
+
+
+    newQdomHI = QdomHI;
+
+    for (n = 0; n <= ORDERHI; n++) {
+      int32_t tmp, tmpB, tmpCorr;
+      int16_t alpha=328; //0.01 in Q15
+      int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
+      int16_t gamma=32440; //(1-0.01)=0.99 in Q1
+      if (maskdata->CorrBufHiQQ[n] != 0) {
+        shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]);
+        sh = QdomHI - maskdata->CorrBufHiQdom[n];
+        if (sh<=shMem) {
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+          tmpCorr = corrhiQQ[n];
+          tmp = tmp + tmpCorr;
+          maskdata->CorrBufHiQQ[n] = tmp;
+          maskdata->CorrBufHiQdom[n] = QdomHI;
+        } else if ((sh-shMem)<7) {
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+          // Shift `alpha` the number of times required to get `tmp` in QdomHI.
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp);
+          tmpCorr = corrhiQQ[n];
+          tmp = tmp + tmpCorr;
+          maskdata->CorrBufHiQQ[n] = tmp;
+          maskdata->CorrBufHiQdom[n] = QdomHI;
+        } else {
+          tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+          // Shift `alpha` as much as possible without overflow the number of
+          // times required to get `tmp` in QdomHI.
+          tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp);
+          tmpCorr = corrhiQQ[n] >> (sh - shMem - 6);
+          tmp = tmp + tmpCorr;
+          maskdata->CorrBufHiQQ[n] = tmp;
+          newQdomHI = QdomHI-(sh-shMem-6);
+          maskdata->CorrBufHiQdom[n] = newQdomHI;
+        }
+      } else {
+        tmp = corrhiQQ[n];
+        tmpCorr = tmp;
+        maskdata->CorrBufHiQQ[n] = tmp;
+        maskdata->CorrBufHiQdom[n] = QdomHI;
+      }
+
+      tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+      tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr);
+      corrhiQQ[n] = tmp + tmpB;
+    }
+
+    if( newQdomHI!=QdomHI) {
+      for (n = 0; n <= ORDERHI; n++) {
+        if (maskdata->CorrBufHiQdom[n] != newQdomHI)
+          corrhiQQ[n] >>= maskdata->CorrBufHiQdom[n] - newQdomHI;
+      }
+      QdomHI = newQdomHI;
+    }
+
+    stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO);
+
+    if (stab<0) {  // If unstable use lower order
+      a_LOQ11[0]=2048;
+      for (n = 1; n <= ORDERLO; n++) {
+        a_LOQ11[n]=0;
+      }
+
+      stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8);
+    }
+
+
+    WebRtcSpl_LevinsonDurbin(corrhiQQ,  a_HIQ12,  k_vechiQ15, ORDERHI);
+
+    /* bandwidth expansion */
+    for (n = 1; n <= ORDERLO; n++) {
+      a_LOQ11[n] = (int16_t)((kPolyVecLo[n - 1] * a_LOQ11[n] + (1 << 14)) >>
+          15);
+    }
+
+
+    polyHI[0] = a_HIQ12[0];
+    for (n = 1; n <= ORDERHI; n++) {
+      a_HIQ12[n] = (int16_t)(((int32_t)(kPolyVecHi[n - 1] * a_HIQ12[n]) +
+        (1 << 14)) >> 15);
+      polyHI[n] = a_HIQ12[n];
+    }
+
+    /* Normalize the corrlo2 vector */
+    sh = WebRtcSpl_NormW32(corrlo2QQ[0]);
+    for (n = 0; n <= ORDERLO; n++) {
+      corrlo2QQ[n] <<= sh;
+    }
+    QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */
+
+
+    /* residual energy */
+
+    sh_lo = 31;
+    res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO,
+        kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo);
+
+    /* Convert to reflection coefficients */
+    WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo);
+
+    if (sh_lo & 0x0001) {
+      res_nrgQQ >>= 1;
+      sh_lo-=1;
+    }
+
+
+    if( res_nrgQQ > 0 )
+    {
+      sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+      /* add hearing threshold and compute the gain */
+      /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+      tmp32a = varscaleQ14 >> 1;  // H_T_HQ19=65536 (16-17=-1)
+      ssh = sh_lo >> 1;  // sqrt_nrg is in Qssh.
+      sh = ssh - 14;
+      tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+      tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
+      tmp32a = varscaleQ14 * snrq;  // Q24 (numerator)
+
+      sh = WebRtcSpl_NormW32(tmp32c);
+      shft = 16 - sh;
+      tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
+
+      tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+      sh = ssh-shft-7;
+      *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
+    }
+    else
+    {
+      *gain_lo_hiQ17 = 100;  // Gains in Q17
+    }
+    gain_lo_hiQ17++;
+
+    /* copy coefficients to output array */
+    for (n = 0; n < ORDERLO; n++) {
+      *lo_coeffQ15 = (int16_t) (rcQ15_lo[n]);
+      lo_coeffQ15++;
+    }
+    /* residual energy */
+    sh_hi = 31;
+    res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI,
+        kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi);
+
+    /* Convert to reflection coefficients */
+    WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi);
+
+    if (sh_hi & 0x0001) {
+      res_nrgQQ >>= 1;
+      sh_hi-=1;
+    }
+
+
+    if( res_nrgQQ > 0 )
+    {
+      sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+
+      /* add hearing threshold and compute the gain */
+      /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+      tmp32a = varscaleQ14 >> 1;  // H_T_HQ19=65536 (16-17=-1)
+
+      ssh = sh_hi >> 1;  // `sqrt_nrg` is in Qssh.
+      sh = ssh - 14;
+      tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+      tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
+      tmp32a = varscaleQ14 * snrq;  // Q24 (numerator)
+
+      sh = WebRtcSpl_NormW32(tmp32c);
+      shft = 16 - sh;
+      tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
+
+      tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+      sh = ssh-shft-7;
+      *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
+    }
+    else
+    {
+      *gain_lo_hiQ17 = 100;  // Gains in Q17
+    }
+    gain_lo_hiQ17++;
+
+
+    /* copy coefficients to output array */
+    for (n = 0; n < ORDERHI; n++) {
+      *hi_coeffQ15 = rcQ15_hi[n];
+      hi_coeffQ15++;
+    }
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
new file mode 100644
index 0000000..40a99e8
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_masking_model.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+void WebRtcIsacfix_GetVars(const int16_t* input,
+                           const int16_t* pitchGains_Q12,
+                           uint32_t* oldEnergy,
+                           int16_t* varscale);
+
+void WebRtcIsacfix_GetLpcCoef(int16_t* inLoQ0,
+                              int16_t* inHiQ0,
+                              MaskFiltstr_enc* maskdata,
+                              int16_t snrQ10,
+                              const int16_t* pitchGains_Q12,
+                              int32_t* gain_lo_hiQ17,
+                              int16_t* lo_coeffQ15,
+                              int16_t* hi_coeffQ15);
+
+typedef int32_t (*CalculateResidualEnergy)(int lpc_order,
+                                           int32_t q_val_corr,
+                                           int q_val_polynomial,
+                                           int16_t* a_polynomial,
+                                           int32_t* corr_coeffs,
+                                           int* q_val_residual_energy);
+extern CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+                                               int32_t q_val_corr,
+                                               int q_val_polynomial,
+                                               int16_t* a_polynomial,
+                                               int32_t* corr_coeffs,
+                                               int* q_val_residual_energy);
+
+#if defined(MIPS_DSP_R2_LE)
+int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(int lpc_order,
+                                                  int32_t q_val_corr,
+                                                  int q_val_polynomial,
+                                                  int16_t* a_polynomial,
+                                                  int32_t* corr_coeffs,
+                                                  int* q_val_residual_energy);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c
new file mode 100644
index 0000000..727008d
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c
@@ -0,0 +1,237 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+
+// MIPS DSPR2 optimization for function WebRtcIsacfix_CalculateResidualEnergy
+// Bit-exact with WebRtcIsacfix_CalculateResidualEnergyC from file
+// lpc_masking_model.c
+int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(int lpc_order,
+                                                  int32_t q_val_corr,
+                                                  int q_val_polynomial,
+                                                  int16_t* a_polynomial,
+                                                  int32_t* corr_coeffs,
+                                                  int* q_val_residual_energy) {
+
+  int i = 0, j = 0;
+  int shift_internal = 0, shift_norm = 0;
+  int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
+  int32_t tmp_corr_c = corr_coeffs[0];
+  int16_t* tmp_a_poly = &a_polynomial[0];
+  int32_t sum64_hi = 0;
+  int32_t sum64_lo = 0;
+
+  for (j = 0; j <= lpc_order; j++) {
+    // For the case of i == 0:
+    //   residual_energy +=
+    //     a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
+
+    int32_t tmp2, tmp3;
+    int16_t sign_1;
+    int16_t sign_2;
+    int16_t sign_3;
+
+    __asm __volatile (
+      ".set      push                                                \n\t"
+      ".set      noreorder                                           \n\t"
+      "lh        %[tmp2],         0(%[tmp_a_poly])                   \n\t"
+      "mul       %[tmp32],        %[tmp2],            %[tmp2]        \n\t"
+      "addiu     %[tmp_a_poly],   %[tmp_a_poly],      2              \n\t"
+      "sra       %[sign_2],       %[sum64_hi],        31             \n\t"
+      "mult      $ac0,            %[tmp32],           %[tmp_corr_c]  \n\t"
+      "shilov    $ac0,            %[shift_internal]                  \n\t"
+      "mfhi      %[tmp2],         $ac0                               \n\t"
+      "mflo      %[tmp3],         $ac0                               \n\t"
+      "sra       %[sign_1],       %[tmp2],            31             \n\t"
+      "xor       %[sign_3],       %[sign_1],          %[sign_2]      \n\t"
+      ".set      pop                                                 \n\t"
+      : [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
+        [tmp_a_poly] "+r" (tmp_a_poly), [sign_1] "=&r" (sign_1),
+        [sign_3] "=&r" (sign_3), [sign_2] "=&r" (sign_2),
+        [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+      : [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
+      : "hi", "lo", "memory"
+    );
+
+    if (sign_3 != 0) {
+      __asm __volatile (
+        ".set      push                                      \n\t"
+        ".set      noreorder                                 \n\t"
+        "addsc     %[sum64_lo],   %[sum64_lo],    %[tmp3]    \n\t"
+        "addwc     %[sum64_hi],   %[sum64_hi],    %[tmp2]    \n\t"
+        ".set      pop                                       \n\t"
+        : [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+        : [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
+        : "hi", "lo", "memory"
+      );
+    } else {
+      if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
+          ((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
+        // Shift right for overflow.
+        __asm __volatile (
+          ".set      push                                             \n\t"
+          ".set      noreorder                                        \n\t"
+          "addiu     %[shift_internal], %[shift_internal],  1         \n\t"
+          "prepend   %[sum64_lo],       %[sum64_hi],        1         \n\t"
+          "sra       %[sum64_hi],       %[sum64_hi],        1         \n\t"
+          "prepend   %[tmp3],           %[tmp2],            1         \n\t"
+          "sra       %[tmp2],           %[tmp2],            1         \n\t"
+          "addsc     %[sum64_lo],       %[sum64_lo],        %[tmp3]   \n\t"
+          "addwc     %[sum64_hi],       %[sum64_hi],        %[tmp2]   \n\t"
+          ".set      pop                                              \n\t"
+          : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+            [shift_internal] "+r" (shift_internal),
+            [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+          :
+          : "hi", "lo", "memory"
+        );
+      } else {
+        __asm __volatile (
+          ".set      push                                      \n\t"
+          ".set      noreorder                                 \n\t"
+          "addsc     %[sum64_lo],   %[sum64_lo],    %[tmp3]    \n\t"
+          "addwc     %[sum64_hi],   %[sum64_hi],    %[tmp2]    \n\t"
+          ".set      pop                                       \n\t"
+          : [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+          : [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
+          : "hi", "lo", "memory"
+        );
+      }
+    }
+  }
+
+  for (i = 1; i <= lpc_order; i++) {
+    tmp_corr_c = corr_coeffs[i];
+    int16_t* tmp_a_poly_j = &a_polynomial[i];
+    int16_t* tmp_a_poly_j_i = &a_polynomial[0];
+    for (j = i; j <= lpc_order; j++) {
+      // For the case of i = 1 .. lpc_order:
+      //   residual_energy +=
+      //     a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
+
+      int32_t tmp2, tmp3;
+      int16_t sign_1;
+      int16_t sign_2;
+      int16_t sign_3;
+
+      __asm __volatile (
+        ".set      push                                                   \n\t"
+        ".set      noreorder                                              \n\t"
+        "lh        %[tmp3],           0(%[tmp_a_poly_j])                  \n\t"
+        "lh        %[tmp2],           0(%[tmp_a_poly_j_i])                \n\t"
+        "addiu     %[tmp_a_poly_j],   %[tmp_a_poly_j],    2               \n\t"
+        "addiu     %[tmp_a_poly_j_i], %[tmp_a_poly_j_i],  2               \n\t"
+        "mul       %[tmp32],          %[tmp3],            %[tmp2]         \n\t"
+        "sll       %[tmp32],          %[tmp32],           1               \n\t"
+        "mult      $ac0,              %[tmp32],           %[tmp_corr_c]   \n\t"
+        "shilov    $ac0,              %[shift_internal]                   \n\t"
+        "mfhi      %[tmp2],           $ac0                                \n\t"
+        "mflo      %[tmp3],           $ac0                                \n\t"
+        "sra       %[sign_1],         %[tmp2],            31              \n\t"
+        "sra       %[sign_2],         %[sum64_hi],        31              \n\t"
+        "xor       %[sign_3],         %[sign_1],          %[sign_2]       \n\t"
+        ".set      pop                                                    \n\t"
+        : [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
+          [tmp_a_poly_j] "+r" (tmp_a_poly_j), [sign_1] "=&r" (sign_1),
+          [tmp_a_poly_j_i] "+r" (tmp_a_poly_j_i), [sign_2] "=&r" (sign_2),
+          [sign_3] "=&r" (sign_3), [sum64_hi] "+r" (sum64_hi),
+          [sum64_lo] "+r" (sum64_lo)
+        : [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
+        : "hi", "lo", "memory"
+      );
+      if (sign_3 != 0) {
+        __asm __volatile (
+          ".set      push                                     \n\t"
+          ".set      noreorder                                \n\t"
+          "addsc     %[sum64_lo],   %[sum64_lo],   %[tmp3]    \n\t"
+          "addwc     %[sum64_hi],   %[sum64_hi],   %[tmp2]    \n\t"
+          ".set      pop                                      \n\t"
+          : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3), [sum64_hi] "+r" (sum64_hi),
+            [sum64_lo] "+r" (sum64_lo)
+          :
+          :"memory"
+        );
+      } else {
+        // Test overflow and sum the result.
+        if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
+            ((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
+          // Shift right for overflow.
+          __asm __volatile (
+            ".set      push                                              \n\t"
+            ".set      noreorder                                         \n\t"
+            "addiu     %[shift_internal],  %[shift_internal],  1         \n\t"
+            "prepend   %[sum64_lo],        %[sum64_hi],        1         \n\t"
+            "sra       %[sum64_hi],        %[sum64_hi],        1         \n\t"
+            "prepend   %[tmp3],            %[tmp2],            1         \n\t"
+            "sra       %[tmp2],            %[tmp2],            1         \n\t"
+            "addsc     %[sum64_lo],        %[sum64_lo],        %[tmp3]   \n\t"
+            "addwc     %[sum64_hi],        %[sum64_hi],        %[tmp2]   \n\t"
+            ".set      pop                                               \n\t"
+            : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+              [shift_internal] "+r" (shift_internal),
+              [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+            :
+            : "hi", "lo", "memory"
+          );
+        } else {
+          __asm __volatile (
+            ".set      push                                      \n\t"
+            ".set      noreorder                                 \n\t"
+            "addsc     %[sum64_lo],    %[sum64_lo],   %[tmp3]    \n\t"
+            "addwc     %[sum64_hi],    %[sum64_hi],   %[tmp2]    \n\t"
+            ".set      pop                                       \n\t"
+            : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+              [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+            :
+            : "hi", "lo", "memory"
+          );
+        }
+      }
+    }
+  }
+  word32_high = sum64_hi;
+  word32_low = sum64_lo;
+
+  // Calculate the value of shifting (shift_norm) for the 64-bit sum.
+  if (word32_high != 0) {
+    shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
+    int tmp1;
+    __asm __volatile (
+      ".set    push                                                     \n\t"
+      ".set    noreorder                                                \n\t"
+      "srl     %[residual_energy],  %[sum64_lo],         %[shift_norm]  \n\t"
+      "li      %[tmp1],             32                                  \n\t"
+      "subu    %[tmp1],             %[tmp1],             %[shift_norm]  \n\t"
+      "sll     %[tmp1],             %[sum64_hi],         %[tmp1]        \n\t"
+      "or      %[residual_energy],  %[residual_energy],  %[tmp1]        \n\t"
+      ".set    pop                                                      \n\t"
+      : [residual_energy] "=&r" (residual_energy), [tmp1]"=&r"(tmp1),
+        [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+      : [shift_norm] "r" (shift_norm)
+      : "memory"
+    );
+  } else {
+    if ((word32_low & 0x80000000) != 0) {
+      shift_norm = 1;
+      residual_energy = (uint32_t)word32_low >> 1;
+    } else {
+      shift_norm = WebRtcSpl_NormW32(word32_low);
+      residual_energy = word32_low << shift_norm;
+      shift_norm = -shift_norm;
+    }
+  }
+
+  // Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
+  //   = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
+  *q_val_residual_energy =
+      q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2;
+
+  return residual_energy;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
new file mode 100644
index 0000000..82793f1
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class LpcMaskingModelTest : public ::testing::Test {
+ protected:
+  // Pass a function pointer to the Tester function.
+  void CalculateResidualEnergyTester(
+      CalculateResidualEnergy CalculateResidualEnergyFunction) {
+    const int kIntOrder = 10;
+    const int32_t kInt32QDomain = 5;
+    const int kIntShift = 11;
+    int16_t a[kIntOrder + 1] = {32760, 122,   7,   0, -32760, -3958,
+                                -48,   18745, 498, 9, 23456};
+    int32_t corr[kIntOrder + 1] = {11443647, -27495, 0, 98745, -11443600, 1,
+                                   1,        498,    9, 888,   23456};
+    int q_shift_residual = 0;
+    int32_t residual_energy = 0;
+
+    // Test the code path where (residual_energy >= 0x10000).
+    residual_energy = CalculateResidualEnergyFunction(
+        kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+    EXPECT_EQ(1789023310, residual_energy);
+    EXPECT_EQ(2, q_shift_residual);
+
+    // Test the code path where (residual_energy < 0x10000)
+    // and ((energy & 0x8000) != 0).
+    for (int i = 0; i < kIntOrder + 1; i++) {
+      a[i] = 24575 >> i;
+      corr[i] = i;
+    }
+    residual_energy = CalculateResidualEnergyFunction(
+        kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+    EXPECT_EQ(1595279092, residual_energy);
+    EXPECT_EQ(26, q_shift_residual);
+
+    // Test the code path where (residual_energy <= 0x7fff).
+    for (int i = 0; i < kIntOrder + 1; i++) {
+      a[i] = 2457 >> i;
+    }
+    residual_energy = CalculateResidualEnergyFunction(
+        kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+    EXPECT_EQ(2029266944, residual_energy);
+    EXPECT_EQ(33, q_shift_residual);
+  }
+};
+
+TEST_F(LpcMaskingModelTest, CalculateResidualEnergyTest) {
+  CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyC);
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
new file mode 100644
index 0000000..d495d29
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
@@ -0,0 +1,1281 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.c
+ *
+ * Coding tables for the KLT coefficients
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+
+/* indices of KLT coefficients used */
+const uint16_t WebRtcIsacfix_kSelIndGain[12] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+  10,  11};
+
+const uint16_t WebRtcIsacfix_kSelIndShape[108] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
+  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
+  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
+  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
+  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
+  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
+  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
+  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
+  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
+  100,  101,  102,  103,  104,  105,  106,  107
+};
+
+/* cdf array for model indicator */
+const uint16_t WebRtcIsacfix_kModelCdf[4] = {
+  0,  15434,  37548,  65535
+};
+
+/* pointer to cdf array for model indicator */
+const uint16_t *WebRtcIsacfix_kModelCdfPtr[1] = {
+  WebRtcIsacfix_kModelCdf
+};
+
+/* initial cdf index for decoder of model indicator */
+const uint16_t WebRtcIsacfix_kModelInitIndex[1] = {
+  1
+};
+
+/* offset to go from rounded value to quantization index */
+const int16_t WebRtcIsacfix_kQuantMinGain[12] ={
+  3,  6,  4,  6,  6,  9,  5,  16,  11,  34,  32,  47
+};
+
+const int16_t WebRtcIsacfix_kQuantMinShape[108] = {
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+  1,  1,  1,  1,  2,  2,  2,  3,  0,  0,
+  0,  0,  1,  0,  0,  0,  0,  1,  1,  1,
+  1,  1,  1,  2,  2,  3,  0,  0,  0,  0,
+  1,  0,  1,  1,  1,  1,  1,  1,  1,  2,
+  2,  4,  3,  5,  0,  0,  0,  0,  1,  1,
+  1,  1,  1,  1,  2,  1,  2,  2,  3,  4,
+  4,  7,  0,  0,  1,  1,  1,  1,  1,  1,
+  1,  2,  3,  2,  3,  4,  4,  5,  7,  13,
+  0,  1,  1,  2,  3,  2,  2,  2,  4,  4,
+  5,  6,  7,  11, 9, 13, 12, 26
+};
+
+/* maximum quantization index */
+const uint16_t WebRtcIsacfix_kMaxIndGain[12] = {
+  6,  12,  8,  14,  10,  19,  12,  31,  22,  56,  52,  138
+};
+
+const uint16_t WebRtcIsacfix_kMaxIndShape[108] = {
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+  2,  2,  2,  2,  4,  4,  5,  6,  0,  0,
+  0,  0,  1,  0,  0,  0,  0,  1,  2,  2,
+  2,  2,  3,  4,  5,  7,  0,  0,  0,  0,
+  2,  0,  2,  2,  2,  2,  3,  2,  2,  4,
+  4,  6,  6,  9,  0,  0,  0,  0,  2,  2,
+  2,  2,  2,  2,  3,  2,  4,  4,  7,  7,
+  9,  13, 0,  0,  2,  2,  2,  2,  2,  2,
+  3,  4,  5,  4,  6,  8,  8, 10, 16, 25,
+  0,  2,  2,  4,  5,  4,  4,  4,  7,  8,
+  9, 10, 13, 19, 17, 23, 25, 49
+};
+
+/* index offset */
+const uint16_t WebRtcIsacfix_kOffsetGain[3][12] = {
+  { 0,  7,  20,  29,  44,  55,  75,  88,  120,  143,  200,  253},
+  { 0,  7,  19,  27,  42,  53,  73,  86,  117,  140,  197,  249},
+  { 0,  7,  20,  28,  44,  55,  75,  89,  121,  145,  202,  257}
+};
+
+const uint16_t WebRtcIsacfix_kOffsetShape[3][108] = {
+  {
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+    11,  14,  17,  20,  23,  28,  33,  39,  46,  47,
+    48,  49,  50,  52,  53,  54,  55,  56,  58,  61,
+    64,  67,  70,  74,  79,  85,  93,  94,  95,  96,
+    97,  100,  101,  104,  107,  110,  113,  117,  120,  123,
+    128,  133,  140,  147,  157,  158,  159,  160,  161,  164,
+    167,  170,  173,  176,  179,  183,  186,  191,  196,  204,
+    212,  222,  236,  237,  238,  241,  244,  247,  250,  253,
+    256,  260,  265,  271,  276,  283,  292,  301,  312,  329,
+    355,  356,  359,  362,  367,  373,  378,  383,  388,  396,
+    405,  415,  426,  440,  460,  478,  502,  528
+  },
+  {
+    0,  1,  2,  3,  4,  6,  7,  8,  9,  11,
+    13,  16,  19,  22,  26,  29,  34,  39,  45,  46,
+    47,  48,  49,  50,  51,  52,  53,  55,  57,  60,
+    63,  66,  70,  73,  78,  84,  91,  92,  93,  94,
+    95,  96,  97,  99,  102,  105,  108,  111,  114,  118,
+    123,  128,  134,  141,  151,  152,  153,  154,  156,  159,
+    162,  165,  168,  171,  174,  177,  181,  186,  194,  200,
+    208,  218,  233,  234,  235,  236,  239,  242,  245,  248,
+    251,  254,  258,  263,  270,  277,  288,  297,  308,  324,
+    349,  351,  354,  357,  361,  366,  372,  378,  383,  390,
+    398,  407,  420,  431,  450,  472,  496,  524
+  },
+  {
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  11,
+    14,  17,  20,  23,  26,  29,  34,  40,  47,  48,
+    49,  50,  51,  52,  53,  54,  55,  58,  61,  64,
+    67,  70,  73,  77,  82,  88,  96,  97,  98,  99,
+    101,  102,  104,  107,  110,  113,  116,  119,  122,  125,
+    129,  134,  141,  150,  160,  161,  162,  163,  166,  168,
+    171,  174,  177,  180,  183,  186,  190,  195,  201,  208,
+    216,  226,  243,  244,  245,  248,  251,  254,  257,  260,
+    263,  268,  273,  278,  284,  291,  299,  310,  323,  340,
+    366,  368,  371,  374,  379,  383,  389,  394,  399,  406,
+    414,  422,  433,  445,  461,  480,  505,  533
+  }
+};
+
+/* initial cdf index for KLT coefficients */
+const uint16_t WebRtcIsacfix_kInitIndexGain[3][12] = {
+  { 3,  6,  4,  7,  5,  10,  6,  16,  11,  28,  26,  69},
+  { 3,  6,  4,  7,  5,  10,  6,  15,  11,  28,  26,  69},
+  { 3,  6,  4,  8,  5,  10,  7,  16,  12,  28,  27,  70}
+};
+
+const uint16_t WebRtcIsacfix_kInitIndexShape[3][108] = {
+  {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+    1,  1,  1,  1,  2,  2,  3,  3,  0,  0,
+    0,  0,  1,  0,  0,  0,  0,  1,  1,  1,
+    1,  1,  2,  2,  3,  4,  0,  0,  0,  0,
+    1,  0,  1,  1,  1,  1,  2,  1,  1,  2,
+    2,  3,  3,  5,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  2,  1,  2,  2,  4,  4,
+    5,  7,  0,  0,  1,  1,  1,  1,  1,  1,
+    2,  2,  3,  2,  3,  4,  4,  5,  8,  13,
+    0,  1,  1,  2,  3,  2,  2,  2,  4,  4,
+    5,  5,  7,  10,  9,  12,  13,  25
+  },
+  {
+    0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
+    1,  1,  1,  2,  1,  2,  2,  3,  0,  0,
+    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
+    1,  2,  1,  2,  3,  3,  0,  0,  0,  0,
+    0,  0,  1,  1,  1,  1,  1,  1,  2,  2,
+    2,  3,  3,  5,  0,  0,  0,  1,  1,  1,
+    1,  1,  1,  1,  1,  2,  2,  4,  3,  4,
+    5,  7,  0,  0,  0,  1,  1,  1,  1,  1,
+    1,  2,  2,  3,  3,  5,  4,  5,  8,  12,
+    1,  1,  1,  2,  2,  3,  3,  2,  3,  4,
+    4,  6,  5,  9,  11,  12,  14,  25
+  },
+  {
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  1,  2,  3,  3,  0,  0,
+    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
+    1,  1,  2,  2,  3,  4,  0,  0,  0,  1,
+    0,  1,  1,  1,  1,  1,  1,  1,  1,  2,
+    2,  3,  4,  5,  0,  0,  0,  1,  1,  1,
+    1,  1,  1,  1,  1,  2,  2,  3,  3,  4,
+    5,  8,  0,  0,  1,  1,  1,  1,  1,  1,
+    2,  2,  2,  3,  3,  4,  5,  6,  8,  13,
+    1,  1,  1,  2,  2,  3,  2,  2,  3,  4,
+    4,  5,  6,  8,  9,  12,  14,  25
+  }
+};
+
+/* offsets for quantizer representation levels*/
+const uint16_t WebRtcIsacfix_kOfLevelsGain[3] = {
+  0,  392,  779
+};
+
+const uint16_t WebRtcIsacfix_kOfLevelsShape[3] = {
+  0,  578,  1152
+};
+
+/* quantizer representation levels */
+
+
+
+const int32_t WebRtcIsacfix_kLevelsGainQ17[1176] = {
+  -364547,-231664,-102123,-573,104807,238257,368823,-758583,-640135,-510291
+  ,-377662,-252785,-113177,2627,112906,248601,389461,522691,644517,763974
+  ,-538963,-368179,-245823,-106095,-890,104299,241111,350730,493190,-800763
+  ,-646230,-510239,-382115,-248623,-111829,-2983,113852,251105,388114,519757
+  ,644048,774712,896334,1057931,-770009,-635310,-503690,-375087,-248106,-108525
+  ,-105,108259,243472,377948,519271,-1160885,-1032044,-914636,-777593,-647891
+  ,-518408,-388028,-254321,-115293,-598,117849,251296,385367,515510,652727
+  ,777432,920363,1038625,1153637,1316836,-632287,-505430,-379430,-248458,-118013
+  ,-888,118762,250266,381650,513327,652169,766471,932113,-2107480,-1971030
+  ,-1827020,-1698263,-1558670,-1436314,-1305377,-1172252,-1047355,-914202,-779651,-651001
+  ,-520999,-390394,-255761,-123490,-1893,126839,256703,385493,518607,651760
+  ,782750,908693,1044131,1163865,1311066,1424177,1582628,1709823,1831740,1955391
+  ,-1423044,-1288917,-1181281,-1043222,-911770,-780354,-646799,-522664,-386721,-258266
+  ,-128060,-1101,128233,259996,390336,519590,649290,778701,908010,1040796
+  ,1161235,1306889,1441882,-4446002,-4301031,-4194304,-4080591,-3947740,-3808975,-3686530
+  ,-3567839,-3383251,-3287089,-3136577,-3017405,-2869860,-2751321,-2619984,-2482932,-2354790
+  ,-2223147,-2090669,-1964135,-1831208,-1706697,-1570817,-1446008,-1305386,-1175773,-1046066
+  ,-915356,-785120,-653614,-524331,-393767,-260442,-130187,-799,128841,261466
+  ,393616,520542,652117,784613,914159,1045399,1181072,1308971,1442502,1570346
+  ,1693912,1843986,1966014,2090474,2224869,2364593,2475934,2628403,2752512,2856640
+  ,-4192441,-4063232,-3917821,-3799195,-3666233,-3519199,-3411021,-3269192,-3135684,-3008826
+  ,-2880875,-2747342,-2620981,-2494872,-2354979,-2229718,-2098939,-1964971,-1835399,-1703452
+  ,-1572806,-1440482,-1311794,-1179338,-1046521,-919823,-785914,-655335,-523416,-395507
+  ,-264833,-132184,-2546,131698,256217,391372,522688,651248,789964,909618
+  ,1035305,1179145,1313824,1436934,1552353,1693722,1815508,1972826,2096328,2228224
+  ,2359296,2490368,2598848,-6160384,-6029312,-5881382,-5767168,-5636096,-5505024,-5373952
+  ,-5228418,-5110384,-4954923,-4880576,-4710990,-4587364,-4471340,-4333905,-4211513,-4051293
+  ,-3907927,-3800105,-3675961,-3538640,-3413663,-3271148,-3152105,-3019103,-2869647,-2744015
+  ,-2620639,-2479385,-2364211,-2227611,-2095427,-1974497,-1834168,-1703561,-1568961,-1439826
+  ,-1309192,-1174050,-1050191,-917836,-786015,-656943,-518934,-394831,-257708,-128041
+  ,1610,128991,264442,393977,521383,653849,788164,918641,1049122,1181971
+  ,1308934,1439505,1571808,1706305,1836318,1966235,2097269,2228990,2357005,2490292
+  ,2617400,2749680,2881234,3014880,3145637,3276467,3409099,3536637,3671493,3802918
+  ,3929740,4065036,4194143,4325999,4456126,4586857,4717194,4843923,4978676,5110913
+  ,5245281,5371394,5499780,5633779,5762611,5897682,6028688,6167546,6296465,6421682
+  ,6548882,6682074,6809432,6941956,7078143,7204509,7334296,7475137,7609896,7732044
+  ,7861604,8002039,8131670,8259222,8390299,8522399,8650037,8782348,8908402,9037815
+  ,9164594,9300338,9434679,9574500,9699702,9833934,9948152,10083972,10244937,10332822
+  ,10485760,10600122,10760754,10892964,11010048,11111004,11272192,11403264,11525091,11624984
+  ,11796480,11915146,-393216,-262144,-101702,-740,100568,262144,393216,-786432
+  ,-655360,-524288,-383907,-243301,-94956,-156,95547,269629,416691,524288
+  ,655360,-393216,-262144,-88448,-37,87318,262144,393216,524288,-917504
+  ,-786432,-655360,-495894,-373308,-267503,-93211,4119,91308,250895,393216
+  ,526138,655360,786432,917504,-786432,-655360,-524288,-393216,-262144,-83497
+  ,222,86893,240922,393216,524288,-1048576,-917504,-790472,-655360,-508639
+  ,-383609,-262016,-95550,-3775,96692,256797,364847,534906,655360,786432
+  ,889679,1048576,1179648,1310720,1441792,-655360,-524288,-377684,-248408,-93690
+  ,1261,95441,227519,393216,524288,655360,786432,917504,-2097152,-1966080
+  ,-1809470,-1703936,-1572864,-1441792,-1314289,-1195149,-1056205,-917504,-809951,-657769
+  ,-521072,-383788,-248747,-106350,-2944,105550,243408,388548,521064,628732
+  ,786432,885456,1064548,1179648,1310720,1441792,1572864,1703936,1835008,-1441792
+  ,-1310720,-1179648,-1037570,-888492,-767774,-646634,-519935,-373458,-248029,-111915
+  ,760,111232,247735,379432,507672,672699,786432,917504,1048576,1179648
+  ,1310720,1441792,-4456448,-4325376,-4194304,-4063232,-3932160,-3801088,-3670016,-3538944
+  ,-3407872,-3276800,-3145728,-3014656,-2883584,-2752512,-2647002,-2490368,-2359296,-2228224
+  ,-2097152,-1951753,-1835008,-1703936,-1594177,-1462001,-1289150,-1160774,-1025917,-924928
+  ,-782509,-641294,-516191,-386630,-251910,-118886,5210,121226,253949,386008
+  ,517973,649374,780064,917783,1052462,1183856,1290593,1419389,1556641,1699884
+  ,1835008,1988314,2090470,2228224,2359296,2490368,2621440,2752512,2883584,-3801088
+  ,-3643514,-3539937,-3409931,-3263294,-3145658,-3012952,-2879230,-2752359,-2622556,-2483471
+  ,-2357556,-2226500,-2093112,-1965892,-1833664,-1701035,-1567767,-1440320,-1310556,-1178339
+  ,-1049625,-916812,-786477,-655277,-525050,-393773,-264828,-130696,-480,132126
+  ,260116,394197,527846,652294,785563,917183,1049511,1175958,1308161,1438759
+  ,1572253,1698835,1828535,1967072,2089391,2212798,2348901,2461547,2621440,2752512
+  ,2883584,-7309870,-7203780,-7062699,-6939106,-6790819,-6672036,-6553600,-6422317,-6288422
+  ,-6164694,-6026456,-5901410,-5754168,-5621459,-5502710,-5369686,-5240454,-5120712,-4976140
+  ,-4847970,-4723070,-4589083,-4450923,-4324680,-4189892,-4065551,-3931803,-3800209,-3668539
+  ,-3539395,-3404801,-3277470,-3141389,-3016710,-2885724,-2752612,-2618541,-2486762,-2354153
+  ,-2225059,-2094984,-1968194,-1830895,-1699508,-1575743,-1444516,-1308683,-1179714,-1053088
+  ,-917981,-783707,-653900,-524980,-395409,-260309,-131948,-3452,132113,263241
+  ,392185,522597,654134,788288,919810,1045795,1179210,1314201,1444235,1574447
+  ,1705193,1834009,1967332,2098102,2229019,2359147,2489859,2619878,2754966,2879671
+  ,3014438,3146143,3276733,3405958,3542196,3667493,3798815,3932961,4062458,4187125
+  ,4322346,4454875,4587752,4716809,4848274,4975027,5111957,5242215,5373085,5501158
+  ,5640140,5762918,5895358,6024008,6157906,6290628,6422713,6546339,6675888,6815606
+  ,6955288,7077501,7211630,7337893,7473635,7607175,7728310,7866475,7999658,8127888
+  ,8241758,8386483,8522550,8641582,8771915,8922139,9038632,9179385,9313426,9437184
+  ,9568256,9699328,9830400,9952933,10120004,10223616,10354688,10474645,10616832,-393216
+  ,-262144,-85425,-121,82533,262144,393216,-786432,-655360,-524288,-379928
+  ,-222821,-95200,287,95541,227093,393216,493567,655360,786432,-393216
+  ,-262144,-86805,510,86722,262144,393216,524288,-1048576,-917504,-786432
+  ,-624456,-529951,-395071,-241627,-101168,81,99975,241605,393216,524288
+  ,655360,786432,917504,-786432,-655360,-524288,-393216,-230359,-95619,-137
+  ,94425,226222,393216,524288,-1179648,-1048576,-917504,-773841,-655360,-492258
+  ,-379715,-244707,-103621,-434,104523,242680,381575,523659,650565,786432
+  ,917504,1048576,1179648,1310720,-786432,-629344,-524288,-376757,-242858,-101932
+  ,-2715,107155,239212,366480,514943,655360,786432,917504,-2228224,-2097152
+  ,-1966080,-1835008,-1703936,-1572864,-1441792,-1284584,-1179648,-1048819,-934658,-777181
+  ,-626371,-515660,-377493,-248975,-113036,436,113584,248354,379718,512475
+  ,653932,796494,917504,1048576,1179648,1310720,1441792,1572864,1703936,1835008
+  ,-1572864,-1441792,-1297608,-1161159,-1032316,-917092,-779770,-647384,-515529,-384269
+  ,-250003,-119252,1053,118111,249512,380545,512039,648101,770656,907003
+  ,1021725,1178082,1310720,1441792,-4587520,-4456448,-4325376,-4194304,-4063232,-3932160
+  ,-3801088,-3670016,-3538944,-3407872,-3276800,-3145728,-2999335,-2883584,-2752512,-2621440
+  ,-2490368,-2359296,-2228224,-2112691,-1966080,-1848781,-1709830,-1566109,-1438427,-1303530
+  ,-1176124,-1040936,-913876,-784585,-652025,-518361,-385267,-256342,-127297,-2733
+  ,125422,257792,389363,519911,651106,783805,909407,1044143,1174156,1309267
+  ,1436173,1553771,1708958,1814083,1967036,2095386,2255169,2359296,2478303,2621440
+  ,2752512,-4456448,-4325376,-4194304,-4063232,-3932160,-3797524,-3670016,-3560250,-3413217
+  ,-3257719,-3166416,-2986626,-2878000,-2781144,-2625383,-2495465,-2346792,-2230930,-2077063
+  ,-1949225,-1819274,-1697261,-1568664,-1443074,-1304302,-1175289,-1043794,-913423,-785561
+  ,-652104,-522835,-392667,-260517,-130088,-2,129509,260990,391931,522470
+  ,655770,784902,917093,1046445,1176951,1303121,1441362,1565401,1702022,1822856
+  ,1952852,2090384,2214607,2338436,2457483,2621440,-8781824,-8650752,-8519680,-8388608
+  ,-8260828,-8126464,-8003337,-7859030,-7750057,-7602176,-7471104,-7340032,-7193045,-7090588
+  ,-6946816,-6843344,-6676635,-6557575,-6447804,-6277614,-6159736,-6035729,-5884723,-5739567
+  ,-5634818,-5489867,-5372864,-5243300,-5098939,-4988639,-4856258,-4728494,-4591717,-4447428
+  ,-4322409,-4192918,-4062638,-3934141,-3797545,-3673373,-3531587,-3407391,-3277404,-3147797
+  ,-3013578,-2886548,-2749811,-2616428,-2490949,-2361301,-2228482,-2096883,-1964343,-1831754
+  ,-1702201,-1572495,-1442012,-1309242,-1182451,-1048996,-916905,-786510,-657079,-524730
+  ,-393672,-261313,-128743,166,130678,261334,393287,524155,655570,786839
+  ,917353,1052167,1179013,1309360,1442634,1571153,1703961,1832027,1965014,2097912
+  ,2224861,2355341,2490455,2623051,2753484,2877015,3015783,3144157,3273705,3405255
+  ,3542006,3669580,3802417,3935413,4065088,4190896,4333521,4456355,4579781,4713832
+  ,4845707,4978625,5113278,5243817,5382318,5500592,5638135,5761179,5900822,6029270
+  ,6186398,6297816,6436435,6559163,6666389,6806548,6950461,7086078,7195777,7350973
+  ,7480132,7614852,7743514,7847288,8014762,8126464,8257536,8388608,8519680,8650752
+  ,8781824,8912896,9043968,9175040,9306112,9437184
+};
+
+
+
+const int16_t WebRtcIsacfix_kLevelsShapeQ10[1735] = {
+  0,     0,    -1,     0,     0,     1,     0,     1,     0,  -821
+  ,     1,  -763,    -1,   656,  -620,     0,   633,  -636,     4,   615
+  ,  -630,     1,   649, -1773,  -670,     5,   678,  1810, -1876,  -676
+  ,     0,   691,  1843, -1806,  -743,    -1,   749,  1795,  2920, -2872
+  , -1761,  -772,    -3,   790,  1763,  2942,     0,     0,     0,     0
+  ,  -792,     2,     0,     0,     1,     0,  -854,     0,  -702,    -1
+  ,   662,  -624,    -5,   638,  -611,    -6,   638,  -647,     0,   651
+  ,  -685,    -4,   679,  2123, -1814,  -693,     0,   664,  1791, -1735
+  ,  -737,     0,   771,  1854,  2873, -2867, -1842,  -793,    -1,   821
+  ,  1826,  2805,  3922,     0,     0,     0,    -1,  -779,     1,   786
+  ,     1,  -708,     0,   789,  -799,     1,   797,  -663,     2,   646
+  ,  -600,     3,   609,  -600,     1,   658,  1807,  -627,    -3,   612
+  ,  -625,     3,   632, -1732,  -674,     1,   672,  2048, -1768,  -715
+  ,     0,   724,  1784, -3881, -3072, -1774,  -719,    -1,   730,  1811
+  , -2963, -1829,  -806,    -1,   816,  1795,  3050, -5389, -3784, -2942
+  , -1893,  -865,   -12,   867,  1885,  2945,  3928,    -2,     1,     4
+  ,     0,  -694,     2,   665,  -598,     5,   587,  -599,    -1,   661
+  ,  -656,    -7,   611,  -607,     5,   603,  -618,    -4,   620, -1794
+  ,  -645,    -2,   654,  -655,    -1,   658, -1801,  -700,     5,   707
+  ,  1927, -1752,  -745,    -8,   752,  1843, -2838, -1781,  -801,    11
+  ,   796,  1811,  2942,  3866, -3849, -3026, -1848,  -819,     2,   827
+  ,  1825,  2963, -3873, -2904, -1869,  -910,    -6,   903,  1902,  2885
+  ,  3978,  5286, -7168, -6081, -4989, -3968, -2963, -1970,  -943,    -2
+  ,   953,  1951,  2968,  3974,  5009,  6032,    -2,     3, -1024,     2
+  ,  1024,  -637,     1,   669,  -613,    -7,   630,  -603,     4,   612
+  ,  -612,     0,   590,  -645,   -11,   627,  -657,    -2,   671,  1849
+  , -1853,  -694,     2,   702,  1838, -3304, -1780,  -736,    -8,   732
+  ,  1772, -1709,  -755,    -6,   760,  1780, -2994, -1780,  -800,     8
+  ,   819,  1830,  2816, -4096, -2822, -1881,  -851,    -4,   855,  1872
+  ,  2840,  3899, -3908, -2904, -1878,  -887,     6,   897,  1872,  2942
+  ,  4008, -4992, -3881, -2933, -1915,  -928,     1,   937,  1919,  2900
+  ,  4009,  4881, -6848, -6157, -5065, -3981, -2983, -1972,  -978,    -1
+  ,   968,  1979,  2988,  4008,  5007,  6108,  7003,  8051,  9027,-13272
+  ,-12012,-11228,-10213, -9261, -8084, -7133, -6075, -5052, -4050, -3036
+  , -2014,  -996,    -4,  1007,  2031,  3038,  4049,  5074,  6134,  7069
+  ,  8094,  9069, 10212, 11049, 12104,    51, -1024,   -13,  1024,  -609
+  ,  -107,   613, -2048,  -687,   -95,   667,  2048, -3072, -1724,  -785
+  ,   -34,   732,  1819, -2048,  -703,   -26,   681,  2048, -2048,  -686
+  ,    -9,   665,  2048, -2048,  -702,    37,   748,  1723, -4096, -2786
+  , -1844,  -837,    37,   811,  1742,  3072, -4096, -2783, -1848,  -881
+  ,    39,   898,  1843,  2792,  3764, -5120, -4096, -2923, -1833,  -852
+  ,   -14,   862,  1824,  2834,  4096, -6144, -5120, -3914, -2842, -1870
+  ,  -886,   -27,   888,  1929,  2931,  4051, -7168, -6144, -5120, -3866
+  , -2933, -1915,  -927,    64,   933,  1902,  2929,  3912,  5063,  6144
+  ,-11264,-10240, -9216, -8192, -7086, -6144, -5039, -3972, -2943, -1929
+  ,  -941,     3,   938,  1942,  2959,  3933,  4905,  6088,  6983,  8192
+  , -9216, -8192, -7202, -6088, -4983, -4019, -2955, -1975,  -966,    17
+  ,   997,  1981,  2967,  3990,  4948,  6022,  6967,  8192,-13312,-12288
+  ,-11264,-10240, -9216, -8049, -6997, -6040, -5026, -4043, -3029, -2034
+  , -1015,   -23,   984,  1997,  3010,  4038,  5002,  6015,  6946,  8061
+  ,  9216, 10240,-12381,-11264,-10240, -9060, -8058, -7153, -6085, -5075
+  , -4051, -3042, -2037, -1017,    -5,  1007,  2028,  3035,  4050,  5088
+  ,  6111,  7160,  8156,  9215, 10095, 11229, 12202, 13016,-26624,-25600
+  ,-24582,-23671,-22674,-21400,-20355,-19508,-18315,-17269,-16361,-15299
+  ,-14363,-13294,-12262,-11237,-10203, -9227, -8165, -7156, -6116, -5122
+  , -4076, -3056, -2043, -1020,    -8,  1027,  2047,  3065,  4110,  5130
+  ,  6125,  7168,  8195,  9206, 10230, 11227, 12256, 13304, 14281, 15316
+  , 16374, 17382, 18428, 19388, 20361, 21468, 22448, 23781,     0,     0
+  ,    -1,     0,    -2,  1024,     0,     0,     0,    -1,  1024, -1024
+  ,     1, -1024,     4,  1024, -1024,     2,  1024, -1024,     2,  1024
+  , -2048, -1024,    -4,  1024, -1024,     2,  1024, -2048, -1024,    -3
+  ,  1024,  2048, -2048, -1024,     4,  1024,  2048, -3072, -2048, -1024
+  ,    -1,   662,  2048,     0,     1,     0,     0,     1,    -2,    -2
+  ,     0,     2,  1024,    -1,  1024, -1024,     4,  1024, -1024,     1
+  ,  1024, -1024,     1,  1024, -2048,  -781,    -4,   844,  -807,    -5
+  ,   866, -2048,  -726,   -13,   777,  2048, -2048,  -643,    -4,   617
+  ,  2048,  3072, -3072, -2048,  -629,     1,   630,  2048,  3072,     0
+  ,    -1,     1,    -2,     2,     1, -1024,     5, -1024,     6,  1024
+  , -1024,     4,  1024, -1024,     1,  1024, -1024,    -9,  1024,  -673
+  ,    -7,   655, -2048,  -665,   -15,   716, -2048,  -647,     4,   640
+  ,  2048, -2048,  -615,    -1,   635,  2048, -2048,  -613,    10,   637
+  ,  2048,  3072, -3072, -2048,  -647,    -3,   641,  2048,  3072, -5120
+  , -4096, -3072, -2048,  -681,     6,   685,  2048,  3072,  4096,     1
+  ,     1,     0,    -1,  1024, -1024,    -3,  1024, -1024,     6,  1024
+  , -1024,    -1,   769,  -733,     0,  1024,  -876,    -2,   653, -1024
+  ,    -4,   786,  -596,   -13,   595,  -634,    -2,   638,  2048, -2048
+  ,  -620,    -5,   620,  2048, -4096, -3072, -2048,  -639,    11,   655
+  ,  2048,  3072, -3072, -2048,  -659,     5,   663,  2048, -3072, -1823
+  ,  -687,    22,   695,  2048,  3072,  4096, -4096, -3072, -1848,  -715
+  ,    -3,   727,  1816,  3072,  4096,  5120, -8192, -7168, -6144, -5120
+  , -4096, -2884, -1771,  -756,   -14,   775,  1844,  3072,  4096,  5120
+  ,  6144,    -1,     1,     0, -1024,     2,   815,  -768,     2,   708
+  , -1024,    -3,   693,  -661,    -7,   607,  -643,    -5,   609,  -624
+  ,     3,   631,  -682,    -3,   691,  2048, -2048,  -640,     5,   650
+  ,  2048, -3072, -2048,  -701,     9,   704,  2048,  3072, -3072, -2048
+  ,  -670,    10,   674,  2048,  3072, -5120, -4096, -3072, -1749,  -738
+  ,     0,   733,  1811,  3072,  4096,  5120, -4096, -3072, -1873,  -753
+  ,     0,   756,  1874,  3072,  4096, -5120, -4096, -2900, -1838,  -793
+  ,    -6,   793,  1868,  2837,  4096,  5120, -7168, -6144, -5120, -4096
+  , -2832, -1891,  -828,     1,   828,  1901,  2823,  3912,  5120,  6144
+  ,  7168,  8192,-13312,-12288,-11264,-10240, -9216, -8192, -7168, -6144
+  , -5120, -3976, -3004, -1911,  -869,     7,   869,  1932,  3024,  3992
+  ,  5009,  6144,  7168,  8192,  9216, 10240, 11264,    -4,  1024,  -629
+  ,   -22,   609,  -623,     9,   640, -2048,  -768,     1,   682, -2048
+  ,  -741,    49,   722,  2048, -3072, -1706,  -808,   -20,   768,  1750
+  , -1684,  -727,   -29,   788,  1840,  3033, -1758,  -784,     0,   801
+  ,  1702, -3072, -1813,  -814,    38,   820,  1884,  2927, -4096, -3241
+  , -1839,  -922,    25,   882,  1886,  2812, -4096, -2982, -1923,  -894
+  ,    84,   912,  1869,  2778,  4096, -4928, -3965, -2902, -1920,  -883
+  ,     3,   917,  1953,  2921,  3957,  4922,  6144,  7168, -5120, -3916
+  , -2897, -1949,  -930,    31,   959,  1934,  2901,  3851,  5120, -9216
+  , -8192, -7046, -6029, -5030, -4034, -2980, -1969, -1013,   -76,   963
+  ,  1963,  2901,  3929,  4893,  6270,  7168,  8192,  9216,-12288,-11264
+  ,-10240, -9216, -8192, -6846, -6123, -5108, -4008, -3000, -1963,  -954
+  ,    -6,   958,  1992,  3009,  4020,  5085,  6097,  7168,  8192,  9216
+  ,-11264,-10139, -9194, -8127, -7156, -6102, -5053, -4049, -3036, -2025
+  , -1009,   -34,   974,  1984,  3034,  4028,  5138,  6000,  7057,  8166
+  ,  9070, 10033, 11360, 12288,-13312,-12288,-10932,-10190, -9120, -8123
+  , -7128, -6103, -5074, -4081, -3053, -2029,  -989,    -4,  1010,  2028
+  ,  3051,  4073,  5071,  6099,  7132,  8147,  9295, 10159, 11023, 12263
+  , 13312, 14336,-25600,-24576,-23552,-22529,-21504,-20480,-19456,-18637
+  ,-17425,-16165,-15316,-14327,-13606,-12135,-11182,-10107, -9153, -8144
+  , -7146, -6160, -5129, -4095, -3064, -2038, -1025,     1,  1031,  2072
+  ,  3074,  4088,  5123,  6149,  7157,  8173,  9198, 10244, 11250, 12268
+  , 13263, 14289, 15351, 16370, 17402, 18413, 19474, 20337, 21386, 22521
+  , 23367, 24350,     0,     0,     0,     0,     0,     0,     0,     0
+  , -1024,     0,  1024, -1024,     0,  1024, -1024,     0,  1024, -1024
+  ,     0,  1024, -1024,     0,  1024,  -773,     0,  1024,  -674,     0
+  ,   645, -2048,  -745,     0,   628,  2048, -2048,  -712,     0,   681
+  ,  2048,  3072, -3072, -2048,  -673,     0,   682,  1964,  3257,     0
+  ,     0,     0,     0,     0,     0,     0,     0, -1024,     0,  1024
+  , -1024,     0,  1024, -1024,     0,  1024,  -705,     0,   623,  -771
+  ,     0,  1024,  -786,     0,   688,  -631,     0,   652,  2048, -2048
+  ,  -627,    -1,   666,  2048, -3072, -1756,  -694,     0,   674,  2048
+  , -3098, -1879,  -720,     5,   694,  1886,  2958,  4096,     0,     0
+  ,     0,     0,  1024,     0,     0,  1024,  -769,     0,  1024, -1024
+  ,     0,  1024, -1024,     0,  1024,  -817,     0,   734,  -786,     0
+  ,   651,  -638,     0,   637,  -623,     0,   671,  -652,     0,   619
+  ,  2048, -2048,  -670,    -1,   663,  2048, -1908,  -680,     1,   686
+  ,  2048,  3072,  4096, -4096, -3072, -1833,  -711,     0,   727,  1747
+  ,  3072,  4096, -4096, -2971, -1826,  -762,     2,   766,  1832,  2852
+  ,  3928,  5079,     0,     0,     0, -1024,     0,  1024, -1024,     0
+  ,  -656,     0,  1024,  -599,     0,   620, -1024,     0,  1024,  -603
+  ,     0,   622,  -643,     0,   660,  -599,     0,   611,  -641,    -1
+  ,   651,  2048, -2048,  -648,    -2,   647,  1798, -3072, -2048,  -672
+  ,     2,   670,  2048, -3072, -1780,  -694,    -1,   706,  1751,  3072
+  , -3072, -1862,  -757,     7,   739,  1798,  3072,  4096, -5120, -4096
+  , -3253, -1811,  -787,     3,   782,  1887,  3123,  4096, -7252, -6144
+  , -5354, -4060, -2864, -1863,  -820,   -11,   847,  1903,  2970,  3851
+  ,  4921,  5957,  7168,  8192,  9306,     0,     0, -1024,     0,  1024
+  ,  -726,     0,   706,  -692,     0,   593,  -598,     0,   616,  -624
+  ,     0,   616,  -605,     0,   613, -2048,  -652,     1,   635,  2048
+  , -2048,  -647,    -1,   660,  2048, -1811,  -668,    -2,   685,  2048
+  , -1796,  -731,    -2,   730,  1702,  3072, -3072, -1766,  -747,    -4
+  ,   756,  1770,  3072, -4096, -3024, -1762,  -783,     4,   771,  1781
+  ,  3072, -5120, -4057, -2807, -1832,  -822,     0,   816,  1804,  2851
+  ,  3949,  5120, -6144, -4899, -3927, -2920, -1893,  -874,    -2,   868
+  ,  1881,  2905,  3960,  4912,  6144, -9216, -8192, -7168, -6225, -4963
+  , -3943, -2956, -1890,  -902,     0,   897,  1914,  2916,  3984,  4990
+  ,  6050,  7168,-11264,-10217, -9114, -8132, -7035, -5988, -4984, -4000
+  , -2980, -1962,  -927,     7,   931,  1956,  2981,  4031,  4972,  6213
+  ,  7227,  8192,  9216, 10240, 11170, 12288, 13312, 14336,     0,  1024
+  ,  -557,     1,   571,  -606,    -4,   612, -1676,  -707,    10,   673
+  ,  2048, -2048,  -727,     5,   686, -3072, -1772,  -755,    12,   716
+  ,  1877, -1856,  -786,     2,   786,  1712, -1685,  -818,   -16,   863
+  ,  1729, -3072, -1762,  -857,     3,   866,  1838,  2841, -3862, -2816
+  , -1864,  -925,    -2,   923,  1897,  2779, -2782, -1838,  -920,   -28
+  ,   931,  1951,  2835,  3804, -4815, -4001, -2940, -1934,  -959,   -22
+  ,   975,  1957,  2904,  3971,  4835, -5148, -3892, -2944, -1953,  -986
+  ,   -11,   989,  1968,  2939,  3949,  4947,  5902, -9216, -8192, -6915
+  , -6004, -4965, -4013, -3009, -1977,  -987,    -1,   982,  1972,  3000
+  ,  3960,  4939,  5814, -8976, -7888, -7084, -5955, -5043, -4009, -2991
+  , -2002, -1000,    -8,   993,  2011,  3023,  4026,  5028,  6023,  7052
+  ,  8014,  9216,-11240,-10036, -9125, -8118, -7105, -6062, -5048, -4047
+  , -3044, -2025, -1009,    -1,  1011,  2023,  3042,  4074,  5085,  6108
+  ,  7119,  8142,  9152, 10114, 11141, 12250, 13307,-15360,-14099,-13284
+  ,-12291,-11223,-10221, -9152, -8147, -7128, -6104, -5077, -4072, -3062
+  , -2033, -1020,     7,  1018,  2038,  3059,  4081,  5084,  6109,  7102
+  ,  8128,  9134, 10125, 11239, 12080,-23552,-22528,-21504,-20480,-19456
+  ,-18159,-17240,-16291,-15364,-14285,-13305,-12271,-11233,-10217, -9198
+  , -8175, -7157, -6134, -5122, -4089, -3071, -2047, -1018,     3,  1026
+  ,  2041,  3077,  4090,  5108,  6131,  7150,  8172,  9175, 10196, 11272
+  , 12303, 13273, 14328, 15332, 16334, 17381, 18409, 19423, 20423, 21451
+  , 22679, 23391, 24568, 25600, 26589
+};
+
+/* cdf tables for quantizer indices */
+const uint16_t WebRtcIsacfix_kCdfGain[1212] = {
+  0,  13,  301,  3730,  61784,  65167,  65489,  65535,  0,  17,
+  142,  314,  929,  2466,  7678,  56450,  63463,  64740,  65204,  65426,
+  65527,  65535,  0,  8,  100,  724,  6301,  60105,  65125,  65510,
+  65531,  65535,  0,  13,  117,  368,  1068,  3010,  11928,  53603,
+  61177,  63404,  64505,  65108,  65422,  65502,  65531,  65535,  0,  4,
+  17,  96,  410,  1859,  12125,  54361,  64103,  65305,  65497,  65535,
+  0,  4,  88,  230,  469,  950,  1746,  3228,  6092,  16592,
+  44756,  56848,  61256,  63308,  64325,  64920,  65309,  65460,  65502,  65522,
+  65535,  0,  88,  352,  1675,  6339,  20749,  46686,  59284,  63525,
+  64949,  65359,  65502,  65527,  65535,  0,  13,  38,  63,  117,
+  234,  381,  641,  929,  1407,  2043,  2809,  4032,  5753,  8792,
+  14407,  24308,  38941,  48947,  55403,  59293,  61411,  62688,  63630,  64329,
+  64840,  65188,  65376,  65472,  65506,  65527,  65531,  65535,  0,  8,
+  29,  75,  222,  615,  1327,  2801,  5623,  9931,  16094,  24966,
+  34419,  43458,  50676,  56186,  60055,  62500,  63936,  64765,  65225,  65435,
+  65514,  65535,  0,  8,  13,  15,  17,  21,  33,  59,
+  71,  92,  151,  243,  360,  456,  674,  934,  1223,  1583,
+  1989,  2504,  3031,  3617,  4354,  5154,  6163,  7411,  8780,  10747,
+  12874,  15591,  18974,  23027,  27436,  32020,  36948,  41830,  46205,  49797,
+  53042,  56094,  58418,  60360,  61763,  62818,  63559,  64103,  64509,  64798,
+  65045,  65162,  65288,  65363,  65447,  65506,  65522,  65531,  65533,  65535,
+  0,  4,  6,  25,  38,  71,  138,  264,  519,  808,
+  1227,  1825,  2516,  3408,  4279,  5560,  7092,  9197,  11420,  14108,
+  16947,  20300,  23926,  27459,  31164,  34827,  38575,  42178,  45540,  48747,
+  51444,  54090,  56426,  58460,  60080,  61595,  62734,  63668,  64275,  64673,
+  64936,  65112,  65217,  65334,  65426,  65464,  65477,  65489,  65518,  65527,
+  65529,  65531,  65533,  65535,  0,  2,  4,  8,  10,  12,
+  14,  16,  21,  33,  50,  71,  84,  92,  105,  138,
+  180,  255,  318,  377,  435,  473,  511,  590,  682,  758,
+  913,  1097,  1256,  1449,  1671,  1884,  2169,  2445,  2772,  3157,
+  3563,  3944,  4375,  4848,  5334,  5820,  6448,  7101,  7716,  8378,
+  9102,  9956,  10752,  11648,  12707,  13670,  14758,  15910,  17187,  18472,
+  19627,  20649,  21951,  23169,  24283,  25552,  26862,  28227,  29391,  30764,
+  31882,  33213,  34432,  35600,  36910,  38116,  39464,  40729,  41872,  43144,
+  44371,  45514,  46762,  47813,  48968,  50069,  51032,  51974,  52908,  53737,
+  54603,  55445,  56282,  56990,  57572,  58191,  58840,  59410,  59887,  60264,
+  60607,  60946,  61269,  61516,  61771,  61960,  62198,  62408,  62558,  62776,
+  62985,  63207,  63408,  63546,  63739,  63906,  64070,  64237,  64371,  64551,
+  64677,  64836,  64999,  65095,  65213,  65284,  65338,  65380,  65426,  65447,
+  65472,  65485,  65487,  65489,  65502,  65510,  65512,  65514,  65516,  65518,
+  65522,  65531,  65533,  65535,  0,  2,  4,  6,  65528,  65531,
+  65533,  65535,  0,  2,  4,  6,  8,  10,  222,  65321,
+  65513,  65528,  65531,  65533,  65535,  0,  2,  4,  50,  65476,
+  65529,  65531,  65533,  65535,  0,  2,  4,  6,  8,  12,
+  38,  544,  64936,  65509,  65523,  65525,  65529,  65531,  65533,  65535,
+  0,  2,  4,  6,  8,  10,  1055,  64508,  65528,  65531,
+  65533,  65535,  0,  2,  4,  6,  8,  10,  12,  123,
+  3956,  62999,  65372,  65495,  65515,  65521,  65523,  65525,  65527,  65529,
+  65531,  65533,  65535,  0,  2,  4,  12,  53,  4707,  59445,
+  65467,  65525,  65527,  65529,  65531,  65533,  65535,  0,  2,  4,
+  6,  8,  10,  12,  14,  16,  38,  40,  50,  67,
+  96,  234,  929,  14345,  55750,  64866,  65389,  65462,  65514,  65517,
+  65519,  65521,  65523,  65525,  65527,  65529,  65531,  65533,  65535,  0,
+  2,  4,  6,  8,  10,  15,  35,  91,  377,  1946,
+  13618,  52565,  63714,  65184,  65465,  65520,  65523,  65525,  65527,  65529,
+  65531,  65533,  65535,  0,  2,  4,  6,  8,  10,  12,
+  14,  16,  18,  20,  22,  24,  26,  28,  30,  32,
+  34,  36,  38,  40,  42,  44,  46,  48,  50,  52,
+  54,  82,  149,  362,  751,  1701,  4239,  12893,  38627,  55072,
+  60875,  63071,  64158,  64702,  65096,  65283,  65412,  65473,  65494,  65505,
+  65508,  65517,  65519,  65521,  65523,  65525,  65527,  65529,  65531,  65533,
+  65535,  0,  2,  15,  23,  53,  143,  260,  418,  698,
+  988,  1353,  1812,  2411,  3144,  4015,  5143,  6401,  7611,  8999,
+  10653,  12512,  14636,  16865,  19404,  22154,  24798,  27521,  30326,  33102,
+  35790,  38603,  41415,  43968,  46771,  49435,  52152,  54715,  57143,  59481,
+  61178,  62507,  63603,  64489,  64997,  65257,  65427,  65473,  65503,  65520,
+  65529,  65531,  65533,  65535,  0,  3,  6,  9,  26,  32,
+  44,  46,  64,  94,  111,  164,  205,  254,  327,  409,
+  506,  608,  733,  885,  1093,  1292,  1482,  1742,  1993,  2329,
+  2615,  3029,  3374,  3798,  4257,  4870,  5405,  5992,  6618,  7225,
+  7816,  8418,  9051,  9761,  10532,  11380,  12113,  13010,  13788,  14594,
+  15455,  16361,  17182,  18088,  18997,  20046,  20951,  21968,  22947,  24124,
+  25296,  26547,  27712,  28775,  29807,  30835,  31709,  32469,  33201,  34014,
+  34876,  35773,  36696,  37620,  38558,  39547,  40406,  41277,  42367,  43290,
+  44445,  45443,  46510,  47684,  48973,  50157,  51187,  52242,  53209,  54083,
+  55006,  55871,  56618,  57293,  57965,  58556,  59222,  59722,  60180,  60554,
+  60902,  61250,  61554,  61837,  62100,  62372,  62631,  62856,  63078,  63324,
+  63557,  63768,  63961,  64089,  64235,  64352,  64501,  64633,  64770,  64887,
+  65001,  65059,  65121,  65188,  65246,  65302,  65346,  65390,  65428,  65463,
+  65477,  65506,  65515,  65517,  65519,  65521,  65523,  65525,  65527,  65529,
+  65531,  65533,  65535,  0,  2,  4,  109,  65332,  65531,  65533,
+  65535,  0,  2,  4,  6,  8,  25,  1817,  63874,  65511,
+  65527,  65529,  65531,  65533,  65535,  0,  2,  4,  907,  65014,
+  65529,  65531,  65533,  65535,  0,  2,  4,  6,  8,  10,
+  12,  132,  2743,  62708,  65430,  65525,  65527,  65529,  65531,  65533,
+  65535,  0,  2,  4,  6,  8,  35,  3743,  61666,  65485,
+  65531,  65533,  65535,  0,  2,  4,  6,  8,  10,  23,
+  109,  683,  6905,  58417,  64911,  65398,  65497,  65518,  65525,  65527,
+  65529,  65531,  65533,  65535,  0,  2,  4,  6,  53,  510,
+  10209,  55212,  64573,  65441,  65522,  65529,  65531,  65533,  65535,  0,
+  2,  4,  6,  8,  10,  12,  14,  16,  18,  20,
+  22,  32,  90,  266,  1037,  3349,  14468,  50488,  62394,  64685,
+  65341,  65480,  65514,  65519,  65521,  65523,  65525,  65527,  65529,  65531,
+  65533,  65535,  0,  2,  4,  6,  9,  16,  37,  106,
+  296,  748,  1868,  5733,  18897,  45553,  60165,  63949,  64926,  65314,
+  65441,  65508,  65524,  65529,  65531,  65533,  65535,  0,  2,  4,
+  6,  8,  10,  12,  14,  16,  18,  20,  22,  24,
+  26,  28,  30,  32,  34,  36,  38,  40,  42,  44,
+  46,  48,  50,  83,  175,  344,  667,  1293,  2337,  4357,
+  8033,  14988,  28600,  43244,  52011,  57042,  59980,  61779,  63065,  63869,
+  64390,  64753,  64988,  65164,  65326,  65422,  65462,  65492,  65506,  65522,
+  65524,  65526,  65531,  65533,  65535,  0,  2,  4,  6,  8,
+  10,  12,  14,  16,  25,  39,  48,  55,  62,  65,
+  85,  106,  139,  169,  194,  252,  323,  485,  688,  1074,
+  1600,  2544,  3863,  5733,  8303,  11397,  15529,  20273,  25734,  31455,
+  36853,  41891,  46410,  50306,  53702,  56503,  58673,  60479,  61880,  62989,
+  63748,  64404,  64852,  65124,  65309,  65424,  65480,  65524,  65528,  65533,
+  65535,  0,  2,  4,  6,  8,  10,  12,  14,  21,
+  23,  25,  27,  29,  31,  39,  41,  43,  48,  60,
+  72,  79,  106,  136,  166,  187,  224,  252,  323,  381,
+  427,  478,  568,  660,  783,  912,  1046,  1175,  1365,  1567,
+  1768,  2024,  2347,  2659,  3049,  3529,  4033,  4623,  5281,  5925,
+  6726,  7526,  8417,  9468,  10783,  12141,  13571,  15222,  16916,  18659,
+  20350,  22020,  23725,  25497,  27201,  29026,  30867,  32632,  34323,  36062,
+  37829,  39466,  41144,  42654,  43981,  45343,  46579,  47759,  49013,  50171,
+  51249,  52283,  53245,  54148,  54938,  55669,  56421,  57109,  57791,  58464,
+  59092,  59674,  60105,  60653,  61083,  61407,  61757,  62095,  62388,  62649,
+  62873,  63157,  63358,  63540,  63725,  63884,  64046,  64155,  64278,  64426,
+  64548,  64654,  64806,  64906,  64994,  65077,  65137,  65215,  65277,  65324,
+  65354,  65409,  65437,  65455,  65462,  65490,  65495,  65499,  65508,  65511,
+  65513,  65515,  65517,  65519,  65521,  65523,  65525,  65527,  65529,  65531,
+  65533,  65535
+};
+
+const uint16_t WebRtcIsacfix_kCdfShape[2059] = {
+  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,
+  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  4,
+  65535,  0,  8,  65514,  65535,  0,  29,  65481,  65535,  0,
+  121,  65439,  65535,  0,  239,  65284,  65535,  0,  8,  779,
+  64999,  65527,  65535,  0,  8,  888,  64693,  65522,  65535,  0,
+  29,  2604,  62843,  65497,  65531,  65535,  0,  25,  176,  4576,
+  61164,  65275,  65527,  65535,  0,  65535,  0,  65535,  0,  65535,
+  0,  65535,  0,  4,  65535,  0,  65535,  0,  65535,  0,
+  65535,  0,  65535,  0,  4,  65535,  0,  33,  65502,  65535,
+  0,  54,  65481,  65535,  0,  251,  65309,  65535,  0,  611,
+  65074,  65535,  0,  1273,  64292,  65527,  65535,  0,  4,  1809,
+  63940,  65518,  65535,  0,  88,  4392,  60603,  65426,  65531,  65535,
+  0,  25,  419,  7046,  57756,  64961,  65514,  65531,  65535,  0,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  4,  65531,
+  65535,  0,  65535,  0,  8,  65531,  65535,  0,  4,  65527,
+  65535,  0,  17,  65510,  65535,  0,  42,  65481,  65535,  0,
+  197,  65342,  65531,  65535,  0,  385,  65154,  65535,  0,  1005,
+  64522,  65535,  0,  8,  1985,  63469,  65533,  65535,  0,  38,
+  3119,  61884,  65514,  65535,  0,  4,  6,  67,  4961,  60804,
+  65472,  65535,  0,  17,  565,  9182,  56538,  65087,  65514,  65535,
+  0,  8,  63,  327,  2118,  14490,  52774,  63839,  65376,  65522,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+  17,  65522,  65535,  0,  59,  65489,  65535,  0,  50,  65522,
+  65535,  0,  54,  65489,  65535,  0,  310,  65179,  65535,  0,
+  615,  64836,  65535,  0,  4,  1503,  63965,  65535,  0,  2780,
+  63383,  65535,  0,  21,  3919,  61051,  65527,  65535,  0,  84,
+  6674,  59929,  65435,  65535,  0,  4,  255,  7976,  55784,  65150,
+  65518,  65531,  65535,  0,  4,  8,  582,  10726,  53465,  64949,
+  65518,  65535,  0,  29,  339,  3006,  17555,  49517,  62956,  65200,
+  65497,  65531,  65535,  0,  2,  33,  138,  565,  2324,  7670,
+  22089,  45966,  58949,  63479,  64966,  65380,  65518,  65535,  0,  65535,
+  0,  65535,  0,  2,  65533,  65535,  0,  46,  65514,  65535,
+  0,  414,  65091,  65535,  0,  540,  64911,  65535,  0,  419,
+  65162,  65535,  0,  976,  64790,  65535,  0,  2977,  62495,  65531,
+  65535,  0,  4,  3852,  61034,  65527,  65535,  0,  4,  29,
+  6021,  60243,  65468,  65535,  0,  84,  6711,  58066,  65418,  65535,
+  0,  13,  281,  9550,  54917,  65125,  65506,  65535,  0,  2,
+  63,  984,  12108,  52644,  64342,  65435,  65527,  65535,  0,  29,
+  251,  2014,  14871,  47553,  62881,  65229,  65518,  65535,  0,  13,
+  142,  749,  4220,  18497,  45200,  60913,  64823,  65426,  65527,  65535,
+  0,  13,  71,  264,  1176,  3789,  10500,  24480,  43488,  56324,
+  62315,  64493,  65242,  65464,  65514,  65522,  65531,  65535,  0,  4,
+  13,  38,  109,  205,  448,  850,  1708,  3429,  6276,  11371,
+  19221,  29734,  40955,  49391,  55411,  59460,  62102,  63793,  64656,  65150,
+  65401,  65485,  65522,  65531,  65535,  0,  65535,  0,  2,  65533,
+  65535,  0,  1160,  65476,  65535,  0,  2,  6640,  64763,  65533,
+  65535,  0,  2,  38,  9923,  61009,  65527,  65535,  0,  2,
+  4949,  63092,  65533,  65535,  0,  2,  3090,  63398,  65533,  65535,
+  0,  2,  2520,  58744,  65510,  65535,  0,  2,  13,  544,
+  8784,  51403,  65148,  65533,  65535,  0,  2,  25,  1017,  10412,
+  43550,  63651,  65489,  65527,  65535,  0,  2,  4,  29,  783,
+  13377,  52462,  64524,  65495,  65533,  65535,  0,  2,  4,  6,
+  100,  1817,  18451,  52590,  63559,  65376,  65531,  65535,  0,  2,
+  4,  6,  46,  385,  2562,  11225,  37416,  60488,  65026,  65487,
+  65529,  65533,  65535,  0,  2,  4,  6,  8,  10,  12,
+  42,  222,  971,  5221,  19811,  45048,  60312,  64486,  65294,  65474,
+  65525,  65529,  65533,  65535,  0,  2,  4,  8,  71,  167,
+  666,  2533,  7875,  19622,  38082,  54359,  62108,  64633,  65290,  65495,
+  65529,  65533,  65535,  0,  2,  4,  6,  8,  10,  13,
+  109,  586,  1930,  4949,  11600,  22641,  36125,  48312,  56899,  61495,
+  63927,  64932,  65389,  65489,  65518,  65531,  65533,  65535,  0,  4,
+  6,  8,  67,  209,  712,  1838,  4195,  8432,  14432,  22834,
+  31723,  40523,  48139,  53929,  57865,  60657,  62403,  63584,  64363,  64907,
+  65167,  65372,  65472,  65514,  65535,  0,  2,  4,  13,  25,
+  42,  46,  50,  75,  113,  147,  281,  448,  657,  909,
+  1185,  1591,  1976,  2600,  3676,  5317,  7398,  9914,  12941,  16169,
+  19477,  22885,  26464,  29851,  33360,  37228,  41139,  44802,  48654,  52058,
+  55181,  57676,  59581,  61022,  62190,  63107,  63676,  64199,  64547,  64924,
+  65158,  65313,  65430,  65481,  65518,  65535,  0,  65535,  0,  65535,
+  0,  65535,  0,  65535,  0,  65533,  65535,  0,  65535,  0,
+  65535,  0,  65535,  0,  65533,  65535,  0,  2,  65535,  0,
+  2,  65533,  65535,  0,  2,  65533,  65535,  0,  2,  65533,
+  65535,  0,  2,  4,  65533,  65535,  0,  2,  65533,  65535,
+  0,  2,  4,  65531,  65533,  65535,  0,  2,  4,  65531,
+  65533,  65535,  0,  2,  4,  6,  65524,  65533,  65535,  0,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+  65535,  0,  65535,  0,  65535,  0,  65533,  65535,  0,  65533,
+  65535,  0,  2,  65533,  65535,  0,  2,  65533,  65535,  0,
+  2,  65533,  65535,  0,  2,  4,  65532,  65535,  0,  6,
+  65523,  65535,  0,  2,  15,  65530,  65533,  65535,  0,  2,
+  35,  65493,  65531,  65533,  65535,  0,  2,  4,  158,  65382,
+  65531,  65533,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+  65535,  0,  65535,  0,  65535,  0,  2,  65535,  0,  2,
+  65533,  65535,  0,  2,  65533,  65535,  0,  2,  65533,  65535,
+  0,  2,  65533,  65535,  0,  9,  65512,  65535,  0,  2,
+  12,  65529,  65535,  0,  2,  73,  65434,  65533,  65535,  0,
+  2,  240,  65343,  65533,  65535,  0,  2,  476,  65017,  65531,
+  65533,  65535,  0,  2,  4,  1046,  64686,  65531,  65533,  65535,
+  0,  2,  4,  6,  8,  1870,  63898,  65529,  65531,  65533,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65533,  65535,
+  0,  2,  65533,  65535,  0,  2,  65533,  65535,  0,  2,
+  65532,  65535,  0,  6,  65533,  65535,  0,  6,  65523,  65535,
+  0,  2,  65532,  65535,  0,  137,  65439,  65535,  0,  576,
+  64899,  65533,  65535,  0,  2,  289,  65299,  65533,  65535,  0,
+  2,  4,  6,  880,  64134,  65531,  65533,  65535,  0,  2,
+  4,  1853,  63347,  65533,  65535,  0,  2,  6,  2516,  61762,
+  65529,  65531,  65533,  65535,  0,  2,  4,  9,  3980,  61380,
+  65503,  65529,  65531,  65533,  65535,  0,  2,  4,  6,  8,
+  10,  12,  61,  6393,  59859,  65466,  65527,  65529,  65531,  65533,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  2,  65532,
+  65535,  0,  3,  65529,  65535,  0,  2,  65529,  65535,  0,
+  61,  65453,  65535,  0,  234,  65313,  65535,  0,  503,  65138,
+  65535,  0,  155,  65402,  65533,  65535,  0,  2,  1058,  64554,
+  65533,  65535,  0,  2,  4,  3138,  62109,  65531,  65533,  65535,
+  0,  2,  4,  2031,  63339,  65531,  65533,  65535,  0,  2,
+  4,  6,  9,  4155,  60778,  65523,  65529,  65531,  65533,  65535,
+  0,  2,  4,  41,  6189,  59269,  65490,  65531,  65533,  65535,
+  0,  2,  4,  6,  210,  8789,  57043,  65400,  65528,  65531,
+  65533,  65535,  0,  2,  4,  6,  8,  26,  453,  10086,
+  55499,  64948,  65483,  65524,  65527,  65529,  65531,  65533,  65535,  0,
+  2,  4,  6,  8,  10,  12,  14,  16,  18,  20,
+  114,  1014,  11202,  52670,  64226,  65356,  65503,  65514,  65523,  65525,
+  65527,  65529,  65531,  65533,  65535,  0,  65533,  65535,  0,  15,
+  65301,  65535,  0,  152,  64807,  65535,  0,  2,  3328,  63308,
+  65535,  0,  2,  4050,  59730,  65533,  65535,  0,  2,  164,
+  10564,  61894,  65529,  65535,  0,  15,  6712,  59831,  65076,  65532,
+  65535,  0,  32,  7712,  57449,  65459,  65535,  0,  2,  210,
+  7849,  53110,  65021,  65523,  65535,  0,  2,  12,  1081,  13883,
+  48262,  62870,  65477,  65535,  0,  2,  88,  847,  6145,  37852,
+  62012,  65454,  65533,  65535,  0,  9,  47,  207,  1823,  14522,
+  45521,  61069,  64891,  65481,  65528,  65531,  65533,  65535,  0,  2,
+  9,  488,  2881,  12758,  38703,  58412,  64420,  65410,  65533,  65535,
+  0,  2,  4,  6,  61,  333,  1891,  6486,  19720,  43188,
+  57547,  62472,  64796,  65421,  65497,  65523,  65529,  65531,  65533,  65535,
+  0,  2,  4,  6,  8,  10,  12,  29,  117,  447,
+  1528,  6138,  21242,  43133,  56495,  62432,  64746,  65362,  65500,  65529,
+  65531,  65533,  65535,  0,  2,  18,  105,  301,  760,  1490,
+  3472,  7568,  15002,  26424,  40330,  53029,  60048,  62964,  64274,  64890,
+  65337,  65445,  65489,  65513,  65527,  65530,  65533,  65535,  0,  2,
+  4,  6,  41,  102,  409,  853,  2031,  4316,  7302,  11328,
+  16869,  24825,  34926,  43481,  50877,  56126,  59874,  62103,  63281,  63857,
+  64166,  64675,  65382,  65522,  65531,  65533,  65535,  0,  2,  4,
+  6,  8,  10,  12,  14,  16,  18,  29,  38,  53,
+  58,  96,  181,  503,  1183,  2849,  5590,  8600,  11379,  13942,
+  16478,  19453,  22638,  26039,  29411,  32921,  37596,  41433,  44998,  48560,
+  51979,  55106,  57666,  59892,  61485,  62616,  63484,  64018,  64375,  64685,
+  64924,  65076,  65278,  65395,  65471,  65509,  65529,  65535,  0,  65535,
+  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,
+  0,  65535,  0,  65535,  0,  2,  65533,  65535,  0,  2,
+  65533,  65535,  0,  2,  65533,  65535,  0,  2,  65533,  65535,
+  0,  2,  65533,  65535,  0,  2,  65533,  65535,  0,  7,
+  65519,  65535,  0,  2,  14,  65491,  65533,  65535,  0,  2,
+  81,  65427,  65531,  65533,  65535,  0,  2,  4,  312,  65293,
+  65528,  65533,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+  2,  65533,  65535,  0,  2,  65533,  65535,  0,  2,  65533,
+  65535,  0,  5,  65523,  65535,  0,  2,  65533,  65535,  0,
+  7,  65526,  65535,  0,  46,  65464,  65533,  65535,  0,  2,
+  120,  65309,  65533,  65535,  0,  2,  5,  362,  65097,  65533,
+  65535,  0,  2,  18,  1164,  64785,  65528,  65531,  65533,  65535,
+  0,  65535,  0,  65535,  0,  65535,  0,  65533,  65535,  0,
+  65535,  0,  65533,  65535,  0,  2,  65533,  65535,  0,  2,
+  65533,  65535,  0,  2,  65533,  65535,  0,  2,  65530,  65535,
+  0,  2,  65523,  65535,  0,  69,  65477,  65535,  0,  141,
+  65459,  65535,  0,  194,  65325,  65533,  65535,  0,  2,  543,
+  64912,  65533,  65535,  0,  5,  1270,  64301,  65529,  65531,  65533,
+  65535,  0,  2,  4,  12,  2055,  63538,  65508,  65531,  65533,
+  65535,  0,  2,  7,  102,  3775,  61970,  65429,  65526,  65528,
+  65533,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  2,
+  65533,  65535,  0,  2,  65535,  0,  9,  65533,  65535,  0,
+  25,  65512,  65535,  0,  2,  65533,  65535,  0,  44,  65480,
+  65535,  0,  48,  65475,  65535,  0,  162,  65373,  65535,  0,
+  637,  64806,  65533,  65535,  0,  2,  935,  64445,  65533,  65535,
+  0,  2,  4,  1662,  64083,  65533,  65535,  0,  2,  12,
+  3036,  62469,  65521,  65533,  65535,  0,  2,  120,  5405,  60468,
+  65469,  65531,  65533,  65535,  0,  2,  4,  18,  254,  6663,
+  58999,  65272,  65528,  65533,  65535,  0,  2,  4,  9,  12,
+  67,  591,  8981,  56781,  64564,  65365,  65508,  65524,  65526,  65529,
+  65531,  65533,  65535,  0,  65535,  0,  65535,  0,  2,  65533,
+  65535,  0,  9,  65526,  65535,  0,  14,  65503,  65535,  0,
+  127,  65390,  65535,  0,  517,  64990,  65535,  0,  178,  65330,
+  65535,  0,  2,  1055,  64533,  65533,  65535,  0,  2,  1558,
+  63942,  65533,  65535,  0,  2,  2205,  63173,  65533,  65535,  0,
+  25,  4493,  60862,  65505,  65533,  65535,  0,  2,  48,  5890,
+  59442,  65482,  65533,  65535,  0,  2,  4,  127,  7532,  58191,
+  65394,  65533,  65535,  0,  2,  5,  32,  550,  10388,  54924,
+  65046,  65510,  65531,  65533,  65535,  0,  2,  4,  30,  150,
+  1685,  14340,  51375,  63619,  65288,  65503,  65528,  65533,  65535,  0,
+  2,  4,  6,  8,  28,  97,  473,  2692,  15407,  50020,
+  62880,  65064,  65445,  65508,  65531,  65533,  65535,  0,  2,  4,
+  12,  32,  79,  150,  372,  907,  2184,  5868,  18207,  45431,
+  59856,  64031,  65096,  65401,  65481,  65507,  65521,  65523,  65525,  65527,
+  65529,  65531,  65533,  65535,  0,  65533,  65535,  0,  182,  65491,
+  65535,  0,  877,  64286,  65535,  0,  9,  2708,  63612,  65533,
+  65535,  0,  2,  6038,  59532,  65535,  0,  2,  92,  5500,
+  60539,  65533,  65535,  0,  268,  8908,  56512,  65385,  65535,  0,
+  129,  13110,  52742,  65036,  65535,  0,  2,  806,  14003,  51929,
+  64732,  65523,  65535,  0,  7,  92,  2667,  18159,  47678,  62610,
+  65355,  65535,  0,  32,  1836,  19676,  48237,  61677,  64960,  65526,
+  65535,  0,  21,  159,  967,  5668,  22782,  44709,  58317,  64020,
+  65406,  65528,  65535,  0,  7,  162,  1838,  8328,  23929,  43014,
+  56394,  63374,  65216,  65484,  65521,  65535,  0,  2,  4,  6,
+  28,  268,  1120,  3613,  10688,  24185,  40989,  54917,  61684,  64510,
+  65403,  65530,  65535,  0,  2,  16,  44,  139,  492,  1739,
+  5313,  13558,  26766,  41566,  52446,  58937,  62815,  64480,  65201,  65454,
+  65524,  65533,  65535,  0,  7,  25,  76,  263,  612,  1466,
+  3325,  6832,  12366,  20152,  29466,  39255,  47360,  53506,  57740,  60726,
+  62845,  64131,  64882,  65260,  65459,  65521,  65528,  65530,  65535,  0,
+  2,  4,  14,  48,  136,  312,  653,  1240,  2369,  4327,
+  7028,  10759,  15449,  21235,  28027,  35386,  42938,  49562,  54990,  59119,
+  62086,  63916,  64863,  65249,  65445,  65493,  65523,  65535,  0,  2,
+  4,  6,  8,  10,  12,  21,  83,  208,  409,  723,
+  1152,  1868,  2951,  4463,  6460,  8979,  11831,  15195,  18863,  22657,
+  26762,  30881,  34963,  39098,  43054,  47069,  50620,  53871,  56821,  59386,
+  61340,  62670,  63512,  64023,  64429,  64750,  64944,  65126,  65279,  65366,
+  65413,  65445,  65473,  65505,  65510,  65521,  65528,  65530,  65535
+};
+
+/* pointers to cdf tables for quantizer indices */
+const uint16_t *WebRtcIsacfix_kCdfGainPtr[3][12] = {
+  { WebRtcIsacfix_kCdfGain +0 +0,   WebRtcIsacfix_kCdfGain +0 +8,   WebRtcIsacfix_kCdfGain +0 +22,
+    WebRtcIsacfix_kCdfGain +0 +32,  WebRtcIsacfix_kCdfGain +0 +48,  WebRtcIsacfix_kCdfGain +0 +60,
+    WebRtcIsacfix_kCdfGain +0 +81,  WebRtcIsacfix_kCdfGain +0 +95,  WebRtcIsacfix_kCdfGain +0 +128,
+    WebRtcIsacfix_kCdfGain +0 +152, WebRtcIsacfix_kCdfGain +0 +210, WebRtcIsacfix_kCdfGain +0 +264
+  },
+  { WebRtcIsacfix_kCdfGain +404 +0,   WebRtcIsacfix_kCdfGain +404 +8,   WebRtcIsacfix_kCdfGain +404 +21,
+    WebRtcIsacfix_kCdfGain +404 +30,  WebRtcIsacfix_kCdfGain +404 +46,  WebRtcIsacfix_kCdfGain +404 +58,
+    WebRtcIsacfix_kCdfGain +404 +79,  WebRtcIsacfix_kCdfGain +404 +93,  WebRtcIsacfix_kCdfGain +404 +125,
+    WebRtcIsacfix_kCdfGain +404 +149, WebRtcIsacfix_kCdfGain +404 +207, WebRtcIsacfix_kCdfGain +404 +260
+  },
+  { WebRtcIsacfix_kCdfGain +803 +0,   WebRtcIsacfix_kCdfGain +803 +8,   WebRtcIsacfix_kCdfGain +803 +22,
+    WebRtcIsacfix_kCdfGain +803 +31,  WebRtcIsacfix_kCdfGain +803 +48,  WebRtcIsacfix_kCdfGain +803 +60,
+    WebRtcIsacfix_kCdfGain +803 +81,  WebRtcIsacfix_kCdfGain +803 +96,  WebRtcIsacfix_kCdfGain +803 +129,
+    WebRtcIsacfix_kCdfGain +803 +154, WebRtcIsacfix_kCdfGain +803 +212, WebRtcIsacfix_kCdfGain +803 +268
+  }
+};
+
+const uint16_t *WebRtcIsacfix_kCdfShapePtr[3][108] = {
+  { WebRtcIsacfix_kCdfShape +0 +0,   WebRtcIsacfix_kCdfShape +0 +2,   WebRtcIsacfix_kCdfShape +0 +4,
+    WebRtcIsacfix_kCdfShape +0 +6,   WebRtcIsacfix_kCdfShape +0 +8,   WebRtcIsacfix_kCdfShape +0 +10,
+    WebRtcIsacfix_kCdfShape +0 +12,  WebRtcIsacfix_kCdfShape +0 +14,  WebRtcIsacfix_kCdfShape +0 +16,
+    WebRtcIsacfix_kCdfShape +0 +18,  WebRtcIsacfix_kCdfShape +0 +21,  WebRtcIsacfix_kCdfShape +0 +25,
+    WebRtcIsacfix_kCdfShape +0 +29,  WebRtcIsacfix_kCdfShape +0 +33,  WebRtcIsacfix_kCdfShape +0 +37,
+    WebRtcIsacfix_kCdfShape +0 +43,  WebRtcIsacfix_kCdfShape +0 +49,  WebRtcIsacfix_kCdfShape +0 +56,
+    WebRtcIsacfix_kCdfShape +0 +64,  WebRtcIsacfix_kCdfShape +0 +66,  WebRtcIsacfix_kCdfShape +0 +68,
+    WebRtcIsacfix_kCdfShape +0 +70,  WebRtcIsacfix_kCdfShape +0 +72,  WebRtcIsacfix_kCdfShape +0 +75,
+    WebRtcIsacfix_kCdfShape +0 +77,  WebRtcIsacfix_kCdfShape +0 +79,  WebRtcIsacfix_kCdfShape +0 +81,
+    WebRtcIsacfix_kCdfShape +0 +83,  WebRtcIsacfix_kCdfShape +0 +86,  WebRtcIsacfix_kCdfShape +0 +90,
+    WebRtcIsacfix_kCdfShape +0 +94,  WebRtcIsacfix_kCdfShape +0 +98,  WebRtcIsacfix_kCdfShape +0 +102,
+    WebRtcIsacfix_kCdfShape +0 +107, WebRtcIsacfix_kCdfShape +0 +113, WebRtcIsacfix_kCdfShape +0 +120,
+    WebRtcIsacfix_kCdfShape +0 +129, WebRtcIsacfix_kCdfShape +0 +131, WebRtcIsacfix_kCdfShape +0 +133,
+    WebRtcIsacfix_kCdfShape +0 +135, WebRtcIsacfix_kCdfShape +0 +137, WebRtcIsacfix_kCdfShape +0 +141,
+    WebRtcIsacfix_kCdfShape +0 +143, WebRtcIsacfix_kCdfShape +0 +147, WebRtcIsacfix_kCdfShape +0 +151,
+    WebRtcIsacfix_kCdfShape +0 +155, WebRtcIsacfix_kCdfShape +0 +159, WebRtcIsacfix_kCdfShape +0 +164,
+    WebRtcIsacfix_kCdfShape +0 +168, WebRtcIsacfix_kCdfShape +0 +172, WebRtcIsacfix_kCdfShape +0 +178,
+    WebRtcIsacfix_kCdfShape +0 +184, WebRtcIsacfix_kCdfShape +0 +192, WebRtcIsacfix_kCdfShape +0 +200,
+    WebRtcIsacfix_kCdfShape +0 +211, WebRtcIsacfix_kCdfShape +0 +213, WebRtcIsacfix_kCdfShape +0 +215,
+    WebRtcIsacfix_kCdfShape +0 +217, WebRtcIsacfix_kCdfShape +0 +219, WebRtcIsacfix_kCdfShape +0 +223,
+    WebRtcIsacfix_kCdfShape +0 +227, WebRtcIsacfix_kCdfShape +0 +231, WebRtcIsacfix_kCdfShape +0 +235,
+    WebRtcIsacfix_kCdfShape +0 +239, WebRtcIsacfix_kCdfShape +0 +243, WebRtcIsacfix_kCdfShape +0 +248,
+    WebRtcIsacfix_kCdfShape +0 +252, WebRtcIsacfix_kCdfShape +0 +258, WebRtcIsacfix_kCdfShape +0 +264,
+    WebRtcIsacfix_kCdfShape +0 +273, WebRtcIsacfix_kCdfShape +0 +282, WebRtcIsacfix_kCdfShape +0 +293,
+    WebRtcIsacfix_kCdfShape +0 +308, WebRtcIsacfix_kCdfShape +0 +310, WebRtcIsacfix_kCdfShape +0 +312,
+    WebRtcIsacfix_kCdfShape +0 +316, WebRtcIsacfix_kCdfShape +0 +320, WebRtcIsacfix_kCdfShape +0 +324,
+    WebRtcIsacfix_kCdfShape +0 +328, WebRtcIsacfix_kCdfShape +0 +332, WebRtcIsacfix_kCdfShape +0 +336,
+    WebRtcIsacfix_kCdfShape +0 +341, WebRtcIsacfix_kCdfShape +0 +347, WebRtcIsacfix_kCdfShape +0 +354,
+    WebRtcIsacfix_kCdfShape +0 +360, WebRtcIsacfix_kCdfShape +0 +368, WebRtcIsacfix_kCdfShape +0 +378,
+    WebRtcIsacfix_kCdfShape +0 +388, WebRtcIsacfix_kCdfShape +0 +400, WebRtcIsacfix_kCdfShape +0 +418,
+    WebRtcIsacfix_kCdfShape +0 +445, WebRtcIsacfix_kCdfShape +0 +447, WebRtcIsacfix_kCdfShape +0 +451,
+    WebRtcIsacfix_kCdfShape +0 +455, WebRtcIsacfix_kCdfShape +0 +461, WebRtcIsacfix_kCdfShape +0 +468,
+    WebRtcIsacfix_kCdfShape +0 +474, WebRtcIsacfix_kCdfShape +0 +480, WebRtcIsacfix_kCdfShape +0 +486,
+    WebRtcIsacfix_kCdfShape +0 +495, WebRtcIsacfix_kCdfShape +0 +505, WebRtcIsacfix_kCdfShape +0 +516,
+    WebRtcIsacfix_kCdfShape +0 +528, WebRtcIsacfix_kCdfShape +0 +543, WebRtcIsacfix_kCdfShape +0 +564,
+    WebRtcIsacfix_kCdfShape +0 +583, WebRtcIsacfix_kCdfShape +0 +608, WebRtcIsacfix_kCdfShape +0 +635
+  },
+  { WebRtcIsacfix_kCdfShape +686 +0,   WebRtcIsacfix_kCdfShape +686 +2,   WebRtcIsacfix_kCdfShape +686 +4,
+    WebRtcIsacfix_kCdfShape +686 +6,   WebRtcIsacfix_kCdfShape +686 +8,   WebRtcIsacfix_kCdfShape +686 +11,
+    WebRtcIsacfix_kCdfShape +686 +13,  WebRtcIsacfix_kCdfShape +686 +15,  WebRtcIsacfix_kCdfShape +686 +17,
+    WebRtcIsacfix_kCdfShape +686 +20,  WebRtcIsacfix_kCdfShape +686 +23,  WebRtcIsacfix_kCdfShape +686 +27,
+    WebRtcIsacfix_kCdfShape +686 +31,  WebRtcIsacfix_kCdfShape +686 +35,  WebRtcIsacfix_kCdfShape +686 +40,
+    WebRtcIsacfix_kCdfShape +686 +44,  WebRtcIsacfix_kCdfShape +686 +50,  WebRtcIsacfix_kCdfShape +686 +56,
+    WebRtcIsacfix_kCdfShape +686 +63,  WebRtcIsacfix_kCdfShape +686 +65,  WebRtcIsacfix_kCdfShape +686 +67,
+    WebRtcIsacfix_kCdfShape +686 +69,  WebRtcIsacfix_kCdfShape +686 +71,  WebRtcIsacfix_kCdfShape +686 +73,
+    WebRtcIsacfix_kCdfShape +686 +75,  WebRtcIsacfix_kCdfShape +686 +77,  WebRtcIsacfix_kCdfShape +686 +79,
+    WebRtcIsacfix_kCdfShape +686 +82,  WebRtcIsacfix_kCdfShape +686 +85,  WebRtcIsacfix_kCdfShape +686 +89,
+    WebRtcIsacfix_kCdfShape +686 +93,  WebRtcIsacfix_kCdfShape +686 +97,  WebRtcIsacfix_kCdfShape +686 +102,
+    WebRtcIsacfix_kCdfShape +686 +106, WebRtcIsacfix_kCdfShape +686 +112, WebRtcIsacfix_kCdfShape +686 +119,
+    WebRtcIsacfix_kCdfShape +686 +127, WebRtcIsacfix_kCdfShape +686 +129, WebRtcIsacfix_kCdfShape +686 +131,
+    WebRtcIsacfix_kCdfShape +686 +133, WebRtcIsacfix_kCdfShape +686 +135, WebRtcIsacfix_kCdfShape +686 +137,
+    WebRtcIsacfix_kCdfShape +686 +139, WebRtcIsacfix_kCdfShape +686 +142, WebRtcIsacfix_kCdfShape +686 +146,
+    WebRtcIsacfix_kCdfShape +686 +150, WebRtcIsacfix_kCdfShape +686 +154, WebRtcIsacfix_kCdfShape +686 +158,
+    WebRtcIsacfix_kCdfShape +686 +162, WebRtcIsacfix_kCdfShape +686 +167, WebRtcIsacfix_kCdfShape +686 +173,
+    WebRtcIsacfix_kCdfShape +686 +179, WebRtcIsacfix_kCdfShape +686 +186, WebRtcIsacfix_kCdfShape +686 +194,
+    WebRtcIsacfix_kCdfShape +686 +205, WebRtcIsacfix_kCdfShape +686 +207, WebRtcIsacfix_kCdfShape +686 +209,
+    WebRtcIsacfix_kCdfShape +686 +211, WebRtcIsacfix_kCdfShape +686 +214, WebRtcIsacfix_kCdfShape +686 +218,
+    WebRtcIsacfix_kCdfShape +686 +222, WebRtcIsacfix_kCdfShape +686 +226, WebRtcIsacfix_kCdfShape +686 +230,
+    WebRtcIsacfix_kCdfShape +686 +234, WebRtcIsacfix_kCdfShape +686 +238, WebRtcIsacfix_kCdfShape +686 +242,
+    WebRtcIsacfix_kCdfShape +686 +247, WebRtcIsacfix_kCdfShape +686 +253, WebRtcIsacfix_kCdfShape +686 +262,
+    WebRtcIsacfix_kCdfShape +686 +269, WebRtcIsacfix_kCdfShape +686 +278, WebRtcIsacfix_kCdfShape +686 +289,
+    WebRtcIsacfix_kCdfShape +686 +305, WebRtcIsacfix_kCdfShape +686 +307, WebRtcIsacfix_kCdfShape +686 +309,
+    WebRtcIsacfix_kCdfShape +686 +311, WebRtcIsacfix_kCdfShape +686 +315, WebRtcIsacfix_kCdfShape +686 +319,
+    WebRtcIsacfix_kCdfShape +686 +323, WebRtcIsacfix_kCdfShape +686 +327, WebRtcIsacfix_kCdfShape +686 +331,
+    WebRtcIsacfix_kCdfShape +686 +335, WebRtcIsacfix_kCdfShape +686 +340, WebRtcIsacfix_kCdfShape +686 +346,
+    WebRtcIsacfix_kCdfShape +686 +354, WebRtcIsacfix_kCdfShape +686 +362, WebRtcIsacfix_kCdfShape +686 +374,
+    WebRtcIsacfix_kCdfShape +686 +384, WebRtcIsacfix_kCdfShape +686 +396, WebRtcIsacfix_kCdfShape +686 +413,
+    WebRtcIsacfix_kCdfShape +686 +439, WebRtcIsacfix_kCdfShape +686 +442, WebRtcIsacfix_kCdfShape +686 +446,
+    WebRtcIsacfix_kCdfShape +686 +450, WebRtcIsacfix_kCdfShape +686 +455, WebRtcIsacfix_kCdfShape +686 +461,
+    WebRtcIsacfix_kCdfShape +686 +468, WebRtcIsacfix_kCdfShape +686 +475, WebRtcIsacfix_kCdfShape +686 +481,
+    WebRtcIsacfix_kCdfShape +686 +489, WebRtcIsacfix_kCdfShape +686 +498, WebRtcIsacfix_kCdfShape +686 +508,
+    WebRtcIsacfix_kCdfShape +686 +522, WebRtcIsacfix_kCdfShape +686 +534, WebRtcIsacfix_kCdfShape +686 +554,
+    WebRtcIsacfix_kCdfShape +686 +577, WebRtcIsacfix_kCdfShape +686 +602, WebRtcIsacfix_kCdfShape +686 +631
+  },
+  { WebRtcIsacfix_kCdfShape +1368 +0,   WebRtcIsacfix_kCdfShape +1368 +2,   WebRtcIsacfix_kCdfShape +1368 +4,
+    WebRtcIsacfix_kCdfShape +1368 +6,   WebRtcIsacfix_kCdfShape +1368 +8,   WebRtcIsacfix_kCdfShape +1368 +10,
+    WebRtcIsacfix_kCdfShape +1368 +12,  WebRtcIsacfix_kCdfShape +1368 +14,  WebRtcIsacfix_kCdfShape +1368 +16,
+    WebRtcIsacfix_kCdfShape +1368 +20,  WebRtcIsacfix_kCdfShape +1368 +24,  WebRtcIsacfix_kCdfShape +1368 +28,
+    WebRtcIsacfix_kCdfShape +1368 +32,  WebRtcIsacfix_kCdfShape +1368 +36,  WebRtcIsacfix_kCdfShape +1368 +40,
+    WebRtcIsacfix_kCdfShape +1368 +44,  WebRtcIsacfix_kCdfShape +1368 +50,  WebRtcIsacfix_kCdfShape +1368 +57,
+    WebRtcIsacfix_kCdfShape +1368 +65,  WebRtcIsacfix_kCdfShape +1368 +67,  WebRtcIsacfix_kCdfShape +1368 +69,
+    WebRtcIsacfix_kCdfShape +1368 +71,  WebRtcIsacfix_kCdfShape +1368 +73,  WebRtcIsacfix_kCdfShape +1368 +75,
+    WebRtcIsacfix_kCdfShape +1368 +77,  WebRtcIsacfix_kCdfShape +1368 +79,  WebRtcIsacfix_kCdfShape +1368 +81,
+    WebRtcIsacfix_kCdfShape +1368 +85,  WebRtcIsacfix_kCdfShape +1368 +89,  WebRtcIsacfix_kCdfShape +1368 +93,
+    WebRtcIsacfix_kCdfShape +1368 +97,  WebRtcIsacfix_kCdfShape +1368 +101, WebRtcIsacfix_kCdfShape +1368 +105,
+    WebRtcIsacfix_kCdfShape +1368 +110, WebRtcIsacfix_kCdfShape +1368 +116, WebRtcIsacfix_kCdfShape +1368 +123,
+    WebRtcIsacfix_kCdfShape +1368 +132, WebRtcIsacfix_kCdfShape +1368 +134, WebRtcIsacfix_kCdfShape +1368 +136,
+    WebRtcIsacfix_kCdfShape +1368 +138, WebRtcIsacfix_kCdfShape +1368 +141, WebRtcIsacfix_kCdfShape +1368 +143,
+    WebRtcIsacfix_kCdfShape +1368 +146, WebRtcIsacfix_kCdfShape +1368 +150, WebRtcIsacfix_kCdfShape +1368 +154,
+    WebRtcIsacfix_kCdfShape +1368 +158, WebRtcIsacfix_kCdfShape +1368 +162, WebRtcIsacfix_kCdfShape +1368 +166,
+    WebRtcIsacfix_kCdfShape +1368 +170, WebRtcIsacfix_kCdfShape +1368 +174, WebRtcIsacfix_kCdfShape +1368 +179,
+    WebRtcIsacfix_kCdfShape +1368 +185, WebRtcIsacfix_kCdfShape +1368 +193, WebRtcIsacfix_kCdfShape +1368 +203,
+    WebRtcIsacfix_kCdfShape +1368 +214, WebRtcIsacfix_kCdfShape +1368 +216, WebRtcIsacfix_kCdfShape +1368 +218,
+    WebRtcIsacfix_kCdfShape +1368 +220, WebRtcIsacfix_kCdfShape +1368 +224, WebRtcIsacfix_kCdfShape +1368 +227,
+    WebRtcIsacfix_kCdfShape +1368 +231, WebRtcIsacfix_kCdfShape +1368 +235, WebRtcIsacfix_kCdfShape +1368 +239,
+    WebRtcIsacfix_kCdfShape +1368 +243, WebRtcIsacfix_kCdfShape +1368 +247, WebRtcIsacfix_kCdfShape +1368 +251,
+    WebRtcIsacfix_kCdfShape +1368 +256, WebRtcIsacfix_kCdfShape +1368 +262, WebRtcIsacfix_kCdfShape +1368 +269,
+    WebRtcIsacfix_kCdfShape +1368 +277, WebRtcIsacfix_kCdfShape +1368 +286, WebRtcIsacfix_kCdfShape +1368 +297,
+    WebRtcIsacfix_kCdfShape +1368 +315, WebRtcIsacfix_kCdfShape +1368 +317, WebRtcIsacfix_kCdfShape +1368 +319,
+    WebRtcIsacfix_kCdfShape +1368 +323, WebRtcIsacfix_kCdfShape +1368 +327, WebRtcIsacfix_kCdfShape +1368 +331,
+    WebRtcIsacfix_kCdfShape +1368 +335, WebRtcIsacfix_kCdfShape +1368 +339, WebRtcIsacfix_kCdfShape +1368 +343,
+    WebRtcIsacfix_kCdfShape +1368 +349, WebRtcIsacfix_kCdfShape +1368 +355, WebRtcIsacfix_kCdfShape +1368 +361,
+    WebRtcIsacfix_kCdfShape +1368 +368, WebRtcIsacfix_kCdfShape +1368 +376, WebRtcIsacfix_kCdfShape +1368 +385,
+    WebRtcIsacfix_kCdfShape +1368 +397, WebRtcIsacfix_kCdfShape +1368 +411, WebRtcIsacfix_kCdfShape +1368 +429,
+    WebRtcIsacfix_kCdfShape +1368 +456, WebRtcIsacfix_kCdfShape +1368 +459, WebRtcIsacfix_kCdfShape +1368 +463,
+    WebRtcIsacfix_kCdfShape +1368 +467, WebRtcIsacfix_kCdfShape +1368 +473, WebRtcIsacfix_kCdfShape +1368 +478,
+    WebRtcIsacfix_kCdfShape +1368 +485, WebRtcIsacfix_kCdfShape +1368 +491, WebRtcIsacfix_kCdfShape +1368 +497,
+    WebRtcIsacfix_kCdfShape +1368 +505, WebRtcIsacfix_kCdfShape +1368 +514, WebRtcIsacfix_kCdfShape +1368 +523,
+    WebRtcIsacfix_kCdfShape +1368 +535, WebRtcIsacfix_kCdfShape +1368 +548, WebRtcIsacfix_kCdfShape +1368 +565,
+    WebRtcIsacfix_kCdfShape +1368 +585, WebRtcIsacfix_kCdfShape +1368 +611, WebRtcIsacfix_kCdfShape +1368 +640
+  }
+};
+
+/* code length for all coefficients using different models */
+
+const int16_t WebRtcIsacfix_kCodeLenGainQ11[392] = {
+  25189, 16036,  8717,   358,  8757, 15706, 21456, 24397, 18502, 17559
+  , 13794, 11088,  7480,   873,  6603, 11636, 14627, 16805, 19132, 26624
+  , 26624, 19408, 13751,  7280,   583,  7591, 15178, 23773, 28672, 25189
+  , 19045, 16442, 13412, 10397,  5893,  1338,  6376,  9992, 12074, 13853
+  , 15781, 19821, 22819, 28672, 28672, 25189, 19858, 15781, 11262,  5477
+  ,  1298,  5632, 11814, 17234, 22020, 28672, 19677, 18125, 16587, 14521
+  , 13032, 11196,  9249,  5411,  2495,  4994,  7975, 10234, 12308, 13892
+  , 15148, 17944, 21725, 23917, 25189, 19539, 16293, 11531,  7808,  4475
+  ,  2739,  4872,  8089, 11314, 14992, 18105, 23257, 26624, 25189, 23257
+  , 23257, 20982, 18697, 18023, 16338, 16036, 14539, 13695, 13146, 11763
+  , 10754,  9074,  7260,  5584,  4430,  5553,  6848,  8344, 10141, 11636
+  , 12535, 13416, 14342, 15477, 17296, 19282, 22349, 23773, 28672, 28672
+  , 26624, 23773, 21456, 18023, 15118, 13362, 11212,  9293,  8043,  6985
+  ,  5908,  5721,  5853,  6518,  7316,  8360,  9716, 11289, 12912, 14652
+  , 16969, 19858, 23773, 26624, 28013, 30720, 30720, 28672, 25426, 23141
+  , 25426, 23773, 20720, 19408, 18697, 19282, 16859, 16338, 16026, 15377
+  , 15021, 14319, 14251, 13937, 13260, 13017, 12332, 11703, 11430, 10359
+  , 10128,  9405,  8757,  8223,  7974,  7859,  7646,  7673,  7997,  8580
+  ,  8880,  9061,  9866, 10397, 11358, 12200, 13244, 14157, 15021, 16026
+  , 16490, 18697, 18479, 20011, 19677, 20720, 24576, 26276, 30720, 30720
+  , 28672, 30720, 24068, 25189, 22437, 20345, 18479, 16396, 16026, 14928
+  , 13877, 13450, 12696, 12766, 11626, 11098, 10159,  9998,  9437,  9275
+  ,  8783,  8552,  8629,  8488,  8522,  8454,  8571,  8775,  8915,  9427
+  ,  9483,  9851, 10260, 10933, 11131, 11974, 12560, 13833, 15080, 16304
+  , 17491, 19017, 18697, 19408, 22020, 25189, 25426, 22819, 26276, 30720
+  , 30720, 30720, 30720, 30720, 30720, 28672, 30720, 30720, 30720, 30720
+  , 28013, 25426, 24397, 23773, 25189, 26624, 25189, 22437, 21725, 20011
+  , 20527, 20720, 20771, 22020, 22020, 19858, 19408, 19972, 17866, 17360
+  , 17791, 17219, 16805, 16927, 16067, 16162, 15661, 15178, 15021, 15209
+  , 14845, 14570, 14490, 14490, 13733, 13617, 13794, 13577, 13312, 12824
+  , 13032, 12683, 12189, 12469, 12109, 11940, 11636, 11617, 11932, 12294
+  , 11578, 11775, 12039, 11654, 11560, 11439, 11909, 11421, 12029, 11513
+  , 11773, 11899, 11560, 11805, 11476, 11664, 11963, 11647, 11754, 11963
+  , 11703, 12211, 11932, 12074, 12469, 12535, 12560, 12912, 12783, 12866
+  , 12884, 13378, 13957, 13775, 13635, 14019, 14545, 15240, 15520, 15554
+  , 15697, 16490, 16396, 17281, 16599, 16969, 17963, 16859, 16983, 16805
+  , 17099, 18210, 17219, 17646, 17700, 17646, 18297, 17425, 18479, 17791
+  , 17718, 19282, 18672, 20173, 20982, 21725, 21456, 23773, 23257, 25189
+  , 30720, 30720, 25189, 26624, 30720, 30720, 30720, 30720, 28672, 26276
+  , 30720, 30720
+};
+
+const int16_t WebRtcIsacfix_kCodeLenShapeQ11[578] = {
+  0,     0,     0,     0,     0,     0,     0,     0,     0, 28672
+  ,     0, 26624,     1, 23773, 22819,     4, 20982, 18598,    10, 19282
+  , 16587,    22, 16442, 26624, 13126,    60, 14245, 26624, 26624, 12736
+  ,    79, 12912, 25189, 22819,  9563,   249,  9474, 22349, 28672, 23257
+  , 17944,  7980,   434,  8181, 16431, 26624,     0,     0,     0,     0
+  , 28672,     0,     0,     0,     0,     0, 28672,     0, 22437,     3
+  , 22437, 20982,     5, 20982, 16442,    22, 16752, 13814,    49, 14646
+  , 11645,   116, 11734, 26624, 28672, 10613,   158, 11010, 24397, 19539
+  ,  8046,   453,  7709, 19017, 28672, 23257, 15110,  6770,   758,  6523
+  , 14108, 24397, 28672,     0,     0,     0,     0, 28672,     0, 28672
+  ,     0, 26624,     1, 28672, 28672,     1, 26624, 24397,     2, 23257
+  , 21725,     4, 20982, 17158,    18, 17281, 28672, 15178,    35, 15209
+  , 12343,    92, 12320, 26624, 10344,   189, 10217, 30720, 22020,  9033
+  ,   322,  8549, 23773, 28672, 30720, 20622,  7666,   473,  7806, 20527
+  , 24397, 14135,  5995,   960,  6018, 14872, 23773, 26624, 20928, 16293
+  , 10636,  4926,  1588,  5256, 11088, 18043, 25189,     0,     0,     0
+  ,     0, 24397,     1, 25189, 20720,     5, 21456, 21209,     3, 25189
+  , 20982,     5, 21456, 15818,    30, 15410, 13794,    60, 13416, 28672
+  , 11162,   142, 11025,  9337,   231, 10094, 23773,  8338,   405,  7930
+  , 26624, 19677,  6787,   613,  7318, 19161, 28672, 16442,  6319,   932
+  ,  5748, 15312, 25189, 28672, 28672, 28672, 13998,  5513,  1263,  5146
+  , 14024, 24397, 22819, 15818,  9460,  4447,  2122,  4681,  9970, 15945
+  , 22349, 28672, 30720, 22622, 19017, 14872, 10689,  7405,  4473,  2983
+  ,  4783,  7894, 11186, 14964, 18210, 24397,     0,     0, 30720,     0
+  , 30720, 21456,     3, 23773, 14964,    39, 14757, 14179,    53, 13751
+  , 14928,    36, 15272, 12430,    79, 13228,  9135,   285,  9077, 28672
+  , 28672,  8377,   403,  7919, 26624, 28672, 23257,  7068,   560,  7473
+  , 20345, 19677,  6770,   720,  6464, 18697, 25189, 16249,  5779,  1087
+  ,  5494, 15209, 22819, 30720, 20622, 12601,  5240,  1419,  5091, 12095
+  , 19408, 26624, 22819, 16805, 10683,  4812,  2056,  4293,  9836, 16026
+  , 24397, 25189, 18409, 13833,  8681,  4503,  2653,  4220,  8329, 13853
+  , 19132, 26624, 25189, 20771, 17219, 12630,  9520,  6733,  4565,  3657
+  ,  4817,  7069, 10058, 13212, 16805, 21209, 26624, 26276, 28672, 28672
+  , 26276, 23257, 20173, 19282, 16538, 15051, 12811, 10754,  9267,  7547
+  ,  6270,  5407,  5214,  6057,  7054,  8226,  9488, 10806, 12793, 14442
+  , 16442, 19677, 22099, 26276, 28672,     0, 30720,     0, 30720, 11920
+  ,    56, 20720, 30720,  6766,   355, 13130, 30720, 30720, 22180,  5589
+  ,   736,  7902, 26624, 30720,  7634,   354,  9721, 30720, 30720,  9027
+  ,   246, 10117, 30720, 30720,  9630,   453,  6709, 23257, 30720, 25683
+  , 14228,  6127,  1271,  4615, 15178, 30720, 30720, 23504, 12382,  5739
+  ,  2015,  3492, 10560, 22020, 26624, 30720, 30720, 23257, 13192,  4873
+  ,  1527,  5001, 12445, 22020, 30720, 30720, 30720, 30720, 19344, 10761
+  ,  4051,  1927,  5281, 10594, 17866, 28672, 30720, 30720, 30720, 21869
+  , 15554, 10060,  5979,  2710,  3085,  7889, 14646, 21725, 28672, 30720
+  , 30720, 30720, 30720, 30720, 30720, 30720, 22719, 17425, 13212,  8083
+  ,  4439,  2820,  4305,  8136, 12988, 17425, 21151, 28672, 28672, 30720
+  , 30720, 30720, 28672, 20527, 19282, 14412, 10513,  7407,  5079,  3744
+  ,  4115,  6308,  9621, 13599, 17040, 22349, 28672, 30720, 30720, 30720
+  , 30720, 30720, 30720, 29522, 19282, 14545, 11485,  9093,  6760,  5262
+  ,  4672,  4970,  6005,  7852,  9732, 12343, 14672, 19161, 22819, 25189
+  , 30720, 30720, 28672, 30720, 30720, 20720, 18125, 14388, 12007,  9825
+  ,  8092,  7064,  6069,  5903,  5932,  6359,  7169,  8310,  9324, 10711
+  , 11867, 13096, 14157, 16338, 17040, 19161, 21725, 23773, 30720, 30720
+  , 26276, 25426, 24397, 28672, 28672, 23257, 22020, 22349, 18297, 17646
+  , 16983, 16431, 16162, 15021, 15178, 13751, 12142, 10895, 10193,  9632
+  ,  9086,  8896,  8823,  8735,  8591,  8754,  8649,  8361,  8329,  8522
+  ,  8373,  8739,  8993,  9657, 10454, 11279, 11899, 12614, 14024, 14273
+  , 15477, 15240, 16649, 17866, 18697, 21151, 22099, 0
+  // The final 0 was added due to http://bugs.webrtc.org/10584.
+};
+
+/* left KLT transforms */
+const int16_t WebRtcIsacfix_kT1GainQ15[3][4] = {
+  { -26130, 19773, 19773, 26130 },
+  { -26664, 19046, 19046, 26664 },
+  { -23538, 22797, 22797, 23538 }
+};
+
+
+
+const int16_t WebRtcIsacfix_kT1ShapeQ15[3][324] = {
+  { 52,16,168,7,439,-138,-89,306,671,882,
+    157,1301,291,1598,-3571,-1943,-1119,32404,96,-12,
+    379,-64,-307,345,-836,539,1045,2541,-2865,-992,
+    1683,-4717,5808,7427,30599,2319,183,-73,451,481,
+    933,-198,781,-397,1244,-777,3690,-2414,149,-1356,
+    -2593,-31140,8289,-1737,-202,-14,-214,360,501,450,
+    -245,-7,797,3638,-2804,3042,-337,22137,-22103,2264,
+    6838,-3381,305,172,263,-195,-355,351,179,513,
+    2234,3343,5509,7531,19075,-17740,-16836,2244,-629,-1505,
+    -153,108,124,-324,2694,-124,1492,-850,5347,4285,
+    7439,-10229,-22822,-12467,-12891,3645,822,-232,131,13,
+    374,565,536,4681,1294,-1935,1926,-5734,-10643,26462,
+    -12480,-5589,-1038,-2468,964,-704,-247,-106,186,-558,
+    -4050,3760,2972,2141,-7393,6294,26740,11991,-3251,5461,
+    5341,1574,2208,-51,-552,-297,-753,-154,2068,-5371,
+    3578,4106,28043,-10533,8041,2353,2389,4609,3410,1906,
+    351,-249,18,-15,1117,539,2870,9084,17585,-24528,
+    -366,-6490,2009,-3170,2942,1116,-232,1672,1065,606,
+    -399,-388,-518,38,3728,28948,-11936,4543,4104,-4441,
+    1545,-4044,1485,622,-68,186,-473,135,-280,125,
+    -546,-1813,6989,6606,23711,19376,-2636,2870,-4553,-1687,
+    878,-375,205,-208,-409,-108,-200,-45,-1670,-337,
+    8213,-5524,-2334,5240,-12939,-26205,5937,-1582,-592,-959,
+    -5374,2449,3400,559,349,-492,668,12379,-27684,3419,
+    5117,4415,-297,-8270,-1252,-3490,-1272,-1199,-3159,191,
+    630,488,-797,-3071,12912,-27783,-10249,1047,647,619,
+    111,-3722,-915,-1055,-502,5,-1384,-306,221,68,
+    5219,13173,-26474,-11663,-5626,927,806,-1127,236,-589,
+    -522,-230,-312,-315,-428,-573,426,192,-11830,-26883,
+    -14121,-2785,-1429,-109,410,-832,-302,539,-459,104,
+    1,-530,-202,-289,153,116,30082,-12944,-671,20,
+    649,98,103,215,234,0,280,-51,-169,298,
+    31,230,-73,-51
+  },
+  { -154,-7,-192,61,-739,-389,-947,-162,-60,94,
+    511,-716,1520,-1428,4168,-2214,1816,32270,-123,-77,
+    -199,-99,-42,-588,203,-240,-930,-35,1580,234,
+    3206,-5507,-1495,-10946,30000,-2667,-136,-176,-240,-175,
+    -204,-661,-1796,-1039,-1271,498,3143,734,2663,2699,
+    -8127,29333,10495,2356,-72,113,-91,118,-2840,-723,
+    -1733,-1158,-389,-2116,-3054,-3,-5179,8071,29546,6308,
+    5657,-3178,-186,-294,-473,-635,1213,-983,-1437,-1715,
+    -1094,1280,-92,-9573,948,29576,-7060,-5921,2954,1349,
+    -337,-108,-1099,962,418,-413,-1149,-334,1241,3975,
+    -6825,26725,-14377,7051,-4772,-1707,2335,2008,-150,570,
+    1371,42,-1649,-619,2039,3369,-1225,1583,-2755,-15207,
+    -27504,-4855,-4304,1495,2733,1324,15,-448,403,353,
+    3016,-1242,2338,2673,2064,-7496,-30447,-3686,5833,-1301,
+    -2455,2122,1519,608,43,-653,773,-3072,912,-1537,
+    4505,10284,30237,1549,3200,-691,205,1702,658,1014,
+    1499,148,79,-322,-1162,-4639,-813,7536,3204,29109,
+    -10747,-26,1611,2286,2114,2561,1022,372,348,207,
+    1062,-1088,-443,-9849,2381,5671,29097,-7612,-2927,3853,
+    194,1155,275,1438,1438,1312,581,888,-784,906,
+    112,-11103,25104,14438,-9311,-3068,1210,368,370,-940,
+    -2434,-1148,1925,392,657,258,-526,1475,-2281,-4265,
+    -1880,1534,2185,-1472,959,-30934,6306,3114,-4109,1768,
+    -2612,-703,45,644,2185,2033,5670,7211,19114,-22427,
+    6432,5150,-4090,-2694,3860,1245,-596,293,1829,369,
+    -319,229,-3256,2170,-6374,-26216,-4570,-16053,-5766,-262,
+    -2006,2873,-1477,147,378,-1544,-344,-544,-985,-481,
+    4210,4542,30757,-7291,-4863,1529,-2079,-628,-603,-783,
+    -408,1646,697,808,-620,-292,181,158,-13313,-29173,
+    5984,-1262,859,-1776,-558,-24,-883,-1421,739,210,
+    -531,-285,131,-160,-246,-56,29345,-13706,-2859,-2966,
+    -300,-970,-2382,-268,-103,-636,-12,-62,-691,-253,
+    -147,-127,27,66
+  },
+  { 55,-212,-198,489,-274,81,682,399,328,-934,
+    -389,-37,1357,-3632,5276,6581,-9493,-29921,29,-45,
+    2,190,172,-15,311,-130,-1085,-25,324,-684,
+    3223,-6580,4485,-5280,-29521,9933,82,-320,-530,229,
+    -705,-533,-414,848,-1842,-4473,1390,-857,6717,-6692,
+    4648,29397,576,8339,-68,-85,238,-330,264,-1012,
+    -381,-203,-3384,-3329,3906,6810,3790,-6250,28312,-8078,
+    8089,1565,160,-569,-612,-613,-1063,-1928,-1125,3421,
+    -7481,-7484,4942,-6984,4330,-25591,-10574,-6982,5682,-1781,
+    -308,89,178,-1715,-420,-3530,-5776,1219,-8617,-7137,
+    7015,4981,24875,12657,-5408,-3356,-785,-1972,326,-858,
+    -506,-3382,-986,-6258,-2259,4015,-8374,-10482,3127,23826,
+    -14126,-514,-5417,2178,-2912,-17,-587,80,67,-5881,
+    -1702,-5351,-4481,398,-10156,-225,20727,-15460,-11603,7752,
+    3660,1714,-2001,-359,499,-527,-1225,-7820,-1297,-6326,
+    -8526,7900,-18328,13311,-17488,-2926,-196,-17,2281,873,
+    480,-160,-624,471,780,-8729,1707,-14262,-20647,1721,
+    18590,-2206,-1214,-1066,312,-2602,783,-412,-113,49,
+    -119,1305,-2371,-15132,-1833,-18252,20295,-8316,2227,341,
+    -2074,-702,3082,-262,-465,-198,430,30,-70,-788,
+    2342,-25132,-4863,19783,-484,2137,2811,-1906,799,1586,
+    962,-734,-191,-30,-129,-93,-1126,1729,5860,-2030,
+    8953,603,-3338,-10869,-1144,22070,12130,10513,3191,-6881,
+    -3514,2090,711,-666,1843,-5997,-5681,2921,-17641,-2801,
+    4969,18590,7169,12214,8587,4405,3008,-1074,-371,-77,
+    253,331,-5611,5014,13152,-1985,18483,-1696,8043,20463,
+    2381,-393,1688,-1205,618,1220,457,248,-83,176,
+    7920,-13676,-22139,-3038,17402,2036,844,3258,994,719,
+    2087,-44,426,494,12,-91,46,5,-14204,22912,
+    -18156,-361,442,2298,-829,2229,386,1433,1335,1323,
+    55,-592,-139,49,-12,-57,27783,17134,350,-282,
+    552,158,142,2488,465,329,1087,118,143,10,
+    56,65,-15,-31
+  }
+};
+
+/* right KLT transforms */
+const int16_t WebRtcIsacfix_kT2GainQ15[3][36] = {
+  {   4775, -14892,  20313, -17104,  10533,  -3613,  -6782,  16044,  -8889,
+      -11019,  21330, -10720,  13193, -15678, -11101,  14461,  12250, -13096,
+      -16951,   2167,  16066,  15569,   -702, -16754, -19195, -12823,  -4321,
+      5128,    13348,  17825,  13232,  13404,  13494,  13490,  13383,  13261
+  },
+  {  -3725,  11408, -18493,  20031, -13097,   3865,   9344, -19294,  10740,
+     8856, -18432,   8982,  13975, -14444, -11930,  11774,  14285, -13594,
+     -16323,     -4,  16340,  15609,    359, -17220, -18401, -13471,  -4643,
+     5225,  13375,  18053,  13124,  13463,  13621,  13583,  13393,  13072
+  },
+  {  -3513,  11402, -17883,  19504, -14399,   4885,   8702, -19513,  12046,
+     8533, -18110,   8447,  12778, -14838, -12444,  13177,  14107, -12759,
+     -17268,    914,  15822,  15661,    838, -16686, -18907, -12936,  -4820,
+     4175,  12398,  18830,  12913,  13215,  13433,  13572,  13601,  13518
+  }
+};
+
+const int16_t WebRtcIsacfix_kT2ShapeQ15[3][36] = {
+  {   4400, -11512,  17205, -19470,  14770,  -5345,   9784, -19222,  11228,
+      6842, -18371,   9909,  14191, -13496, -11563,  14015,  11827, -14839,
+      -15439,    948,  17802,  14827,  -2053, -17132,  18723,  14516,   4135,
+      -6822, -13869, -16016,  12975,  13341,  13563,  13603,  13478,  13296
+  },
+  {   5420, -14215,  19060, -18073,  11709,  -3911,   9645, -18335,   7717,
+      10842, -19283,   9777,  14898, -12555, -13661,  11668,  13520, -13733,
+      -15936,  -1358,  15671,  16728,    328, -17100,  17527,  13973,   5587,
+      -5194, -14165, -17677,  12970,  13446,  13693,  13660,  13462,  13015
+  },
+  {   4386, -12426,  18019, -18895,  13894,  -5034,   9713, -19270,  10283,
+      8692, -18439,   9317,  13992, -13454, -13241,  12850,  13366, -13336,
+      -16334,   -498,  15976,  16213,   -114, -16987,  18191,  13659,   4958,
+      -5116, -13444, -18021,  12911,  13424,  13718,  13674,  13464,  13054
+  }
+};
+
+/* means of log gains and LAR coefficients*/
+const int16_t WebRtcIsacfix_kMeansGainQ8[3][12] = {
+  { -1758, -1370, -1758, -1373, -1757, -1375,
+    -1758, -1374, -1758, -1373, -1755, -1370
+  },
+  { -1569, -1224, -1569, -1225, -1569, -1227,
+    -1569, -1226, -1567, -1225, -1565, -1224
+  },
+  { -1452,  -957, -1447,  -951, -1438,  -944,
+    -1431,  -938, -1419,  -931, -1406,  -926
+  }
+};
+
+
+const int32_t WebRtcIsacfix_kMeansShapeQ17[3][108] = {
+  { -119581, 34418, -44193, 11112, -4428, 18906, 9222, 8068, 1953, 5425,
+    1871, 1689, 109933, 33751, 10471, -2566, 1090, 2320, -119219, 33728,
+    -43759, 11450, -4870, 19117, 9174, 8037, 1972, 5331, 1872, 1843,
+    109899, 34301, 10629, -2316, 1272, 2562, -118608, 32318, -44012, 11591,
+    -4914, 18932, 9456, 8088, 1900, 5419, 1723, 1853, 109963, 35059,
+    10745, -2335, 1161, 2520, -119174, 32107, -44462, 11635, -4694, 18611,
+    9757, 8108, 1969, 5486, 1673, 1777, 109636, 34907, 10643, -2406,
+    1034, 2420, -118597, 32320, -44590, 10854, -4569, 18821, 9701, 7866,
+    2003, 5577, 1732, 1626, 109913, 34448, 10714, -2752, 990, 2228,
+    -118138, 32996, -44352, 10334, -3772, 18488, 9464, 7865, 2208, 5540,
+    1745, 1664, 109880, 33381, 10640, -2779, 980, 2054
+  },
+  { -146328, 46370, 1047, 26431, 10035, 13933, 6415, 14359, -2368, 6661,
+    2269, 1764, 96623, 7802, 4163, 10742, 1643, 2954, -146871, 46561, 1127,
+    26225, 10113, 14096, 6771, 14323, -2037, 6788, 2297, 1761, 96324, 8382,
+    4309, 10450, 1695, 3016, -146502, 46475, 1580, 26118, 10487, 14179, 6622,
+    14439, -2034, 6757, 2342, 1761, 95869, 8966, 4347, 10358, 1999, 2855,
+    -146958, 47717, 826, 25952, 10263, 14061, 5266, 13681, -2417, 6582, 2047,
+    1608, 96257, 9107, 4452, 10301, 1792, 2676, -146992, 47123, 446, 25822,
+    10405, 14292, 5140, 13804, -2403, 6496, 1834, 1735, 97489, 9253, 4414,
+    10684, 1549, 2721, -145811, 46182, 901, 26482, 10241, 14524, 6075, 14514,
+    -2147, 6691, 2196, 1899, 97011, 8178, 4102, 10758, 1638, 2869
+  },
+  { -166617, 46969, -43908, 17726, 6330, 25615, 6913, 5450, -2301, 1984,
+    507, 2883, 149998, 28709, 19333, 16703, 11093, 8965, -168254, 46604,
+    -44315, 17862, 6474, 25746, 7018, 5373, -2343, 1930, 513, 2819, 150391,
+    28627, 19194, 16678, 10998, 8929, -169093, 46084, -44767, 17427, 6401,
+    25674, 7147, 5472, -2336, 1820, 491, 2802, 149860, 28430, 19064, 16524,
+    10898, 8875, -170205, 46189, -44877, 17403, 6190, 25209, 7035, 5673, -2173,
+    1894, 574, 2756, 148830, 28230, 18819, 16418, 10789, 8811, -171263, 45045,
+    -44834, 16858, 6103, 24726, 7014, 5713, -2103, 1877, 518, 2729, 147073,
+    27744, 18629, 16277, 10690, 8703, -171720, 44153, -45062, 15951, 5872,
+    24429, 7044, 5585, -2082, 1807, 519, 2769, 144791, 27402, 18490, 16126,
+    10548, 8635
+  }
+};
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
new file mode 100644
index 0000000..50e1b12
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* indices of KLT coefficients used */
+extern const uint16_t WebRtcIsacfix_kSelIndGain[12];
+
+extern const uint16_t WebRtcIsacfix_kSelIndShape[108];
+
+/* cdf array for model indicator */
+extern const uint16_t WebRtcIsacfix_kModelCdf[KLT_NUM_MODELS + 1];
+
+/* pointer to cdf array for model indicator */
+extern const uint16_t* WebRtcIsacfix_kModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const uint16_t WebRtcIsacfix_kModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const int16_t WebRtcIsacfix_kQuantMinGain[12];
+
+extern const int16_t WebRtcIsacfix_kQuantMinShape[108];
+
+/* maximum quantization index */
+extern const uint16_t WebRtcIsacfix_kMaxIndGain[12];
+
+extern const uint16_t WebRtcIsacfix_kMaxIndShape[108];
+
+/* index offset */
+extern const uint16_t WebRtcIsacfix_kOffsetGain[KLT_NUM_MODELS][12];
+
+extern const uint16_t WebRtcIsacfix_kOffsetShape[KLT_NUM_MODELS][108];
+
+/* initial cdf index for KLT coefficients */
+extern const uint16_t WebRtcIsacfix_kInitIndexGain[KLT_NUM_MODELS][12];
+
+extern const uint16_t WebRtcIsacfix_kInitIndexShape[KLT_NUM_MODELS][108];
+
+/* offsets for quantizer representation levels */
+extern const uint16_t WebRtcIsacfix_kOfLevelsGain[3];
+
+extern const uint16_t WebRtcIsacfix_kOfLevelsShape[3];
+
+/* quantizer representation levels */
+extern const int32_t WebRtcIsacfix_kLevelsGainQ17[1176];
+
+extern const int16_t WebRtcIsacfix_kLevelsShapeQ10[1735];
+
+/* cdf tables for quantizer indices */
+extern const uint16_t WebRtcIsacfix_kCdfGain[1212];
+
+extern const uint16_t WebRtcIsacfix_kCdfShape[2059];
+
+/* pointers to cdf tables for quantizer indices */
+extern const uint16_t* WebRtcIsacfix_kCdfGainPtr[KLT_NUM_MODELS][12];
+
+extern const uint16_t* WebRtcIsacfix_kCdfShapePtr[KLT_NUM_MODELS][108];
+
+/* code length for all coefficients using different models */
+extern const int16_t WebRtcIsacfix_kCodeLenGainQ11[392];
+
+extern const int16_t WebRtcIsacfix_kCodeLenShapeQ11[578];
+
+/* left KLT transforms */
+extern const int16_t WebRtcIsacfix_kT1GainQ15[KLT_NUM_MODELS][4];
+
+extern const int16_t WebRtcIsacfix_kT1ShapeQ15[KLT_NUM_MODELS][324];
+
+/* right KLT transforms */
+extern const int16_t WebRtcIsacfix_kT2GainQ15[KLT_NUM_MODELS][36];
+
+extern const int16_t WebRtcIsacfix_kT2ShapeQ15[KLT_NUM_MODELS][36];
+
+/* means of log gains and LAR coefficients */
+extern const int16_t WebRtcIsacfix_kMeansGainQ8[KLT_NUM_MODELS][12];
+
+extern const int32_t WebRtcIsacfix_kMeansShapeQ17[3][108];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
new file mode 100644
index 0000000..78cb93f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
@@ -0,0 +1,435 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+/* log2[0.2, 0.5, 0.98] in Q8 */
+static const int16_t kLogLagWinQ8[3] = {
+  -594, -256, -7
+};
+
+/* [1 -0.75 0.25] in Q12 */
+static const int16_t kACoefQ12[3] = {
+  4096, -3072, 1024
+};
+
+int32_t WebRtcIsacfix_Log2Q8(uint32_t x) {
+  int32_t zeros;
+  int16_t frac;
+
+  zeros=WebRtcSpl_NormU32(x);
+  frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+  /* log2(magn(i)) */
+
+  return ((31 - zeros) << 8) + frac;
+}
+
+static __inline int16_t Exp2Q10(int16_t x) { // Both in and out in Q10
+
+  int16_t tmp16_1, tmp16_2;
+
+  tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+  tmp16_1 = -(x >> 10);
+  if(tmp16_1>0)
+    return tmp16_2 >> tmp16_1;
+  else
+    return tmp16_2 << -tmp16_1;
+
+}
+
+
+
+/* 1D parabolic interpolation . All input and output values are in Q8 */
+static __inline void Intrp1DQ8(int32_t *x, int32_t *fx, int32_t *y, int32_t *fy) {
+
+  int16_t sign1=1, sign2=1;
+  int32_t r32, q32, t32, nom32, den32;
+  int16_t t16, tmp16, tmp16_1;
+
+  if ((fx[0]>0) && (fx[2]>0)) {
+    r32=fx[1]-fx[2];
+    q32=fx[0]-fx[1];
+    nom32=q32+r32;
+    den32 = (q32 - r32) * 2;
+    if (nom32<0)
+      sign1=-1;
+    if (den32<0)
+      sign2=-1;
+
+    /* t = (q32+r32)/(2*(q32-r32)) = (fx[0]-fx[1] + fx[1]-fx[2])/(2 * fx[0]-fx[1] - (fx[1]-fx[2]))*/
+    /* (Signs are removed because WebRtcSpl_DivResultInQ31 can't handle negative numbers) */
+    /* t in Q31, without signs */
+    t32 = WebRtcSpl_DivResultInQ31(nom32 * sign1, den32 * sign2);
+
+    t16 = (int16_t)(t32 >> 23);  /* Q8 */
+    t16=t16*sign1*sign2;        /* t in Q8 with signs */
+
+    *y = x[0]+t16;          /* Q8 */
+    // *y = x[1]+t16;          /* Q8 */
+
+    /* The following code calculates fy in three steps */
+    /* fy = 0.5 * t * (t-1) * fx[0] + (1-t*t) * fx[1] + 0.5 * t * (t+1) * fx[2]; */
+
+    /* Part I: 0.5 * t * (t-1) * fx[0] */
+    tmp16_1 = (int16_t)(t16 * t16);  /* Q8*Q8=Q16 */
+    tmp16_1 >>= 2;  /* Q16>>2 = Q14 */
+    t16 <<= 6;  /* Q8<<6 = Q14  */
+    tmp16 = tmp16_1-t16;
+    *fy = WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[0]); /* (Q14 * Q8 >>15)/2 = Q8 */
+
+    /* Part II: (1-t*t) * fx[1] */
+    tmp16 = 16384-tmp16_1;        /* 1 in Q14 - Q14 */
+    *fy += WEBRTC_SPL_MUL_16_32_RSFT14(tmp16, fx[1]);/* Q14 * Q8 >> 14 = Q8 */
+
+    /* Part III: 0.5 * t * (t+1) * fx[2] */
+    tmp16 = tmp16_1+t16;
+    *fy += WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[2]);/* (Q14 * Q8 >>15)/2 = Q8 */
+  } else {
+    *y = x[0];
+    *fy= fx[1];
+  }
+}
+
+
+static void FindFour32(int32_t *in, int16_t length, int16_t *bestind)
+{
+  int32_t best[4]= {-100, -100, -100, -100};
+  int16_t k;
+
+  for (k=0; k<length; k++) {
+    if (in[k] > best[3]) {
+      if (in[k] > best[2]) {
+        if (in[k] > best[1]) {
+          if (in[k] > best[0]) { // The Best
+            best[3] = best[2];
+            bestind[3] = bestind[2];
+            best[2] = best[1];
+            bestind[2] = bestind[1];
+            best[1] = best[0];
+            bestind[1] = bestind[0];
+            best[0] = in[k];
+            bestind[0] = k;
+          } else { // 2nd best
+            best[3] = best[2];
+            bestind[3] = bestind[2];
+            best[2] = best[1];
+            bestind[2] = bestind[1];
+            best[1] = in[k];
+            bestind[1] = k;
+          }
+        } else { // 3rd best
+          best[3] = best[2];
+          bestind[3] = bestind[2];
+          best[2] = in[k];
+          bestind[2] = k;
+        }
+      } else {  // 4th best
+        best[3] = in[k];
+        bestind[3] = k;
+      }
+    }
+  }
+}
+
+
+
+
+
+extern void WebRtcIsacfix_PCorr2Q32(const int16_t *in, int32_t *logcorQ8);
+
+
+
+void WebRtcIsacfix_InitialPitch(const int16_t *in, /* Q0 */
+                                PitchAnalysisStruct *State,
+                                int16_t *lagsQ7                   /* Q7 */
+                                )
+{
+  int16_t buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+  int32_t *crrvecQ8_1,*crrvecQ8_2;
+  int32_t cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2];
+  int k;
+  int16_t peaks_indq;
+  int16_t peakiq[PITCH_LAG_SPAN2];
+  int32_t corr;
+  int32_t corr32, corr_max32, corr_max_o32;
+  int16_t npkq;
+  int16_t best4q[4]={0,0,0,0};
+  int32_t xq[3],yq[1],fyq[1];
+  int32_t *fxq;
+  int32_t best_lag1q, best_lag2q;
+  int32_t tmp32a,tmp32b,lag32,ratq;
+  int16_t start;
+  int16_t oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16;
+  int32_t tmp32c,tmp32d, tmp32e;
+  int16_t old_lagQ;
+  int32_t old_lagQ8;
+  int32_t lagsQ8[4];
+
+  old_lagQ = State->PFstr_wght.oldlagQ7; // Q7
+  old_lagQ8 = old_lagQ << 1;  // Q8
+
+  oldgQ12= State->PFstr_wght.oldgainQ12;
+
+  crrvecQ8_1=&cv1q[1];
+  crrvecQ8_2=&cv2q[1];
+
+
+  /* copy old values from state buffer */
+  memcpy(buf_dec16, State->dec_buffer16, sizeof(State->dec_buffer16));
+
+  /* decimation; put result after the old values */
+  WebRtcIsacfix_DecimateAllpass32(in, State->decimator_state32, PITCH_FRAME_LEN,
+                                  &buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+  /* low-pass filtering */
+  start= PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2;
+  WebRtcSpl_FilterARFastQ12(&buf_dec16[start],&buf_dec16[start],(int16_t*)kACoefQ12,3, PITCH_FRAME_LEN/2);
+
+  /* copy end part back into state buffer */
+  for (k = 0; k < (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2); k++)
+    State->dec_buffer16[k] = buf_dec16[k+PITCH_FRAME_LEN/2];
+
+
+  /* compute correlation for first and second half of the frame */
+  WebRtcIsacfix_PCorr2Q32(buf_dec16, crrvecQ8_1);
+  WebRtcIsacfix_PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2);
+
+
+  /* bias towards pitch lag of previous frame */
+  tmp32a = WebRtcIsacfix_Log2Q8((uint32_t) old_lagQ8) - 2304;
+      // log2(0.5*oldlag) in Q8
+  tmp32b = oldgQ12 * oldgQ12 >> 10;  // Q12 & * 4.0;
+  gain_bias16 = (int16_t) tmp32b;  //Q12
+  if (gain_bias16 > 3276) gain_bias16 = 3276; // 0.8 in Q12
+
+
+  for (k = 0; k < PITCH_LAG_SPAN2; k++)
+  {
+    if (crrvecQ8_1[k]>0) {
+      tmp32b = WebRtcIsacfix_Log2Q8((uint32_t) (k + (PITCH_MIN_LAG/2-2)));
+      tmp16a = (int16_t) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4
+      tmp32c = tmp16a * tmp16a >> 6;  // Q10
+      tmp16b = (int16_t) tmp32c; // Q10 & <8
+      tmp32d = tmp16b * 177 >> 8;  // mult with ln2 in Q8
+      tmp16c = (int16_t) tmp32d; // Q10 & <4
+      tmp16d = Exp2Q10((int16_t) -tmp16c); //Q10
+      tmp32c = gain_bias16 * tmp16d >> 13;  // Q10  & * 0.5
+      bias16 = (int16_t) (1024 + tmp32c); // Q10
+      tmp32b = WebRtcIsacfix_Log2Q8((uint32_t)bias16) - 2560;
+          // Q10 in -> Q8 out with 10*2^8 offset
+      crrvecQ8_1[k] += tmp32b ; // -10*2^8 offset
+    }
+  }
+
+  /* taper correlation functions */
+  for (k = 0; k < 3; k++) {
+    crrvecQ8_1[k] += kLogLagWinQ8[k];
+    crrvecQ8_2[k] += kLogLagWinQ8[k];
+
+    crrvecQ8_1[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+    crrvecQ8_2[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+  }
+
+
+  /* Make zeropadded corr vectors */
+  cv1q[0]=0;
+  cv2q[0]=0;
+  cv1q[PITCH_LAG_SPAN2+1]=0;
+  cv2q[PITCH_LAG_SPAN2+1]=0;
+  corr_max32 = 0;
+
+  for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+  {
+
+
+    corr32=crrvecQ8_1[k-1];
+    if (corr32 > corr_max32)
+      corr_max32 = corr32;
+
+    corr32=crrvecQ8_2[k-1];
+    corr32 += -4; // Compensate for later (log2(0.99))
+
+    if (corr32 > corr_max32)
+      corr_max32 = corr32;
+
+  }
+
+  /* threshold value to qualify as a peak */
+  // corr_max32 += -726; // log(0.14)/log(2.0) in Q8
+  corr_max32 += -1000; // log(0.14)/log(2.0) in Q8
+  corr_max_o32 = corr_max32;
+
+
+  /* find peaks in corr1 */
+  peaks_indq = 0;
+  for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+  {
+    corr32=cv1q[k];
+    if (corr32>corr_max32) { // Disregard small peaks
+      if ((corr32>=cv1q[k-1]) && (corr32>cv1q[k+1])) { // Peak?
+        peakvq[peaks_indq] = corr32;
+        peakiq[peaks_indq++] = k;
+      }
+    }
+  }
+
+
+  /* find highest interpolated peak */
+  corr_max32=0;
+  best_lag1q =0;
+  if (peaks_indq > 0) {
+    FindFour32(peakvq, (int16_t) peaks_indq, best4q);
+    npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+
+    for (k=0;k<npkq;k++) {
+
+      lag32 =  peakiq[best4q[k]];
+      fxq = &cv1q[peakiq[best4q[k]]-1];
+      xq[0]= lag32;
+      xq[0] <<= 8;
+      Intrp1DQ8(xq, fxq, yq, fyq);
+
+      tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
+      /* Bias towards short lags */
+      /* log(pow(0.8, log(2.0 * *y )))/log(2.0) */
+      tmp32b = (int16_t)tmp32a * -42 >> 8;
+      tmp32c= tmp32b + 256;
+      *fyq += tmp32c;
+      if (*fyq > corr_max32) {
+        corr_max32 = *fyq;
+        best_lag1q = *yq;
+      }
+    }
+    tmp32b = (best_lag1q - OFFSET_Q8) * 2;
+    lagsQ8[0] = tmp32b + PITCH_MIN_LAG_Q8;
+    lagsQ8[1] = lagsQ8[0];
+  } else {
+    lagsQ8[0] = old_lagQ8;
+    lagsQ8[1] = lagsQ8[0];
+  }
+
+  /* Bias towards constant pitch */
+  tmp32a = lagsQ8[0] - PITCH_MIN_LAG_Q8;
+  ratq = (tmp32a >> 1) + OFFSET_Q8;
+
+  for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+  {
+    tmp32a = k << 7; // 0.5*k Q8
+    tmp32b = tmp32a * 2 - ratq;  // Q8
+    tmp32c = (int16_t)tmp32b * (int16_t)tmp32b >> 8;  // Q8
+
+    tmp32b = tmp32c + (ratq >> 1);
+        // (k-r)^2 + 0.5 * r  Q8
+    tmp32c = WebRtcIsacfix_Log2Q8((uint32_t)tmp32a) - 2048;
+        // offset 8*2^8 , log2(0.5*k) Q8
+    tmp32d = WebRtcIsacfix_Log2Q8((uint32_t)tmp32b) - 2048;
+        // offset 8*2^8 , log2(0.5*k) Q8
+    tmp32e =  tmp32c - tmp32d;
+
+    cv2q[k] += tmp32e >> 1;
+
+  }
+
+  /* find peaks in corr2 */
+  corr_max32 = corr_max_o32;
+  peaks_indq = 0;
+
+  for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+  {
+    corr=cv2q[k];
+    if (corr>corr_max32) { // Disregard small peaks
+      if ((corr>=cv2q[k-1]) && (corr>cv2q[k+1])) { // Peak?
+        peakvq[peaks_indq] = corr;
+        peakiq[peaks_indq++] = k;
+      }
+    }
+  }
+
+
+
+  /* find highest interpolated peak */
+  corr_max32 = 0;
+  best_lag2q =0;
+  if (peaks_indq > 0) {
+
+    FindFour32(peakvq, (int16_t) peaks_indq, best4q);
+    npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+    for (k=0;k<npkq;k++) {
+
+      lag32 =  peakiq[best4q[k]];
+      fxq = &cv2q[peakiq[best4q[k]]-1];
+
+      xq[0]= lag32;
+      xq[0] <<= 8;
+      Intrp1DQ8(xq, fxq, yq, fyq);
+
+      /* Bias towards short lags */
+      /* log(pow(0.8, log(2.0f * *y )))/log(2.0f) */
+      tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
+      tmp32b = (int16_t)tmp32a * -82 >> 8;
+      tmp32c= tmp32b + 256;
+      *fyq += tmp32c;
+      if (*fyq > corr_max32) {
+        corr_max32 = *fyq;
+        best_lag2q = *yq;
+      }
+    }
+
+    tmp32b = (best_lag2q - OFFSET_Q8) * 2;
+    lagsQ8[2] = tmp32b + PITCH_MIN_LAG_Q8;
+    lagsQ8[3] = lagsQ8[2];
+  } else {
+    lagsQ8[2] = lagsQ8[0];
+    lagsQ8[3] = lagsQ8[0];
+  }
+
+  lagsQ7[0] = (int16_t)(lagsQ8[0] >> 1);
+  lagsQ7[1] = (int16_t)(lagsQ8[1] >> 1);
+  lagsQ7[2] = (int16_t)(lagsQ8[2] >> 1);
+  lagsQ7[3] = (int16_t)(lagsQ8[3] >> 1);
+}
+
+
+
+void WebRtcIsacfix_PitchAnalysis(const int16_t *inn,               /* PITCH_FRAME_LEN samples */
+                                 int16_t *outQ0,                  /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+                                 PitchAnalysisStruct *State,
+                                 int16_t *PitchLags_Q7,
+                                 int16_t *PitchGains_Q12)
+{
+  int16_t inbufQ0[PITCH_FRAME_LEN + QLOOKAHEAD];
+  int16_t k;
+
+  /* inital pitch estimate */
+  WebRtcIsacfix_InitialPitch(inn, State,  PitchLags_Q7);
+
+
+  /* Calculate gain */
+  WebRtcIsacfix_PitchFilterGains(inn, &(State->PFstr_wght), PitchLags_Q7, PitchGains_Q12);
+
+  /* concatenate previous input's end and current input */
+  for (k = 0; k < QLOOKAHEAD; k++) {
+    inbufQ0[k] = State->inbuf[k];
+  }
+  for (k = 0; k < PITCH_FRAME_LEN; k++) {
+    inbufQ0[k+QLOOKAHEAD] = (int16_t) inn[k];
+  }
+
+  /* lookahead pitch filtering for masking analysis */
+  WebRtcIsacfix_PitchFilter(inbufQ0, outQ0, &(State->PFstr), PitchLags_Q7,PitchGains_Q12, 2);
+
+
+  /* store last part of input */
+  for (k = 0; k < QLOOKAHEAD; k++) {
+    State->inbuf[k] = inbufQ0[k + PITCH_FRAME_LEN];
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
new file mode 100644
index 0000000..4303c82
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+void WebRtcIsacfix_PitchAnalysis(
+    const int16_t* in, /* PITCH_FRAME_LEN samples */
+    int16_t* outQ0,    /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+    PitchAnalysisStruct* State,
+    int16_t* lagsQ7,
+    int16_t* PitchGains_Q12);
+
+void WebRtcIsacfix_InitialPitch(const int16_t* in,
+                                PitchAnalysisStruct* State,
+                                int16_t* qlags);
+
+void WebRtcIsacfix_PitchFilter(int16_t* indatFix,
+                               int16_t* outdatQQ,
+                               PitchFiltstr* pfp,
+                               int16_t* lagsQ7,
+                               int16_t* gainsQ12,
+                               int16_t type);
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+                                   int16_t gain,
+                                   size_t index,
+                                   int16_t sign,
+                                   int16_t* inputState,
+                                   int16_t* outputBuff2,
+                                   const int16_t* coefficient,
+                                   int16_t* inputBuf,
+                                   int16_t* outputBuf,
+                                   int* index2);
+
+void WebRtcIsacfix_PitchFilterGains(const int16_t* indatQ0,
+                                    PitchFiltstr* pfp,
+                                    int16_t* lagsQ7,
+                                    int16_t* gainsQ12);
+
+void WebRtcIsacfix_DecimateAllpass32(
+    const int16_t* in,
+    int32_t* state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+    int16_t N,         /* number of input samples */
+    int16_t* out);     /* array of size N/2 */
+
+int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
new file mode 100644
index 0000000..c4af9ab
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+#ifdef WEBRTC_HAS_NEON
+#include <arm_neon.h>
+#endif
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
+  int16_t scaling,n,k;
+  int32_t csum32, lys, lcs;
+  int64_t ysum64;
+  const int32_t oneQ8 = 1 << 8;  // 1.00 in Q8
+  const int16_t* x;
+  const int16_t* inptr;
+
+  x = in + PITCH_MAX_LAG / 2 + 2;
+  scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
+                                       PITCH_CORR_LEN2,
+                                       PITCH_CORR_LEN2);
+  ysum64 = 1;
+  csum32 = 0;
+  x = in + PITCH_MAX_LAG / 2 + 2;
+  for (n = 0; n < PITCH_CORR_LEN2; n++) {
+    ysum64 += in[n] * in[n] >> scaling;  // Q0
+    csum32 += x[n] * in[n] >> scaling;  // Q0
+  }
+  logcorQ8 += PITCH_LAG_SPAN2 - 1;
+  lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum64) >> 1; // Q8, sqrt(ysum)
+  if (csum32 > 0) {
+    lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
+    if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2 in Q8
+      *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
+    } else {
+      *logcorQ8 = oneQ8;                // 1.00
+    }
+  } else {
+    *logcorQ8 = 0;
+  }
+
+
+  for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+    inptr = &in[k];
+    ysum64 -= in[k - 1] * in[k - 1] >> scaling;
+    ysum64 += (int32_t)(in[PITCH_CORR_LEN2 + k - 1])
+        * in[PITCH_CORR_LEN2 + k - 1] >> scaling;
+
+#ifdef WEBRTC_HAS_NEON
+    {
+      int32_t vbuff[4];
+      int32x4_t int_32x4_sum = vmovq_n_s32(0);
+      // Can't shift a Neon register to right with a non-constant shift value.
+      int32x4_t int_32x4_scale = vdupq_n_s32(-scaling);
+      // Assert a codition used in loop unrolling at compile-time.
+      RTC_COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0);
+
+      for (n = 0; n < PITCH_CORR_LEN2; n += 4) {
+        int16x4_t int_16x4_x = vld1_s16(&x[n]);
+        int16x4_t int_16x4_in = vld1_s16(&inptr[n]);
+        int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in);
+        int_32x4 = vshlq_s32(int_32x4, int_32x4_scale);
+        int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4);
+      }
+
+      // Use vector store to avoid long stall from data trasferring
+      // from vector to general register.
+      vst1q_s32(vbuff, int_32x4_sum);
+      csum32 = vbuff[0] + vbuff[1];
+      csum32 += vbuff[2];
+      csum32 += vbuff[3];
+    }
+#else
+    int64_t csum64_tmp = 0;
+    if(scaling == 0) {
+      for (n = 0; n < PITCH_CORR_LEN2; n++) {
+        csum64_tmp += (int32_t)(x[n]) * inptr[n];
+      }
+    } else {
+      for (n = 0; n < PITCH_CORR_LEN2; n++) {
+        csum64_tmp += ((int32_t)(x[n]) * inptr[n]) >> scaling;
+      }
+    }
+    csum32 = csum64_tmp;
+#endif
+
+    logcorQ8--;
+
+    lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum64) >> 1; // Q8, sqrt(ysum)
+
+    if (csum32 > 0) {
+      lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
+      if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2
+        *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
+      } else {
+        *logcorQ8 = oneQ8;                // 1.00
+      }
+    } else {
+      *logcorQ8 = 0;
+    }
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c
new file mode 100644
index 0000000..4ead84c
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c
@@ -0,0 +1,193 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
+  int16_t scaling,n,k;
+  int32_t ysum32,csum32, lys, lcs;
+  const int32_t oneQ8 = 1 << 8;  // 1.00 in Q8
+  const int16_t* x;
+  const int16_t* inptr;
+
+  x = in + PITCH_MAX_LAG / 2 + 2;
+  scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
+                                       PITCH_CORR_LEN2,
+                                       PITCH_CORR_LEN2);
+  ysum32 = 1;
+  csum32 = 0;
+  x = in + PITCH_MAX_LAG / 2 + 2;
+  {
+    const int16_t* tmp_x = x;
+    const int16_t* tmp_in = in;
+    int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+    n = PITCH_CORR_LEN2;
+    RTC_COMPILE_ASSERT(PITCH_CORR_LEN2 % 4 == 0);
+    __asm __volatile (
+      ".set       push                                          \n\t"
+      ".set       noreorder                                     \n\t"
+     "1:                                                        \n\t"
+      "lh         %[tmp1],       0(%[tmp_in])                   \n\t"
+      "lh         %[tmp2],       2(%[tmp_in])                   \n\t"
+      "lh         %[tmp3],       4(%[tmp_in])                   \n\t"
+      "lh         %[tmp4],       6(%[tmp_in])                   \n\t"
+      "lh         %[tmp5],       0(%[tmp_x])                    \n\t"
+      "lh         %[tmp6],       2(%[tmp_x])                    \n\t"
+      "lh         %[tmp7],       4(%[tmp_x])                    \n\t"
+      "lh         %[tmp8],       6(%[tmp_x])                    \n\t"
+      "mul        %[tmp5],       %[tmp1],        %[tmp5]        \n\t"
+      "mul        %[tmp1],       %[tmp1],        %[tmp1]        \n\t"
+      "mul        %[tmp6],       %[tmp2],        %[tmp6]        \n\t"
+      "mul        %[tmp2],       %[tmp2],        %[tmp2]        \n\t"
+      "mul        %[tmp7],       %[tmp3],        %[tmp7]        \n\t"
+      "mul        %[tmp3],       %[tmp3],        %[tmp3]        \n\t"
+      "mul        %[tmp8],       %[tmp4],        %[tmp8]        \n\t"
+      "mul        %[tmp4],       %[tmp4],        %[tmp4]        \n\t"
+      "addiu      %[n],          %[n],           -4             \n\t"
+      "srav       %[tmp5],       %[tmp5],        %[scaling]     \n\t"
+      "srav       %[tmp1],       %[tmp1],        %[scaling]     \n\t"
+      "srav       %[tmp6],       %[tmp6],        %[scaling]     \n\t"
+      "srav       %[tmp2],       %[tmp2],        %[scaling]     \n\t"
+      "srav       %[tmp7],       %[tmp7],        %[scaling]     \n\t"
+      "srav       %[tmp3],       %[tmp3],        %[scaling]     \n\t"
+      "srav       %[tmp8],       %[tmp8],        %[scaling]     \n\t"
+      "srav       %[tmp4],       %[tmp4],        %[scaling]     \n\t"
+      "addu       %[ysum32],     %[ysum32],      %[tmp1]        \n\t"
+      "addu       %[csum32],     %[csum32],      %[tmp5]        \n\t"
+      "addu       %[ysum32],     %[ysum32],      %[tmp2]        \n\t"
+      "addu       %[csum32],     %[csum32],      %[tmp6]        \n\t"
+      "addu       %[ysum32],     %[ysum32],      %[tmp3]        \n\t"
+      "addu       %[csum32],     %[csum32],      %[tmp7]        \n\t"
+      "addu       %[ysum32],     %[ysum32],      %[tmp4]        \n\t"
+      "addu       %[csum32],     %[csum32],      %[tmp8]        \n\t"
+      "addiu      %[tmp_in],     %[tmp_in],      8              \n\t"
+      "bgtz       %[n],          1b                             \n\t"
+      " addiu     %[tmp_x],      %[tmp_x],       8              \n\t"
+      ".set       pop                                           \n\t"
+      : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
+        [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
+        [tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [tmp_in] "+r" (tmp_in),
+        [ysum32] "+r" (ysum32), [tmp_x] "+r" (tmp_x), [csum32] "+r" (csum32),
+        [n] "+r" (n)
+      : [scaling] "r" (scaling)
+      : "memory", "hi", "lo"
+    );
+  }
+  logcorQ8 += PITCH_LAG_SPAN2 - 1;
+  lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
+  if (csum32 > 0) {
+    lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
+    if (lcs > (lys + oneQ8)) {  // csum/sqrt(ysum) > 2 in Q8
+      *logcorQ8 = lcs - lys;  // log2(csum/sqrt(ysum))
+    } else {
+      *logcorQ8 = oneQ8;  // 1.00
+    }
+  } else {
+    *logcorQ8 = 0;
+  }
+
+  for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+    inptr = &in[k];
+    const int16_t* tmp_in1 = &in[k - 1];
+    const int16_t* tmp_in2 = &in[PITCH_CORR_LEN2 + k - 1];
+    const int16_t* tmp_x = x;
+    int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+    n = PITCH_CORR_LEN2;
+    csum32 = 0;
+    __asm __volatile (
+      ".set       push                                             \n\t"
+      ".set       noreorder                                        \n\t"
+      "lh         %[tmp1],        0(%[tmp_in1])                    \n\t"
+      "lh         %[tmp2],        0(%[tmp_in2])                    \n\t"
+      "mul        %[tmp1],        %[tmp1],         %[tmp1]         \n\t"
+      "mul        %[tmp2],        %[tmp2],         %[tmp2]         \n\t"
+      "srav       %[tmp1],        %[tmp1],         %[scaling]      \n\t"
+      "srav       %[tmp2],        %[tmp2],         %[scaling]      \n\t"
+      "subu       %[ysum32],      %[ysum32],       %[tmp1]         \n\t"
+      "bnez       %[scaling],     2f                               \n\t"
+      " addu      %[ysum32],      %[ysum32],       %[tmp2]         \n\t"
+     "1:                                                           \n\t"
+      "lh         %[tmp1],        0(%[inptr])                      \n\t"
+      "lh         %[tmp2],        0(%[tmp_x])                      \n\t"
+      "lh         %[tmp3],        2(%[inptr])                      \n\t"
+      "lh         %[tmp4],        2(%[tmp_x])                      \n\t"
+      "lh         %[tmp5],        4(%[inptr])                      \n\t"
+      "lh         %[tmp6],        4(%[tmp_x])                      \n\t"
+      "lh         %[tmp7],        6(%[inptr])                      \n\t"
+      "lh         %[tmp8],        6(%[tmp_x])                      \n\t"
+      "mul        %[tmp1],        %[tmp1],         %[tmp2]         \n\t"
+      "mul        %[tmp2],        %[tmp3],         %[tmp4]         \n\t"
+      "mul        %[tmp3],        %[tmp5],         %[tmp6]         \n\t"
+      "mul        %[tmp4],        %[tmp7],         %[tmp8]         \n\t"
+      "addiu      %[n],           %[n],            -4              \n\t"
+      "addiu      %[inptr],       %[inptr],        8               \n\t"
+      "addiu      %[tmp_x],       %[tmp_x],        8               \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp1]         \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp2]         \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp3]         \n\t"
+      "bgtz       %[n],           1b                               \n\t"
+      " addu      %[csum32],      %[csum32],       %[tmp4]         \n\t"
+      "b          3f                                               \n\t"
+      " nop                                                        \n\t"
+     "2:                                                           \n\t"
+      "lh         %[tmp1],        0(%[inptr])                      \n\t"
+      "lh         %[tmp2],        0(%[tmp_x])                      \n\t"
+      "lh         %[tmp3],        2(%[inptr])                      \n\t"
+      "lh         %[tmp4],        2(%[tmp_x])                      \n\t"
+      "lh         %[tmp5],        4(%[inptr])                      \n\t"
+      "lh         %[tmp6],        4(%[tmp_x])                      \n\t"
+      "lh         %[tmp7],        6(%[inptr])                      \n\t"
+      "lh         %[tmp8],        6(%[tmp_x])                      \n\t"
+      "mul        %[tmp1],        %[tmp1],         %[tmp2]         \n\t"
+      "mul        %[tmp2],        %[tmp3],         %[tmp4]         \n\t"
+      "mul        %[tmp3],        %[tmp5],         %[tmp6]         \n\t"
+      "mul        %[tmp4],        %[tmp7],         %[tmp8]         \n\t"
+      "addiu      %[n],           %[n],            -4              \n\t"
+      "addiu      %[inptr],       %[inptr],        8               \n\t"
+      "addiu      %[tmp_x],       %[tmp_x],        8               \n\t"
+      "srav       %[tmp1],        %[tmp1],         %[scaling]      \n\t"
+      "srav       %[tmp2],        %[tmp2],         %[scaling]      \n\t"
+      "srav       %[tmp3],        %[tmp3],         %[scaling]      \n\t"
+      "srav       %[tmp4],        %[tmp4],         %[scaling]      \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp1]         \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp2]         \n\t"
+      "addu       %[csum32],      %[csum32],       %[tmp3]         \n\t"
+      "bgtz       %[n],           2b                               \n\t"
+      " addu      %[csum32],      %[csum32],       %[tmp4]         \n\t"
+     "3:                                                           \n\t"
+      ".set       pop                                              \n\t"
+      : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
+        [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
+        [tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [inptr] "+r" (inptr),
+        [csum32] "+r" (csum32), [tmp_x] "+r" (tmp_x), [ysum32] "+r" (ysum32),
+        [n] "+r" (n)
+      : [tmp_in1] "r" (tmp_in1), [tmp_in2] "r" (tmp_in2),
+        [scaling] "r" (scaling)
+      : "memory", "hi", "lo"
+    );
+
+    logcorQ8--;
+    lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
+    if (csum32 > 0) {
+      lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32); // 2log(csum) in Q8
+      if (lcs > (lys + oneQ8)) { // csum/sqrt(ysum) > 2
+        *logcorQ8 = lcs - lys;  // log2(csum/sqrt(ysum))
+      } else {
+        *logcorQ8 = oneQ8;  // 1.00
+      }
+    } else {
+      *logcorQ8 = 0;
+    }
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
new file mode 100644
index 0000000..7355330
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
@@ -0,0 +1,248 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "rtc_base/compile_assert_c.h"
+
+// Number of segments in a pitch subframe.
+static const int kSegments = 5;
+
+// A division factor of 1/5 in Q15.
+static const int16_t kDivFactor = 6553;
+
+// Interpolation coefficients; generated by design_pitch_filter.m.
+// Coefficients are stored in Q14.
+static const int16_t kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+  {-367, 1090, -2706,  9945, 10596, -3318,  1626, -781,  287},
+  {-325,  953, -2292,  7301, 12963, -3320,  1570, -743,  271},
+  {-240,  693, -1622,  4634, 14809, -2782,  1262, -587,  212},
+  {-125,  358,  -817,  2144, 15982, -1668,   721, -329,  118},
+  {   0,    0,    -1,     1, 16380,     1,    -1,    0,    0},
+  { 118, -329,   721, -1668, 15982,  2144,  -817,  358, -125},
+  { 212, -587,  1262, -2782, 14809,  4634, -1622,  693, -240},
+  { 271, -743,  1570, -3320, 12963,  7301, -2292,  953, -325}
+};
+
+static __inline size_t CalcLrIntQ(int16_t fixVal,
+                                  int16_t qDomain) {
+  int32_t roundVal = 1 << (qDomain - 1);
+
+  return (fixVal + roundVal) >> qDomain;
+}
+
+void WebRtcIsacfix_PitchFilter(int16_t* indatQQ, // Q10 if type is 1 or 4,
+                                                       // Q0 if type is 2.
+                               int16_t* outdatQQ,
+                               PitchFiltstr* pfp,
+                               int16_t* lagsQ7,
+                               int16_t* gainsQ12,
+                               int16_t type) {
+  int    k, ind, cnt;
+  int16_t sign = 1;
+  int16_t inystateQQ[PITCH_DAMPORDER];
+  int16_t ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD];
+  const int16_t Gain = 21299;     // 1.3 in Q14
+  int16_t oldLagQ7;
+  int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
+  size_t frcQQ = 0;
+  int32_t indW32 = 0;
+  const int16_t* fracoeffQQ = NULL;
+
+  // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM().
+  RTC_COMPILE_ASSERT(PITCH_FRACORDER == 9);
+  RTC_COMPILE_ASSERT(PITCH_DAMPORDER == 5);
+
+  // Set up buffer and states.
+  memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+  memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ));
+
+  // Get old lag and gain value from memory.
+  oldLagQ7 = pfp->oldlagQ7;
+  oldGainQ12 = pfp->oldgainQ12;
+
+  if (type == 4) {
+    sign = -1;
+
+    // Make output more periodic.
+    for (k = 0; k < PITCH_SUBFRAMES; k++) {
+      gainsQ12[k] = (int16_t)(gainsQ12[k] * Gain >> 14);
+    }
+  }
+
+  // No interpolation if pitch lag step is big.
+  if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) {
+    oldLagQ7 = lagsQ7[0];
+    oldGainQ12 = gainsQ12[0];
+  }
+
+  ind = 0;
+
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    // Calculate interpolation steps.
+    lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+    lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+                  lagdeltaQ7, kDivFactor, 15);
+    curLagQ7 = oldLagQ7;
+    gaindeltaQ12 = gainsQ12[k] - oldGainQ12;
+    gaindeltaQ12 = (int16_t)(gaindeltaQ12 * kDivFactor >> 15);
+
+    curGainQ12 = oldGainQ12;
+    oldLagQ7 = lagsQ7[k];
+    oldGainQ12 = gainsQ12[k];
+
+    // Each frame has 4 60-sample pitch subframes, and each subframe has 5
+    // 12-sample segments. Each segment need to be processed with
+    // newly-updated parameters, so we break the pitch filtering into
+    // two for-loops (5 x 12) below. It's also why kDivFactor = 0.2 (in Q15).
+    for (cnt = 0; cnt < kSegments; cnt++) {
+      // Update parameters for each segment.
+      curGainQ12 += gaindeltaQ12;
+      curLagQ7 += lagdeltaQ7;
+      indW32 = CalcLrIntQ(curLagQ7, 7);
+      if (indW32 < PITCH_FRACORDER - 2) {
+        // WebRtcIsacfix_PitchFilterCore requires indW32 >= PITCH_FRACORDER -
+        // 2; otherwise, it will read from entries of ubufQQ that haven't been
+        // written yet. (This problem has only been seen in fuzzer tests, not
+        // in real life.) See Chromium bug 581901.
+        indW32 = PITCH_FRACORDER - 2;
+      }
+      frcQQ = ((indW32 << 7) + 64 - curLagQ7) >> 4;
+
+      if (frcQQ >= PITCH_FRACS) {
+        frcQQ = 0;
+      }
+      fracoeffQQ = kIntrpCoef[frcQQ];
+
+      // Pitch filtering.
+      WebRtcIsacfix_PitchFilterCore(PITCH_SUBFRAME_LEN / kSegments, curGainQ12,
+        indW32, sign, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+    }
+  }
+
+  // Export buffer and states.
+  memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+  memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ));
+
+  pfp->oldlagQ7 = oldLagQ7;
+  pfp->oldgainQ12 = oldGainQ12;
+
+  if (type == 2) {
+    // Filter look-ahead segment.
+    WebRtcIsacfix_PitchFilterCore(QLOOKAHEAD, curGainQ12, indW32, 1, inystateQQ,
+                ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+  }
+}
+
+
+void WebRtcIsacfix_PitchFilterGains(const int16_t* indatQ0,
+                                    PitchFiltstr* pfp,
+                                    int16_t* lagsQ7,
+                                    int16_t* gainsQ12) {
+  int  k, n, m;
+  size_t ind, pos, pos3QQ;
+
+  int16_t ubufQQ[PITCH_INTBUFFSIZE];
+  int16_t oldLagQ7, lagdeltaQ7, curLagQ7;
+  const int16_t* fracoeffQQ = NULL;
+  int16_t scale;
+  int16_t cnt = 0, tmpW16;
+  size_t frcQQ, indW16 = 0;
+  int32_t tmpW32, tmp2W32, csum1QQ, esumxQQ;
+
+  // Set up buffer and states.
+  memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+  oldLagQ7 = pfp->oldlagQ7;
+
+  // No interpolation if pitch lag step is big.
+  if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) {
+    oldLagQ7 = lagsQ7[0];
+  }
+
+  ind = 0;
+  pos = ind + PITCH_BUFFSIZE;
+  scale = 0;
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+
+    // Calculate interpolation steps.
+    lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+    lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+                   lagdeltaQ7, kDivFactor, 15);
+    curLagQ7 = oldLagQ7;
+    oldLagQ7 = lagsQ7[k];
+
+    csum1QQ = 1;
+    esumxQQ = 1;
+
+    // Same as function WebRtcIsacfix_PitchFilter(), we break the pitch
+    // filtering into two for-loops (5 x 12) below.
+    for (cnt = 0; cnt < kSegments; cnt++) {
+      // Update parameters for each segment.
+      curLagQ7 += lagdeltaQ7;
+      indW16 = CalcLrIntQ(curLagQ7, 7);
+      frcQQ = ((indW16 << 7) + 64 - curLagQ7) >> 4;
+
+      if (frcQQ >= PITCH_FRACS) {
+        frcQQ = 0;
+      }
+      fracoeffQQ = kIntrpCoef[frcQQ];
+
+      pos3QQ = pos - (indW16 + 4);
+
+      for (n = 0; n < PITCH_SUBFRAME_LEN / kSegments; n++) {
+        // Filter to get fractional pitch.
+
+        tmpW32 = 0;
+        for (m = 0; m < PITCH_FRACORDER; m++) {
+          tmpW32 += ubufQQ[pos3QQ + m] * fracoeffQQ[m];
+        }
+
+        // Subtract from input and update buffer.
+        ubufQQ[pos] = indatQ0[ind];
+
+        tmp2W32 = WEBRTC_SPL_MUL_16_32_RSFT14(indatQ0[ind], tmpW32);
+        tmpW32 += 8192;
+        tmpW16 = tmpW32 >> 14;
+        tmpW32 = tmpW16 * tmpW16;
+
+        if ((tmp2W32 > 1073700000) || (csum1QQ > 1073700000) ||
+            (tmpW32 > 1073700000) || (esumxQQ > 1073700000)) {  // 2^30
+          scale++;
+          csum1QQ >>= 1;
+          esumxQQ >>= 1;
+        }
+        csum1QQ += tmp2W32 >> scale;
+        esumxQQ += tmpW32 >> scale;
+
+        ind++;
+        pos++;
+        pos3QQ++;
+      }
+    }
+
+    if (csum1QQ < esumxQQ) {
+      tmp2W32 = WebRtcSpl_DivResultInQ31(csum1QQ, esumxQQ);
+
+      // Gain should be half the correlation.
+      tmpW32 = tmp2W32 >> 20;
+    } else {
+      tmpW32 = 4096;
+    }
+    gainsQ12[k] = (int16_t)WEBRTC_SPL_SAT(PITCH_MAX_GAIN_Q12, tmpW32, 0);
+  }
+
+  // Export buffer and states.
+  memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+  pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES - 1];
+  pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES - 1];
+
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
new file mode 100644
index 0000000..0659468
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
@@ -0,0 +1,143 @@
+@
+@ Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+@
+@ Use of this source code is governed by a BSD-style license
+@ that can be found in the LICENSE file in the root of the source
+@ tree. An additional intellectual property rights grant can be found
+@ in the file PATENTS.  All contributing project authors may
+@ be found in the AUTHORS file in the root of the source tree.
+@
+
+@ Contains the core loop routine for the pitch filter function in iSAC,
+@ optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in pitch_filter.c.
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/system/asm_defines.h"
+
+GLOBAL_FUNCTION WebRtcIsacfix_PitchFilterCore
+.align  2
+
+@ void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+@                                    int16_t gain,
+@                                    size_t index,
+@                                    int16_t sign,
+@                                    int16_t* inputState,
+@                                    int16_t* outputBuf2,
+@                                    const int16_t* coefficient,
+@                                    int16_t* inputBuf,
+@                                    int16_t* outputBuf,
+@                                    int* index2) {
+DEFINE_FUNCTION WebRtcIsacfix_PitchFilterCore
+  push {r4-r11}
+  sub sp, #8
+
+  str r0, [sp]                @ loopNumber
+  str r3, [sp, #4]            @ sign
+  ldr r3, [sp, #44]           @ outputBuf2
+  ldr r6, [sp, #60]           @ index2
+  ldr r7, [r6]                @ *index2
+  ldr r8, [sp, #52]           @ inputBuf
+  ldr r12, [sp, #56]          @ outputBuf
+
+  add r4, r7, r0
+  str r4, [r6]                @ Store return value to index2.
+
+  mov r10, r7, asl #1
+  add r12, r10                @ &outputBuf[*index2]
+  add r8, r10                 @ &inputBuf[*index2]
+
+  add r4, r7, #PITCH_BUFFSIZE @ *index2 + PITCH_BUFFSIZE
+  add r6, r3, r4, lsl #1      @ &outputBuf2[*index2 + PITCH_BUFFSIZE]
+  sub r4, r2                  @ r2: index
+  sub r4, #2                  @ *index2 + PITCH_BUFFSIZE - index - 2
+  add r3, r4, lsl #1          @ &ubufQQpos2[*index2]
+  ldr r9, [sp, #48]           @ coefficient
+
+LOOP:
+@ Usage of registers in the loop:
+@  r0: loop counter
+@  r1: gain
+@  r2: tmpW32
+@  r3: &ubufQQpos2[]
+@  r6: &outputBuf2[]
+@  r8: &inputBuf[]
+@  r9: &coefficient[]
+@  r12: &outputBuf[]
+@  r4, r5, r7, r10, r11: scratch
+
+  @ Filter to get fractional pitch.
+  @ The pitch filter loop here is unrolled with 9 multipications.
+  pld [r3]
+  ldr r10, [r3], #4           @ ubufQQpos2[*index2 + 0, *index2 + 1]
+  ldr r4, [r9], #4            @ coefficient[0, 1]
+  ldr r11, [r3], #4
+  ldr r5, [r9], #4
+  smuad r2, r10, r4
+  smlad r2, r11, r5, r2
+
+  ldr r10, [r3], #4
+  ldr r4, [r9], #4
+  ldr r11, [r3], #4
+  ldr r5, [r9], #4
+  smlad r2, r10, r4, r2
+  ldrh r10, [r3], #-14        @ r3 back to &ubufQQpos2[*index2].
+  ldrh  r4, [r9], #-16        @ r9 back to &coefficient[0].
+  smlad r2, r11, r5, r2
+  smlabb r2, r10, r4, r2
+
+  @ Saturate to avoid overflow in tmpW16.
+  asr r2, #1
+  add r4, r2, #0x1000
+  ssat r7, #16, r4, asr #13
+
+  @ Shift low pass filter state, and excute the low pass filter.
+  @ The memmove() and the low pass filter loop are unrolled and mixed.
+  smulbb r5, r1, r7
+  add r7, r5, #0x800
+  asr r7, #12                 @ Get the value for inputState[0].
+  ldr r11, [sp, #40]          @ inputState
+  pld [r11]
+  adr r10, kDampFilter
+  ldrsh r4, [r10], #2         @ kDampFilter[0]
+  mul r2, r7, r4
+  ldr r4, [r11]               @ inputState[0, 1], before shift.
+  strh r7, [r11]              @ inputState[0], after shift.
+  ldr r5, [r11, #4]           @ inputState[2, 3], before shift.
+  ldr r7, [r10], #4           @ kDampFilter[1, 2]
+  ldr r10, [r10]              @ kDampFilter[3, 4]
+  str r4, [r11, #2]           @ inputState[1, 2], after shift.
+  str r5, [r11, #6]           @ inputState[3, 4], after shift.
+  smlad r2, r4, r7, r2
+  smlad r2, r5, r10, r2
+
+  @ Saturate to avoid overflow.
+  @ First shift the sample to the range of [0xC0000000, 0x3FFFFFFF],
+  @ to avoid overflow in the next saturation step.
+  asr r2, #1
+  add r10, r2, #0x2000
+  ssat r10, #16, r10, asr #14
+
+  @ Subtract from input and update buffer.
+  ldr r11, [sp, #4]           @ sign
+  ldrsh r4, [r8]
+  ldrsh r7, [r8], #2          @ inputBuf[*index2]
+  smulbb r5, r11, r10
+  subs r0, #1
+  sub r4, r5
+  ssat r2, #16, r4
+  strh  r2, [r12], #2         @ outputBuf[*index2]
+
+  add r2, r7
+  ssat r2, #16, r2
+  strh  r2, [r6], #2          @ outputBuff2[*index2 + PITCH_BUFFSIZE]
+  bgt LOOP
+
+  add sp, #8
+  pop {r4-r11}
+  bx  lr
+
+.align  2
+kDampFilter:
+  .short  -2294, 8192, 20972, 8192, -2294
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
new file mode 100644
index 0000000..f23d19d
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+/* Filter coefficicients in Q15. */
+static const int16_t kDampFilter[PITCH_DAMPORDER] = {
+  -2294, 8192, 20972, 8192, -2294
+};
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+                                   int16_t gain,
+                                   size_t index,
+                                   int16_t sign,
+                                   int16_t* inputState,
+                                   int16_t* outputBuf2,
+                                   const int16_t* coefficient,
+                                   int16_t* inputBuf,
+                                   int16_t* outputBuf,
+                                   int* index2) {
+  int i = 0, j = 0;  /* Loop counters. */
+  int16_t* ubufQQpos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)];
+  int16_t tmpW16 = 0;
+
+  for (i = 0; i < loopNumber; i++) {
+    int32_t tmpW32 = 0;
+
+    /* Filter to get fractional pitch. */
+    for (j = 0; j < PITCH_FRACORDER; j++) {
+      tmpW32 += ubufQQpos2[*index2 + j] * coefficient[j];
+    }
+
+    /* Saturate to avoid overflow in tmpW16. */
+    tmpW32 = WEBRTC_SPL_SAT(536862719, tmpW32, -536879104);
+    tmpW32 += 8192;
+    tmpW16 = (int16_t)(tmpW32 >> 14);
+
+    /* Shift low pass filter state. */
+    memmove(&inputState[1], &inputState[0],
+            (PITCH_DAMPORDER - 1) * sizeof(int16_t));
+    inputState[0] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+                      gain, tmpW16, 12);
+
+    /* Low pass filter. */
+    tmpW32 = 0;
+    /* TODO(kma): Define a static inline function WebRtcSpl_DotProduct()
+       in spl_inl.h to replace this and other similar loops. */
+    for (j = 0; j < PITCH_DAMPORDER; j++) {
+      tmpW32 += inputState[j] * kDampFilter[j];
+    }
+
+    /* Saturate to avoid overflow in tmpW16. */
+    tmpW32 = WEBRTC_SPL_SAT(1073725439, tmpW32, -1073758208);
+    tmpW32 += 16384;
+    tmpW16 = (int16_t)(tmpW32 >> 15);
+
+    /* Subtract from input and update buffer. */
+    tmpW32 = inputBuf[*index2] - sign * tmpW16;
+    outputBuf[*index2] = WebRtcSpl_SatW32ToW16(tmpW32);
+    tmpW32 = inputBuf[*index2] + outputBuf[*index2];
+    outputBuf2[*index2 + PITCH_BUFFSIZE] = WebRtcSpl_SatW32ToW16(tmpW32);
+
+    (*index2)++;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c
new file mode 100644
index 0000000..785fd94
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+                                   int16_t gain,
+                                   size_t index,
+                                   int16_t sign,
+                                   int16_t* inputState,
+                                   int16_t* outputBuf2,
+                                   const int16_t* coefficient,
+                                   int16_t* inputBuf,
+                                   int16_t* outputBuf,
+                                   int* index2) {
+  int ind2t = *index2;
+  int i = 0;
+  int16_t* out2_pos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)] + ind2t;
+  int32_t w1, w2, w3, w4, w5, gain32, sign32;
+  int32_t coef1, coef2, coef3, coef4, coef5 = 0;
+  // Define damp factors as int32_t (pair of int16_t)
+  int32_t kDampF0 = 0x0000F70A;
+  int32_t kDampF1 = 0x51EC2000;
+  int32_t kDampF2 = 0xF70A2000;
+  int16_t* input1 = inputBuf + ind2t;
+  int16_t* output1 = outputBuf + ind2t;
+  int16_t* output2 = outputBuf2 + ind2t + PITCH_BUFFSIZE;
+
+  // Load coefficients outside the loop and sign-extend gain and sign
+  __asm __volatile (
+    ".set     push                                        \n\t"
+    ".set     noreorder                                   \n\t"
+    "lwl      %[coef1],       3(%[coefficient])           \n\t"
+    "lwl      %[coef2],       7(%[coefficient])           \n\t"
+    "lwl      %[coef3],       11(%[coefficient])          \n\t"
+    "lwl      %[coef4],       15(%[coefficient])          \n\t"
+    "lwr      %[coef1],       0(%[coefficient])           \n\t"
+    "lwr      %[coef2],       4(%[coefficient])           \n\t"
+    "lwr      %[coef3],       8(%[coefficient])           \n\t"
+    "lwr      %[coef4],       12(%[coefficient])          \n\t"
+    "lhu      %[coef5],       16(%[coefficient])          \n\t"
+    "seh      %[gain32],      %[gain]                     \n\t"
+    "seh      %[sign32],      %[sign]                     \n\t"
+    ".set     pop                                         \n\t"
+    : [coef1] "=&r" (coef1), [coef2] "=&r" (coef2), [coef3] "=&r" (coef3),
+      [coef4] "=&r" (coef4), [coef5] "=&r" (coef5), [gain32] "=&r" (gain32),
+      [sign32] "=&r" (sign32)
+    : [coefficient] "r" (coefficient), [gain] "r" (gain),
+      [sign] "r" (sign)
+    : "memory"
+  );
+
+  for (i = 0; i < loopNumber; i++) {
+    __asm __volatile (
+      ".set       push                                            \n\t"
+      ".set       noreorder                                       \n\t"
+      // Filter to get fractional pitch
+      "li         %[w1],          8192                            \n\t"
+      "mtlo       %[w1]                                           \n\t"
+      "mthi       $0                                              \n\t"
+      "lwl        %[w1],          3(%[out2_pos2])                 \n\t"
+      "lwl        %[w2],          7(%[out2_pos2])                 \n\t"
+      "lwl        %[w3],          11(%[out2_pos2])                \n\t"
+      "lwl        %[w4],          15(%[out2_pos2])                \n\t"
+      "lwr        %[w1],          0(%[out2_pos2])                 \n\t"
+      "lwr        %[w2],          4(%[out2_pos2])                 \n\t"
+      "lwr        %[w3],          8(%[out2_pos2])                 \n\t"
+      "lwr        %[w4],          12(%[out2_pos2])                \n\t"
+      "lhu        %[w5],          16(%[out2_pos2])                \n\t"
+      "dpa.w.ph   $ac0,           %[w1],              %[coef1]    \n\t"
+      "dpa.w.ph   $ac0,           %[w2],              %[coef2]    \n\t"
+      "dpa.w.ph   $ac0,           %[w3],              %[coef3]    \n\t"
+      "dpa.w.ph   $ac0,           %[w4],              %[coef4]    \n\t"
+      "dpa.w.ph   $ac0,           %[w5],              %[coef5]    \n\t"
+      "addiu      %[out2_pos2],   %[out2_pos2],       2           \n\t"
+      "mthi       $0,             $ac1                            \n\t"
+      "lwl        %[w2],          3(%[inputState])                \n\t"
+      "lwl        %[w3],          7(%[inputState])                \n\t"
+      // Fractional pitch shift & saturation
+      "extr_s.h   %[w1],          $ac0,               14          \n\t"
+      "li         %[w4],          16384                           \n\t"
+      "lwr        %[w2],          0(%[inputState])                \n\t"
+      "lwr        %[w3],          4(%[inputState])                \n\t"
+      "mtlo       %[w4],          $ac1                            \n\t"
+      // Shift low pass filter state
+      "swl        %[w2],          5(%[inputState])                \n\t"
+      "swl        %[w3],          9(%[inputState])                \n\t"
+      "mul        %[w1],          %[gain32],          %[w1]       \n\t"
+      "swr        %[w2],          2(%[inputState])                \n\t"
+      "swr        %[w3],          6(%[inputState])                \n\t"
+      // Low pass filter accumulation
+      "dpa.w.ph   $ac1,           %[kDampF1],         %[w2]       \n\t"
+      "dpa.w.ph   $ac1,           %[kDampF2],         %[w3]       \n\t"
+      "lh         %[w4],          0(%[input1])                    \n\t"
+      "addiu      %[input1],      %[input1],          2           \n\t"
+      "shra_r.w   %[w1],          %[w1],              12          \n\t"
+      "sh         %[w1],          0(%[inputState])                \n\t"
+      "dpa.w.ph   $ac1,           %[kDampF0],         %[w1]       \n\t"
+      // Low pass filter shift & saturation
+      "extr_s.h   %[w2],          $ac1,               15          \n\t"
+      "mul        %[w2],          %[w2],              %[sign32]   \n\t"
+      // Buffer update
+      "subu       %[w2],          %[w4],              %[w2]       \n\t"
+      "shll_s.w   %[w2],          %[w2],              16          \n\t"
+      "sra        %[w2],          %[w2],              16          \n\t"
+      "sh         %[w2],          0(%[output1])                   \n\t"
+      "addu       %[w2],          %[w2],              %[w4]       \n\t"
+      "shll_s.w   %[w2],          %[w2],              16          \n\t"
+      "addiu      %[output1],     %[output1],         2           \n\t"
+      "sra        %[w2],          %[w2],              16          \n\t"
+      "sh         %[w2],          0(%[output2])                   \n\t"
+      "addiu      %[output2],     %[output2],         2           \n\t"
+      ".set       pop                                             \n\t"
+      : [w1] "=&r" (w1), [w2] "=&r" (w2), [w3] "=&r" (w3), [w4] "=&r" (w4),
+        [w5] "=&r" (w5), [input1] "+r" (input1), [out2_pos2] "+r" (out2_pos2),
+        [output1] "+r" (output1), [output2] "+r" (output2)
+      : [coefficient] "r" (coefficient), [inputState] "r" (inputState),
+        [gain32] "r" (gain32), [sign32] "r" (sign32), [kDampF0] "r" (kDampF0),
+        [kDampF1] "r" (kDampF1), [kDampF2] "r" (kDampF2),
+        [coef1] "r" (coef1), [coef2] "r" (coef2), [coef3] "r" (coef3),
+        [coef4] "r" (coef4), [coef5] "r" (coef5)
+      : "hi", "lo", "$ac1hi", "$ac1lo", "memory"
+    );
+  }
+  (*index2) += loopNumber;
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
new file mode 100644
index 0000000..bfbab19
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* cdf for quantized pitch filter gains */
+const uint16_t WebRtcIsacfix_kPitchGainCdf[255] = {
+  0,  2,  4,  6,  64,  901,  903,  905,  16954,  16956,
+  16961,  17360,  17362,  17364,  17366,  17368,  17370,  17372,  17374,  17411,
+  17514,  17516,  17583,  18790,  18796,  18802,  20760,  20777,  20782,  21722,
+  21724,  21728,  21738,  21740,  21742,  21744,  21746,  21748,  22224,  22227,
+  22230,  23214,  23229,  23239,  25086,  25108,  25120,  26088,  26094,  26098,
+  26175,  26177,  26179,  26181,  26183,  26185,  26484,  26507,  26522,  27705,
+  27731,  27750,  29767,  29799,  29817,  30866,  30883,  30885,  31025,  31029,
+  31031,  31033,  31035,  31037,  31114,  31126,  31134,  32687,  32722,  32767,
+  35718,  35742,  35757,  36943,  36952,  36954,  37115,  37128,  37130,  37132,
+  37134,  37136,  37143,  37145,  37152,  38843,  38863,  38897,  47458,  47467,
+  47474,  49040,  49061,  49063,  49145,  49157,  49159,  49161,  49163,  49165,
+  49167,  49169,  49171,  49757,  49770,  49782,  61333,  61344,  61346,  62860,
+  62883,  62885,  62887,  62889,  62891,  62893,  62895,  62897,  62899,  62901,
+  62903,  62905,  62907,  62909,  65496,  65498,  65500,  65521,  65523,  65525,
+  65527,  65529,  65531,  65533,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerlimiGain[3] = {
+  -7, -2, -1
+};
+
+const int16_t WebRtcIsacfix_kUpperlimitGain[3] = {
+  0,  3,  1
+};
+
+const uint16_t WebRtcIsacfix_kMultsGain[2] = {
+  18,  3
+};
+
+/* size of cdf table */
+const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1] = {
+  256
+};
+
+/* mean values of pitch filter gains in FIXED point Q12 */
+const int16_t WebRtcIsacfix_kPitchGain1[144] = {
+  843, 1092, 1336, 1222, 1405, 1656, 1500, 1815, 1843, 1838, 1839,
+  1843, 1843, 1843, 1843, 1843,   1843, 1843, 814, 846, 1092, 1013,
+  1174, 1383, 1391, 1511, 1584, 1734, 1753, 1843, 1843, 1843,   1843,
+  1843, 1843, 1843, 524, 689, 777, 845, 947, 1069, 1090, 1263,
+  1380, 1447, 1559, 1676,   1645, 1749, 1843, 1843, 1843, 1843, 81,
+  477, 563, 611, 706, 806, 849, 1012, 1192, 1128,   1330, 1489,
+  1425, 1576, 1826, 1741, 1843, 1843, 0,     290, 305, 356, 488,
+  575, 602, 741,    890, 835, 1079, 1196, 1182, 1376, 1519, 1506,
+  1680, 1843, 0,     47,  97,  69,  289, 381,    385, 474, 617,
+  664, 803, 1079, 935, 1160, 1269, 1265, 1506, 1741, 0,      0,
+  0,      0,      112, 120, 190, 283, 442, 343, 526, 809, 684,
+  935, 1134, 1020, 1265, 1506, 0,      0,      0,      0,      0,      0,
+  0,      111,    256, 87,  373, 597, 430, 684, 935, 770, 1020,
+  1265
+};
+
+const int16_t WebRtcIsacfix_kPitchGain2[144] = {
+  1760, 1525, 1285, 1747, 1671, 1393, 1843, 1826, 1555, 1843, 1784,
+  1606, 1843, 1843, 1711, 1843,   1843, 1814, 1389, 1275, 1040, 1564,
+  1414, 1252, 1610, 1495, 1343, 1753, 1592, 1405, 1804, 1720,   1475,
+  1843, 1814, 1581, 1208, 1061, 856, 1349, 1148, 994, 1390, 1253,
+  1111, 1495, 1343, 1178,   1770, 1465, 1234, 1814, 1581, 1342, 1040,
+  793, 713, 1053, 895, 737, 1128, 1003, 861, 1277,   1094, 981,
+  1475, 1192, 1019, 1581, 1342, 1098, 855, 570, 483, 833, 648,
+  540, 948, 744,    572, 1009, 844, 636, 1234, 934, 685, 1342,
+  1217, 984, 537, 318, 124, 603, 423, 350,    687, 479, 322,
+  791, 581, 430, 987, 671, 488, 1098, 849, 597, 283, 27,
+  0,     397,    222, 38,  513, 271, 124, 624, 325, 157, 737,
+  484, 233, 849, 597, 343, 27,  0,      0,   141, 0,     0,
+  256, 69,  0,     370, 87,  0,     484, 229, 0,     597, 343,
+  87
+};
+
+const int16_t WebRtcIsacfix_kPitchGain3[144] = {
+  1843, 1843, 1711, 1843, 1818, 1606, 1843, 1827, 1511, 1814, 1639,
+  1393, 1760, 1525, 1285, 1656,   1419, 1176, 1835, 1718, 1475, 1841,
+  1650, 1387, 1648, 1498, 1287, 1600, 1411, 1176, 1522, 1299,   1040,
+  1419, 1176, 928, 1773, 1461, 1128, 1532, 1355, 1202, 1429, 1260,
+  1115, 1398, 1151, 1025,   1172, 1080, 790, 1176, 928, 677, 1475,
+  1147, 1019, 1276, 1096, 922, 1214, 1010, 901, 1057,   893, 800,
+  1040, 796, 734, 928, 677, 424, 1137, 897, 753, 1120, 830,
+  710, 875, 751,    601, 795, 642, 583, 790, 544, 475, 677,
+  474, 140, 987, 750, 482, 697, 573, 450,    691, 487, 303,
+  661, 394, 332, 537, 303, 220, 424, 168, 0,     737, 484,
+  229, 624,    348, 153, 441, 261, 136, 397, 166, 51,  283,
+  27,  0,     168, 0,     0,     484, 229,    0,   370, 57,  0,
+  256, 43,  0,     141, 0,  0,   27,  0,   0,   0,   0,
+  0
+};
+
+
+const int16_t WebRtcIsacfix_kPitchGain4[144] = {
+  1843, 1843, 1843, 1843, 1841, 1843, 1500, 1821, 1843, 1222, 1434,
+  1656, 843, 1092, 1336, 504,    757, 1007, 1843, 1843, 1843, 1838,
+  1791, 1843, 1265, 1505, 1599, 965, 1219, 1425, 730, 821,    1092,
+  249, 504, 757, 1783, 1819, 1843, 1351, 1567, 1727, 1096, 1268,
+  1409, 805, 961, 1131,   444, 670, 843, 0,  249, 504, 1425,
+  1655, 1743, 1096, 1324, 1448, 822, 1019, 1199, 490,    704, 867,
+  81,  450, 555, 0,     0,  249, 1247, 1428, 1530, 881, 1073,
+  1283, 610, 759,    939, 278, 464, 645, 0,     200, 270, 0,
+  0,   0,  935, 1163, 1410, 528, 790, 1068,   377, 499, 717,
+  173, 240, 274, 0,   43,  62,  0,   0,   0,   684, 935,
+  1182, 343,    551, 735, 161, 262, 423, 0,      55,  27,  0,
+  0,   0,   0,   0,   0,   430, 684,    935, 87,  377, 597,
+  0,   46,  256, 0,   0,   0,   0,   0,   0,   0,   0,
+  0
+};
+
+
+
+/* transform matrix in Q12*/
+const int16_t WebRtcIsacfix_kTransform[4][4] = {
+  { -2048, -2048, -2048, -2048 },
+  {  2748,   916,  -916, -2748 },
+  {  2048, -2048, -2048,  2048 },
+  {   916, -2748,  2748,  -916 }
+};
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
new file mode 100644
index 0000000..59e1738
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include <stdint.h>
+
+/********************* Pitch Filter Gain Coefficient Tables
+ * ************************/
+/* cdf for quantized pitch filter gains */
+extern const uint16_t WebRtcIsacfix_kPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerlimiGain[3];
+extern const int16_t WebRtcIsacfix_kUpperlimitGain[3];
+extern const uint16_t WebRtcIsacfix_kMultsGain[2];
+
+/* mean values of pitch filter gains in Q12*/
+extern const int16_t WebRtcIsacfix_kPitchGain1[144];
+extern const int16_t WebRtcIsacfix_kPitchGain2[144];
+extern const int16_t WebRtcIsacfix_kPitchGain3[144];
+extern const int16_t WebRtcIsacfix_kPitchGain4[144];
+
+/* size of cdf table */
+extern const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1];
+
+/* transform matrix */
+extern const int16_t WebRtcIsacfix_kTransform[4][4];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
new file mode 100644
index 0000000..894716e
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
@@ -0,0 +1,306 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Lo[127] = {
+  0,  134,  336,  549,  778,  998,  1264,  1512,  1777,  2070,
+  2423,  2794,  3051,  3361,  3708,  3979,  4315,  4610,  4933,  5269,
+  5575,  5896,  6155,  6480,  6816,  7129,  7477,  7764,  8061,  8358,
+  8718,  9020,  9390,  9783,  10177,  10543,  10885,  11342,  11795,  12213,
+  12680,  13096,  13524,  13919,  14436,  14903,  15349,  15795,  16267,  16734,
+  17266,  17697,  18130,  18632,  19080,  19447,  19884,  20315,  20735,  21288,
+  21764,  22264,  22723,  23193,  23680,  24111,  24557,  25022,  25537,  26082,
+  26543,  27090,  27620,  28139,  28652,  29149,  29634,  30175,  30692,  31273,
+  31866,  32506,  33059,  33650,  34296,  34955,  35629,  36295,  36967,  37726,
+  38559,  39458,  40364,  41293,  42256,  43215,  44231,  45253,  46274,  47359,
+  48482,  49678,  50810,  51853,  53016,  54148,  55235,  56263,  57282,  58363,
+  59288,  60179,  61076,  61806,  62474,  63129,  63656,  64160,  64533,  64856,
+  65152,  65535,  65535,  65535,  65535,  65535,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20] = {
+  0,  429,  3558,  5861,  8558,  11639,  15210,  19502,  24773,  31983,
+  42602,  48567,  52601,  55676,  58160,  60172,  61889,  63235,  65383,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2] = {
+  0,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10] = {
+  0,  2966,  6368,  11182,  19431,  37793,  48532,  55353,  60626,  65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrLo[4] = {
+  WebRtcIsacfix_kPitchLagCdf1Lo,
+  WebRtcIsacfix_kPitchLagCdf2Lo,
+  WebRtcIsacfix_kPitchLagCdf3Lo,
+  WebRtcIsacfix_kPitchLagCdf4Lo
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1] = {
+  128
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitLo[4] = {
+  -140, -9,  0, -4
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitLo[4] = {
+  -20,  9,  0,  4
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndLo[3] = {
+  10,  1,  5
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const int16_t WebRtcIsacfix_kMeanLag2Lo[19] = {
+  -17627, -16207, -14409, -12319, -10253, -8200, -6054, -3986, -1948, -19,
+  1937, 3974, 6064, 8155, 10229, 12270, 14296, 16127, 17520
+};
+
+const int16_t WebRtcIsacfix_kMeanLag4Lo[9] = {
+  -7949, -6063, -4036, -1941, 38, 1977, 4060, 6059
+};
+
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Mid[255] = {
+  0,  28,  61,  88,  121,  149,  233,  331,  475,  559,
+  624,  661,  689,  712,  745,  791,  815,  843,  866,  922,
+  959,  1024,  1061,  1117,  1178,  1238,  1280,  1350,  1453,  1513,
+  1564,  1625,  1671,  1741,  1788,  1904,  2072,  2421,  2626,  2770,
+  2840,  2900,  2942,  3012,  3068,  3115,  3147,  3194,  3254,  3319,
+  3366,  3520,  3678,  3780,  3850,  3911,  3957,  4032,  4106,  4185,
+  4292,  4474,  4683,  4842,  5019,  5191,  5321,  5428,  5540,  5675,
+  5763,  5847,  5959,  6127,  6304,  6564,  6839,  7090,  7263,  7421,
+  7556,  7728,  7872,  7984,  8142,  8361,  8580,  8743,  8938,  9227,
+  9409,  9539,  9674,  9795,  9930,  10060,  10177,  10382,  10614,  10861,
+  11038,  11271,  11415,  11629,  11792,  12044,  12193,  12416,  12574,  12821,
+  13007,  13235,  13445,  13654,  13901,  14134,  14488,  15000,  15703,  16285,
+  16504,  16797,  17086,  17328,  17579,  17807,  17998,  18268,  18538,  18836,
+  19087,  19274,  19474,  19716,  19935,  20270,  20833,  21303,  21532,  21741,
+  21978,  22207,  22523,  22770,  23054,  23613,  23943,  24204,  24399,  24651,
+  24832,  25074,  25270,  25549,  25759,  26015,  26150,  26424,  26713,  27048,
+  27342,  27504,  27681,  27854,  28021,  28207,  28412,  28664,  28859,  29064,
+  29278,  29548,  29748,  30107,  30377,  30656,  30856,  31164,  31452,  31755,
+  32011,  32328,  32626,  32919,  33319,  33789,  34329,  34925,  35396,  35973,
+  36443,  36964,  37551,  38156,  38724,  39357,  40023,  40908,  41587,  42602,
+  43924,  45037,  45810,  46597,  47421,  48291,  49092,  50051,  51448,  52719,
+  53440,  54241,  54944,  55977,  56676,  57299,  57872,  58389,  59059,  59688,
+  60237,  60782,  61094,  61573,  61890,  62290,  62658,  63030,  63217,  63454,
+  63622,  63882,  64003,  64273,  64427,  64529,  64581,  64697,  64758,  64902,
+  65414,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Mid[36] = {
+  0,  71,  335,  581,  836,  1039,  1323,  1795,  2258,  2608,
+  3005,  3591,  4243,  5344,  7163,  10583,  16848,  28078,  49448,  57007,
+  60357,  61850,  62837,  63437,  63872,  64188,  64377,  64614,  64774,  64949,
+  65039,  65115,  65223,  65360,  65474,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2] = {
+  0,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20] = {
+  0,  28,  246,  459,  667,  1045,  1523,  2337,  4337,  11347,
+  44231,  56709,  60781,  62243,  63161,  63969,  64608,  65062,  65502,  65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrMid[4] = {
+  WebRtcIsacfix_kPitchLagCdf1Mid,
+  WebRtcIsacfix_kPitchLagCdf2Mid,
+  WebRtcIsacfix_kPitchLagCdf3Mid,
+  WebRtcIsacfix_kPitchLagCdf4Mid
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1] = {
+  256
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitMid[4] = {
+  -280, -17,  0, -9
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitMid[4] = {
+  -40,  17,  0,  9
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndMid[3] = {
+  18,  1,  10
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const int16_t WebRtcIsacfix_kMeanLag2Mid[35] = {
+  -17297, -16250, -15416, -14343, -13341, -12363, -11270,
+  -10355, -9122, -8217, -7172, -6083, -5102, -4004, -3060,
+  -1982, -952, -18, 935, 1976, 3040, 4032,
+  5082, 6065, 7257, 8202, 9264, 10225, 11242,
+  12234, 13337, 14336, 15374, 16187, 17347
+};
+
+
+const int16_t WebRtcIsacfix_kMeanLag4Mid[19] = {
+  -8811, -8081, -7203, -6003, -5057, -4025, -2983, -1964,
+  -891, 29, 921, 1920, 2988, 4064, 5187, 6079, 7173, 8074, 8849
+};
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Hi[511] = {
+  0,  7,  18,  33,  69,  105,  156,  228,  315,  612,
+  680,  691,  709,  724,  735,  738,  742,  746,  749,  753,
+  756,  760,  764,  774,  782,  785,  789,  796,  800,  803,
+  807,  814,  818,  822,  829,  832,  847,  854,  858,  869,
+  876,  883,  898,  908,  934,  977,  1010,  1050,  1060,  1064,
+  1075,  1078,  1086,  1089,  1093,  1104,  1111,  1122,  1133,  1136,
+  1151,  1162,  1183,  1209,  1252,  1281,  1339,  1364,  1386,  1401,
+  1411,  1415,  1426,  1430,  1433,  1440,  1448,  1455,  1462,  1477,
+  1487,  1495,  1502,  1506,  1509,  1516,  1524,  1531,  1535,  1542,
+  1553,  1556,  1578,  1589,  1611,  1625,  1639,  1643,  1654,  1665,
+  1672,  1687,  1694,  1705,  1708,  1719,  1730,  1744,  1752,  1759,
+  1791,  1795,  1820,  1867,  1886,  1915,  1936,  1943,  1965,  1987,
+  2041,  2099,  2161,  2175,  2200,  2211,  2226,  2233,  2244,  2251,
+  2266,  2280,  2287,  2298,  2309,  2316,  2331,  2342,  2356,  2378,
+  2403,  2418,  2447,  2497,  2544,  2602,  2863,  2895,  2903,  2935,
+  2950,  2971,  3004,  3011,  3018,  3029,  3040,  3062,  3087,  3127,
+  3152,  3170,  3199,  3243,  3293,  3322,  3340,  3377,  3402,  3427,
+  3474,  3518,  3543,  3579,  3601,  3637,  3659,  3706,  3731,  3760,
+  3818,  3847,  3869,  3901,  3920,  3952,  4068,  4169,  4220,  4271,
+  4524,  4571,  4604,  4632,  4672,  4730,  4777,  4806,  4857,  4904,
+  4951,  5002,  5031,  5060,  5107,  5150,  5212,  5266,  5331,  5382,
+  5432,  5490,  5544,  5610,  5700,  5762,  5812,  5874,  5972,  6022,
+  6091,  6163,  6232,  6305,  6402,  6540,  6685,  6880,  7090,  7271,
+  7379,  7452,  7542,  7625,  7687,  7770,  7843,  7911,  7966,  8024,
+  8096,  8190,  8252,  8320,  8411,  8501,  8585,  8639,  8751,  8842,
+  8918,  8986,  9066,  9127,  9203,  9269,  9345,  9406,  9464,  9536,
+  9612,  9667,  9735,  9844,  9931,  10036,  10119,  10199,  10260,  10358,
+  10441,  10514,  10666,  10734,  10872,  10951,  11053,  11125,  11223,  11324,
+  11516,  11664,  11737,  11816,  11892,  12008,  12120,  12200,  12280,  12392,
+  12490,  12576,  12685,  12812,  12917,  13003,  13108,  13210,  13300,  13384,
+  13470,  13579,  13673,  13771,  13879,  13999,  14136,  14201,  14368,  14614,
+  14759,  14867,  14958,  15030,  15121,  15189,  15280,  15385,  15461,  15555,
+  15653,  15768,  15884,  15971,  16069,  16145,  16210,  16279,  16380,  16463,
+  16539,  16615,  16688,  16818,  16919,  17017,  18041,  18338,  18523,  18649,
+  18790,  18917,  19047,  19167,  19315,  19460,  19601,  19731,  19858,  20068,
+  20173,  20318,  20466,  20625,  20741,  20911,  21045,  21201,  21396,  21588,
+  21816,  22022,  22305,  22547,  22786,  23072,  23322,  23600,  23879,  24168,
+  24433,  24769,  25120,  25511,  25895,  26289,  26792,  27219,  27683,  28077,
+  28566,  29094,  29546,  29977,  30491,  30991,  31573,  32105,  32594,  33173,
+  33788,  34497,  35181,  35833,  36488,  37255,  37921,  38645,  39275,  39894,
+  40505,  41167,  41790,  42431,  43096,  43723,  44385,  45134,  45858,  46607,
+  47349,  48091,  48768,  49405,  49955,  50555,  51167,  51985,  52611,  53078,
+  53494,  53965,  54435,  54996,  55601,  56125,  56563,  56838,  57244,  57566,
+  57967,  58297,  58771,  59093,  59419,  59647,  59886,  60143,  60461,  60693,
+  60917,  61170,  61416,  61634,  61891,  62122,  62310,  62455,  62632,  62839,
+  63103,  63436,  63639,  63805,  63906,  64015,  64192,  64355,  64475,  64558,
+  64663,  64742,  64811,  64865,  64916,  64956,  64981,  65025,  65068,  65115,
+  65195,  65314,  65419,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Hi[68] = {
+  0,  7,  11,  22,  37,  52,  56,  59,  81,  85,
+  89,  96,  115,  130,  137,  152,  170,  181,  193,  200,
+  207,  233,  237,  259,  289,  318,  363,  433,  592,  992,
+  1607,  3062,  6149,  12206,  25522,  48368,  58223,  61918,  63640,  64584,
+  64943,  65098,  65206,  65268,  65294,  65335,  65350,  65372,  65387,  65402,
+  65413,  65420,  65428,  65435,  65439,  65450,  65454,  65468,  65472,  65476,
+  65483,  65491,  65498,  65505,  65516,  65520,  65528,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2] = {
+  0,  65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Hi[35] = {
+  0,  7,  19,  30,  41,  48,  63,  74,  82,  96,
+  122,  152,  215,  330,  701,  2611,  10931,  48106,  61177,  64341,
+  65112,  65238,  65309,  65338,  65364,  65379,  65401,  65427,  65453,
+  65465,  65476,  65490,  65509,  65528,  65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrHi[4] = {
+  WebRtcIsacfix_kPitchLagCdf1Hi,
+  WebRtcIsacfix_kPitchLagCdf2Hi,
+  WebRtcIsacfix_kPitchLagCdf3Hi,
+  WebRtcIsacfix_kPitchLagCdf4Hi
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1] = {
+  512
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitHi[4] = {
+  -552, -34,  0, -16
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitHi[4] = {
+  -80,  32,  0,  17
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndHi[3] = {
+  34,  1,  18
+};
+
+/* mean values of pitch filter lags */
+
+const int16_t WebRtcIsacfix_kMeanLag2Hi[67] = {
+  -17482, -16896, -16220, -15929, -15329, -14848, -14336, -13807, -13312, -12800, -12218, -11720,
+  -11307, -10649, -10396, -9742, -9148, -8668, -8297, -7718, -7155, -6656, -6231, -5600, -5129,
+  -4610, -4110, -3521, -3040, -2525, -2016, -1506, -995, -477, -5, 469, 991, 1510, 2025, 2526, 3079,
+  3555, 4124, 4601, 5131, 5613, 6194, 6671, 7140, 7645, 8207, 8601, 9132, 9728, 10359, 10752, 11302,
+  11776, 12288, 12687, 13204, 13759, 14295, 14810, 15360, 15764, 16350
+};
+
+
+const int16_t WebRtcIsacfix_kMeanLag4Hi[34] = {
+  -8175, -7659, -7205, -6684, -6215, -5651, -5180, -4566, -4087, -3536, -3096,
+  -2532, -1990, -1482, -959, -440, 11, 451, 954, 1492, 2020, 2562, 3059,
+  3577, 4113, 4618, 5134, 5724, 6060, 6758, 7015, 7716, 8066, 8741
+};
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
new file mode 100644
index 0000000..228da26
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
+
+#include <stdint.h>
+
+/********************* Pitch Filter Lag Coefficient Tables
+ * ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Lo[127];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrLo[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitLo[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitLo[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndLo[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Lo[19];
+extern const int16_t WebRtcIsacfix_kMeanLag4Lo[9];
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Mid[255];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Mid[36];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrMid[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitMid[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitMid[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndMid[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Mid[35];
+extern const int16_t WebRtcIsacfix_kMeanLag4Mid[19];
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Hi[511];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Hi[68];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Hi[35];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrHi[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitHi[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitHi[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndHi[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Hi[67];
+extern const int16_t WebRtcIsacfix_kMeanLag4Hi[34];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/settings.h b/modules/audio_coding/codecs/isac/fix/source/settings.h
new file mode 100644
index 0000000..03a2d05
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/settings.h
@@ -0,0 +1,211 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+
+/* sampling frequency (Hz) */
+#define FS 16000
+/* 1.5 times Sampling frequency */
+#define FS_1_HALF (uint32_t)24000
+/* Three times Sampling frequency */
+#define FS3 (uint32_t)48000
+/* Eight times Sampling frequency */
+#define FS8 (uint32_t)128000
+
+/* number of samples per frame (either 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder (30ms) */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms 160 /* ((10*FS)/1000) */
+/* Number of samples per 1 ms */
+#define SAMPLES_PER_MSEC 16
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN 40 /* (UPDATE/2) */
+/* samples of look ahead (in a half-band, so actually half the samples of look
+ * ahead @ FS) */
+#define QLOOKAHEAD 24 /* 3 ms */
+
+/* order of AR model in spectral entropy coder */
+#define AR_ORDER 6
+#define MAX_ORDER 13
+#define LEVINSON_MAX_ORDER 12
+
+/* window length (masking analysis) */
+#define WINLEN 256
+/* order of low-band pole filter used to approximate masking curve */
+#define ORDERLO 12
+/* order of hi-band pole filter used to approximate masking curve */
+#define ORDERHI 6
+
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_SHAPE_ORDER 18 /* (ORDERLO + ORDERHI) */
+
+#define KLT_ORDER_GAIN 12   /* (2 * SUBFRAMES) */
+#define KLT_ORDER_SHAPE 108 /*  (LPC_SHAPE_ORDER * SUBFRAMES) */
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* for decimator */
+#define ALLPASSSECTIONS 2
+/* The number of composite all-pass filter factors */
+#define NUMBEROFCOMPOSITEAPSECTIONS 4
+
+/* The number of all-pass filter factors in an upper or lower channel*/
+#define NUMBEROFCHANNELAPSECTIONS 2
+
+#define DPMIN_Q10 -10240  /* -10.00 in Q10 */
+#define DPMAX_Q10 10240   /* 10.00 in Q10 */
+#define MINBITS_Q10 10240 /* 10.0 in Q10 */
+
+/* array size for byte stream in number of Word16. */
+#define STREAM_MAXW16 \
+  300 /* The old maximum size still needed for the decoding */
+#define STREAM_MAXW16_30MS \
+  100 /* 100 Word16 = 200 bytes = 53.4 kbit/s @ 30 ms.framelength */
+#define STREAM_MAXW16_60MS \
+  200 /* 200 Word16 = 400 bytes = 53.4 kbit/s @ 60 ms.framelength */
+/* This is used only at the decoder bit-stream struct.
+ * - The encoder and decoder bitstream containers are of different size because
+ *   old iSAC limited the encoded bitstream to 600 bytes. But newer versions
+ *   restrict to shorter bitstream.
+ * - We add 10 bytes of guards to the internal bitstream container. The reason
+ *   is that entropy decoder might read few bytes (3 according to our
+ *   observations) more than the actual size of the bitstream. To avoid reading
+ *   outside memory, in rare occasion of full-size bitstream we add 10 bytes
+ *   of guard. */
+#define INTERNAL_STREAM_SIZE_W16 (STREAM_MAXW16 + 5)
+
+/* storage size for bit counts */
+//#define BIT_COUNTER_SIZE                        30
+/* maximum order of any AR model or filter */
+#define MAX_AR_MODEL_ORDER 12
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 1
+
+/* Bandwidth estimator */
+
+#define MIN_ISAC_BW 10000 /* Minimum bandwidth in bits per sec */
+#define MAX_ISAC_BW 32000 /* Maxmum bandwidth in bits per sec */
+#define MIN_ISAC_MD 5     /* Minimum Max Delay in ?? */
+#define MAX_ISAC_MD 25    /* Maxmum Max Delay in ?? */
+#define DELAY_CORRECTION_MAX 717
+#define DELAY_CORRECTION_MED 819
+#define Thld_30_60 18000
+#define Thld_60_30 27000
+
+/* assumed header size; we don't know the exact number (header compression may
+ * be used) */
+#define HEADER_SIZE 35 /* bytes */
+#define INIT_FRAME_LEN 60
+#define INIT_BN_EST 20000
+#define INIT_BN_EST_Q7 2560000    /* 20 kbps in Q7 */
+#define INIT_REC_BN_EST_Q5 789312 /* INIT_BN_EST + INIT_HDR_RATE in Q5 */
+
+/* 8738 in Q18 is ~ 1/30 */
+/* #define INIT_HDR_RATE (((HEADER_SIZE * 8 * 1000) * 8738) >> NUM_BITS_TO_SHIFT
+ * (INIT_FRAME_LEN)) */
+#define INIT_HDR_RATE 4666
+/* number of packets in a row for a high rate burst */
+#define BURST_LEN 3
+/* ms, max time between two full bursts */
+#define BURST_INTERVAL 800
+/* number of packets in a row for initial high rate burst */
+#define INIT_BURST_LEN 5
+/* bits/s, rate for the first BURST_LEN packets */
+#define INIT_RATE 10240000 /* INIT_BN_EST in Q9 */
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN 240   /* (FRAMESAMPLES/2) 30 ms  */
+#define PITCH_MAX_LAG 140     /* 57 Hz  */
+#define PITCH_MIN_LAG 20      /* 400 Hz */
+#define PITCH_MIN_LAG_Q8 5120 /* 256 * PITCH_MIN_LAG */
+#define OFFSET_Q8 768         /* 256 * 3 */
+
+#define PITCH_MAX_GAIN_Q12 1843 /* 0.45 */
+#define PITCH_LAG_SPAN2 65      /* (PITCH_MAX_LAG/2-PITCH_MIN_LAG/2+5) */
+#define PITCH_CORR_LEN2 60      /* 15 ms  */
+#define PITCH_CORR_STEP2 60     /* (PITCH_FRAME_LEN/4) */
+#define PITCH_SUBFRAMES 4
+#define PITCH_SUBFRAME_LEN 60 /* (PITCH_FRAME_LEN/PITCH_SUBFRAMES) */
+
+/* For pitch filter */
+#define PITCH_BUFFSIZE \
+  190 /* (PITCH_MAX_LAG + 50) Extra 50 for fraction and LP filters */
+#define PITCH_INTBUFFSIZE 430 /* (PITCH_FRAME_LEN+PITCH_BUFFSIZE) */
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+/* PLC */
+#define DECAY_RATE \
+  10 /* Q15, 20% of decay every lost frame apllied linearly sample by sample*/
+#define PLC_WAS_USED 1
+#define PLC_NOT_USED 3
+#define RECOVERY_OVERLAP 80
+#define RESAMP_RES 256
+#define RESAMP_RES_BIT 8
+
+/* Define Error codes */
+/* 6000 General */
+#define ISAC_MEMORY_ALLOCATION_FAILED 6010
+#define ISAC_MODE_MISMATCH 6020
+#define ISAC_DISALLOWED_BOTTLENECK 6030
+#define ISAC_DISALLOWED_FRAME_LENGTH 6040
+/* 6200 Bandwidth estimator */
+#define ISAC_RANGE_ERROR_BW_ESTIMATOR 6240
+/* 6400 Encoder */
+#define ISAC_ENCODER_NOT_INITIATED 6410
+#define ISAC_DISALLOWED_CODING_MODE 6420
+#define ISAC_DISALLOWED_FRAME_MODE_ENCODER 6430
+#define ISAC_DISALLOWED_BITSTREAM_LENGTH 6440
+#define ISAC_PAYLOAD_LARGER_THAN_LIMIT 6450
+/* 6600 Decoder */
+#define ISAC_DECODER_NOT_INITIATED 6610
+#define ISAC_EMPTY_PACKET 6620
+#define ISAC_PACKET_TOO_SHORT 6625
+#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
+#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
+#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650
+#define ISAC_RANGE_ERROR_DECODE_PITCH_GAIN 6660
+#define ISAC_RANGE_ERROR_DECODE_PITCH_LAG 6670
+#define ISAC_RANGE_ERROR_DECODE_LPC 6680
+#define ISAC_RANGE_ERROR_DECODE_SPECTRUM 6690
+#define ISAC_LENGTH_MISMATCH 6730
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000..4ef9a33
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
@@ -0,0 +1,193 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.c
+ *
+ * This file contains tables with AR coefficients, Gain coefficients
+ * and cosine tables.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+
+/* cdf for quantized reflection coefficient 1 */
+const uint16_t WebRtcIsacfix_kRc1Cdf[12] = {
+  0,  2,  4,  129,  7707,  57485,  65495,  65527,  65529,  65531,
+  65533,  65535
+};
+
+/* cdf for quantized reflection coefficient 2 */
+const uint16_t WebRtcIsacfix_kRc2Cdf[12] = {
+  0,  2,  4,  7,  531,  25298,  64525,  65526,  65529,  65531,
+  65533,  65535
+};
+
+/* cdf for quantized reflection coefficient 3 */
+const uint16_t WebRtcIsacfix_kRc3Cdf[12] = {
+  0,  2,  4,  6,  620,  22898,  64843,  65527,  65529,  65531,
+  65533,  65535
+};
+
+/* cdf for quantized reflection coefficient 4 */
+const uint16_t WebRtcIsacfix_kRc4Cdf[12] = {
+  0,  2,  4,  6,  35,  10034,  60733,  65506,  65529,  65531,
+  65533,  65535
+};
+
+/* cdf for quantized reflection coefficient 5 */
+const uint16_t WebRtcIsacfix_kRc5Cdf[12] = {
+  0,  2,  4,  6,  36,  7567,  56727,  65385,  65529,  65531,
+  65533,  65535
+};
+
+/* cdf for quantized reflection coefficient 6 */
+const uint16_t WebRtcIsacfix_kRc6Cdf[12] = {
+  0,  2,  4,  6,  14,  6579,  57360,  65409,  65529,  65531,
+  65533,  65535
+};
+
+/* representation levels for quantized reflection coefficient 1 */
+const int16_t WebRtcIsacfix_kRc1Levels[11] = {
+  -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const int16_t WebRtcIsacfix_kRc2Levels[11] = {
+  -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const int16_t WebRtcIsacfix_kRc3Levels[11] = {
+  -32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const int16_t WebRtcIsacfix_kRc4Levels[11] = {
+  -32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const int16_t WebRtcIsacfix_kRc5Levels[11] = {
+  -32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const int16_t WebRtcIsacfix_kRc6Levels[11] = {
+  -32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const int16_t WebRtcIsacfix_kRcBound[12] = {
+  -32768, -31441, -27566, -21458, -13612, -4663,
+  4663, 13612, 21458, 27566, 31441, 32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const uint16_t WebRtcIsacfix_kRcInitInd[6] = {
+  5,  5,  5,  5,  5,  5
+};
+
+/* pointers to AR cdf tables */
+const uint16_t *WebRtcIsacfix_kRcCdfPtr[AR_ORDER] = {
+  WebRtcIsacfix_kRc1Cdf,
+  WebRtcIsacfix_kRc2Cdf,
+  WebRtcIsacfix_kRc3Cdf,
+  WebRtcIsacfix_kRc4Cdf,
+  WebRtcIsacfix_kRc5Cdf,
+  WebRtcIsacfix_kRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const int16_t *WebRtcIsacfix_kRcLevPtr[AR_ORDER] = {
+  WebRtcIsacfix_kRc1Levels,
+  WebRtcIsacfix_kRc2Levels,
+  WebRtcIsacfix_kRc3Levels,
+  WebRtcIsacfix_kRc4Levels,
+  WebRtcIsacfix_kRc5Levels,
+  WebRtcIsacfix_kRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+
+/* cdf for Gain coefficient */
+const uint16_t WebRtcIsacfix_kGainCdf[19] = {
+  0,  2,  4,  6,  8,  10,  12,  14,  16,  1172,
+  11119,  29411,  51699,  64445,  65527,  65529,  65531,  65533,  65535
+};
+
+/* representation levels for quantized squared Gain coefficient */
+const int32_t WebRtcIsacfix_kGain2Lev[18] = {
+  128, 128, 128, 128, 128, 215, 364, 709, 1268,
+  1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000
+};
+
+/* quantization boundary levels for squared Gain coefficient */
+const int32_t WebRtcIsacfix_kGain2Bound[19] = {
+  0, 21, 35, 59, 99, 166, 280, 475, 815, 1414,
+  2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF
+};
+
+/* pointers to Gain cdf table */
+const uint16_t *WebRtcIsacfix_kGainPtr[1] = {
+  WebRtcIsacfix_kGainCdf
+};
+
+/* gain initial index for gain quantizer and cdf table search */
+const uint16_t WebRtcIsacfix_kGainInitInd[1] = {
+  11
+};
+
+
+/************************* Cosine Tables ****************************/
+
+/* cosine table */
+const int16_t WebRtcIsacfix_kCos[6][60] = {
+  { 512,   512,   511,   510,   508,   507,   505,   502,   499,   496,
+        493,   489,   485,   480,   476,   470,   465,   459,   453,   447,
+ 440,   433,   426,   418,   410,   402,   394,   385,   376,   367,
+        357,   348,   338,   327,   317,   306,   295,   284,   273,   262,
+ 250,   238,   226,   214,   202,   190,   177,   165,   152,   139,
+        126,   113,   100,   87,   73,   60,   47,   33,   20,   7       },
+  { 512,   510,   508,   503,   498,   491,   483,   473,   462,   450,
+        437,   422,   406,   389,   371,   352,   333,   312,   290,   268,
+ 244,   220,   196,   171,   145,   120,   93,   67,   40,   13,
+        -13,   -40,   -67,   -93,   -120,   -145,   -171,   -196,   -220,   -244,
+ -268,   -290,   -312,   -333,   -352,   -371,   -389,   -406,   -422,   -437,
+        -450,   -462,   -473,   -483,   -491,   -498,   -503,   -508,   -510,   -512    },
+  { 512,   508,   502,   493,   480,   465,   447,   426,   402,   376,
+        348,   317,   284,   250,   214,   177,   139,   100,   60,   20,
+ -20,   -60,   -100,   -139,   -177,   -214,   -250,   -284,   -317,   -348,
+        -376,   -402,   -426,   -447,   -465,   -480,   -493,   -502,   -508,   -512,
+ -512,   -508,   -502,   -493,   -480,   -465,   -447,   -426,   -402,   -376,
+        -348,   -317,   -284,   -250,   -214,   -177,   -139,   -100,   -60,   -20     },
+  { 511,   506,   495,   478,   456,   429,   398,   362,   322,   279,
+        232,   183,   133,   80,   27,   -27,   -80,   -133,   -183,   -232,
+ -279,   -322,   -362,   -398,   -429,   -456,   -478,   -495,   -506,   -511,
+        -511,   -506,   -495,   -478,   -456,   -429,   -398,   -362,   -322,   -279,
+ -232,   -183,   -133,   -80,   -27,   27,   80,   133,   183,   232,
+        279,   322,   362,   398,   429,   456,   478,   495,   506,   511     },
+  { 511,   502,   485,   459,   426,   385,   338,   284,   226,   165,
+        100,   33,   -33,   -100,   -165,   -226,   -284,   -338,   -385,   -426,
+ -459,   -485,   -502,   -511,   -511,   -502,   -485,   -459,   -426,   -385,
+        -338,   -284,   -226,   -165,   -100,   -33,   33,   100,   165,   226,
+ 284,   338,   385,   426,   459,   485,   502,   511,   511,   502,
+        485,   459,   426,   385,   338,   284,   226,   165,   100,   33      },
+  { 510,   498,   473,   437,   389,   333,   268,   196,   120,   40,
+        -40,   -120,   -196,   -268,   -333,   -389,   -437,   -473,   -498,   -510,
+ -510,   -498,   -473,   -437,   -389,   -333,   -268,   -196,   -120,   -40,
+        40,   120,   196,   268,   333,   389,   437,   473,   498,   510,
+ 510,   498,   473,   437,   389,   333,   268,   196,   120,   40,
+        -40,   -120,   -196,   -268,   -333,   -389,   -437,   -473,   -498,   -510    }
+};
diff --git a/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000..2282a36
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
@@ -0,0 +1,97 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const uint16_t WebRtcIsacfix_kRc1Cdf[12];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const uint16_t WebRtcIsacfix_kRc2Cdf[12];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const uint16_t WebRtcIsacfix_kRc3Cdf[12];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const uint16_t WebRtcIsacfix_kRc4Cdf[12];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const uint16_t WebRtcIsacfix_kRc5Cdf[12];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const uint16_t WebRtcIsacfix_kRc6Cdf[12];
+
+/* representation levels for quantized reflection coefficient 1 */
+extern const int16_t WebRtcIsacfix_kRc1Levels[11];
+
+/* representation levels for quantized reflection coefficient 2 */
+extern const int16_t WebRtcIsacfix_kRc2Levels[11];
+
+/* representation levels for quantized reflection coefficient 3 */
+extern const int16_t WebRtcIsacfix_kRc3Levels[11];
+
+/* representation levels for quantized reflection coefficient 4 */
+extern const int16_t WebRtcIsacfix_kRc4Levels[11];
+
+/* representation levels for quantized reflection coefficient 5 */
+extern const int16_t WebRtcIsacfix_kRc5Levels[11];
+
+/* representation levels for quantized reflection coefficient 6 */
+extern const int16_t WebRtcIsacfix_kRc6Levels[11];
+
+/* quantization boundary levels for reflection coefficients */
+extern const int16_t WebRtcIsacfix_kRcBound[12];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search
+ */
+extern const uint16_t WebRtcIsacfix_kRcInitInd[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const uint16_t* WebRtcIsacfix_kRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const int16_t* WebRtcIsacfix_kRcLevPtr[AR_ORDER];
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const uint16_t WebRtcIsacfix_kGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const int32_t WebRtcIsacfix_kGain2Lev[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const int32_t WebRtcIsacfix_kGain2Bound[19];
+
+/* pointer to Gain cdf table */
+extern const uint16_t* WebRtcIsacfix_kGainPtr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const uint16_t WebRtcIsacfix_kGainInitInd[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const int16_t WebRtcIsacfix_kCos[6][60];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ \
+        */
diff --git a/modules/audio_coding/codecs/isac/fix/source/structs.h b/modules/audio_coding/codecs/isac/fix/source/structs.h
new file mode 100644
index 0000000..3044d51
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/structs.h
@@ -0,0 +1,345 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Bitstream struct for decoder */
+typedef struct Bitstreamstruct_dec {
+  uint16_t stream[INTERNAL_STREAM_SIZE_W16]; /* Array bytestream to decode */
+  uint32_t W_upper;                          /* Upper boundary of interval W */
+  uint32_t streamval;
+  uint16_t stream_index; /* Index to the current position in bytestream */
+  int16_t full;          /* 0 - first byte in memory filled, second empty*/
+  /* 1 - both bytes are empty (we just filled the previous memory */
+
+  size_t stream_size; /* The size of stream in bytes. */
+} Bitstr_dec;
+
+/* Bitstream struct for encoder */
+typedef struct Bitstreamstruct_enc {
+  uint16_t
+      stream[STREAM_MAXW16_60MS]; /* Vector for adding encoded bytestream */
+  uint32_t W_upper;               /* Upper boundary of interval W */
+  uint32_t streamval;
+  uint16_t stream_index; /* Index to the current position in bytestream */
+  int16_t full;          /* 0 - first byte in memory filled, second empty*/
+  /* 1 - both bytes are empty (we just filled the previous memory */
+
+} Bitstr_enc;
+
+typedef struct {
+  int16_t DataBufferLoQ0[WINLEN];
+  int16_t DataBufferHiQ0[WINLEN];
+
+  int32_t CorrBufLoQQ[ORDERLO + 1];
+  int32_t CorrBufHiQQ[ORDERHI + 1];
+
+  int16_t CorrBufLoQdom[ORDERLO + 1];
+  int16_t CorrBufHiQdom[ORDERHI + 1];
+
+  int32_t PreStateLoGQ15[ORDERLO + 1];
+  int32_t PreStateHiGQ15[ORDERHI + 1];
+
+  uint32_t OldEnergy;
+
+} MaskFiltstr_enc;
+
+typedef struct {
+  int16_t PostStateLoGQ0[ORDERLO + 1];
+  int16_t PostStateHiGQ0[ORDERHI + 1];
+
+  uint32_t OldEnergy;
+
+} MaskFiltstr_dec;
+
+typedef struct {
+  // state vectors for each of the two analysis filters
+
+  int32_t INSTAT1_fix[2 * (QORDER - 1)];
+  int32_t INSTAT2_fix[2 * (QORDER - 1)];
+  int16_t INLABUF1_fix[QLOOKAHEAD];
+  int16_t INLABUF2_fix[QLOOKAHEAD];
+
+  /* High pass filter */
+  int32_t HPstates_fix[HPORDER];
+
+} PreFiltBankstr;
+
+typedef struct {
+  // state vectors for each of the two analysis filters
+  int32_t STATE_0_LOWER_fix[2 * POSTQORDER];
+  int32_t STATE_0_UPPER_fix[2 * POSTQORDER];
+
+  /* High pass filter */
+
+  int32_t HPstates1_fix[HPORDER];
+  int32_t HPstates2_fix[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+  /* data buffer for pitch filter */
+  int16_t ubufQQ[PITCH_BUFFSIZE];
+
+  /* low pass state vector */
+  int16_t ystateQQ[PITCH_DAMPORDER];
+
+  /* old lag and gain */
+  int16_t oldlagQ7;
+  int16_t oldgainQ12;
+
+} PitchFiltstr;
+
+typedef struct {
+  // for inital estimator
+  int16_t dec_buffer16[PITCH_CORR_LEN2 + PITCH_CORR_STEP2 + PITCH_MAX_LAG / 2 -
+                       PITCH_FRAME_LEN / 2 + 2];
+  int32_t decimator_state32[2 * ALLPASSSECTIONS + 1];
+  int16_t inbuf[QLOOKAHEAD];
+
+  PitchFiltstr PFstr_wght;
+  PitchFiltstr PFstr;
+
+} PitchAnalysisStruct;
+
+typedef struct {
+  /* Parameters used in PLC to avoid re-computation       */
+
+  /* --- residual signals --- */
+  int16_t prevPitchInvIn[FRAMESAMPLES / 2];
+  int16_t prevPitchInvOut[PITCH_MAX_LAG + 10];  // [FRAMESAMPLES/2]; save 90
+  int32_t prevHP[PITCH_MAX_LAG + 10];           // [FRAMESAMPLES/2]; save 90
+
+  int16_t decayCoeffPriodic; /* how much to supress a sample */
+  int16_t decayCoeffNoise;
+  int16_t used; /* if PLC is used */
+
+  int16_t* lastPitchLP;  // [FRAMESAMPLES/2]; saved 240;
+
+  /* --- LPC side info --- */
+  int16_t lofilt_coefQ15[ORDERLO];
+  int16_t hifilt_coefQ15[ORDERHI];
+  int32_t gain_lo_hiQ17[2];
+
+  /* --- LTP side info --- */
+  int16_t AvgPitchGain_Q12;
+  int16_t lastPitchGain_Q12;
+  int16_t lastPitchLag_Q7;
+
+  /* --- Add-overlap in recovery packet --- */
+  int16_t overlapLP[RECOVERY_OVERLAP];  // [FRAMESAMPLES/2]; saved 160
+
+  int16_t pitchCycles;
+  int16_t A;
+  int16_t B;
+  size_t pitchIndex;
+  size_t stretchLag;
+  int16_t* prevPitchLP;  // [ FRAMESAMPLES/2 ]; saved 240
+  int16_t seed;
+
+  int16_t std;
+} PLCstr;
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+  int16_t prevFrameSizeMs; /* Previous frame size (in ms) */
+  uint16_t prevRtpNumber;  /* Previous RTP timestamp from received packet */
+  /* (in samples relative beginning)  */
+  uint32_t prevSendTime;    /* Send time for previous packet, from RTP header */
+  uint32_t prevArrivalTime; /* Arrival time for previous packet (in ms using
+                               timeGetTime()) */
+  uint16_t prevRtpRate; /* rate of previous packet, derived from RTP timestamps
+                           (in bits/s) */
+  uint32_t lastUpdate; /* Time since the last update of the Bottle Neck estimate
+                          (in samples) */
+  uint32_t lastReduction; /* Time sinse the last reduction (in samples) */
+  int32_t countUpdates;   /* How many times the estimate was update in the
+                             beginning */
+
+  /* The estimated bottle neck rate from there to here (in bits/s) */
+  uint32_t recBw;
+  uint32_t recBwInv;
+  uint32_t recBwAvg;
+  uint32_t recBwAvgQ;
+
+  uint32_t minBwInv;
+  uint32_t maxBwInv;
+
+  /* The estimated mean absolute jitter value, as seen on this side (in ms) */
+  int32_t recJitter;
+  int32_t recJitterShortTerm;
+  int32_t recJitterShortTermAbs;
+  int32_t recMaxDelay;
+  int32_t recMaxDelayAvgQ;
+
+  int16_t recHeaderRate; /* (assumed) bitrate for headers (bps) */
+
+  uint32_t sendBwAvg; /* The estimated bottle neck rate from here to there (in
+                         bits/s) */
+  int32_t sendMaxDelayAvg; /* The estimated mean absolute jitter value, as seen
+                              on the other siee (in ms)  */
+
+  int16_t countRecPkts; /* number of packets received since last update */
+  int16_t highSpeedRec; /* flag for marking that a high speed network has been
+                           detected downstream */
+
+  /* number of consecutive pkts sent during which the bwe estimate has
+     remained at a value greater than the downstream threshold for determining
+     highspeed network */
+  int16_t countHighSpeedRec;
+
+  /* flag indicating bwe should not adjust down immediately for very late pckts
+   */
+  int16_t inWaitPeriod;
+
+  /* variable holding the time of the start of a window of time when
+     bwe should not adjust down immediately for very late pckts */
+  uint32_t startWaitPeriod;
+
+  /* number of consecutive pkts sent during which the bwe estimate has
+     remained at a value greater than the upstream threshold for determining
+     highspeed network */
+  int16_t countHighSpeedSent;
+
+  /* flag indicated the desired number of packets over threshold rate have been
+     sent and bwe will assume the connection is over broadband network */
+  int16_t highSpeedSend;
+
+  IsacBandwidthInfo external_bw_info;
+} BwEstimatorstr;
+
+typedef struct {
+  /* boolean, flags if previous packet exceeded B.N. */
+  int16_t PrevExceed;
+  /* ms */
+  int16_t ExceedAgo;
+  /* packets left to send in current burst */
+  int16_t BurstCounter;
+  /* packets */
+  int16_t InitCounter;
+  /* ms remaining in buffer when next packet will be sent */
+  int16_t StillBuffered;
+
+} RateModel;
+
+/* The following strutc is used to store data from encoding, to make it
+   fast and easy to construct a new bitstream with a different Bandwidth
+   estimate. All values (except framelength and minBytes) is double size to
+   handle 60 ms of data.
+*/
+typedef struct {
+  /* Used to keep track of if it is first or second part of 60 msec packet */
+  int startIdx;
+
+  /* Frame length in samples */
+  int16_t framelength;
+
+  /* Pitch Gain */
+  int16_t pitchGain_index[2];
+
+  /* Pitch Lag */
+  int32_t meanGain[2];
+  int16_t pitchIndex[PITCH_SUBFRAMES * 2];
+
+  /* LPC */
+  int32_t LPCcoeffs_g[12 * 2]; /* KLT_ORDER_GAIN = 12 */
+  int16_t LPCindex_s[108 * 2]; /* KLT_ORDER_SHAPE = 108 */
+  int16_t LPCindex_g[12 * 2];  /* KLT_ORDER_GAIN = 12 */
+
+  /* Encode Spec */
+  int16_t fre[FRAMESAMPLES];
+  int16_t fim[FRAMESAMPLES];
+  int16_t AvgPitchGain[2];
+
+  /* Used in adaptive mode only */
+  int minBytes;
+
+} IsacSaveEncoderData;
+
+typedef struct {
+  Bitstr_enc bitstr_obj;
+  MaskFiltstr_enc maskfiltstr_obj;
+  PreFiltBankstr prefiltbankstr_obj;
+  PitchFiltstr pitchfiltstr_obj;
+  PitchAnalysisStruct pitchanalysisstr_obj;
+  RateModel rate_data_obj;
+
+  int16_t buffer_index;
+  int16_t current_framesamples;
+
+  int16_t data_buffer_fix[FRAMESAMPLES];  // the size was MAX_FRAMESAMPLES
+
+  int16_t frame_nb;
+  int16_t BottleNeck;
+  int16_t MaxDelay;
+  int16_t new_framelength;
+  int16_t s2nr;
+  uint16_t MaxBits;
+
+  int16_t bitstr_seed;
+
+  IsacSaveEncoderData* SaveEnc_ptr;
+  int16_t payloadLimitBytes30; /* Maximum allowed number of bits for a 30 msec
+                                  packet */
+  int16_t payloadLimitBytes60; /* Maximum allowed number of bits for a 30 msec
+                                  packet */
+  int16_t maxPayloadBytes; /* Maximum allowed number of bits for both 30 and 60
+                              msec packet */
+  int16_t maxRateInBytes; /* Maximum allowed rate in bytes per 30 msec packet */
+  int16_t enforceFrameSize; /* If set iSAC will never change packet size */
+
+} IsacFixEncoderInstance;
+
+typedef struct {
+  Bitstr_dec bitstr_obj;
+  MaskFiltstr_dec maskfiltstr_obj;
+  PostFiltBankstr postfiltbankstr_obj;
+  PitchFiltstr pitchfiltstr_obj;
+  PLCstr plcstr_obj; /* TS; for packet loss concealment */
+} IsacFixDecoderInstance;
+
+typedef struct {
+  IsacFixEncoderInstance ISACenc_obj;
+  IsacFixDecoderInstance ISACdec_obj;
+  BwEstimatorstr bwestimator_obj;
+  int16_t CodingMode; /* 0 = adaptive; 1 = instantaneous */
+  int16_t errorcode;
+  int16_t initflag; /* 0 = nothing initiated; 1 = encoder or decoder */
+  /* not initiated; 2 = all initiated */
+} ISACFIX_SubStruct;
+
+typedef struct {
+  int32_t lpcGains[12]; /* 6 lower-band & 6 upper-band we may need to double it
+                           for 60*/
+  /* */
+  uint32_t W_upper; /* Upper boundary of interval W */
+  uint32_t streamval;
+  uint16_t stream_index; /* Index to the current position in bytestream */
+  int16_t full;          /* 0 - first byte in memory filled, second empty*/
+  /* 1 - both bytes are empty (we just filled the previous memory */
+  uint16_t beforeLastWord;
+  uint16_t lastWord;
+} transcode_obj;
+
+// Bitstr_enc myBitStr;
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_ */
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform.c b/modules/audio_coding/codecs/isac/fix/source/transform.c
new file mode 100644
index 0000000..80b244b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/transform.c
@@ -0,0 +1,214 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * WebRtcIsacfix_kTransform.c
+ *
+ * Transform functions
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/third_party/fft/fft.h"
+
+/* Tables are defined in transform_tables.c file or ARM assembly files. */
+/* Cosine table 1 in Q14 */
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+/* Sine table 1 in Q14 */
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+/* Sine table 2 in Q14 */
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+void WebRtcIsacfix_Time2SpecC(int16_t *inre1Q9,
+                              int16_t *inre2Q9,
+                              int16_t *outreQ7,
+                              int16_t *outimQ7)
+{
+
+  int k;
+  int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
+  int16_t tmp1rQ14, tmp1iQ14;
+  int32_t xrQ16, xiQ16, yrQ16, yiQ16;
+  int32_t v1Q16, v2Q16;
+  int16_t factQ19, sh;
+
+  /* Multiply with complex exponentials and combine into one complex vector */
+  factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921
+  for (k = 0; k < FRAMESAMPLES/2; k++) {
+    tmp1rQ14 = WebRtcIsacfix_kCosTab1[k];
+    tmp1iQ14 = WebRtcIsacfix_kSinTab1[k];
+    xrQ16 = (tmp1rQ14 * inre1Q9[k] + tmp1iQ14 * inre2Q9[k]) >> 7;
+    xiQ16 = (tmp1rQ14 * inre2Q9[k] - tmp1iQ14 * inre1Q9[k]) >> 7;
+    // Q-domains below: (Q16*Q19>>16)>>3 = Q16
+    tmpreQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16) + 4) >> 3;
+    tmpimQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16) + 4) >> 3;
+  }
+
+
+  xrQ16  = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2);
+  yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2);
+  if (yrQ16>xrQ16) {
+    xrQ16 = yrQ16;
+  }
+
+  sh = WebRtcSpl_NormW32(xrQ16);
+  sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+  //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+  //"Fastest" vectors
+  if (sh>=0) {
+    for (k=0; k<FRAMESAMPLES/2; k++) {
+      inre1Q9[k] = (int16_t)(tmpreQ16[k] << sh);  // Q(16+sh)
+      inre2Q9[k] = (int16_t)(tmpimQ16[k] << sh);  // Q(16+sh)
+    }
+  } else {
+    int32_t round = 1 << (-sh - 1);
+    for (k=0; k<FRAMESAMPLES/2; k++) {
+      inre1Q9[k] = (int16_t)((tmpreQ16[k] + round) >> -sh);  // Q(16+sh)
+      inre2Q9[k] = (int16_t)((tmpimQ16[k] + round) >> -sh);  // Q(16+sh)
+    }
+  }
+
+  /* Get DFT */
+  WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call
+
+  //"Fastest" vectors
+  if (sh>=0) {
+    for (k=0; k<FRAMESAMPLES/2; k++) {
+      tmpreQ16[k] = inre1Q9[k] >> sh;  // Q(16+sh) -> Q16
+      tmpimQ16[k] = inre2Q9[k] >> sh;  // Q(16+sh) -> Q16
+    }
+  } else {
+    for (k=0; k<FRAMESAMPLES/2; k++) {
+      tmpreQ16[k] = inre1Q9[k] << -sh;  // Q(16+sh) -> Q16
+      tmpimQ16[k] = inre2Q9[k] << -sh;  // Q(16+sh) -> Q16
+    }
+  }
+
+
+  /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+  for (k = 0; k < FRAMESAMPLES/4; k++) {
+    xrQ16 = tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+    yiQ16 = -tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+    xiQ16 = tmpimQ16[k] - tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+    yrQ16 = tmpimQ16[k] + tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+    tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
+    tmp1iQ14 = WebRtcIsacfix_kSinTab2[k];
+    v1Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xiQ16);
+    v2Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xiQ16);
+    outreQ7[k] = (int16_t)(v1Q16 >> 9);
+    outimQ7[k] = (int16_t)(v2Q16 >> 9);
+    v1Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yiQ16);
+    v2Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yiQ16);
+    // CalcLrIntQ(v1Q16, 9);
+    outreQ7[FRAMESAMPLES / 2 - 1 - k] = (int16_t)(v1Q16 >> 9);
+    // CalcLrIntQ(v2Q16, 9);
+    outimQ7[FRAMESAMPLES / 2 - 1 - k] = (int16_t)(v2Q16 >> 9);
+
+  }
+}
+
+
+void WebRtcIsacfix_Spec2TimeC(int16_t *inreQ7, int16_t *inimQ7, int32_t *outre1Q16, int32_t *outre2Q16)
+{
+
+  int k;
+  int16_t tmp1rQ14, tmp1iQ14;
+  int32_t xrQ16, xiQ16, yrQ16, yiQ16;
+  int32_t tmpInRe, tmpInIm, tmpInRe2, tmpInIm2;
+  int16_t factQ11;
+  int16_t sh;
+
+  for (k = 0; k < FRAMESAMPLES/4; k++) {
+    /* Move zero in time to beginning of frames */
+    tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
+    tmp1iQ14 = WebRtcIsacfix_kSinTab2[k];
+
+    tmpInRe = inreQ7[k] * (1 << 9);  // Q7 -> Q16
+    tmpInIm = inimQ7[k] * (1 << 9);  // Q7 -> Q16
+    tmpInRe2 = inreQ7[FRAMESAMPLES / 2 - 1 - k] * (1 << 9);  // Q7 -> Q16
+    tmpInIm2 = inimQ7[FRAMESAMPLES / 2 - 1 - k] * (1 << 9);  // Q7 -> Q16
+
+    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm);
+    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe);
+    yrQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm2) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe2);
+    yiQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe2) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm2);
+
+    /* Combine into one vector,  z = x + j * y */
+    outre1Q16[k] = xrQ16 - yiQ16;
+    outre1Q16[FRAMESAMPLES/2 - 1 - k] = xrQ16 + yiQ16;
+    outre2Q16[k] = xiQ16 + yrQ16;
+    outre2Q16[FRAMESAMPLES/2 - 1 - k] = -xiQ16 + yrQ16;
+  }
+
+  /* Get IDFT */
+  tmpInRe  = WebRtcSpl_MaxAbsValueW32(outre1Q16, 240);
+  tmpInIm = WebRtcSpl_MaxAbsValueW32(outre2Q16, 240);
+  if (tmpInIm>tmpInRe) {
+    tmpInRe = tmpInIm;
+  }
+
+  sh = WebRtcSpl_NormW32(tmpInRe);
+  sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+  //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+  //"Fastest" vectors
+  if (sh>=0) {
+    for (k=0; k<240; k++) {
+      inreQ7[k] = (int16_t)(outre1Q16[k] << sh);  // Q(16+sh)
+      inimQ7[k] = (int16_t)(outre2Q16[k] << sh);  // Q(16+sh)
+    }
+  } else {
+    int32_t round = 1 << (-sh - 1);
+    for (k=0; k<240; k++) {
+      inreQ7[k] = (int16_t)((outre1Q16[k] + round) >> -sh);  // Q(16+sh)
+      inimQ7[k] = (int16_t)((outre2Q16[k] + round) >> -sh);  // Q(16+sh)
+    }
+  }
+
+  WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call
+
+  //"Fastest" vectors
+  if (sh>=0) {
+    for (k=0; k<240; k++) {
+      outre1Q16[k] = inreQ7[k] >> sh;  // Q(16+sh) -> Q16
+      outre2Q16[k] = inimQ7[k] >> sh;  // Q(16+sh) -> Q16
+    }
+  } else {
+    for (k=0; k<240; k++) {
+      outre1Q16[k] = inreQ7[k] * (1 << -sh);  // Q(16+sh) -> Q16
+      outre2Q16[k] = inimQ7[k] * (1 << -sh);  // Q(16+sh) -> Q16
+    }
+  }
+
+  /* Divide through by the normalizing constant: */
+  /* scale all values with 1/240, i.e. with 273 in Q16 */
+  /* 273/65536 ~= 0.0041656                            */
+  /*     1/240 ~= 0.0041666                            */
+  for (k=0; k<240; k++) {
+    outre1Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre1Q16[k]);
+    outre2Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]);
+  }
+
+  /* Demodulate and separate */
+  factQ11 = 31727; // sqrt(240) in Q11 is round(15.49193338482967*2048) = 31727
+  for (k = 0; k < FRAMESAMPLES/2; k++) {
+    tmp1rQ14 = WebRtcIsacfix_kCosTab1[k];
+    tmp1iQ14 = WebRtcIsacfix_kSinTab1[k];
+    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre1Q16[k]) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre2Q16[k]);
+    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre2Q16[k]) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre1Q16[k]);
+    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16);
+    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16);
+    outre2Q16[k] = xiQ16;
+    outre1Q16[k] = xrQ16;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform_mips.c b/modules/audio_coding/codecs/isac/fix/source/transform_mips.c
new file mode 100644
index 0000000..a87b3b5
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/transform_mips.c
@@ -0,0 +1,1294 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// The tables are defined in transform_tables.c file.
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+extern const int16_t WebRtcIsacfix_kCosTab2[FRAMESAMPLES/4];
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+// MIPS DSPr2 version of the WebRtcIsacfix_Time2Spec function
+// is not bit-exact with the C version.
+// The accuracy of the MIPS DSPr2 version is same or better.
+void WebRtcIsacfix_Time2SpecMIPS(int16_t* inre1Q9,
+                                 int16_t* inre2Q9,
+                                 int16_t* outreQ7,
+                                 int16_t* outimQ7) {
+  int k = FRAMESAMPLES / 2;
+  int32_t tmpreQ16[FRAMESAMPLES / 2], tmpimQ16[FRAMESAMPLES / 2];
+  int32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
+  int32_t inre1, inre2, tmpre, tmpim, factor, max, max1;
+  int16_t* cosptr;
+  int16_t* sinptr;
+
+  cosptr = (int16_t*)WebRtcIsacfix_kCosTab1;
+  sinptr = (int16_t*)WebRtcIsacfix_kSinTab1;
+
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[inre1],     %[inre1Q9],   0             \n\t"
+    "addiu          %[inre2],     %[inre2Q9],   0             \n\t"
+    "addiu          %[tmpre],     %[tmpreQ16],  0             \n\t"
+    "addiu          %[tmpim],     %[tmpimQ16],  0             \n\t"
+    "addiu          %[factor],    $zero,        16921         \n\t"
+    "mul            %[max],       $zero,        $zero         \n\t"
+    // Multiply with complex exponentials and combine into one complex vector.
+    // Also, calculate the maximal absolute value in the same loop.
+   "1:                                                        \n\t"
+#if defined(MIPS_DSP_R2_LE)
+    "lwl            %[r0],        0(%[inre1])                 \n\t"
+    "lwl            %[r2],        0(%[cosptr])                \n\t"
+    "lwl            %[r3],        0(%[sinptr])                \n\t"
+    "lwl            %[r1],        0(%[inre2])                 \n\t"
+    "lwr            %[r0],        0(%[inre1])                 \n\t"
+    "lwr            %[r2],        0(%[cosptr])                \n\t"
+    "lwr            %[r3],        0(%[sinptr])                \n\t"
+    "lwr            %[r1],        0(%[inre2])                 \n\t"
+    "muleq_s.w.phr  %[r4],        %[r2],        %[r0]         \n\t"
+    "muleq_s.w.phr  %[r5],        %[r3],        %[r0]         \n\t"
+    "muleq_s.w.phr  %[r6],        %[r3],        %[r1]         \n\t"
+    "muleq_s.w.phr  %[r7],        %[r2],        %[r1]         \n\t"
+    "muleq_s.w.phl  %[r8],        %[r2],        %[r0]         \n\t"
+    "muleq_s.w.phl  %[r0],        %[r3],        %[r0]         \n\t"
+    "muleq_s.w.phl  %[r3],        %[r3],        %[r1]         \n\t"
+    "muleq_s.w.phl  %[r1],        %[r2],        %[r1]         \n\t"
+    "addiu          %[k],         %[k],         -2            \n\t"
+    "addu           %[r4],        %[r4],        %[r6]         \n\t"
+    "subu           %[r5],        %[r7],        %[r5]         \n\t"
+    "sra            %[r4],        %[r4],        8             \n\t"
+    "sra            %[r5],        %[r5],        8             \n\t"
+    "mult           $ac0,         %[factor],    %[r4]         \n\t"
+    "mult           $ac1,         %[factor],    %[r5]         \n\t"
+    "addu           %[r3],        %[r8],        %[r3]         \n\t"
+    "subu           %[r0],        %[r1],        %[r0]         \n\t"
+    "sra            %[r3],        %[r3],        8             \n\t"
+    "sra            %[r0],        %[r0],        8             \n\t"
+    "mult           $ac2,         %[factor],    %[r3]         \n\t"
+    "mult           $ac3,         %[factor],    %[r0]         \n\t"
+    "extr_r.w       %[r4],        $ac0,         16            \n\t"
+    "extr_r.w       %[r5],        $ac1,         16            \n\t"
+    "addiu          %[inre1],     %[inre1],     4             \n\t"
+    "addiu          %[inre2],     %[inre2],     4             \n\t"
+    "extr_r.w       %[r6],        $ac2,         16            \n\t"
+    "extr_r.w       %[r7],        $ac3,         16            \n\t"
+    "addiu          %[cosptr],    %[cosptr],    4             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    4             \n\t"
+    "shra_r.w       %[r4],        %[r4],        3             \n\t"
+    "shra_r.w       %[r5],        %[r5],        3             \n\t"
+    "sw             %[r4],        0(%[tmpre])                 \n\t"
+    "absq_s.w       %[r4],        %[r4]                       \n\t"
+    "sw             %[r5],        0(%[tmpim])                 \n\t"
+    "absq_s.w       %[r5],        %[r5]                       \n\t"
+    "shra_r.w       %[r6],        %[r6],        3             \n\t"
+    "shra_r.w       %[r7],        %[r7],        3             \n\t"
+    "sw             %[r6],        4(%[tmpre])                 \n\t"
+    "absq_s.w       %[r6],        %[r6]                       \n\t"
+    "sw             %[r7],        4(%[tmpim])                 \n\t"
+    "absq_s.w       %[r7],        %[r7]                       \n\t"
+    "slt            %[r0],        %[r4],        %[r5]         \n\t"
+    "movn           %[r4],        %[r5],        %[r0]         \n\t"
+    "slt            %[r1],        %[r6],        %[r7]         \n\t"
+    "movn           %[r6],        %[r7],        %[r1]         \n\t"
+    "slt            %[r0],        %[max],       %[r4]         \n\t"
+    "movn           %[max],       %[r4],        %[r0]         \n\t"
+    "slt            %[r1],        %[max],       %[r6]         \n\t"
+    "movn           %[max],       %[r6],        %[r1]         \n\t"
+    "addiu          %[tmpre],     %[tmpre],     8             \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[tmpim],     %[tmpim],     8             \n\t"
+#else  // #if defined(MIPS_DSP_R2_LE)
+    "lh             %[r0],        0(%[inre1])                 \n\t"
+    "lh             %[r1],        0(%[inre2])                 \n\t"
+    "lh             %[r2],        0(%[cosptr])                \n\t"
+    "lh             %[r3],        0(%[sinptr])                \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "mul            %[r4],        %[r0],        %[r2]         \n\t"
+    "mul            %[r5],        %[r1],        %[r3]         \n\t"
+    "mul            %[r0],        %[r0],        %[r3]         \n\t"
+    "mul            %[r2],        %[r1],        %[r2]         \n\t"
+    "addiu          %[inre1],     %[inre1],     2             \n\t"
+    "addiu          %[inre2],     %[inre2],     2             \n\t"
+    "addiu          %[cosptr],    %[cosptr],    2             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    2             \n\t"
+    "addu           %[r1],        %[r4],        %[r5]         \n\t"
+    "sra            %[r1],        %[r1],        7             \n\t"
+    "sra            %[r3],        %[r1],        16            \n\t"
+    "andi           %[r1],        %[r1],        0xFFFF        \n\t"
+    "sra            %[r1],        %[r1],        1             \n\t"
+    "mul            %[r1],        %[factor],    %[r1]         \n\t"
+    "mul            %[r3],        %[factor],    %[r3]         \n\t"
+    "subu           %[r0],        %[r2],        %[r0]         \n\t"
+    "sra            %[r0],        %[r0],        7             \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "sra            %[r0],        %[r0],        1             \n\t"
+    "mul            %[r0],        %[factor],    %[r0]         \n\t"
+    "mul            %[r2],        %[factor],    %[r2]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r1],        %[r1],        15            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r1],        %[r1],        0x4000        \n\t"
+    "sra            %[r1],        %[r1],        15            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r1],        %[r3],        %[r1]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r1],        %[r1],        3             \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r1],        %[r1],        4             \n\t"
+    "sra            %[r1],        %[r1],        3             \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sw             %[r1],        0(%[tmpre])                 \n\t"
+    "addiu          %[tmpre],     %[tmpre],     4             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "absq_s.w       %[r1],        %[r1]                       \n\t"
+    "shra_r.w       %[r0],        %[r0],        15            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "negu           %[r4],        %[r1]                       \n\t"
+    "slt            %[r3],        %[r1],        $zero         \n\t"
+    "movn           %[r1],        %[r4],        %[r3]         \n\t"
+    "addiu          %[r0],        %[r0],        0x4000        \n\t"
+    "sra            %[r0],        %[r0],        15            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r2]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r0],        %[r0],        3             \n\t"
+    "sw             %[r0],        0(%[tmpim])                 \n\t"
+    "absq_s.w       %[r0],        %[r0]                       \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r0],        %[r0],        4             \n\t"
+    "sra            %[r0],        %[r0],        3             \n\t"
+    "sw             %[r0],        0(%[tmpim])                 \n\t"
+    "negu           %[r2],        %[r0]                       \n\t"
+    "slt            %[r3],        %[r0],        $zero         \n\t"
+    "movn           %[r0],        %[r2],        %[r3]         \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "slt            %[r2],        %[max],       %[r1]         \n\t"
+    "movn           %[max],       %[r1],        %[r2]         \n\t"
+    "slt            %[r2],        %[max],       %[r0]         \n\t"
+    "movn           %[max],       %[r0],        %[r2]         \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[tmpim],     %[tmpim],     4             \n\t"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+    // Calculate WebRtcSpl_NormW32(max).
+    // If max gets value >=0, we should shift max steps to the left, and the
+    // domain will be Q(16+shift). If max gets value <0, we should shift -max
+    // steps to the right, and the domain will be Q(16+max)
+    "clz            %[max],       %[max]                      \n\t"
+    "addiu          %[max],       %[max],       -25           \n\t"
+    ".set           pop                                       \n\t"
+    : [k] "+r" (k), [inre1] "=&r" (inre1), [inre2] "=&r" (inre2),
+      [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+      [r3] "=&r" (r3), [r4] "=&r" (r4), [tmpre] "=&r" (tmpre),
+      [tmpim] "=&r" (tmpim), [max] "=&r" (max), [factor] "=&r" (factor),
+#if defined(MIPS_DSP_R2_LE)
+      [r6] "=&r" (r6), [r7] "=&r" (r7), [r8] "=&r" (r8),
+#endif  // #if defined(MIPS_DSP_R2_LE)
+      [r5] "=&r" (r5)
+    : [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9),
+      [tmpreQ16] "r" (tmpreQ16), [tmpimQ16] "r" (tmpimQ16),
+      [cosptr] "r" (cosptr), [sinptr] "r" (sinptr)
+    : "hi", "lo", "memory"
+#if defined(MIPS_DSP_R2_LE)
+    , "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+  );
+
+  // "Fastest" vectors
+  k = FRAMESAMPLES / 4;
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[tmpre],     %[tmpreQ16],  0             \n\t"
+    "addiu          %[tmpim],     %[tmpimQ16],  0             \n\t"
+    "addiu          %[inre1],     %[inre1Q9],   0             \n\t"
+    "addiu          %[inre2],     %[inre2Q9],   0             \n\t"
+    "blez           %[max],       2f                          \n\t"
+    " subu          %[max1],      $zero,        %[max]        \n\t"
+   "1:                                                        \n\t"
+    "lw             %[r0],        0(%[tmpre])                 \n\t"
+    "lw             %[r1],        0(%[tmpim])                 \n\t"
+    "lw             %[r2],        4(%[tmpre])                 \n\t"
+    "lw             %[r3],        4(%[tmpim])                 \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "sllv           %[r0],        %[r0],        %[max]        \n\t"
+    "sllv           %[r1],        %[r1],        %[max]        \n\t"
+    "sllv           %[r2],        %[r2],        %[max]        \n\t"
+    "sllv           %[r3],        %[r3],        %[max]        \n\t"
+    "addiu          %[tmpre],     %[tmpre],     8             \n\t"
+    "addiu          %[tmpim],     %[tmpim],     8             \n\t"
+    "sh             %[r0],        0(%[inre1])                 \n\t"
+    "sh             %[r1],        0(%[inre2])                 \n\t"
+    "sh             %[r2],        2(%[inre1])                 \n\t"
+    "sh             %[r3],        2(%[inre2])                 \n\t"
+    "addiu          %[inre1],     %[inre1],     4             \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[inre2],     %[inre2],     4             \n\t"
+    "b              4f                                        \n\t"
+    " nop                                                     \n\t"
+   "2:                                                        \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+    "addiu          %[r4],        %[max1],      -1            \n\t"
+    "addiu          %[r5],        $zero,        1             \n\t"
+    "sllv           %[r4],        %[r5],        %[r4]         \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+   "3:                                                        \n\t"
+    "lw             %[r0],        0(%[tmpre])                 \n\t"
+    "lw             %[r1],        0(%[tmpim])                 \n\t"
+    "lw             %[r2],        4(%[tmpre])                 \n\t"
+    "lw             %[r3],        4(%[tmpim])                 \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shrav_r.w      %[r0],        %[r0],        %[max1]       \n\t"
+    "shrav_r.w      %[r1],        %[r1],        %[max1]       \n\t"
+    "shrav_r.w      %[r2],        %[r2],        %[max1]       \n\t"
+    "shrav_r.w      %[r3],        %[r3],        %[max1]       \n\t"
+#else // #if !defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r4]         \n\t"
+    "addu           %[r1],        %[r1],        %[r4]         \n\t"
+    "addu           %[r2],        %[r2],        %[r4]         \n\t"
+    "addu           %[r3],        %[r3],        %[r4]         \n\t"
+    "srav           %[r0],        %[r0],        %[max1]       \n\t"
+    "srav           %[r1],        %[r1],        %[max1]       \n\t"
+    "srav           %[r2],        %[r2],        %[max1]       \n\t"
+    "srav           %[r3],        %[r3],        %[max1]       \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+    "addiu          %[tmpre],     %[tmpre],     8             \n\t"
+    "addiu          %[tmpim],     %[tmpim],     8             \n\t"
+    "sh             %[r0],        0(%[inre1])                 \n\t"
+    "sh             %[r1],        0(%[inre2])                 \n\t"
+    "sh             %[r2],        2(%[inre1])                 \n\t"
+    "sh             %[r3],        2(%[inre2])                 \n\t"
+    "addiu          %[inre1],     %[inre1],     4             \n\t"
+    "bgtz           %[k],         3b                          \n\t"
+    " addiu         %[inre2],     %[inre2],     4             \n\t"
+   "4:                                                        \n\t"
+    ".set           pop                                       \n\t"
+    : [tmpre] "=&r" (tmpre), [tmpim] "=&r" (tmpim), [inre1] "=&r" (inre1),
+      [inre2] "=&r" (inre2), [k] "+r" (k), [max1] "=&r" (max1),
+#if !defined(MIPS_DSP_R1_LE)
+      [r4] "=&r" (r4), [r5] "=&r" (r5),
+#endif // #if !defined(MIPS_DSP_R1_LE)
+      [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3)
+    : [tmpreQ16] "r" (tmpreQ16), [tmpimQ16] "r" (tmpimQ16),
+      [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9), [max] "r" (max)
+    : "memory"
+  );
+
+  // Get DFT
+  WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call
+
+  // "Fastest" vectors and
+  // Use symmetry to separate into two complex vectors
+  // and center frames in time around zero
+  // merged into one loop
+  cosptr = (int16_t*)WebRtcIsacfix_kCosTab2;
+  sinptr = (int16_t*)WebRtcIsacfix_kSinTab2;
+  k = FRAMESAMPLES / 4;
+  factor = FRAMESAMPLES - 2;  // offset for FRAMESAMPLES / 2 - 1 array member
+
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[inre1],     %[inre1Q9],   0             \n\t"
+    "addiu          %[inre2],     %[inre2Q9],   0             \n\t"
+    "addiu          %[tmpre],     %[outreQ7],   0             \n\t"
+    "addiu          %[tmpim],     %[outimQ7],   0             \n\t"
+    "bltz           %[max],       2f                          \n\t"
+    " subu          %[max1],      $zero,        %[max]        \n\t"
+   "1:                                                        \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+    "addu           %[r4],        %[inre1],     %[offset]     \n\t"
+    "addu           %[r5],        %[inre2],     %[offset]     \n\t"
+#endif  // #if !defined(MIPS_DSP_R1_LE)
+    "lh             %[r0],        0(%[inre1])                 \n\t"
+    "lh             %[r1],        0(%[inre2])                 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "lhx            %[r2],        %[offset](%[inre1])         \n\t"
+    "lhx            %[r3],        %[offset](%[inre2])         \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "lh             %[r2],        0(%[r4])                    \n\t"
+    "lh             %[r3],        0(%[r5])                    \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "srav           %[r0],        %[r0],        %[max]        \n\t"
+    "srav           %[r1],        %[r1],        %[max]        \n\t"
+    "srav           %[r2],        %[r2],        %[max]        \n\t"
+    "srav           %[r3],        %[r3],        %[max]        \n\t"
+    "addu           %[r4],        %[r0],        %[r2]         \n\t"
+    "subu           %[r0],        %[r2],        %[r0]         \n\t"
+    "subu           %[r2],        %[r1],        %[r3]         \n\t"
+    "addu           %[r1],        %[r1],        %[r3]         \n\t"
+    "lh             %[r3],        0(%[cosptr])                \n\t"
+    "lh             %[r5],        0(%[sinptr])                \n\t"
+    "andi           %[r6],        %[r4],        0xFFFF        \n\t"
+    "sra            %[r4],        %[r4],        16            \n\t"
+    "mul            %[r7],        %[r3],        %[r6]         \n\t"
+    "mul            %[r8],        %[r3],        %[r4]         \n\t"
+    "mul            %[r6],        %[r5],        %[r6]         \n\t"
+    "mul            %[r4],        %[r5],        %[r4]         \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "addiu          %[inre1],     %[inre1],     2             \n\t"
+    "addiu          %[inre2],     %[inre2],     2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r8],        %[r8],        2             \n\t"
+    "addu           %[r8],        %[r8],        %[r7]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r4],        %[r4],        2             \n\t"
+    "addu           %[r4],        %[r4],        %[r6]         \n\t"
+    "andi           %[r6],        %[r2],        0xFFFF        \n\t"
+    "sra            %[r2],        %[r2],        16            \n\t"
+    "mul            %[r7],        %[r5],        %[r6]         \n\t"
+    "mul            %[r9],        %[r5],        %[r2]         \n\t"
+    "mul            %[r6],        %[r3],        %[r6]         \n\t"
+    "mul            %[r2],        %[r3],        %[r2]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    2             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "addu           %[r9],        %[r7],        %[r9]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r2],        %[r2],        2             \n\t"
+    "addu           %[r2],        %[r6],        %[r2]         \n\t"
+    "subu           %[r8],        %[r8],        %[r9]         \n\t"
+    "sra            %[r8],        %[r8],        9             \n\t"
+    "addu           %[r2],        %[r4],        %[r2]         \n\t"
+    "sra            %[r2],        %[r2],        9             \n\t"
+    "sh             %[r8],        0(%[tmpre])                 \n\t"
+    "sh             %[r2],        0(%[tmpim])                 \n\t"
+
+    "andi           %[r4],        %[r1],        0xFFFF        \n\t"
+    "sra            %[r1],        %[r1],        16            \n\t"
+    "andi           %[r6],        %[r0],        0xFFFF        \n\t"
+    "sra            %[r0],        %[r0],        16            \n\t"
+    "mul            %[r7],        %[r5],        %[r4]         \n\t"
+    "mul            %[r9],        %[r5],        %[r1]         \n\t"
+    "mul            %[r4],        %[r3],        %[r4]         \n\t"
+    "mul            %[r1],        %[r3],        %[r1]         \n\t"
+    "mul            %[r8],        %[r3],        %[r0]         \n\t"
+    "mul            %[r3],        %[r3],        %[r6]         \n\t"
+    "mul            %[r6],        %[r5],        %[r6]         \n\t"
+    "mul            %[r0],        %[r5],        %[r0]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "addu           %[r9],        %[r9],        %[r7]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r4],        %[r4],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r4],        %[r4],        0x2000        \n\t"
+    "sra            %[r4],        %[r4],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r1],        %[r1],        2             \n\t"
+    "addu           %[r1],        %[r1],        %[r4]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r3],        %[r3],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r3],        %[r3],        0x2000        \n\t"
+    "sra            %[r3],        %[r3],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r8],        %[r8],        2             \n\t"
+    "addu           %[r8],        %[r8],        %[r3]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r0],        %[r0],        2             \n\t"
+    "addu           %[r0],        %[r0],        %[r6]         \n\t"
+    "addu           %[r3],        %[tmpre],     %[offset]     \n\t"
+    "addu           %[r2],        %[tmpim],     %[offset]     \n\t"
+    "addu           %[r9],        %[r9],        %[r8]         \n\t"
+    "negu           %[r9],        %[r9]                       \n\t"
+    "sra            %[r9],        %[r9],        9             \n\t"
+    "subu           %[r0],        %[r0],        %[r1]         \n\t"
+    "addiu          %[offset],    %[offset],    -4            \n\t"
+    "sh             %[r9],        0(%[r3])                    \n\t"
+    "sh             %[r0],        0(%[r2])                    \n\t"
+    "addiu          %[tmpre],     %[tmpre],     2             \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[tmpim],     %[tmpim],     2             \n\t"
+    "b              3f                                        \n\t"
+    " nop                                                     \n\t"
+   "2:                                                        \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+    "addu           %[r4],        %[inre1],     %[offset]     \n\t"
+    "addu           %[r5],        %[inre2],     %[offset]     \n\t"
+#endif  // #if !defined(MIPS_DSP_R1_LE)
+    "lh             %[r0],        0(%[inre1])                 \n\t"
+    "lh             %[r1],        0(%[inre2])                 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "lhx            %[r2],        %[offset](%[inre1])         \n\t"
+    "lhx            %[r3],        %[offset](%[inre2])         \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "lh             %[r2],        0(%[r4])                    \n\t"
+    "lh             %[r3],        0(%[r5])                    \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sllv           %[r0],        %[r0],        %[max1]       \n\t"
+    "sllv           %[r1],        %[r1],        %[max1]       \n\t"
+    "sllv           %[r2],        %[r2],        %[max1]       \n\t"
+    "sllv           %[r3],        %[r3],        %[max1]       \n\t"
+    "addu           %[r4],        %[r0],        %[r2]         \n\t"
+    "subu           %[r0],        %[r2],        %[r0]         \n\t"
+    "subu           %[r2],        %[r1],        %[r3]         \n\t"
+    "addu           %[r1],        %[r1],        %[r3]         \n\t"
+    "lh             %[r3],        0(%[cosptr])                \n\t"
+    "lh             %[r5],        0(%[sinptr])                \n\t"
+    "andi           %[r6],        %[r4],        0xFFFF        \n\t"
+    "sra            %[r4],        %[r4],        16            \n\t"
+    "mul            %[r7],        %[r3],        %[r6]         \n\t"
+    "mul            %[r8],        %[r3],        %[r4]         \n\t"
+    "mul            %[r6],        %[r5],        %[r6]         \n\t"
+    "mul            %[r4],        %[r5],        %[r4]         \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "addiu          %[inre1],     %[inre1],     2             \n\t"
+    "addiu          %[inre2],     %[inre2],     2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r8],        %[r8],        2             \n\t"
+    "addu           %[r8],        %[r8],        %[r7]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r4],        %[r4],        2             \n\t"
+    "addu           %[r4],        %[r4],        %[r6]         \n\t"
+    "andi           %[r6],        %[r2],        0xFFFF        \n\t"
+    "sra            %[r2],        %[r2],        16            \n\t"
+    "mul            %[r7],        %[r5],        %[r6]         \n\t"
+    "mul            %[r9],        %[r5],        %[r2]         \n\t"
+    "mul            %[r6],        %[r3],        %[r6]         \n\t"
+    "mul            %[r2],        %[r3],        %[r2]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    2             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "addu           %[r9],        %[r7],        %[r9]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r2],        %[r2],        2             \n\t"
+    "addu           %[r2],        %[r6],        %[r2]         \n\t"
+    "subu           %[r8],        %[r8],        %[r9]         \n\t"
+    "sra            %[r8],        %[r8],        9             \n\t"
+    "addu           %[r2],        %[r4],        %[r2]         \n\t"
+    "sra            %[r2],        %[r2],        9             \n\t"
+    "sh             %[r8],        0(%[tmpre])                 \n\t"
+    "sh             %[r2],        0(%[tmpim])                 \n\t"
+    "andi           %[r4],        %[r1],        0xFFFF        \n\t"
+    "sra            %[r1],        %[r1],        16            \n\t"
+    "andi           %[r6],        %[r0],        0xFFFF        \n\t"
+    "sra            %[r0],        %[r0],        16            \n\t"
+    "mul            %[r7],        %[r5],        %[r4]         \n\t"
+    "mul            %[r9],        %[r5],        %[r1]         \n\t"
+    "mul            %[r4],        %[r3],        %[r4]         \n\t"
+    "mul            %[r1],        %[r3],        %[r1]         \n\t"
+    "mul            %[r8],        %[r3],        %[r0]         \n\t"
+    "mul            %[r3],        %[r3],        %[r6]         \n\t"
+    "mul            %[r6],        %[r5],        %[r6]         \n\t"
+    "mul            %[r0],        %[r5],        %[r0]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r7],        %[r7],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r7],        %[r7],        0x2000        \n\t"
+    "sra            %[r7],        %[r7],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "addu           %[r9],        %[r9],        %[r7]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r4],        %[r4],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r4],        %[r4],        0x2000        \n\t"
+    "sra            %[r4],        %[r4],        14            \n\t"
+#endif
+    "sll            %[r1],        %[r1],        2             \n\t"
+    "addu           %[r1],        %[r1],        %[r4]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r3],        %[r3],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r3],        %[r3],        0x2000        \n\t"
+    "sra            %[r3],        %[r3],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r8],        %[r8],        2             \n\t"
+    "addu           %[r8],        %[r8],        %[r3]         \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r6],        %[r6],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r6],        %[r6],        0x2000        \n\t"
+    "sra            %[r6],        %[r6],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "sll            %[r0],        %[r0],        2             \n\t"
+    "addu           %[r0],        %[r0],        %[r6]         \n\t"
+    "addu           %[r3],        %[tmpre],     %[offset]     \n\t"
+    "addu           %[r2],        %[tmpim],     %[offset]     \n\t"
+    "addu           %[r9],        %[r9],        %[r8]         \n\t"
+    "negu           %[r9],        %[r9]                       \n\t"
+    "sra            %[r9],        %[r9],        9             \n\t"
+    "subu           %[r0],        %[r0],        %[r1]         \n\t"
+    "sra            %[r0],        %[r0],        9             \n\t"
+    "addiu          %[offset],    %[offset],    -4            \n\t"
+    "sh             %[r9],        0(%[r3])                    \n\t"
+    "sh             %[r0],        0(%[r2])                    \n\t"
+    "addiu          %[tmpre],     %[tmpre],     2             \n\t"
+    "bgtz           %[k],         2b                          \n\t"
+    " addiu         %[tmpim],     %[tmpim],     2             \n\t"
+   "3:                                                        \n\t"
+    ".set           pop                                       \n\t"
+    : [inre1] "=&r" (inre1), [inre2] "=&r" (inre2), [tmpre] "=&r" (tmpre),
+      [tmpim] "=&r" (tmpim), [offset] "+r" (factor), [k] "+r" (k),
+      [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+      [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+      [r8] "=&r" (r8), [r9] "=&r" (r9), [max1] "=&r" (max1)
+    : [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9),
+      [outreQ7] "r" (outreQ7), [outimQ7] "r" (outimQ7),
+      [max] "r" (max), [cosptr] "r" (cosptr), [sinptr] "r" (sinptr)
+    : "hi", "lo", "memory"
+  );
+}
+
+void WebRtcIsacfix_Spec2TimeMIPS(int16_t *inreQ7,
+                                 int16_t *inimQ7,
+                                 int32_t *outre1Q16,
+                                 int32_t *outre2Q16) {
+  int k = FRAMESAMPLES / 4;
+  int16_t* inre;
+  int16_t* inim;
+  int32_t* outre1;
+  int32_t* outre2;
+  int16_t* cosptr = (int16_t*)WebRtcIsacfix_kCosTab2;
+  int16_t* sinptr = (int16_t*)WebRtcIsacfix_kSinTab2;
+  int32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, max, max1;
+#if defined(MIPS_DSP_R1_LE)
+  int32_t offset = FRAMESAMPLES - 4;
+#else  // #if defined(MIPS_DSP_R1_LE)
+  int32_t offset = FRAMESAMPLES - 2;
+#endif  // #if defined(MIPS_DSP_R1_LE)
+
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[inre],      %[inreQ7],    0             \n\t"
+    "addiu          %[inim] ,     %[inimQ7],    0             \n\t"
+    "addiu          %[outre1],    %[outre1Q16], 0             \n\t"
+    "addiu          %[outre2],    %[outre2Q16], 0             \n\t"
+    "mul            %[max],       $zero,        $zero         \n\t"
+   "1:                                                        \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    // Process two samples in one iteration avoiding left shift before
+    // multiplication. MaxAbsValueW32 function inlined into the loop.
+    "addu           %[r8],        %[inre],      %[offset]     \n\t"
+    "addu           %[r9],        %[inim],      %[offset]     \n\t"
+    "lwl            %[r4],        0(%[r8])                    \n\t"
+    "lwl            %[r5],        0(%[r9])                    \n\t"
+    "lwl            %[r0],        0(%[inre])                  \n\t"
+    "lwl            %[r1],        0(%[inim])                  \n\t"
+    "lwl            %[r2],        0(%[cosptr])                \n\t"
+    "lwl            %[r3],        0(%[sinptr])                \n\t"
+    "lwr            %[r4],        0(%[r8])                    \n\t"
+    "lwr            %[r5],        0(%[r9])                    \n\t"
+    "lwr            %[r0],        0(%[inre])                  \n\t"
+    "lwr            %[r1],        0(%[inim])                  \n\t"
+    "lwr            %[r2],        0(%[cosptr])                \n\t"
+    "lwr            %[r3],        0(%[sinptr])                \n\t"
+    "packrl.ph      %[r4],        %[r4],        %[r4]         \n\t"
+    "packrl.ph      %[r5],        %[r5],        %[r5]         \n\t"
+    "muleq_s.w.phr  %[r6],        %[r0],        %[r2]         \n\t"
+    "muleq_s.w.phr  %[r7],        %[r1],        %[r3]         \n\t"
+    "muleq_s.w.phr  %[r8],        %[r4],        %[r2]         \n\t"
+    "muleq_s.w.phr  %[r9],        %[r5],        %[r3]         \n\t"
+    "addiu          %[k],         %[k],         -2            \n\t"
+    "addiu          %[cosptr],    %[cosptr],    4             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    4             \n\t"
+    "addiu          %[inre],      %[inre],      4             \n\t"
+    "addiu          %[inim],      %[inim],      4             \n\t"
+    "shra_r.w       %[r6],        %[r6],        6             \n\t"
+    "shra_r.w       %[r7],        %[r7],        6             \n\t"
+    "shra_r.w       %[r8],        %[r8],        6             \n\t"
+    "shra_r.w       %[r9],        %[r9],        6             \n\t"
+    "addu           %[r6],        %[r6],        %[r7]         \n\t"
+    "subu           %[r9],        %[r9],        %[r8]         \n\t"
+    "subu           %[r7],        %[r6],        %[r9]         \n\t"
+    "addu           %[r6],        %[r6],        %[r9]         \n\t"
+    "sw             %[r7],        0(%[outre1])                \n\t"
+    "absq_s.w       %[r7],        %[r7]                       \n\t"
+    "slt            %[r8],        %[max],       %[r7]         \n\t"
+    "movn           %[max],       %[r7],        %[r8]         \n\t"
+    "sll            %[r7],        %[offset],    1             \n\t"
+    "addu           %[r7],        %[outre1],    %[r7]         \n\t"
+    "sw             %[r6],        4(%[r7])                    \n\t"
+    "absq_s.w       %[r6],        %[r6]                       \n\t"
+    "slt            %[r8],        %[max],       %[r6]         \n\t"
+    "movn           %[max],       %[r6],        %[r8]         \n\t"
+    "muleq_s.w.phl  %[r6],        %[r0],        %[r2]         \n\t"
+    "muleq_s.w.phl  %[r7],        %[r1],        %[r3]         \n\t"
+    "muleq_s.w.phl  %[r8],        %[r4],        %[r2]         \n\t"
+    "muleq_s.w.phl  %[r9],        %[r5],        %[r3]         \n\t"
+    "shra_r.w       %[r6],        %[r6],        6             \n\t"
+    "shra_r.w       %[r7],        %[r7],        6             \n\t"
+    "shra_r.w       %[r8],        %[r8],        6             \n\t"
+    "shra_r.w       %[r9],        %[r9],        6             \n\t"
+    "addu           %[r6],        %[r6],        %[r7]         \n\t"
+    "subu           %[r9],        %[r9],        %[r8]         \n\t"
+    "subu           %[r7],        %[r6],        %[r9]         \n\t"
+    "addu           %[r6],        %[r6],        %[r9]         \n\t"
+    "sw             %[r7],        4(%[outre1])                \n\t"
+    "absq_s.w       %[r7],        %[r7]                       \n\t"
+    "slt            %[r8],        %[max],       %[r7]         \n\t"
+    "movn           %[max],       %[r7],        %[r8]         \n\t"
+    "sll            %[r7],        %[offset],    1             \n\t"
+    "addu           %[r7],        %[outre1],    %[r7]         \n\t"
+    "sw             %[r6],        0(%[r7])                    \n\t"
+    "absq_s.w       %[r6],        %[r6]                       \n\t"
+    "slt            %[r8],        %[max],       %[r6]         \n\t"
+    "movn           %[max],       %[r6],        %[r8]         \n\t"
+    "muleq_s.w.phr  %[r6],        %[r1],        %[r2]         \n\t"
+    "muleq_s.w.phr  %[r7],        %[r0],        %[r3]         \n\t"
+    "muleq_s.w.phr  %[r8],        %[r5],        %[r2]         \n\t"
+    "muleq_s.w.phr  %[r9],        %[r4],        %[r3]         \n\t"
+    "addiu          %[outre1],    %[outre1],    8             \n\t"
+    "shra_r.w       %[r6],        %[r6],        6             \n\t"
+    "shra_r.w       %[r7],        %[r7],        6             \n\t"
+    "shra_r.w       %[r8],        %[r8],        6             \n\t"
+    "shra_r.w       %[r9],        %[r9],        6             \n\t"
+    "subu           %[r6],        %[r6],        %[r7]         \n\t"
+    "addu           %[r9],        %[r9],        %[r8]         \n\t"
+    "subu           %[r7],        %[r6],        %[r9]         \n\t"
+    "addu           %[r6],        %[r9],        %[r6]         \n\t"
+    "negu           %[r6],        %[r6]                       \n\t"
+    "sw             %[r7],        0(%[outre2])                \n\t"
+    "absq_s.w       %[r7],        %[r7]                       \n\t"
+    "slt            %[r8],        %[max],       %[r7]         \n\t"
+    "movn           %[max],       %[r7],        %[r8]         \n\t"
+    "sll            %[r7],        %[offset],    1             \n\t"
+    "addu           %[r7],        %[outre2],    %[r7]         \n\t"
+    "sw             %[r6],        4(%[r7])                    \n\t"
+    "absq_s.w       %[r6],        %[r6]                       \n\t"
+    "slt            %[r8],        %[max],       %[r6]         \n\t"
+    "movn           %[max],       %[r6],        %[r8]         \n\t"
+    "muleq_s.w.phl  %[r6],       %[r1],         %[r2]         \n\t"
+    "muleq_s.w.phl  %[r7],       %[r0],         %[r3]         \n\t"
+    "muleq_s.w.phl  %[r8],       %[r5],         %[r2]         \n\t"
+    "muleq_s.w.phl  %[r9],       %[r4],         %[r3]         \n\t"
+    "addiu          %[offset],   %[offset],     -8            \n\t"
+    "shra_r.w       %[r6],       %[r6],         6             \n\t"
+    "shra_r.w       %[r7],       %[r7],         6             \n\t"
+    "shra_r.w       %[r8],       %[r8],         6             \n\t"
+    "shra_r.w       %[r9],       %[r9],         6             \n\t"
+    "subu           %[r6],       %[r6],         %[r7]         \n\t"
+    "addu           %[r9],       %[r9],         %[r8]         \n\t"
+    "subu           %[r7],       %[r6],         %[r9]         \n\t"
+    "addu           %[r6],       %[r9],         %[r6]         \n\t"
+    "negu           %[r6],       %[r6]                        \n\t"
+    "sw             %[r7],       4(%[outre2])                 \n\t"
+    "absq_s.w       %[r7],       %[r7]                        \n\t"
+    "slt            %[r8],       %[max],        %[r7]         \n\t"
+    "movn           %[max],      %[r7],         %[r8]         \n\t"
+    "sll            %[r7],       %[offset],     1             \n\t"
+    "addu           %[r7],       %[outre2],     %[r7]         \n\t"
+    "sw             %[r6],       0(%[r7])                     \n\t"
+    "absq_s.w       %[r6],       %[r6]                        \n\t"
+    "slt            %[r8],       %[max],        %[r6]         \n\t"
+    "movn           %[max],      %[r6],         %[r8]         \n\t"
+    "bgtz           %[k],        1b                           \n\t"
+    " addiu         %[outre2],   %[outre2],     8             \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "lh             %[r0],       0(%[inre])                   \n\t"
+    "lh             %[r1],       0(%[inim])                   \n\t"
+    "lh             %[r4],       0(%[cosptr])                 \n\t"
+    "lh             %[r5],       0(%[sinptr])                 \n\t"
+    "addiu          %[k],        %[k],          -1            \n\t"
+    "mul            %[r2],       %[r0],         %[r4]         \n\t"
+    "mul            %[r0],       %[r0],         %[r5]         \n\t"
+    "mul            %[r3],       %[r1],         %[r5]         \n\t"
+    "mul            %[r1],       %[r1],         %[r4]         \n\t"
+    "addiu          %[cosptr],   %[cosptr],     2             \n\t"
+    "addiu          %[sinptr],   %[sinptr],     2             \n\t"
+    "addu           %[r8],       %[inre],       %[offset]     \n\t"
+    "addu           %[r9],       %[inim],       %[offset]     \n\t"
+    "addiu          %[r2],       %[r2],         16            \n\t"
+    "sra            %[r2],       %[r2],         5             \n\t"
+    "addiu          %[r0],       %[r0],         16            \n\t"
+    "sra            %[r0],       %[r0],         5             \n\t"
+    "addiu          %[r3],       %[r3],         16            \n\t"
+    "sra            %[r3],       %[r3],         5             \n\t"
+    "lh             %[r6],       0(%[r8])                     \n\t"
+    "lh             %[r7],       0(%[r9])                     \n\t"
+    "addiu          %[r1],       %[r1],         16            \n\t"
+    "sra            %[r1],       %[r1],         5             \n\t"
+    "mul            %[r8],       %[r7],         %[r4]         \n\t"
+    "mul            %[r7],       %[r7],         %[r5]         \n\t"
+    "mul            %[r9],       %[r6],         %[r4]         \n\t"
+    "mul            %[r6],       %[r6],         %[r5]         \n\t"
+    "addu           %[r2],       %[r2],         %[r3]         \n\t"
+    "subu           %[r1],       %[r1],         %[r0]         \n\t"
+    "sll            %[r0],       %[offset],     1             \n\t"
+    "addu           %[r4],       %[outre1],     %[r0]         \n\t"
+    "addu           %[r5],       %[outre2],     %[r0]         \n\t"
+    "addiu          %[r8],       %[r8],         16            \n\t"
+    "sra            %[r8],       %[r8],         5             \n\t"
+    "addiu          %[r7],       %[r7],         16            \n\t"
+    "sra            %[r7],       %[r7],         5             \n\t"
+    "addiu          %[r6],       %[r6],         16            \n\t"
+    "sra            %[r6],       %[r6],         5             \n\t"
+    "addiu          %[r9],       %[r9],         16            \n\t"
+    "sra            %[r9],       %[r9],         5             \n\t"
+    "addu           %[r8],       %[r8],         %[r6]         \n\t"
+    "negu           %[r8],       %[r8]                        \n\t"
+    "subu           %[r7],       %[r7],         %[r9]         \n\t"
+    "subu           %[r6],       %[r2],         %[r7]         \n\t"
+    "addu           %[r0],       %[r2],         %[r7]         \n\t"
+    "addu           %[r3],       %[r1],         %[r8]         \n\t"
+    "subu           %[r1],       %[r8],         %[r1]         \n\t"
+    "sw             %[r6],       0(%[outre1])                 \n\t"
+    "sw             %[r0],       0(%[r4])                     \n\t"
+    "sw             %[r3],       0(%[outre2])                 \n\t"
+    "sw             %[r1],       0(%[r5])                     \n\t"
+    "addiu          %[outre1],   %[outre1],     4             \n\t"
+    "addiu          %[offset],   %[offset],     -4            \n\t"
+    "addiu          %[inre],     %[inre],       2             \n\t"
+    "addiu          %[inim],     %[inim],       2             \n\t"
+    // Inlined WebRtcSpl_MaxAbsValueW32
+    "negu           %[r5],       %[r6]                        \n\t"
+    "slt            %[r2],       %[r6],         $zero         \n\t"
+    "movn           %[r6],       %[r5],         %[r2]         \n\t"
+    "negu           %[r5],       %[r0]                        \n\t"
+    "slt            %[r2],       %[r0],         $zero         \n\t"
+    "movn           %[r0],       %[r5],         %[r2]         \n\t"
+    "negu           %[r5],       %[r3]                        \n\t"
+    "slt            %[r2],       %[r3],         $zero         \n\t"
+    "movn           %[r3],       %[r5],         %[r2]         \n\t"
+    "negu           %[r5],       %[r1]                        \n\t"
+    "slt            %[r2],       %[r1],         $zero         \n\t"
+    "movn           %[r1],       %[r5],         %[r2]         \n\t"
+    "slt            %[r2],       %[r6],         %[r0]         \n\t"
+    "slt            %[r5],       %[r3],         %[r1]         \n\t"
+    "movn           %[r6],       %[r0],         %[r2]         \n\t"
+    "movn           %[r3],       %[r1],         %[r5]         \n\t"
+    "slt            %[r2],       %[r6],         %[r3]         \n\t"
+    "movn           %[r6],       %[r3],         %[r2]         \n\t"
+    "slt            %[r2],       %[max],        %[r6]         \n\t"
+    "movn           %[max],      %[r6],         %[r2]         \n\t"
+    "bgtz           %[k],        1b                           \n\t"
+    " addiu         %[outre2],   %[outre2],     4             \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "clz            %[max],      %[max]                       \n\t"
+    "addiu          %[max],      %[max],        -25           \n\t"
+    ".set           pop                                       \n\t"
+    : [inre] "=&r" (inre), [inim] "=&r" (inim),
+      [outre1] "=&r" (outre1), [outre2] "=&r" (outre2),
+      [offset] "+r" (offset), [k] "+r" (k), [r0] "=&r" (r0),
+      [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+      [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6),
+      [r7] "=&r" (r7), [r8] "=&r" (r8), [r9] "=&r" (r9),
+      [max] "=&r" (max)
+    : [inreQ7] "r" (inreQ7), [inimQ7] "r" (inimQ7),
+      [cosptr] "r" (cosptr), [sinptr] "r" (sinptr),
+      [outre1Q16] "r" (outre1Q16), [outre2Q16] "r" (outre2Q16)
+    : "hi", "lo", "memory"
+  );
+
+  // "Fastest" vectors
+  k = FRAMESAMPLES / 4;
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[inre],      %[inreQ7],    0             \n\t"
+    "addiu          %[inim],      %[inimQ7],    0             \n\t"
+    "addiu          %[outre1],    %[outre1Q16], 0             \n\t"
+    "addiu          %[outre2],    %[outre2Q16], 0             \n\t"
+    "bltz           %[max],       2f                          \n\t"
+    " subu          %[max1],      $zero,        %[max]        \n\t"
+   "1:                                                        \n\t"
+    "lw             %[r0],        0(%[outre1])                \n\t"
+    "lw             %[r1],        0(%[outre2])                \n\t"
+    "lw             %[r2],        4(%[outre1])                \n\t"
+    "lw             %[r3],        4(%[outre2])                \n\t"
+    "sllv           %[r0],        %[r0],        %[max]        \n\t"
+    "sllv           %[r1],        %[r1],        %[max]        \n\t"
+    "sllv           %[r2],        %[r2],        %[max]        \n\t"
+    "sllv           %[r3],        %[r3],        %[max]        \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "addiu          %[outre1],    %[outre1],    8             \n\t"
+    "addiu          %[outre2],    %[outre2],    8             \n\t"
+    "sh             %[r0],        0(%[inre])                  \n\t"
+    "sh             %[r1],        0(%[inim])                  \n\t"
+    "sh             %[r2],        2(%[inre])                  \n\t"
+    "sh             %[r3],        2(%[inim])                  \n\t"
+    "addiu          %[inre],      %[inre],      4             \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[inim],      %[inim],      4             \n\t"
+    "b              4f                                        \n\t"
+    " nop                                                     \n\t"
+   "2:                                                        \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+    "addiu          %[r4],        $zero,        1             \n\t"
+    "addiu          %[r5],        %[max1],      -1            \n\t"
+    "sllv           %[r4],        %[r4],        %[r5]         \n\t"
+#endif  // #if !defined(MIPS_DSP_R1_LE)
+   "3:                                                        \n\t"
+    "lw             %[r0],        0(%[outre1])                \n\t"
+    "lw             %[r1],        0(%[outre2])                \n\t"
+    "lw             %[r2],        4(%[outre1])                \n\t"
+    "lw             %[r3],        4(%[outre2])                \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shrav_r.w      %[r0],        %[r0],        %[max1]       \n\t"
+    "shrav_r.w      %[r1],        %[r1],        %[max1]       \n\t"
+    "shrav_r.w      %[r2],        %[r2],        %[max1]       \n\t"
+    "shrav_r.w      %[r3],        %[r3],        %[max1]       \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r4]         \n\t"
+    "addu           %[r1],        %[r1],        %[r4]         \n\t"
+    "addu           %[r2],        %[r2],        %[r4]         \n\t"
+    "addu           %[r3],        %[r3],        %[r4]         \n\t"
+    "srav           %[r0],        %[r0],        %[max1]       \n\t"
+    "srav           %[r1],        %[r1],        %[max1]       \n\t"
+    "srav           %[r2],        %[r2],        %[max1]       \n\t"
+    "srav           %[r3],        %[r3],        %[max1]       \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[outre1],    %[outre1],    8             \n\t"
+    "addiu          %[outre2],    %[outre2],    8             \n\t"
+    "sh             %[r0],        0(%[inre])                  \n\t"
+    "sh             %[r1],        0(%[inim])                  \n\t"
+    "sh             %[r2],        2(%[inre])                  \n\t"
+    "sh             %[r3],        2(%[inim])                  \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "addiu          %[inre],      %[inre],      4             \n\t"
+    "bgtz           %[k],         3b                          \n\t"
+    " addiu         %[inim],      %[inim],      4             \n\t"
+   "4:                                                        \n\t"
+    ".set           pop                                       \n\t"
+    : [k] "+r" (k), [max1] "=&r" (max1), [r0] "=&r" (r0),
+      [inre] "=&r" (inre), [inim] "=&r" (inim),
+      [outre1] "=&r" (outre1), [outre2] "=&r" (outre2),
+#if !defined(MIPS_DSP_R1_LE)
+      [r4] "=&r" (r4), [r5] "=&r" (r5),
+#endif  // #if !defined(MIPS_DSP_R1_LE)
+      [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3)
+    : [max] "r" (max), [inreQ7] "r" (inreQ7),
+      [inimQ7] "r" (inimQ7), [outre1Q16] "r" (outre1Q16),
+      [outre2Q16] "r" (outre2Q16)
+    : "memory"
+  );
+
+  WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call
+
+  // All the remaining processing is done inside a single loop to avoid
+  // unnecessary memory accesses. MIPS DSPr2 version processes two samples
+  // at a time.
+  cosptr = (int16_t*)WebRtcIsacfix_kCosTab1;
+  sinptr = (int16_t*)WebRtcIsacfix_kSinTab1;
+  k = FRAMESAMPLES / 2;
+  __asm __volatile (
+    ".set           push                                      \n\t"
+    ".set           noreorder                                 \n\t"
+    "addiu          %[inre],      %[inreQ7],    0             \n\t"
+    "addiu          %[inim],      %[inimQ7],    0             \n\t"
+    "addiu          %[outre1],    %[outre1Q16], 0             \n\t"
+    "addiu          %[outre2],    %[outre2Q16], 0             \n\t"
+    "addiu          %[r4],        $zero,        273           \n\t"
+    "addiu          %[r5],        $zero,        31727         \n\t"
+#if defined(MIPS_DSP_R2_LE)
+    "addiu          %[max],       %[max],       16            \n\t"
+    "replv.ph       %[r4],        %[r4]                       \n\t"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+    "bltz           %[max],       2f                          \n\t"
+    " subu          %[max1],      $zero,        %[max]        \n\t"
+#if defined(MIPS_DSP_R2_LE)
+    "addiu          %[max],       %[max],       1             \n\t"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+   "1:                                                        \n\t"
+#if defined(MIPS_DSP_R2_LE)
+    "lwl            %[r0],        0(%[inre])                  \n\t"
+    "lwl            %[r1],        0(%[inim])                  \n\t"
+    "lh             %[r2],        0(%[cosptr])                \n\t"
+    "lwr            %[r0],        0(%[inre])                  \n\t"
+    "lwr            %[r1],        0(%[inim])                  \n\t"
+    "lh             %[r3],        0(%[sinptr])                \n\t"
+    "muleq_s.w.phr  %[r6],        %[r0],        %[r4]         \n\t"
+    "muleq_s.w.phr  %[r7],        %[r1],        %[r4]         \n\t"
+    "muleq_s.w.phl  %[r0],        %[r0],        %[r4]         \n\t"
+    "muleq_s.w.phl  %[r1],        %[r1],        %[r4]         \n\t"
+    "addiu          %[k],         %[k],         -2            \n\t"
+    "addiu          %[inre],      %[inre],      4             \n\t"
+    "addiu          %[inim],      %[inim],      4             \n\t"
+    "shrav_r.w      %[r6],        %[r6],        %[max]        \n\t"
+    "shrav_r.w      %[r7],        %[r7],        %[max]        \n\t"
+    "mult           $ac0,         %[r2],        %[r6]         \n\t"
+    "mult           $ac1,         %[r3],        %[r7]         \n\t"
+    "mult           $ac2,         %[r2],        %[r7]         \n\t"
+    "mult           $ac3,         %[r3],        %[r6]         \n\t"
+    "lh             %[r2],        2(%[cosptr])                \n\t"
+    "lh             %[r3],        2(%[sinptr])                \n\t"
+    "extr_r.w       %[r6],        $ac0,         14            \n\t"
+    "extr_r.w       %[r7],        $ac1,         14            \n\t"
+    "extr_r.w       %[r8],        $ac2,         14            \n\t"
+    "extr_r.w       %[r9],        $ac3,         14            \n\t"
+    "shrav_r.w      %[r0],        %[r0],        %[max]        \n\t"
+    "shrav_r.w      %[r1],        %[r1],        %[max]        \n\t"
+    "mult           $ac0,         %[r2],        %[r0]         \n\t"
+    "mult           $ac1,         %[r3],        %[r1]         \n\t"
+    "mult           $ac2,         %[r2],        %[r1]         \n\t"
+    "mult           $ac3,         %[r3],        %[r0]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    4             \n\t"
+    "extr_r.w       %[r0],        $ac0,         14            \n\t"
+    "extr_r.w       %[r1],        $ac1,         14            \n\t"
+    "extr_r.w       %[r2],        $ac2,         14            \n\t"
+    "extr_r.w       %[r3],        $ac3,         14            \n\t"
+    "subu           %[r6],        %[r6],        %[r7]         \n\t"
+    "addu           %[r8],        %[r8],        %[r9]         \n\t"
+    "mult           $ac0,         %[r5],        %[r6]         \n\t"
+    "mult           $ac1,         %[r5],        %[r8]         \n\t"
+    "addiu          %[sinptr],    %[sinptr],    4             \n\t"
+    "subu           %[r0],        %[r0],        %[r1]         \n\t"
+    "addu           %[r2],        %[r2],        %[r3]         \n\t"
+    "extr_r.w       %[r1],        $ac0,         11            \n\t"
+    "extr_r.w       %[r3],        $ac1,         11            \n\t"
+    "mult           $ac2,         %[r5],        %[r0]         \n\t"
+    "mult           $ac3,         %[r5],        %[r2]         \n\t"
+    "sw             %[r1],        0(%[outre1])                \n\t"
+    "sw             %[r3],        0(%[outre2])                \n\t"
+    "addiu          %[outre1],    %[outre1],    8             \n\t"
+    "extr_r.w       %[r0],        $ac2,         11            \n\t"
+    "extr_r.w       %[r2],        $ac3,         11            \n\t"
+    "sw             %[r0],        -4(%[outre1])               \n\t"
+    "sw             %[r2],        4(%[outre2])                \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[outre2],    %[outre2],    8             \n\t"
+    "b              3f                                        \n\t"
+#else  // #if defined(MIPS_DSP_R2_LE)
+    "lh             %[r0],        0(%[inre])                  \n\t"
+    "lh             %[r1],        0(%[inim])                  \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "srav           %[r0],        %[r0],        %[max]        \n\t"
+    "srav           %[r1],        %[r1],        %[max]        \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "sra            %[r0],        %[r0],        1             \n\t"
+    "sra            %[r3],        %[r1],        16            \n\t"
+    "andi           %[r1],        %[r1],        0xFFFF        \n\t"
+    "sra            %[r1],        %[r1],        1             \n\t"
+    "mul            %[r2],        %[r2],        %[r4]         \n\t"
+    "mul            %[r0],        %[r0],        %[r4]         \n\t"
+    "mul            %[r3],        %[r3],        %[r4]         \n\t"
+    "mul            %[r1],        %[r1],        %[r4]         \n\t"
+    "addiu          %[inre],      %[inre],      2             \n\t"
+    "addiu          %[inim],      %[inim],      2             \n\t"
+    "lh             %[r6],        0(%[cosptr])                \n\t"
+    "lh             %[r7],        0(%[sinptr])                \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r0],        %[r0],        15            \n\t"
+    "shra_r.w       %[r1],        %[r1],        15            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r0],        %[r0],        0x4000        \n\t"
+    "addiu          %[r1],        %[r1],        0x4000        \n\t"
+    "sra            %[r0],        %[r0],        15            \n\t"
+    "sra            %[r1],        %[r1],        15            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r2],        %[r0]         \n\t"
+    "addu           %[r1],        %[r3],        %[r1]         \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "mul            %[r9],        %[r2],        %[r6]         \n\t"
+    "mul            %[r2],        %[r2],        %[r7]         \n\t"
+    "mul            %[r8],        %[r0],        %[r6]         \n\t"
+    "mul            %[r0],        %[r0],        %[r7]         \n\t"
+    "sra            %[r3],        %[r3],        16            \n\t"
+    "andi           %[r1],        %[r1],        0xFFFF        \n\t"
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "sll            %[r2],        %[r2],        2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r8],        %[r8],        14            \n\t"
+    "shra_r.w       %[r0],        %[r0],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r8],        %[r8],        0x2000        \n\t"
+    "addiu          %[r0],        %[r0],        0x2000        \n\t"
+    "sra            %[r8],        %[r8],        14            \n\t"
+    "sra            %[r0],        %[r0],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r9],        %[r9],        %[r8]         \n\t"
+    "addu           %[r2],        %[r2],        %[r0]         \n\t"
+    "mul            %[r0],        %[r3],        %[r6]         \n\t"
+    "mul            %[r3],        %[r3],        %[r7]         \n\t"
+    "mul            %[r8],        %[r1],        %[r6]         \n\t"
+    "mul            %[r1],        %[r1],        %[r8]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    2             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    2             \n\t"
+    "sll            %[r0],        %[r0],        2             \n\t"
+    "sll            %[r3],        %[r3],        2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r8],        %[r8],        14            \n\t"
+    "shra_r.w       %[r1],        %[r1],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r8],        %[r8],        0x2000        \n\t"
+    "addiu          %[r1],        %[r1],        0x2000        \n\t"
+    "sra            %[r8],        %[r8],        14            \n\t"
+    "sra            %[r1],        %[r1],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r8]         \n\t"
+    "addu           %[r3],        %[r3],        %[r1]         \n\t"
+    "subu           %[r9],        %[r9],        %[r3]         \n\t"
+    "addu           %[r0],        %[r0],        %[r2]         \n\t"
+    "sra            %[r1],        %[r9],        16            \n\t"
+    "andi           %[r9],        %[r9],        0xFFFF        \n\t"
+    "mul            %[r1],        %[r1],        %[r5]         \n\t"
+    "mul            %[r9],        %[r9],        %[r5]         \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "mul            %[r2],        %[r2],        %[r5]         \n\t"
+    "mul            %[r0],        %[r0],        %[r5]         \n\t"
+    "sll            %[r1],        %[r1],        5             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r9],        %[r9],        11            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r9],        %[r9],        0x400         \n\t"
+    "sra            %[r9],        %[r9],        11            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r1],        %[r1],        %[r9]         \n\t"
+    "sll            %[r2],        %[r2],        5             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r0],        %[r0],        11            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r0],        %[r0],        0x400         \n\t"
+    "sra            %[r0],        %[r0],        11            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r2]         \n\t"
+    "sw             %[r1],        0(%[outre1])                \n\t"
+    "addiu          %[outre1],    %[outre1],    4             \n\t"
+    "sw             %[r0],        0(%[outre2])                \n\t"
+    "bgtz           %[k],         1b                          \n\t"
+    " addiu         %[outre2],    %[outre2],    4             \n\t"
+    "b              3f                                        \n\t"
+    " nop                                                     \n\t"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+   "2:                                                        \n\t"
+#if defined(MIPS_DSP_R2_LE)
+    "addiu          %[max1],      %[max1],      -1            \n\t"
+   "21:                                                       \n\t"
+    "lwl            %[r0],        0(%[inre])                  \n\t"
+    "lwl            %[r1],        0(%[inim])                  \n\t"
+    "lh             %[r2],        0(%[cosptr])                \n\t"
+    "lwr            %[r0],        0(%[inre])                  \n\t"
+    "lwr            %[r1],        0(%[inim])                  \n\t"
+    "lh             %[r3],        0(%[sinptr])                \n\t"
+    "muleq_s.w.phr  %[r6],        %[r0],        %[r4]         \n\t"
+    "muleq_s.w.phr  %[r7],        %[r1],        %[r4]         \n\t"
+    "muleq_s.w.phl  %[r0],        %[r0],        %[r4]         \n\t"
+    "muleq_s.w.phl  %[r1],        %[r1],        %[r4]         \n\t"
+    "addiu          %[k],         %[k],         -2            \n\t"
+    "addiu          %[inre],      %[inre],      4             \n\t"
+    "addiu          %[inim],      %[inim],      4             \n\t"
+    "sllv           %[r6],        %[r6],        %[max1]       \n\t"
+    "sllv           %[r7],        %[r7],        %[max1]       \n\t"
+    "mult           $ac0,         %[r2],        %[r6]         \n\t"
+    "mult           $ac1,         %[r3],        %[r7]         \n\t"
+    "mult           $ac2,         %[r2],        %[r7]         \n\t"
+    "mult           $ac3,         %[r3],        %[r6]         \n\t"
+    "lh             %[r2],        2(%[cosptr])                \n\t"
+    "lh             %[r3],        2(%[sinptr])                \n\t"
+    "extr_r.w       %[r6],        $ac0,         14            \n\t"
+    "extr_r.w       %[r7],        $ac1,         14            \n\t"
+    "extr_r.w       %[r8],        $ac2,         14            \n\t"
+    "extr_r.w       %[r9],        $ac3,         14            \n\t"
+    "sllv           %[r0],        %[r0],        %[max1]       \n\t"
+    "sllv           %[r1],        %[r1],        %[max1]       \n\t"
+    "mult           $ac0,         %[r2],        %[r0]         \n\t"
+    "mult           $ac1,         %[r3],        %[r1]         \n\t"
+    "mult           $ac2,         %[r2],        %[r1]         \n\t"
+    "mult           $ac3,         %[r3],        %[r0]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    4             \n\t"
+    "extr_r.w       %[r0],        $ac0,         14            \n\t"
+    "extr_r.w       %[r1],        $ac1,         14            \n\t"
+    "extr_r.w       %[r2],        $ac2,         14            \n\t"
+    "extr_r.w       %[r3],        $ac3,         14            \n\t"
+    "subu           %[r6],        %[r6],        %[r7]         \n\t"
+    "addu           %[r8],        %[r8],        %[r9]         \n\t"
+    "mult           $ac0,         %[r5],        %[r6]         \n\t"
+    "mult           $ac1,         %[r5],        %[r8]         \n\t"
+    "addiu          %[sinptr],    %[sinptr],    4             \n\t"
+    "subu           %[r0],        %[r0],        %[r1]         \n\t"
+    "addu           %[r2],        %[r2],        %[r3]         \n\t"
+    "extr_r.w       %[r1],        $ac0,         11            \n\t"
+    "extr_r.w       %[r3],        $ac1,         11            \n\t"
+    "mult           $ac2,         %[r5],        %[r0]         \n\t"
+    "mult           $ac3,         %[r5],        %[r2]         \n\t"
+    "sw             %[r1],        0(%[outre1])                \n\t"
+    "sw             %[r3],        0(%[outre2])                \n\t"
+    "addiu          %[outre1],    %[outre1],    8             \n\t"
+    "extr_r.w       %[r0],        $ac2,         11            \n\t"
+    "extr_r.w       %[r2],        $ac3,         11            \n\t"
+    "sw             %[r0],        -4(%[outre1])               \n\t"
+    "sw             %[r2],        4(%[outre2])                \n\t"
+    "bgtz           %[k],         21b                         \n\t"
+    " addiu         %[outre2],    %[outre2],    8             \n\t"
+    "b              3f                                        \n\t"
+    " nop                                                     \n\t"
+#else  // #if defined(MIPS_DSP_R2_LE)
+    "lh             %[r0],        0(%[inre])                  \n\t"
+    "lh             %[r1],        0(%[inim])                  \n\t"
+    "addiu          %[k],         %[k],         -1            \n\t"
+    "sllv           %[r0],        %[r0],        %[max1]       \n\t"
+    "sllv           %[r1],        %[r1],        %[max1]       \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "sra            %[r0],        %[r0],        1             \n\t"
+    "sra            %[r3],        %[r1],        16            \n\t"
+    "andi           %[r1],        %[r1],        0xFFFF        \n\t"
+    "sra            %[r1],        %[r1],        1             \n\t"
+    "mul            %[r2],        %[r2],        %[r4]         \n\t"
+    "mul            %[r0],        %[r0],        %[r4]         \n\t"
+    "mul            %[r3],        %[r3],        %[r4]         \n\t"
+    "mul            %[r1],        %[r1],        %[r4]         \n\t"
+    "addiu          %[inre],      %[inre],      2             \n\t"
+    "addiu          %[inim],      %[inim],      2             \n\t"
+    "lh             %[r6],        0(%[cosptr])                \n\t"
+    "lh             %[r7],        0(%[sinptr])                \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r0],        %[r0],        15            \n\t"
+    "shra_r.w       %[r1],        %[r1],        15            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r0],        %[r0],        0x4000        \n\t"
+    "addiu          %[r1],        %[r1],        0x4000        \n\t"
+    "sra            %[r0],        %[r0],        15            \n\t"
+    "sra            %[r1],        %[r1],        15            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r2],        %[r0]         \n\t"
+    "addu           %[r1],        %[r3],        %[r1]         \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "mul            %[r9],        %[r2],        %[r6]         \n\t"
+    "mul            %[r2],        %[r2],        %[r7]         \n\t"
+    "mul            %[r8],        %[r0],        %[r6]         \n\t"
+    "mul            %[r0],        %[r0],        %[r7]         \n\t"
+    "sra            %[r3],        %[r1],        16            \n\t"
+    "andi           %[r1],        %[r1],        0xFFFF        \n\t"
+    "sll            %[r9],        %[r9],        2             \n\t"
+    "sll            %[r2],        %[r2],        2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r8],        %[r8],        14            \n\t"
+    "shra_r.w       %[r0],        %[r0],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r8],        %[r8],        0x2000        \n\t"
+    "addiu          %[r0],        %[r0],        0x2000        \n\t"
+    "sra            %[r8],        %[r8],        14            \n\t"
+    "sra            %[r0],        %[r0],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r9],        %[r9],        %[r8]         \n\t"
+    "addu           %[r2],        %[r2],        %[r0]         \n\t"
+    "mul            %[r0],        %[r3],        %[r6]         \n\t"
+    "mul            %[r3],        %[r3],        %[r7]         \n\t"
+    "mul            %[r8],        %[r1],        %[r6]         \n\t"
+    "mul            %[r1],        %[r1],        %[r7]         \n\t"
+    "addiu          %[cosptr],    %[cosptr],    2             \n\t"
+    "addiu          %[sinptr],    %[sinptr],    2             \n\t"
+    "sll            %[r0],        %[r0],        2             \n\t"
+    "sll            %[r3],        %[r3],        2             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r8],        %[r8],        14            \n\t"
+    "shra_r.w       %[r1],        %[r1],        14            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r8],        %[r8],        0x2000        \n\t"
+    "addiu          %[r1],        %[r1],        0x2000        \n\t"
+    "sra            %[r8],        %[r8],        14            \n\t"
+    "sra            %[r1],        %[r1],        14            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r8]         \n\t"
+    "addu           %[r3],        %[r3],        %[r1]         \n\t"
+    "subu           %[r9],        %[r9],        %[r3]         \n\t"
+    "addu           %[r0],        %[r0],        %[r2]         \n\t"
+    "sra            %[r1],        %[r9],        16            \n\t"
+    "andi           %[r9],        %[r9],        0xFFFF        \n\t"
+    "mul            %[r1],        %[r1],        %[r5]         \n\t"
+    "mul            %[r9],        %[r9],        %[r5]         \n\t"
+    "sra            %[r2],        %[r0],        16            \n\t"
+    "andi           %[r0],        %[r0],        0xFFFF        \n\t"
+    "mul            %[r2],        %[r2],        %[r5]         \n\t"
+    "mul            %[r0],        %[r0],        %[r5]         \n\t"
+    "sll            %[r1],        %[r1],        5             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r9],        %[r9],        11            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r9],        %[r9],        0x400         \n\t"
+    "sra            %[r9],        %[r9],        11            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r1],        %[r1],        %[r9]         \n\t"
+    "sll            %[r2],        %[r2],        5             \n\t"
+#if defined(MIPS_DSP_R1_LE)
+    "shra_r.w       %[r0],        %[r0],        11            \n\t"
+#else  // #if defined(MIPS_DSP_R1_LE)
+    "addiu          %[r0],        %[r0],        0x400         \n\t"
+    "sra            %[r0],        %[r0],        11            \n\t"
+#endif  // #if defined(MIPS_DSP_R1_LE)
+    "addu           %[r0],        %[r0],        %[r2]         \n\t"
+    "sw             %[r1],        0(%[outre1])                \n\t"
+    "addiu          %[outre1],    %[outre1],    4             \n\t"
+    "sw             %[r0],        0(%[outre2])                \n\t"
+    "bgtz           %[k],         2b                          \n\t"
+    " addiu         %[outre2],    %[outre2],    4             \n\t"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+   "3:                                                        \n\t"
+    ".set           pop                                       \n\t"
+    : [k] "+r" (k), [r0] "=&r" (r0), [r1] "=&r" (r1),
+      [r2] "=&r" (r2), [r3] "=&r" (r3), [r4] "=&r" (r4),
+      [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+      [r8] "=&r" (r8), [r9] "=&r" (r9), [max1] "=&r" (max1),
+      [inre] "=&r" (inre), [inim] "=&r" (inim),
+      [outre1] "=&r" (outre1), [outre2] "=&r" (outre2)
+    : [max] "r" (max), [inreQ7] "r" (inreQ7),
+      [inimQ7] "r" (inimQ7), [cosptr] "r" (cosptr),
+      [sinptr] "r" (sinptr), [outre1Q16] "r" (outre1Q16),
+      [outre2Q16] "r" (outre2Q16)
+    : "hi", "lo", "memory"
+#if defined(MIPS_DSP_R2_LE)
+    , "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+#endif  // #if defined(MIPS_DSP_R2_LE)
+  );
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform_neon.c b/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
new file mode 100644
index 0000000..79dadc4
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
@@ -0,0 +1,479 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Tables are defined in transform_tables.c file.
+// Cosine table 1 in Q14.
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+// Sine table 1 in Q14.
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+// Sine table 2 in Q14.
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+static inline int32_t ComplexMulAndFindMaxNeon(int16_t* inre1Q9,
+                                               int16_t* inre2Q9,
+                                               int32_t* outreQ16,
+                                               int32_t* outimQ16) {
+  int k;
+  const int16_t* kCosTab = &WebRtcIsacfix_kCosTab1[0];
+  const int16_t* kSinTab = &WebRtcIsacfix_kSinTab1[0];
+  // 0.5 / sqrt(240) in Q19 is round((.5 / sqrt(240)) * (2^19)) = 16921.
+  // Use "16921 << 5" and vqdmulh, instead of ">> 26" as in the C code.
+  int32_t fact  = 16921 << 5;
+  int32x4_t factq = vdupq_n_s32(fact);
+  uint32x4_t max_r = vdupq_n_u32(0);
+  uint32x4_t max_i = vdupq_n_u32(0);
+
+  for (k = 0; k < FRAMESAMPLES/2; k += 8) {
+    int16x8_t tmpr = vld1q_s16(kCosTab);
+    int16x8_t tmpi = vld1q_s16(kSinTab);
+    int16x8_t inre1 = vld1q_s16(inre1Q9);
+    int16x8_t inre2 = vld1q_s16(inre2Q9);
+    kCosTab += 8;
+    kSinTab += 8;
+    inre1Q9 += 8;
+    inre2Q9 += 8;
+
+    // Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code.
+    int32x4_t tmp0 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre1));
+    int32x4_t tmp1 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre2));
+    tmp0 = vmlal_s16(tmp0, vget_low_s16(tmpi), vget_low_s16(inre2));
+    tmp1 = vmlsl_s16(tmp1, vget_low_s16(tmpi), vget_low_s16(inre1));
+#if defined(WEBRTC_ARCH_ARM64)
+    int32x4_t tmp2 = vmull_high_s16(tmpr, inre1);
+    int32x4_t tmp3 = vmull_high_s16(tmpr, inre2);
+    tmp2 = vmlal_high_s16(tmp2, tmpi, inre2);
+    tmp3 = vmlsl_high_s16(tmp3, tmpi, inre1);
+#else
+    int32x4_t tmp2 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre1));
+    int32x4_t tmp3 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre2));
+    tmp2 = vmlal_s16(tmp2, vget_high_s16(tmpi), vget_high_s16(inre2));
+    tmp3 = vmlsl_s16(tmp3, vget_high_s16(tmpi), vget_high_s16(inre1));
+#endif
+
+    int32x4_t outr_0 = vqdmulhq_s32(tmp0, factq);
+    int32x4_t outr_1 = vqdmulhq_s32(tmp2, factq);
+    int32x4_t outi_0 = vqdmulhq_s32(tmp1, factq);
+    int32x4_t outi_1 = vqdmulhq_s32(tmp3, factq);
+    vst1q_s32(outreQ16, outr_0);
+    outreQ16 += 4;
+    vst1q_s32(outreQ16, outr_1);
+    outreQ16 += 4;
+    vst1q_s32(outimQ16, outi_0);
+    outimQ16 += 4;
+    vst1q_s32(outimQ16, outi_1);
+    outimQ16 += 4;
+
+    // Find the absolute maximum in the vectors.
+    tmp0 = vabsq_s32(outr_0);
+    tmp1 = vabsq_s32(outr_1);
+    tmp2 = vabsq_s32(outi_0);
+    tmp3 = vabsq_s32(outi_1);
+    // vabs doesn't change the value of 0x80000000.
+    // Use u32 so we don't lose the value 0x80000000.
+    max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp0));
+    max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp2));
+    max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp1));
+    max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp3));
+  }
+
+  max_r = vmaxq_u32(max_r, max_i);
+#if defined(WEBRTC_ARCH_ARM64)
+  uint32_t maximum = vmaxvq_u32(max_r);
+#else
+  uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
+  max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
+  uint32_t maximum = vget_lane_u32(max32x2_r, 0);
+#endif
+
+  return (int32_t)maximum;
+}
+
+static inline void PreShiftW32toW16Neon(int32_t* inre,
+                                        int32_t* inim,
+                                        int16_t* outre,
+                                        int16_t* outim,
+                                        int32_t sh) {
+  int k;
+  int32x4_t sh32x4 = vdupq_n_s32(sh);
+  for (k = 0; k < FRAMESAMPLES/2; k += 16) {
+    int32x4x4_t inre32x4x4 = vld4q_s32(inre);
+    int32x4x4_t inim32x4x4 = vld4q_s32(inim);
+    inre += 16;
+    inim += 16;
+    inre32x4x4.val[0] = vrshlq_s32(inre32x4x4.val[0], sh32x4);
+    inre32x4x4.val[1] = vrshlq_s32(inre32x4x4.val[1], sh32x4);
+    inre32x4x4.val[2] = vrshlq_s32(inre32x4x4.val[2], sh32x4);
+    inre32x4x4.val[3] = vrshlq_s32(inre32x4x4.val[3], sh32x4);
+    inim32x4x4.val[0] = vrshlq_s32(inim32x4x4.val[0], sh32x4);
+    inim32x4x4.val[1] = vrshlq_s32(inim32x4x4.val[1], sh32x4);
+    inim32x4x4.val[2] = vrshlq_s32(inim32x4x4.val[2], sh32x4);
+    inim32x4x4.val[3] = vrshlq_s32(inim32x4x4.val[3], sh32x4);
+    int16x4x4_t outre16x4x4;
+    int16x4x4_t outim16x4x4;
+    outre16x4x4.val[0]  = vmovn_s32(inre32x4x4.val[0]);
+    outre16x4x4.val[1]  = vmovn_s32(inre32x4x4.val[1]);
+    outre16x4x4.val[2]  = vmovn_s32(inre32x4x4.val[2]);
+    outre16x4x4.val[3]  = vmovn_s32(inre32x4x4.val[3]);
+    outim16x4x4.val[0]  = vmovn_s32(inim32x4x4.val[0]);
+    outim16x4x4.val[1]  = vmovn_s32(inim32x4x4.val[1]);
+    outim16x4x4.val[2]  = vmovn_s32(inim32x4x4.val[2]);
+    outim16x4x4.val[3]  = vmovn_s32(inim32x4x4.val[3]);
+    vst4_s16(outre, outre16x4x4);
+    vst4_s16(outim, outim16x4x4);
+    outre += 16;
+    outim += 16;
+  }
+}
+
+static inline void PostShiftAndSeparateNeon(int16_t* inre,
+                                            int16_t* inim,
+                                            int16_t* outre,
+                                            int16_t* outim,
+                                            int32_t sh) {
+  int k;
+  int16_t* inre1 = inre;
+  int16_t* inre2 = &inre[FRAMESAMPLES/2 - 4];
+  int16_t* inim1 = inim;
+  int16_t* inim2 = &inim[FRAMESAMPLES/2 - 4];
+  int16_t* outre1 = outre;
+  int16_t* outre2 = &outre[FRAMESAMPLES/2 - 4];
+  int16_t* outim1 = outim;
+  int16_t* outim2 = &outim[FRAMESAMPLES/2 - 4];
+  const int16_t* kSinTab1 = &WebRtcIsacfix_kSinTab2[0];
+  const int16_t* kSinTab2 = &WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 -4];
+  // By vshl, we effectively did "<< (-sh - 23)", instead of "<< (-sh)",
+  // ">> 14" and then ">> 9" as in the C code.
+  int32x4_t shift = vdupq_n_s32(-sh - 23);
+
+  for (k = 0; k < FRAMESAMPLES/4; k += 4) {
+    int16x4_t tmpi = vld1_s16(kSinTab1);
+    kSinTab1 += 4;
+    int16x4_t tmpr = vld1_s16(kSinTab2);
+    kSinTab2 -= 4;
+    int16x4_t inre_0 = vld1_s16(inre1);
+    inre1 += 4;
+    int16x4_t inre_1 = vld1_s16(inre2);
+    inre2 -= 4;
+    int16x4_t inim_0 = vld1_s16(inim1);
+    inim1 += 4;
+    int16x4_t inim_1 = vld1_s16(inim2);
+    inim2 -= 4;
+    tmpr = vneg_s16(tmpr);
+    inre_1 = vrev64_s16(inre_1);
+    inim_1 = vrev64_s16(inim_1);
+    tmpr = vrev64_s16(tmpr);
+
+    int16x4_t xr = vqadd_s16(inre_0, inre_1);
+    int16x4_t xi = vqsub_s16(inim_0, inim_1);
+    int16x4_t yr = vqadd_s16(inim_0, inim_1);
+    int16x4_t yi = vqsub_s16(inre_1, inre_0);
+
+    int32x4_t outr0 = vmull_s16(tmpr, xr);
+    int32x4_t outi0 = vmull_s16(tmpi, xr);
+    int32x4_t outr1 = vmull_s16(tmpi, yr);
+    int32x4_t outi1 = vmull_s16(tmpi, yi);
+    outr0 = vmlsl_s16(outr0, tmpi, xi);
+    outi0 = vmlal_s16(outi0, tmpr, xi);
+    outr1 = vmlal_s16(outr1, tmpr, yi);
+    outi1 = vmlsl_s16(outi1, tmpr, yr);
+
+    outr0 = vshlq_s32(outr0, shift);
+    outi0 = vshlq_s32(outi0, shift);
+    outr1 = vshlq_s32(outr1, shift);
+    outi1 = vshlq_s32(outi1, shift);
+    outr1 = vnegq_s32(outr1);
+
+    int16x4_t outre_0  = vmovn_s32(outr0);
+    int16x4_t outim_0  = vmovn_s32(outi0);
+    int16x4_t outre_1  = vmovn_s32(outr1);
+    int16x4_t outim_1  = vmovn_s32(outi1);
+    outre_1 = vrev64_s16(outre_1);
+    outim_1 = vrev64_s16(outim_1);
+
+    vst1_s16(outre1, outre_0);
+    outre1 += 4;
+    vst1_s16(outim1, outim_0);
+    outim1 += 4;
+    vst1_s16(outre2, outre_1);
+    outre2 -= 4;
+    vst1_s16(outim2, outim_1);
+    outim2 -= 4;
+  }
+}
+
+void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
+                                 int16_t* inre2Q9,
+                                 int16_t* outreQ7,
+                                 int16_t* outimQ7) {
+  int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
+  int32_t max;
+  int32_t sh;
+
+  // Multiply with complex exponentials and combine into one complex vector.
+  // And find the maximum.
+  max = ComplexMulAndFindMaxNeon(inre1Q9, inre2Q9, tmpreQ16, tmpimQ16);
+
+  sh = (int32_t)WebRtcSpl_NormW32(max);
+  sh = sh - 24;
+
+  // If sh becomes >= 0, then we should shift sh steps to the left,
+  // and the domain will become Q(16 + sh).
+  // If sh becomes < 0, then we should shift -sh steps to the right,
+  // and the domain will become Q(16 + sh).
+  PreShiftW32toW16Neon(tmpreQ16, tmpimQ16, inre1Q9, inre2Q9, sh);
+
+  // Get DFT.
+  WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1);
+
+  // If sh >= 0, shift sh steps to the right,
+  // If sh < 0, shift -sh steps to the left.
+  // Use symmetry to separate into two complex vectors
+  // and center frames in time around zero.
+  PostShiftAndSeparateNeon(inre1Q9, inre2Q9, outreQ7, outimQ7, sh);
+}
+
+static inline int32_t TransformAndFindMaxNeon(int16_t* inre,
+                                              int16_t* inim,
+                                              int32_t* outre,
+                                              int32_t* outim) {
+  int k;
+  int16_t* inre1 = inre;
+  int16_t* inre2 = &inre[FRAMESAMPLES/2 - 4];
+  int16_t* inim1 = inim;
+  int16_t* inim2 = &inim[FRAMESAMPLES/2 - 4];
+  int32_t* outre1 = outre;
+  int32_t* outre2 = &outre[FRAMESAMPLES/2 - 4];
+  int32_t* outim1 = outim;
+  int32_t* outim2 = &outim[FRAMESAMPLES/2 - 4];
+  const int16_t* kSinTab1 = &WebRtcIsacfix_kSinTab2[0];
+  const int16_t* kSinTab2 = &WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 4];
+  uint32x4_t max_r = vdupq_n_u32(0);
+  uint32x4_t max_i = vdupq_n_u32(0);
+
+  // Use ">> 5", instead of "<< 9" and then ">> 14" as in the C code.
+  for (k = 0; k < FRAMESAMPLES/4; k += 4) {
+    int16x4_t tmpi = vld1_s16(kSinTab1);
+    kSinTab1 += 4;
+    int16x4_t tmpr = vld1_s16(kSinTab2);
+    kSinTab2 -= 4;
+    int16x4_t inre_0 = vld1_s16(inre1);
+    inre1 += 4;
+    int16x4_t inre_1 = vld1_s16(inre2);
+    inre2 -= 4;
+    int16x4_t inim_0 = vld1_s16(inim1);
+    inim1 += 4;
+    int16x4_t inim_1 = vld1_s16(inim2);
+    inim2 -= 4;
+    tmpr = vneg_s16(tmpr);
+    inre_1 = vrev64_s16(inre_1);
+    inim_1 = vrev64_s16(inim_1);
+    tmpr = vrev64_s16(tmpr);
+
+    int32x4_t xr = vmull_s16(tmpr, inre_0);
+    int32x4_t xi = vmull_s16(tmpr, inim_0);
+    int32x4_t yr = vmull_s16(tmpr, inim_1);
+    int32x4_t yi = vmull_s16(tmpi, inim_1);
+    xr = vmlal_s16(xr, tmpi, inim_0);
+    xi = vmlsl_s16(xi, tmpi, inre_0);
+    yr = vmlal_s16(yr, tmpi, inre_1);
+    yi = vmlsl_s16(yi, tmpr, inre_1);
+    yr = vnegq_s32(yr);
+
+    xr = vshrq_n_s32(xr, 5);
+    xi = vshrq_n_s32(xi, 5);
+    yr = vshrq_n_s32(yr, 5);
+    yi = vshrq_n_s32(yi, 5);
+
+    int32x4_t outr0 = vsubq_s32(xr, yi);
+    int32x4_t outr1 = vaddq_s32(xr, yi);
+    int32x4_t outi0 = vaddq_s32(xi, yr);
+    int32x4_t outi1 = vsubq_s32(yr, xi);
+
+    // Find the absolute maximum in the vectors.
+    int32x4_t tmp0 = vabsq_s32(outr0);
+    int32x4_t tmp1 = vabsq_s32(outr1);
+    int32x4_t tmp2 = vabsq_s32(outi0);
+    int32x4_t tmp3 = vabsq_s32(outi1);
+    // vabs doesn't change the value of 0x80000000.
+    // Use u32 so we don't lose the value 0x80000000.
+    max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp0));
+    max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp2));
+    max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp1));
+    max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp3));
+
+    // Store the vectors.
+    outr1 = vrev64q_s32(outr1);
+    outi1 = vrev64q_s32(outi1);
+    int32x4_t outr_1 = vcombine_s32(vget_high_s32(outr1), vget_low_s32(outr1));
+    int32x4_t outi_1 = vcombine_s32(vget_high_s32(outi1), vget_low_s32(outi1));
+
+    vst1q_s32(outre1, outr0);
+    outre1 += 4;
+    vst1q_s32(outim1, outi0);
+    outim1 += 4;
+    vst1q_s32(outre2, outr_1);
+    outre2 -= 4;
+    vst1q_s32(outim2, outi_1);
+    outim2 -= 4;
+  }
+
+  max_r = vmaxq_u32(max_r, max_i);
+#if defined(WEBRTC_ARCH_ARM64)
+  uint32_t maximum = vmaxvq_u32(max_r);
+#else
+  uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
+  max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
+  uint32_t maximum = vget_lane_u32(max32x2_r, 0);
+#endif
+
+  return (int32_t)maximum;
+}
+
+static inline void PostShiftAndDivideAndDemodulateNeon(int16_t* inre,
+                                                       int16_t* inim,
+                                                       int32_t* outre1,
+                                                       int32_t* outre2,
+                                                       int32_t sh) {
+  int k;
+  int16_t* p_inre = inre;
+  int16_t* p_inim = inim;
+  int32_t* p_outre1 = outre1;
+  int32_t* p_outre2 = outre2;
+  const int16_t* kCosTab = &WebRtcIsacfix_kCosTab1[0];
+  const int16_t* kSinTab = &WebRtcIsacfix_kSinTab1[0];
+  int32x4_t shift = vdupq_n_s32(-sh - 16);
+  // Divide through by the normalizing constant:
+  // scale all values with 1/240, i.e. with 273 in Q16.
+  // 273/65536 ~= 0.0041656
+  // 1/240 ~= 0.0041666
+  int16x8_t scale = vdupq_n_s16(273);
+  // Sqrt(240) in Q11 is round(15.49193338482967 * 2048) = 31727.
+  int factQ19 = 31727 << 16;
+  int32x4_t fact = vdupq_n_s32(factQ19);
+
+  for (k = 0; k < FRAMESAMPLES/2; k += 8) {
+    int16x8_t inre16x8 = vld1q_s16(p_inre);
+    int16x8_t inim16x8 = vld1q_s16(p_inim);
+    p_inre += 8;
+    p_inim += 8;
+    int16x8_t tmpr = vld1q_s16(kCosTab);
+    int16x8_t tmpi = vld1q_s16(kSinTab);
+    kCosTab += 8;
+    kSinTab += 8;
+    // By vshl and vmull, we effectively did "<< (-sh - 16)",
+    // instead of "<< (-sh)" and ">> 16" as in the C code.
+    int32x4_t outre1_0 = vmull_s16(vget_low_s16(inre16x8), vget_low_s16(scale));
+    int32x4_t outre2_0 = vmull_s16(vget_low_s16(inim16x8), vget_low_s16(scale));
+#if defined(WEBRTC_ARCH_ARM64)
+    int32x4_t outre1_1 = vmull_high_s16(inre16x8, scale);
+    int32x4_t outre2_1 = vmull_high_s16(inim16x8, scale);
+#else
+    int32x4_t outre1_1 = vmull_s16(vget_high_s16(inre16x8),
+                                   vget_high_s16(scale));
+    int32x4_t outre2_1 = vmull_s16(vget_high_s16(inim16x8),
+                                   vget_high_s16(scale));
+#endif
+
+    outre1_0 = vshlq_s32(outre1_0, shift);
+    outre1_1 = vshlq_s32(outre1_1, shift);
+    outre2_0 = vshlq_s32(outre2_0, shift);
+    outre2_1 = vshlq_s32(outre2_1, shift);
+
+    // Demodulate and separate.
+    int32x4_t tmpr_0 = vmovl_s16(vget_low_s16(tmpr));
+    int32x4_t tmpi_0 = vmovl_s16(vget_low_s16(tmpi));
+#if defined(WEBRTC_ARCH_ARM64)
+    int32x4_t tmpr_1 = vmovl_high_s16(tmpr);
+    int32x4_t tmpi_1 = vmovl_high_s16(tmpi);
+#else
+    int32x4_t tmpr_1 = vmovl_s16(vget_high_s16(tmpr));
+    int32x4_t tmpi_1 = vmovl_s16(vget_high_s16(tmpi));
+#endif
+
+    int64x2_t xr0 = vmull_s32(vget_low_s32(tmpr_0), vget_low_s32(outre1_0));
+    int64x2_t xi0 = vmull_s32(vget_low_s32(tmpr_0), vget_low_s32(outre2_0));
+    int64x2_t xr2 = vmull_s32(vget_low_s32(tmpr_1), vget_low_s32(outre1_1));
+    int64x2_t xi2 = vmull_s32(vget_low_s32(tmpr_1), vget_low_s32(outre2_1));
+    xr0 = vmlsl_s32(xr0, vget_low_s32(tmpi_0), vget_low_s32(outre2_0));
+    xi0 = vmlal_s32(xi0, vget_low_s32(tmpi_0), vget_low_s32(outre1_0));
+    xr2 = vmlsl_s32(xr2, vget_low_s32(tmpi_1), vget_low_s32(outre2_1));
+    xi2 = vmlal_s32(xi2, vget_low_s32(tmpi_1), vget_low_s32(outre1_1));
+
+#if defined(WEBRTC_ARCH_ARM64)
+    int64x2_t xr1 = vmull_high_s32(tmpr_0, outre1_0);
+    int64x2_t xi1 = vmull_high_s32(tmpr_0, outre2_0);
+    int64x2_t xr3 = vmull_high_s32(tmpr_1, outre1_1);
+    int64x2_t xi3 = vmull_high_s32(tmpr_1, outre2_1);
+    xr1 = vmlsl_high_s32(xr1, tmpi_0, outre2_0);
+    xi1 = vmlal_high_s32(xi1, tmpi_0, outre1_0);
+    xr3 = vmlsl_high_s32(xr3, tmpi_1, outre2_1);
+    xi3 = vmlal_high_s32(xi3, tmpi_1, outre1_1);
+#else
+    int64x2_t xr1 = vmull_s32(vget_high_s32(tmpr_0), vget_high_s32(outre1_0));
+    int64x2_t xi1 = vmull_s32(vget_high_s32(tmpr_0), vget_high_s32(outre2_0));
+    int64x2_t xr3 = vmull_s32(vget_high_s32(tmpr_1), vget_high_s32(outre1_1));
+    int64x2_t xi3 = vmull_s32(vget_high_s32(tmpr_1), vget_high_s32(outre2_1));
+    xr1 = vmlsl_s32(xr1, vget_high_s32(tmpi_0), vget_high_s32(outre2_0));
+    xi1 = vmlal_s32(xi1, vget_high_s32(tmpi_0), vget_high_s32(outre1_0));
+    xr3 = vmlsl_s32(xr3, vget_high_s32(tmpi_1), vget_high_s32(outre2_1));
+    xi3 = vmlal_s32(xi3, vget_high_s32(tmpi_1), vget_high_s32(outre1_1));
+#endif
+
+    outre1_0 = vcombine_s32(vrshrn_n_s64(xr0, 10), vrshrn_n_s64(xr1, 10));
+    outre2_0 = vcombine_s32(vrshrn_n_s64(xi0, 10), vrshrn_n_s64(xi1, 10));
+    outre1_1 = vcombine_s32(vrshrn_n_s64(xr2, 10), vrshrn_n_s64(xr3, 10));
+    outre2_1 = vcombine_s32(vrshrn_n_s64(xi2, 10), vrshrn_n_s64(xi3, 10));
+    outre1_0 = vqdmulhq_s32(outre1_0, fact);
+    outre2_0 = vqdmulhq_s32(outre2_0, fact);
+    outre1_1 = vqdmulhq_s32(outre1_1, fact);
+    outre2_1 = vqdmulhq_s32(outre2_1, fact);
+
+    vst1q_s32(p_outre1, outre1_0);
+    p_outre1 += 4;
+    vst1q_s32(p_outre1, outre1_1);
+    p_outre1 += 4;
+    vst1q_s32(p_outre2, outre2_0);
+    p_outre2 += 4;
+    vst1q_s32(p_outre2, outre2_1);
+    p_outre2 += 4;
+  }
+}
+
+void WebRtcIsacfix_Spec2TimeNeon(int16_t* inreQ7,
+                                 int16_t* inimQ7,
+                                 int32_t* outre1Q16,
+                                 int32_t* outre2Q16) {
+  int32_t max;
+  int32_t sh;
+
+  max = TransformAndFindMaxNeon(inreQ7, inimQ7, outre1Q16, outre2Q16);
+
+
+  sh = (int32_t)WebRtcSpl_NormW32(max);
+  sh = sh - 24;
+  // If sh becomes >= 0, then we should shift sh steps to the left,
+  // and the domain will become Q(16 + sh).
+  // If sh becomes < 0, then we should shift -sh steps to the right,
+  // and the domain will become Q(16 + sh).
+
+  // "Fastest" vectors.
+  PreShiftW32toW16Neon(outre1Q16, outre2Q16, inreQ7, inimQ7, sh);
+
+  // Get IDFT.
+  WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1);
+
+  PostShiftAndDivideAndDemodulateNeon(inreQ7, inimQ7, outre1Q16, outre2Q16, sh);
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform_tables.c b/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
new file mode 100644
index 0000000..e661eff
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This file contains trigonometric functions look-up tables used in
+ * transform functions WebRtcIsacfix_Time2Spec and WebRtcIsacfix_Spec2Time.
+ */
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Cosine table 1 in Q14. */
+const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2] = {
+  16384,  16383,  16378,  16371,  16362,  16349,  16333,  16315,  16294,  16270,
+  16244,  16214,  16182,  16147,  16110,  16069,  16026,  15980,  15931,  15880,
+  15826,  15769,  15709,  15647,  15582,  15515,  15444,  15371,  15296,  15218,
+  15137,  15053,  14968,  14879,  14788,  14694,  14598,  14500,  14399,  14295,
+  14189,  14081,  13970,  13856,  13741,  13623,  13502,  13380,  13255,  13128,
+  12998,  12867,  12733,  12597,  12458,  12318,  12176,  12031,  11885,  11736,
+  11585,  11433,  11278,  11121,  10963,  10803,  10641,  10477,  10311,  10143,
+  9974,   9803,   9630,   9456,   9280,   9102,   8923,   8743,   8561,   8377,
+  8192,   8006,   7818,   7629,   7438,   7246,   7053,   6859,   6664,   6467,
+  6270,   6071,   5872,   5671,   5469,   5266,   5063,   4859,   4653,   4447,
+  4240,   4033,   3825,   3616,   3406,   3196,   2986,   2775,   2563,   2351,
+  2139,   1926,   1713,   1499,   1285,   1072,    857,    643,    429,    214,
+  0,   -214,   -429,   -643,   -857,  -1072,  -1285,  -1499,  -1713,  -1926,
+  -2139,  -2351,  -2563,  -2775,  -2986,  -3196,  -3406,  -3616,  -3825,  -4033,
+  -4240,  -4447,  -4653,  -4859,  -5063,  -5266,  -5469,  -5671,  -5872,  -6071,
+  -6270,  -6467,  -6664,  -6859,  -7053,  -7246,  -7438,  -7629,  -7818,  -8006,
+  -8192,  -8377,  -8561,  -8743,  -8923,  -9102,  -9280,  -9456,  -9630,  -9803,
+  -9974, -10143, -10311, -10477, -10641, -10803, -10963, -11121, -11278, -11433,
+  -11585, -11736, -11885, -12031, -12176, -12318, -12458, -12597, -12733,
+  -12867, -12998, -13128, -13255, -13380, -13502, -13623, -13741, -13856,
+  -13970, -14081, -14189, -14295, -14399, -14500, -14598, -14694, -14788,
+  -14879, -14968, -15053, -15137, -15218, -15296, -15371, -15444, -15515,
+  -15582, -15647, -15709, -15769, -15826, -15880, -15931, -15980, -16026,
+  -16069, -16110, -16147, -16182, -16214, -16244, -16270, -16294, -16315,
+  -16333, -16349, -16362, -16371, -16378, -16383
+};
+
+/* Sine table 1 in Q14. */
+const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2] = {
+  0,   214,   429,   643,   857,  1072,  1285,  1499,  1713,  1926,
+  2139,  2351,  2563,  2775,  2986,  3196,  3406,  3616,  3825,  4033,
+  4240,  4447,  4653,  4859,  5063,  5266,  5469,  5671,  5872,  6071,
+  6270,  6467,  6664,  6859,  7053,  7246,  7438,  7629,  7818,  8006,
+  8192,  8377,  8561,  8743,  8923,  9102,  9280,  9456,  9630,  9803,
+  9974, 10143, 10311, 10477, 10641, 10803, 10963, 11121, 11278, 11433,
+  11585, 11736, 11885, 12031, 12176, 12318, 12458, 12597, 12733, 12867,
+  12998, 13128, 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081,
+  14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879, 14968, 15053,
+  15137, 15218, 15296, 15371, 15444, 15515, 15582, 15647, 15709, 15769,
+  15826, 15880, 15931, 15980, 16026, 16069, 16110, 16147, 16182, 16214,
+  16244, 16270, 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383,
+  16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315, 16294, 16270,
+  16244, 16214, 16182, 16147, 16110, 16069, 16026, 15980, 15931, 15880,
+  15826, 15769, 15709, 15647, 15582, 15515, 15444, 15371, 15296, 15218,
+  15137, 15053, 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295,
+  14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380, 13255, 13128,
+  12998, 12867, 12733, 12597, 12458, 12318, 12176, 12031, 11885, 11736,
+  11585, 11433, 11278, 11121, 10963, 10803, 10641, 10477, 10311, 10143,
+  9974,  9803,  9630,  9456,  9280,  9102,  8923,  8743,  8561,  8377,
+  8192,  8006,  7818,  7629,  7438,  7246,  7053,  6859,  6664,  6467,
+  6270,  6071,  5872,  5671,  5469,  5266,  5063,  4859,  4653,  4447,
+  4240,  4033,  3825,  3616,  3406,  3196,  2986,  2775,  2563,  2351,
+  2139,  1926,  1713,  1499,  1285,  1072,   857,   643,   429,   214
+};
+
+
+/* Sine table 2 in Q14. */
+const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4] = {
+  16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305, 16283, -16257,
+  16229, -16199, 16165, -16129, 16090, -16048, 16003, -15956, 15906, -15853,
+  15798, -15739, 15679, -15615, 15549, -15480, 15408, -15334, 15257, -15178,
+  15095, -15011, 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242,
+  14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318, 13192, -13063,
+  12933, -12800, 12665, -12528, 12389, -12247, 12104, -11958, 11810, -11661,
+  11509, -11356, 11200, -11042, 10883, -10722, 10559, -10394, 10227, -10059,
+  9889,  -9717,  9543,  -9368,  9191,  -9013,  8833,  -8652,  8469,  -8285,
+  8099,  -7912,  7723,  -7534,  7342,  -7150,  6957,  -6762,  6566,  -6369,
+  6171,  -5971,  5771,  -5570,  5368,  -5165,  4961,  -4756,  4550,  -4344,
+  4137,  -3929,  3720,  -3511,  3301,  -3091,  2880,  -2669,  2457,  -2245,
+  2032,  -1819,  1606,  -1392,  1179,   -965,   750,   -536,   322,   -107
+};
+
+#if defined(MIPS32_LE)
+/* Cosine table 2 in Q14. Used only on MIPS platforms. */
+const int16_t WebRtcIsacfix_kCosTab2[FRAMESAMPLES/4] = {
+  107,   -322,   536,   -750,   965,  -1179,  1392,  -1606,  1819,  -2032,
+  2245,  -2457,  2669,  -2880,  3091,  -3301,  3511,  -3720,  3929,  -4137,
+  4344,  -4550,  4756,  -4961,  5165,  -5368,  5570,  -5771,  5971,  -6171,
+  6369,  -6566,  6762,  -6957,  7150,  -7342,  7534,  -7723,  7912,  -8099,
+  8285,  -8469,  8652,  -8833,  9013,  -9191,  9368,  -9543,  9717,  -9889,
+  10059, -10227, 10394, -10559, 10722, -10883, 11042, -11200, 11356, -11509,
+  11661, -11810, 11958, -12104, 12247, -12389, 12528, -12665, 12800, -12933,
+  13063, -13192, 13318, -13441, 13563, -13682, 13799, -13913, 14025, -14135,
+  14242, -14347, 14449, -14549, 14647, -14741, 14834, -14924, 15011, -15095,
+  15178, -15257, 15334, -15408, 15480, -15549, 15615, -15679, 15739, -15798,
+  15853, -15906, 15956, -16003, 16048, -16090, 16129, -16165, 16199, -16229,
+  16257, -16283, 16305, -16325, 16342, -16356, 16367, -16375, 16381, -16384
+};
+#endif
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc
new file mode 100644
index 0000000..433ec53
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc
@@ -0,0 +1,199 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+static const int kSamples = FRAMESAMPLES / 2;
+static const int32_t spec2time_out_expected_1[kSamples] = {
+    -3366470, -2285227, -3415765,  -2310215, -3118030,  -2222470, -3030254,
+    -2192091, -3423170, -2216041,  -3305541, -2171936,  -3195767, -2095779,
+    -3153304, -2157560, -3071167,  -2032108, -3101190,  -1972016, -3103824,
+    -2089118, -3139811, -1898337,  -3102801, -2055082,  -3029665, -1854140,
+    -2962586, -1966454, -3071167,  -1894588, -2851743,  -1917315, -2848087,
+    -1594932, -2799242, -1462184,  -2845887, -1437599,  -2691776, -1329637,
+    -2770659, -1268491, -2625161,  -1578991, -2460299,  -1186385, -2365613,
+    -1039354, -2322608, -958518,   -2271749, -789860,   -2254538, -850308,
+    -2384436, -850959,  -2133734,  -587678,  -2093316,  -495115,  -1973364,
+    -475177,  -1801282, -173507,   -1848516, -158015,   -1792018, -62648,
+    -1643313, 214746,   -1500758,  267077,   -1450193,  560521,   -1521579,
+    675283,   -1345408, 857559,    -1300822, 1116332,   -1294533, 1241117,
+    -1070027, 1263503,  -983816,   1529821,  -1019586,  1910421,  -955420,
+    2073688,  -836459,  2401105,   -653905,  2690474,   -731425,  2930131,
+    -935234,  3299500,  -875978,   3523432,  -878906,   3924822,  -1081630,
+    4561267,  -1203023, 5105274,   -1510983, 6052762,   -2294646, 7021597,
+    -3108053, 8826736,  -4935222,  11678789, -8442713,  18725700, -21526692,
+    25420577, 19589811, -28108666, 12634054, -14483066, 6263217,  -9979706,
+    3665661,  -7909736, 2531530,   -6434896, 1700772,   -5525393, 1479473,
+    -4894262, 1231760,  -4353044,  1032940,  -3786590,  941152,   -3331614,
+    665090,   -2851619, 830696,    -2762201, 958007,    -2483118, 788233,
+    -2184965, 804825,   -1967306,  1007255,  -1862474,  920889,   -1457506,
+    755406,   -1405841, 890230,    -1302124, 1161599,   -701867,  1154163,
+    -1083366, 1204743,  -513581,   1547264,  -650636,   1493384,  -285543,
+    1771863,  -277906,  1841343,   -9078,    1751863,   230222,   1819578,
+    207170,   1978972,  398137,    2106468,  552155,    1997624,  685213,
+    2129520,  601078,   2238736,   944591,   2441879,   1194178,  2355280,
+    986124,   2393328,  1049005,   2417944,  1208368,   2489516,  1352023,
+    2572118,  1445283,  2856081,   1532997,  2742279,   1615877,  2915274,
+    1808036,  2856871,  1806936,   3241747,  1622461,   2978558,  1841297,
+    3010378,  1923666,  3271367,   2126700,  3070935,   1956958,  3107588,
+    2128405,  3288872,  2114911,   3315952,  2406651,   3344038,  2370199,
+    3368980,  2144361,  3305030,   2183803,  3401450,   2523102,  3405463,
+    2452475,  3463355,  2421678,   3551968,  2431949,   3477251,  2148125,
+    3244489,  2174090};
+static const int32_t spec2time_out_expected_2[kSamples] = {
+    1691694,   -2499988, -2035547,  1060469,   988634,    -2044502, -306271,
+    2041000,   201454,   -2289456,  93694,     2129427,   -369152,  -1887834,
+    860796,    2089102,  -929424,   -1673956,  1395291,   1785651,  -1619673,
+    -1380109,  1963449,  1093311,   -2111007,  -840456,   2372786,  578119,
+    -2242702,  89774,    2463304,   -132717,   -2121480,  643634,   2277636,
+    -1125999,  -1995858, 1543748,   2227861,   -1483779,  -1495491, 2102642,
+    1833876,   -1920568, -958378,   2485101,   772261,    -2454257, -24942,
+    2918714,   136838,   -2500453,  816118,    3039735,   -746560,  -2365815,
+    1586396,   2714951,  -1511696,  -1942334,  2571792,   2182827,  -2325335,
+    -1311543,  3055970,  1367220,   -2737182,  -110626,   3889222,  631008,
+    -3280879,  853066,   4122279,   -706638,   -3334449,  2148311,  3993512,
+    -1846301,  -3004894, 3426779,   3329522,   -3165264,  -2242423, 4756866,
+    2557711,   -4131280, -805259,   5702711,   1120592,   -4852821, 743664,
+    6476444,   -621186,  -5465828,  2815787,   6768835,   -3017442, -5338409,
+    5658126,   6838454,  -5492288,  -4682382,  8874947,   6153814,  -8832561,
+    -2649251,  12817398, 4237692,   -13000247, 1190661,   18986363, -115738,
+    -19693978, 9908367,  30660381,  -10632635, -37962068, 47022884, 89744622,
+    -42087632, 40279224, -88869341, -47542383, 38572364,  10441576, -30339718,
+    -9926740,  19896578, 28009,     -18886612, -1124047,  13232498, -4150304,
+    -12770551, 2637074,  9051831,   -6162211,  -8713972,  4557937,  5489716,
+    -6862312,  -5532349, 5415449,   2791310,   -6999367,  -2790102, 5375806,
+    546222,    -6486452, -821261,   4994973,   -1278840,  -5645501, 1060484,
+    3996285,   -2503954, -4653629,  2220549,   3036977,   -3282133, -3318585,
+    2780636,   1789880,  -4004589,  -2041031,  3105373,   574819,   -3992722,
+    -971004,   3001703,  -676739,   -3841508,  417284,    2897970,  -1427018,
+    -3058480,  1189948,  2210960,   -2268992,  -2603272,  1949785,  1576172,
+    -2720404,  -1891738, 2309456,   769178,    -2975646,  -707150,  2424652,
+    -88039,    -2966660, -65452,    2320780,   -957557,   -2798978, 744640,
+    1879794,   -1672081, -2365319,  1253309,   1366383,   -2204082, -1544367,
+    1801452,   613828,   -2531994,  -983847,   2064842,   118326,   -2613790,
+    -203220,   2219635,  -730341,   -2641861,  563557,    1765434,  -1329916,
+    -2272927,  1037138,  1266725,   -1939220,  -1588643,  1754528,  816552,
+    -2376303,  -1099167, 1864999,   122477,    -2422762,  -400027,  1889228,
+    -579916,   -2490353, 287139,    2011318,   -1176657,  -2502978, 812896,
+    1116502,   -1940211};
+static const int16_t time2spec_out_expected_1[kSamples] = {
+    20342, 23889, -10063, -9419, 3242,  7280,  -2012, -5029, 332,   4478,
+    -97,   -3244, -891,   3117,  773,   -2204, -1335, 2009,  1236,  -1469,
+    -1562, 1277,  1366,   -815,  -1619, 599,   1449,  -177,  -1507, 116,
+    1294,  263,   -1338,  -244,  1059,  553,   -1045, -549,  829,   826,
+    -731,  -755,  516,    909,   -427,  -853,  189,   1004,  -184,  -828,
+    -108,  888,   72,     -700,  -280,  717,   342,   -611,  -534,  601,
+    534,   -374,  -646,   399,   567,   -171,  -720,  234,   645,   -11,
+    -712,  -26,   593,    215,   -643,  -172,  536,   361,   -527,  -403,
+    388,   550,   -361,   -480,  208,   623,   -206,  -585,  41,    578,
+    12,    -504,  -182,   583,   218,   -437,  -339,  499,   263,   -354,
+    -450,  347,   456,    -193,  -524,  212,   475,   -74,   -566,  94,
+    511,   112,   -577,   -201,  408,   217,   -546,  -295,  338,   387,
+    -13,   4,     -46,    2,     -76,   103,   -83,   108,   -55,   100,
+    -150,  131,   -156,   141,   -171,  179,   -190,  128,   -227,  172,
+    -214,  215,   -189,   265,   -244,  322,   -335,  337,   -352,  358,
+    -368,  362,   -355,   366,   -381,  403,   -395,  411,   -392,  446,
+    -458,  504,   -449,   507,   -464,  452,   -491,  481,   -534,  486,
+    -516,  560,   -535,   525,   -537,  559,   -554,  570,   -616,  591,
+    -585,  627,   -509,   588,   -584,  547,   -610,  580,   -614,  635,
+    -620,  655,   -554,   546,   -591,  642,   -590,  660,   -656,  629,
+    -604,  620,   -580,   617,   -645,  648,   -573,  612,   -604,  584,
+    -571,  597,   -562,   627,   -550,  560,   -606,  529,   -584,  568,
+    -503,  532,   -463,   512,   -440,  399,   -457,  437,   -349,  278,
+    -317,  257,   -220,   163,   -8,    -61,   18,    -161,  367,   -1306};
+static const int16_t time2spec_out_expected_2[kSamples] = {
+    14283, -11552, -15335, 6626,  7554,  -2150, -6309, 1307,  4523,  -4,
+    -3908, -314,   3001,   914,   -2715, -1042, 2094,  1272,  -1715, -1399,
+    1263,  1508,   -1021,  -1534, 735,   1595,  -439,  -1447, 155,   1433,
+    22,    -1325,  -268,   1205,  424,   -1030, -608,  950,   643,   -733,
+    -787,  661,    861,    -502,  -888,  331,   852,   -144,  -849,  19,
+    833,   99,     -826,   -154,  771,   368,   -735,  -459,  645,   513,
+    -491,  -604,   431,    630,   -314,  -598,  183,   622,   -78,   -612,
+    -48,   641,    154,    -645,  -257,  610,   281,   -529,  -444,  450,
+    441,   -327,   -506,   274,   476,   -232,  -570,  117,   554,   -86,
+    -531,  -21,    572,    151,   -606,  -221,  496,   322,   -407,  -388,
+    407,   394,    -268,   -428,  280,   505,   -115,  -588,  19,    513,
+    -29,   -539,   -109,   468,   173,   -501,  -242,  442,   278,   -478,
+    -680,  656,    -659,   656,   -669,  602,   -688,  612,   -667,  612,
+    -642,  627,    -648,   653,   -676,  596,   -680,  655,   -649,  678,
+    -672,  587,    -608,   637,   -645,  637,   -620,  556,   -580,  553,
+    -635,  518,    -599,   583,   -501,  536,   -544,  473,   -552,  583,
+    -511,  541,    -532,   563,   -486,  461,   -453,  486,   -388,  424,
+    -416,  432,    -374,   399,   -462,  364,   -346,  293,   -329,  331,
+    -313,  281,    -247,   309,   -337,  241,   -190,  207,   -194,  179,
+    -163,  155,    -156,   117,   -135,  107,   -126,  29,    -22,   81,
+    -8,    17,     -61,    -10,   8,     -37,   80,    -44,   72,    -88,
+    65,    -89,    130,    -114,  181,   -215,  189,   -245,  260,   -288,
+    294,   -339,   344,    -396,  407,   -429,  438,   -439,  485,   -556,
+    629,   -612,   637,    -645,  661,   -737,  829,   -830,  831,   -1041};
+
+class TransformTest : public ::testing::Test {
+ protected:
+  // Pass a function pointer to the Tester function.
+  void Time2SpecTester(Time2Spec Time2SpecFunction) {
+    // WebRtcIsacfix_Time2Spec functions hard coded the buffer lengths. It's a
+    // large buffer but we have to test it here.
+    int16_t data_in_1[kSamples] = {0};
+    int16_t data_in_2[kSamples] = {0};
+    int16_t data_out_1[kSamples] = {0};
+    int16_t data_out_2[kSamples] = {0};
+
+    for (int i = 0; i < kSamples; i++) {
+      data_in_1[i] = i * i + 1777;
+      data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
+    }
+
+    Time2SpecFunction(data_in_1, data_in_2, data_out_1, data_out_2);
+
+    for (int i = 0; i < kSamples; i++) {
+      // We don't require bit-exact for ARM assembly code.
+      EXPECT_LE(abs(time2spec_out_expected_1[i] - data_out_1[i]), 1);
+      EXPECT_LE(abs(time2spec_out_expected_2[i] - data_out_2[i]), 1);
+    }
+  }
+
+  // Pass a function pointer to the Tester function.
+  void Spec2TimeTester(Spec2Time Spec2TimeFunction) {
+    // WebRtcIsacfix_Spec2Time functions hard coded the buffer lengths. It's a
+    // large buffer but we have to test it here.
+    int16_t data_in_1[kSamples] = {0};
+    int16_t data_in_2[kSamples] = {0};
+    int32_t data_out_1[kSamples] = {0};
+    int32_t data_out_2[kSamples] = {0};
+    for (int i = 0; i < kSamples; i++) {
+      data_in_1[i] = i * i + 1777;
+      data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
+    }
+
+    Spec2TimeFunction(data_in_1, data_in_2, data_out_1, data_out_2);
+
+    for (int i = 0; i < kSamples; i++) {
+      // We don't require bit-exact for ARM assembly code.
+      EXPECT_LE(abs(spec2time_out_expected_1[i] - data_out_1[i]), 16);
+      EXPECT_LE(abs(spec2time_out_expected_2[i] - data_out_2[i]), 16);
+    }
+  }
+};
+
+TEST_F(TransformTest, Time2SpecTest) {
+  Time2SpecTester(WebRtcIsacfix_Time2SpecC);
+#if defined(WEBRTC_HAS_NEON)
+  Time2SpecTester(WebRtcIsacfix_Time2SpecNeon);
+#endif
+}
+
+TEST_F(TransformTest, Spec2TimeTest) {
+  Spec2TimeTester(WebRtcIsacfix_Spec2TimeC);
+#if defined(WEBRTC_HAS_NEON)
+  Spec2TimeTester(WebRtcIsacfix_Spec2TimeNeon);
+#endif
+}
diff --git a/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc b/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
new file mode 100644
index 0000000..903ac64
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+#include "rtc_base/checks.h"
+
+using std::string;
+
+namespace webrtc {
+
+static const int kIsacBlockDurationMs = 30;
+static const int kIsacInputSamplingKhz = 16;
+static const int kIsacOutputSamplingKhz = 16;
+
+class IsacSpeedTest : public AudioCodecSpeedTest {
+ protected:
+  IsacSpeedTest();
+  void SetUp() override;
+  void TearDown() override;
+  float EncodeABlock(int16_t* in_data,
+                     uint8_t* bit_stream,
+                     size_t max_bytes,
+                     size_t* encoded_bytes) override;
+  float DecodeABlock(const uint8_t* bit_stream,
+                     size_t encoded_bytes,
+                     int16_t* out_data) override;
+  ISACFIX_MainStruct* ISACFIX_main_inst_;
+};
+
+IsacSpeedTest::IsacSpeedTest()
+    : AudioCodecSpeedTest(kIsacBlockDurationMs,
+                          kIsacInputSamplingKhz,
+                          kIsacOutputSamplingKhz),
+      ISACFIX_main_inst_(NULL) {}
+
+void IsacSpeedTest::SetUp() {
+  AudioCodecSpeedTest::SetUp();
+
+  // Check whether the allocated buffer for the bit stream is large enough.
+  EXPECT_GE(max_bytes_, static_cast<size_t>(STREAM_MAXW16_60MS));
+
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcIsacfix_Create(&ISACFIX_main_inst_));
+  EXPECT_EQ(0, WebRtcIsacfix_EncoderInit(ISACFIX_main_inst_, 1));
+  WebRtcIsacfix_DecoderInit(ISACFIX_main_inst_);
+  // Set bitrate and block length.
+  EXPECT_EQ(0, WebRtcIsacfix_Control(ISACFIX_main_inst_, bit_rate_,
+                                     block_duration_ms_));
+}
+
+void IsacSpeedTest::TearDown() {
+  AudioCodecSpeedTest::TearDown();
+  // Free memory.
+  EXPECT_EQ(0, WebRtcIsacfix_Free(ISACFIX_main_inst_));
+}
+
+float IsacSpeedTest::EncodeABlock(int16_t* in_data,
+                                  uint8_t* bit_stream,
+                                  size_t max_bytes,
+                                  size_t* encoded_bytes) {
+  // ISAC takes 10 ms everycall
+  const int subblocks = block_duration_ms_ / 10;
+  const int subblock_length = 10 * input_sampling_khz_;
+  int value = 0;
+
+  clock_t clocks = clock();
+  size_t pointer = 0;
+  for (int idx = 0; idx < subblocks; idx++, pointer += subblock_length) {
+    value =
+        WebRtcIsacfix_Encode(ISACFIX_main_inst_, &in_data[pointer], bit_stream);
+    if (idx == subblocks - 1)
+      EXPECT_GT(value, 0);
+    else
+      EXPECT_EQ(0, value);
+  }
+  clocks = clock() - clocks;
+  *encoded_bytes = static_cast<size_t>(value);
+  RTC_DCHECK_LE(*encoded_bytes, max_bytes);
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+float IsacSpeedTest::DecodeABlock(const uint8_t* bit_stream,
+                                  size_t encoded_bytes,
+                                  int16_t* out_data) {
+  int value;
+  int16_t audio_type;
+  clock_t clocks = clock();
+  value = WebRtcIsacfix_Decode(ISACFIX_main_inst_, bit_stream, encoded_bytes,
+                               out_data, &audio_type);
+  clocks = clock() - clocks;
+  EXPECT_EQ(output_length_sample_, static_cast<size_t>(value));
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+TEST_P(IsacSpeedTest, IsacEncodeDecodeTest) {
+  size_t kDurationSec = 400;  // Test audio length in second.
+  EncodeDecode(kDurationSec);
+}
+
+const coding_param param_set[] = {
+    std::make_tuple(1,
+                    32000,
+                    string("audio_coding/speech_mono_16kHz"),
+                    string("pcm"),
+                    true)};
+
+INSTANTIATE_TEST_SUITE_P(AllTest,
+                         IsacSpeedTest,
+                         ::testing::ValuesIn(param_set));
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc b/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc
new file mode 100644
index 0000000..cafca75
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc
@@ -0,0 +1,346 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <array>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_fix.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_fix.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
+#include "modules/audio_coding/test/PCMFile.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/strings/string_builder.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+namespace {
+
+constexpr int kPayloadType = 42;
+
+enum class IsacImpl { kFixed, kFloat };
+
+absl::string_view IsacImplToString(IsacImpl impl) {
+  switch (impl) {
+    case IsacImpl::kFixed:
+      return "fixed";
+    case IsacImpl::kFloat:
+      return "float";
+  }
+}
+
+std::unique_ptr<PCMFile> GetPcmTestFileReader(int sample_rate_hz) {
+  std::string filename;
+  switch (sample_rate_hz) {
+    case 16000:
+      filename = test::ResourcePath("audio_coding/testfile16kHz", "pcm");
+      break;
+    case 32000:
+      filename = test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+      break;
+    default:
+      RTC_DCHECK_NOTREACHED()
+          << "No test file available for " << sample_rate_hz << " Hz.";
+  }
+  auto pcm_file = std::make_unique<PCMFile>();
+  pcm_file->ReadStereo(false);
+  pcm_file->Open(filename, sample_rate_hz, "rb", /*auto_rewind=*/true);
+  pcm_file->FastForward(/*num_10ms_blocks=*/100);  // Skip initial silence.
+  RTC_CHECK(!pcm_file->EndOfFile());
+  return pcm_file;
+}
+
+// Returns a view to the interleaved samples of an AudioFrame object.
+rtc::ArrayView<const int16_t> AudioFrameToView(const AudioFrame& audio_frame) {
+  return {audio_frame.data(),
+          audio_frame.samples_per_channel() * audio_frame.num_channels()};
+}
+
+std::unique_ptr<AudioEncoder> CreateEncoder(IsacImpl impl,
+                                            int sample_rate_hz,
+                                            int frame_size_ms,
+                                            int bitrate_bps) {
+  RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+  RTC_CHECK(frame_size_ms == 30 || frame_size_ms == 60);
+  RTC_CHECK_GT(bitrate_bps, 0);
+  switch (impl) {
+    case IsacImpl::kFixed: {
+      AudioEncoderIsacFix::Config config;
+      config.bit_rate = bitrate_bps;
+      config.frame_size_ms = frame_size_ms;
+      RTC_CHECK_EQ(16000, sample_rate_hz);
+      return AudioEncoderIsacFix::MakeAudioEncoder(config, kPayloadType);
+    }
+    case IsacImpl::kFloat: {
+      AudioEncoderIsacFloat::Config config;
+      config.bit_rate = bitrate_bps;
+      config.frame_size_ms = frame_size_ms;
+      config.sample_rate_hz = sample_rate_hz;
+      return AudioEncoderIsacFloat::MakeAudioEncoder(config, kPayloadType);
+    }
+  }
+}
+
+std::unique_ptr<AudioDecoder> CreateDecoder(IsacImpl impl, int sample_rate_hz) {
+  RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+  switch (impl) {
+    case IsacImpl::kFixed: {
+      webrtc::AudioDecoderIsacFix::Config config;
+      RTC_CHECK_EQ(16000, sample_rate_hz);
+      return webrtc::AudioDecoderIsacFix::MakeAudioDecoder(config);
+    }
+    case IsacImpl::kFloat: {
+      webrtc::AudioDecoderIsacFloat::Config config;
+      config.sample_rate_hz = sample_rate_hz;
+      return webrtc::AudioDecoderIsacFloat::MakeAudioDecoder(config);
+    }
+  }
+}
+
+struct EncoderTestParams {
+  IsacImpl impl;
+  int sample_rate_hz;
+  int frame_size_ms;
+};
+
+class EncoderTest : public testing::TestWithParam<EncoderTestParams> {
+ protected:
+  EncoderTest() = default;
+  IsacImpl GetIsacImpl() const { return GetParam().impl; }
+  int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+  int GetFrameSizeMs() const { return GetParam().frame_size_ms; }
+};
+
+TEST_P(EncoderTest, TestConfig) {
+  for (int bitrate_bps : {10000, 21000, 32000}) {
+    SCOPED_TRACE(bitrate_bps);
+    auto encoder = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+                                 GetFrameSizeMs(), bitrate_bps);
+    EXPECT_EQ(GetSampleRateHz(), encoder->SampleRateHz());
+    EXPECT_EQ(size_t{1}, encoder->NumChannels());
+    EXPECT_EQ(bitrate_bps, encoder->GetTargetBitrate());
+  }
+}
+
+// Encodes an input audio sequence with a low and a high target bitrate and
+// checks that the number of produces bytes in the first case is less than that
+// of the second case.
+TEST_P(EncoderTest, TestDifferentBitrates) {
+  auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+  constexpr int kLowBps = 20000;
+  constexpr int kHighBps = 25000;
+  auto encoder_low = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+                                   GetFrameSizeMs(), kLowBps);
+  auto encoder_high = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+                                    GetFrameSizeMs(), kHighBps);
+  int num_bytes_low = 0;
+  int num_bytes_high = 0;
+  constexpr int kNumFrames = 12;
+  for (int i = 0; i < kNumFrames; ++i) {
+    AudioFrame in;
+    pcm_file->Read10MsData(in);
+    rtc::Buffer low, high;
+    encoder_low->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &low);
+    encoder_high->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &high);
+    num_bytes_low += low.size();
+    num_bytes_high += high.size();
+  }
+  EXPECT_LT(num_bytes_low, num_bytes_high);
+}
+
+// Encodes an input audio sequence first with a low, then with a high target
+// bitrate *using the same encoder* and checks that the number of emitted bytes
+// in the first case is less than in the second case.
+TEST_P(EncoderTest, TestDynamicBitrateChange) {
+  constexpr int kLowBps = 20000;
+  constexpr int kHighBps = 25000;
+  constexpr int kStartBps = 30000;
+  auto encoder = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+                               GetFrameSizeMs(), kStartBps);
+  std::map<int, int> num_bytes;
+  constexpr int kNumFrames = 200;  // 2 seconds.
+  for (int bitrate_bps : {kLowBps, kHighBps}) {
+    auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+    encoder->OnReceivedTargetAudioBitrate(bitrate_bps);
+    for (int i = 0; i < kNumFrames; ++i) {
+      AudioFrame in;
+      pcm_file->Read10MsData(in);
+      rtc::Buffer buf;
+      encoder->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &buf);
+      num_bytes[bitrate_bps] += buf.size();
+    }
+  }
+  // kHighBps / kLowBps == 1.25, so require the high-bitrate run to produce at
+  // least 1.195 times the number of bytes.
+  EXPECT_LT(1.195 * num_bytes[kLowBps], num_bytes[kHighBps]);
+}
+
+// Checks that, given a target bitrate, the encoder does not overshoot too much.
+TEST_P(EncoderTest, DoNotOvershootTargetBitrate) {
+  for (int bitrate_bps : {10000, 15000, 20000, 26000, 32000}) {
+    SCOPED_TRACE(bitrate_bps);
+    auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+    auto e = CreateEncoder(GetIsacImpl(), GetSampleRateHz(), GetFrameSizeMs(),
+                           bitrate_bps);
+    int num_bytes = 0;
+    constexpr int kNumFrames = 200;  // 2 seconds.
+    for (int i = 0; i < kNumFrames; ++i) {
+      AudioFrame in;
+      pcm_file->Read10MsData(in);
+      rtc::Buffer encoded;
+      e->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
+      num_bytes += encoded.size();
+    }
+    // Inverse of the duration of `kNumFrames` 10 ms frames (unit: seconds^-1).
+    constexpr float kAudioDurationInv = 100.f / kNumFrames;
+    const int measured_bitrate_bps = 8 * num_bytes * kAudioDurationInv;
+    EXPECT_LT(measured_bitrate_bps, bitrate_bps + 2250);  // Max 2250 bps extra.
+  }
+}
+
+// Creates tests for different encoder configurations and implementations.
+INSTANTIATE_TEST_SUITE_P(
+    IsacApiTest,
+    EncoderTest,
+    ::testing::ValuesIn([] {
+      std::vector<EncoderTestParams> cases;
+      for (IsacImpl impl : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+        for (int frame_size_ms : {30, 60}) {
+          cases.push_back({impl, 16000, frame_size_ms});
+        }
+      }
+      cases.push_back({IsacImpl::kFloat, 32000, 30});
+      return cases;
+    }()),
+    [](const ::testing::TestParamInfo<EncoderTestParams>& info) {
+      rtc::StringBuilder b;
+      const auto& p = info.param;
+      b << IsacImplToString(p.impl) << "_" << p.sample_rate_hz << "_"
+        << p.frame_size_ms;
+      return b.Release();
+    });
+
+struct DecoderTestParams {
+  IsacImpl impl;
+  int sample_rate_hz;
+};
+
+class DecoderTest : public testing::TestWithParam<DecoderTestParams> {
+ protected:
+  DecoderTest() = default;
+  IsacImpl GetIsacImpl() const { return GetParam().impl; }
+  int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+};
+
+TEST_P(DecoderTest, TestConfig) {
+  auto decoder = CreateDecoder(GetIsacImpl(), GetSampleRateHz());
+  EXPECT_EQ(GetSampleRateHz(), decoder->SampleRateHz());
+  EXPECT_EQ(size_t{1}, decoder->Channels());
+}
+
+// Creates tests for different decoder configurations and implementations.
+INSTANTIATE_TEST_SUITE_P(
+    IsacApiTest,
+    DecoderTest,
+    ::testing::ValuesIn({DecoderTestParams{IsacImpl::kFixed, 16000},
+                         DecoderTestParams{IsacImpl::kFloat, 16000},
+                         DecoderTestParams{IsacImpl::kFloat, 32000}}),
+    [](const ::testing::TestParamInfo<DecoderTestParams>& info) {
+      const auto& p = info.param;
+      return (rtc::StringBuilder()
+              << IsacImplToString(p.impl) << "_" << p.sample_rate_hz)
+          .Release();
+    });
+
+struct EncoderDecoderPairTestParams {
+  int sample_rate_hz;
+  int frame_size_ms;
+  IsacImpl encoder_impl;
+  IsacImpl decoder_impl;
+};
+
+class EncoderDecoderPairTest
+    : public testing::TestWithParam<EncoderDecoderPairTestParams> {
+ protected:
+  EncoderDecoderPairTest() = default;
+  int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+  int GetEncoderFrameSizeMs() const { return GetParam().frame_size_ms; }
+  IsacImpl GetEncoderIsacImpl() const { return GetParam().encoder_impl; }
+  IsacImpl GetDecoderIsacImpl() const { return GetParam().decoder_impl; }
+  int GetEncoderFrameSize() const {
+    return GetEncoderFrameSizeMs() * GetSampleRateHz() / 1000;
+  }
+};
+
+// Checks that the number of encoded and decoded samples match.
+TEST_P(EncoderDecoderPairTest, EncodeDecode) {
+  auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+  auto encoder = CreateEncoder(GetEncoderIsacImpl(), GetSampleRateHz(),
+                               GetEncoderFrameSizeMs(), /*bitrate_bps=*/20000);
+  auto decoder = CreateDecoder(GetDecoderIsacImpl(), GetSampleRateHz());
+  const int encoder_frame_size = GetEncoderFrameSize();
+  std::vector<int16_t> out(encoder_frame_size);
+  size_t num_encoded_samples = 0;
+  size_t num_decoded_samples = 0;
+  constexpr int kNumFrames = 12;
+  for (int i = 0; i < kNumFrames; ++i) {
+    AudioFrame in;
+    pcm_file->Read10MsData(in);
+    rtc::Buffer encoded;
+    encoder->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
+    num_encoded_samples += in.samples_per_channel();
+    if (encoded.empty()) {
+      continue;
+    }
+    // Decode.
+    const std::vector<AudioDecoder::ParseResult> parse_result =
+        decoder->ParsePayload(std::move(encoded), /*timestamp=*/0);
+    EXPECT_EQ(parse_result.size(), size_t{1});
+    auto decode_result = parse_result[0].frame->Decode(out);
+    EXPECT_TRUE(decode_result.has_value());
+    EXPECT_EQ(out.size(), decode_result->num_decoded_samples);
+    num_decoded_samples += decode_result->num_decoded_samples;
+  }
+  EXPECT_EQ(num_encoded_samples, num_decoded_samples);
+}
+
+// Creates tests for different encoder frame sizes and different
+// encoder/decoder implementations.
+INSTANTIATE_TEST_SUITE_P(
+    IsacApiTest,
+    EncoderDecoderPairTest,
+    ::testing::ValuesIn([] {
+      std::vector<EncoderDecoderPairTestParams> cases;
+      for (int frame_size_ms : {30, 60}) {
+        for (IsacImpl enc : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+          for (IsacImpl dec : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+            cases.push_back({16000, frame_size_ms, enc, dec});
+          }
+        }
+      }
+      cases.push_back({32000, 30, IsacImpl::kFloat, IsacImpl::kFloat});
+      return cases;
+    }()),
+    [](const ::testing::TestParamInfo<EncoderDecoderPairTestParams>& info) {
+      rtc::StringBuilder b;
+      const auto& p = info.param;
+      b << p.sample_rate_hz << "_" << p.frame_size_ms << "_"
+        << IsacImplToString(p.encoder_impl) << "_"
+        << IsacImplToString(p.decoder_impl);
+      return b.Release();
+    });
+
+}  // namespace
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h b/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h
new file mode 100644
index 0000000..fae2f3d
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
+
+namespace webrtc {
+
+using AudioDecoderIsacFloatImpl = AudioDecoderIsacT<IsacFloat>;
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
diff --git a/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h b/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h
new file mode 100644
index 0000000..dc32bcd
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
+
+namespace webrtc {
+
+using AudioEncoderIsacFloatImpl = AudioEncoderIsacT<IsacFloat>;
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
diff --git a/modules/audio_coding/codecs/isac/main/include/isac.h b/modules/audio_coding/codecs/isac/main/include/isac.h
new file mode 100644
index 0000000..3b05a8b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/include/isac.h
@@ -0,0 +1,617 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+
+typedef struct WebRtcISACStruct ISACStruct;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/******************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ *        - *ISAC_main_inst   : a pointer to the coder instance.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_Create(ISACStruct** ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ *        - ISAC_main_inst    : an ISAC instance.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_Free(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_EncoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - CodingMode        : 0 -> Bit rate and frame length are
+ *                                automatically adjusted to available bandwidth
+ *                                on transmission channel, just valid if codec
+ *                                is created to work in wideband mode.
+ *                              1 -> User sets a frame length and a target bit
+ *                                rate which is taken as the maximum
+ *                                short-term average bit rate.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_EncoderInit(ISACStruct* ISAC_main_inst, int16_t CodingMode);
+
+/******************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms audio blocks and inserts it into a package.
+ * Input speech length has 160 samples if operating at 16 kHz sampling
+ * rate, or 320 if operating at 32 kHz sampling rate. The encoder buffers the
+ * input audio until the whole frame is buffered then proceeds with encoding.
+ *
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - speechIn          : input speech vector.
+ *
+ * Output:
+ *        - encoded           : the encoded data vector
+ *
+ * Return value:
+ *                            : >0 - Length (in bytes) of coded data
+ *                            :  0 - The buffer didn't reach the chosen
+ *                               frame-size so it keeps buffering speech
+ *                               samples.
+ *                            : -1 - Error
+ */
+
+int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst,
+                      const int16_t* speechIn,
+                      uint8_t* encoded);
+
+/******************************************************************************
+ * WebRtcIsac_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ */
+
+void WebRtcIsac_DecoderInit(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - encoded           : encoded ISAC frame(s).
+ *        - packet_size       : size of the packet.
+ *        - rtp_seq_number    : the RTP number of the packet.
+ *        - send_ts           : the RTP send timestamp, given in samples
+ *        - arr_ts            : the arrival time of the packet (from NetEq)
+ *                              in samples.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_UpdateBwEstimate(ISACStruct* ISAC_main_inst,
+                                    const uint8_t* encoded,
+                                    size_t packet_size,
+                                    uint16_t rtp_seq_number,
+                                    uint32_t send_ts,
+                                    uint32_t arr_ts);
+
+/******************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes an ISAC frame. At 16 kHz sampling rate, the length
+ * of the output audio could be either 480 or 960 samples, equivalent to
+ * 30 or 60 ms respectively. At 32 kHz sampling rate, the length of the
+ * output audio is 960 samples, which is 30 ms.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - encoded           : encoded ISAC frame(s).
+ *        - len               : bytes in encoded vector.
+ *
+ * Output:
+ *        - decoded           : The decoded vector.
+ *
+ * Return value               : >0 - number of samples in decoded vector.
+ *                              -1 - Error.
+ */
+
+int WebRtcIsac_Decode(ISACStruct* ISAC_main_inst,
+                      const uint8_t* encoded,
+                      size_t len,
+                      int16_t* decoded,
+                      int16_t* speechType);
+
+/******************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of frames, i.e. multiples of 30 ms audio. Therefore,
+ * the output is multiple of 480 samples if operating at 16 kHz and multiple
+ * of 960 if operating at 32 kHz.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - noOfLostFrames    : Number of PLC frames to produce.
+ *
+ * Output:
+ *        - decoded           : The decoded vector.
+ *
+ * Return value               : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsac_DecodePlc(ISACStruct* ISAC_main_inst,
+                            int16_t* decoded,
+                            size_t noOfLostFrames);
+
+/******************************************************************************
+ * WebRtcIsac_Control(...)
+ *
+ * This function sets the limit on the short-term average bit-rate and the
+ * frame length. Should be used only in Instantaneous mode. At 16 kHz sampling
+ * rate, an average bit-rate between 10000 to 32000 bps is valid and a
+ * frame-size of 30 or 60 ms is acceptable. At 32 kHz, an average bit-rate
+ * between 10000 to 56000 is acceptable, and the valid frame-size is 30 ms.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - rate              : limit on the short-term average bit rate,
+ *                              in bits/second.
+ *        - framesize         : frame-size in millisecond.
+ *
+ * Return value               : 0  - ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_Control(ISACStruct* ISAC_main_inst,
+                           int32_t rate,
+                           int framesize);
+
+void WebRtcIsac_SetInitialBweBottleneck(ISACStruct* ISAC_main_inst,
+                                        int bottleneck_bits_per_second);
+
+/******************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Therefore, this API is not
+ * applicable if the codec is created to operate in super-wideband mode.
+ *
+ * Through this API, users can enforce a frame-size for all values of
+ * bottleneck. Then iSAC will not automatically change the frame-size.
+ *
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - rateBPS           : initial value of bottleneck in bits/second
+ *                              10000 <= rateBPS <= 56000 is accepted
+ *                              For default bottleneck set rateBPS = 0
+ *        - frameSizeMs       : number of milliseconds per frame (30 or 60)
+ *        - enforceFrameSize  : 1 to enforce the given frame-size through
+ *                              out the adaptation process, 0 to let iSAC
+ *                              change the frame-size if required.
+ *
+ * Return value               : 0  - ok
+ *                             -1 - Error
+ */
+
+int16_t WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst,
+                              int32_t rateBPS,
+                              int frameSizeMs,
+                              int16_t enforceFrameSize);
+
+/******************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ *        - encoded           : Encoded bit-stream
+ *
+ * Output:
+ *        - frameLength       : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst,
+                                const uint8_t* encoded,
+                                int16_t* frameLength);
+
+/******************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ *        - version      : Pointer to character string
+ *
+ */
+
+void WebRtcIsac_version(char* version);
+
+/******************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occurred in the
+ * specified instance.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance
+ *
+ * Return value               : Error code
+ */
+
+int16_t WebRtcIsac_GetErrorCode(ISACStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through in-band
+ * signalling retreived by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...). If
+ * xxx_control is never called the default values is returned. The default
+ * value for bottleneck at 16 kHz encoder sampling rate is 32000 bits/sec,
+ * and it is 56000 bits/sec for 32 kHz sampling rate.
+ * Note that the output is the iSAC internal operating bottleneck which might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Output:
+ *        - *bottleneck       : bottleneck in bits/sec
+ *
+ * Return value               : -1 if error happens
+ *                               0 bit-rates computed correctly.
+ */
+
+int16_t WebRtcIsac_GetUplinkBw(ISACStruct* ISAC_main_inst, int32_t* bottleneck);
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - maxPayloadBytes   : maximum size of the payload in bytes
+ *                              valid values are between 120 and 400 bytes
+ *                              if encoder sampling rate is 16 kHz. For
+ *                              32 kHz encoder sampling rate valid values
+ *                              are between 120 and 600 bytes.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if error happens
+ */
+
+int16_t WebRtcIsac_SetMaxPayloadSize(ISACStruct* ISAC_main_inst,
+                                     int16_t maxPayloadBytes);
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - maxRate           : maximum rate in bits per second,
+ *                              valid values are 32000 to 53400 bits/sec in
+ *                              wideband mode, and 32000 to 160000 bits/sec in
+ *                              super-wideband mode.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if error happens
+ */
+
+int16_t WebRtcIsac_SetMaxRate(ISACStruct* ISAC_main_inst, int32_t maxRate);
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Return value               : sampling frequency in Hertz.
+ *
+ */
+
+uint16_t WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Return value               : sampling rate in Hertz.
+ *
+ */
+
+uint16_t WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * Set the sampling rate of the decoder.  Initialization of the decoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - sampRate          : sampling rate in Hertz.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if failed.
+ */
+
+int16_t WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
+                                  uint16_t samp_rate_hz);
+
+/******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * Set the sampling rate of the encoder. Initialization of the encoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created. The encoding-mode and the
+ * bottleneck remain unchanged by this call, however, the maximum rate and
+ * maximum payload-size will reset to their default value.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - sampRate          : sampling rate in Hertz.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if failed.
+ */
+
+int16_t WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
+                                  uint16_t sample_rate_hz);
+
+/******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 2! Currently not implemented for SWB mode.
+ * NOTE 3! Rates larger than the bottleneck of the codec will be limited
+ *         to the current bottleneck.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - bweIndex          : Index of bandwidth estimate to put in new
+ *                              bitstream
+ *        - rate              : target rate of the transcoder is bits/sec.
+ *                              Valid values are the accepted rate in iSAC,
+ *                              i.e. 10000 to 56000.
+ *        - isRCU                       : if the new bit-stream is an RCU
+ * stream. Note that the rate parameter always indicates the target rate of the
+ * main payload, regardless of 'isRCU' value.
+ *
+ * Output:
+ *        - encoded           : The encoded data vector
+ *
+ * Return value               : >0 - Length (in bytes) of coded data
+ *                              -1 - Error  or called in SWB mode
+ *                                 NOTE! No error code is written to
+ *                                 the struct since it is only allowed to read
+ *                                 the struct.
+ */
+int16_t WebRtcIsac_GetNewBitStream(ISACStruct* ISAC_main_inst,
+                                   int16_t bweIndex,
+                                   int16_t jitterInfo,
+                                   int32_t rate,
+                                   uint8_t* encoded,
+                                   int16_t isRCU);
+
+/****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC struct
+ *
+ * Output:
+ *        - bweIndex          : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsac_GetDownLinkBwIndex(ISACStruct* ISAC_main_inst,
+                                      int16_t* bweIndex,
+                                      int16_t* jitterInfo);
+
+/****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC struct
+ *        - bweIndex          : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsac_UpdateUplinkBw(ISACStruct* ISAC_main_inst, int16_t bweIndex);
+
+/****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ *        - encoded           : Encoded bitstream
+ *
+ * Output:
+ *        - frameLength       : Length of frame in packet (in samples)
+ *        - bweIndex         : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsac_ReadBwIndex(const uint8_t* encoded, int16_t* bweIndex);
+
+/*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * returns the frame lenght (in samples) of the next packet. In the case of
+ * channel-adaptive mode, iSAC decides on its frame lenght based on the
+ * estimated bottleneck this allows a user to prepare for the next packet (at
+ * the encoder)
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ *        - ISAC_main_inst     : iSAC struct
+ *
+ * Return Value                : frame lenght in samples
+ *
+ */
+
+int16_t WebRtcIsac_GetNewFrameLen(ISACStruct* ISAC_main_inst);
+
+/****************************************************************************
+ *  WebRtcIsac_GetRedPayload(...)
+ *
+ *  Populates "encoded" with the redundant payload of the recently encoded
+ *  frame. This function has to be called once that WebRtcIsac_Encode(...)
+ *  returns a positive value. Regardless of the frame-size this function will
+ *  be called only once after encoding is completed.
+ *
+ * Input:
+ *      - ISAC_main_inst    : iSAC struct
+ *
+ * Output:
+ *        - encoded            : the encoded data vector
+ *
+ *
+ * Return value:
+ *                              : >0 - Length (in bytes) of coded data
+ *                              : -1 - Error
+ *
+ *
+ */
+int16_t WebRtcIsac_GetRedPayload(ISACStruct* ISAC_main_inst, uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload i case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ *      - ISAC_main_inst     : ISAC instance.
+ *      - encoded            : encoded ISAC RCU frame(s)
+ *      - len                : bytes in encoded vector
+ *
+ * Output:
+ *      - decoded            : The decoded vector
+ *
+ * Return value              : >0 - number of samples in decoded vector
+ *                             -1 - Error
+ */
+int WebRtcIsac_DecodeRcu(ISACStruct* ISAC_main_inst,
+                         const uint8_t* encoded,
+                         size_t len,
+                         int16_t* decoded,
+                         int16_t* speechType);
+
+/* If `inst` is a decoder but not an encoder: tell it what sample rate the
+   encoder is using, for bandwidth estimation purposes. */
+void WebRtcIsac_SetEncSampRateInDecoder(ISACStruct* inst, int sample_rate_hz);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/arith_routines.c b/modules/audio_coding/codecs/isac/main/source/arith_routines.c
new file mode 100644
index 0000000..9d5c693
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/arith_routines.c
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+
+/*
+ * terminate and return byte stream;
+ * returns the number of bytes in the stream
+ */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata) /* in-/output struct containing bitstream */
+{
+  uint8_t *stream_ptr;
+
+
+  /* point to the right place in the stream buffer */
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+
+  /* find minimum length (determined by current interval width) */
+  if ( streamdata->W_upper > 0x01FFFFFF )
+  {
+    streamdata->streamval += 0x01000000;
+    /* add carry to buffer */
+    if (streamdata->streamval < 0x01000000)
+    {
+      /* propagate carry */
+      while ( !(++(*--stream_ptr)) );
+      /* put pointer back to the old value */
+      stream_ptr = streamdata->stream + streamdata->stream_index;
+    }
+    /* write remaining data to bitstream */
+    *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+  }
+  else
+  {
+    streamdata->streamval += 0x00010000;
+    /* add carry to buffer */
+    if (streamdata->streamval < 0x00010000)
+    {
+      /* propagate carry */
+      while ( !(++(*--stream_ptr)) );
+      /* put pointer back to the old value */
+      stream_ptr = streamdata->stream + streamdata->stream_index;
+    }
+    /* write remaining data to bitstream */
+    *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+    *stream_ptr++ = (uint8_t) ((streamdata->streamval >> 16) & 0x00FF);
+  }
+
+  /* calculate stream length */
+  return (int)(stream_ptr - streamdata->stream);
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/arith_routines.h b/modules/audio_coding/codecs/isac/main/source/arith_routines.h
new file mode 100644
index 0000000..3f9f6de
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/arith_routines.h
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+int WebRtcIsac_EncLogisticMulti2(
+    Bitstr* streamdata, /* in-/output struct containing bitstream */
+    int16_t* dataQ7,    /* input: data vector */
+    const uint16_t*
+        env, /* input: side info vector defining the width of the pdf */
+    int N,   /* input: data vector length */
+    int16_t isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+/* returns the number of bytes in the stream */
+int WebRtcIsac_EncTerminate(
+    Bitstr* streamdata); /* in-/output struct containing bitstream */
+
+/* returns the number of bytes in the stream so far */
+int WebRtcIsac_DecLogisticMulti2(
+    int16_t* data,      /* output: data vector */
+    Bitstr* streamdata, /* in-/output struct containing bitstream */
+    const uint16_t*
+        env, /* input: side info vector defining the width of the pdf */
+    const int16_t* dither, /* input: dither vector */
+    int N,                 /* input: data vector length */
+    int16_t isSWB12kHz);   /* if the codec is working in 12kHz bandwidth */
+
+void WebRtcIsac_EncHistMulti(
+    Bitstr* streamdata,         /* in-/output struct containing bitstream */
+    const int* data,            /* input: data vector */
+    const uint16_t* const* cdf, /* input: array of cdf arrays */
+    int N);                     /* input: data vector length */
+
+int WebRtcIsac_DecHistBisectMulti(
+    int* data,                  /* output: data vector */
+    Bitstr* streamdata,         /* in-/output struct containing bitstream */
+    const uint16_t* const* cdf, /* input: array of cdf arrays */
+    const uint16_t*
+        cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+    int N);       /* input: data vector length */
+
+int WebRtcIsac_DecHistOneStepMulti(
+    int* data,                  /* output: data vector */
+    Bitstr* streamdata,         /* in-/output struct containing bitstream */
+    const uint16_t* const* cdf, /* input: array of cdf arrays */
+    const uint16_t*
+        init_index, /* input: vector of initial cdf table search entries */
+    int N);         /* input: data vector length */
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c b/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
new file mode 100644
index 0000000..e948979
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
@@ -0,0 +1,291 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+
+
+/*
+ * code symbols into arithmetic bytestream
+ */
+void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
+                             const int *data,  /* input: data vector */
+                             const uint16_t *const *cdf, /* input: array of cdf arrays */
+                             const int N)   /* input: data vector length */
+{
+  uint32_t W_lower, W_upper;
+  uint32_t W_upper_LSB, W_upper_MSB;
+  uint8_t *stream_ptr;
+  uint8_t *stream_ptr_carry;
+  uint32_t cdf_lo, cdf_hi;
+  int k;
+
+
+  /* point to beginning of stream buffer */
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+  W_upper = streamdata->W_upper;
+
+  for (k=N; k>0; k--)
+  {
+    /* fetch cdf_lower and cdf_upper from cdf tables */
+    cdf_lo = (uint32_t) *(*cdf + *data);
+    cdf_hi = (uint32_t) *(*cdf++ + *data++ + 1);
+
+    /* update interval */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+    W_lower = W_upper_MSB * cdf_lo;
+    W_lower += (W_upper_LSB * cdf_lo) >> 16;
+    W_upper = W_upper_MSB * cdf_hi;
+    W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+    /* shift interval such that it begins at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamdata->streamval += W_lower;
+
+    /* handle carry */
+    if (streamdata->streamval < W_lower)
+    {
+      /* propagate carry */
+      stream_ptr_carry = stream_ptr;
+      while (!(++(*--stream_ptr_carry)));
+    }
+
+    /* renormalize interval, store most significant byte of streamval and update streamval */
+    while ( !(W_upper & 0xFF000000) )      /* W_upper < 2^24 */
+    {
+      W_upper <<= 8;
+      *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+      streamdata->streamval <<= 8;
+    }
+  }
+
+  /* calculate new stream_index */
+  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+  streamdata->W_upper = W_upper;
+
+  return;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, using method of bisection
+ * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
+ */
+int WebRtcIsac_DecHistBisectMulti(int *data,     /* output: data vector */
+                                  Bitstr *streamdata,   /* in-/output struct containing bitstream */
+                                  const uint16_t *const *cdf,  /* input: array of cdf arrays */
+                                  const uint16_t *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+                                  const int N)    /* input: data vector length */
+{
+  uint32_t    W_lower, W_upper;
+  uint32_t    W_tmp;
+  uint32_t    W_upper_LSB, W_upper_MSB;
+  uint32_t    streamval;
+  const   uint8_t *stream_ptr;
+  const   uint16_t *cdf_ptr;
+  int     size_tmp;
+  int     k;
+
+  W_lower = 0; //to remove warning -DH
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+  W_upper = streamdata->W_upper;
+  if (W_upper == 0)
+    /* Should not be possible in normal operation */
+    return -2;
+
+  if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */
+  {
+    /* read first word from bytestream */
+    streamval = *stream_ptr << 24;
+    streamval |= *++stream_ptr << 16;
+    streamval |= *++stream_ptr << 8;
+    streamval |= *++stream_ptr;
+  } else {
+    streamval = streamdata->streamval;
+  }
+
+  for (k=N; k>0; k--)
+  {
+    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+
+    /* start halfway the cdf range */
+    size_tmp = *cdf_size++ >> 1;
+    cdf_ptr = *cdf + (size_tmp - 1);
+
+    /* method of bisection */
+    for ( ;; )
+    {
+      W_tmp = W_upper_MSB * *cdf_ptr;
+      W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+      size_tmp >>= 1;
+      if (size_tmp == 0) break;
+      if (streamval > W_tmp)
+      {
+        W_lower = W_tmp;
+        cdf_ptr += size_tmp;
+      } else {
+        W_upper = W_tmp;
+        cdf_ptr -= size_tmp;
+      }
+    }
+    if (streamval > W_tmp)
+    {
+      W_lower = W_tmp;
+      *data++ = (int)(cdf_ptr - *cdf++);
+    } else {
+      W_upper = W_tmp;
+      *data++ = (int)(cdf_ptr - *cdf++ - 1);
+    }
+
+    /* shift interval to start at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamval -= W_lower;
+
+    /* renormalize interval and update streamval */
+    while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */
+    {
+      /* read next byte from stream */
+      streamval = (streamval << 8) | *++stream_ptr;
+      W_upper <<= 8;
+    }
+
+    if (W_upper == 0)
+      /* Should not be possible in normal operation */
+      return -2;
+
+
+  }
+
+  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+  streamdata->W_upper = W_upper;
+  streamdata->streamval = streamval;
+
+
+  /* find number of bytes in original stream (determined by current interval width) */
+  if ( W_upper > 0x01FFFFFF )
+    return streamdata->stream_index - 2;
+  else
+    return streamdata->stream_index - 1;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, taking single step up or
+ * down at a time
+ * cdf tables can be of arbitrary size, but large tables may take a lot of iterations
+ */
+int WebRtcIsac_DecHistOneStepMulti(int *data,        /* output: data vector */
+                                   Bitstr *streamdata,      /* in-/output struct containing bitstream */
+                                   const uint16_t *const *cdf,   /* input: array of cdf arrays */
+                                   const uint16_t *init_index, /* input: vector of initial cdf table search entries */
+                                   const int N)     /* input: data vector length */
+{
+  uint32_t    W_lower, W_upper;
+  uint32_t    W_tmp;
+  uint32_t    W_upper_LSB, W_upper_MSB;
+  uint32_t    streamval;
+  const   uint8_t *stream_ptr;
+  const   uint16_t *cdf_ptr;
+  int     k;
+
+
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+  W_upper = streamdata->W_upper;
+  if (W_upper == 0)
+    /* Should not be possible in normal operation */
+    return -2;
+
+  if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */
+  {
+    /* read first word from bytestream */
+    streamval = (uint32_t)(*stream_ptr) << 24;
+    streamval |= (uint32_t)(*++stream_ptr) << 16;
+    streamval |= (uint32_t)(*++stream_ptr) << 8;
+    streamval |= (uint32_t)(*++stream_ptr);
+  } else {
+    streamval = streamdata->streamval;
+  }
+
+
+  for (k=N; k>0; k--)
+  {
+    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+
+    /* start at the specified table entry */
+    cdf_ptr = *cdf + (*init_index++);
+    W_tmp = W_upper_MSB * *cdf_ptr;
+    W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+    if (streamval > W_tmp)
+    {
+      for ( ;; )
+      {
+        W_lower = W_tmp;
+        if (cdf_ptr[0]==65535)
+          /* range check */
+          return -3;
+        W_tmp = W_upper_MSB * *++cdf_ptr;
+        W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+        if (streamval <= W_tmp) break;
+      }
+      W_upper = W_tmp;
+      *data++ = (int)(cdf_ptr - *cdf++ - 1);
+    } else {
+      for ( ;; )
+      {
+        W_upper = W_tmp;
+        --cdf_ptr;
+        if (cdf_ptr<*cdf) {
+          /* range check */
+          return -3;
+        }
+        W_tmp = W_upper_MSB * *cdf_ptr;
+        W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+        if (streamval > W_tmp) break;
+      }
+      W_lower = W_tmp;
+      *data++ = (int)(cdf_ptr - *cdf++);
+    }
+
+    /* shift interval to start at zero */
+    W_upper -= ++W_lower;
+    /* add integer to bitstream */
+    streamval -= W_lower;
+
+    /* renormalize interval and update streamval */
+    while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */
+    {
+      /* read next byte from stream */
+      streamval = (streamval << 8) | *++stream_ptr;
+      W_upper <<= 8;
+    }
+  }
+
+  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+  streamdata->W_upper = W_upper;
+  streamdata->streamval = streamval;
+
+
+  /* find number of bytes in original stream (determined by current interval width) */
+  if ( W_upper > 0x01FFFFFF )
+    return streamdata->stream_index - 2;
+  else
+    return streamdata->stream_index - 1;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c b/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
new file mode 100644
index 0000000..777780f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
@@ -0,0 +1,303 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * This file contains functions for arithmatically encoding and
+ * decoding DFT coefficients.
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+
+
+
+static const int32_t kHistEdgesQ15[51] = {
+  -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+  -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
+  -65536, -52429, -39322, -26215, -13108,  0,  13107,  26214,  39321,  52428,
+  65536,  78643,  91750,  104857,  117964,  131072,  144179,  157286,  170393,  183500,
+  196608,  209715,  222822,  235929,  249036,  262144,  275251,  288358,  301465,  314572,
+  327680};
+
+
+static const int kCdfSlopeQ0[51] = {  /* Q0 */
+  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+  5,  5,  13,  23,  47,  87,  154,  315,  700,  1088,
+  2471,  6064,  14221,  21463,  36634,  36924,  19750,  13270,  5806,  2312,
+  1095,  660,  316,  145,  86,  41,  32,  5,  5,  5,
+  5,  5,  5,  5,  5,  5,  5,  5,  5,  2, 0};
+
+
+static const int kCdfQ16[51] = {  /* Q16 */
+  0,  2,  4,  6,  8,  10,  12,  14,  16,  18,
+  20,  22,  24,  29,  38,  57,  92,  153,  279,  559,
+  994,  1983,  4408,  10097,  18682,  33336,  48105,  56005,  61313,  63636,
+  64560,  64998,  65262,  65389,  65447,  65481,  65497,  65510,  65512,  65514,
+  65516,  65518,  65520,  65522,  65524,  65526,  65528,  65530,  65532,  65534,
+  65535};
+
+
+
+/* function to be converted to fixed point */
+static __inline uint32_t piecewise(int32_t xinQ15) {
+
+  int32_t ind, qtmp1, qtmp2, qtmp3;
+  uint32_t tmpUW32;
+
+
+  qtmp2 = xinQ15;
+
+  if (qtmp2 < kHistEdgesQ15[0]) {
+    qtmp2 = kHistEdgesQ15[0];
+  }
+  if (qtmp2 > kHistEdgesQ15[50]) {
+    qtmp2 = kHistEdgesQ15[50];
+  }
+
+  qtmp1 = qtmp2 - kHistEdgesQ15[0];       /* Q15 - Q15 = Q15        */
+  ind = (qtmp1 * 5) >> 16;              /* 2^16 / 5 = 0.4 in Q15  */
+  /* Q15 -> Q0              */
+  qtmp1 = qtmp2 - kHistEdgesQ15[ind];     /* Q15 - Q15 = Q15        */
+  qtmp2 = kCdfSlopeQ0[ind] * qtmp1;      /* Q0 * Q15 = Q15         */
+  qtmp3 = qtmp2>>15;                    /* Q15 -> Q0              */
+
+  tmpUW32 = kCdfQ16[ind] + qtmp3;    /* Q0 + Q0 = Q0           */
+  return tmpUW32;
+}
+
+
+
+int WebRtcIsac_EncLogisticMulti2(
+    Bitstr *streamdata,      /* in-/output struct containing bitstream */
+    int16_t *dataQ7,    /* input: data vector */
+    const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
+    const int N,       /* input: data vector length / 2 */
+    const int16_t isSWB12kHz)
+{
+  uint32_t W_lower, W_upper;
+  uint32_t W_upper_LSB, W_upper_MSB;
+  uint8_t *stream_ptr;
+  uint8_t *maxStreamPtr;
+  uint8_t *stream_ptr_carry;
+  uint32_t cdf_lo, cdf_hi;
+  int k;
+
+  /* point to beginning of stream buffer */
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+  W_upper = streamdata->W_upper;
+
+  maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1;
+  for (k = 0; k < N; k++)
+  {
+    /* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */
+    cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+    cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+
+    /* test and clip if probability gets too small */
+    while (cdf_lo+1 >= cdf_hi) {
+      /* clip */
+      if (*dataQ7 > 0) {
+        *dataQ7 -= 128;
+        cdf_hi = cdf_lo;
+        cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+      } else {
+        *dataQ7 += 128;
+        cdf_lo = cdf_hi;
+        cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+      }
+    }
+
+    dataQ7++;
+    // increment only once per 4 iterations for SWB-16kHz or WB
+    // increment only once per 2 iterations for SWB-12kHz
+    envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+
+    /* update interval */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+    W_lower = W_upper_MSB * cdf_lo;
+    W_lower += (W_upper_LSB * cdf_lo) >> 16;
+    W_upper = W_upper_MSB * cdf_hi;
+    W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+    /* shift interval such that it begins at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamdata->streamval += W_lower;
+
+    /* handle carry */
+    if (streamdata->streamval < W_lower)
+    {
+      /* propagate carry */
+      stream_ptr_carry = stream_ptr;
+      while (!(++(*--stream_ptr_carry)));
+    }
+
+    /* renormalize interval, store most significant byte of streamval and update streamval */
+    while ( !(W_upper & 0xFF000000) )      /* W_upper < 2^24 */
+    {
+      W_upper <<= 8;
+      *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+
+      if(stream_ptr > maxStreamPtr)
+      {
+        return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+      }
+      streamdata->streamval <<= 8;
+    }
+  }
+
+  /* calculate new stream_index */
+  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+  streamdata->W_upper = W_upper;
+
+  return 0;
+}
+
+
+
+int WebRtcIsac_DecLogisticMulti2(
+    int16_t *dataQ7,       /* output: data vector */
+    Bitstr *streamdata,      /* in-/output struct containing bitstream */
+    const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
+    const int16_t *ditherQ7,/* input: dither vector */
+    const int N,         /* input: data vector length */
+    const int16_t isSWB12kHz)
+{
+  uint32_t    W_lower, W_upper;
+  uint32_t    W_tmp;
+  uint32_t    W_upper_LSB, W_upper_MSB;
+  uint32_t    streamval;
+  const uint8_t *stream_ptr;
+  uint32_t    cdf_tmp;
+  int16_t     candQ7;
+  int             k;
+
+  // Position just past the end of the stream. STREAM_SIZE_MAX_60 instead of
+  // STREAM_SIZE_MAX (which is the size of the allocated buffer) because that's
+  // the limit to how much data is filled in.
+  const uint8_t* const stream_end = streamdata->stream + STREAM_SIZE_MAX_60;
+
+  stream_ptr = streamdata->stream + streamdata->stream_index;
+  W_upper = streamdata->W_upper;
+  if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */
+  {
+    /* read first word from bytestream */
+    if (stream_ptr + 3 >= stream_end)
+      return -1;  // Would read out of bounds. Malformed input?
+    streamval = *stream_ptr << 24;
+    streamval |= *++stream_ptr << 16;
+    streamval |= *++stream_ptr << 8;
+    streamval |= *++stream_ptr;
+  } else {
+    streamval = streamdata->streamval;
+  }
+
+
+  for (k = 0; k < N; k++)
+  {
+    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+    W_upper_LSB = W_upper & 0x0000FFFF;
+    W_upper_MSB = W_upper >> 16;
+
+    /* find first candidate by inverting the logistic cdf */
+    candQ7 = - *ditherQ7 + 64;
+    cdf_tmp = piecewise(candQ7 * *envQ8);
+
+    W_tmp = W_upper_MSB * cdf_tmp;
+    W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+    if (streamval > W_tmp)
+    {
+      W_lower = W_tmp;
+      candQ7 += 128;
+      cdf_tmp = piecewise(candQ7 * *envQ8);
+
+      W_tmp = W_upper_MSB * cdf_tmp;
+      W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+      while (streamval > W_tmp)
+      {
+        W_lower = W_tmp;
+        candQ7 += 128;
+        cdf_tmp = piecewise(candQ7 * *envQ8);
+
+        W_tmp = W_upper_MSB * cdf_tmp;
+        W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+        /* error check */
+        if (W_lower == W_tmp) return -1;
+      }
+      W_upper = W_tmp;
+
+      /* another sample decoded */
+      *dataQ7 = candQ7 - 64;
+    }
+    else
+    {
+      W_upper = W_tmp;
+      candQ7 -= 128;
+      cdf_tmp = piecewise(candQ7 * *envQ8);
+
+      W_tmp = W_upper_MSB * cdf_tmp;
+      W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+      while ( !(streamval > W_tmp) )
+      {
+        W_upper = W_tmp;
+        candQ7 -= 128;
+        cdf_tmp = piecewise(candQ7 * *envQ8);
+
+        W_tmp = W_upper_MSB * cdf_tmp;
+        W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+        /* error check */
+        if (W_upper == W_tmp) return -1;
+      }
+      W_lower = W_tmp;
+
+      /* another sample decoded */
+      *dataQ7 = candQ7 + 64;
+    }
+    ditherQ7++;
+    dataQ7++;
+    // increment only once per 4 iterations for SWB-16kHz or WB
+    // increment only once per 2 iterations for SWB-12kHz
+    envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+    /* shift interval to start at zero */
+    W_upper -= ++W_lower;
+
+    /* add integer to bitstream */
+    streamval -= W_lower;
+
+    /* renormalize interval and update streamval */
+    while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */
+    {
+      /* read next byte from stream */
+      if (stream_ptr + 1 >= stream_end)
+        return -1;  // Would read out of bounds. Malformed input?
+      streamval = (streamval << 8) | *++stream_ptr;
+      W_upper <<= 8;
+    }
+  }
+
+  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+  streamdata->W_upper = W_upper;
+  streamdata->streamval = streamval;
+
+  /* find number of bytes in original stream (determined by current interval width) */
+  if ( W_upper > 0x01FFFFFF )
+    return streamdata->stream_index - 2;
+  else
+    return streamdata->stream_index - 1;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc b/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc
new file mode 100644
index 0000000..b671002
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioDecoderIsacT<IsacFloat>;
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc b/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
new file mode 100644
index 0000000..b7f2c0b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioEncoderIsacT<IsacFloat>;
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc b/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc
new file mode 100644
index 0000000..07bab05
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+
+#include <limits>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+void TestBadConfig(const AudioEncoderIsacFloatImpl::Config& config) {
+  EXPECT_FALSE(config.IsOk());
+}
+
+void TestGoodConfig(const AudioEncoderIsacFloatImpl::Config& config) {
+  EXPECT_TRUE(config.IsOk());
+  AudioEncoderIsacFloatImpl aei(config);
+}
+
+// Wrap subroutine calls that test things in this, so that the error messages
+// will be accompanied by stack traces that make it possible to tell which
+// subroutine invocation caused the failure.
+#define S(x)          \
+  do {                \
+    SCOPED_TRACE(#x); \
+    x;                \
+  } while (0)
+
+}  // namespace
+
+TEST(AudioEncoderIsacTest, TestConfigBitrate) {
+  AudioEncoderIsacFloatImpl::Config config;
+
+  // The default value is some real, positive value.
+  EXPECT_GT(config.bit_rate, 1);
+  S(TestGoodConfig(config));
+
+  // 0 is another way to ask for the default value.
+  config.bit_rate = 0;
+  S(TestGoodConfig(config));
+
+  // Try some unreasonable values and watch them fail.
+  config.bit_rate = -1;
+  S(TestBadConfig(config));
+  config.bit_rate = 1;
+  S(TestBadConfig(config));
+  config.bit_rate = std::numeric_limits<int>::max();
+  S(TestBadConfig(config));
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c b/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
new file mode 100644
index 0000000..486cd95
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
@@ -0,0 +1,1013 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * BwEstimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "rtc_base/checks.h"
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const float kQRateTableWb[12] =
+{
+  10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+  18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f};
+
+
+static const float kQRateTableSwb[24] =
+{
+  10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+  18859.8f, 20963.3f, 23153.1f, 25342.9f, 27532.7f, 29722.5f,
+  31912.3f, 34102.1f, 36291.9f, 38481.7f, 40671.4f, 42861.2f,
+  45051.0f, 47240.8f, 49430.6f, 51620.4f, 53810.2f, 56000.0f,
+};
+
+
+
+
+int32_t WebRtcIsac_InitBandwidthEstimator(
+    BwEstimatorstr*              bwest_str,
+    enum IsacSamplingRate encoderSampRate,
+    enum IsacSamplingRate decoderSampRate)
+{
+  switch(encoderSampRate)
+  {
+    case kIsacWideband:
+      {
+        bwest_str->send_bw_avg       = INIT_BN_EST_WB;
+        break;
+      }
+    case kIsacSuperWideband:
+      {
+        bwest_str->send_bw_avg       = INIT_BN_EST_SWB;
+        break;
+      }
+  }
+
+  switch(decoderSampRate)
+  {
+    case kIsacWideband:
+      {
+        bwest_str->prev_frame_length = INIT_FRAME_LEN_WB;
+        bwest_str->rec_bw_inv        = 1.0f /
+            (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+        bwest_str->rec_bw            = (int32_t)INIT_BN_EST_WB;
+        bwest_str->rec_bw_avg_Q      = INIT_BN_EST_WB;
+        bwest_str->rec_bw_avg        = INIT_BN_EST_WB + INIT_HDR_RATE_WB;
+        bwest_str->rec_header_rate   = INIT_HDR_RATE_WB;
+        break;
+      }
+    case kIsacSuperWideband:
+      {
+        bwest_str->prev_frame_length = INIT_FRAME_LEN_SWB;
+        bwest_str->rec_bw_inv        = 1.0f /
+            (INIT_BN_EST_SWB + INIT_HDR_RATE_SWB);
+        bwest_str->rec_bw            = (int32_t)INIT_BN_EST_SWB;
+        bwest_str->rec_bw_avg_Q      = INIT_BN_EST_SWB;
+        bwest_str->rec_bw_avg        = INIT_BN_EST_SWB + INIT_HDR_RATE_SWB;
+        bwest_str->rec_header_rate   = INIT_HDR_RATE_SWB;
+        break;
+      }
+  }
+
+  bwest_str->prev_rec_rtp_number       = 0;
+  bwest_str->prev_rec_arr_ts           = 0;
+  bwest_str->prev_rec_send_ts          = 0;
+  bwest_str->prev_rec_rtp_rate         = 1.0f;
+  bwest_str->last_update_ts            = 0;
+  bwest_str->last_reduction_ts         = 0;
+  bwest_str->count_tot_updates_rec     = -9;
+  bwest_str->rec_jitter                = 10.0f;
+  bwest_str->rec_jitter_short_term     = 0.0f;
+  bwest_str->rec_jitter_short_term_abs = 5.0f;
+  bwest_str->rec_max_delay             = 10.0f;
+  bwest_str->rec_max_delay_avg_Q       = 10.0f;
+  bwest_str->num_pkts_rec              = 0;
+
+  bwest_str->send_max_delay_avg        = 10.0f;
+
+  bwest_str->hsn_detect_rec = 0;
+
+  bwest_str->num_consec_rec_pkts_over_30k = 0;
+
+  bwest_str->hsn_detect_snd = 0;
+
+  bwest_str->num_consec_snt_pkts_over_30k = 0;
+
+  bwest_str->in_wait_period = 0;
+
+  bwest_str->change_to_WB = 0;
+
+  bwest_str->numConsecLatePkts = 0;
+  bwest_str->consecLatency = 0;
+  bwest_str->inWaitLatePkts = 0;
+  bwest_str->senderTimestamp = 0;
+  bwest_str->receiverTimestamp = 0;
+
+  bwest_str->external_bw_info.in_use = 0;
+
+  return 0;
+}
+
+/* This function updates both bottle neck rates                                                      */
+/* Parameters:                                                                                       */
+/* rtp_number    - value from RTP packet, from NetEq                                                 */
+/* frame length  - length of signal frame in ms, from iSAC decoder                                   */
+/* send_ts       - value in RTP header giving send time in samples                                     */
+/* arr_ts        - value given by timeGetTime() time of arrival in samples of packet from NetEq      */
+/* pksize        - size of packet in bytes, from NetEq                                               */
+/* Index         - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise                                                   */
+int16_t WebRtcIsac_UpdateBandwidthEstimator(
+    BwEstimatorstr* bwest_str,
+    const uint16_t rtp_number,
+    const int32_t frame_length,
+    const uint32_t send_ts,
+    const uint32_t arr_ts,
+    const size_t pksize
+    /*,    const uint16_t Index*/)
+{
+  float weight = 0.0f;
+  float curr_bw_inv = 0.0f;
+  float rec_rtp_rate;
+  float t_diff_proj;
+  float arr_ts_diff;
+  float send_ts_diff;
+  float arr_time_noise;
+  float arr_time_noise_abs;
+
+  float delay_correction_factor = 1;
+  float late_diff = 0.0f;
+  int immediate_set = 0;
+  int num_pkts_expected;
+
+  RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+  // We have to adjust the header-rate if the first packet has a
+  // frame-size different than the initialized value.
+  if ( frame_length != bwest_str->prev_frame_length )
+  {
+    bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+        1000.0f / (float)frame_length;     /* bits/s */
+  }
+
+  /* UPDATE ESTIMATES ON THIS SIDE */
+  /* compute far-side transmission rate */
+  rec_rtp_rate = ((float)pksize * 8.0f * 1000.0f / (float)frame_length) +
+      bwest_str->rec_header_rate;
+  // rec_rtp_rate packet bits/s + header bits/s
+
+  /* check for timer wrap-around */
+  if (arr_ts < bwest_str->prev_rec_arr_ts)
+  {
+    bwest_str->prev_rec_arr_ts   = arr_ts;
+    bwest_str->last_update_ts    = arr_ts;
+    bwest_str->last_reduction_ts = arr_ts + 3*FS;
+    bwest_str->num_pkts_rec      = 0;
+
+    /* store frame length */
+    bwest_str->prev_frame_length = frame_length;
+
+    /* store far-side transmission rate */
+    bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+    /* store far-side RTP time stamp */
+    bwest_str->prev_rec_rtp_number = rtp_number;
+
+    return 0;
+  }
+
+  bwest_str->num_pkts_rec++;
+
+  /* check that it's not one of the first 9 packets */
+  if ( bwest_str->count_tot_updates_rec > 0 )
+  {
+    if(bwest_str->in_wait_period > 0 )
+    {
+      bwest_str->in_wait_period--;
+    }
+
+    bwest_str->inWaitLatePkts -= ((bwest_str->inWaitLatePkts > 0)? 1:0);
+    send_ts_diff = (float)(send_ts - bwest_str->prev_rec_send_ts);
+
+    if (send_ts_diff <= (16 * frame_length)*2)
+      //doesn't allow for a dropped packet, not sure necessary to be
+      // that strict -DH
+    {
+      /* if not been updated for a long time, reduce the BN estimate */
+      if((uint32_t)(arr_ts - bwest_str->last_update_ts) *
+         1000.0f / FS > 3000)
+      {
+        //how many frames should have been received since the last
+        // update if too many have been dropped or there have been
+        // big delays won't allow this reduction may no longer need
+        // the send_ts_diff here
+        num_pkts_expected = (int)(((float)(arr_ts -
+                                           bwest_str->last_update_ts) * 1000.0f /(float) FS) /
+                                  (float)frame_length);
+
+        if(((float)bwest_str->num_pkts_rec/(float)num_pkts_expected) >
+           0.9)
+        {
+          float inv_bitrate = (float) pow( 0.99995,
+                                           (double)((uint32_t)(arr_ts -
+                                                                     bwest_str->last_reduction_ts)*1000.0f/FS) );
+
+          if ( inv_bitrate )
+          {
+            bwest_str->rec_bw_inv /= inv_bitrate;
+
+            //precautionary, likely never necessary
+            if (bwest_str->hsn_detect_snd &&
+                bwest_str->hsn_detect_rec)
+            {
+              if (bwest_str->rec_bw_inv > 0.000066f)
+              {
+                bwest_str->rec_bw_inv = 0.000066f;
+              }
+            }
+          }
+          else
+          {
+            bwest_str->rec_bw_inv = 1.0f /
+                (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+          }
+          /* reset time-since-update counter */
+          bwest_str->last_reduction_ts = arr_ts;
+        }
+        else
+          //reset here?
+        {
+          bwest_str->last_reduction_ts = arr_ts + 3*FS;
+          bwest_str->last_update_ts = arr_ts;
+          bwest_str->num_pkts_rec = 0;
+        }
+      }
+    }
+    else
+    {
+      bwest_str->last_reduction_ts = arr_ts + 3*FS;
+      bwest_str->last_update_ts = arr_ts;
+      bwest_str->num_pkts_rec = 0;
+    }
+
+
+    /* temporarily speed up adaptation if frame length has changed */
+    if ( frame_length != bwest_str->prev_frame_length )
+    {
+      bwest_str->count_tot_updates_rec = 10;
+      bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+          1000.0f / (float)frame_length;     /* bits/s */
+
+      bwest_str->rec_bw_inv = 1.0f /((float)bwest_str->rec_bw +
+                                     bwest_str->rec_header_rate);
+    }
+
+    ////////////////////////
+    arr_ts_diff = (float)(arr_ts - bwest_str->prev_rec_arr_ts);
+
+    if (send_ts_diff > 0 )
+    {
+      late_diff = arr_ts_diff - send_ts_diff;
+    }
+    else
+    {
+      late_diff = arr_ts_diff - (float)(16 * frame_length);
+    }
+
+    if((late_diff > 0) && !bwest_str->inWaitLatePkts)
+    {
+      bwest_str->numConsecLatePkts++;
+      bwest_str->consecLatency += late_diff;
+    }
+    else
+    {
+      bwest_str->numConsecLatePkts = 0;
+      bwest_str->consecLatency = 0;
+    }
+    if(bwest_str->numConsecLatePkts > 50)
+    {
+      float latencyMs = bwest_str->consecLatency/(FS/1000);
+      float averageLatencyMs = latencyMs / bwest_str->numConsecLatePkts;
+      delay_correction_factor = frame_length / (frame_length + averageLatencyMs);
+      immediate_set = 1;
+      bwest_str->inWaitLatePkts = (int16_t)((bwest_str->consecLatency/(FS/1000)) / 30);// + 150;
+      bwest_str->start_wait_period = arr_ts;
+    }
+    ///////////////////////////////////////////////
+
+
+
+    /*   update only if previous packet was not lost */
+    if ( rtp_number == bwest_str->prev_rec_rtp_number + 1 )
+    {
+
+
+      if (!(bwest_str->hsn_detect_snd && bwest_str->hsn_detect_rec))
+      {
+        if ((arr_ts_diff > (float)(16 * frame_length)))
+        {
+          //1/2 second
+          if ((late_diff > 8000.0f) && !bwest_str->in_wait_period)
+          {
+            delay_correction_factor = 0.7f;
+            bwest_str->in_wait_period = 55;
+            bwest_str->start_wait_period = arr_ts;
+            immediate_set = 1;
+          }
+          //320 ms
+          else if (late_diff > 5120.0f && !bwest_str->in_wait_period)
+          {
+            delay_correction_factor = 0.8f;
+            immediate_set = 1;
+            bwest_str->in_wait_period = 44;
+            bwest_str->start_wait_period = arr_ts;
+          }
+        }
+      }
+
+
+      if ((bwest_str->prev_rec_rtp_rate > bwest_str->rec_bw_avg) &&
+          (rec_rtp_rate > bwest_str->rec_bw_avg)                 &&
+          !bwest_str->in_wait_period)
+      {
+        /* test if still in initiation period and increment counter */
+        if (bwest_str->count_tot_updates_rec++ > 99)
+        {
+          /* constant weight after initiation part */
+          weight = 0.01f;
+        }
+        else
+        {
+          /* weight decreases with number of updates */
+          weight = 1.0f / (float) bwest_str->count_tot_updates_rec;
+        }
+        /* Bottle Neck Estimation */
+
+        /* limit outliers */
+        /* if more than 25 ms too much */
+        if (arr_ts_diff > frame_length * FS/1000 + 400.0f)
+        {
+          // in samples,  why 25ms??
+          arr_ts_diff = frame_length * FS/1000 + 400.0f;
+        }
+        if(arr_ts_diff < (frame_length * FS/1000) - 160.0f)
+        {
+          /* don't allow it to be less than frame rate - 10 ms */
+          arr_ts_diff = (float)frame_length * FS/1000 - 160.0f;
+        }
+
+        /* compute inverse receiving rate for last packet */
+        curr_bw_inv = arr_ts_diff / ((float)(pksize + HEADER_SIZE) *
+                                     8.0f * FS); // (180+35)*8*16000 = 27.5 Mbit....
+
+
+        if(curr_bw_inv <
+           (1.0f / (MAX_ISAC_BW + bwest_str->rec_header_rate)))
+        {
+          // don't allow inv rate to be larger than MAX
+          curr_bw_inv = (1.0f /
+                         (MAX_ISAC_BW + bwest_str->rec_header_rate));
+        }
+
+        /* update bottle neck rate estimate */
+        bwest_str->rec_bw_inv = weight * curr_bw_inv +
+            (1.0f - weight) * bwest_str->rec_bw_inv;
+
+        /* reset time-since-update counter */
+        bwest_str->last_update_ts    = arr_ts;
+        bwest_str->last_reduction_ts = arr_ts + 3 * FS;
+        bwest_str->num_pkts_rec = 0;
+
+        /* Jitter Estimation */
+        /* projected difference between arrival times */
+        t_diff_proj = ((float)(pksize + HEADER_SIZE) * 8.0f *
+                       1000.0f) / bwest_str->rec_bw_avg;
+
+
+        // difference between projected and actual
+        //   arrival time differences
+        arr_time_noise = (float)(arr_ts_diff*1000.0f/FS) -
+            t_diff_proj;
+        arr_time_noise_abs = (float) fabs( arr_time_noise );
+
+        /* long term averaged absolute jitter */
+        bwest_str->rec_jitter = weight * arr_time_noise_abs +
+            (1.0f - weight) * bwest_str->rec_jitter;
+        if (bwest_str->rec_jitter > 10.0f)
+        {
+          bwest_str->rec_jitter = 10.0f;
+        }
+        /* short term averaged absolute jitter */
+        bwest_str->rec_jitter_short_term_abs = 0.05f *
+            arr_time_noise_abs + 0.95f *
+            bwest_str->rec_jitter_short_term_abs;
+
+        /* short term averaged jitter */
+        bwest_str->rec_jitter_short_term = 0.05f * arr_time_noise +
+            0.95f * bwest_str->rec_jitter_short_term;
+      }
+    }
+  }
+  else
+  {
+    // reset time-since-update counter when
+    // receiving the first 9 packets
+    bwest_str->last_update_ts    = arr_ts;
+    bwest_str->last_reduction_ts = arr_ts + 3*FS;
+    bwest_str->num_pkts_rec = 0;
+
+    bwest_str->count_tot_updates_rec++;
+  }
+
+  /* limit minimum bottle neck rate */
+  if (bwest_str->rec_bw_inv > 1.0f / ((float)MIN_ISAC_BW +
+                                      bwest_str->rec_header_rate))
+  {
+    bwest_str->rec_bw_inv = 1.0f / ((float)MIN_ISAC_BW +
+                                    bwest_str->rec_header_rate);
+  }
+
+  // limit maximum bitrate
+  if (bwest_str->rec_bw_inv < 1.0f / ((float)MAX_ISAC_BW +
+                                      bwest_str->rec_header_rate))
+  {
+    bwest_str->rec_bw_inv = 1.0f / ((float)MAX_ISAC_BW +
+                                    bwest_str->rec_header_rate);
+  }
+
+  /* store frame length */
+  bwest_str->prev_frame_length = frame_length;
+
+  /* store far-side transmission rate */
+  bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+  /* store far-side RTP time stamp */
+  bwest_str->prev_rec_rtp_number = rtp_number;
+
+  // Replace bwest_str->rec_max_delay by the new
+  // value (atomic operation)
+  bwest_str->rec_max_delay = 3.0f * bwest_str->rec_jitter;
+
+  /* store send and arrival time stamp */
+  bwest_str->prev_rec_arr_ts = arr_ts ;
+  bwest_str->prev_rec_send_ts = send_ts;
+
+  /* Replace bwest_str->rec_bw by the new value (atomic operation) */
+  bwest_str->rec_bw = (int32_t)(1.0f / bwest_str->rec_bw_inv -
+                                      bwest_str->rec_header_rate);
+
+  if (immediate_set)
+  {
+    bwest_str->rec_bw = (int32_t) (delay_correction_factor *
+                                         (float) bwest_str->rec_bw);
+
+    if (bwest_str->rec_bw < (int32_t) MIN_ISAC_BW)
+    {
+      bwest_str->rec_bw = (int32_t) MIN_ISAC_BW;
+    }
+
+    bwest_str->rec_bw_avg = bwest_str->rec_bw +
+        bwest_str->rec_header_rate;
+
+    bwest_str->rec_bw_avg_Q = (float) bwest_str->rec_bw;
+
+    bwest_str->rec_jitter_short_term = 0.0f;
+
+    bwest_str->rec_bw_inv = 1.0f / (bwest_str->rec_bw +
+                                    bwest_str->rec_header_rate);
+
+    bwest_str->count_tot_updates_rec = 1;
+
+    immediate_set = 0;
+    bwest_str->consecLatency = 0;
+    bwest_str->numConsecLatePkts = 0;
+  }
+
+  return 0;
+}
+
+
+/* This function updates the send bottle neck rate                                                   */
+/* Index         - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise                                                   */
+int16_t WebRtcIsac_UpdateUplinkBwImpl(
+    BwEstimatorstr*           bwest_str,
+    int16_t               index,
+    enum IsacSamplingRate encoderSamplingFreq)
+{
+  RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+  if((index < 0) || (index > 23))
+  {
+    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+  }
+
+  /* UPDATE ESTIMATES FROM OTHER SIDE */
+  if(encoderSamplingFreq == kIsacWideband)
+  {
+    if(index > 11)
+    {
+      index -= 12;   
+      /* compute the jitter estimate as decoded on the other side */
+      bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+          0.1f * (float)MAX_ISAC_MD;
+    }
+    else
+    {
+      /* compute the jitter estimate as decoded on the other side */
+      bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+          0.1f * (float)MIN_ISAC_MD;
+    }
+
+    /* compute the BN estimate as decoded on the other side */
+    bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+        0.1f * kQRateTableWb[index];
+  }
+  else
+  {
+    /* compute the BN estimate as decoded on the other side */
+    bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+        0.1f * kQRateTableSwb[index];
+  }
+
+  if (bwest_str->send_bw_avg > (float) 28000 && !bwest_str->hsn_detect_snd)
+  {
+    bwest_str->num_consec_snt_pkts_over_30k++;
+
+    if (bwest_str->num_consec_snt_pkts_over_30k >= 66)
+    {
+      //approx 2 seconds with 30ms frames
+      bwest_str->hsn_detect_snd = 1;
+    }
+  }
+  else if (!bwest_str->hsn_detect_snd)
+  {
+    bwest_str->num_consec_snt_pkts_over_30k = 0;
+  }
+  return 0;
+}
+
+// called when there is upper-band bit-stream to update jitter
+// statistics.
+int16_t WebRtcIsac_UpdateUplinkJitter(
+    BwEstimatorstr*              bwest_str,
+    int32_t                  index)
+{
+  RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+  if((index < 0) || (index > 23))
+  {
+    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+  }
+
+  if(index > 0)
+  {
+    /* compute the jitter estimate as decoded on the other side */
+    bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+        0.1f * (float)MAX_ISAC_MD;
+  }
+  else
+  {
+    /* compute the jitter estimate as decoded on the other side */
+    bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+        0.1f * (float)MIN_ISAC_MD;
+  }
+
+  return 0;
+}
+
+
+
+// Returns the bandwidth/jitter estimation code (integer 0...23)
+// to put in the sending iSAC payload
+void
+WebRtcIsac_GetDownlinkBwJitIndexImpl(
+    BwEstimatorstr*           bwest_str,
+    int16_t*              bottleneckIndex,
+    int16_t*              jitterInfo,
+    enum IsacSamplingRate decoderSamplingFreq)
+{
+  float MaxDelay;
+  //uint16_t MaxDelayBit;
+
+  float rate;
+  float r;
+  float e1, e2;
+  const float weight = 0.1f;
+  const float* ptrQuantizationTable;
+  int16_t addJitterInfo;
+  int16_t minInd;
+  int16_t maxInd;
+  int16_t midInd;
+
+  if (bwest_str->external_bw_info.in_use) {
+    *bottleneckIndex = bwest_str->external_bw_info.bottleneck_idx;
+    *jitterInfo = bwest_str->external_bw_info.jitter_info;
+    return;
+  }
+
+  /* Get Max Delay Bit */
+  /* get unquantized max delay */
+  MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str);
+
+  if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+        MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) *
+                                   bwest_str->rec_max_delay_avg_Q - weight * MIN_ISAC_MD) )
+  {
+    jitterInfo[0] = 0;
+    /* update quantized average */
+    bwest_str->rec_max_delay_avg_Q =
+        (1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+        (float)MIN_ISAC_MD;
+  }
+  else
+  {
+    jitterInfo[0] = 1;
+    /* update quantized average */
+    bwest_str->rec_max_delay_avg_Q =
+        (1.f-weight) * bwest_str->rec_max_delay_avg_Q + weight *
+        (float)MAX_ISAC_MD;
+  }
+
+  // Get unquantized rate.
+  rate = (float)WebRtcIsac_GetDownlinkBandwidth(bwest_str);
+
+  /* Get Rate Index */
+  if(decoderSamplingFreq == kIsacWideband)
+  {
+    ptrQuantizationTable = kQRateTableWb;
+    addJitterInfo = 1;
+    maxInd = 11;
+  }
+  else
+  {
+    ptrQuantizationTable = kQRateTableSwb;
+    addJitterInfo = 0;
+    maxInd = 23;
+  }
+
+  minInd = 0;
+  while(maxInd > minInd + 1)
+  {
+    midInd = (maxInd + minInd) >> 1;
+    if(rate > ptrQuantizationTable[midInd])
+    {
+      minInd = midInd;
+    }
+    else
+    {
+      maxInd = midInd;
+    }
+  }
+  // Chose the index which gives results an average which is closest
+  // to rate
+  r = (1 - weight) * bwest_str->rec_bw_avg_Q - rate;
+  e1 = weight * ptrQuantizationTable[minInd] + r;
+  e2 = weight * ptrQuantizationTable[maxInd] + r;
+  e1 = (e1 > 0)? e1:-e1;
+  e2 = (e2 > 0)? e2:-e2;
+  if(e1 < e2)
+  {
+    bottleneckIndex[0] = minInd;
+  }
+  else
+  {
+    bottleneckIndex[0] = maxInd;
+  }
+
+  bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q +
+      weight * ptrQuantizationTable[bottleneckIndex[0]];
+  bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo;
+
+  bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight *
+      (rate + bwest_str->rec_header_rate);
+}
+
+
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+int32_t WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str)
+{
+  int32_t  rec_bw;
+  float   jitter_sign;
+  float   bw_adjust;
+
+  RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+  /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */
+  jitter_sign = bwest_str->rec_jitter_short_term /
+      bwest_str->rec_jitter_short_term_abs;
+
+  /* adjust bw proportionally to negative average jitter sign */
+  bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+
+  /* adjust Rate if jitter sign is mostly constant */
+  rec_bw = (int32_t)(bwest_str->rec_bw * bw_adjust);
+
+  /* limit range of bottle neck rate */
+  if (rec_bw < MIN_ISAC_BW)
+  {
+    rec_bw = MIN_ISAC_BW;
+  }
+  else if (rec_bw > MAX_ISAC_BW)
+  {
+    rec_bw = MAX_ISAC_BW;
+  }
+  return rec_bw;
+}
+
+/* Returns the max delay (in ms) */
+int32_t
+WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+  int32_t rec_max_delay;
+
+  RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+  rec_max_delay = (int32_t)(bwest_str->rec_max_delay);
+
+  /* limit range of jitter estimate */
+  if (rec_max_delay < MIN_ISAC_MD)
+  {
+    rec_max_delay = MIN_ISAC_MD;
+  }
+  else if (rec_max_delay > MAX_ISAC_MD)
+  {
+    rec_max_delay = MAX_ISAC_MD;
+  }
+  return rec_max_delay;
+}
+
+/* Clamp val to the closed interval [min,max]. */
+static int32_t clamp(int32_t val, int32_t min, int32_t max) {
+  RTC_DCHECK_LE(min, max);
+  return val < min ? min : (val > max ? max : val);
+}
+
+int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str) {
+  return bwest_str->external_bw_info.in_use
+             ? bwest_str->external_bw_info.send_bw_avg
+             : clamp(bwest_str->send_bw_avg, MIN_ISAC_BW, MAX_ISAC_BW);
+}
+
+int32_t WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str) {
+  return bwest_str->external_bw_info.in_use
+             ? bwest_str->external_bw_info.send_max_delay_avg
+             : clamp(bwest_str->send_max_delay_avg, MIN_ISAC_MD, MAX_ISAC_MD);
+}
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+    RateModel*         State,
+    int                StreamSize,    /* bytes in bitstream */
+    const int          FrameSamples,  /* samples per frame */
+    const double       BottleNeck,    /* bottle neck rate; excl headers (bps) */
+    const double       DelayBuildUp,  /* max delay from bottleneck buffering (ms) */
+    enum ISACBandwidth bandwidth
+    /*,int16_t        frequentLargePackets*/)
+{
+  double MinRate = 0.0;
+  int    MinBytes;
+  double TransmissionTime;
+  int    burstInterval = BURST_INTERVAL;
+
+  // first 10 packets @ low rate, then INIT_BURST_LEN packets @
+  // fixed rate of INIT_RATE bps
+  if (State->InitCounter > 0)
+  {
+    if (State->InitCounter-- <= INIT_BURST_LEN)
+    {
+      if(bandwidth == isac8kHz)
+      {
+        MinRate = INIT_RATE_WB;
+      }
+      else
+      {
+        MinRate = INIT_RATE_SWB;
+      }
+    }
+    else
+    {
+      MinRate = 0;
+    }
+  }
+  else
+  {
+    /* handle burst */
+    if (State->BurstCounter)
+    {
+      if (State->StillBuffered < (1.0 - 1.0/BURST_LEN) * DelayBuildUp)
+      {
+        /* max bps derived from BottleNeck and DelayBuildUp values */
+        MinRate = (1.0 + (FS/1000) * DelayBuildUp /
+                   (double)(BURST_LEN * FrameSamples)) * BottleNeck;
+      }
+      else
+      {
+        // max bps derived from StillBuffered and DelayBuildUp
+        // values
+        MinRate = (1.0 + (FS/1000) * (DelayBuildUp -
+                                      State->StillBuffered) / (double)FrameSamples) * BottleNeck;
+        if (MinRate < 1.04 * BottleNeck)
+        {
+          MinRate = 1.04 * BottleNeck;
+        }
+      }
+      State->BurstCounter--;
+    }
+  }
+
+
+  /* convert rate from bits/second to bytes/packet */
+  MinBytes = (int) (MinRate * FrameSamples / (8.0 * FS));
+
+  /* StreamSize will be adjusted if less than MinBytes */
+  if (StreamSize < MinBytes)
+  {
+    StreamSize = MinBytes;
+  }
+
+  /* keep track of when bottle neck was last exceeded by at least 1% */
+  if (StreamSize * 8.0 * FS / FrameSamples > 1.01 * BottleNeck) {
+    if (State->PrevExceed) {
+      /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+      State->ExceedAgo -= /*BURST_INTERVAL*/ burstInterval / (BURST_LEN - 1);
+      if (State->ExceedAgo < 0)
+        State->ExceedAgo = 0;
+    }
+    else
+    {
+      State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+      State->PrevExceed = 1;
+    }
+  }
+  else
+  {
+    State->PrevExceed = 0;
+    State->ExceedAgo += (FrameSamples * 1000) / FS;     /* ms */
+  }
+
+  /* set burst flag if bottle neck not exceeded for long time */
+  if ((State->ExceedAgo > burstInterval) &&
+      (State->BurstCounter == 0))
+  {
+    if (State->PrevExceed)
+    {
+      State->BurstCounter = BURST_LEN - 1;
+    }
+    else
+    {
+      State->BurstCounter = BURST_LEN;
+    }
+  }
+
+
+  /* Update buffer delay */
+  TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck;  /* ms */
+  State->StillBuffered += TransmissionTime;
+  State->StillBuffered -= (FrameSamples * 1000) / FS;     /* ms */
+  if (State->StillBuffered < 0.0)
+  {
+    State->StillBuffered = 0.0;
+  }
+
+  return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+    RateModel *State,
+    int StreamSize,                    /* bytes in bitstream */
+    const int FrameSamples,            /* samples per frame */
+    const double BottleNeck)        /* bottle neck rate; excl headers (bps) */
+{
+  double TransmissionTime;
+
+  /* avoid the initial "high-rate" burst */
+  State->InitCounter = 0;
+
+  /* Update buffer delay */
+  TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck;  /* ms */
+  State->StillBuffered += TransmissionTime;
+  State->StillBuffered -= (FrameSamples * 1000) / FS;     /* ms */
+  if (State->StillBuffered < 0.0)
+    State->StillBuffered = 0.0;
+
+}
+
+
+void WebRtcIsac_InitRateModel(
+    RateModel *State)
+{
+  State->PrevExceed      = 0;                        /* boolean */
+  State->ExceedAgo       = 0;                        /* ms */
+  State->BurstCounter    = 0;                        /* packets */
+  State->InitCounter     = INIT_BURST_LEN + 10;    /* packets */
+  State->StillBuffered   = 1.0;                    /* ms */
+}
+
+int WebRtcIsac_GetNewFrameLength(
+    double bottle_neck,
+    int    current_framesamples)
+{
+  int new_framesamples;
+
+  const int Thld_20_30 = 20000;
+
+  //const int Thld_30_20 = 30000;
+  const int Thld_30_20 = 1000000;   // disable 20 ms frames
+
+  const int Thld_30_60 = 18000;
+  //const int Thld_30_60 = 0;      // disable 60 ms frames
+
+  const int Thld_60_30 = 27000;
+
+
+  new_framesamples = current_framesamples;
+
+  /* find new framelength */
+  switch(current_framesamples) {
+    case 320:
+      if (bottle_neck < Thld_20_30)
+        new_framesamples = 480;
+      break;
+    case 480:
+      if (bottle_neck < Thld_30_60)
+        new_framesamples = 960;
+      else if (bottle_neck > Thld_30_20)
+        new_framesamples = 320;
+      break;
+    case 960:
+      if (bottle_neck >= Thld_60_30)
+        new_framesamples = 480;
+      break;
+  }
+
+  return new_framesamples;
+}
+
+double WebRtcIsac_GetSnr(
+    double bottle_neck,
+    int    framesamples)
+{
+  double s2nr;
+
+  const double a_20 = -30.0;
+  const double b_20 = 0.8;
+  const double c_20 = 0.0;
+
+  const double a_30 = -23.0;
+  const double b_30 = 0.48;
+  const double c_30 = 0.0;
+
+  const double a_60 = -23.0;
+  const double b_60 = 0.53;
+  const double c_60 = 0.0;
+
+
+  /* find new SNR value */
+  switch(framesamples) {
+    case 320:
+      s2nr = a_20 + b_20 * bottle_neck * 0.001 + c_20 * bottle_neck *
+          bottle_neck * 0.000001;
+      break;
+    case 480:
+      s2nr = a_30 + b_30 * bottle_neck * 0.001 + c_30 * bottle_neck *
+          bottle_neck * 0.000001;
+      break;
+    case 960:
+      s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck *
+          bottle_neck * 0.000001;
+      break;
+    default:
+      s2nr = 0;
+  }
+
+  return s2nr;
+
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h b/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
new file mode 100644
index 0000000..5f4550a
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define MIN_ISAC_BW 10000
+#define MIN_ISAC_BW_LB 10000
+#define MIN_ISAC_BW_UB 25000
+
+#define MAX_ISAC_BW 56000
+#define MAX_ISAC_BW_UB 32000
+#define MAX_ISAC_BW_LB 32000
+
+#define MIN_ISAC_MD 5
+#define MAX_ISAC_MD 25
+
+// assumed header size, in bytes; we don't know the exact number
+// (header compression may be used)
+#define HEADER_SIZE 35
+
+// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
+#define INIT_FRAME_LEN_WB 60
+#define INIT_FRAME_LEN_SWB 30
+
+// Initial Bottleneck Estimate, in bits/sec, for
+// Wideband & Super-wideband mode
+#define INIT_BN_EST_WB 20e3f
+#define INIT_BN_EST_SWB 56e3f
+
+// Initial Header rate (header rate depends on frame-size),
+// in bits/sec, for Wideband & Super-Wideband mode.
+#define INIT_HDR_RATE_WB \
+  ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
+#define INIT_HDR_RATE_SWB \
+  ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
+
+// number of packets in a row for a high rate burst
+#define BURST_LEN 3
+
+// ms, max time between two full bursts
+#define BURST_INTERVAL 500
+
+// number of packets in a row for initial high rate burst
+#define INIT_BURST_LEN 5
+
+// bits/s, rate for the first BURST_LEN packets
+#define INIT_RATE_WB INIT_BN_EST_WB
+#define INIT_RATE_SWB INIT_BN_EST_SWB
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* This function initializes the struct                    */
+/* to be called before using the struct for anything else  */
+/* returns 0 if everything went fine, -1 otherwise         */
+int32_t WebRtcIsac_InitBandwidthEstimator(
+    BwEstimatorstr* bwest_str,
+    enum IsacSamplingRate encoderSampRate,
+    enum IsacSamplingRate decoderSampRate);
+
+/* This function updates the receiving estimate */
+/* Parameters: */
+/* rtp_number    - value from RTP packet, from NetEq */
+/* frame length  - length of signal frame in ms, from iSAC decoder */
+/* send_ts       - value in RTP header giving send time in samples */
+/* arr_ts        - value given by timeGetTime() time of arrival in samples of
+ * packet from NetEq      */
+/* pksize        - size of packet in bytes, from NetEq */
+/* Index         - integer (range 0...23) indicating bottle neck & jitter as
+ * estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+int16_t WebRtcIsac_UpdateBandwidthEstimator(BwEstimatorstr* bwest_str,
+                                            uint16_t rtp_number,
+                                            int32_t frame_length,
+                                            uint32_t send_ts,
+                                            uint32_t arr_ts,
+                                            size_t pksize);
+
+/* Update receiving estimates. Used when we only receive BWE index, no iSAC data
+ * packet. */
+int16_t WebRtcIsac_UpdateUplinkBwImpl(
+    BwEstimatorstr* bwest_str,
+    int16_t Index,
+    enum IsacSamplingRate encoderSamplingFreq);
+
+/* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the
+ * sending iSAC payload */
+void WebRtcIsac_GetDownlinkBwJitIndexImpl(
+    BwEstimatorstr* bwest_str,
+    int16_t* bottleneckIndex,
+    int16_t* jitterInfo,
+    enum IsacSamplingRate decoderSamplingFreq);
+
+/* Returns the bandwidth estimation (in bps) */
+int32_t WebRtcIsac_GetDownlinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay (in ms) */
+int32_t WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth that iSAC should send with in bps */
+int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay value from the other side in ms */
+int32_t WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+    RateModel* State,
+    int StreamSize,      /* bytes in bitstream */
+    int FrameLen,        /* ms per frame */
+    double BottleNeck,   /* bottle neck rate; excl headers (bps) */
+    double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+    enum ISACBandwidth bandwidth
+    /*,int16_t        frequentLargePackets*/);
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+    RateModel* State,
+    int StreamSize,     /* bytes in bitstream */
+    int FrameSamples,   /* samples per frame */
+    double BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+void WebRtcIsac_InitRateModel(RateModel* State);
+
+/* Returns the new framelength value (input argument: bottle_neck) */
+int WebRtcIsac_GetNewFrameLength(double bottle_neck, int current_framelength);
+
+/* Returns the new SNR value (input argument: bottle_neck) */
+double WebRtcIsac_GetSnr(double bottle_neck, int new_framelength);
+
+int16_t WebRtcIsac_UpdateUplinkJitter(BwEstimatorstr* bwest_str, int32_t index);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ \
+        */
diff --git a/modules/audio_coding/codecs/isac/main/source/codec.h b/modules/audio_coding/codecs/isac/main/source/codec.h
new file mode 100644
index 0000000..a7c7ddc
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/codec.h
@@ -0,0 +1,223 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/third_party/fft/fft.h"
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream);
+
+int WebRtcIsac_EstimateBandwidth(BwEstimatorstr* bwest_str,
+                                 Bitstr* streamdata,
+                                 size_t packet_size,
+                                 uint16_t rtp_seq_number,
+                                 uint32_t send_ts,
+                                 uint32_t arr_ts,
+                                 enum IsacSamplingRate encoderSampRate,
+                                 enum IsacSamplingRate decoderSampRate);
+
+int WebRtcIsac_DecodeLb(const TransformTables* transform_tables,
+                        float* signal_out,
+                        ISACLBDecStruct* ISACdec_obj,
+                        int16_t* current_framesamples,
+                        int16_t isRCUPayload);
+
+int WebRtcIsac_DecodeRcuLb(float* signal_out,
+                           ISACLBDecStruct* ISACdec_obj,
+                           int16_t* current_framesamples);
+
+int WebRtcIsac_EncodeLb(const TransformTables* transform_tables,
+                        float* in,
+                        ISACLBEncStruct* ISACencLB_obj,
+                        int16_t codingMode,
+                        int16_t bottleneckIndex);
+
+int WebRtcIsac_EncodeStoredDataLb(const IsacSaveEncoderData* ISACSavedEnc_obj,
+                                  Bitstr* ISACBitStr_obj,
+                                  int BWnumber,
+                                  float scale);
+
+int WebRtcIsac_EncodeStoredDataUb(
+    const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+    Bitstr* bitStream,
+    int32_t jitterInfo,
+    float scale,
+    enum ISACBandwidth bandwidth);
+
+int16_t WebRtcIsac_GetRedPayloadUb(
+    const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+    Bitstr* bitStreamObj,
+    enum ISACBandwidth bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ *   - inRateBitPerSec           : a total bit-rate in bits/sec.
+ *
+ * Output:
+ *   - rateLBBitPerSec           : a bit-rate allocated to the lower-band
+ *                                 in bits/sec.
+ *   - rateUBBitPerSec           : a bit-rate allocated to the upper-band
+ *                                 in bits/sec.
+ *
+ * Return value                  : 0 if rate allocation has been successful.
+ *                                -1 if failed to allocate rates.
+ */
+
+int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
+                                  double* rateLBBitPerSec,
+                                  double* rateUBBitPerSec,
+                                  enum ISACBandwidth* bandwidthKHz);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb16()
+ *
+ * Decode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input/Output:
+ *       -ISACdec_obj        : pointer to the upper-band decoder object. The
+ *                             bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ *       -signal_out         : decoded audio, 480 samples 30 ms.
+ *
+ * Return value              : >0 number of decoded bytes.
+ *                             <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables,
+                          float* signal_out,
+                          ISACUBDecStruct* ISACdec_obj,
+                          int16_t isRCUPayload);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb12()
+ *
+ * Decode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input/Output:
+ *       -ISACdec_obj        : pointer to the upper-band decoder object. The
+ *                             bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ *       -signal_out         : decoded audio, 480 samples 30 ms.
+ *
+ * Return value              : >0 number of decoded bytes.
+ *                             <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables,
+                          float* signal_out,
+                          ISACUBDecStruct* ISACdec_obj,
+                          int16_t isRCUPayload);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb16()
+ *
+ * Encode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input:
+ *       -in                 : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ *       -ISACdec_obj        : pointer to the upper-band encoder object. The
+ *                             bit-stream is stored inside the encoder object.
+ *
+ * Return value              : >0 number of encoded bytes.
+ *                             <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables,
+                          float* in,
+                          ISACUBEncStruct* ISACenc_obj,
+                          int32_t jitterInfo);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb12()
+ *
+ * Encode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input:
+ *       -in                 : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ *       -ISACdec_obj        : pointer to the upper-band encoder object. The
+ *                             bit-stream is stored inside the encoder object.
+ *
+ * Return value              : >0 number of encoded bytes.
+ *                             <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables,
+                          float* in,
+                          ISACUBEncStruct* ISACenc_obj,
+                          int32_t jitterInfo);
+
+/************************** initialization functions *************************/
+
+void WebRtcIsac_InitMasking(MaskFiltstr* maskdata);
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr* postfiltdata);
+
+/**************************** transform functions ****************************/
+
+void WebRtcIsac_InitTransform(TransformTables* tables);
+
+void WebRtcIsac_Time2Spec(const TransformTables* tables,
+                          double* inre1,
+                          double* inre2,
+                          int16_t* outre,
+                          int16_t* outim,
+                          FFTstr* fftstr_obj);
+
+void WebRtcIsac_Spec2time(const TransformTables* tables,
+                          double* inre,
+                          double* inim,
+                          double* outre1,
+                          double* outre2,
+                          FFTstr* fftstr_obj);
+
+/***************************** filterbank functions **************************/
+
+void WebRtcIsac_FilterAndCombineFloat(float* InLP,
+                                      float* InHP,
+                                      float* Out,
+                                      PostFiltBankstr* postfiltdata);
+
+/************************* normalized lattice filters ************************/
+
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+                                    float* stateF,
+                                    float* stateG,
+                                    float* lat_in,
+                                    double* filtcoeflo,
+                                    double* lat_out);
+
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+                                    float* stateF,
+                                    float* stateG,
+                                    double* lat_in,
+                                    double* lo_filt_coef,
+                                    float* lat_out);
+
+void WebRtcIsac_Dir2Lat(double* a, int orderCoef, float* sth, float* cth);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/crc.c b/modules/audio_coding/codecs/isac/main/source/crc.c
new file mode 100644
index 0000000..1bb0827
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/crc.c
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/crc.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+
+#define POLYNOMIAL 0x04c11db7L
+
+
+static const uint32_t kCrcTable[256] = {
+  0,          0x4c11db7,  0x9823b6e,  0xd4326d9,  0x130476dc, 0x17c56b6b,
+  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13,  0x54bf6a4,
+  0x808d07d,  0xcc9cdca,  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+  0x3f9b762c, 0x3b5a6b9b,  0x315d626, 0x7d4cb91,  0xa97ed48,  0xe56f0ff,
+  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+  0x18197087, 0x1cd86d30, 0x29f3d35,  0x65e2082,  0xb1d065b,  0xfdc1bec,
+  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ *  - bitstream              : payload bitstream
+ *  - len_bitstream_in_bytes : number of 8-bit words in the bit stream
+ *
+ * Output:
+ *  - crc                    : checksum
+ *
+ * Return value              :  0 - Ok
+ *                             -1 - Error
+ */
+
+int WebRtcIsac_GetCrc(const int16_t* bitstream,
+                      int len_bitstream_in_bytes,
+                      uint32_t* crc)
+{
+  uint8_t* bitstream_ptr_uw8;
+  uint32_t crc_state;
+  int byte_cntr;
+  int crc_tbl_indx;
+
+  /* Sanity Check. */
+  if (bitstream == NULL) {
+    return -1;
+  }
+  /* cast to UWord8 pointer */
+  bitstream_ptr_uw8 = (uint8_t *)bitstream;
+
+  /* initialize */
+  crc_state = 0xFFFFFFFF;
+
+  for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
+    crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
+                       bitstream_ptr_uw8[byte_cntr]) & 0xFF;
+    crc_state = (crc_state << 8) ^ kCrcTable[crc_tbl_indx];
+  }
+
+  *crc = ~crc_state;
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/crc.h b/modules/audio_coding/codecs/isac/main/source/crc.h
new file mode 100644
index 0000000..f031019
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/crc.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * crc.h
+ *
+ * Checksum functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+
+#include <stdint.h>
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ *  - encoded      : payload bit stream
+ *  - no_of_word8s : number of 8-bit words in the bit stream
+ *
+ * Output:
+ *  - crc          : checksum
+ *
+ * Return value    :  0 - Ok
+ *                   -1 - Error
+ */
+
+int WebRtcIsac_GetCrc(const int16_t* encoded, int no_of_word8s, uint32_t* crc);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/decode.c b/modules/audio_coding/codecs/isac/main/source/decode.c
new file mode 100644
index 0000000..6e114e4
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/decode.c
@@ -0,0 +1,303 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_B.c
+ *
+ * This file contains definition of funtions for decoding.
+ * Decoding of lower-band, including normal-decoding and RCU decoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_filter.h"
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsac_DecodeLb(const TransformTables* transform_tables,
+                        float* signal_out, ISACLBDecStruct* ISACdecLB_obj,
+                        int16_t* current_framesamples,
+                        int16_t isRCUPayload) {
+  int k;
+  int len, err;
+  int16_t bandwidthInd;
+
+  float LP_dec_float[FRAMESAMPLES_HALF];
+  float HP_dec_float[FRAMESAMPLES_HALF];
+
+  double LPw[FRAMESAMPLES_HALF];
+  double HPw[FRAMESAMPLES_HALF];
+  double LPw_pf[FRAMESAMPLES_HALF];
+
+  double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES];
+  double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES];
+
+  double real_f[FRAMESAMPLES_HALF];
+  double imag_f[FRAMESAMPLES_HALF];
+
+  double PitchLags[4];
+  double PitchGains[4];
+  double AvgPitchGain;
+  int16_t PitchGains_Q12[4];
+  int16_t AvgPitchGain_Q12;
+
+  float gain;
+
+  int frame_nb; /* counter */
+  int frame_mode; /* 0 30ms, 1 for 60ms */
+  /* Processed_samples: 480 (30, 60 ms). Cannot take other values. */
+
+  WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj));
+
+  len = 0;
+
+  /* Decode framelength and BW estimation - not used,
+     only for stream pointer*/
+  err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
+                                  current_framesamples);
+  if (err < 0) {
+    return err;
+  }
+
+  /* Frame_mode:
+   * 0: indicates 30 ms frame (480 samples)
+   * 1: indicates 60 ms frame (960 samples) */
+  frame_mode = *current_framesamples / MAX_FRAMESAMPLES;
+
+  err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
+  if (err < 0) {
+    return err;
+  }
+
+  /* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames
+     bundled together (60ms). */
+  for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+    /* Decode & de-quantize pitch parameters */
+    err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj,
+                                     PitchGains_Q12);
+    if (err < 0) {
+      return err;
+    }
+
+    err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12,
+                                    PitchLags);
+    if (err < 0) {
+      return err;
+    }
+
+    AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+        PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+    /* Decode & de-quantize filter coefficients. */
+    err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef,
+                               hi_filt_coef);
+    if (err < 0) {
+      return err;
+    }
+    /* Decode & de-quantize spectrum. */
+    len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12,
+                                kIsacLowerBand, real_f, imag_f);
+    if (len < 0) {
+      return len;
+    }
+
+    /* Inverse transform. */
+    WebRtcIsac_Spec2time(transform_tables, real_f, imag_f, LPw, HPw,
+                         &ISACdecLB_obj->fftstr_obj);
+
+    /* Convert PitchGains back to float for pitchfilter_post */
+    for (k = 0; k < 4; k++) {
+      PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+    }
+    if (isRCUPayload) {
+      for (k = 0; k < 240; k++) {
+        LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+        HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+      }
+    }
+
+    /* Inverse pitch filter. */
+    WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj,
+                               PitchLags, PitchGains);
+    /* Convert AvgPitchGain back to float for computation of gain. */
+    AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096;
+    gain = 1.0f - 0.45f * (float)AvgPitchGain;
+
+    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+      /* Reduce gain to compensate for pitch enhancer. */
+      LPw_pf[k] *= gain;
+    }
+
+    if (isRCUPayload) {
+      for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+        /* Compensation for transcoding gain changes. */
+        LPw_pf[k] *= RCU_TRANSCODING_SCALE;
+        HPw[k] *= RCU_TRANSCODING_SCALE;
+      }
+    }
+    /* Perceptual post-filtering (using normalized lattice filter). */
+    WebRtcIsac_NormLatticeFilterAr(
+        ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
+        (ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef,
+        LP_dec_float);
+    WebRtcIsac_NormLatticeFilterAr(
+        ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
+        (ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef,
+        HP_dec_float);
+
+    /* Recombine the 2 bands. */
+    WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float,
+                                     signal_out + frame_nb * FRAMESAMPLES,
+                                     &ISACdecLB_obj->postfiltbankstr_obj);
+  }
+  return len;
+}
+
+
+/*
+ * This decode function is called when the codec is operating in 16 kHz
+ * bandwidth to decode the upperband, i.e. 8-16 kHz.
+ *
+ * Contrary to lower-band, the upper-band (8-16 kHz) is not split in
+ * frequency, but split to 12 sub-frames, i.e. twice as lower-band.
+ */
+int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables,
+                          float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
+                          int16_t isRCUPayload) {
+  int len, err;
+
+  double halfFrameFirst[FRAMESAMPLES_HALF];
+  double halfFrameSecond[FRAMESAMPLES_HALF];
+
+  double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) +
+                           (UB_LPC_ORDER + 1)];
+
+  double real_f[FRAMESAMPLES_HALF];
+  double imag_f[FRAMESAMPLES_HALF];
+  const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+  len = 0;
+
+  /* Decode & de-quantize filter coefficients. */
+  memset(percepFilterParam, 0, sizeof(percepFilterParam));
+  err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+                                       percepFilterParam, isac16kHz);
+  if (err < 0) {
+    return err;
+  }
+
+  /* Decode & de-quantize spectrum. */
+  len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+                              kIsacUpperBand16, real_f, imag_f);
+  if (len < 0) {
+    return len;
+  }
+  if (isRCUPayload) {
+    int n;
+    for (n = 0; n < 240; n++) {
+      real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+      imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+    }
+  }
+  /* Inverse transform. */
+  WebRtcIsac_Spec2time(transform_tables,
+                       real_f, imag_f, halfFrameFirst, halfFrameSecond,
+                       &ISACdecUB_obj->fftstr_obj);
+
+  /* Perceptual post-filtering (using normalized lattice filter). */
+  WebRtcIsac_NormLatticeFilterAr(
+      UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+      (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
+      &percepFilterParam[(UB_LPC_ORDER + 1)], signal_out);
+
+  WebRtcIsac_NormLatticeFilterAr(
+      UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+      (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
+      &percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)],
+      &signal_out[FRAMESAMPLES_HALF]);
+
+  return len;
+}
+
+/*
+ * This decode function is called when the codec operates at 0-12 kHz
+ * bandwidth to decode the upperband, i.e. 8-12 kHz.
+ *
+ * At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
+ * kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
+ * reconstructed and 12-16 kHz replaced with zeros. Then two bands
+ * are combined, to reconstruct the upperband 8-16 kHz.
+ */
+int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables,
+                          float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
+                          int16_t isRCUPayload) {
+  int len, err;
+
+  float LP_dec_float[FRAMESAMPLES_HALF];
+  float HP_dec_float[FRAMESAMPLES_HALF];
+
+  double LPw[FRAMESAMPLES_HALF];
+  double HPw[FRAMESAMPLES_HALF];
+
+  double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES];
+
+  double real_f[FRAMESAMPLES_HALF];
+  double imag_f[FRAMESAMPLES_HALF];
+  const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+  len = 0;
+
+  /* Decode & dequantize filter coefficients. */
+  err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+                                       percepFilterParam, isac12kHz);
+  if (err < 0) {
+    return err;
+  }
+
+  /* Decode & de-quantize spectrum. */
+  len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+                              kIsacUpperBand12, real_f, imag_f);
+  if (len < 0) {
+    return len;
+  }
+
+  if (isRCUPayload) {
+    int n;
+    for (n = 0; n < 240; n++) {
+      real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+      imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+    }
+  }
+  /* Inverse transform. */
+  WebRtcIsac_Spec2time(transform_tables,
+                       real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj);
+  /* perceptual post-filtering (using normalized lattice filter) */
+  WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
+                                 ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+                                 (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG,
+                                 LPw, percepFilterParam, LP_dec_float);
+  /* Zero for 12-16 kHz. */
+  memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
+  /* Recombine the 2 bands. */
+  WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
+                                   &ISACdecUB_obj->postfiltbankstr_obj);
+  return len;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/decode_bwe.c b/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
new file mode 100644
index 0000000..89d970f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+
+
+int
+WebRtcIsac_EstimateBandwidth(
+    BwEstimatorstr*           bwest_str,
+    Bitstr*                   streamdata,
+    size_t                packet_size,
+    uint16_t              rtp_seq_number,
+    uint32_t              send_ts,
+    uint32_t              arr_ts,
+    enum IsacSamplingRate encoderSampRate,
+    enum IsacSamplingRate decoderSampRate)
+{
+  int16_t  index;
+  int16_t  frame_samples;
+  uint32_t sendTimestampIn16kHz;
+  uint32_t arrivalTimestampIn16kHz;
+  uint32_t diffSendTime;
+  uint32_t diffArrivalTime;
+  int err;
+
+  /* decode framelength and BW estimation */
+  err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
+  if(err < 0)  // error check
+  {
+    return err;
+  }
+  err = WebRtcIsac_DecodeSendBW(streamdata, &index);
+  if(err < 0)  // error check
+  {
+    return err;
+  }
+
+  /* UPDATE ESTIMATES FROM OTHER SIDE */
+  err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
+  if(err < 0)
+  {
+    return err;
+  }
+
+  // We like BWE to work at 16 kHz sampling rate,
+  // therefore, we have to change the timestamps accordingly.
+  // translate the send timestamp if required
+  diffSendTime = (uint32_t)((uint32_t)send_ts -
+                                  (uint32_t)bwest_str->senderTimestamp);
+  bwest_str->senderTimestamp = send_ts;
+
+  diffArrivalTime = (uint32_t)((uint32_t)arr_ts -
+                                     (uint32_t)bwest_str->receiverTimestamp);
+  bwest_str->receiverTimestamp = arr_ts;
+
+  if(decoderSampRate == kIsacSuperWideband)
+  {
+    diffArrivalTime = (uint32_t)diffArrivalTime >> 1;
+    diffSendTime = (uint32_t)diffSendTime >> 1;
+  }
+
+  // arrival timestamp in 16 kHz
+  arrivalTimestampIn16kHz = (uint32_t)((uint32_t)
+                                             bwest_str->prev_rec_arr_ts + (uint32_t)diffArrivalTime);
+  // send timestamp in 16 kHz
+  sendTimestampIn16kHz = (uint32_t)((uint32_t)
+                                          bwest_str->prev_rec_send_ts + (uint32_t)diffSendTime);
+
+  err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
+                                            (frame_samples * 1000) / FS, sendTimestampIn16kHz,
+                                            arrivalTimestampIn16kHz, packet_size);
+  // error check
+  if(err < 0)
+  {
+    return err;
+  }
+
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/encode.c b/modules/audio_coding/codecs/isac/main/source/encode.c
new file mode 100644
index 0000000..bf92d02
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/encode.c
@@ -0,0 +1,1260 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * This file contains definition of funtions for encoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_analysis.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_filter.h"
+
+
+#define UB_LOOKAHEAD 24
+
+
+/*
+  Rate allocation tables of lower and upper-band bottleneck for
+  12kHz & 16kHz bandwidth.
+
+  12 kHz bandwidth
+  -----------------
+  The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
+  considered 7 enteries, uniformly distributed in this interval, i.e. 38,
+  39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
+  and the upper-band bottlenecks are specified in
+  'kLowerBandBitRate12' and 'kUpperBandBitRate12'
+  tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
+  bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
+  overall bottleneck of the codec, we use linear interpolation to get
+  lower-band and upper-band bottlenecks.
+
+  16 kHz bandwidth
+  -----------------
+  The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
+  considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
+  52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
+  bottlenecks are specified in 'kLowerBandBitRate16' and
+  'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
+  of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
+  kbps for upper-band. Given an overall bottleneck of the codec, we use linear
+  interpolation to get lower-band and upper-band bottlenecks.
+
+ */
+
+/*     38  39.17  40.33   41.5  42.67  43.83     45 */
+static const int16_t kLowerBandBitRate12[7] = {
+    29000, 30000, 30000, 31000, 31000, 32000, 32000 };
+static const int16_t kUpperBandBitRate12[7] = {
+    25000, 25000, 27000, 27000, 29000, 29000, 32000 };
+
+/*    50     51.2  52.4   53.6   54.8    56 */
+static const int16_t kLowerBandBitRate16[6] = {
+    31000, 31000, 32000, 32000, 32000, 32000 };
+static const int16_t kUpperBandBitRate16[6] = {
+    28000, 29000, 29000, 30000, 31000, 32000 };
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ *   - inRateBitPerSec           : a total bottleneck in bits/sec.
+ *
+ * Output:
+ *   - rateLBBitPerSec           : a bottleneck allocated to the lower-band
+ *                                 in bits/sec.
+ *   - rateUBBitPerSec           : a bottleneck allocated to the upper-band
+ *                                 in bits/sec.
+ *
+ * Return value                  : 0 if rate allocation has been successful.
+ *                                -1 if failed to allocate rates.
+ */
+
+int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
+                                        double* rateLBBitPerSec,
+                                        double* rateUBBitPerSec,
+                                        enum ISACBandwidth* bandwidthKHz) {
+  int16_t idx;
+  double idxD;
+  double idxErr;
+  if (inRateBitPerSec < 38000) {
+    /* If the given overall bottleneck is less than 38000 then
+     * then codec has to operate in wideband mode, i.e. 8 kHz
+     * bandwidth. */
+    *rateLBBitPerSec = (int16_t)((inRateBitPerSec > 32000) ?
+        32000 : inRateBitPerSec);
+    *rateUBBitPerSec = 0;
+    *bandwidthKHz = isac8kHz;
+  } else if ((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000)) {
+    /* At a bottleneck between 38 and 50 kbps the codec is operating
+     * at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
+     * upper/lower bottleneck */
+
+    /* Find the bottlenecks by linear interpolation,
+     * step is (45000 - 38000)/6.0 we use the inverse of it. */
+    const double stepSizeInv = 8.5714286e-4;
+    idxD = (inRateBitPerSec - 38000) * stepSizeInv;
+    idx = (idxD >= 6) ? 6 : ((int16_t)idxD);
+    idxErr = idxD - idx;
+    *rateLBBitPerSec = kLowerBandBitRate12[idx];
+    *rateUBBitPerSec = kUpperBandBitRate12[idx];
+
+    if (idx < 6) {
+      *rateLBBitPerSec += (int16_t)(
+          idxErr * (kLowerBandBitRate12[idx + 1] - kLowerBandBitRate12[idx]));
+      *rateUBBitPerSec += (int16_t)(
+          idxErr * (kUpperBandBitRate12[idx + 1] - kUpperBandBitRate12[idx]));
+    }
+    *bandwidthKHz = isac12kHz;
+  } else if ((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000)) {
+    /* A bottleneck between 50 and 56 kbps corresponds to bandwidth
+     * of 16 kHz. Using xxxBandBitRate16[] to calculates
+     * upper/lower bottleneck. */
+
+    /* Find the bottlenecks by linear interpolation
+     * step is (56000 - 50000)/5 we use the inverse of it. */
+    const double stepSizeInv = 8.3333333e-4;
+    idxD = (inRateBitPerSec - 50000) * stepSizeInv;
+    idx = (idxD >= 5) ? 5 : ((int16_t)idxD);
+    idxErr = idxD - idx;
+    *rateLBBitPerSec = kLowerBandBitRate16[idx];
+    *rateUBBitPerSec  = kUpperBandBitRate16[idx];
+
+    if (idx < 5) {
+      *rateLBBitPerSec += (int16_t)(idxErr *
+          (kLowerBandBitRate16[idx + 1] -
+              kLowerBandBitRate16[idx]));
+
+      *rateUBBitPerSec += (int16_t)(idxErr *
+          (kUpperBandBitRate16[idx + 1] -
+              kUpperBandBitRate16[idx]));
+    }
+    *bandwidthKHz = isac16kHz;
+  } else {
+    /* Out-of-range botlteneck value. */
+    return -1;
+  }
+
+  /* limit the values. */
+  *rateLBBitPerSec = (*rateLBBitPerSec > 32000) ? 32000 : *rateLBBitPerSec;
+  *rateUBBitPerSec = (*rateUBBitPerSec > 32000) ? 32000 : *rateUBBitPerSec;
+  return 0;
+}
+
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream) {
+  bit_stream->W_upper = 0xFFFFFFFF;
+  bit_stream->stream_index = 0;
+  bit_stream->streamval = 0;
+}
+
+int WebRtcIsac_EncodeLb(const TransformTables* transform_tables,
+                        float* in, ISACLBEncStruct* ISACencLB_obj,
+                        int16_t codingMode,
+                        int16_t bottleneckIndex) {
+  int stream_length = 0;
+  int err;
+  int k;
+  int iterCntr;
+
+  double lofilt_coef[(ORDERLO + 1)*SUBFRAMES];
+  double hifilt_coef[(ORDERHI + 1)*SUBFRAMES];
+  float LP[FRAMESAMPLES_HALF];
+  float HP[FRAMESAMPLES_HALF];
+
+  double LP_lookahead[FRAMESAMPLES_HALF];
+  double HP_lookahead[FRAMESAMPLES_HALF];
+  double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD];
+  double LPw[FRAMESAMPLES_HALF];
+
+  double HPw[FRAMESAMPLES_HALF];
+  double LPw_pf[FRAMESAMPLES_HALF];
+  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
+  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
+
+  double PitchLags[4];
+  double PitchGains[4];
+  int16_t PitchGains_Q12[4];
+  int16_t AvgPitchGain_Q12;
+
+  int frame_mode; /* 0 for 30ms, 1 for 60ms */
+  int status = 0;
+  int my_index;
+  transcode_obj transcodingParam;
+  double bytesLeftSpecCoding;
+  uint16_t payloadLimitBytes;
+
+  /* Copy new frame-length and bottleneck rate only for the first 10 ms data */
+  if (ISACencLB_obj->buffer_index == 0) {
+    /* Set the framelength for the next packet. */
+    ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength;
+  }
+  /* 'frame_mode' is 0 (30 ms) or 1 (60 ms). */
+  frame_mode = ISACencLB_obj->current_framesamples / MAX_FRAMESAMPLES;
+
+  /* buffer speech samples (by 10ms packet) until the frame-length */
+  /* is reached (30 or 60 ms).                                     */
+  /*****************************************************************/
+
+  /* fill the buffer with 10ms input data */
+  for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+    ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] = in[k];
+  }
+
+  /* If buffersize is not equal to current framesize then increase index
+   * and return. We do no encoding untill we have enough audio.  */
+  if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != FRAMESAMPLES) {
+    ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms;
+    return 0;
+  }
+  /* If buffer reached the right size, reset index and continue with
+   * encoding the frame. */
+  ISACencLB_obj->buffer_index = 0;
+
+  /* End of buffer function. */
+  /**************************/
+
+  /* Encoding */
+  /************/
+
+  if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+    /* This is to avoid Linux warnings until we change 'int' to 'Word32'
+     * at all places. */
+    int intVar;
+    /* reset bitstream */
+    WebRtcIsac_ResetBitstream(&(ISACencLB_obj->bitstr_obj));
+
+    if ((codingMode == 0) && (frame_mode == 0) &&
+        (ISACencLB_obj->enforceFrameSize == 0)) {
+      ISACencLB_obj->new_framelength = WebRtcIsac_GetNewFrameLength(
+          ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+    }
+
+    ISACencLB_obj->s2nr = WebRtcIsac_GetSnr(
+        ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+
+    /* Encode frame length. */
+    status = WebRtcIsac_EncodeFrameLen(
+        ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj);
+    if (status < 0) {
+      /* Wrong frame size. */
+      return status;
+    }
+    /* Save framelength for multiple packets memory. */
+    ISACencLB_obj->SaveEnc_obj.framelength =
+        ISACencLB_obj->current_framesamples;
+
+    /* To be used for Redundant Coding. */
+    ISACencLB_obj->lastBWIdx = bottleneckIndex;
+    intVar = (int)bottleneckIndex;
+    WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj);
+  }
+
+  /* Split signal in two bands. */
+  WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP,
+                                 LP_lookahead, HP_lookahead,
+                                 &ISACencLB_obj->prefiltbankstr_obj);
+
+  /* estimate pitch parameters and pitch-filter lookahead signal */
+  WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf,
+                           &ISACencLB_obj->pitchanalysisstr_obj, PitchLags,
+                           PitchGains);
+
+  /* Encode in FIX Q12. */
+
+  /* Convert PitchGain to Fixed point. */
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchGains_Q12[k] = (int16_t)(PitchGains[k] * 4096.0);
+  }
+
+  /* Set where to store data in multiple packets memory. */
+  if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+    ISACencLB_obj->SaveEnc_obj.startIdx = 0;
+  } else {
+    ISACencLB_obj->SaveEnc_obj.startIdx = 1;
+  }
+
+  /* Quantize & encode pitch parameters. */
+  WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj,
+                             &ISACencLB_obj->SaveEnc_obj);
+  WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12,
+                            &ISACencLB_obj->bitstr_obj,
+                            &ISACencLB_obj->SaveEnc_obj);
+
+  AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+      PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+  /* Find coefficients for perceptual pre-filters. */
+  WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead,
+                          &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr,
+                          PitchGains_Q12, lofilt_coef, hifilt_coef);
+
+  /* Code LPC model and shape - gains not quantized yet. */
+  WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj,
+                         &ISACencLB_obj->SaveEnc_obj);
+
+  /* Convert PitchGains back to FLOAT for pitchfilter_pre. */
+  for (k = 0; k < 4; k++) {
+    PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+  }
+
+  /* Store the state of arithmetic coder before coding LPC gains. */
+  transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper;
+  transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index;
+  transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval;
+  transcodingParam.stream[0] =
+      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+                                       2];
+  transcodingParam.stream[1] =
+      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+                                       1];
+  transcodingParam.stream[2] =
+      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index];
+
+  /* Store LPC Gains before encoding them. */
+  for (k = 0; k < SUBFRAMES; k++) {
+    transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+    transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+  }
+
+  /* Code gains */
+  WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+                             &ISACencLB_obj->bitstr_obj,
+                             &ISACencLB_obj->SaveEnc_obj);
+
+  /* Get the correct value for the payload limit and calculate the
+   * number of bytes left for coding the spectrum. */
+  if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+    /* It is a 60ms and we are in the first 30ms then the limit at
+     * this point should be half of the assigned value. */
+    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1;
+  } else if (frame_mode == 0) {
+    /* It is a 30ms frame */
+    /* Subract 3 because termination process may add 3 bytes. */
+    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
+  } else {
+    /* This is the second half of a 60ms frame. */
+    /* Subract 3 because termination process may add 3 bytes. */
+    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
+  }
+  bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+  /* Perceptual pre-filtering (using normalized lattice filter). */
+  /* Low-band filtering. */
+  WebRtcIsac_NormLatticeFilterMa(ORDERLO,
+                                 ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
+                                 ISACencLB_obj->maskfiltstr_obj.PreStateLoG,
+                                 LP, lofilt_coef, LPw);
+  /* High-band filtering. */
+  WebRtcIsac_NormLatticeFilterMa(ORDERHI,
+                                 ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
+                                 ISACencLB_obj->maskfiltstr_obj.PreStateHiG,
+                                 HP, hifilt_coef, HPw);
+  /* Pitch filter. */
+  WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
+                            PitchLags, PitchGains);
+  /* Transform */
+  WebRtcIsac_Time2Spec(transform_tables,
+                       LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj);
+
+  /* Save data for multiple packets memory. */
+  my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
+  memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+  memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+  ISACencLB_obj->SaveEnc_obj.AvgPitchGain[ISACencLB_obj->SaveEnc_obj.startIdx] =
+      AvgPitchGain_Q12;
+
+  /* Quantization and loss-less coding. */
+  err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+                              &ISACencLB_obj->bitstr_obj);
+  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    /* There has been an error but it was not too large payload
+       (we can cure too large payload). */
+    if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+      /* If this is the second 30ms of a 60ms frame reset
+         this such that in the next call encoder starts fresh. */
+      ISACencLB_obj->frame_nb = 0;
+    }
+    return err;
+  }
+  iterCntr = 0;
+  while ((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    double bytesSpecCoderUsed;
+    double transcodeScale;
+
+    if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+      /* We were not able to limit the payload size */
+      if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+        /* This was the first 30ms of a 60ms frame. Although
+           the payload is larger than it should be but we let
+           the second 30ms be encoded. Maybe together we
+           won't exceed the limit. */
+        ISACencLB_obj->frame_nb = 1;
+        return 0;
+      } else if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
+        ISACencLB_obj->frame_nb = 0;
+      }
+
+      if (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+        return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+      } else {
+        return status;
+      }
+    }
+
+    if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+      bytesSpecCoderUsed = STREAM_SIZE_MAX;
+      /* Being conservative */
+      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+    } else {
+      bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
+          transcodingParam.stream_index;
+      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+    }
+
+    /* To be safe, we reduce the scale depending on
+       the number of iterations. */
+    transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+        (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+    /* Scale the LPC Gains. */
+    for (k = 0; k < SUBFRAMES; k++) {
+      lofilt_coef[(LPC_LOBAND_ORDER + 1) * k] =
+          transcodingParam.loFiltGain[k] * transcodeScale;
+      hifilt_coef[(LPC_HIBAND_ORDER + 1) * k] =
+          transcodingParam.hiFiltGain[k] * transcodeScale;
+      transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+      transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+    }
+
+    /* Scale DFT coefficients. */
+    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+      fre[k] = (int16_t)(fre[k] * transcodeScale);
+      fim[k] = (int16_t)(fim[k] * transcodeScale);
+    }
+
+    /* Save data for multiple packets memory. */
+    my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
+    memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+    memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+    /* Re-store the state of arithmetic coder before coding LPC gains. */
+    ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+    ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+    ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+        transcodingParam.stream[0];
+    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+        transcodingParam.stream[1];
+    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+        transcodingParam.stream[2];
+
+    /* Code gains. */
+    WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+                               &ISACencLB_obj->bitstr_obj,
+                               &ISACencLB_obj->SaveEnc_obj);
+
+    /* Update the number of bytes left for encoding the spectrum. */
+    bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+    /* Encode the spectrum. */
+    err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+                                &ISACencLB_obj->bitstr_obj);
+
+    if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+      /* There has been an error but it was not too large
+         payload (we can cure too large payload). */
+      if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+        /* If this is the second 30 ms of a 60 ms frame reset
+           this such that in the next call encoder starts fresh. */
+        ISACencLB_obj->frame_nb = 0;
+      }
+      return err;
+    }
+    iterCntr++;
+  }
+
+  /* If 60 ms frame-size and just processed the first 30 ms, */
+  /* go back to main function to buffer the other 30 ms speech frame. */
+  if (frame_mode == 1) {
+    if (ISACencLB_obj->frame_nb == 0) {
+      ISACencLB_obj->frame_nb = 1;
+      return 0;
+    } else if (ISACencLB_obj->frame_nb == 1) {
+      ISACencLB_obj->frame_nb = 0;
+      /* Also update the frame-length for next packet,
+         in Adaptive mode only. */
+      if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0)) {
+        ISACencLB_obj->new_framelength =
+            WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
+                                         ISACencLB_obj->current_framesamples);
+      }
+    }
+  } else {
+    ISACencLB_obj->frame_nb = 0;
+  }
+
+  /* Complete arithmetic coding. */
+  stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
+  return stream_length;
+}
+
+
+
+static int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj,
+                          uint16_t payloadLimitBytes,
+                          double bytesLeftSpecCoding,
+                          transcode_obj* transcodingParam,
+                          int16_t* fre, int16_t* fim,
+                          double* lpcGains, enum ISACBand band, int status) {
+
+  int iterCntr = 0;
+  int k;
+  double bytesSpecCoderUsed;
+  double transcodeScale;
+  const int16_t kAveragePitchGain = 0.0;
+
+  do {
+    if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+      /* We were not able to limit the payload size. */
+      return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+    }
+
+    if (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+      bytesSpecCoderUsed = STREAM_SIZE_MAX;
+      /* Being conservative. */
+      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+    } else {
+      bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
+          transcodingParam->stream_index;
+      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+    }
+
+    /* To be safe, we reduce the scale depending on the
+       number of iterations. */
+    transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+        (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+    /* Scale the LPC Gains. */
+    if (band == kIsacUpperBand16) {
+      /* Two sets of coefficients if 16 kHz. */
+      for (k = 0; k < SUBFRAMES; k++) {
+        transcodingParam->loFiltGain[k] *= transcodeScale;
+        transcodingParam->hiFiltGain[k] *= transcodeScale;
+      }
+    } else {
+      /* One sets of coefficients if 12 kHz. */
+      for (k = 0; k < SUBFRAMES; k++) {
+        transcodingParam->loFiltGain[k] *= transcodeScale;
+      }
+    }
+
+    /* Scale DFT coefficients. */
+    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+      fre[k] = (int16_t)(fre[k] * transcodeScale + 0.5);
+      fim[k] = (int16_t)(fim[k] * transcodeScale + 0.5);
+    }
+    /* Store FFT coefficients for multiple encoding. */
+    memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+          sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+    memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+           sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+    /* Store the state of arithmetic coder before coding LPC gains */
+    ISACencUB_obj->bitstr_obj.W_upper = transcodingParam->W_upper;
+    ISACencUB_obj->bitstr_obj.stream_index = transcodingParam->stream_index;
+    ISACencUB_obj->bitstr_obj.streamval = transcodingParam->streamval;
+    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 2] =
+        transcodingParam->stream[0];
+    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 1] =
+        transcodingParam->stream[1];
+    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index] =
+        transcodingParam->stream[2];
+
+    /* Store the gains for multiple encoding. */
+    memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+           SUBFRAMES * sizeof(double));
+    /* Entropy Code lpc-gains, indices are stored for a later use.*/
+    WebRtcIsac_EncodeLpcGainUb(transcodingParam->loFiltGain,
+                               &ISACencUB_obj->bitstr_obj,
+                               ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+    /* If 16kHz should do one more set. */
+    if (band == kIsacUpperBand16) {
+      /* Store the gains for multiple encoding. */
+      memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain[SUBFRAMES],
+             &lpcGains[SUBFRAMES], SUBFRAMES * sizeof(double));
+      /* Entropy Code lpc-gains, indices are stored for a later use.*/
+      WebRtcIsac_EncodeLpcGainUb(
+          transcodingParam->hiFiltGain, &ISACencUB_obj->bitstr_obj,
+          &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+    }
+
+    /* Update the number of bytes left for encoding the spectrum. */
+    bytesLeftSpecCoding = payloadLimitBytes -
+        ISACencUB_obj->bitstr_obj.stream_index;
+
+    /* Save the bit-stream object at this point for FEC. */
+    memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+           &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+    /* Encode the spectrum. */
+    status = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain,
+                                   band, &ISACencUB_obj->bitstr_obj);
+    if ((status < 0) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+      /* There has been an error but it was not too large payload
+         (we can cure too large payload). */
+      return status;
+    }
+    iterCntr++;
+  } while ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+      (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH));
+  return 0;
+}
+
+int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables,
+                          float* in, ISACUBEncStruct* ISACencUB_obj,
+                          int32_t jitterInfo) {
+  int err;
+  int k;
+
+  double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+  double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES << 1) +
+                            (1 + UB_LPC_ORDER)];
+
+  double LP_lookahead[FRAMESAMPLES];
+  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
+  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
+
+  int status = 0;
+
+  double varscale[2];
+  double corr[SUBFRAMES << 1][UB_LPC_ORDER + 1];
+  double lpcGains[SUBFRAMES << 1];
+  transcode_obj transcodingParam;
+  uint16_t payloadLimitBytes;
+  double s2nr;
+  const int16_t kAveragePitchGain = 0.0;
+  int bytesLeftSpecCoding;
+
+  /* Buffer speech samples (by 10ms packet) until the frame-length is   */
+  /* reached (30 ms).                                                   */
+  /*********************************************************************/
+
+  /* fill the buffer with 10ms input data */
+  memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+         FRAMESAMPLES_10ms * sizeof(float));
+
+  /* If buffer size is not equal to current frame-size, and end of file is
+   * not reached yet, we don't do encoding unless we have the whole frame. */
+  if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+    ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+    return 0;
+  }
+
+  /* End of buffer function. */
+  /**************************/
+
+  /* Encoding */
+  /************/
+
+  /* Reset bit-stream */
+  WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+  /* Encoding of bandwidth information. */
+  WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+
+  status = WebRtcIsac_EncodeBandwidth(isac16kHz, &ISACencUB_obj->bitstr_obj);
+  if (status < 0) {
+    return status;
+  }
+
+  s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+  memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
+
+  for (k = 0; k < FRAMESAMPLES; k++) {
+    LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
+  }
+
+  /* Find coefficients for perceptual pre-filters. */
+  WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+                          &lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
+
+  memcpy(ISACencUB_obj->lastLPCVec,
+         &lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
+         sizeof(double) * UB_LPC_ORDER);
+
+  /* Code LPC model and shape - gains not quantized yet. */
+  WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+                         percepFilterParams, isac16kHz,
+                         &ISACencUB_obj->SaveEnc_obj);
+
+  /* the first set of lpc parameters are from the last sub-frame of
+   * the previous frame. so we don't care about them. */
+  WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
+                        (SUBFRAMES << 1), lpcGains, corr, varscale);
+
+  /* Store the state of arithmetic coder before coding LPC gains */
+  transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+  transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+  transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+  transcodingParam.stream[0] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+                                       2];
+  transcodingParam.stream[1] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+                                       1];
+  transcodingParam.stream[2] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+  /* Store LPC Gains before encoding them. */
+  for (k = 0; k < SUBFRAMES; k++) {
+    transcodingParam.loFiltGain[k] = lpcGains[k];
+    transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
+  }
+
+  /* Store the gains for multiple encoding. */
+  memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+         (SUBFRAMES << 1) * sizeof(double));
+
+  WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+                             ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+  WebRtcIsac_EncodeLpcGainUb(
+      &lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
+      &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+
+  /* Get the correct value for the payload limit and calculate the number of
+     bytes left for coding the spectrum. It is a 30ms frame
+     Subract 3 because termination process may add 3 bytes */
+  payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+      ISACencUB_obj->numBytesUsed - 3;
+  bytesLeftSpecCoding = payloadLimitBytes -
+        ISACencUB_obj->bitstr_obj.stream_index;
+
+  for (k = 0; k < (SUBFRAMES << 1); k++) {
+    percepFilterParams[k * (UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
+        lpcGains[k];
+  }
+
+  /* LPC filtering (using normalized lattice filter), */
+  /* first half-frame. */
+  WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+                                 &ISACencUB_obj->data_buffer_float[0],
+                                 &percepFilterParams[UB_LPC_ORDER + 1],
+                                 &LP_lookahead[0]);
+
+  /* Second half-frame filtering. */
+  WebRtcIsac_NormLatticeFilterMa(
+      UB_LPC_ORDER, ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+      ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+      &ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
+      &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)],
+      &LP_lookahead[FRAMESAMPLES_HALF]);
+
+  WebRtcIsac_Time2Spec(transform_tables,
+                       &LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF],
+                       fre, fim, &ISACencUB_obj->fftstr_obj);
+
+  /* Store FFT coefficients for multiple encoding. */
+  memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, sizeof(fre));
+  memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim, sizeof(fim));
+
+  /* Prepare the audio buffer for the next packet
+   * move the last 3 ms to the beginning of the buffer. */
+  memcpy(ISACencUB_obj->data_buffer_float,
+         &ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
+         LB_TOTAL_DELAY_SAMPLES * sizeof(float));
+  /* start writing with 3 ms delay to compensate for the delay
+   * of the lower-band. */
+  ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
+
+  /* Save the bit-stream object at this point for FEC. */
+  memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj, &ISACencUB_obj->bitstr_obj,
+         sizeof(Bitstr));
+
+  /* Qantization and lossless coding */
+  /* Note that there is no pitch-gain for this band so kAveragePitchGain = 0
+   * is passed to the function. In fact, the function ignores the 3rd parameter
+   * for this band. */
+  err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand16,
+                              &ISACencUB_obj->bitstr_obj);
+  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    return err;
+  }
+
+  if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+                         &transcodingParam, fre, fim, lpcGains,
+                         kIsacUpperBand16, err);
+  }
+  if (err < 0) {
+    return err;
+  }
+  /* Complete arithmetic coding. */
+  return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables,
+                          float* in, ISACUBEncStruct* ISACencUB_obj,
+                          int32_t jitterInfo) {
+  int err;
+  int k;
+
+  double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+  double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
+  float LP[FRAMESAMPLES_HALF];
+  float HP[FRAMESAMPLES_HALF];
+
+  double LP_lookahead[FRAMESAMPLES_HALF];
+  double HP_lookahead[FRAMESAMPLES_HALF];
+  double LPw[FRAMESAMPLES_HALF];
+
+  double HPw[FRAMESAMPLES_HALF];
+  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
+  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
+
+  int status = 0;
+
+  double varscale[1];
+
+  double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
+  double lpcGains[SUBFRAMES];
+  transcode_obj transcodingParam;
+  uint16_t payloadLimitBytes;
+  double s2nr;
+  const int16_t kAveragePitchGain = 0.0;
+  double bytesLeftSpecCoding;
+
+  /* Buffer speech samples (by 10ms packet) until the framelength is  */
+  /* reached (30 ms).                                                 */
+  /********************************************************************/
+
+  /* Fill the buffer with 10ms input data. */
+  memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+         FRAMESAMPLES_10ms * sizeof(float));
+
+  /* if buffer-size is not equal to current frame-size then increase the
+     index and return. We do the encoding when we have enough audio.     */
+  if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+    ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+    return 0;
+  }
+  /* If buffer reached the right size, reset index and continue
+     with encoding the frame */
+  ISACencUB_obj->buffer_index = 0;
+
+  /* End of buffer function */
+  /**************************/
+
+  /* Encoding */
+  /************/
+
+  /* Reset bit-stream. */
+  WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+  /* Encoding bandwidth information. */
+  WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+  status = WebRtcIsac_EncodeBandwidth(isac12kHz, &ISACencUB_obj->bitstr_obj);
+  if (status < 0) {
+    return status;
+  }
+
+  s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+  /* Split signal in two bands. */
+  WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
+                                 HP_lookahead, LP_lookahead,
+                                 &ISACencUB_obj->prefiltbankstr_obj);
+
+  /* Find coefficients for perceptual pre-filters. */
+  WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+                          lpcVecs, corr, varscale, isac12kHz);
+
+  /* Code LPC model and shape - gains not quantized yet. */
+  WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+                         percepFilterParams, isac12kHz,
+                         &ISACencUB_obj->SaveEnc_obj);
+
+  WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains, corr,
+                        varscale);
+
+  /* Store the state of arithmetic coder before coding LPC gains. */
+  transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+  transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+  transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+  transcodingParam.stream[0] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+                                       2];
+  transcodingParam.stream[1] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+                                       1];
+  transcodingParam.stream[2] =
+      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+  /* Store LPC Gains before encoding them. */
+  for (k = 0; k < SUBFRAMES; k++) {
+    transcodingParam.loFiltGain[k] = lpcGains[k];
+  }
+
+  /* Store the gains for multiple encoding. */
+  memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
+         sizeof(double));
+
+  WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+                             ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+  for (k = 0; k < SUBFRAMES; k++) {
+    percepFilterParams[k * (UB_LPC_ORDER + 1)] = lpcGains[k];
+  }
+
+  /* perceptual pre-filtering (using normalized lattice filter) */
+  /* low-band filtering */
+  WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP,
+                                 percepFilterParams, LPw);
+
+  /* Get the correct value for the payload limit and calculate the number
+     of bytes left for coding the spectrum. It is a 30ms frame Subract 3
+     because termination process may add 3 bytes */
+  payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+      ISACencUB_obj->numBytesUsed - 3;
+  bytesLeftSpecCoding = payloadLimitBytes -
+      ISACencUB_obj->bitstr_obj.stream_index;
+
+  memset(HPw, 0, sizeof(HPw));
+
+  /* Transform */
+  WebRtcIsac_Time2Spec(transform_tables,
+                       LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj);
+
+  /* Store FFT coefficients for multiple encoding. */
+  memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+         sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+  memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+         sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+  /* Save the bit-stream object at this point for FEC. */
+  memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+         &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+  /* Quantization and loss-less coding */
+  /* The 4th parameter to this function is pitch-gain, which is only used
+   * when encoding 0-8 kHz band, and irrelevant in this function, therefore,
+   * we insert zero here. */
+  err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand12,
+                              &ISACencUB_obj->bitstr_obj);
+  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    /* There has been an error but it was not too large
+       payload (we can cure too large payload) */
+    return err;
+  }
+
+  if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+    err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+                         &transcodingParam, fre, fim, lpcGains,
+                         kIsacUpperBand12, err);
+  }
+  if (err < 0) {
+    return err;
+  }
+  /* Complete arithmetic coding. */
+  return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+
+
+
+
+/* This function is used to create a new bit-stream with new BWE.
+   The same data as previously encoded with the function WebRtcIsac_Encoder().
+   The data needed is taken from the structure, where it was stored
+   when calling the encoder. */
+
+int WebRtcIsac_EncodeStoredDataLb(const IsacSaveEncoderData* ISACSavedEnc_obj,
+                                  Bitstr* ISACBitStr_obj, int BWnumber,
+                                  float scale) {
+  int ii;
+  int status;
+  int BWno = BWnumber;
+
+  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+  const uint16_t** cdf;
+
+  double tmpLPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * 2];
+  double tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * 2];
+  int tmpLPCindex_g[12 * 2];
+  int16_t tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
+  const int kModel = 0;
+
+  /* Sanity Check - possible values for BWnumber is 0 - 23. */
+  if ((BWnumber < 0) || (BWnumber > 23)) {
+    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+  }
+
+  /* Reset bit-stream. */
+  WebRtcIsac_ResetBitstream(ISACBitStr_obj);
+
+  /* Encode frame length */
+  status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
+                                     ISACBitStr_obj);
+  if (status < 0) {
+    /* Wrong frame size. */
+    return status;
+  }
+
+  /* Transcoding */
+  if ((scale > 0.0) && (scale < 1.0)) {
+    /* Compensate LPC gain. */
+    for (ii = 0;
+        ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+        ii++) {
+      tmpLPCcoeffs_lo[ii] = scale *  ISACSavedEnc_obj->LPCcoeffs_lo[ii];
+    }
+    for (ii = 0;
+        ii < ((ORDERHI + 1) * SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+        ii++) {
+      tmpLPCcoeffs_hi[ii] = scale *  ISACSavedEnc_obj->LPCcoeffs_hi[ii];
+    }
+    /* Scale DFT. */
+    for (ii = 0;
+        ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+        ii++) {
+      tmp_fre[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fre[ii]);
+      tmp_fim[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fim[ii]);
+    }
+  } else {
+    for (ii = 0;
+        ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
+        ii++) {
+      tmpLPCindex_g[ii] =  ISACSavedEnc_obj->LPCindex_g[ii];
+    }
+    for (ii = 0;
+        ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+        ii++) {
+      tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
+      tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
+    }
+  }
+
+  /* Encode bandwidth estimate. */
+  WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
+
+  /* Loop over number of 30 msec */
+  for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
+    /* Encode pitch gains. */
+    *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+                            &ISACSavedEnc_obj->pitchGain_index[ii],
+                            WebRtcIsac_kQPitchGainCdf_ptr, 1);
+
+    /* Entropy coding of quantization pitch lags */
+    /* Voicing classification. */
+    if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
+      cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+    } else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
+      cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+    } else {
+      cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+    }
+    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+                            &ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES * ii],
+                            cdf, PITCH_SUBFRAMES);
+
+    /* LPC */
+    /* Only one model exists. The entropy coding is done only for backward
+     * compatibility. */
+    WebRtcIsac_EncHistMulti(ISACBitStr_obj, &kModel,
+                            WebRtcIsac_kQKltModelCdfPtr, 1);
+    /* Entropy coding of quantization indices - LPC shape only. */
+    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+                            &ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE * ii],
+                            WebRtcIsac_kQKltCdfPtrShape,
+                            KLT_ORDER_SHAPE);
+
+    /* If transcoding, get new LPC gain indices */
+    if (scale < 1.0) {
+      WebRtcIsac_TranscodeLPCCoef(
+          &tmpLPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * ii],
+          &tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * ii],
+          &tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
+    }
+
+    /* Entropy coding of quantization indices - LPC gain. */
+    WebRtcIsac_EncHistMulti(ISACBitStr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN * ii],
+                            WebRtcIsac_kQKltCdfPtrGain, KLT_ORDER_GAIN);
+
+    /* Quantization and loss-less coding. */
+    status = WebRtcIsac_EncodeSpec(&tmp_fre[ii * FRAMESAMPLES_HALF],
+                                   &tmp_fim[ii * FRAMESAMPLES_HALF],
+                                   ISACSavedEnc_obj->AvgPitchGain[ii],
+                                   kIsacLowerBand, ISACBitStr_obj);
+    if (status < 0) {
+      return status;
+    }
+  }
+  /* Complete arithmetic coding. */
+  return WebRtcIsac_EncTerminate(ISACBitStr_obj);
+}
+
+
+int WebRtcIsac_EncodeStoredDataUb(
+    const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+    Bitstr* bitStream,
+    int32_t jitterInfo,
+    float scale,
+    enum ISACBandwidth bandwidth) {
+  int n;
+  int err;
+  double lpcGain[SUBFRAMES];
+  int16_t realFFT[FRAMESAMPLES_HALF];
+  int16_t imagFFT[FRAMESAMPLES_HALF];
+  const uint16_t** shape_cdf;
+  int shape_len;
+  const int16_t kAveragePitchGain = 0.0;
+  enum ISACBand band;
+  /* Reset bitstream. */
+  WebRtcIsac_ResetBitstream(bitStream);
+
+  /* Encode jitter index. */
+  WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
+
+  err = WebRtcIsac_EncodeBandwidth(bandwidth, bitStream);
+  if (err < 0) {
+    return err;
+  }
+
+  /* Encode LPC-shape. */
+  if (bandwidth == isac12kHz) {
+    shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb12;
+    shape_len = UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME;
+    band = kIsacUpperBand12;
+  } else {
+    shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb16;
+    shape_len = UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME;
+    band = kIsacUpperBand16;
+  }
+  WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
+                          shape_cdf, shape_len);
+
+  if ((scale <= 0.0) || (scale >= 1.0)) {
+    /* We only consider scales between zero and one. */
+    WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
+                            WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+    if (bandwidth == isac16kHz) {
+      /* Store gain indices of the second half. */
+      WebRtcIsac_EncHistMulti(bitStream,
+                              &ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
+                              WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+    }
+    /* Store FFT coefficients. */
+    err = WebRtcIsac_EncodeSpec(ISACSavedEnc_obj->realFFT,
+                                ISACSavedEnc_obj->imagFFT, kAveragePitchGain,
+                                band, bitStream);
+  } else {
+    /* Scale LPC gain and FFT coefficients. */
+    for (n = 0; n < SUBFRAMES; n++) {
+      lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
+    }
+    /* Store LPC gains. */
+    WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+
+    if (bandwidth == isac16kHz) {
+      /* Scale and code the gains of the second half of the frame, if 16kHz. */
+      for (n = 0; n < SUBFRAMES; n++) {
+        lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
+      }
+      WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+    }
+
+    for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+      realFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->realFFT[n] +
+          0.5f);
+      imagFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->imagFFT[n] +
+          0.5f);
+    }
+    /* Store FFT coefficients. */
+    err = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain,
+                                band, bitStream);
+  }
+  if (err < 0) {
+    /* Error happened while encoding FFT coefficients. */
+    return err;
+  }
+
+  /* Complete arithmetic coding. */
+  return WebRtcIsac_EncTerminate(bitStream);
+}
+
+int16_t WebRtcIsac_GetRedPayloadUb(
+    const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+    Bitstr*                        bitStreamObj,
+    enum ISACBandwidth             bandwidth) {
+  int n;
+  int16_t status;
+  int16_t realFFT[FRAMESAMPLES_HALF];
+  int16_t imagFFT[FRAMESAMPLES_HALF];
+  enum ISACBand band;
+  const int16_t kAveragePitchGain = 0.0;
+  /* Store bit-stream object. */
+  memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
+
+  /* Scale FFT coefficients. */
+  for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+    realFFT[n] = (int16_t)((float)ISACSavedEncObj->realFFT[n] *
+        RCU_TRANSCODING_SCALE_UB + 0.5);
+    imagFFT[n] = (int16_t)((float)ISACSavedEncObj->imagFFT[n] *
+        RCU_TRANSCODING_SCALE_UB + 0.5);
+  }
+
+  band = (bandwidth == isac12kHz) ? kIsacUpperBand12 : kIsacUpperBand16;
+  status = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain, band,
+                                 bitStreamObj);
+  if (status < 0) {
+    return status;
+  } else {
+    /* Terminate entropy coding */
+    return WebRtcIsac_EncTerminate(bitStreamObj);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
new file mode 100644
index 0000000..7b02e64
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
@@ -0,0 +1,706 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * code_LPC_UB.c
+ *
+ * This file contains definition of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ *      -lar                : pointer to lar vectors. LAR vectors are
+ *                            concatenated.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -lar                : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+int16_t
+WebRtcIsac_RemoveLarMean(
+    double* lar,
+    int16_t bandwidth)
+{
+  int16_t coeffCntr;
+  int16_t vecCntr;
+  int16_t numVec;
+  const double* meanLAR;
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        numVec = UB_LPC_VEC_PER_FRAME;
+        meanLAR = WebRtcIsac_kMeanLarUb12;
+        break;
+      }
+    case isac16kHz:
+      {
+        numVec = UB16_LPC_VEC_PER_FRAME;
+        meanLAR = WebRtcIsac_kMeanLarUb16;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+  {
+    for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+    {
+      // REMOVE MEAN
+      *lar++ -= meanLAR[coeffCntr];
+    }
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ *      -inLar              : pointer to mean-removed LAR vecrtors.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : decorrelated LAR vectors.
+ */
+int16_t
+WebRtcIsac_DecorrelateIntraVec(
+    const double* data,
+    double*       out,
+    int16_t bandwidth)
+{
+  const double* ptrData;
+  const double* ptrRow;
+  int16_t rowCntr;
+  int16_t colCntr;
+  int16_t larVecCntr;
+  int16_t numVec;
+  const double* decorrMat;
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+        numVec = UB_LPC_VEC_PER_FRAME;
+        break;
+      }
+    case isac16kHz:
+      {
+        decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+        numVec = UB16_LPC_VEC_PER_FRAME;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  //
+  // decorrMat * data
+  //
+  // data is assumed to contain 'numVec' of LAR
+  // vectors (mean removed) each of dimension 'UB_LPC_ORDER'
+  // concatenated one after the other.
+  //
+
+  ptrData = data;
+  for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
+  {
+    for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+    {
+      ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
+      *out = 0;
+      for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+      {
+        *out += ptrData[colCntr] * ptrRow[colCntr];
+      }
+      out++;
+    }
+    ptrData += UB_LPC_ORDER;
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ *      -data               : pointer to matrix of LAR vectors. The matrix
+ *                            is stored column-wise.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : decorrelated LAR vectors.
+ */
+int16_t
+WebRtcIsac_DecorrelateInterVec(
+    const double* data,
+    double* out,
+    int16_t bandwidth)
+{
+  int16_t coeffCntr;
+  int16_t rowCntr;
+  int16_t colCntr;
+  const double* decorrMat;
+  int16_t interVecDim;
+
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+        interVecDim = UB_LPC_VEC_PER_FRAME;
+        break;
+      }
+    case isac16kHz:
+      {
+        decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+        interVecDim = UB16_LPC_VEC_PER_FRAME;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  //
+  // data * decorrMat
+  //
+  // data is of size 'interVecDim' * 'UB_LPC_ORDER'
+  // That is 'interVecDim' of LAR vectors (mean removed)
+  // in columns each of dimension 'UB_LPC_ORDER'.
+  // matrix is stored column-wise.
+  //
+
+  for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+  {
+    for(colCntr = 0; colCntr < interVecDim; colCntr++)
+    {
+      out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
+      for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+      {
+        out[coeffCntr + colCntr * UB_LPC_ORDER] +=
+            data[coeffCntr + rowCntr * UB_LPC_ORDER] *
+            decorrMat[rowCntr * interVecDim + colCntr];
+      }
+    }
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ *      -data               : uncorrelated LAR vectors.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -data               : quantized version of the input.
+ *      -idx                : pointer to quantization indices.
+ */
+double
+WebRtcIsac_QuantizeUncorrLar(
+    double* data,
+    int* recIdx,
+    int16_t bandwidth)
+{
+  int16_t cntr;
+  int32_t idx;
+  int16_t interVecDim;
+  const double* leftRecPoint;
+  double quantizationStepSize;
+  const int16_t* numQuantCell;
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        leftRecPoint         = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+        quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+        numQuantCell         = WebRtcIsac_kLpcShapeNumRecPointUb12;
+        interVecDim          = UB_LPC_VEC_PER_FRAME;
+        break;
+      }
+    case isac16kHz:
+      {
+        leftRecPoint         = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+        quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+        numQuantCell         = WebRtcIsac_kLpcShapeNumRecPointUb16;
+        interVecDim          = UB16_LPC_VEC_PER_FRAME;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  //
+  // Quantize the parametrs.
+  //
+  for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+  {
+    idx = (int32_t)floor((*data - leftRecPoint[cntr]) /
+                               quantizationStepSize + 0.5);
+    if(idx < 0)
+    {
+      idx = 0;
+    }
+    else if(idx >= numQuantCell[cntr])
+    {
+      idx = numQuantCell[cntr] - 1;
+    }
+
+    *data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
+    *recIdx++ = idx;
+  }
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ *      -idx                : pointer to quantiztion indices.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : pointer to quantized values.
+ */
+int16_t
+WebRtcIsac_DequantizeLpcParam(
+    const int* idx,
+    double*    out,
+    int16_t bandwidth)
+{
+  int16_t cntr;
+  int16_t interVecDim;
+  const double* leftRecPoint;
+  double quantizationStepSize;
+
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        leftRecPoint =         WebRtcIsac_kLpcShapeLeftRecPointUb12;
+        quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+        interVecDim =          UB_LPC_VEC_PER_FRAME;
+        break;
+      }
+    case isac16kHz:
+      {
+        leftRecPoint =         WebRtcIsac_kLpcShapeLeftRecPointUb16;
+        quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+        interVecDim =          UB16_LPC_VEC_PER_FRAME;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  //
+  // Dequantize given the quantization indices
+  //
+
+  for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+  {
+    *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
+  }
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ *      -data               : uncorrelated parameters.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : correlated parametrs.
+ */
+int16_t
+WebRtcIsac_CorrelateIntraVec(
+    const double* data,
+    double*       out,
+    int16_t bandwidth)
+{
+  int16_t vecCntr;
+  int16_t rowCntr;
+  int16_t colCntr;
+  int16_t numVec;
+  const double* ptrData;
+  const double* intraVecDecorrMat;
+
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        numVec            = UB_LPC_VEC_PER_FRAME;
+        intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+        break;
+      }
+    case isac16kHz:
+      {
+        numVec            = UB16_LPC_VEC_PER_FRAME;
+        intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+        break;
+      }
+    default:
+      return -1;
+  }
+
+
+  ptrData = data;
+  for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+  {
+    for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+    {
+      *out = 0;
+      for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+      {
+        *out += ptrData[rowCntr] *
+            intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
+      }
+      out++;
+    }
+    ptrData += UB_LPC_ORDER;
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ *      -data
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : correlated parametrs.
+ */
+int16_t
+WebRtcIsac_CorrelateInterVec(
+    const double* data,
+    double*       out,
+    int16_t bandwidth)
+{
+  int16_t coeffCntr;
+  int16_t rowCntr;
+  int16_t colCntr;
+  int16_t interVecDim;
+  double myVec[UB16_LPC_VEC_PER_FRAME] = {0.0};
+  const double* interVecDecorrMat;
+
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        interVecDim       = UB_LPC_VEC_PER_FRAME;
+        interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+        break;
+      }
+    case isac16kHz:
+      {
+        interVecDim       = UB16_LPC_VEC_PER_FRAME;
+        interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+  {
+    for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+    {
+      myVec[rowCntr] = 0;
+      for(colCntr = 0; colCntr < interVecDim; colCntr++)
+      {
+        myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
+            interVecDecorrMat[rowCntr * interVecDim + colCntr];
+        //ptrData += UB_LPC_ORDER;
+      }
+    }
+
+    for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+    {
+      out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
+    }
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ *      -data               : pointer to mean-removed LAR:s.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -data               : pointer to LARs.
+ */
+int16_t
+WebRtcIsac_AddLarMean(
+    double* data,
+    int16_t bandwidth)
+{
+  int16_t coeffCntr;
+  int16_t vecCntr;
+  int16_t numVec;
+  const double* meanLAR;
+
+  switch(bandwidth)
+  {
+    case isac12kHz:
+      {
+        numVec = UB_LPC_VEC_PER_FRAME;
+        meanLAR = WebRtcIsac_kMeanLarUb12;
+        break;
+      }
+    case isac16kHz:
+      {
+        numVec = UB16_LPC_VEC_PER_FRAME;
+        meanLAR = WebRtcIsac_kMeanLarUb16;
+        break;
+      }
+    default:
+      return -1;
+  }
+
+  for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+  {
+    for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+    {
+      *data++ += meanLAR[coeffCntr];
+    }
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ *      -lpcGain            : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ *      -lpcGain            : mean-removed in log domain.
+ */
+int16_t
+WebRtcIsac_ToLogDomainRemoveMean(
+    double* data)
+{
+  int16_t coeffCntr;
+  for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+  {
+    data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
+  }
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ *      -data               : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ *      -out                : decorrelated parameters.
+ */
+int16_t WebRtcIsac_DecorrelateLPGain(
+    const double* data,
+    double* out)
+{
+  int16_t rowCntr;
+  int16_t colCntr;
+
+  for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+  {
+    *out = 0;
+    for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+    {
+      *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
+    }
+    out++;
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ *      -lpcGain            : uncorrelated LPC gains.
+ *
+ * Output:
+ *      -idx                : quantization indices
+ *      -lpcGain            : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+    double* data,
+    int*    idx)
+{
+  int16_t coeffCntr;
+  for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+  {
+    *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
+                                WebRtcIsac_kQSizeLpcGain + 0.5);
+
+    if(*idx < 0)
+    {
+      *idx = 0;
+    }
+    else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
+    {
+      *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
+    }
+    *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+        WebRtcIsac_kQSizeLpcGain;
+
+    data++;
+    idx++;
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ *      -idx                : pointer to quantization indices.
+ *
+ * Output:
+ *      -lpcGains           : quantized values of the given parametes.
+ */
+int16_t WebRtcIsac_DequantizeLpcGain(
+    const int* idx,
+    double*    out)
+{
+  int16_t coeffCntr;
+  for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+  {
+    *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+        WebRtcIsac_kQSizeLpcGain;
+    out++;
+    idx++;
+  }
+  return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ *      -data               : decorrelated parameters.
+ *
+ * Output:
+ *      -out                : correlated parameters.
+ */
+int16_t WebRtcIsac_CorrelateLpcGain(
+    const double* data,
+    double* out)
+{
+  int16_t rowCntr;
+  int16_t colCntr;
+
+  for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+  {
+    *out = 0;
+    for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+    {
+      *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
+    }
+    out++;
+  }
+
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ *      -lpcGain            : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ *      -lpcGain            : LPC gain in normal domain.
+ */
+int16_t WebRtcIsac_AddMeanToLinearDomain(
+    double* lpcGains)
+{
+  int16_t coeffCntr;
+  for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+  {
+    lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
+  }
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
new file mode 100644
index 0000000..8bc3d75
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
@@ -0,0 +1,246 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode_lpc_swb.h
+ *
+ * This file contains declaration of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ *      -lar                : pointer to lar vectors. LAR vectors are
+ *                            concatenated.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -lar                : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+int16_t WebRtcIsac_RemoveLarMean(double* lar, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ *      -inLar              : pointer to mean-removed LAR vecrtors.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : decorrelated LAR vectors.
+ */
+int16_t WebRtcIsac_DecorrelateIntraVec(const double* inLAR,
+                                       double* out,
+                                       int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ *      -data               : pointer to matrix of LAR vectors. The matrix
+ *                            is stored column-wise.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : decorrelated LAR vectors.
+ */
+int16_t WebRtcIsac_DecorrelateInterVec(const double* data,
+                                       double* out,
+                                       int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ *      -data               : uncorrelated LAR vectors.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -data               : quantized version of the input.
+ *      -idx                : pointer to quantization indices.
+ */
+double WebRtcIsac_QuantizeUncorrLar(double* data, int* idx, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ *      -data               : uncorrelated parameters.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : correlated parametrs.
+ */
+int16_t WebRtcIsac_CorrelateIntraVec(const double* data,
+                                     double* out,
+                                     int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ *      -data
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : correlated parametrs.
+ */
+int16_t WebRtcIsac_CorrelateInterVec(const double* data,
+                                     double* out,
+                                     int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ *      -data               : pointer to mean-removed LAR:s.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -data               : pointer to LARs.
+ */
+int16_t WebRtcIsac_AddLarMean(double* data, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ *      -idx                : pointer to quantiztion indices.
+ *      -bandwidth          : indicates if the given LAR vectors belong
+ *                            to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ *      -out                : pointer to quantized values.
+ */
+int16_t WebRtcIsac_DequantizeLpcParam(const int* idx,
+                                      double* out,
+                                      int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ *      -lpcGain            : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ *      -lpcGain            : mean-removed in log domain.
+ */
+int16_t WebRtcIsac_ToLogDomainRemoveMean(double* lpGains);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ *      -data               : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ *      -out                : decorrelated parameters.
+ */
+int16_t WebRtcIsac_DecorrelateLPGain(const double* data, double* out);
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ *      -lpcGain            : uncorrelated LPC gains.
+ *
+ * Output:
+ *      -idx                : quantization indices
+ *      -lpcGain            : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(double* lpGains, int* idx);
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ *      -idx                : pointer to quantization indices.
+ *
+ * Output:
+ *      -lpcGains           : quantized values of the given parametes.
+ */
+int16_t WebRtcIsac_DequantizeLpcGain(const int* idx, double* lpGains);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ *      -data               : decorrelated parameters.
+ *
+ * Output:
+ *      -out                : correlated parameters.
+ */
+int16_t WebRtcIsac_CorrelateLpcGain(const double* data, double* out);
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ *      -lpcGain            : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ *      -lpcGain            : LPC gain in normal domain.
+ */
+int16_t WebRtcIsac_AddMeanToLinearDomain(double* lpcGains);
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
diff --git a/modules/audio_coding/codecs/isac/main/source/entropy_coding.c b/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
new file mode 100644
index 0000000..188c8f6
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
@@ -0,0 +1,2066 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This header file defines all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+
+#include <math.h>
+#include <string.h>
+
+static const uint16_t kLpcVecPerSegmentUb12 = 5;
+static const uint16_t kLpcVecPerSegmentUb16 = 4;
+
+/* CDF array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const uint16_t kOneBitEqualProbCdf[3] = {
+    0, 32768, 65535 };
+
+/* Pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const uint16_t* const kOneBitEqualProbCdf_ptr[1] = {
+    kOneBitEqualProbCdf };
+
+/*
+ * Initial cdf index for decoder of encoded bandwidth
+ * (12 vs 16 kHz) indicator.
+ */
+static const uint16_t kOneBitEqualProbInitIndex[1] = { 1 };
+
+
+static const int kIsSWB12 = 1;
+
+/* compute correlation from power spectrum */
+static void FindCorrelation(int32_t* PSpecQ12, int32_t* CorrQ7) {
+  int32_t summ[FRAMESAMPLES / 8];
+  int32_t diff[FRAMESAMPLES / 8];
+  const int16_t* CS_ptrQ9;
+  int32_t sum;
+  int k, n;
+
+  for (k = 0; k < FRAMESAMPLES / 8; k++) {
+    summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+    diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+  }
+
+  sum = 2;
+  for (n = 0; n < FRAMESAMPLES / 8; n++) {
+    sum += summ[n];
+  }
+  CorrQ7[0] = sum;
+
+  for (k = 0; k < AR_ORDER; k += 2) {
+    sum = 0;
+    CS_ptrQ9 = WebRtcIsac_kCos[k];
+    for (n = 0; n < FRAMESAMPLES / 8; n++)
+      sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9;
+    CorrQ7[k + 1] = sum;
+  }
+
+  for (k = 1; k < AR_ORDER; k += 2) {
+    sum = 0;
+    CS_ptrQ9 = WebRtcIsac_kCos[k];
+    for (n = 0; n < FRAMESAMPLES / 8; n++)
+      sum += (CS_ptrQ9[n] * summ[n] + 256) >> 9;
+    CorrQ7[k + 1] = sum;
+  }
+}
+
+/* compute inverse AR power spectrum */
+/* Changed to the function used in iSAC FIX for compatibility reasons */
+static void FindInvArSpec(const int16_t* ARCoefQ12,
+                          const int32_t gainQ10,
+                          int32_t* CurveQ16) {
+  int32_t CorrQ11[AR_ORDER + 1];
+  int64_t sum, tmpGain;
+  int32_t diffQ16[FRAMESAMPLES / 8];
+  const int16_t* CS_ptrQ9;
+  int k, n;
+  int16_t round, shftVal = 0, sh;
+
+  sum = 0;
+  for (n = 0; n < AR_ORDER + 1; n++) {
+    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);   /* Q24 */
+  }
+  sum = ((sum >> 6) * 65 + 32768) >> 16;  /* Q8 */
+  CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+  /* To avoid overflow, we shift down gainQ10 if it is large.
+   * We will not lose any precision */
+  if (gainQ10 > 400000) {
+    tmpGain = gainQ10 >> 3;
+    round = 32;
+    shftVal = 6;
+  } else {
+    tmpGain = gainQ10;
+    round = 256;
+    shftVal = 9;
+  }
+
+  for (k = 1; k < AR_ORDER + 1; k++) {
+    sum = 16384;
+    for (n = k; n < AR_ORDER + 1; n++)
+      sum += WEBRTC_SPL_MUL(ARCoefQ12[n - k], ARCoefQ12[n]); /* Q24 */
+    sum >>= 15;
+    CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+  }
+  sum = CorrQ11[0] << 7;
+  for (n = 0; n < FRAMESAMPLES / 8; n++) {
+    CurveQ16[n] = sum;
+  }
+  for (k = 1; k < AR_ORDER; k += 2) {
+    for (n = 0; n < FRAMESAMPLES / 8; n++) {
+      CurveQ16[n] += (WebRtcIsac_kCos[k][n] * CorrQ11[k + 1] + 2) >> 2;
+    }
+  }
+
+  CS_ptrQ9 = WebRtcIsac_kCos[0];
+
+  /* If CorrQ11[1] too large we avoid getting overflow in the
+   * calculation by shifting */
+  sh = WebRtcSpl_NormW32(CorrQ11[1]);
+  if (CorrQ11[1] == 0) { /* Use next correlation */
+    sh = WebRtcSpl_NormW32(CorrQ11[2]);
+  }
+  if (sh < 9) {
+    shftVal = 9 - sh;
+  } else {
+    shftVal = 0;
+  }
+  for (n = 0; n < FRAMESAMPLES / 8; n++) {
+    diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+  }
+  for (k = 2; k < AR_ORDER; k += 2) {
+    CS_ptrQ9 = WebRtcIsac_kCos[k];
+    for (n = 0; n < FRAMESAMPLES / 8; n++) {
+      diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+    }
+  }
+
+  for (k = 0; k < FRAMESAMPLES / 8; k++) {
+    int32_t diff_q16_shifted = (int32_t)((uint32_t)(diffQ16[k]) << shftVal);
+    CurveQ16[FRAMESAMPLES_QUARTER - 1 - k] = CurveQ16[k] - diff_q16_shifted;
+    CurveQ16[k] += diff_q16_shifted;
+  }
+}
+
+/* Generate array of dither samples in Q7. */
+static void GenerateDitherQ7Lb(int16_t* bufQ7, uint32_t seed,
+                               int length, int16_t AvgPitchGain_Q12) {
+  int   k, shft;
+  int16_t dither1_Q7, dither2_Q7, dither_gain_Q14;
+
+  /* This threshold should be equal to that in decode_spec(). */
+  if (AvgPitchGain_Q12 < 614) {
+    for (k = 0; k < length - 2; k += 3) {
+      /* New random unsigned int. */
+      seed = (seed * 196314165) + 907633515;
+
+      /* Fixed-point dither sample between -64 and 64 (Q7). */
+      /* dither = seed * 128 / 4294967295 */
+      dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      /* New random unsigned int. */
+      seed = (seed * 196314165) + 907633515;
+
+      /* Fixed-point dither sample between -64 and 64. */
+      dither2_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      shft = (seed >> 25) & 15;
+      if (shft < 5) {
+        bufQ7[k]   = dither1_Q7;
+        bufQ7[k + 1] = dither2_Q7;
+        bufQ7[k + 2] = 0;
+      } else if (shft < 10) {
+        bufQ7[k]   = dither1_Q7;
+        bufQ7[k + 1] = 0;
+        bufQ7[k + 2] = dither2_Q7;
+      } else {
+        bufQ7[k]   = 0;
+        bufQ7[k + 1] = dither1_Q7;
+        bufQ7[k + 2] = dither2_Q7;
+      }
+    }
+  } else {
+    dither_gain_Q14 = (int16_t)(22528 - 10 * AvgPitchGain_Q12);
+
+    /* Dither on half of the coefficients. */
+    for (k = 0; k < length - 1; k += 2) {
+      /* New random unsigned int */
+      seed = (seed * 196314165) + 907633515;
+
+      /* Fixed-point dither sample between -64 and 64. */
+      dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+      /* Dither sample is placed in either even or odd index. */
+      shft = (seed >> 25) & 1;     /* Either 0 or 1 */
+
+      bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192) >> 14);
+      bufQ7[k + 1 - shft] = 0;
+    }
+  }
+}
+
+
+
+/******************************************************************************
+ * GenerateDitherQ7LbUB()
+ *
+ * generate array of dither samples in Q7 There are less zeros in dither
+ * vector compared to GenerateDitherQ7Lb.
+ *
+ * A uniform random number generator with the range of [-64 64] is employed
+ * but the generated dithers are scaled by 0.35, a heuristic scaling.
+ *
+ * Input:
+ *      -seed               : the initial seed for the random number generator.
+ *      -length             : the number of dither values to be generated.
+ *
+ * Output:
+ *      -bufQ7              : pointer to a buffer where dithers are written to.
+ */
+static void GenerateDitherQ7LbUB(
+    int16_t* bufQ7,
+    uint32_t seed,
+    int length) {
+  int k;
+  for (k = 0; k < length; k++) {
+    /* new random unsigned int */
+    seed = (seed * 196314165) + 907633515;
+
+    /* Fixed-point dither sample between -64 and 64 (Q7). */
+    /* bufQ7 = seed * 128 / 4294967295 */
+    bufQ7[k] = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+    /* Scale by 0.35. */
+    bufQ7[k] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k], 2048, 13);
+  }
+}
+
+/*
+ * Function to decode the complex spectrum from the bit stream
+ * returns the total number of bytes in the stream.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata, int16_t AvgPitchGain_Q12,
+                          enum ISACBand band, double* fr, double* fi) {
+  int16_t  DitherQ7[FRAMESAMPLES];
+  int16_t  data[FRAMESAMPLES];
+  int32_t  invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+  uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
+  int16_t  ARCoefQ12[AR_ORDER + 1];
+  int16_t  RCQ15[AR_ORDER];
+  int16_t  gainQ10;
+  int32_t  gain2_Q10, res;
+  int32_t  in_sqrt;
+  int32_t  newRes;
+  int k, len, i;
+  int is_12khz = !kIsSWB12;
+  int num_dft_coeff = FRAMESAMPLES;
+  /* Create dither signal. */
+  if (band == kIsacLowerBand) {
+    GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES,
+                       AvgPitchGain_Q12);
+  } else {
+    GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
+    if (band == kIsacUpperBand12) {
+      is_12khz = kIsSWB12;
+      num_dft_coeff = FRAMESAMPLES_HALF;
+    }
+  }
+
+  /* Decode model parameters. */
+  if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+  if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+  /* Compute inverse AR power spectrum. */
+  FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+  /* Convert to magnitude spectrum,
+   * by doing square-roots (modified from SPLIB). */
+  res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+    in_sqrt = invARSpec2_Q16[k];
+    i = 10;
+
+    /* Negative values make no sense for a real sqrt-function. */
+    if (in_sqrt < 0)
+      in_sqrt = -in_sqrt;
+
+    newRes = (in_sqrt / res + res) >> 1;
+    do {
+      res = newRes;
+      newRes = (in_sqrt / res + res) >> 1;
+    } while (newRes != res && i-- > 0);
+
+    invARSpecQ8[k] = (int16_t)newRes;
+  }
+
+  len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7,
+                                     num_dft_coeff, is_12khz);
+  /* Arithmetic decoding of spectrum. */
+  if (len < 1) {
+    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+  }
+
+  switch (band) {
+    case kIsacLowerBand: {
+      /* Scale down spectral samples with low SNR. */
+      int32_t p1;
+      int32_t p2;
+      if (AvgPitchGain_Q12 <= 614) {
+        p1 = 30 << 10;
+        p2 = 32768 + (33 << 16);
+      } else {
+        p1 = 36 << 10;
+        p2 = 32768 + (40 << 16);
+      }
+      for (k = 0; k < FRAMESAMPLES; k += 4) {
+        gainQ10 = WebRtcSpl_DivW32W16ResW16(p1, (int16_t)(
+            (invARSpec2_Q16[k >> 2] + p2) >> 16));
+        *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
+        *fi++ = (double)((data[k + 1] * gainQ10 + 512) >> 10) / 128.0;
+        *fr++ = (double)((data[k + 2] * gainQ10 + 512) >> 10) / 128.0;
+        *fi++ = (double)((data[k + 3] * gainQ10 + 512) >> 10) / 128.0;
+      }
+      break;
+    }
+    case kIsacUpperBand12: {
+      for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4) {
+        fr[i] = (double)data[ k ] / 128.0;
+        fi[i] = (double)data[k + 1] / 128.0;
+        i++;
+        fr[i] = (double)data[k + 2] / 128.0;
+        fi[i] = (double)data[k + 3] / 128.0;
+        i++;
+      }
+      /* The second half of real and imaginary coefficients is zero. This is
+       * due to using the old FFT module which requires two signals as input
+       * while in 0-12 kHz mode we only have 8-12 kHz band, and the second
+       * signal is set to zero. */
+      memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+             sizeof(double));
+      memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+             sizeof(double));
+      break;
+    }
+    case kIsacUpperBand16: {
+      for (i = 0, k = 0; k < FRAMESAMPLES; k += 4, i++) {
+        fr[i] = (double)data[ k ] / 128.0;
+        fi[i] = (double)data[k + 1] / 128.0;
+        fr[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 2] / 128.0;
+        fi[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 3] / 128.0;
+      }
+      break;
+    }
+  }
+  return len;
+}
+
+
+int WebRtcIsac_EncodeSpec(const int16_t* fr, const int16_t* fi,
+                          int16_t AvgPitchGain_Q12, enum ISACBand band,
+                          Bitstr* streamdata) {
+  int16_t ditherQ7[FRAMESAMPLES];
+  int16_t dataQ7[FRAMESAMPLES];
+  int32_t PSpec[FRAMESAMPLES_QUARTER];
+  int32_t invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+  uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
+  int32_t CorrQ7[AR_ORDER + 1];
+  int32_t CorrQ7_norm[AR_ORDER + 1];
+  int16_t RCQ15[AR_ORDER];
+  int16_t ARCoefQ12[AR_ORDER + 1];
+  int32_t gain2_Q10;
+  int16_t val;
+  int32_t nrg, res;
+  uint32_t sum;
+  int32_t in_sqrt;
+  int32_t newRes;
+  int16_t err;
+  uint32_t nrg_u32;
+  int shift_var;
+  int k, n, j, i;
+  int is_12khz = !kIsSWB12;
+  int num_dft_coeff = FRAMESAMPLES;
+
+  /* Create dither signal. */
+  if (band == kIsacLowerBand) {
+    GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES,
+                       AvgPitchGain_Q12);
+  } else {
+    GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
+    if (band == kIsacUpperBand12) {
+      is_12khz = kIsSWB12;
+      num_dft_coeff = FRAMESAMPLES_HALF;
+    }
+  }
+
+  /* add dither and quantize, and compute power spectrum */
+  switch (band) {
+    case kIsacLowerBand: {
+      for (k = 0; k < FRAMESAMPLES; k += 4) {
+        val = ((*fr++ + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
+        dataQ7[k] = val;
+        sum = val * val;
+
+        val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+        dataQ7[k + 1] = val;
+        sum += val * val;
+
+        val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+        dataQ7[k + 2] = val;
+        sum += val * val;
+
+        val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+        dataQ7[k + 3] = val;
+        sum += val * val;
+
+        PSpec[k >> 2] = sum >> 2;
+      }
+      break;
+    }
+    case kIsacUpperBand12: {
+      for (k = 0, j = 0; k < FRAMESAMPLES_HALF; k += 4) {
+        val = ((*fr++ + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
+        dataQ7[k] = val;
+        sum = val * val;
+
+        val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+        dataQ7[k + 1] = val;
+        sum += val * val;
+
+        PSpec[j++] = sum >> 1;
+
+        val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+        dataQ7[k + 2] = val;
+        sum = val * val;
+
+        val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+        dataQ7[k + 3] = val;
+        sum += val * val;
+
+        PSpec[j++] = sum >> 1;
+      }
+      break;
+    }
+    case kIsacUpperBand16: {
+      for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) {
+        val = ((fr[j] + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
+        dataQ7[k] = val;
+        sum = val * val;
+
+        val = ((fi[j] + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+        dataQ7[k + 1] = val;
+        sum += val * val;
+
+        val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 2] + 64) &
+            0xFF80) - ditherQ7[k + 2];
+        dataQ7[k + 2] = val;
+        sum += val * val;
+
+        val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 3] + 64) &
+            0xFF80) - ditherQ7[k + 3];
+        dataQ7[k + 3] = val;
+        sum += val * val;
+
+        PSpec[k >> 2] = sum >> 2;
+      }
+      break;
+    }
+  }
+
+  /* compute correlation from power spectrum */
+  FindCorrelation(PSpec, CorrQ7);
+
+  /* Find AR coefficients */
+  /* Aumber of bit shifts to 14-bit normalize CorrQ7[0]
+   * (leaving room for sign) */
+  shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+  if (shift_var > 0) {
+    for (k = 0; k < AR_ORDER + 1; k++) {
+      CorrQ7_norm[k] = CorrQ7[k] << shift_var;
+    }
+  } else {
+    for (k = 0; k < AR_ORDER + 1; k++) {
+      CorrQ7_norm[k] = CorrQ7[k] >> (-shift_var);
+    }
+  }
+
+  /* Find RC coefficients. */
+  WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+  /* Quantize & code RC Coefficient. */
+  WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+  /* RC -> AR coefficients */
+  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+  /* Compute ARCoef' * Corr * ARCoef in Q19. */
+  nrg = 0;
+  for (j = 0; j <= AR_ORDER; j++) {
+    for (n = 0; n <= j; n++) {
+      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
+          4) >> 3;
+    }
+    for (n = j + 1; n <= AR_ORDER; n++) {
+      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
+          4) >> 3;
+    }
+  }
+
+  nrg_u32 = (uint32_t)nrg;
+  if (shift_var > 0) {
+    nrg_u32 = nrg_u32 >> shift_var;
+  } else {
+    nrg_u32 = nrg_u32 << (-shift_var);
+  }
+  if (nrg_u32 > 0x7FFFFFFF) {
+    nrg = 0x7FFFFFFF;
+  }  else {
+    nrg = (int32_t)nrg_u32;
+  }
+  /* Also shifts 31 bits to the left! */
+  gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg);
+
+  /* Quantize & code gain2_Q10. */
+  if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+    return -1;
+  }
+
+  /* Compute inverse AR power spectrum. */
+  FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+  /* Convert to magnitude spectrum, by doing square-roots
+   * (modified from SPLIB). */
+  res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+    in_sqrt = invARSpec2_Q16[k];
+    i = 10;
+    /* Negative values make no sense for a real sqrt-function. */
+    if (in_sqrt < 0) {
+      in_sqrt = -in_sqrt;
+    }
+    newRes = (in_sqrt / res + res) >> 1;
+    do {
+      res = newRes;
+      newRes = (in_sqrt / res + res) >> 1;
+    } while (newRes != res && i-- > 0);
+
+    invARSpecQ8[k] = (int16_t)newRes;
+  }
+  /* arithmetic coding of spectrum */
+  err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+                                     num_dft_coeff, is_12khz);
+  if (err < 0) {
+    return (err);
+  }
+  return 0;
+}
+
+
+/* step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a) {
+  int m, k;
+  double tmp[MAX_AR_MODEL_ORDER];
+
+  a[0] = 1.0;
+  tmp[0] = 1.0;
+  for (m = 1; m <= N; m++) {
+    /* copy */
+    memcpy(&tmp[1], &a[1], (m - 1) * sizeof(double));
+    a[m] = RC[m - 1];
+    for (k = 1; k < m; k++) {
+      a[k] += RC[m - 1] * tmp[m - k];
+    }
+  }
+  return;
+}
+
+/* step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC) {
+  int m, k;
+  double tmp[MAX_AR_MODEL_ORDER];
+  double tmp_inv;
+
+  RC[N - 1] = a[N];
+  for (m = N - 1; m > 0; m--) {
+    tmp_inv = 1.0 / (1.0 - RC[m] * RC[m]);
+    for (k = 1; k <= m; k++) {
+      tmp[k] = (a[k] - RC[m] * a[m - k + 1]) * tmp_inv;
+    }
+
+    memcpy(&a[1], &tmp[1], (m - 1) * sizeof(double));
+    RC[m - 1] = tmp[m];
+  }
+  return;
+}
+
+
+#define MAX_ORDER 100
+
+/* Matlab's LAR definition */
+void WebRtcIsac_Rc2Lar(const double* refc, double* lar, int order) {
+  int k;
+  for (k = 0; k < order; k++) {
+    lar[k] = log((1 + refc[k]) / (1 - refc[k]));
+  }
+}
+
+
+void WebRtcIsac_Lar2Rc(const double* lar, double* refc,  int order) {
+  int k;
+  double tmp;
+
+  for (k = 0; k < order; k++) {
+    tmp = exp(lar[k]);
+    refc[k] = (tmp - 1) / (tmp + 1);
+  }
+}
+
+void WebRtcIsac_Poly2Lar(double* lowband, int orderLo, double* hiband,
+                         int orderHi, int Nsub, double* lars) {
+  int k;
+  double rc[MAX_ORDER], *inpl, *inph, *outp;
+
+  inpl = lowband;
+  inph = hiband;
+  outp = lars;
+  for (k = 0; k < Nsub; k++) {
+    /* gains */
+    outp[0] = inpl[0];
+    outp[1] = inph[0];
+    outp += 2;
+
+    /* Low band */
+    inpl[0] = 1.0;
+    WebRtcIsac_Poly2Rc(inpl, orderLo, rc);
+    WebRtcIsac_Rc2Lar(rc, outp, orderLo);
+    outp += orderLo;
+
+    /* High band */
+    inph[0] = 1.0;
+    WebRtcIsac_Poly2Rc(inph, orderHi, rc);
+    WebRtcIsac_Rc2Lar(rc, outp, orderHi);
+    outp += orderHi;
+
+    inpl += orderLo + 1;
+    inph += orderHi + 1;
+  }
+}
+
+
+int16_t WebRtcIsac_Poly2LarUB(double* lpcVecs, int16_t bandwidth) {
+  double      poly[MAX_ORDER];
+  double      rc[MAX_ORDER];
+  double*     ptrIO;
+  int16_t vecCntr;
+  int16_t vecSize;
+  int16_t numVec;
+
+  vecSize = UB_LPC_ORDER;
+  switch (bandwidth) {
+    case isac12kHz: {
+      numVec  = UB_LPC_VEC_PER_FRAME;
+      break;
+    }
+    case isac16kHz: {
+      numVec  = UB16_LPC_VEC_PER_FRAME;
+      break;
+    }
+    default:
+      return -1;
+  }
+
+  ptrIO = lpcVecs;
+  poly[0] = 1.0;
+  for (vecCntr = 0; vecCntr < numVec; vecCntr++) {
+    memcpy(&poly[1], ptrIO, sizeof(double) * vecSize);
+    WebRtcIsac_Poly2Rc(poly, vecSize, rc);
+    WebRtcIsac_Rc2Lar(rc, ptrIO, vecSize);
+    ptrIO += vecSize;
+  }
+  return 0;
+}
+
+
+void WebRtcIsac_Lar2Poly(double* lars, double* lowband, int orderLo,
+                         double* hiband, int orderHi, int Nsub) {
+  int k, orderTot;
+  double rc[MAX_ORDER], *outpl, *outph, *inp;
+
+  orderTot = (orderLo + orderHi + 2);
+  outpl = lowband;
+  outph = hiband;
+  /* First two elements of 'inp' store gains*/
+  inp = lars;
+  for (k = 0; k < Nsub; k++) {
+    /* Low band */
+    WebRtcIsac_Lar2Rc(&inp[2], rc, orderLo);
+    WebRtcIsac_Rc2Poly(rc, orderLo, outpl);
+
+    /* High band */
+    WebRtcIsac_Lar2Rc(&inp[orderLo + 2], rc, orderHi);
+    WebRtcIsac_Rc2Poly(rc, orderHi, outph);
+
+    /* gains */
+    outpl[0] = inp[0];
+    outph[0] = inp[1];
+
+    outpl += orderLo + 1;
+    outph += orderHi + 1;
+    inp += orderTot;
+  }
+}
+
+/*
+ *  assumes 2 LAR vectors interpolates to 'numPolyVec' A-polynomials
+ *  Note: 'numPolyVecs' includes the first and the last point of the interval
+ */
+void WebRtcIsac_Lar2PolyInterpolUB(double* larVecs, double* percepFilterParams,
+                                   int numPolyVecs) {
+  int polyCntr, coeffCntr;
+  double larInterpol[UB_LPC_ORDER];
+  double rc[UB_LPC_ORDER];
+  double delta[UB_LPC_ORDER];
+
+  /* calculate the step-size for linear interpolation coefficients */
+  for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+    delta[coeffCntr] = (larVecs[UB_LPC_ORDER + coeffCntr] -
+        larVecs[coeffCntr]) / (numPolyVecs - 1);
+  }
+
+  for (polyCntr = 0; polyCntr < numPolyVecs; polyCntr++) {
+    for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+      larInterpol[coeffCntr] = larVecs[coeffCntr] +
+          delta[coeffCntr] * polyCntr;
+    }
+    WebRtcIsac_Lar2Rc(larInterpol, rc, UB_LPC_ORDER);
+
+    /* convert to A-polynomial, the following function returns A[0] = 1;
+     * which is written where gains had to be written. Then we write the
+     * gain (outside this function). This way we say a memcpy. */
+    WebRtcIsac_Rc2Poly(rc, UB_LPC_ORDER, percepFilterParams);
+    percepFilterParams += (UB_LPC_ORDER + 1);
+  }
+}
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata, double* LPCCoef_lo,
+                         double* LPCCoef_hi) {
+  double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+  int err;
+
+  err = WebRtcIsac_DecodeLpcCoef(streamdata, lars);
+  if (err < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_LPC;
+  }
+  WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+                      SUBFRAMES);
+  return 0;
+}
+
+int16_t WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+                                       double* percepFilterParams,
+                                       int16_t bandwidth) {
+  double lpcCoeff[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+  int err;
+  int interpolCntr;
+  int subframeCntr;
+  int16_t numSegments;
+  int16_t numVecPerSegment;
+  int16_t numGains;
+
+  double percepFilterGains[SUBFRAMES << 1];
+  double* ptrOutParam = percepFilterParams;
+
+  err = WebRtcIsac_DecodeLpcCoefUB(streamdata, lpcCoeff, percepFilterGains,
+                                   bandwidth);
+  if (err < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_LPC;
+  }
+
+  switch (bandwidth) {
+    case isac12kHz: {
+      numGains = SUBFRAMES;
+      numSegments = UB_LPC_VEC_PER_FRAME - 1;
+      numVecPerSegment = kLpcVecPerSegmentUb12;
+      break;
+    }
+    case isac16kHz: {
+      numGains = SUBFRAMES << 1;
+      numSegments = UB16_LPC_VEC_PER_FRAME - 1;
+      numVecPerSegment = kLpcVecPerSegmentUb16;
+      break;
+    }
+    default:
+      return -1;
+  }
+
+  for (interpolCntr = 0; interpolCntr < numSegments; interpolCntr++) {
+    WebRtcIsac_Lar2PolyInterpolUB(&lpcCoeff[interpolCntr * UB_LPC_ORDER],
+                                  ptrOutParam, numVecPerSegment + 1);
+    ptrOutParam += (numVecPerSegment * (UB_LPC_ORDER + 1));
+  }
+
+  ptrOutParam = percepFilterParams;
+
+  if (bandwidth == isac16kHz) {
+    ptrOutParam += (1 + UB_LPC_ORDER);
+  }
+
+  for (subframeCntr = 0; subframeCntr < numGains; subframeCntr++) {
+    *ptrOutParam = percepFilterGains[subframeCntr];
+    ptrOutParam += (1 + UB_LPC_ORDER);
+  }
+  return 0;
+}
+
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef) {
+  int j, k, n, pos, pos2, posg, poss, offsg, offss, offs2;
+  int index_g[KLT_ORDER_GAIN], index_s[KLT_ORDER_SHAPE];
+  double tmpcoeffs_g[KLT_ORDER_GAIN], tmpcoeffs_s[KLT_ORDER_SHAPE];
+  double tmpcoeffs2_g[KLT_ORDER_GAIN], tmpcoeffs2_s[KLT_ORDER_SHAPE];
+  double sum;
+  int err;
+  int model = 1;
+
+  /* entropy decoding of model number */
+  /* We are keeping this for backward compatibility of bit-streams. */
+  err = WebRtcIsac_DecHistOneStepMulti(&model, streamdata,
+                                       WebRtcIsac_kQKltModelCdfPtr,
+                                       WebRtcIsac_kQKltModelInitIndex, 1);
+  if (err < 0) {
+    return err;
+  }
+  /* Only accepted value of model is 0. It is kept in bit-stream for backward
+   * compatibility. */
+  if (model != 0) {
+    return -ISAC_DISALLOWED_LPC_MODEL;
+  }
+
+  /* entropy decoding of quantization indices */
+  err = WebRtcIsac_DecHistOneStepMulti(
+      index_s, streamdata, WebRtcIsac_kQKltCdfPtrShape,
+      WebRtcIsac_kQKltInitIndexShape, KLT_ORDER_SHAPE);
+  if (err < 0) {
+    return err;
+  }
+  err = WebRtcIsac_DecHistOneStepMulti(
+      index_g, streamdata, WebRtcIsac_kQKltCdfPtrGain,
+      WebRtcIsac_kQKltInitIndexGain, KLT_ORDER_GAIN);
+  if (err < 0) {
+    return err;
+  }
+
+  /* find quantization levels for coefficients */
+  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+    tmpcoeffs_s[k] =
+        WebRtcIsac_kQKltLevelsShape[WebRtcIsac_kQKltOffsetShape[k] +
+                                    index_s[k]];
+  }
+  for (k = 0; k < KLT_ORDER_GAIN; k++) {
+    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOffsetGain[k] +
+                                                index_g[k]];
+  }
+
+  /* Inverse KLT  */
+
+  /* Left transform, transpose matrix!  */
+  offsg = 0;
+  offss = 0;
+  posg = 0;
+  poss = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    offs2 = 0;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = offsg;
+      pos2 = offs2;
+      for (n = 0; n < LPC_GAIN_ORDER; n++) {
+        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+      }
+      tmpcoeffs2_g[posg++] = sum;
+      offs2 += LPC_GAIN_ORDER;
+    }
+    offs2 = 0;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = offss;
+      pos2 = offs2;
+      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+      }
+      tmpcoeffs2_s[poss++] = sum;
+      offs2 += LPC_SHAPE_ORDER;
+    }
+    offsg += LPC_GAIN_ORDER;
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* Right transform, transpose matrix */
+  offsg = 0;
+  offss = 0;
+  posg = 0;
+  poss = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = j;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+        pos += LPC_GAIN_ORDER;
+        pos2 += SUBFRAMES;
+
+      }
+      tmpcoeffs_g[posg++] = sum;
+    }
+    poss = offss;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = j;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+        pos += LPC_SHAPE_ORDER;
+        pos2 += SUBFRAMES;
+      }
+      tmpcoeffs_s[poss++] = sum;
+    }
+    offsg += LPC_GAIN_ORDER;
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* scaling, mean addition, and gain restoration */
+  posg = 0;
+  poss = 0;
+  pos = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    /* log gains */
+    LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+    LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+    LPCCoef[pos] = exp(LPCCoef[pos]);
+    pos++;
+    posg++;
+    LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+    LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+    LPCCoef[pos] = exp(LPCCoef[pos]);
+    pos++;
+    posg++;
+
+    /* Low-band LAR coefficients. */
+    for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+    }
+
+    /* High-band LAR coefficients. */
+    for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+    }
+  }
+  return 0;
+}
+
+/* Encode LPC in LAR domain. */
+void WebRtcIsac_EncodeLar(double* LPCCoef, Bitstr* streamdata,
+                          IsacSaveEncoderData* encData) {
+  int j, k, n, pos, pos2, poss, offss, offs2;
+  int index_s[KLT_ORDER_SHAPE];
+  int index_ovr_s[KLT_ORDER_SHAPE];
+  double tmpcoeffs_s[KLT_ORDER_SHAPE];
+  double tmpcoeffs2_s[KLT_ORDER_SHAPE];
+  double sum;
+  const int kModel = 0;
+
+  /* Mean removal and scaling. */
+  poss = 0;
+  pos = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    /* First two element are gains, move over them. */
+    pos += 2;
+
+    /* Low-band LAR coefficients. */
+    for (n = 0; n < LPC_LOBAND_ORDER; n++, poss++, pos++) {
+      tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+      tmpcoeffs_s[poss] *= LPC_LOBAND_SCALE;
+    }
+
+    /* High-band LAR coefficients. */
+    for (n = 0; n < LPC_HIBAND_ORDER; n++, poss++, pos++) {
+      tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+      tmpcoeffs_s[poss] *= LPC_HIBAND_SCALE;
+    }
+  }
+
+  /* KLT  */
+
+  /* Left transform. */
+  offss = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    poss = offss;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = offss;
+      pos2 = k;
+      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2];
+        pos2 += LPC_SHAPE_ORDER;
+      }
+      tmpcoeffs2_s[poss++] = sum;
+    }
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* Right transform. */
+  offss = 0;
+  offs2 = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    poss = offss;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = offs2;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2++];
+        pos += LPC_SHAPE_ORDER;
+      }
+      tmpcoeffs_s[poss++] = sum;
+    }
+    offs2 += SUBFRAMES;
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* Quantize coefficients. */
+  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+    index_s[k] = (WebRtcIsac_lrint(tmpcoeffs_s[k] / KLT_STEPSIZE)) +
+        WebRtcIsac_kQKltQuantMinShape[k];
+    if (index_s[k] < 0) {
+      index_s[k] = 0;
+    } else if (index_s[k] > WebRtcIsac_kQKltMaxIndShape[k]) {
+      index_s[k] = WebRtcIsac_kQKltMaxIndShape[k];
+    }
+    index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[k] + index_s[k];
+  }
+
+
+  /* Only one model remains in this version of the code, kModel = 0. We
+   * are keeping for bit-streams to be backward compatible. */
+  /* entropy coding of model number */
+  WebRtcIsac_EncHistMulti(streamdata, &kModel, WebRtcIsac_kQKltModelCdfPtr, 1);
+
+  /* Save data for creation of multiple bit streams */
+  /* Entropy coding of quantization indices - shape only. */
+  WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape,
+                          KLT_ORDER_SHAPE);
+
+  /* Save data for creation of multiple bit streams. */
+  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+    encData->LPCindex_s[KLT_ORDER_SHAPE * encData->startIdx + k] = index_s[k];
+  }
+
+  /* Find quantization levels for shape coefficients. */
+  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+    tmpcoeffs_s[k] = WebRtcIsac_kQKltLevelsShape[index_ovr_s[k]];
+  }
+  /* Inverse KLT.  */
+  /* Left transform, transpose matrix.! */
+  offss = 0;
+  poss = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    offs2 = 0;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = offss;
+      pos2 = offs2;
+      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+      }
+      tmpcoeffs2_s[poss++] = sum;
+      offs2 += LPC_SHAPE_ORDER;
+    }
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* Right transform, Transpose matrix */
+  offss = 0;
+  poss = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    poss = offss;
+    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = j;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+        pos += LPC_SHAPE_ORDER;
+        pos2 += SUBFRAMES;
+      }
+      tmpcoeffs_s[poss++] = sum;
+    }
+    offss += LPC_SHAPE_ORDER;
+  }
+
+  /* Scaling, mean addition, and gain restoration. */
+  poss = 0;
+  pos = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    /* Ignore gains. */
+    pos += 2;
+
+    /* Low band LAR coefficients. */
+    for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+    }
+
+    /* High band LAR coefficients. */
+    for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+    }
+  }
+}
+
+
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo, double* LPCCoef_hi,
+                            Bitstr* streamdata, IsacSaveEncoderData* encData) {
+  double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+  int k;
+
+  WebRtcIsac_Poly2Lar(LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI, SUBFRAMES,
+                      lars);
+  WebRtcIsac_EncodeLar(lars, streamdata, encData);
+  WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+                      SUBFRAMES);
+  /* Save data for creation of multiple bit streams (and transcoding). */
+  for (k = 0; k < (ORDERLO + 1)*SUBFRAMES; k++) {
+    encData->LPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * encData->startIdx + k] =
+        LPCCoef_lo[k];
+  }
+  for (k = 0; k < (ORDERHI + 1)*SUBFRAMES; k++) {
+    encData->LPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * encData->startIdx + k] =
+        LPCCoef_hi[k];
+  }
+}
+
+
+int16_t WebRtcIsac_EncodeLpcUB(double* lpcVecs, Bitstr* streamdata,
+                               double* interpolLPCCoeff,
+                               int16_t bandwidth,
+                                     ISACUBSaveEncDataStruct* encData) {
+  double    U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+  int     idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+  int interpolCntr;
+
+  WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth);
+  WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth);
+  WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth);
+  WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth);
+  WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth);
+
+  WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+  WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+  WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+
+  switch (bandwidth) {
+    case isac12kHz: {
+      /* Store the indices to be used for multiple encoding. */
+      memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+             UB_LPC_VEC_PER_FRAME * sizeof(int));
+      WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12,
+                              UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+      for (interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS;
+          interpolCntr++) {
+        WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+                                      kLpcVecPerSegmentUb12 + 1);
+        lpcVecs += UB_LPC_ORDER;
+        interpolLPCCoeff += (kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1));
+      }
+      break;
+    }
+    case isac16kHz: {
+      /* Store the indices to be used for multiple encoding. */
+      memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+             UB16_LPC_VEC_PER_FRAME * sizeof(int));
+      WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16,
+                              UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+      for (interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS;
+          interpolCntr++) {
+        WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+                                      kLpcVecPerSegmentUb16 + 1);
+        lpcVecs += UB_LPC_ORDER;
+        interpolLPCCoeff += (kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1));
+      }
+      break;
+    }
+    default:
+      return -1;
+  }
+  return 0;
+}
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo, double* LPCCoef_hi,
+                                Bitstr* streamdata,
+                                IsacSaveEncoderData* encData) {
+  int j, k, n, pos, pos2, posg, offsg, offs2;
+  int index_g[KLT_ORDER_GAIN];
+  int index_ovr_g[KLT_ORDER_GAIN];
+  double tmpcoeffs_g[KLT_ORDER_GAIN];
+  double tmpcoeffs2_g[KLT_ORDER_GAIN];
+  double sum;
+  /* log gains, mean removal and scaling */
+  posg = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+    posg++;
+    tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+    posg++;
+  }
+
+  /* KLT  */
+
+  /* Left transform. */
+  offsg = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = offsg;
+      pos2 = k;
+      for (n = 0; n < LPC_GAIN_ORDER; n++) {
+        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+        pos2 += LPC_GAIN_ORDER;
+      }
+      tmpcoeffs2_g[posg++] = sum;
+    }
+    offsg += LPC_GAIN_ORDER;
+  }
+
+  /* Right transform. */
+  offsg = 0;
+  offs2 = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = offs2;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+        pos += LPC_GAIN_ORDER;
+      }
+      tmpcoeffs_g[posg++] = sum;
+    }
+    offs2 += SUBFRAMES;
+    offsg += LPC_GAIN_ORDER;
+  }
+
+  /* Quantize coefficients. */
+  for (k = 0; k < KLT_ORDER_GAIN; k++) {
+    /* Get index. */
+    pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+    index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+    if (index_g[k] < 0) {
+      index_g[k] = 0;
+    } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+      index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+    }
+    index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+    /* Find quantization levels for coefficients. */
+    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+
+    /* Save data for creation of multiple bit streams. */
+    encData->LPCindex_g[KLT_ORDER_GAIN * encData->startIdx + k] = index_g[k];
+  }
+
+  /* Entropy coding of quantization indices - gain. */
+  WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain,
+                          KLT_ORDER_GAIN);
+
+  /* Find quantization levels for coefficients. */
+  /* Left transform. */
+  offsg = 0;
+  posg = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    offs2 = 0;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = offsg;
+      pos2 = offs2;
+      for (n = 0; n < LPC_GAIN_ORDER; n++)
+        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+      tmpcoeffs2_g[posg++] = sum;
+      offs2 += LPC_GAIN_ORDER;
+    }
+    offsg += LPC_GAIN_ORDER;
+  }
+
+  /* Right transform, transpose matrix. */
+  offsg = 0;
+  posg = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = j;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+        pos += LPC_GAIN_ORDER;
+        pos2 += SUBFRAMES;
+      }
+      tmpcoeffs_g[posg++] = sum;
+    }
+    offsg += LPC_GAIN_ORDER;
+  }
+
+
+  /* Scaling, mean addition, and gain restoration. */
+  posg = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+    sum += WebRtcIsac_kLpcMeansGain[posg];
+    LPCCoef_lo[k * (LPC_LOBAND_ORDER + 1)] = exp(sum);
+    pos++;
+    posg++;
+    sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+    sum += WebRtcIsac_kLpcMeansGain[posg];
+    LPCCoef_hi[k * (LPC_HIBAND_ORDER + 1)] = exp(sum);
+    pos++;
+    posg++;
+  }
+
+}
+
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains, Bitstr* streamdata,
+                                int* lpcGainIndex) {
+  double U[UB_LPC_GAIN_DIM];
+  int idx[UB_LPC_GAIN_DIM];
+  WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+  WebRtcIsac_DecorrelateLPGain(lpGains, U);
+  WebRtcIsac_QuantizeLpcGain(U, idx);
+  /* Store the index for re-encoding for FEC. */
+  memcpy(lpcGainIndex, idx, UB_LPC_GAIN_DIM * sizeof(int));
+  WebRtcIsac_CorrelateLpcGain(U, lpGains);
+  WebRtcIsac_AddMeanToLinearDomain(lpGains);
+  WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+                          UB_LPC_GAIN_DIM);
+}
+
+
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata) {
+  double U[UB_LPC_GAIN_DIM];
+  int idx[UB_LPC_GAIN_DIM];
+  WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+  WebRtcIsac_DecorrelateLPGain(lpGains, U);
+  WebRtcIsac_QuantizeLpcGain(U, idx);
+  WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+                          UB_LPC_GAIN_DIM);
+}
+
+
+
+int16_t WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata) {
+  double U[UB_LPC_GAIN_DIM];
+  int idx[UB_LPC_GAIN_DIM];
+  int err;
+  err = WebRtcIsac_DecHistOneStepMulti(idx, streamdata,
+                                       WebRtcIsac_kLpcGainCdfMat,
+                                       WebRtcIsac_kLpcGainEntropySearch,
+                                       UB_LPC_GAIN_DIM);
+  if (err < 0) {
+    return -1;
+  }
+  WebRtcIsac_DequantizeLpcGain(idx, U);
+  WebRtcIsac_CorrelateLpcGain(U, lpGains);
+  WebRtcIsac_AddMeanToLinearDomain(lpGains);
+  return 0;
+}
+
+
+
+/* decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, int16_t* RCQ15) {
+  int k, err;
+  int index[AR_ORDER];
+
+  /* entropy decoding of quantization indices */
+  err = WebRtcIsac_DecHistOneStepMulti(index, streamdata,
+                                       WebRtcIsac_kQArRcCdfPtr,
+                                       WebRtcIsac_kQArRcInitIndex, AR_ORDER);
+  if (err < 0)
+    return err;
+
+  /* find quantization levels for reflection coefficients */
+  for (k = 0; k < AR_ORDER; k++) {
+    RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+  }
+  return 0;
+}
+
+
+/* quantize & code RC */
+void WebRtcIsac_EncodeRc(int16_t* RCQ15, Bitstr* streamdata) {
+  int k;
+  int index[AR_ORDER];
+
+  /* quantize reflection coefficients (add noise feedback?) */
+  for (k = 0; k < AR_ORDER; k++) {
+    index[k] = WebRtcIsac_kQArRcInitIndex[k];
+    // The safe-guards in following while conditions are to suppress gcc 4.8.3
+    // warnings, Issue 2888. Otherwise, first and last elements of
+    // `WebRtcIsac_kQArBoundaryLevels` are such that the following search
+    // *never* cause an out-of-boundary read.
+    if (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k]]) {
+      while (index[k] + 1 < NUM_AR_RC_QUANT_BAUNDARY &&
+        RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1]) {
+        index[k]++;
+      }
+    } else {
+      while (index[k] > 0 &&
+        RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ;
+    }
+    RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+  }
+
+  /* entropy coding of quantization indices */
+  WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER);
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, int32_t* gainQ10) {
+  int index, err;
+
+  /* entropy decoding of quantization index */
+  err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata,
+                                       WebRtcIsac_kQGainCdf_ptr,
+                                       WebRtcIsac_kQGainInitIndex, 1);
+  if (err < 0) {
+    return err;
+  }
+  /* find quantization level */
+  *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+  return 0;
+}
+
+
+/* quantize & code squared Gain */
+int WebRtcIsac_EncodeGain2(int32_t* gainQ10, Bitstr* streamdata) {
+  int index;
+
+  /* find quantization index */
+  index = WebRtcIsac_kQGainInitIndex[0];
+  if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index]) {
+    while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1]) {
+      index++;
+    }
+  } else {
+    while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ;
+  }
+  /* De-quantize */
+  *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+
+  /* entropy coding of quantization index */
+  WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1);
+  return 0;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata,
+                               int16_t* PitchGains_Q12) {
+  int index_comb, err;
+  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+
+  /* Entropy decoding of quantization indices */
+  *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+  err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata,
+                                      WebRtcIsac_kQPitchGainCdf_ptr,
+                                      WebRtcIsac_kQCdfTableSizeGain, 1);
+  /* Error check, Q_mean_Gain.. tables are of size 144 */
+  if ((err < 0) || (index_comb < 0) || (index_comb >= 144)) {
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+  }
+  /* De-quantize back to pitch gains by table look-up. */
+  PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+  PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+  PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+  PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+  return 0;
+}
+
+
+/* Quantize & code Pitch Gains. */
+void WebRtcIsac_EncodePitchGain(int16_t* PitchGains_Q12,
+                                Bitstr* streamdata,
+                                IsacSaveEncoderData* encData) {
+  int k, j;
+  double C;
+  double S[PITCH_SUBFRAMES];
+  int index[3];
+  int index_comb;
+  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+  double PitchGains[PITCH_SUBFRAMES] = {0, 0, 0, 0};
+
+  /* Take the asin. */
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+    S[k] = asin(PitchGains[k]);
+  }
+
+  /* Find quantization index; only for the first three
+   * transform coefficients. */
+  for (k = 0; k < 3; k++) {
+    /*  transform */
+    C = 0.0;
+    for (j = 0; j < PITCH_SUBFRAMES; j++) {
+      C += WebRtcIsac_kTransform[k][j] * S[j];
+    }
+    /* Quantize */
+    index[k] = WebRtcIsac_lrint(C / PITCH_GAIN_STEPSIZE);
+
+    /* Check that the index is not outside the boundaries of the table. */
+    if (index[k] < WebRtcIsac_kIndexLowerLimitGain[k]) {
+      index[k] = WebRtcIsac_kIndexLowerLimitGain[k];
+    } else if (index[k] > WebRtcIsac_kIndexUpperLimitGain[k]) {
+      index[k] = WebRtcIsac_kIndexUpperLimitGain[k];
+    }
+    index[k] -= WebRtcIsac_kIndexLowerLimitGain[k];
+  }
+
+  /* Calculate unique overall index. */
+  index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] +
+      WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2];
+
+  /* unquantize back to pitch gains by table look-up */
+  PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+  PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+  PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+  PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+
+  /* entropy coding of quantization pitch gains */
+  *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+  WebRtcIsac_EncHistMulti(streamdata, &index_comb,
+                          WebRtcIsac_kQPitchGainCdf_ptr, 1);
+  encData->pitchGain_index[encData->startIdx] = index_comb;
+}
+
+
+
+/* Pitch LAG */
+/* Decode & de-quantize Pitch Lags. */
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata, int16_t* PitchGain_Q12,
+                              double* PitchLags) {
+  int k, err;
+  double StepSize;
+  double C;
+  int index[PITCH_SUBFRAMES];
+  double mean_gain;
+  const double* mean_val2, *mean_val3, *mean_val4;
+  const int16_t* lower_limit;
+  const uint16_t* init_index;
+  const uint16_t* cdf_size;
+  const uint16_t** cdf;
+  double PitchGain[4] = {0, 0, 0, 0};
+
+  /* compute mean pitch gain */
+  mean_gain = 0.0;
+  for (k = 0; k < 4; k++) {
+    PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+    mean_gain += PitchGain[k];
+  }
+  mean_gain /= 4.0;
+
+  /* voicing classification. */
+  if (mean_gain < 0.2) {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+    cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo;
+    mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+    mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+    mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+    lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+    init_index = WebRtcIsac_kQInitIndexLagLo;
+  } else if (mean_gain < 0.4) {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+    cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid;
+    mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+    mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+    mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+    lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+    init_index = WebRtcIsac_kQInitIndexLagMid;
+  } else {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+    cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi;
+    mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+    mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+    mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+    lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+    init_index = WebRtcIsac_kQInitIndexLagHi;
+  }
+
+  /* Entropy decoding of quantization indices. */
+  err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+  if ((err < 0) || (index[0] < 0)) {
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+  }
+  err = WebRtcIsac_DecHistOneStepMulti(index + 1, streamdata, cdf + 1,
+                                       init_index, 3);
+  if (err < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+  }
+
+  /* Unquantize back to transform coefficients and do the inverse transform:
+   * S = T'*C. */
+  C = (index[0] + lower_limit[0]) * StepSize;
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+  }
+  C = mean_val2[index[1]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+  }
+  C = mean_val3[index[2]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+  }
+  C = mean_val4[index[3]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+  }
+  return 0;
+}
+
+
+
+/* Quantize & code pitch lags. */
+void WebRtcIsac_EncodePitchLag(double* PitchLags, int16_t* PitchGain_Q12,
+                               Bitstr* streamdata,
+                               IsacSaveEncoderData* encData) {
+  int k, j;
+  double StepSize;
+  double C;
+  int index[PITCH_SUBFRAMES];
+  double mean_gain;
+  const double* mean_val2, *mean_val3, *mean_val4;
+  const int16_t* lower_limit, *upper_limit;
+  const uint16_t** cdf;
+  double PitchGain[4] = {0, 0, 0, 0};
+
+  /* compute mean pitch gain */
+  mean_gain = 0.0;
+  for (k = 0; k < 4; k++) {
+    PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+    mean_gain += PitchGain[k];
+  }
+  mean_gain /= 4.0;
+
+  /* Save data for creation of multiple bit streams */
+  encData->meanGain[encData->startIdx] = mean_gain;
+
+  /* Voicing classification. */
+  if (mean_gain < 0.2) {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+    mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+    mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+    mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+    lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+    upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo;
+  } else if (mean_gain < 0.4) {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+    mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+    mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+    mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+    lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+    upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid;
+  } else {
+    StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+    cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+    mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+    mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+    mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+    lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+    upper_limit = WebRtcIsac_kQindexUpperLimitLagHi;
+  }
+
+  /* find quantization index */
+  for (k = 0; k < 4; k++) {
+    /*  transform */
+    C = 0.0;
+    for (j = 0; j < PITCH_SUBFRAMES; j++) {
+      C += WebRtcIsac_kTransform[k][j] * PitchLags[j];
+    }
+    /* quantize */
+    index[k] = WebRtcIsac_lrint(C / StepSize);
+
+    /* check that the index is not outside the boundaries of the table */
+    if (index[k] < lower_limit[k]) {
+      index[k] = lower_limit[k];
+    } else if (index[k] > upper_limit[k]) index[k] = upper_limit[k]; {
+      index[k] -= lower_limit[k];
+    }
+    /* Save data for creation of multiple bit streams */
+    encData->pitchIndex[PITCH_SUBFRAMES * encData->startIdx + k] = index[k];
+  }
+
+  /* Un-quantize back to transform coefficients and do the inverse transform:
+   * S = T'*C */
+  C = (index[0] + lower_limit[0]) * StepSize;
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+  }
+  C = mean_val2[index[1]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+  }
+  C = mean_val3[index[2]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+  }
+  C = mean_val4[index[3]];
+  for (k = 0; k < PITCH_SUBFRAMES; k++) {
+    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+  }
+  /* entropy coding of quantization pitch lags */
+  WebRtcIsac_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+}
+
+
+
+/* Routines for in-band signaling of bandwidth estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const uint16_t WebRtcIsac_kFrameLengthCdf[4] = {
+    0, 21845, 43690, 65535 };
+
+/* pointer to cdf array for frame length indicator */
+const uint16_t* WebRtcIsac_kFrameLengthCdf_ptr[1] = {
+    WebRtcIsac_kFrameLengthCdf };
+
+/* initial cdf index for decoder of frame length indicator */
+const uint16_t WebRtcIsac_kFrameLengthInitIndex[1] = { 1 };
+
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, int16_t* framesamples) {
+  int frame_mode, err;
+  err = 0;
+  /* entropy decoding of frame length [1:30ms,2:60ms] */
+  err = WebRtcIsac_DecHistOneStepMulti(&frame_mode, streamdata,
+                                       WebRtcIsac_kFrameLengthCdf_ptr,
+                                       WebRtcIsac_kFrameLengthInitIndex, 1);
+  if (err < 0)
+    return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
+
+  switch (frame_mode) {
+    case 1:
+      *framesamples = 480; /* 30ms */
+      break;
+    case 2:
+      *framesamples = 960; /* 60ms */
+      break;
+    default:
+      err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
+  }
+  return err;
+}
+
+int WebRtcIsac_EncodeFrameLen(int16_t framesamples, Bitstr* streamdata) {
+  int frame_mode, status;
+
+  status = 0;
+  frame_mode = 0;
+  /* entropy coding of frame length [1:480 samples,2:960 samples] */
+  switch (framesamples) {
+    case 480:
+      frame_mode = 1;
+      break;
+    case 960:
+      frame_mode = 2;
+      break;
+    default:
+      status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
+  }
+
+  if (status < 0)
+    return status;
+
+  WebRtcIsac_EncHistMulti(streamdata, &frame_mode,
+                          WebRtcIsac_kFrameLengthCdf_ptr, 1);
+  return status;
+}
+
+/* cdf array for estimated bandwidth */
+static const uint16_t kBwCdf[25] = {
+    0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
+    32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
+    62804, 65535 };
+
+/* pointer to cdf array for estimated bandwidth */
+static const uint16_t* const kBwCdfPtr[1] = { kBwCdf };
+
+/* initial cdf index for decoder of estimated bandwidth*/
+static const uint16_t kBwInitIndex[1] = { 7 };
+
+
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, int16_t* BWno) {
+  int BWno32, err;
+
+  /* entropy decoding of sender's BW estimation [0..23] */
+  err = WebRtcIsac_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr,
+                                       kBwInitIndex, 1);
+  if (err < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+  }
+  *BWno = (int16_t)BWno32;
+  return err;
+}
+
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata) {
+  /* entropy encoding of receiver's BW estimation [0..23] */
+  WebRtcIsac_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+}
+
+
+/* estimate code length of LPC Coef */
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo, double* LPCCoef_hi,
+                                 int* index_g) {
+  int j, k, n, pos, pos2, posg, offsg, offs2;
+  int index_ovr_g[KLT_ORDER_GAIN];
+  double tmpcoeffs_g[KLT_ORDER_GAIN];
+  double tmpcoeffs2_g[KLT_ORDER_GAIN];
+  double sum;
+
+  /* log gains, mean removal and scaling */
+  posg = 0;
+  for (k = 0; k < SUBFRAMES; k++) {
+    tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+    posg++;
+    tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+    posg++;
+  }
+
+  /* KLT  */
+
+  /* Left transform. */
+  offsg = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = offsg;
+      pos2 = k;
+      for (n = 0; n < LPC_GAIN_ORDER; n++) {
+        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+        pos2 += LPC_GAIN_ORDER;
+      }
+      tmpcoeffs2_g[posg++] = sum;
+    }
+    offsg += LPC_GAIN_ORDER;
+  }
+
+  /* Right transform. */
+  offsg = 0;
+  offs2 = 0;
+  for (j = 0; j < SUBFRAMES; j++) {
+    posg = offsg;
+    for (k = 0; k < LPC_GAIN_ORDER; k++) {
+      sum = 0;
+      pos = k;
+      pos2 = offs2;
+      for (n = 0; n < SUBFRAMES; n++) {
+        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+        pos += LPC_GAIN_ORDER;
+      }
+      tmpcoeffs_g[posg++] = sum;
+    }
+    offs2 += SUBFRAMES;
+    offsg += LPC_GAIN_ORDER;
+  }
+
+
+  /* quantize coefficients */
+  for (k = 0; k < KLT_ORDER_GAIN; k++) {
+    /* Get index. */
+    pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+    index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+    if (index_g[k] < 0) {
+      index_g[k] = 0;
+    } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+      index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+    }
+    index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+    /* find quantization levels for coefficients */
+    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+  }
+}
+
+
+/* Decode & de-quantize LPC Coefficients. */
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata, double* lpcVecs,
+                               double* percepFilterGains,
+                               int16_t bandwidth) {
+  int  index_s[KLT_ORDER_SHAPE];
+
+  double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+  int err;
+
+  /* Entropy decoding of quantization indices. */
+  switch (bandwidth) {
+    case isac12kHz: {
+      err = WebRtcIsac_DecHistOneStepMulti(
+          index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb12,
+          WebRtcIsac_kLpcShapeEntropySearchUb12, UB_LPC_ORDER *
+          UB_LPC_VEC_PER_FRAME);
+      break;
+    }
+    case isac16kHz: {
+      err = WebRtcIsac_DecHistOneStepMulti(
+          index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb16,
+          WebRtcIsac_kLpcShapeEntropySearchUb16, UB_LPC_ORDER *
+          UB16_LPC_VEC_PER_FRAME);
+      break;
+    }
+    default:
+      return -1;
+  }
+
+  if (err < 0) {
+    return err;
+  }
+
+  WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth);
+  WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+  WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+  WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+  WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata);
+
+  if (bandwidth == isac16kHz) {
+    /* Decode another set of Gains. */
+    WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata);
+  }
+  return 0;
+}
+
+int16_t WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+                                   Bitstr* streamData) {
+  int bandwidthMode;
+  switch (bandwidth) {
+    case isac12kHz: {
+      bandwidthMode = 0;
+      break;
+    }
+    case isac16kHz: {
+      bandwidthMode = 1;
+      break;
+    }
+    default:
+      return -ISAC_DISALLOWED_ENCODER_BANDWIDTH;
+  }
+  WebRtcIsac_EncHistMulti(streamData, &bandwidthMode, kOneBitEqualProbCdf_ptr,
+                          1);
+  return 0;
+}
+
+int16_t WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+                                   enum ISACBandwidth* bandwidth) {
+  int bandwidthMode;
+  if (WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData,
+                                     kOneBitEqualProbCdf_ptr,
+                                     kOneBitEqualProbInitIndex, 1) < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+  }
+  switch (bandwidthMode) {
+    case 0: {
+      *bandwidth = isac12kHz;
+      break;
+    }
+    case 1: {
+      *bandwidth = isac16kHz;
+      break;
+    }
+    default:
+      return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER;
+  }
+  return 0;
+}
+
+int16_t WebRtcIsac_EncodeJitterInfo(int32_t jitterIndex,
+                                    Bitstr* streamData) {
+  /* This is to avoid LINUX warning until we change 'int' to 'Word32'. */
+  int intVar;
+
+  if ((jitterIndex < 0) || (jitterIndex > 1)) {
+    return -1;
+  }
+  intVar = (int)(jitterIndex);
+  /* Use the same CDF table as for bandwidth
+   * both take two values with equal probability.*/
+  WebRtcIsac_EncHistMulti(streamData, &intVar, kOneBitEqualProbCdf_ptr, 1);
+  return 0;
+}
+
+int16_t WebRtcIsac_DecodeJitterInfo(Bitstr* streamData,
+                                    int32_t* jitterInfo) {
+  int intVar;
+  /* Use the same CDF table as for bandwidth
+   * both take two values with equal probability. */
+  if (WebRtcIsac_DecHistOneStepMulti(&intVar, streamData,
+                                     kOneBitEqualProbCdf_ptr,
+                                     kOneBitEqualProbInitIndex, 1) < 0) {
+    return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+  }
+  *jitterInfo = (int16_t)(intVar);
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/entropy_coding.h b/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
new file mode 100644
index 0000000..6c2b8d3
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
@@ -0,0 +1,347 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file declares all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpec()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *  - AvgPitchGain_Q12      : average pitch-gain of the frame. This is only
+ *                            relevant for 0-4 kHz band, and the input value is
+ *                            not used in other bands.
+ *  - band                  : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ *   - *fr                  : pointer to a buffer where the real part of DFT
+ *                            coefficients are written to.
+ *   - *fi                  : pointer to a buffer where the imaginary part
+ *                            of DFT coefficients are written to.
+ *
+ * Return value             : < 0 if an error occures
+ *                              0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata,
+                          int16_t AvgPitchGain_Q12,
+                          enum ISACBand band,
+                          double* fr,
+                          double* fi);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpec()
+ * Encode real and imaginary part of the DFT coefficients into the given
+ * bit-stream.
+ *
+ * Input:
+ *  - *fr                   : pointer to a buffer where the real part of DFT
+ *                            coefficients are written to.
+ *  - *fi                   : pointer to a buffer where the imaginary part
+ *                            of DFT coefficients are written to.
+ *  - AvgPitchGain_Q12      : average pitch-gain of the frame. This is only
+ *                            relevant for 0-4 kHz band, and the input value is
+ *                            not used in other bands.
+ *  - band                  : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Return value             : < 0 if an error occures
+ *                              0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpec(const int16_t* fr,
+                          const int16_t* fi,
+                          int16_t AvgPitchGain_Q12,
+                          enum ISACBand band,
+                          Bitstr* streamdata);
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef);
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata,
+                               double* lpcVecs,
+                               double* percepFilterGains,
+                               int16_t bandwidth);
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata,
+                         double* LPCCoef_lo,
+                         double* LPCCoef_hi);
+
+/* quantize & code LPC Coef */
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo,
+                            double* LPCCoef_hi,
+                            Bitstr* streamdata,
+                            IsacSaveEncoderData* encData);
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo,
+                                double* LPCCoef_hi,
+                                Bitstr* streamdata,
+                                IsacSaveEncoderData* encData);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcUB()
+ * Encode LPC parameters, given as A-polynomial, of upper-band. The encoding
+ * is performed in LAR domain.
+ * For the upper-band, we compute and encode LPC of some sub-frames, LPC of
+ * other sub-frames are computed by linear interpolation, in LAR domain. This
+ * function performs the interpolation and returns the LPC of all sub-frames.
+ *
+ * Inputs:
+ *  - lpcCoef               : a buffer containing A-polynomials of sub-frames
+ *                            (excluding first coefficient that is 1).
+ *  - bandwidth             : specifies if the codec is operating at 0-12 kHz
+ *                            or 0-16 kHz mode.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a structure containing the encoded
+ *                            data and the parameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - interpolLPCCoeff      : Decoded and interpolated LPC (A-polynomial)
+ *                            of all sub-frames.
+ *                            If LP analysis is of order K, and there are N
+ *                            sub-frames then this is a buffer of size
+ *                            (k + 1) * N, each vector starts with the LPC gain
+ *                            of the corresponding sub-frame. The LPC gains
+ *                            are encoded and inserted after this function is
+ *                            called. The first A-coefficient which is 1 is not
+ *                            included.
+ *
+ * Return value             : 0 if encoding is successful,
+ *                           <0 if failed to encode.
+ */
+int16_t WebRtcIsac_EncodeLpcUB(double* lpcCoeff,
+                               Bitstr* streamdata,
+                               double* interpolLPCCoeff,
+                               int16_t bandwidth,
+                               ISACUBSaveEncDataStruct* encData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeInterpolLpcUb()
+ * Decode LPC coefficients and interpolate to get the coefficients fo all
+ * sub-frmaes.
+ *
+ * Inputs:
+ *  - bandwidth             : spepecifies if the codec is in 0-12 kHz or
+ *                            0-16 kHz mode.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - percepFilterParam     : Decoded and interpolated LPC (A-polynomial) of
+ *                            all sub-frames.
+ *                            If LP analysis is of order K, and there are N
+ *                            sub-frames then this is a buffer of size
+ *                            (k + 1) * N, each vector starts with the LPC gain
+ *                            of the corresponding sub-frame. The LPC gains
+ *                            are encoded and inserted after this function is
+ *                            called. The first A-coefficient which is 1 is not
+ *                            included.
+ *
+ * Return value             : 0 if encoding is successful,
+ *                           <0 if failed to encode.
+ */
+int16_t WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+                                       double* percepFilterParam,
+                                       int16_t bandwidth);
+
+/* Decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, int16_t* RCQ15);
+
+/* Quantize & code RC */
+void WebRtcIsac_EncodeRc(int16_t* RCQ15, Bitstr* streamdata);
+
+/* Decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, int32_t* Gain2);
+
+/* Quantize & code squared Gain (input is squared gain) */
+int WebRtcIsac_EncodeGain2(int32_t* gain2, Bitstr* streamdata);
+
+void WebRtcIsac_EncodePitchGain(int16_t* PitchGains_Q12,
+                                Bitstr* streamdata,
+                                IsacSaveEncoderData* encData);
+
+void WebRtcIsac_EncodePitchLag(double* PitchLags,
+                               int16_t* PitchGain_Q12,
+                               Bitstr* streamdata,
+                               IsacSaveEncoderData* encData);
+
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata, int16_t* PitchGain_Q12);
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata,
+                              int16_t* PitchGain_Q12,
+                              double* PitchLag);
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, int16_t* framelength);
+int WebRtcIsac_EncodeFrameLen(int16_t framelength, Bitstr* streamdata);
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, int16_t* BWno);
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata);
+
+/* Step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC);
+
+/* Step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a);
+
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo,
+                                 double* LPCCoef_hi,
+                                 int* index_g);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Encode LPC gains of sub-Frames.
+ *
+ * Input/outputs:
+ *  - lpGains               : a buffer which contains 'SUBFRAME' number of
+ *                            LP gains to be encoded. The input values are
+ *                            overwritten by the quantized values.
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - lpcGainIndex          : quantization indices for lpc gains, these will
+ *                            be stored to be used  for FEC.
+ */
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains,
+                                Bitstr* streamdata,
+                                int* lpcGainIndex);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Store LPC gains of sub-Frames in 'streamdata'.
+ *
+ * Input:
+ *  - lpGains               : a buffer which contains 'SUBFRAME' number of
+ *                            LP gains to be encoded.
+ * Input/outputs:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ */
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeLpcGainUb()
+ * Decode the LPC gain of sub-frames.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - lpGains               : a buffer where decoded LPC gians will be stored.
+ *
+ * Return value             : 0 if succeeded.
+ *                           <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeBandwidth()
+ * Encode if the bandwidth of encoded audio is 0-12 kHz or 0-16 kHz.
+ *
+ * Input:
+ *  - bandwidth             : an enumerator specifying if the codec in is
+ *                            0-12 kHz or 0-16 kHz mode.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Return value             : 0 if succeeded.
+ *                           <0 if failed.
+ */
+int16_t WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+                                   Bitstr* streamData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeBandwidth()
+ * Decode the bandwidth of the encoded audio, i.e. if the bandwidth is 0-12 kHz
+ * or 0-16 kHz.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - bandwidth             : an enumerator specifying if the codec is in
+ *                            0-12 kHz or 0-16 kHz mode.
+ *
+ * Return value             : 0 if succeeded.
+ *                           <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+                                   enum ISACBandwidth* bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Input:
+ *  - jitterInfo            : one bit of info specifying if the channel is
+ *                            in high/low jitter. Zero indicates low jitter
+ *                            and one indicates high jitter.
+ *
+ * Return value             : 0 if succeeded.
+ *                           <0 if failed.
+ */
+int16_t WebRtcIsac_EncodeJitterInfo(int32_t jitterIndex, Bitstr* streamData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ *  - streamdata            : pointer to a stucture containg the encoded
+ *                            data and theparameters needed for entropy
+ *                            coding.
+ *
+ * Output:
+ *  - jitterInfo            : one bit of info specifying if the channel is
+ *                            in high/low jitter. Zero indicates low jitter
+ *                            and one indicates high jitter.
+ *
+ * Return value             : 0 if succeeded.
+ *                           <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeJitterInfo(Bitstr* streamData, int32_t* jitterInfo);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/filterbanks.c b/modules/audio_coding/codecs/isac/main/source/filterbanks.c
new file mode 100644
index 0000000..d57b550
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/filterbanks.c
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function WebRtcIsac_AllPassFilter2Float,
+ * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+/* Combining */
+
+/* HPstcoeff_out_1 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut1Float[4] =
+{-1.99701049409000f, 0.99714204490000f, 0.01701049409000f, -0.01704204490000f};
+
+/* HPstcoeff_out_2 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut2Float[4] =
+{-1.98645294509837f, 0.98672435560000f, 0.00645294509837f, -0.00662435560000f};
+
+
+/* Function WebRtcIsac_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+   length FRAMESAMPLES_HALF input low-pass and
+   high-pass signals and creates a reconstructed fullband
+   output signal of length FRAMESAMPLES. WebRtcIsac_FilterAndCombine
+   is the sibling function of WebRtcIsac_SplitAndFilter */
+/* INPUTS:
+   inLP: a length FRAMESAMPLES_HALF array of input low-pass
+   samples.
+   inHP: a length FRAMESAMPLES_HALF array of input high-pass
+   samples.
+   postfiltdata: input data structure containing the filterbank
+   states from the previous decoding iteration.
+   OUTPUTS:
+   Out: a length FRAMESAMPLES array of output reconstructed
+   samples (fullband) based on the input low-pass and
+   high-pass signals.
+   postfiltdata: the input data structure containing the filterbank
+   states is updated for the next decoding iteration */
+void WebRtcIsac_FilterAndCombineFloat(float *InLP,
+                                      float *InHP,
+                                      float *Out,
+                                      PostFiltBankstr *postfiltdata)
+{
+  int k;
+  float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+  float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+  float ftmp, ftmp2;
+
+  /* Form the polyphase signals*/
+  for (k=0;k<FRAMESAMPLES_HALF;k++) {
+    tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/
+    tempin_ch2[k]=InLP[k]-InHP[k]; /* Construct a new lower channel signal*/
+  }
+
+
+  /* all-pass filter the new upper channel signal. HOWEVER, use the all-pass filter factors
+     that were used as a lower channel at the encoding side.  So at the decoder, the
+     corresponding all-pass filter factors for each channel are swapped.*/
+  WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat,
+                                 FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_float);
+
+  /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors
+     at the decoder are swapped from the ones at the encoder, the 'upper' channel
+     all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new
+     lower channel signal */
+  WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
+                                 FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
+
+
+  /* Merge outputs to form the full length output signal.*/
+  for (k=0;k<FRAMESAMPLES_HALF;k++) {
+    Out[2*k]=tempin_ch2[k];
+    Out[2*k+1]=tempin_ch1[k];
+  }
+
+
+  /* High pass filter */
+
+  for (k=0;k<FRAMESAMPLES;k++) {
+    ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] +
+        kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
+    ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
+        kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
+    postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
+    postfiltdata->HPstates1_float[0] = ftmp;
+    Out[k] = ftmp2;
+  }
+
+  for (k=0;k<FRAMESAMPLES;k++) {
+    ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] +
+        kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
+    ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
+        kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
+    postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
+    postfiltdata->HPstates2_float[0] = ftmp;
+    Out[k] = ftmp2;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/intialize.c b/modules/audio_coding/codecs/isac/main/source/intialize.c
new file mode 100644
index 0000000..5c951f6
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/intialize.c
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* encode.c  - Encoding function for the iSAC coder */
+
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+
+void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) {
+
+  int k;
+
+  for (k = 0; k < WINLEN; k++) {
+    maskdata->DataBufferLo[k] = 0.0;
+    maskdata->DataBufferHi[k] = 0.0;
+  }
+  for (k = 0; k < ORDERLO+1; k++) {
+    maskdata->CorrBufLo[k] = 0.0;
+    maskdata->PreStateLoF[k] = 0.0;
+    maskdata->PreStateLoG[k] = 0.0;
+    maskdata->PostStateLoF[k] = 0.0;
+    maskdata->PostStateLoG[k] = 0.0;
+  }
+  for (k = 0; k < ORDERHI+1; k++) {
+    maskdata->CorrBufHi[k] = 0.0;
+    maskdata->PreStateHiF[k] = 0.0;
+    maskdata->PreStateHiG[k] = 0.0;
+    maskdata->PostStateHiF[k] = 0.0;
+    maskdata->PostStateHiG[k] = 0.0;
+  }
+
+  maskdata->OldEnergy = 10.0;
+  return;
+}
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+  int k;
+
+  for (k = 0; k < 2*POSTQORDER; k++) {
+    postfiltdata->STATE_0_LOWER[k] = 0;
+    postfiltdata->STATE_0_UPPER[k] = 0;
+
+    postfiltdata->STATE_0_LOWER_float[k] = 0;
+    postfiltdata->STATE_0_UPPER_float[k] = 0;
+  }
+
+  /* High pass filter states */
+  postfiltdata->HPstates1[0] = 0.0;
+  postfiltdata->HPstates1[1] = 0.0;
+
+  postfiltdata->HPstates2[0] = 0.0;
+  postfiltdata->HPstates2[1] = 0.0;
+
+  postfiltdata->HPstates1_float[0] = 0.0f;
+  postfiltdata->HPstates1_float[1] = 0.0f;
+
+  postfiltdata->HPstates2_float[0] = 0.0f;
+  postfiltdata->HPstates2_float[1] = 0.0f;
+
+  return;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/isac.c b/modules/audio_coding/codecs/isac/main/source/isac.c
new file mode 100644
index 0000000..456f447
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/isac.c
@@ -0,0 +1,2307 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * isac.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/crc.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+#include "rtc_base/system/arch.h"
+
+#define BIT_MASK_DEC_INIT 0x0001
+#define BIT_MASK_ENC_INIT 0x0002
+
+#define LEN_CHECK_SUM_WORD8     4
+#define MAX_NUM_LAYERS         10
+
+
+/****************************************************************************
+ * UpdatePayloadSizeLimit(...)
+ *
+ * Call this function to update the limit on the payload size. The limit on
+ * payload size might change i) if a user ''directly changes the limit by
+ * calling xxx_setMaxPayloadSize() or xxx_setMaxRate(), or ii) indirectly
+ * when bandwidth is changing. The latter might be the result of bandwidth
+ * adaptation, or direct change of the bottleneck in instantaneous mode.
+ *
+ * This function takes the current overall limit on payload, and translates it
+ * to the limits on lower and upper-band. If the codec is in wideband mode,
+ * then the overall limit and the limit on the lower-band is the same.
+ * Otherwise, a fraction of the limit should be allocated to lower-band
+ * leaving some room for the upper-band bit-stream. That is why an update
+ * of limit is required every time that the bandwidth is changing.
+ *
+ */
+static void UpdatePayloadSizeLimit(ISACMainStruct* instISAC) {
+  int16_t lim30MsPayloadBytes = WEBRTC_SPL_MIN(
+                          (instISAC->maxPayloadSizeBytes),
+                          (instISAC->maxRateBytesPer30Ms));
+  int16_t lim60MsPayloadBytes = WEBRTC_SPL_MIN(
+                          (instISAC->maxPayloadSizeBytes),
+                          (instISAC->maxRateBytesPer30Ms << 1));
+
+  /* The only time that iSAC will have 60 ms
+   * frame-size is when operating in wideband, so
+   * there is no upper-band bit-stream. */
+
+  if (instISAC->bandwidthKHz == isac8kHz) {
+    /* At 8 kHz there is no upper-band bit-stream,
+     * therefore, the lower-band limit is the overall limit. */
+    instISAC->instLB.ISACencLB_obj.payloadLimitBytes60 =
+      lim60MsPayloadBytes;
+    instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+      lim30MsPayloadBytes;
+  } else {
+    /* When in super-wideband, we only have 30 ms frames.
+     * Do a rate allocation for the given limit. */
+    if (lim30MsPayloadBytes > 250) {
+      /* 4/5 to lower-band the rest for upper-band. */
+      instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+        (lim30MsPayloadBytes << 2) / 5;
+    } else if (lim30MsPayloadBytes > 200) {
+      /* For the interval of 200 to 250 the share of
+       * upper-band linearly grows from 20 to 50. */
+      instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+        (lim30MsPayloadBytes << 1) / 5 + 100;
+    } else {
+      /* Allocate only 20 for upper-band. */
+      instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+        lim30MsPayloadBytes - 20;
+    }
+    instISAC->instUB.ISACencUB_obj.maxPayloadSizeBytes =
+      lim30MsPayloadBytes;
+  }
+}
+
+
+/****************************************************************************
+ * UpdateBottleneck(...)
+ *
+ * This function updates the bottleneck only if the codec is operating in
+ * channel-adaptive mode. Furthermore, as the update of bottleneck might
+ * result in an update of bandwidth, therefore, the bottlenech should be
+ * updated just right before the first 10ms of a frame is pushed into encoder.
+ *
+ */
+static void UpdateBottleneck(ISACMainStruct* instISAC) {
+  /* Read the bottleneck from bandwidth estimator for the
+   * first 10 ms audio. This way, if there is a change
+   * in bandwidth, upper and lower-band will be in sync. */
+  if ((instISAC->codingMode == 0) &&
+      (instISAC->instLB.ISACencLB_obj.buffer_index == 0) &&
+      (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) {
+    int32_t bottleneck =
+        WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj);
+
+    /* Adding hysteresis when increasing signal bandwidth. */
+    if ((instISAC->bandwidthKHz == isac8kHz)
+        && (bottleneck > 37000)
+        && (bottleneck < 41000)) {
+      bottleneck = 37000;
+    }
+
+    /* Switching from 12 kHz to 16 kHz is not allowed at this revision.
+     * If we let this happen, we have to take care of buffer_index and
+     * the last LPC vector. */
+    if ((instISAC->bandwidthKHz != isac16kHz) &&
+        (bottleneck > 46000)) {
+      bottleneck = 46000;
+    }
+
+    /* We might need a rate allocation. */
+    if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+      /* Wideband is the only choice we have here. */
+      instISAC->instLB.ISACencLB_obj.bottleneck =
+        (bottleneck > 32000) ? 32000 : bottleneck;
+      instISAC->bandwidthKHz = isac8kHz;
+    } else {
+      /* Do the rate-allocation and get the new bandwidth. */
+      enum ISACBandwidth bandwidth;
+      WebRtcIsac_RateAllocation(bottleneck,
+                                &(instISAC->instLB.ISACencLB_obj.bottleneck),
+                                &(instISAC->instUB.ISACencUB_obj.bottleneck),
+                                &bandwidth);
+      if (bandwidth != isac8kHz) {
+        instISAC->instLB.ISACencLB_obj.new_framelength = 480;
+      }
+      if (bandwidth != instISAC->bandwidthKHz) {
+        /* Bandwidth is changing. */
+        instISAC->bandwidthKHz = bandwidth;
+        UpdatePayloadSizeLimit(instISAC);
+        if (bandwidth == isac12kHz) {
+          instISAC->instLB.ISACencLB_obj.buffer_index = 0;
+        }
+        /* Currently we don't let the bandwidth to switch to 16 kHz
+         * if in adaptive mode. If we let this happen, we have to take
+         * care of buffer_index and the last LPC vector. */
+      }
+    }
+  }
+}
+
+
+/****************************************************************************
+ * GetSendBandwidthInfo(...)
+ *
+ * This is called to get the bandwidth info. This info is the bandwidth and
+ * the jitter of 'there-to-here' channel, estimated 'here.' These info
+ * is signaled in an in-band fashion to the other side.
+ *
+ * The call to the bandwidth estimator triggers a recursive averaging which
+ * has to be synchronized between encoder & decoder, therefore, the call to
+ * BWE should be once per packet. As the BWE info is inserted into bit-stream
+ * We need a valid info right before the encodeLB function is going to
+ * generate a bit-stream. That is when lower-band buffer has already 20ms
+ * of audio, and the 3rd block of 10ms is going to be injected into encoder.
+ *
+ * Inputs:
+ *         - instISAC          : iSAC instance.
+ *
+ * Outputs:
+ *         - bandwidthIndex    : an index which has to be encoded in
+ *                               lower-band bit-stream, indicating the
+ *                               bandwidth of there-to-here channel.
+ *         - jitterInfo        : this indicates if the jitter is high
+ *                               or low and it is encoded in upper-band
+ *                               bit-stream.
+ *
+ */
+static void GetSendBandwidthInfo(ISACMainStruct* instISAC,
+                                 int16_t* bandwidthIndex,
+                                 int16_t* jitterInfo) {
+  if ((instISAC->instLB.ISACencLB_obj.buffer_index ==
+      (FRAMESAMPLES_10ms << 1)) &&
+      (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) {
+    /* Bandwidth estimation and coding. */
+    WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj),
+                                         bandwidthIndex, jitterInfo,
+                                         instISAC->decoderSamplingRateKHz);
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ *        - ISAC_main_inst    : address of the pointer to the coder instance.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+int16_t WebRtcIsac_Create(ISACStruct** ISAC_main_inst) {
+  ISACMainStruct* instISAC;
+
+  if (ISAC_main_inst != NULL) {
+    instISAC = (ISACMainStruct*)malloc(sizeof(ISACMainStruct));
+    *ISAC_main_inst = (ISACStruct*)instISAC;
+    if (*ISAC_main_inst != NULL) {
+      instISAC->errorCode = 0;
+      instISAC->initFlag = 0;
+      /* Default is wideband. */
+      instISAC->bandwidthKHz = isac8kHz;
+      instISAC->encoderSamplingRateKHz = kIsacWideband;
+      instISAC->decoderSamplingRateKHz = kIsacWideband;
+      instISAC->in_sample_rate_hz = 16000;
+
+      WebRtcIsac_InitTransform(&instISAC->transform_tables);
+      return 0;
+    } else {
+      return -1;
+    }
+  } else {
+    return -1;
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ *        - ISAC_main_inst    : a ISAC instance.
+ *
+ * Return value               : 0 - Ok
+ *                             -1 - Error
+ */
+int16_t WebRtcIsac_Free(ISACStruct* ISAC_main_inst) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  free(instISAC);
+  return 0;
+}
+
+
+/****************************************************************************
+ * EncoderInitLb(...) - internal function for initialization of
+ *                                Lower Band
+ * EncoderInitUb(...) - internal function for initialization of
+ *                                Upper Band
+ * WebRtcIsac_EncoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - CodingMode        : 0 -> Bit rate and frame length are automatically
+ *                                 adjusted to available bandwidth on
+ *                                 transmission channel, applicable just to
+ *                                 wideband mode.
+ *                              1 -> User sets a frame length and a target bit
+ *                                 rate which is taken as the maximum
+ *                                 short-term average bit rate.
+ *
+ * Return value               :  0 - Ok
+ *                              -1 - Error
+ */
+static int16_t EncoderInitLb(ISACLBStruct* instLB,
+                             int16_t codingMode,
+                             enum IsacSamplingRate sampRate) {
+  int16_t statusInit = 0;
+  int k;
+
+  /* Init stream vector to zero */
+  for (k = 0; k < STREAM_SIZE_MAX_60; k++) {
+    instLB->ISACencLB_obj.bitstr_obj.stream[k] = 0;
+  }
+
+  if ((codingMode == 1) || (sampRate == kIsacSuperWideband)) {
+    /* 30 ms frame-size if either in super-wideband or
+     * instantaneous mode (I-mode). */
+    instLB->ISACencLB_obj.new_framelength = 480;
+  } else {
+    instLB->ISACencLB_obj.new_framelength = INITIAL_FRAMESAMPLES;
+  }
+
+  WebRtcIsac_InitMasking(&instLB->ISACencLB_obj.maskfiltstr_obj);
+  WebRtcIsac_InitPreFilterbank(&instLB->ISACencLB_obj.prefiltbankstr_obj);
+  WebRtcIsac_InitPitchFilter(&instLB->ISACencLB_obj.pitchfiltstr_obj);
+  WebRtcIsac_InitPitchAnalysis(
+    &instLB->ISACencLB_obj.pitchanalysisstr_obj);
+
+  instLB->ISACencLB_obj.buffer_index = 0;
+  instLB->ISACencLB_obj.frame_nb = 0;
+  /* Default for I-mode. */
+  instLB->ISACencLB_obj.bottleneck = 32000;
+  instLB->ISACencLB_obj.current_framesamples = 0;
+  instLB->ISACencLB_obj.s2nr = 0;
+  instLB->ISACencLB_obj.payloadLimitBytes30 = STREAM_SIZE_MAX_30;
+  instLB->ISACencLB_obj.payloadLimitBytes60 = STREAM_SIZE_MAX_60;
+  instLB->ISACencLB_obj.maxPayloadBytes = STREAM_SIZE_MAX_60;
+  instLB->ISACencLB_obj.maxRateInBytes = STREAM_SIZE_MAX_30;
+  instLB->ISACencLB_obj.enforceFrameSize = 0;
+  /* Invalid value prevents getRedPayload to
+     run before encoder is called. */
+  instLB->ISACencLB_obj.lastBWIdx            = -1;
+  return statusInit;
+}
+
+static int16_t EncoderInitUb(ISACUBStruct* instUB,
+                             int16_t bandwidth) {
+  int16_t statusInit = 0;
+  int k;
+
+  /* Init stream vector to zero. */
+  for (k = 0; k < STREAM_SIZE_MAX_60; k++) {
+    instUB->ISACencUB_obj.bitstr_obj.stream[k] = 0;
+  }
+
+  WebRtcIsac_InitMasking(&instUB->ISACencUB_obj.maskfiltstr_obj);
+  WebRtcIsac_InitPreFilterbank(&instUB->ISACencUB_obj.prefiltbankstr_obj);
+
+  if (bandwidth == isac16kHz) {
+    instUB->ISACencUB_obj.buffer_index = LB_TOTAL_DELAY_SAMPLES;
+  } else {
+    instUB->ISACencUB_obj.buffer_index = 0;
+  }
+  /* Default for I-mode. */
+  instUB->ISACencUB_obj.bottleneck = 32000;
+  /* These store the limits for the wideband + super-wideband bit-stream. */
+  instUB->ISACencUB_obj.maxPayloadSizeBytes = STREAM_SIZE_MAX_30 << 1;
+  /* This has to be updated after each lower-band encoding to guarantee
+   * a correct payload-limitation. */
+  instUB->ISACencUB_obj.numBytesUsed = 0;
+  memset(instUB->ISACencUB_obj.data_buffer_float, 0,
+         (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES) * sizeof(float));
+
+  memcpy(&(instUB->ISACencUB_obj.lastLPCVec),
+         WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+
+  return statusInit;
+}
+
+
+int16_t WebRtcIsac_EncoderInit(ISACStruct* ISAC_main_inst,
+                               int16_t codingMode) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  int16_t status;
+
+  if ((codingMode != 0) && (codingMode != 1)) {
+    instISAC->errorCode = ISAC_DISALLOWED_CODING_MODE;
+    return -1;
+  }
+  /* Default bottleneck. */
+  instISAC->bottleneck = MAX_ISAC_BW;
+
+  if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+    instISAC->bandwidthKHz = isac8kHz;
+    instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+    instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+  } else {
+    instISAC->bandwidthKHz = isac16kHz;
+    instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+    instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+  }
+
+  /* Channel-adaptive = 0; Instantaneous (Channel-independent) = 1. */
+  instISAC->codingMode = codingMode;
+
+  WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+                                    instISAC->encoderSamplingRateKHz,
+                                    instISAC->decoderSamplingRateKHz);
+
+  WebRtcIsac_InitRateModel(&instISAC->rate_data_obj);
+  /* Default for I-mode. */
+  instISAC->MaxDelay = 10.0;
+
+  status = EncoderInitLb(&instISAC->instLB, codingMode,
+                         instISAC->encoderSamplingRateKHz);
+  if (status < 0) {
+    instISAC->errorCode = -status;
+    return -1;
+  }
+
+  if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+    /* Initialize encoder filter-bank. */
+    memset(instISAC->analysisFBState1, 0,
+           FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+    memset(instISAC->analysisFBState2, 0,
+           FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+    status = EncoderInitUb(&(instISAC->instUB),
+                           instISAC->bandwidthKHz);
+    if (status < 0) {
+      instISAC->errorCode = -status;
+      return -1;
+    }
+  }
+  /* Initialization is successful, set the flag. */
+  instISAC->initFlag |= BIT_MASK_ENC_INIT;
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - speechIn          : input speech vector.
+ *
+ * Output:
+ *        - encoded           : the encoded data vector
+ *
+ * Return value:
+ *                            : >0 - Length (in bytes) of coded data
+ *                            :  0 - The buffer didn't reach the chosen
+ *                                  frameSize so it keeps buffering speech
+ *                                 samples.
+ *                            : -1 - Error
+ */
+int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst,
+                      const int16_t* speechIn,
+                      uint8_t* encoded) {
+  float inFrame[FRAMESAMPLES_10ms];
+  int16_t speechInLB[FRAMESAMPLES_10ms];
+  int16_t speechInUB[FRAMESAMPLES_10ms];
+  int streamLenLB = 0;
+  int streamLenUB = 0;
+  int streamLen = 0;
+  size_t k = 0;
+  uint8_t garbageLen = 0;
+  int32_t bottleneck = 0;
+  int16_t bottleneckIdx = 0;
+  int16_t jitterInfo = 0;
+
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  ISACLBStruct* instLB = &(instISAC->instLB);
+  ISACUBStruct* instUB = &(instISAC->instUB);
+
+  /* Check if encoder initiated. */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+    WebRtcSpl_AnalysisQMF(speechIn, SWBFRAMESAMPLES_10ms, speechInLB,
+                          speechInUB, instISAC->analysisFBState1,
+                          instISAC->analysisFBState2);
+
+    /* Convert from fixed to floating point. */
+    for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+      inFrame[k] = (float)speechInLB[k];
+    }
+  } else {
+    for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+      inFrame[k] = (float) speechIn[k];
+    }
+  }
+
+  /* Add some noise to avoid denormal numbers. */
+  inFrame[0] += (float)1.23455334e-3;
+  inFrame[1] -= (float)2.04324239e-3;
+  inFrame[2] += (float)1.90854954e-3;
+  inFrame[9] += (float)1.84854878e-3;
+
+  /* This function will update the bottleneck if required. */
+  UpdateBottleneck(instISAC);
+
+  /* Get the bandwith information which has to be sent to the other side. */
+  GetSendBandwidthInfo(instISAC, &bottleneckIdx, &jitterInfo);
+
+  /* Encode lower-band. */
+  streamLenLB = WebRtcIsac_EncodeLb(&instISAC->transform_tables,
+                                    inFrame, &instLB->ISACencLB_obj,
+                                    instISAC->codingMode, bottleneckIdx);
+  if (streamLenLB < 0) {
+    return -1;
+  }
+
+  if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+    instUB = &(instISAC->instUB);
+
+    /* Convert to float. */
+    for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+      inFrame[k] = (float) speechInUB[k];
+    }
+
+    /* Add some noise to avoid denormal numbers. */
+    inFrame[0] += (float)1.23455334e-3;
+    inFrame[1] -= (float)2.04324239e-3;
+    inFrame[2] += (float)1.90854954e-3;
+    inFrame[9] += (float)1.84854878e-3;
+
+    /* Tell to upper-band the number of bytes used so far.
+     * This is for payload limitation. */
+    instUB->ISACencUB_obj.numBytesUsed =
+        (int16_t)(streamLenLB + 1 + LEN_CHECK_SUM_WORD8);
+    /* Encode upper-band. */
+    switch (instISAC->bandwidthKHz) {
+      case isac12kHz: {
+        streamLenUB = WebRtcIsac_EncodeUb12(&instISAC->transform_tables,
+                                            inFrame, &instUB->ISACencUB_obj,
+                                            jitterInfo);
+        break;
+      }
+      case isac16kHz: {
+        streamLenUB = WebRtcIsac_EncodeUb16(&instISAC->transform_tables,
+                                            inFrame, &instUB->ISACencUB_obj,
+                                            jitterInfo);
+        break;
+      }
+      case isac8kHz: {
+        streamLenUB = 0;
+        break;
+      }
+    }
+
+    if ((streamLenUB < 0) && (streamLenUB != -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) {
+      /* An error has happened but this is not the error due to a
+       * bit-stream larger than the limit. */
+      return -1;
+    }
+
+    if (streamLenLB == 0) {
+      return 0;
+    }
+
+    /* One byte is allocated for the length. According to older decoders
+       so the length bit-stream plus one byte for size and
+       LEN_CHECK_SUM_WORD8 for the checksum should be less than or equal
+       to 255. */
+    if ((streamLenUB > (255 - (LEN_CHECK_SUM_WORD8 + 1))) ||
+        (streamLenUB == -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) {
+      /* We have got a too long bit-stream we skip the upper-band
+       * bit-stream for this frame. */
+      streamLenUB = 0;
+    }
+
+    memcpy(encoded, instLB->ISACencLB_obj.bitstr_obj.stream, streamLenLB);
+    streamLen = streamLenLB;
+    if (streamLenUB > 0) {
+      encoded[streamLenLB] = (uint8_t)(streamLenUB + 1 + LEN_CHECK_SUM_WORD8);
+      memcpy(&encoded[streamLenLB + 1],
+             instUB->ISACencUB_obj.bitstr_obj.stream,
+             streamLenUB);
+      streamLen += encoded[streamLenLB];
+    } else {
+      encoded[streamLenLB] = 0;
+    }
+  } else {
+    if (streamLenLB == 0) {
+      return 0;
+    }
+    memcpy(encoded, instLB->ISACencLB_obj.bitstr_obj.stream, streamLenLB);
+    streamLenUB = 0;
+    streamLen = streamLenLB;
+  }
+
+  /* Add Garbage if required. */
+  bottleneck = WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj);
+  if (instISAC->codingMode == 0) {
+    int minBytes;
+    int limit;
+    uint8_t* ptrGarbage;
+
+    instISAC->MaxDelay = (double)WebRtcIsac_GetUplinkMaxDelay(
+                           &instISAC->bwestimator_obj);
+
+    /* Update rate model and get minimum number of bytes in this packet. */
+    minBytes = WebRtcIsac_GetMinBytes(
+        &(instISAC->rate_data_obj), streamLen,
+        instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck,
+        instISAC->MaxDelay, instISAC->bandwidthKHz);
+
+    /* Make sure MinBytes does not exceed packet size limit. */
+    if (instISAC->bandwidthKHz == isac8kHz) {
+      if (instLB->ISACencLB_obj.current_framesamples == FRAMESAMPLES) {
+        limit = instLB->ISACencLB_obj.payloadLimitBytes30;
+      } else {
+        limit = instLB->ISACencLB_obj.payloadLimitBytes60;
+      }
+    } else {
+      limit = instUB->ISACencUB_obj.maxPayloadSizeBytes;
+    }
+    minBytes = (minBytes > limit) ? limit : minBytes;
+
+    /* Make sure we don't allow more than 255 bytes of garbage data.
+     * We store the length of the garbage data in 8 bits in the bitstream,
+     * 255 is the max garbage length we can signal using 8 bits. */
+    if ((instISAC->bandwidthKHz == isac8kHz) ||
+        (streamLenUB == 0)) {
+      ptrGarbage = &encoded[streamLenLB];
+      limit = streamLen + 255;
+    } else {
+      ptrGarbage = &encoded[streamLenLB + 1 + streamLenUB];
+      limit = streamLen + (255 - encoded[streamLenLB]);
+    }
+    minBytes = (minBytes > limit) ? limit : minBytes;
+
+    garbageLen = (minBytes > streamLen) ? (uint8_t)(minBytes - streamLen) : 0;
+
+    /* Save data for creation of multiple bit-streams. */
+    /* If bit-stream too short then add garbage at the end. */
+    if (garbageLen > 0) {
+      /* Overwrite the garbage area to avoid leaking possibly sensitive data
+         over the network. This also makes the output deterministic. */
+      memset(ptrGarbage, 0, garbageLen);
+
+      /* For a correct length of the upper-band bit-stream together
+       * with the garbage. Garbage is embeded in upper-band bit-stream.
+       * That is the only way to preserve backward compatibility. */
+      if ((instISAC->bandwidthKHz == isac8kHz) ||
+          (streamLenUB == 0)) {
+        encoded[streamLenLB] = garbageLen;
+      } else {
+        encoded[streamLenLB] += garbageLen;
+        /* Write the length of the garbage at the end of the upper-band
+         *  bit-stream, if exists. This helps for sanity check. */
+        encoded[streamLenLB + 1 + streamLenUB] = garbageLen;
+
+      }
+      streamLen += garbageLen;
+    }
+  } else {
+    /* update rate model */
+    WebRtcIsac_UpdateRateModel(
+        &instISAC->rate_data_obj, streamLen,
+        instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck);
+    garbageLen = 0;
+  }
+
+  /* Generate CRC if required. */
+  if ((instISAC->bandwidthKHz != isac8kHz) && (streamLenUB > 0)) {
+    uint32_t crc;
+
+    WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+                      streamLenUB + garbageLen, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+    for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+      encoded[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+          (uint8_t)(crc >> (24 - k * 8));
+    }
+#else
+    memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc, LEN_CHECK_SUM_WORD8);
+#endif
+  }
+  return streamLen;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 2! Rates larger than the bottleneck of the codec will be limited
+ *         to the current bottleneck.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - bweIndex          : Index of bandwidth estimate to put in new
+ *                              bitstream
+ *        - rate              : target rate of the transcoder is bits/sec.
+ *                              Valid values are the accepted rate in iSAC,
+ *                              i.e. 10000 to 56000.
+ *
+ * Output:
+ *        - encoded           : The encoded data vector
+ *
+ * Return value               : >0 - Length (in bytes) of coded data
+ *                              -1 - Error  or called in SWB mode
+ *                                 NOTE! No error code is written to
+ *                                 the struct since it is only allowed to read
+ *                                 the struct.
+ */
+int16_t WebRtcIsac_GetNewBitStream(ISACStruct*  ISAC_main_inst,
+                                   int16_t  bweIndex,
+                                   int16_t  jitterInfo,
+                                   int32_t  rate,
+                                   uint8_t* encoded,
+                                   int16_t  isRCU) {
+  Bitstr iSACBitStreamInst;   /* Local struct for bitstream handling */
+  int16_t streamLenLB;
+  int16_t streamLenUB;
+  int16_t totalStreamLen;
+  double gain2;
+  double gain1;
+  float scale;
+  enum ISACBandwidth bandwidthKHz;
+  double rateLB;
+  double rateUB;
+  int32_t currentBN;
+  uint32_t crc;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  int16_t  k;
+#endif
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    return -1;
+  }
+
+  /* Get the bottleneck of this iSAC and limit the
+   * given rate to the current bottleneck. */
+  WebRtcIsac_GetUplinkBw(ISAC_main_inst, &currentBN);
+  if (rate > currentBN) {
+    rate = currentBN;
+  }
+
+  if (WebRtcIsac_RateAllocation(rate, &rateLB, &rateUB, &bandwidthKHz) < 0) {
+    return -1;
+  }
+
+  /* Cannot transcode from 16 kHz to 12 kHz. */
+  if ((bandwidthKHz == isac12kHz) &&
+      (instISAC->bandwidthKHz == isac16kHz)) {
+    return -1;
+  }
+
+  /* A gain [dB] for the given rate. */
+  gain1 = WebRtcIsac_GetSnr(
+      rateLB, instISAC->instLB.ISACencLB_obj.current_framesamples);
+  /* The gain [dB] of this iSAC. */
+  gain2 = WebRtcIsac_GetSnr(
+      instISAC->instLB.ISACencLB_obj.bottleneck,
+      instISAC->instLB.ISACencLB_obj.current_framesamples);
+
+  /* Scale is the ratio of two gains in normal domain. */
+  scale = (float)pow(10, (gain1 - gain2) / 20.0);
+  /* Change the scale if this is a RCU bit-stream. */
+  scale = (isRCU) ? (scale * RCU_TRANSCODING_SCALE) : scale;
+
+  streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+                  &instISAC->instLB.ISACencLB_obj.SaveEnc_obj,
+                  &iSACBitStreamInst, bweIndex, scale);
+
+  if (streamLenLB < 0) {
+    return -1;
+  }
+
+  /* Convert from bytes to int16_t. */
+  memcpy(encoded, iSACBitStreamInst.stream, streamLenLB);
+
+  if (bandwidthKHz == isac8kHz) {
+    return streamLenLB;
+  }
+
+  totalStreamLen = streamLenLB;
+  /* super-wideband is always at 30ms.
+   * These gains are in dB.
+   * Gain for the given rate. */
+  gain1 = WebRtcIsac_GetSnr(rateUB, FRAMESAMPLES);
+  /* Gain of this iSAC */
+  gain2 = WebRtcIsac_GetSnr(instISAC->instUB.ISACencUB_obj.bottleneck,
+                            FRAMESAMPLES);
+
+  /* Scale is the ratio of two gains in normal domain. */
+  scale = (float)pow(10, (gain1 - gain2) / 20.0);
+
+  /* Change the scale if this is a RCU bit-stream. */
+  scale = (isRCU)? (scale * RCU_TRANSCODING_SCALE_UB) : scale;
+
+  streamLenUB = WebRtcIsac_EncodeStoredDataUb(
+                  &(instISAC->instUB.ISACencUB_obj.SaveEnc_obj),
+                  &iSACBitStreamInst, jitterInfo, scale,
+                  instISAC->bandwidthKHz);
+
+  if (streamLenUB < 0) {
+    return -1;
+  }
+
+  if (streamLenUB + 1 + LEN_CHECK_SUM_WORD8 > 255) {
+    return streamLenLB;
+  }
+
+  totalStreamLen = streamLenLB + streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+  encoded[streamLenLB] = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+
+  memcpy(&encoded[streamLenLB + 1], iSACBitStreamInst.stream,
+         streamLenUB);
+
+  WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+                    streamLenUB, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+    encoded[totalStreamLen - LEN_CHECK_SUM_WORD8 + k] =
+      (uint8_t)((crc >> (24 - k * 8)) & 0xFF);
+  }
+#else
+  memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc,
+         LEN_CHECK_SUM_WORD8);
+#endif
+  return totalStreamLen;
+}
+
+
+/****************************************************************************
+ * DecoderInitLb(...) - internal function for initialization of
+ *                                Lower Band
+ * DecoderInitUb(...) - internal function for initialization of
+ *                                Upper Band
+ * WebRtcIsac_DecoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ */
+static void DecoderInitLb(ISACLBStruct* instISAC) {
+  int i;
+  /* Initialize stream vector to zero. */
+  for (i = 0; i < STREAM_SIZE_MAX_60; i++) {
+    instISAC->ISACdecLB_obj.bitstr_obj.stream[i] = 0;
+  }
+
+  WebRtcIsac_InitMasking(&instISAC->ISACdecLB_obj.maskfiltstr_obj);
+  WebRtcIsac_InitPostFilterbank(
+    &instISAC->ISACdecLB_obj.postfiltbankstr_obj);
+  WebRtcIsac_InitPitchFilter(&instISAC->ISACdecLB_obj.pitchfiltstr_obj);
+}
+
+static void DecoderInitUb(ISACUBStruct* instISAC) {
+  int i;
+  /* Init stream vector to zero */
+  for (i = 0; i < STREAM_SIZE_MAX_60; i++) {
+    instISAC->ISACdecUB_obj.bitstr_obj.stream[i] = 0;
+  }
+
+  WebRtcIsac_InitMasking(&instISAC->ISACdecUB_obj.maskfiltstr_obj);
+  WebRtcIsac_InitPostFilterbank(
+    &instISAC->ISACdecUB_obj.postfiltbankstr_obj);
+}
+
+void WebRtcIsac_DecoderInit(ISACStruct* ISAC_main_inst) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  DecoderInitLb(&instISAC->instLB);
+  if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) {
+    memset(instISAC->synthesisFBState1, 0,
+           FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+    memset(instISAC->synthesisFBState2, 0,
+           FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+    DecoderInitUb(&(instISAC->instUB));
+  }
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) {
+    WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+                                      instISAC->encoderSamplingRateKHz,
+                                      instISAC->decoderSamplingRateKHz);
+  }
+  instISAC->initFlag |= BIT_MASK_DEC_INIT;
+  instISAC->resetFlag_8kHz = 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * NOTE:
+ * The estimates of bandwidth is not valid if the sample rate of the far-end
+ * encoder is set to 48 kHz and send timestamps are increamented according to
+ * 48 kHz sampling rate.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - encoded           : encoded ISAC frame(s).
+ *        - packet_size       : size of the packet.
+ *        - rtp_seq_number    : the RTP number of the packet.
+ *        - arr_ts            : the arrival time of the packet (from NetEq)
+ *                              in samples.
+ *
+ * Return value               :  0 - Ok
+ *                              -1 - Error
+ */
+int16_t WebRtcIsac_UpdateBwEstimate(ISACStruct* ISAC_main_inst,
+                                    const uint8_t* encoded,
+                                    size_t packet_size,
+                                    uint16_t rtp_seq_number,
+                                    uint32_t send_ts,
+                                    uint32_t arr_ts) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  int k;
+#endif
+  int16_t err;
+
+  /* Check if decoder initiated. */
+  if ((instISAC->initFlag & BIT_MASK_DEC_INIT) != BIT_MASK_DEC_INIT) {
+    instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+    return -1;
+  }
+
+  /* Check that the size of the packet is valid, and if not return without
+   * updating the bandwidth estimate. A valid size is at least 10 bytes. */
+  if (packet_size < 10) {
+    /* Return error code if the packet length is null. */
+    instISAC->errorCode = ISAC_EMPTY_PACKET;
+    return -1;
+  }
+
+  WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  for (k = 0; k < 10; k++) {
+    uint16_t ek = ((const uint16_t*)encoded)[k >> 1];
+    streamdata.stream[k] = (uint8_t)((ek >> ((k & 1) << 3)) & 0xff);
+  }
+#else
+  memcpy(streamdata.stream, encoded, 10);
+#endif
+
+  err = WebRtcIsac_EstimateBandwidth(&instISAC->bwestimator_obj, &streamdata,
+                                     packet_size, rtp_seq_number, send_ts,
+                                     arr_ts, instISAC->encoderSamplingRateKHz,
+                                     instISAC->decoderSamplingRateKHz);
+  if (err < 0) {
+    /* Return error code if something went wrong. */
+    instISAC->errorCode = -err;
+    return -1;
+  }
+  return 0;
+}
+
+static int Decode(ISACStruct* ISAC_main_inst,
+                  const uint8_t* encoded,
+                  size_t lenEncodedBytes,
+                  int16_t* decoded,
+                  int16_t* speechType,
+                  int16_t isRCUPayload) {
+  /* Number of samples (480 or 960), output from decoder
+     that were actually used in the encoder/decoder
+     (determined on the fly). */
+  int16_t numSamplesLB;
+  int16_t numSamplesUB;
+  int16_t speechIdx;
+  float outFrame[MAX_FRAMESAMPLES];
+  int16_t outFrameLB[MAX_FRAMESAMPLES];
+  int16_t outFrameUB[MAX_FRAMESAMPLES];
+  int numDecodedBytesLBint;
+  size_t numDecodedBytesLB;
+  int numDecodedBytesUB;
+  size_t lenEncodedLBBytes;
+  int16_t validChecksum = 1;
+  int16_t k;
+  uint16_t numLayer;
+  size_t totSizeBytes;
+  int16_t err;
+
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  ISACUBDecStruct* decInstUB = &(instISAC->instUB.ISACdecUB_obj);
+  ISACLBDecStruct* decInstLB = &(instISAC->instLB.ISACdecLB_obj);
+
+  /* Check if decoder initiated. */
+  if ((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+      BIT_MASK_DEC_INIT) {
+    instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+    return -1;
+  }
+
+  if (lenEncodedBytes == 0) {
+    /* return error code if the packet length is null. */
+    instISAC->errorCode = ISAC_EMPTY_PACKET;
+    return -1;
+  }
+
+  /* The size of the encoded lower-band is bounded by
+   * STREAM_SIZE_MAX. If a payload with the size larger than STREAM_SIZE_MAX
+   * is received, it is not considered erroneous. */
+  lenEncodedLBBytes = (lenEncodedBytes > STREAM_SIZE_MAX) ?
+      STREAM_SIZE_MAX : lenEncodedBytes;
+
+  /* Copy to lower-band bit-stream structure. */
+  memcpy(instISAC->instLB.ISACdecLB_obj.bitstr_obj.stream, encoded,
+         lenEncodedLBBytes);
+
+  /* We need to initialize numSamplesLB to something; otherwise, in the test
+     for whether we should return -1 below, the compiler might generate code
+     that fools Memcheck (Valgrind) into thinking that the control flow depends
+     on the uninitialized value in numSamplesLB (since WebRtcIsac_DecodeLb will
+     not fill it in if it fails and returns -1). */
+  numSamplesLB = 0;
+
+  /* Regardless of that the current codec is setup to work in
+   * wideband or super-wideband, the decoding of the lower-band
+   * has to be performed. */
+  numDecodedBytesLBint = WebRtcIsac_DecodeLb(&instISAC->transform_tables,
+                                             outFrame, decInstLB,
+                                             &numSamplesLB, isRCUPayload);
+  numDecodedBytesLB = (size_t)numDecodedBytesLBint;
+  if ((numDecodedBytesLBint < 0) ||
+      (numDecodedBytesLB > lenEncodedLBBytes) ||
+      (numSamplesLB > MAX_FRAMESAMPLES)) {
+    instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+    return -1;
+  }
+
+  /* Error Check, we accept multi-layer bit-stream This will limit number
+   * of iterations of the while loop. Even without this the number
+   * of iterations is limited. */
+  numLayer = 1;
+  totSizeBytes = numDecodedBytesLB;
+  while (totSizeBytes != lenEncodedBytes) {
+    if ((totSizeBytes > lenEncodedBytes) ||
+        (encoded[totSizeBytes] == 0) ||
+        (numLayer > MAX_NUM_LAYERS)) {
+      instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+      return -1;
+    }
+    totSizeBytes += encoded[totSizeBytes];
+    numLayer++;
+  }
+
+  if (instISAC->decoderSamplingRateKHz == kIsacWideband) {
+    for (k = 0; k < numSamplesLB; k++) {
+      if (outFrame[k] > 32767) {
+        decoded[k] = 32767;
+      } else if (outFrame[k] < -32768) {
+        decoded[k] = -32768;
+      } else {
+        decoded[k] = (int16_t)WebRtcIsac_lrint(outFrame[k]);
+      }
+    }
+    numSamplesUB = 0;
+  } else {
+    uint32_t crc;
+    /* We don't accept larger than 30ms (480 samples at lower-band)
+     * frame-size. */
+    for (k = 0; k < numSamplesLB; k++) {
+      if (outFrame[k] > 32767) {
+        outFrameLB[k] = 32767;
+      } else if (outFrame[k] < -32768) {
+        outFrameLB[k] = -32768;
+      } else {
+        outFrameLB[k] = (int16_t)WebRtcIsac_lrint(outFrame[k]);
+      }
+    }
+
+    /* Check for possible error, and if upper-band stream exists. */
+    if (numDecodedBytesLB == lenEncodedBytes) {
+      /* Decoding was successful. No super-wideband bit-stream exists. */
+      numSamplesUB = numSamplesLB;
+      memset(outFrameUB, 0, sizeof(int16_t) *  numSamplesUB);
+
+      /* Prepare for the potential increase of signal bandwidth. */
+      instISAC->resetFlag_8kHz = 2;
+    } else {
+      /* This includes the checksum and the bytes that stores the length. */
+      int16_t lenNextStream = encoded[numDecodedBytesLB];
+
+      /* Is this garbage or valid super-wideband bit-stream?
+       * Check if checksum is valid. */
+      if (lenNextStream <= (LEN_CHECK_SUM_WORD8 + 1)) {
+        /* Such a small second layer cannot be super-wideband layer.
+         * It must be a short garbage. */
+        validChecksum = 0;
+      } else {
+        /* Run CRC to see if the checksum match. */
+        WebRtcIsac_GetCrc((int16_t*)(&encoded[numDecodedBytesLB + 1]),
+                          lenNextStream - LEN_CHECK_SUM_WORD8 - 1, &crc);
+
+        validChecksum = 1;
+        for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+          validChecksum &= (((crc >> (24 - k * 8)) & 0xFF) ==
+                            encoded[numDecodedBytesLB + lenNextStream -
+                                          LEN_CHECK_SUM_WORD8 + k]);
+        }
+      }
+
+      if (!validChecksum) {
+        /* This is a garbage, we have received a wideband
+         * bit-stream with garbage. */
+        numSamplesUB = numSamplesLB;
+        memset(outFrameUB, 0, sizeof(int16_t) * numSamplesUB);
+      } else {
+        /* A valid super-wideband biststream exists. */
+        enum ISACBandwidth bandwidthKHz;
+        int32_t maxDelayBit;
+
+        /* If we have super-wideband bit-stream, we cannot
+         * have 60 ms frame-size. */
+        if (numSamplesLB > FRAMESAMPLES) {
+          instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+          return -1;
+        }
+
+        /* The rest of the bit-stream contains the upper-band
+         * bit-stream curently this is the only thing there,
+         * however, we might add more layers. */
+
+        /* Have to exclude one byte where the length is stored
+         * and last 'LEN_CHECK_SUM_WORD8' bytes where the
+         * checksum is stored. */
+        lenNextStream -= (LEN_CHECK_SUM_WORD8 + 1);
+
+        memcpy(decInstUB->bitstr_obj.stream,
+               &encoded[numDecodedBytesLB + 1], lenNextStream);
+
+        /* Reset bit-stream object, this is the first decoding. */
+        WebRtcIsac_ResetBitstream(&(decInstUB->bitstr_obj));
+
+        /* Decode jitter information. */
+        err = WebRtcIsac_DecodeJitterInfo(&decInstUB->bitstr_obj, &maxDelayBit);
+        if (err < 0) {
+          instISAC->errorCode = -err;
+          return -1;
+        }
+
+        /* Update jitter info which is in the upper-band bit-stream
+         * only if the encoder is in super-wideband. Otherwise,
+         * the jitter info is already embedded in bandwidth index
+         * and has been updated. */
+        if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+          err = WebRtcIsac_UpdateUplinkJitter(
+                  &(instISAC->bwestimator_obj), maxDelayBit);
+          if (err < 0) {
+            instISAC->errorCode = -err;
+            return -1;
+          }
+        }
+
+        /* Decode bandwidth information. */
+        err = WebRtcIsac_DecodeBandwidth(&decInstUB->bitstr_obj,
+                                         &bandwidthKHz);
+        if (err < 0) {
+          instISAC->errorCode = -err;
+          return -1;
+        }
+
+        switch (bandwidthKHz) {
+          case isac12kHz: {
+            numDecodedBytesUB = WebRtcIsac_DecodeUb12(
+                &instISAC->transform_tables, outFrame, decInstUB, isRCUPayload);
+
+            /* Hang-over for transient alleviation -
+             * wait two frames to add the upper band going up from 8 kHz. */
+            if (instISAC->resetFlag_8kHz > 0) {
+              if (instISAC->resetFlag_8kHz == 2) {
+                /* Silence first and a half frame. */
+                memset(outFrame, 0, MAX_FRAMESAMPLES *
+                       sizeof(float));
+              } else {
+                const float rampStep = 2.0f / MAX_FRAMESAMPLES;
+                float rampVal = 0;
+                memset(outFrame, 0, (MAX_FRAMESAMPLES >> 1) *
+                       sizeof(float));
+
+                /* Ramp up second half of second frame. */
+                for (k = MAX_FRAMESAMPLES / 2; k < MAX_FRAMESAMPLES; k++) {
+                  outFrame[k] *= rampVal;
+                  rampVal += rampStep;
+                }
+              }
+              instISAC->resetFlag_8kHz -= 1;
+            }
+
+            break;
+          }
+          case isac16kHz: {
+            numDecodedBytesUB = WebRtcIsac_DecodeUb16(
+                &instISAC->transform_tables, outFrame, decInstUB, isRCUPayload);
+            break;
+          }
+          default:
+            return -1;
+        }
+
+        if (numDecodedBytesUB < 0) {
+          instISAC->errorCode = numDecodedBytesUB;
+          return -1;
+        }
+        if (numDecodedBytesLB + numDecodedBytesUB > lenEncodedBytes) {
+          // We have supposedly decoded more bytes than we were given. Likely
+          // caused by bad input data.
+          instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+          return -1;
+        }
+
+        /* It might be less due to garbage. */
+        if ((numDecodedBytesUB != lenNextStream) &&
+            (numDecodedBytesLB + 1 + numDecodedBytesUB >= lenEncodedBytes ||
+             numDecodedBytesUB !=
+                 (lenNextStream -
+                  encoded[numDecodedBytesLB + 1 + numDecodedBytesUB]))) {
+          instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+          return -1;
+        }
+
+        /* If there is no error Upper-band always decodes
+         * 30 ms (480 samples). */
+        numSamplesUB = FRAMESAMPLES;
+
+        /* Convert to W16. */
+        for (k = 0; k < numSamplesUB; k++) {
+          if (outFrame[k] > 32767) {
+            outFrameUB[k] = 32767;
+          } else if (outFrame[k] < -32768) {
+            outFrameUB[k] = -32768;
+          } else {
+            outFrameUB[k] = (int16_t)WebRtcIsac_lrint(
+                              outFrame[k]);
+          }
+        }
+      }
+    }
+
+    speechIdx = 0;
+    while (speechIdx < numSamplesLB) {
+      WebRtcSpl_SynthesisQMF(&outFrameLB[speechIdx], &outFrameUB[speechIdx],
+                             FRAMESAMPLES_10ms, &decoded[(speechIdx << 1)],
+                             instISAC->synthesisFBState1,
+                             instISAC->synthesisFBState2);
+
+      speechIdx += FRAMESAMPLES_10ms;
+    }
+  }
+  *speechType = 0;
+  return (numSamplesLB + numSamplesUB);
+}
+
+
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes a ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the  frameSize (30 or 60 ms).
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - encoded           : encoded ISAC frame(s)
+ *        - len               : bytes in encoded vector
+ *
+ * Output:
+ *        - decoded           : The decoded vector
+ *
+ * Return value               : >0 - number of samples in decoded vector
+ *                              -1 - Error
+ */
+
+int WebRtcIsac_Decode(ISACStruct* ISAC_main_inst,
+                      const uint8_t* encoded,
+                      size_t lenEncodedBytes,
+                      int16_t* decoded,
+                      int16_t* speechType) {
+  int16_t isRCUPayload = 0;
+  return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+                speechType, isRCUPayload);
+}
+
+/****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload in case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ *      - ISAC_main_inst     : ISAC instance.
+ *      - encoded            : encoded ISAC RCU frame(s)
+ *      - len                : bytes in encoded vector
+ *
+ * Output:
+ *      - decoded            : The decoded vector
+ *
+ * Return value              : >0 - number of samples in decoded vector
+ *                             -1 - Error
+ */
+
+
+
+int WebRtcIsac_DecodeRcu(ISACStruct* ISAC_main_inst,
+                         const uint8_t* encoded,
+                         size_t lenEncodedBytes,
+                         int16_t* decoded,
+                         int16_t* speechType) {
+  int16_t isRCUPayload = 1;
+  return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+                speechType, isRCUPayload);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the  frameSize (30 or 60 ms).
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - noOfLostFrames    : Number of PLC frames to produce
+ *
+ * Output:
+ *        - decoded           : The decoded vector
+ *
+ * Return value               : Number of samples in decoded PLC vector
+ */
+size_t WebRtcIsac_DecodePlc(ISACStruct* ISAC_main_inst,
+                            int16_t* decoded,
+                            size_t noOfLostFrames) {
+  size_t numSamples = 0;
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  /* Limit number of frames to two = 60 millisecond.
+   * Otherwise we exceed data vectors. */
+  if (noOfLostFrames > 2) {
+    noOfLostFrames = 2;
+  }
+
+  /* Get the number of samples per frame */
+  switch (instISAC->decoderSamplingRateKHz) {
+    case kIsacWideband: {
+      numSamples = 480 * noOfLostFrames;
+      break;
+    }
+    case kIsacSuperWideband: {
+      numSamples = 960 * noOfLostFrames;
+      break;
+    }
+  }
+
+  /* Set output samples to zero. */
+  memset(decoded, 0, numSamples * sizeof(int16_t));
+  return numSamples;
+}
+
+
+/****************************************************************************
+ * ControlLb(...) - Internal function for controlling Lower Band
+ * ControlUb(...) - Internal function for controlling Upper Band
+ * WebRtcIsac_Control(...) - API function
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - rate              : limit on the short-term average bit rate,
+ *                              in bits/second (between 10000 and 32000)
+ *        - frameSize         : number of milliseconds per frame (30 or 60)
+ *
+ * Return value               : 0 - ok
+ *                             -1 - Error
+ */
+static int16_t ControlLb(ISACLBStruct* instISAC, double rate,
+                         int16_t frameSize) {
+  if ((rate >= 10000) && (rate <= 32000)) {
+    instISAC->ISACencLB_obj.bottleneck = rate;
+  } else {
+    return -ISAC_DISALLOWED_BOTTLENECK;
+  }
+
+  if ((frameSize == 30) || (frameSize == 60)) {
+    instISAC->ISACencLB_obj.new_framelength = (FS / 1000) *  frameSize;
+  } else {
+    return -ISAC_DISALLOWED_FRAME_LENGTH;
+  }
+
+  return 0;
+}
+
+static int16_t ControlUb(ISACUBStruct* instISAC, double rate) {
+  if ((rate >= 10000) && (rate <= 32000)) {
+    instISAC->ISACencUB_obj.bottleneck = rate;
+  } else {
+    return -ISAC_DISALLOWED_BOTTLENECK;
+  }
+  return 0;
+}
+
+int16_t WebRtcIsac_Control(ISACStruct* ISAC_main_inst,
+                           int32_t bottleneckBPS,
+                           int frameSize) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  int16_t status;
+  double rateLB;
+  double rateUB;
+  enum ISACBandwidth bandwidthKHz;
+
+  if (instISAC->codingMode == 0) {
+    /* In adaptive mode. */
+    instISAC->errorCode = ISAC_MODE_MISMATCH;
+    return -1;
+  }
+
+  /* Check if encoder initiated */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+    /* If the sampling rate is 16kHz then bandwith should be 8kHz,
+     * regardless of bottleneck. */
+    bandwidthKHz = isac8kHz;
+    rateLB = (bottleneckBPS > 32000) ? 32000 : bottleneckBPS;
+    rateUB = 0;
+  } else {
+    if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB,
+                                  &bandwidthKHz) < 0) {
+      return -1;
+    }
+  }
+
+  if ((instISAC->encoderSamplingRateKHz == kIsacSuperWideband) &&
+      (frameSize != 30) &&
+      (bandwidthKHz != isac8kHz)) {
+    /* Cannot have 60 ms in super-wideband. */
+    instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+    return -1;
+  }
+
+  status = ControlLb(&instISAC->instLB, rateLB, (int16_t)frameSize);
+  if (status < 0) {
+    instISAC->errorCode = -status;
+    return -1;
+  }
+  if (bandwidthKHz != isac8kHz) {
+    status = ControlUb(&(instISAC->instUB), rateUB);
+    if (status < 0) {
+      instISAC->errorCode = -status;
+      return -1;
+    }
+  }
+
+
+  /* Check if bandwidth is changing from wideband to super-wideband
+   * then we have to synch data buffer of lower & upper-band. Also
+   * clean up the upper-band data buffer. */
+
+  if ((instISAC->bandwidthKHz == isac8kHz) && (bandwidthKHz != isac8kHz)) {
+    memset(instISAC->instUB.ISACencUB_obj.data_buffer_float, 0,
+           sizeof(float) * (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES));
+
+    if (bandwidthKHz == isac12kHz) {
+      instISAC->instUB.ISACencUB_obj.buffer_index =
+        instISAC->instLB.ISACencLB_obj.buffer_index;
+    } else {
+      instISAC->instUB.ISACencUB_obj.buffer_index =
+          LB_TOTAL_DELAY_SAMPLES + instISAC->instLB.ISACencLB_obj.buffer_index;
+
+      memcpy(&(instISAC->instUB.ISACencUB_obj.lastLPCVec),
+             WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+    }
+  }
+
+  /* Update the payload limit if the bandwidth is changing. */
+  if (instISAC->bandwidthKHz != bandwidthKHz) {
+    instISAC->bandwidthKHz = bandwidthKHz;
+    UpdatePayloadSizeLimit(instISAC);
+  }
+  instISAC->bottleneck = bottleneckBPS;
+  return 0;
+}
+
+void WebRtcIsac_SetInitialBweBottleneck(ISACStruct* ISAC_main_inst,
+                                        int bottleneck_bits_per_second) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  RTC_DCHECK_GE(bottleneck_bits_per_second, 10000);
+  RTC_DCHECK_LE(bottleneck_bits_per_second, 32000);
+  instISAC->bwestimator_obj.send_bw_avg = (float)bottleneck_bits_per_second;
+}
+
+/****************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance.
+ *        - rateBPS           : initial value of bottleneck in bits/second
+ *                              10000 <= rateBPS <= 32000 is accepted
+ *                              For default bottleneck set rateBPS = 0
+ *        - frameSizeMs       : number of milliseconds per frame (30 or 60)
+ *        - enforceFrameSize  : 1 to enforce the given frame-size through out
+ *                              the adaptation process, 0 to let iSAC change
+ *                              the frame-size if required.
+ *
+ * Return value               : 0 - ok
+ *                             -1 - Error
+ */
+int16_t WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst,
+                              int32_t bottleneckBPS,
+                              int frameSizeMs,
+                              int16_t enforceFrameSize) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  enum ISACBandwidth bandwidth;
+
+   /* Check if encoder initiated */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  /* Check that we are in channel-adaptive mode, otherwise, return (-1) */
+  if (instISAC->codingMode != 0) {
+    instISAC->errorCode = ISAC_MODE_MISMATCH;
+    return -1;
+  }
+  if ((frameSizeMs != 30) &&
+      (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) {
+    return -1;
+  }
+
+  /* Set structure variable if enforceFrameSize is set. ISAC will then
+   * keep the chosen frame size. */
+  if (enforceFrameSize != 0) {
+    instISAC->instLB.ISACencLB_obj.enforceFrameSize = 1;
+  } else {
+    instISAC->instLB.ISACencLB_obj.enforceFrameSize = 0;
+  }
+
+  /* Set the initial rate. If the input value is zero then the default intial
+   * rate is used. Otehrwise, values between 10 to 32 kbps are accepted. */
+  if (bottleneckBPS != 0) {
+    double rateLB;
+    double rateUB;
+    if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB,
+                                  &bandwidth) < 0) {
+      return -1;
+    }
+    instISAC->bwestimator_obj.send_bw_avg = (float)bottleneckBPS;
+    instISAC->bandwidthKHz = bandwidth;
+  }
+
+  /* Set the initial frame-size. If 'enforceFrameSize' is set, the frame-size
+   *  will not change */
+  if (frameSizeMs != 0) {
+    if ((frameSizeMs  == 30) || (frameSizeMs == 60)) {
+      instISAC->instLB.ISACencLB_obj.new_framelength =
+          (int16_t)((FS / 1000) * frameSizeMs);
+    } else {
+      instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+      return -1;
+    }
+  }
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * the other side to this side.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC structure
+ *
+ * Output:
+ *        - bweIndex         : Bandwidth estimate to transmit to other side.
+ *
+ */
+int16_t WebRtcIsac_GetDownLinkBwIndex(ISACStruct* ISAC_main_inst,
+                                      int16_t* bweIndex,
+                                      int16_t* jitterInfo) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  /* Check if encoder initialized. */
+  if ((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+      BIT_MASK_DEC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  /* Call function to get Bandwidth Estimate. */
+  WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj), bweIndex,
+                                       jitterInfo,
+                                       instISAC->decoderSamplingRateKHz);
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC structure
+ *        - rateIndex         : Bandwidth estimate from other side.
+ *
+ * Return value               : 0 - ok
+ *                             -1 - index out of range
+ */
+int16_t WebRtcIsac_UpdateUplinkBw(ISACStruct* ISAC_main_inst,
+                                  int16_t bweIndex) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  int16_t returnVal;
+
+  /* Check if encoder initiated. */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  /* Call function to get Bandwidth Estimate. */
+  returnVal = WebRtcIsac_UpdateUplinkBwImpl(
+                &(instISAC->bwestimator_obj), bweIndex,
+                instISAC->encoderSamplingRateKHz);
+
+  if (returnVal < 0) {
+    instISAC->errorCode = -returnVal;
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the
+ * bit-stream.
+ *
+ * Input:
+ *        - encoded           : Encoded bit-stream
+ *
+ * Output:
+ *        - frameLength       : Length of frame in packet (in samples)
+ *        - bweIndex          : Bandwidth estimate in bit-stream
+ *
+ */
+int16_t WebRtcIsac_ReadBwIndex(const uint8_t* encoded,
+                               int16_t* bweIndex) {
+  Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  int k;
+#endif
+  int16_t err;
+
+  WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  for (k = 0; k < 10; k++) {
+    int16_t ek2 = ((const int16_t*)encoded)[k >> 1];
+    streamdata.stream[k] = (uint8_t)((ek2 >> ((k & 1) << 3)) & 0xff);
+  }
+#else
+  memcpy(streamdata.stream, encoded, 10);
+#endif
+
+  /* Decode frame length. */
+  err = WebRtcIsac_DecodeFrameLen(&streamdata, bweIndex);
+  if (err < 0) {
+    return err;
+  }
+
+  /* Decode BW estimation. */
+  err = WebRtcIsac_DecodeSendBW(&streamdata, bweIndex);
+  if (err < 0) {
+    return err;
+  }
+
+  return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the number of samples the decoder will generate if
+ * the given payload is decoded.
+ *
+ * Input:
+ *        - encoded           : Encoded bitstream
+ *
+ * Output:
+ *        - frameLength       : Length of frame in packet (in samples)
+ *
+ */
+int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst,
+                                const uint8_t* encoded,
+                                int16_t* frameLength) {
+  Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  int k;
+#endif
+  int16_t err;
+  ISACMainStruct* instISAC;
+
+  WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  for (k = 0; k < 10; k++) {
+    int16_t ek2 = ((const int16_t*)encoded)[k >> 1];
+    streamdata.stream[k] = (uint8_t)((ek2 >> ((k & 1) << 3)) & 0xff);
+  }
+#else
+  memcpy(streamdata.stream, encoded, 10);
+#endif
+
+  /* Decode frame length. */
+  err = WebRtcIsac_DecodeFrameLen(&streamdata, frameLength);
+  if (err < 0) {
+    return -1;
+  }
+  instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) {
+    /* The decoded frame length indicates the number of samples in
+     * lower-band in this case, multiply by 2 to get the total number
+     * of samples. */
+    *frameLength <<= 1;
+  }
+  return 0;
+}
+
+
+/*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * This function returns the frame length (in samples) of the next packet.
+ * In the case of channel-adaptive mode, iSAC decides on its frame length based
+ * on the estimated bottleneck, this AOI allows a user to prepare for the next
+ * packet (at the encoder).
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ *        - ISAC_main_inst     : iSAC struct
+ *
+ * Return Value                : frame lenght in samples
+ *
+ */
+int16_t WebRtcIsac_GetNewFrameLen(ISACStruct* ISAC_main_inst) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  /* Return new frame length. */
+  if (instISAC->in_sample_rate_hz == 16000)
+    return (instISAC->instLB.ISACencLB_obj.new_framelength);
+  else  /* 32000 Hz */
+    return ((instISAC->instLB.ISACencLB_obj.new_framelength) * 2);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance.
+ * When a function returns -1 an error code will be set for that instance.
+ * The function below extracts the code of the last error that occurred in
+ * the specified instance.
+ *
+ * Input:
+ *        - ISAC_main_inst    : ISAC instance
+ *
+ * Return value               : Error code
+ */
+int16_t WebRtcIsac_GetErrorCode(ISACStruct* ISAC_main_inst) {
+ return ((ISACMainStruct*)ISAC_main_inst)->errorCode;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through an in-band
+ * signalling retrieved by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...) (if
+ * xxx_control is never called, the default values are used.).
+ * Note that the output is the iSAC internal operating bottleneck which might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Output:
+ *        - *bottleneck       : bottleneck in bits/sec
+ *
+ * Return value               : -1 if error happens
+ *                               0 bit-rates computed correctly.
+ */
+int16_t WebRtcIsac_GetUplinkBw(ISACStruct*  ISAC_main_inst,
+                               int32_t* bottleneck) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+  if (instISAC->codingMode == 0) {
+    /* We are in adaptive mode then get the bottleneck from BWE. */
+    *bottleneck = (int32_t)instISAC->bwestimator_obj.send_bw_avg;
+  } else {
+    *bottleneck = instISAC->bottleneck;
+  }
+
+  if ((*bottleneck > 32000) && (*bottleneck < 38000)) {
+    *bottleneck = 32000;
+  } else if ((*bottleneck > 45000) && (*bottleneck < 50000)) {
+    *bottleneck = 45000;
+  } else if (*bottleneck > 56000) {
+    *bottleneck = 56000;
+  }
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - maxPayloadBytes   : maximum size of the payload in bytes
+ *                              valid values are between 100 and 400 bytes
+ *                              if encoder sampling rate is 16 kHz. For
+ *                              32 kHz encoder sampling rate valid values
+ *                              are between 100 and 600 bytes.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if error happens
+ */
+int16_t WebRtcIsac_SetMaxPayloadSize(ISACStruct* ISAC_main_inst,
+                                     int16_t maxPayloadBytes) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  int16_t status = 0;
+
+  /* Check if encoder initiated */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+
+  if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+    /* Sanity check. */
+    if (maxPayloadBytes < 120) {
+      /* 'maxRate' is out of valid range
+       * set to the acceptable value and return -1. */
+      maxPayloadBytes = 120;
+      status = -1;
+    }
+
+    /* sanity check */
+    if (maxPayloadBytes > STREAM_SIZE_MAX) {
+      /* maxRate is out of valid range,
+       * set to the acceptable value and return -1. */
+      maxPayloadBytes = STREAM_SIZE_MAX;
+      status = -1;
+    }
+  } else {
+    if (maxPayloadBytes < 120) {
+      /* Max payload-size is out of valid range
+       * set to the acceptable value and return -1. */
+      maxPayloadBytes = 120;
+      status = -1;
+    }
+    if (maxPayloadBytes > STREAM_SIZE_MAX_60) {
+      /* Max payload-size is out of valid range
+       * set to the acceptable value and return -1. */
+      maxPayloadBytes = STREAM_SIZE_MAX_60;
+      status = -1;
+    }
+  }
+  instISAC->maxPayloadSizeBytes = maxPayloadBytes;
+  UpdatePayloadSizeLimit(instISAC);
+  return status;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - maxRate           : maximum rate in bits per second,
+ *                              valid values are 32000 to 53400 bits/sec in
+ *                              wideband mode, and 32000 to 160000 bits/sec in
+ *                              super-wideband mode.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if error happens
+ */
+int16_t WebRtcIsac_SetMaxRate(ISACStruct* ISAC_main_inst,
+                              int32_t maxRate) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  int16_t maxRateInBytesPer30Ms;
+  int16_t status = 0;
+
+  /* check if encoder initiated */
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+    return -1;
+  }
+  /* Calculate maximum number of bytes per 30 msec packets for the
+     given maximum rate. Multiply with 30/1000 to get number of
+     bits per 30 ms, divide by 8 to get number of bytes per 30 ms:
+     maxRateInBytes = floor((maxRate * 30/1000) / 8); */
+  maxRateInBytesPer30Ms = (int16_t)(maxRate * 3 / 800);
+
+  if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+    if (maxRate < 32000) {
+      /* 'maxRate' is out of valid range.
+       * Set to the acceptable value and return -1. */
+      maxRateInBytesPer30Ms = 120;
+      status = -1;
+    }
+
+    if (maxRate > 53400) {
+      /* 'maxRate' is out of valid range.
+       * Set to the acceptable value and return -1. */
+      maxRateInBytesPer30Ms = 200;
+      status = -1;
+    }
+  } else {
+    if (maxRateInBytesPer30Ms < 120) {
+      /* 'maxRate' is out of valid range
+       * Set to the acceptable value and return -1. */
+      maxRateInBytesPer30Ms = 120;
+      status = -1;
+    }
+
+    if (maxRateInBytesPer30Ms > STREAM_SIZE_MAX) {
+      /* 'maxRate' is out of valid range.
+       * Set to the acceptable value and return -1. */
+      maxRateInBytesPer30Ms = STREAM_SIZE_MAX;
+      status = -1;
+    }
+  }
+  instISAC->maxRateBytesPer30Ms = maxRateInBytesPer30Ms;
+  UpdatePayloadSizeLimit(instISAC);
+  return status;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * This function populates "encoded" with the redundant payload of the recently
+ * encodedframe. This function has to be called once that WebRtcIsac_Encode(...)
+ * returns a positive value. Regardless of the frame-size this function will
+ * be called only once after encoding is completed. The bit-stream is
+ * targeted for 16000 bit/sec.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC struct
+ *
+ * Output:
+ *        - encoded           : the encoded data vector
+ *
+ *
+ * Return value               : >0 - Length (in bytes) of coded data
+ *                            : -1 - Error
+ */
+int16_t WebRtcIsac_GetRedPayload(ISACStruct* ISAC_main_inst,
+                                 uint8_t* encoded) {
+  Bitstr iSACBitStreamInst;
+  int16_t streamLenLB;
+  int16_t streamLenUB;
+  int16_t streamLen;
+  int16_t totalLenUB;
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+  int k;
+#endif
+
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+  }
+
+  WebRtcIsac_ResetBitstream(&(iSACBitStreamInst));
+
+  streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+                  &instISAC->instLB.ISACencLB_obj.SaveEnc_obj,
+                  &iSACBitStreamInst,
+                  instISAC->instLB.ISACencLB_obj.lastBWIdx,
+                  RCU_TRANSCODING_SCALE);
+  if (streamLenLB < 0) {
+    return -1;
+  }
+
+  /* convert from bytes to int16_t. */
+  memcpy(encoded, iSACBitStreamInst.stream, streamLenLB);
+  streamLen = streamLenLB;
+  if (instISAC->bandwidthKHz == isac8kHz) {
+    return streamLenLB;
+  }
+
+  streamLenUB = WebRtcIsac_GetRedPayloadUb(
+                  &instISAC->instUB.ISACencUB_obj.SaveEnc_obj,
+                  &iSACBitStreamInst, instISAC->bandwidthKHz);
+  if (streamLenUB < 0) {
+    /* An error has happened but this is not the error due to a
+     * bit-stream larger than the limit. */
+    return -1;
+  }
+
+  /* We have one byte to write the total length of the upper-band.
+   * The length includes the bit-stream length, check-sum and the
+   * single byte where the length is written to. This is according to
+   * iSAC wideband and how the "garbage" is dealt. */
+  totalLenUB = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+  if (totalLenUB > 255) {
+    streamLenUB = 0;
+  }
+
+  /* Generate CRC if required. */
+  if ((instISAC->bandwidthKHz != isac8kHz) &&
+      (streamLenUB > 0)) {
+    uint32_t crc;
+    streamLen += totalLenUB;
+    encoded[streamLenLB] = (uint8_t)totalLenUB;
+    memcpy(&encoded[streamLenLB + 1], iSACBitStreamInst.stream,
+           streamLenUB);
+
+    WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+                      streamLenUB, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+    for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+      encoded[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+        (uint8_t)((crc >> (24 - k * 8)) & 0xFF);
+    }
+#else
+    memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc,
+           LEN_CHECK_SUM_WORD8);
+#endif
+  }
+  return streamLen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ *        - version      : Pointer to character string
+ *
+ */
+void WebRtcIsac_version(char* version) {
+  strcpy(version, "4.3.0");
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * This function sets the sampling rate of the encoder. Initialization of the
+ * encoder WILL NOT overwrite the sampling rate of the encoder. The default
+ * value is 16 kHz which is set when the instance is created. The encoding-mode
+ * and the bottleneck remain unchanged by this call, however, the maximum rate
+ * and maximum payload-size will be reset to their default values.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - sample_rate_hz    : sampling rate in Hertz, valid values are 16000
+ *                              and 32000.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if failed.
+ */
+int16_t WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
+                                  uint16_t sample_rate_hz) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  enum IsacSamplingRate encoder_operational_rate;
+
+  if ((sample_rate_hz != 16000) && (sample_rate_hz != 32000)) {
+    /* Sampling Frequency is not supported. */
+    instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+    return -1;
+  }
+  if (sample_rate_hz == 16000) {
+    encoder_operational_rate = kIsacWideband;
+  } else {
+    encoder_operational_rate = kIsacSuperWideband;
+  }
+
+  if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+      BIT_MASK_ENC_INIT) {
+    if (encoder_operational_rate == kIsacWideband) {
+      instISAC->bandwidthKHz = isac8kHz;
+    } else {
+      instISAC->bandwidthKHz = isac16kHz;
+    }
+  } else {
+    ISACUBStruct* instUB = &(instISAC->instUB);
+    ISACLBStruct* instLB = &(instISAC->instLB);
+    int32_t bottleneck = instISAC->bottleneck;
+    int16_t codingMode = instISAC->codingMode;
+    int16_t frameSizeMs = instLB->ISACencLB_obj.new_framelength /
+        (FS / 1000);
+
+    if ((encoder_operational_rate == kIsacWideband) &&
+        (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) {
+      /* Changing from super-wideband to wideband.
+       * we don't need to re-initialize the encoder of the lower-band. */
+      instISAC->bandwidthKHz = isac8kHz;
+      if (codingMode == 1) {
+        ControlLb(instLB,
+                  (bottleneck > 32000) ? 32000 : bottleneck, FRAMESIZE);
+      }
+      instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+      instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+    } else if ((encoder_operational_rate == kIsacSuperWideband) &&
+               (instISAC->encoderSamplingRateKHz == kIsacWideband)) {
+      double bottleneckLB = 0;
+      double bottleneckUB = 0;
+      if (codingMode == 1) {
+        WebRtcIsac_RateAllocation(bottleneck, &bottleneckLB, &bottleneckUB,
+                                  &(instISAC->bandwidthKHz));
+      }
+
+      instISAC->bandwidthKHz = isac16kHz;
+      instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+      instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+
+      EncoderInitLb(instLB, codingMode, encoder_operational_rate);
+      EncoderInitUb(instUB, instISAC->bandwidthKHz);
+
+      memset(instISAC->analysisFBState1, 0,
+             FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+      memset(instISAC->analysisFBState2, 0,
+             FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+      if (codingMode == 1) {
+        instISAC->bottleneck = bottleneck;
+        ControlLb(instLB, bottleneckLB,
+                  (instISAC->bandwidthKHz == isac8kHz) ? frameSizeMs:FRAMESIZE);
+        if (instISAC->bandwidthKHz > isac8kHz) {
+          ControlUb(instUB, bottleneckUB);
+        }
+      } else {
+        instLB->ISACencLB_obj.enforceFrameSize = 0;
+        instLB->ISACencLB_obj.new_framelength = FRAMESAMPLES;
+      }
+    }
+  }
+  instISAC->encoderSamplingRateKHz = encoder_operational_rate;
+  instISAC->in_sample_rate_hz = sample_rate_hz;
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * This function sets the sampling rate of the decoder. Initialization of the
+ * decoder WILL NOT overwrite the sampling rate of the encoder. The default
+ * value is 16 kHz which is set when the instance is created.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *        - sample_rate_hz    : sampling rate in Hertz, valid values are 16000
+ *                              and 32000.
+ *
+ * Return value               : 0 if successful
+ *                             -1 if failed.
+ */
+int16_t WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
+                                  uint16_t sample_rate_hz) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  enum IsacSamplingRate decoder_operational_rate;
+
+  if (sample_rate_hz == 16000) {
+    decoder_operational_rate = kIsacWideband;
+  } else if (sample_rate_hz == 32000) {
+    decoder_operational_rate = kIsacSuperWideband;
+  } else {
+    /* Sampling Frequency is not supported. */
+    instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+    return -1;
+  }
+
+  if ((instISAC->decoderSamplingRateKHz == kIsacWideband) &&
+        (decoder_operational_rate == kIsacSuperWideband)) {
+      /* Switching from wideband to super-wideband at the decoder
+       * we need to reset the filter-bank and initialize upper-band decoder. */
+      memset(instISAC->synthesisFBState1, 0,
+             FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+      memset(instISAC->synthesisFBState2, 0,
+             FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+      DecoderInitUb(&instISAC->instUB);
+  }
+  instISAC->decoderSamplingRateKHz = decoder_operational_rate;
+  return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Return value               : sampling rate in Hertz. The input to encoder
+ *                              is expected to be sampled in this rate.
+ *
+ */
+uint16_t WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  return instISAC->in_sample_rate_hz;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ *        - ISAC_main_inst    : iSAC instance
+ *
+ * Return value               : sampling rate in Hertz. Decoder output is
+ *                              sampled at this rate.
+ *
+ */
+uint16_t WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+  return instISAC->decoderSamplingRateKHz == kIsacWideband ? 16000 : 32000;
+}
+
+void WebRtcIsac_SetEncSampRateInDecoder(ISACStruct* inst,
+                                        int sample_rate_hz) {
+  ISACMainStruct* instISAC = (ISACMainStruct*)inst;
+  RTC_DCHECK_NE(0, instISAC->initFlag & BIT_MASK_DEC_INIT);
+  RTC_DCHECK(!(instISAC->initFlag & BIT_MASK_ENC_INIT));
+  RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+  instISAC->encoderSamplingRateKHz = sample_rate_hz / 1000;
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/isac_float_type.h b/modules/audio_coding/codecs/isac/main/source/isac_float_type.h
new file mode 100644
index 0000000..511bc97
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/isac_float_type.h
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
+
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+namespace webrtc {
+
+struct IsacFloat {
+  using instance_type = ISACStruct;
+  static const bool has_swb = true;
+  static inline int16_t Control(instance_type* inst,
+                                int32_t rate,
+                                int framesize) {
+    return WebRtcIsac_Control(inst, rate, framesize);
+  }
+  static inline int16_t ControlBwe(instance_type* inst,
+                                   int32_t rate_bps,
+                                   int frame_size_ms,
+                                   int16_t enforce_frame_size) {
+    return WebRtcIsac_ControlBwe(inst, rate_bps, frame_size_ms,
+                                 enforce_frame_size);
+  }
+  static inline int16_t Create(instance_type** inst) {
+    return WebRtcIsac_Create(inst);
+  }
+  static inline int DecodeInternal(instance_type* inst,
+                                   const uint8_t* encoded,
+                                   size_t len,
+                                   int16_t* decoded,
+                                   int16_t* speech_type) {
+    return WebRtcIsac_Decode(inst, encoded, len, decoded, speech_type);
+  }
+  static inline size_t DecodePlc(instance_type* inst,
+                                 int16_t* decoded,
+                                 size_t num_lost_frames) {
+    return WebRtcIsac_DecodePlc(inst, decoded, num_lost_frames);
+  }
+
+  static inline void DecoderInit(instance_type* inst) {
+    WebRtcIsac_DecoderInit(inst);
+  }
+  static inline int Encode(instance_type* inst,
+                           const int16_t* speech_in,
+                           uint8_t* encoded) {
+    return WebRtcIsac_Encode(inst, speech_in, encoded);
+  }
+  static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+    return WebRtcIsac_EncoderInit(inst, coding_mode);
+  }
+  static inline uint16_t EncSampRate(instance_type* inst) {
+    return WebRtcIsac_EncSampRate(inst);
+  }
+
+  static inline int16_t Free(instance_type* inst) {
+    return WebRtcIsac_Free(inst);
+  }
+  static inline int16_t GetErrorCode(instance_type* inst) {
+    return WebRtcIsac_GetErrorCode(inst);
+  }
+
+  static inline int16_t GetNewFrameLen(instance_type* inst) {
+    return WebRtcIsac_GetNewFrameLen(inst);
+  }
+  static inline int16_t SetDecSampRate(instance_type* inst,
+                                       uint16_t sample_rate_hz) {
+    return WebRtcIsac_SetDecSampRate(inst, sample_rate_hz);
+  }
+  static inline int16_t SetEncSampRate(instance_type* inst,
+                                       uint16_t sample_rate_hz) {
+    return WebRtcIsac_SetEncSampRate(inst, sample_rate_hz);
+  }
+  static inline void SetEncSampRateInDecoder(instance_type* inst,
+                                             uint16_t sample_rate_hz) {
+    WebRtcIsac_SetEncSampRateInDecoder(inst, sample_rate_hz);
+  }
+  static inline void SetInitialBweBottleneck(instance_type* inst,
+                                             int bottleneck_bits_per_second) {
+    WebRtcIsac_SetInitialBweBottleneck(inst, bottleneck_bits_per_second);
+  }
+  static inline int16_t SetMaxPayloadSize(instance_type* inst,
+                                          int16_t max_payload_size_bytes) {
+    return WebRtcIsac_SetMaxPayloadSize(inst, max_payload_size_bytes);
+  }
+  static inline int16_t SetMaxRate(instance_type* inst, int32_t max_bit_rate) {
+    return WebRtcIsac_SetMaxRate(inst, max_bit_rate);
+  }
+};
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
diff --git a/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
new file mode 100644
index 0000000..c98b21d
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+#include <string>
+
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+struct WebRtcISACStruct;
+
+namespace webrtc {
+
+// Number of samples in a 60 ms, sampled at 32 kHz.
+const int kIsacNumberOfSamples = 320 * 6;
+// Maximum number of bytes in output bitstream.
+const size_t kMaxBytes = 1000;
+
+class IsacTest : public ::testing::Test {
+ protected:
+  IsacTest();
+  virtual void SetUp();
+
+  WebRtcISACStruct* isac_codec_;
+
+  int16_t speech_data_[kIsacNumberOfSamples];
+  int16_t output_data_[kIsacNumberOfSamples];
+  uint8_t bitstream_[kMaxBytes];
+  uint8_t bitstream_small_[7];  // Simulate sync packets.
+};
+
+IsacTest::IsacTest() : isac_codec_(NULL) {}
+
+void IsacTest::SetUp() {
+  // Read some samples from a speech file, to be used in the encode test.
+  FILE* input_file;
+  const std::string file_name =
+      webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+  input_file = fopen(file_name.c_str(), "rb");
+  ASSERT_TRUE(input_file != NULL);
+  ASSERT_EQ(kIsacNumberOfSamples,
+            static_cast<int32_t>(fread(speech_data_, sizeof(int16_t),
+                                       kIsacNumberOfSamples, input_file)));
+  fclose(input_file);
+  input_file = NULL;
+}
+
+// Test failing Create.
+TEST_F(IsacTest, IsacCreateFail) {
+  // Test to see that an invalid pointer is caught.
+  EXPECT_EQ(-1, WebRtcIsac_Create(NULL));
+}
+
+// Test failing Free.
+TEST_F(IsacTest, IsacFreeFail) {
+  // Test to see that free function doesn't crash.
+  EXPECT_EQ(0, WebRtcIsac_Free(NULL));
+}
+
+// Test normal Create and Free.
+TEST_F(IsacTest, IsacCreateFree) {
+  EXPECT_EQ(0, WebRtcIsac_Create(&isac_codec_));
+  EXPECT_TRUE(isac_codec_ != NULL);
+  EXPECT_EQ(0, WebRtcIsac_Free(isac_codec_));
+}
+
+TEST_F(IsacTest, IsacUpdateBWE) {
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcIsac_Create(&isac_codec_));
+
+  // Init encoder (adaptive mode) and decoder.
+  WebRtcIsac_EncoderInit(isac_codec_, 0);
+  WebRtcIsac_DecoderInit(isac_codec_);
+
+  int encoded_bytes;
+
+  // Test with call with a small packet (sync packet).
+  EXPECT_EQ(-1, WebRtcIsac_UpdateBwEstimate(isac_codec_, bitstream_small_, 7, 1,
+                                            12345, 56789));
+
+  // Encode 60 ms of data (needed to create a first packet).
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_EQ(0, encoded_bytes);
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_EQ(0, encoded_bytes);
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_EQ(0, encoded_bytes);
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_EQ(0, encoded_bytes);
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_EQ(0, encoded_bytes);
+  encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+  EXPECT_GT(encoded_bytes, 0);
+
+  // Call to update bandwidth estimator with real data.
+  EXPECT_EQ(0, WebRtcIsac_UpdateBwEstimate(isac_codec_, bitstream_,
+                                           static_cast<size_t>(encoded_bytes),
+                                           1, 12345, 56789));
+
+  // Free memory.
+  EXPECT_EQ(0, WebRtcIsac_Free(isac_codec_));
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/isac/main/source/lattice.c b/modules/audio_coding/codecs/isac/main/source/lattice.c
new file mode 100644
index 0000000..d9d2d65
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lattice.c
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+
+#include <math.h>
+#include <memory.h>
+#include <string.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+                                     float *stateF,
+                                     float *stateG,
+                                     float *lat_in,
+                                     double *filtcoeflo,
+                                     double *lat_out)
+{
+  int n,k,i,u,temp1;
+  int ord_1 = orderCoef+1;
+  float sth[MAX_AR_MODEL_ORDER];
+  float cth[MAX_AR_MODEL_ORDER];
+  float inv_cth[MAX_AR_MODEL_ORDER];
+  double a[MAX_AR_MODEL_ORDER+1];
+  float f[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], g[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+  float gain1;
+
+  for (u=0;u<SUBFRAMES;u++)
+  {
+    /* set the Direct Form coefficients */
+    temp1 = u*ord_1;
+    a[0] = 1;
+    memcpy(a+1, filtcoeflo+temp1+1, sizeof(double) * (ord_1-1));
+
+    /* compute lattice filter coefficients */
+    WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+    /* compute the gain */
+    gain1 = (float)filtcoeflo[temp1];
+    for (k=0;k<orderCoef;k++)
+    {
+      gain1 *= cth[k];
+      inv_cth[k] = 1/cth[k];
+    }
+
+    /* normalized lattice filter */
+    /*****************************/
+
+    /* initial conditions */
+    for (i=0;i<HALF_SUBFRAMELEN;i++)
+    {
+      f[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+      g[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+    }
+
+    /* get the state of f&g for the first input, for all orders */
+    for (i=1;i<ord_1;i++)
+    {
+      f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+      g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+    }
+
+    /* filtering */
+    for(k=0;k<orderCoef;k++)
+    {
+      for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+      {
+        f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
+        g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
+      }
+    }
+
+    for(n=0;n<HALF_SUBFRAMELEN;n++)
+    {
+      lat_out[n + u * HALF_SUBFRAMELEN] = gain1 * f[orderCoef][n];
+    }
+
+    /* save the states */
+    for (i=0;i<ord_1;i++)
+    {
+      stateF[i] = f[i][HALF_SUBFRAMELEN-1];
+      stateG[i] = g[i][HALF_SUBFRAMELEN-1];
+    }
+    /* process next frame */
+  }
+
+  return;
+}
+
+
+/*///////////////////AR filter ///////////////////////////////*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+                                     float *stateF,
+                                     float *stateG,
+                                     double *lat_in,
+                                     double *lo_filt_coef,
+                                     float *lat_out)
+{
+  int n,k,i,u,temp1;
+  int ord_1 = orderCoef+1;
+  float sth[MAX_AR_MODEL_ORDER];
+  float cth[MAX_AR_MODEL_ORDER];
+  double a[MAX_AR_MODEL_ORDER+1];
+  float ARf[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], ARg[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+  float gain1,inv_gain1;
+
+  for (u=0;u<SUBFRAMES;u++)
+  {
+    /* set the denominator and numerator of the Direct Form */
+    temp1 = u*ord_1;
+    a[0] = 1;
+
+    memcpy(a+1, lo_filt_coef+temp1+1, sizeof(double) * (ord_1-1));
+
+    WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+    gain1 = (float)lo_filt_coef[temp1];
+    for (k=0;k<orderCoef;k++)
+    {
+      gain1 = cth[k]*gain1;
+    }
+
+    /* initial conditions */
+    inv_gain1 = 1/gain1;
+    for (i=0;i<HALF_SUBFRAMELEN;i++)
+    {
+      ARf[orderCoef][i] = (float)lat_in[i + u * HALF_SUBFRAMELEN]*inv_gain1;
+    }
+
+
+    for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
+    {
+      ARf[i][0] = cth[i]*ARf[i+1][0] - sth[i]*stateG[i];
+      ARg[i+1][0] = sth[i]*ARf[i+1][0] + cth[i]* stateG[i];
+    }
+    ARg[0][0] = ARf[0][0];
+
+    for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+    {
+      for(k=orderCoef-1;k>=0;k--)
+      {
+        ARf[k][n+1] = cth[k]*ARf[k+1][n+1] - sth[k]*ARg[k][n];
+        ARg[k+1][n+1] = sth[k]*ARf[k+1][n+1] + cth[k]* ARg[k][n];
+      }
+      ARg[0][n+1] = ARf[0][n+1];
+    }
+
+    memcpy(lat_out+u * HALF_SUBFRAMELEN, &(ARf[0][0]), sizeof(float) * HALF_SUBFRAMELEN);
+
+    /* cannot use memcpy in the following */
+    for (i=0;i<ord_1;i++)
+    {
+      stateF[i] = ARf[i][HALF_SUBFRAMELEN-1];
+      stateG[i] = ARg[i][HALF_SUBFRAMELEN-1];
+    }
+
+  }
+
+  return;
+}
+
+
+/* compute the reflection coefficients using the step-down procedure*/
+/* converts the direct form parameters to lattice form.*/
+/* a and b are vectors which contain the direct form coefficients,
+   according to
+   A(z) = a(1) + a(2)*z + a(3)*z^2 + ... + a(M+1)*z^M
+   B(z) = b(1) + b(2)*z + b(3)*z^2 + ... + b(M+1)*z^M
+*/
+
+void WebRtcIsac_Dir2Lat(double *a,
+                        int orderCoef,
+                        float *sth,
+                        float *cth)
+{
+  int m, k;
+  float tmp[MAX_AR_MODEL_ORDER];
+  float tmp_inv, cth2;
+
+  sth[orderCoef-1] = (float)a[orderCoef];
+  cth2 = 1.0f - sth[orderCoef-1] * sth[orderCoef-1];
+  cth[orderCoef-1] = (float)sqrt(cth2);
+  for (m=orderCoef-1; m>0; m--)
+  {
+    tmp_inv = 1.0f / cth2;
+    for (k=1; k<=m; k++)
+    {
+      tmp[k] = ((float)a[k] - sth[m] * (float)a[m-k+1]) * tmp_inv;
+    }
+
+    for (k=1; k<m; k++)
+    {
+      a[k] = tmp[k];
+    }
+
+    sth[m-1] = tmp[m];
+    cth2 = 1 - sth[m-1] * sth[m-1];
+    cth[m-1] = (float)sqrt(cth2);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c b/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
new file mode 100644
index 0000000..0fda73b
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
@@ -0,0 +1,496 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_analysis.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/filter_functions.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+/* window */
+/* Matlab generation code:
+ *  t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ *  for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ */
+static const double kLpcCorrWindow[WINLEN] = {
+  0.00000000, 0.00000001, 0.00000004, 0.00000010, 0.00000020,
+  0.00000035, 0.00000055, 0.00000083, 0.00000118, 0.00000163,
+  0.00000218, 0.00000283, 0.00000361, 0.00000453, 0.00000558, 0.00000679,
+  0.00000817, 0.00000973, 0.00001147, 0.00001342, 0.00001558,
+  0.00001796, 0.00002058, 0.00002344, 0.00002657, 0.00002997,
+  0.00003365, 0.00003762, 0.00004190, 0.00004651, 0.00005144, 0.00005673,
+  0.00006236, 0.00006837, 0.00007476, 0.00008155, 0.00008875,
+  0.00009636, 0.00010441, 0.00011290, 0.00012186, 0.00013128,
+  0.00014119, 0.00015160, 0.00016252, 0.00017396, 0.00018594, 0.00019846,
+  0.00021155, 0.00022521, 0.00023946, 0.00025432, 0.00026978,
+  0.00028587, 0.00030260, 0.00031998, 0.00033802, 0.00035674,
+  0.00037615, 0.00039626, 0.00041708, 0.00043863, 0.00046092, 0.00048396,
+  0.00050775, 0.00053233, 0.00055768, 0.00058384, 0.00061080,
+  0.00063858, 0.00066720, 0.00069665, 0.00072696, 0.00075813,
+  0.00079017, 0.00082310, 0.00085692, 0.00089164, 0.00092728, 0.00096384,
+  0.00100133, 0.00103976, 0.00107914, 0.00111947, 0.00116077,
+  0.00120304, 0.00124630, 0.00129053, 0.00133577, 0.00138200,
+  0.00142924, 0.00147749, 0.00152676, 0.00157705, 0.00162836, 0.00168070,
+  0.00173408, 0.00178850, 0.00184395, 0.00190045, 0.00195799,
+  0.00201658, 0.00207621, 0.00213688, 0.00219860, 0.00226137,
+  0.00232518, 0.00239003, 0.00245591, 0.00252284, 0.00259079, 0.00265977,
+  0.00272977, 0.00280078, 0.00287280, 0.00294582, 0.00301984,
+  0.00309484, 0.00317081, 0.00324774, 0.00332563, 0.00340446,
+  0.00348421, 0.00356488, 0.00364644, 0.00372889, 0.00381220, 0.00389636,
+  0.00398135, 0.00406715, 0.00415374, 0.00424109, 0.00432920,
+  0.00441802, 0.00450754, 0.00459773, 0.00468857, 0.00478001,
+  0.00487205, 0.00496464, 0.00505775, 0.00515136, 0.00524542, 0.00533990,
+  0.00543476, 0.00552997, 0.00562548, 0.00572125, 0.00581725,
+  0.00591342, 0.00600973, 0.00610612, 0.00620254, 0.00629895,
+  0.00639530, 0.00649153, 0.00658758, 0.00668341, 0.00677894, 0.00687413,
+  0.00696891, 0.00706322, 0.00715699, 0.00725016, 0.00734266,
+  0.00743441, 0.00752535, 0.00761540, 0.00770449, 0.00779254,
+  0.00787947, 0.00796519, 0.00804963, 0.00813270, 0.00821431, 0.00829437,
+  0.00837280, 0.00844949, 0.00852436, 0.00859730, 0.00866822,
+  0.00873701, 0.00880358, 0.00886781, 0.00892960, 0.00898884,
+  0.00904542, 0.00909923, 0.00915014, 0.00919805, 0.00924283, 0.00928436,
+  0.00932252, 0.00935718, 0.00938821, 0.00941550, 0.00943890,
+  0.00945828, 0.00947351, 0.00948446, 0.00949098, 0.00949294,
+  0.00949020, 0.00948262, 0.00947005, 0.00945235, 0.00942938, 0.00940099,
+  0.00936704, 0.00932738, 0.00928186, 0.00923034, 0.00917268,
+  0.00910872, 0.00903832, 0.00896134, 0.00887763, 0.00878706,
+  0.00868949, 0.00858478, 0.00847280, 0.00835343, 0.00822653, 0.00809199,
+  0.00794970, 0.00779956, 0.00764145, 0.00747530, 0.00730103,
+  0.00711857, 0.00692787, 0.00672888, 0.00652158, 0.00630597,
+  0.00608208, 0.00584994, 0.00560962, 0.00536124, 0.00510493, 0.00484089,
+  0.00456935, 0.00429062, 0.00400505, 0.00371310, 0.00341532,
+  0.00311238, 0.00280511, 0.00249452, 0.00218184, 0.00186864,
+  0.00155690, 0.00124918, 0.00094895, 0.00066112, 0.00039320, 0.00015881
+};
+
+static void WebRtcIsac_GetVars(const double* input,
+                               const int16_t* pitchGains_Q12,
+                               double* oldEnergy,
+                               double* varscale) {
+  double nrg[4], chng, pg;
+  int k;
+
+  double pitchGains[4]={0,0,0,0};;
+
+  /* Calculate energies of first and second frame halfs */
+  nrg[0] = 0.0001;
+  for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES_QUARTER + QLOOKAHEAD) / 2; k++) {
+    nrg[0] += input[k]*input[k];
+  }
+  nrg[1] = 0.0001;
+  for ( ; k < (FRAMESAMPLES_HALF + QLOOKAHEAD) / 2; k++) {
+    nrg[1] += input[k]*input[k];
+  }
+  nrg[2] = 0.0001;
+  for ( ; k < (FRAMESAMPLES*3/4 + QLOOKAHEAD) / 2; k++) {
+    nrg[2] += input[k]*input[k];
+  }
+  nrg[3] = 0.0001;
+  for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+    nrg[3] += input[k]*input[k];
+  }
+
+  /* Calculate average level change */
+  chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+                 fabs(10.0 * log10(nrg[2] / nrg[1])) +
+                 fabs(10.0 * log10(nrg[1] / nrg[0])) +
+                 fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+  /* Find average pitch gain */
+  pg = 0.0;
+  for (k=0; k<4; k++)
+  {
+    pitchGains[k] = ((float)pitchGains_Q12[k])/4096;
+    pg += pitchGains[k];
+  }
+  pg *= 0.25;
+
+  /* If pitch gain is low and energy constant - increase noise level*/
+  /* Matlab code:
+     pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+  */
+  *varscale = 0.0 + 1.0 * exp( -1.4 * exp(-200.0 * pg*pg*pg) / (1.0 + 0.4 * chng) );
+
+  *oldEnergy = nrg[3];
+}
+
+static void WebRtcIsac_GetVarsUB(const double* input,
+                                 double* oldEnergy,
+                                 double* varscale) {
+  double nrg[4], chng;
+  int k;
+
+  /* Calculate energies of first and second frame halfs */
+  nrg[0] = 0.0001;
+  for (k = 0; k < (FRAMESAMPLES_QUARTER) / 2; k++) {
+    nrg[0] += input[k]*input[k];
+  }
+  nrg[1] = 0.0001;
+  for ( ; k < (FRAMESAMPLES_HALF) / 2; k++) {
+    nrg[1] += input[k]*input[k];
+  }
+  nrg[2] = 0.0001;
+  for ( ; k < (FRAMESAMPLES*3/4) / 2; k++) {
+    nrg[2] += input[k]*input[k];
+  }
+  nrg[3] = 0.0001;
+  for ( ; k < (FRAMESAMPLES) / 2; k++) {
+    nrg[3] += input[k]*input[k];
+  }
+
+  /* Calculate average level change */
+  chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+                 fabs(10.0 * log10(nrg[2] / nrg[1])) +
+                 fabs(10.0 * log10(nrg[1] / nrg[0])) +
+                 fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+  /* If pitch gain is low and energy constant - increase noise level*/
+  /* Matlab code:
+     pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+  */
+  *varscale = exp( -1.4 / (1.0 + 0.4 * chng) );
+
+  *oldEnergy = nrg[3];
+}
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+                             double signal_noise_ratio, const int16_t *pitchGains_Q12,
+                             double *lo_coeff, double *hi_coeff)
+{
+  int k, n, j, pos1, pos2;
+  double varscale;
+
+  double DataLo[WINLEN], DataHi[WINLEN];
+  double corrlo[ORDERLO+2], corrlo2[ORDERLO+1];
+  double corrhi[ORDERHI+1];
+  double k_veclo[ORDERLO], k_vechi[ORDERHI];
+
+  double a_LO[ORDERLO+1], a_HI[ORDERHI+1];
+  double tmp, res_nrg;
+
+  double FwdA, FwdB;
+
+  /* hearing threshold level in dB; higher value gives more noise */
+  const double HearThresOffset = -28.0;
+
+  /* bandwdith expansion factors for low- and high band */
+  const double gammaLo = 0.9;
+  const double gammaHi = 0.8;
+
+  /* less-noise-at-low-frequencies factor */
+  double aa;
+
+
+  /* convert from dB to signal level */
+  const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+  double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;    /* divide by sqrt(12) */
+
+  /* change quallevel depending on pitch gains and level fluctuations */
+  WebRtcIsac_GetVars(inLo, pitchGains_Q12, &(maskdata->OldEnergy), &varscale);
+
+  /* less-noise-at-low-frequencies factor */
+  aa = 0.35 * (0.5 + 0.5 * varscale);
+
+  /* replace data in buffer by new look-ahead data */
+  for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++)
+    maskdata->DataBufferLo[pos1 + WINLEN - QLOOKAHEAD] = inLo[pos1];
+
+  for (k = 0; k < SUBFRAMES; k++) {
+
+    /* Update input buffer and multiply signal with window */
+    for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+      maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 + UPDATE/2];
+      maskdata->DataBufferHi[pos1] = maskdata->DataBufferHi[pos1 + UPDATE/2];
+      DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+      DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+    }
+    pos2 = k * UPDATE/2;
+    for (n = 0; n < UPDATE/2; n++, pos1++) {
+      maskdata->DataBufferLo[pos1] = inLo[QLOOKAHEAD + pos2];
+      maskdata->DataBufferHi[pos1] = inHi[pos2++];
+      DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+      DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+    }
+
+    /* Get correlation coefficients */
+    WebRtcIsac_AutoCorr(corrlo, DataLo, WINLEN, ORDERLO+1); /* computing autocorrelation */
+    WebRtcIsac_AutoCorr(corrhi, DataHi, WINLEN, ORDERHI);
+
+
+    /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+    corrlo2[0] = (1.0+aa*aa) * corrlo[0] - 2.0*aa * corrlo[1];
+    tmp = (1.0 + aa*aa);
+    for (n = 1; n <= ORDERLO; n++) {
+      corrlo2[n] = tmp * corrlo[n] - aa * (corrlo[n-1] + corrlo[n+1]);
+    }
+    tmp = (1.0+aa) * (1.0+aa);
+    for (n = 0; n <= ORDERHI; n++) {
+      corrhi[n] = tmp * corrhi[n];
+    }
+
+    /* add white noise floor */
+    corrlo2[0] += 1e-6;
+    corrhi[0] += 1e-6;
+
+
+    FwdA = 0.01;
+    FwdB = 0.01;
+
+    /* recursive filtering of correlation over subframes */
+    for (n = 0; n <= ORDERLO; n++) {
+      maskdata->CorrBufLo[n] = FwdA * maskdata->CorrBufLo[n] + corrlo2[n];
+      corrlo2[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufLo[n] + (1.0-FwdB) * corrlo2[n];
+    }
+    for (n = 0; n <= ORDERHI; n++) {
+      maskdata->CorrBufHi[n] = FwdA * maskdata->CorrBufHi[n] + corrhi[n];
+      corrhi[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufHi[n] + (1.0-FwdB) * corrhi[n];
+    }
+
+    /* compute prediction coefficients */
+    WebRtcIsac_LevDurb(a_LO, k_veclo, corrlo2, ORDERLO);
+    WebRtcIsac_LevDurb(a_HI, k_vechi, corrhi, ORDERHI);
+
+    /* bandwidth expansion */
+    tmp = gammaLo;
+    for (n = 1; n <= ORDERLO; n++) {
+      a_LO[n] *= tmp;
+      tmp *= gammaLo;
+    }
+
+    /* residual energy */
+    res_nrg = 0.0;
+    for (j = 0; j <= ORDERLO; j++) {
+      for (n = 0; n <= j; n++) {
+        res_nrg += a_LO[j] * corrlo2[j-n] * a_LO[n];
+      }
+      for (n = j+1; n <= ORDERLO; n++) {
+        res_nrg += a_LO[j] * corrlo2[n-j] * a_LO[n];
+      }
+    }
+
+    /* add hearing threshold and compute the gain */
+    *lo_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+    /* copy coefficients to output array */
+    for (n = 1; n <= ORDERLO; n++) {
+      *lo_coeff++ = a_LO[n];
+    }
+
+
+    /* bandwidth expansion */
+    tmp = gammaHi;
+    for (n = 1; n <= ORDERHI; n++) {
+      a_HI[n] *= tmp;
+      tmp *= gammaHi;
+    }
+
+    /* residual energy */
+    res_nrg = 0.0;
+    for (j = 0; j <= ORDERHI; j++) {
+      for (n = 0; n <= j; n++) {
+        res_nrg += a_HI[j] * corrhi[j-n] * a_HI[n];
+      }
+      for (n = j+1; n <= ORDERHI; n++) {
+        res_nrg += a_HI[j] * corrhi[n-j] * a_HI[n];
+      }
+    }
+
+    /* add hearing threshold and compute of the gain */
+    *hi_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+    /* copy coefficients to output array */
+    for (n = 1; n <= ORDERHI; n++) {
+      *hi_coeff++ = a_HI[n];
+    }
+  }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcCoefUb()
+ *
+ * Compute LP coefficients and correlation coefficients. At 12 kHz LP
+ * coefficients of the first and the last sub-frame is computed. At 16 kHz
+ * LP coefficients of 4th, 8th and 12th sub-frames are computed. We always
+ * compute correlation coefficients of all sub-frames.
+ *
+ * Inputs:
+ *       -inSignal           : Input signal
+ *       -maskdata           : a structure keeping signal from previous frame.
+ *       -bandwidth          : specifies if the codec is in 0-16 kHz mode or
+ *                             0-12 kHz mode.
+ *
+ * Outputs:
+ *       -lpCoeff            : pointer to a buffer where A-polynomials are
+ *                             written to (first coeff is 1 and it is not
+ *                             written)
+ *       -corrMat            : a matrix where correlation coefficients of each
+ *                             sub-frame are written to one row.
+ *       -varscale           : a scale used to compute LPC gains.
+ */
+void
+WebRtcIsac_GetLpcCoefUb(
+    double*      inSignal,
+    MaskFiltstr* maskdata,
+    double*      lpCoeff,
+    double       corrMat[][UB_LPC_ORDER + 1],
+    double*      varscale,
+    int16_t  bandwidth)
+{
+  int frameCntr, activeFrameCntr, n, pos1, pos2;
+  int16_t criterion1;
+  int16_t criterion2;
+  int16_t numSubFrames = SUBFRAMES * (1 + (bandwidth == isac16kHz));
+  double data[WINLEN];
+  double corrSubFrame[UB_LPC_ORDER+2];
+  double reflecCoeff[UB_LPC_ORDER];
+
+  double aPolynom[UB_LPC_ORDER+1];
+  double tmp;
+
+  /* bandwdith expansion factors */
+  const double gamma = 0.9;
+
+  /* change quallevel depending on pitch gains and level fluctuations */
+  WebRtcIsac_GetVarsUB(inSignal, &(maskdata->OldEnergy), varscale);
+
+  /* replace data in buffer by new look-ahead data */
+  for(frameCntr = 0, activeFrameCntr = 0; frameCntr < numSubFrames;
+      frameCntr++)
+  {
+    if(frameCntr == SUBFRAMES)
+    {
+      // we are in 16 kHz
+      varscale++;
+      WebRtcIsac_GetVarsUB(&inSignal[FRAMESAMPLES_HALF],
+                          &(maskdata->OldEnergy), varscale);
+    }
+    /* Update input buffer and multiply signal with window */
+    for(pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++)
+    {
+      maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 +
+                                                            UPDATE/2];
+      data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+    }
+    pos2 = frameCntr * UPDATE/2;
+    for(n = 0; n < UPDATE/2; n++, pos1++, pos2++)
+    {
+      maskdata->DataBufferLo[pos1] = inSignal[pos2];
+      data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+    }
+
+    /* Get correlation coefficients */
+    /* computing autocorrelation    */
+    WebRtcIsac_AutoCorr(corrSubFrame, data, WINLEN, UB_LPC_ORDER+1);
+    memcpy(corrMat[frameCntr], corrSubFrame,
+           (UB_LPC_ORDER+1)*sizeof(double));
+
+    criterion1 = ((frameCntr == 0) || (frameCntr == (SUBFRAMES - 1))) &&
+        (bandwidth == isac12kHz);
+    criterion2 = (((frameCntr+1) % 4) == 0) &&
+        (bandwidth == isac16kHz);
+    if(criterion1 || criterion2)
+    {
+      /* add noise */
+      corrSubFrame[0] += 1e-6;
+      /* compute prediction coefficients */
+      WebRtcIsac_LevDurb(aPolynom, reflecCoeff, corrSubFrame,
+                        UB_LPC_ORDER);
+
+      /* bandwidth expansion */
+      tmp = gamma;
+      for (n = 1; n <= UB_LPC_ORDER; n++)
+      {
+        *lpCoeff++ = aPolynom[n] * tmp;
+        tmp *= gamma;
+      }
+      activeFrameCntr++;
+    }
+  }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcGain()
+ *
+ * Compute the LPC gains for each sub-frame, given the LPC of each sub-frame
+ * and the corresponding correlation coefficients.
+ *
+ * Inputs:
+ *       -signal_noise_ratio : the desired SNR in dB.
+ *       -numVecs            : number of sub-frames
+ *       -corrMat             : a matrix of correlation coefficients where
+ *                             each row is a set of correlation coefficients of
+ *                             one sub-frame.
+ *       -varscale           : a scale computed when WebRtcIsac_GetLpcCoefUb()
+ *                             is called.
+ *
+ * Outputs:
+ *       -gain               : pointer to a buffer where LP gains are written.
+ *
+ */
+void
+WebRtcIsac_GetLpcGain(
+    double        signal_noise_ratio,
+    const double* filtCoeffVecs,
+    int           numVecs,
+    double*       gain,
+    double        corrMat[][UB_LPC_ORDER + 1],
+    const double* varscale)
+{
+  int16_t j, n;
+  int16_t subFrameCntr;
+  double aPolynom[ORDERLO + 1];
+  double res_nrg;
+
+  const double HearThresOffset = -28.0;
+  const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+  /* divide by sqrt(12) = 3.46 */
+  const double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;
+
+  aPolynom[0] = 1;
+  for(subFrameCntr = 0; subFrameCntr < numVecs; subFrameCntr++)
+  {
+    if(subFrameCntr == SUBFRAMES)
+    {
+      // we are in second half of a SWB frame. use new varscale
+      varscale++;
+    }
+    memcpy(&aPolynom[1], &filtCoeffVecs[(subFrameCntr * (UB_LPC_ORDER + 1)) +
+                                        1], sizeof(double) * UB_LPC_ORDER);
+
+    /* residual energy */
+    res_nrg = 0.0;
+    for(j = 0; j <= UB_LPC_ORDER; j++)
+    {
+      for(n = 0; n <= j; n++)
+      {
+        res_nrg += aPolynom[j] * corrMat[subFrameCntr][j-n] *
+            aPolynom[n];
+      }
+      for(n = j+1; n <= UB_LPC_ORDER; n++)
+      {
+        res_nrg += aPolynom[j] * corrMat[subFrameCntr][n-j] *
+            aPolynom[n];
+      }
+    }
+
+    /* add hearing threshold and compute the gain */
+    gain[subFrameCntr] = S_N_R / (sqrt(res_nrg) / *varscale + H_T_H);
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h b/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
new file mode 100644
index 0000000..5503e2d
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_analysis.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_GetLpcCoefLb(double* inLo,
+                             double* inHi,
+                             MaskFiltstr* maskdata,
+                             double signal_noise_ratio,
+                             const int16_t* pitchGains_Q12,
+                             double* lo_coeff,
+                             double* hi_coeff);
+
+void WebRtcIsac_GetLpcGain(double signal_noise_ratio,
+                           const double* filtCoeffVecs,
+                           int numVecs,
+                           double* gain,
+                           double corrLo[][UB_LPC_ORDER + 1],
+                           const double* varscale);
+
+void WebRtcIsac_GetLpcCoefUb(double* inSignal,
+                             MaskFiltstr* maskdata,
+                             double* lpCoeff,
+                             double corr[][UB_LPC_ORDER + 1],
+                             double* varscale,
+                             int16_t bandwidth);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYIS_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
new file mode 100644
index 0000000..6707540
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.c
+ *
+ * This file defines tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+const double WebRtcIsac_kQSizeLpcGain = 0.100000;
+
+const double WebRtcIsac_kMeanLpcGain = -3.3822;
+
+/*
+* The smallest reconstruction points for quantiztion of
+* LPC gains.
+*/
+const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES] =
+{
+   -0.800000, -1.000000, -1.200000, -2.200000, -3.000000, -12.700000
+};
+
+/*
+* Number of reconstruction points of quantizers for LPC Gains.
+*/
+const int16_t WebRtcIsac_kNumQCellLpcGain[SUBFRAMES] =
+{
+    17,  20,  25,  45,  77, 170
+};
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES] =
+{
+     8,  10,  12,  22,  38,  85
+};
+
+/*
+* The following 6 vectors define CDF of 6 decorrelated LPC
+* gains.
+*/
+const uint16_t WebRtcIsac_kLpcGainCdfVec0[18] =
+{
+     0,    10,    27,    83,   234,   568,  1601,  4683, 16830, 57534, 63437,
+ 64767, 65229, 65408, 65483, 65514, 65527, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec1[21] =
+{
+     0,    15,    33,    84,   185,   385,   807,  1619,  3529,  7850, 19488,
+ 51365, 62437, 64548, 65088, 65304, 65409, 65484, 65507, 65522, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec2[26] =
+{
+     0,    15,    29,    54,    89,   145,   228,   380,   652,  1493,  4260,
+ 12359, 34133, 50749, 57224, 60814, 62927, 64078, 64742, 65103, 65311, 65418,
+ 65473, 65509, 65521, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec3[46] =
+{
+     0,     8,    12,    16,    26,    42,    56,    76,   111,   164,   247,
+   366,   508,   693,  1000,  1442,  2155,  3188,  4854,  7387, 11249, 17617,
+ 30079, 46711, 56291, 60127, 62140, 63258, 63954, 64384, 64690, 64891, 65031,
+ 65139, 65227, 65293, 65351, 65399, 65438, 65467, 65492, 65504, 65510, 65518,
+ 65523, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec4[78] =
+{
+     0,    17,    29,    39,    51,    70,   104,   154,   234,   324,   443,
+   590,   760,   971,  1202,  1494,  1845,  2274,  2797,  3366,  4088,  4905,
+  5899,  7142,  8683, 10625, 12983, 16095, 20637, 28216, 38859, 47237, 51537,
+ 54150, 56066, 57583, 58756, 59685, 60458, 61103, 61659, 62144, 62550, 62886,
+ 63186, 63480, 63743, 63954, 64148, 64320, 64467, 64600, 64719, 64837, 64939,
+ 65014, 65098, 65160, 65211, 65250, 65290, 65325, 65344, 65366, 65391, 65410,
+ 65430, 65447, 65460, 65474, 65487, 65494, 65501, 65509, 65513, 65518, 65520,
+ 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec5[171] =
+{
+     0,    10,    12,    14,    16,    18,    23,    29,    35,    42,    51,
+    58,    65,    72,    78,    87,    96,   103,   111,   122,   134,   150,
+   167,   184,   202,   223,   244,   265,   289,   315,   346,   379,   414,
+   450,   491,   532,   572,   613,   656,   700,   751,   802,   853,   905,
+   957,  1021,  1098,  1174,  1250,  1331,  1413,  1490,  1565,  1647,  1730,
+  1821,  1913,  2004,  2100,  2207,  2314,  2420,  2532,  2652,  2783,  2921,
+  3056,  3189,  3327,  3468,  3640,  3817,  3993,  4171,  4362,  4554,  4751,
+  4948,  5142,  5346,  5566,  5799,  6044,  6301,  6565,  6852,  7150,  7470,
+  7797,  8143,  8492,  8835,  9181,  9547,  9919, 10315, 10718, 11136, 11566,
+ 12015, 12482, 12967, 13458, 13953, 14432, 14903, 15416, 15936, 16452, 16967,
+ 17492, 18024, 18600, 19173, 19736, 20311, 20911, 21490, 22041, 22597, 23157,
+ 23768, 24405, 25034, 25660, 26280, 26899, 27614, 28331, 29015, 29702, 30403,
+ 31107, 31817, 32566, 33381, 34224, 35099, 36112, 37222, 38375, 39549, 40801,
+ 42074, 43350, 44626, 45982, 47354, 48860, 50361, 51845, 53312, 54739, 56026,
+ 57116, 58104, 58996, 59842, 60658, 61488, 62324, 63057, 63769, 64285, 64779,
+ 65076, 65344, 65430, 65500, 65517, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LPC Gains
+*/
+const uint16_t* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES] =
+{
+    WebRtcIsac_kLpcGainCdfVec0, WebRtcIsac_kLpcGainCdfVec1,
+    WebRtcIsac_kLpcGainCdfVec2, WebRtcIsac_kLpcGainCdfVec3,
+    WebRtcIsac_kLpcGainCdfVec4, WebRtcIsac_kLpcGainCdfVec5
+};
+
+/*
+* A matrix to decorrellate LPC gains of subframes.
+*/
+const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES] =
+{
+    {-0.150860,  0.327872,  0.367220,  0.504613,  0.559270,  0.409234},
+    { 0.457128, -0.613591, -0.289283, -0.029734,  0.393760,  0.418240},
+    {-0.626043,  0.136489, -0.439118, -0.448323,  0.135987,  0.420869},
+    { 0.526617,  0.480187,  0.242552, -0.488754, -0.158713,  0.411331},
+    {-0.302587, -0.494953,  0.588112, -0.063035, -0.404290,  0.387510},
+    { 0.086378,  0.147714, -0.428875,  0.548300, -0.570121,  0.401391}
+};
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
new file mode 100644
index 0000000..39c4a24
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.h
+ *
+ * This file declares tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kQSizeLpcGain;
+
+extern const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES];
+
+extern const int16_t WebRtcIsac_kNumQCellLpcGain[SUBFRAMES];
+
+extern const uint16_t WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec0[18];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec1[21];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec2[26];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec3[46];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec4[78];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec5[171];
+
+extern const uint16_t* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES];
+
+extern const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES];
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
new file mode 100644
index 0000000..e3600a7
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
@@ -0,0 +1,158 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER] =
+{
+  0.03748928306641, 0.09453441192543, -0.01112522344398, 0.03800237516842
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+    {-0.00075365493856,  -0.05809964887743,  -0.23397966154116,   0.97050367376411},
+    { 0.00625021257734,  -0.17299965610679,   0.95977735920651,   0.22104179375008},
+    { 0.20543384258374,  -0.96202143495696,  -0.15301870801552,  -0.09432375099565},
+    {-0.97865075648479,  -0.20300322280841,  -0.02581111653779,  -0.01913568980258}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME] =
+{
+    { 0.70650597970460,  -0.70770707262373},
+    {-0.70770707262373,  -0.70650597970460}
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb12 = 0.150000;
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME] =
+{
+    -0.900000, -1.050000, -1.350000, -1.800000, -1.350000, -1.650000,
+    -2.250000, -3.450000
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const int16_t WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+    13, 15, 19, 27, 19, 24, 32, 48
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+     6,  7,  9, 13,  9, 12, 16, 24
+};
+
+/*
+* The following 8 vectors define CDF of 8 decorrelated LAR
+* coefficients.
+*/
+const uint16_t WebRtcIsac_kLpcShapeCdfVec0Ub12[14] =
+{
+     0,    13,    95,   418,  1687,  6498, 21317, 44200, 59029, 63849, 65147,
+ 65449, 65525, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub12[16] =
+{
+     0,    10,    59,   255,   858,  2667,  8200, 22609, 42988, 57202, 62947,
+ 64743, 65308, 65476, 65522, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub12[20] =
+{
+     0,    18,    40,   118,   332,   857,  2017,  4822, 11321, 24330, 41279,
+ 54342, 60637, 63394, 64659, 65184, 65398, 65482, 65518, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub12[28] =
+{
+     0,    21,    38,    90,   196,   398,   770,  1400,  2589,  4650,  8211,
+ 14933, 26044, 39592, 50814, 57452, 60971, 62884, 63995, 64621, 65019, 65273,
+ 65410, 65480, 65514, 65522, 65531, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub12[20] =
+{
+     0,     7,    46,   141,   403,   969,  2132,  4649, 10633, 24902, 43254,
+ 54665, 59928, 62674, 64173, 64938, 65293, 65464, 65523, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub12[25] =
+{
+     0,     7,    22,    72,   174,   411,   854,  1737,  3545,  6774, 13165,
+ 25221, 40980, 52821, 58714, 61706, 63472, 64437, 64989, 65287, 65430, 65503,
+ 65525, 65529, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub12[33] =
+{
+     0,    11,    21,    36,    65,   128,   228,   401,   707,  1241,  2126,
+  3589,  6060, 10517, 18853, 31114, 42477, 49770, 54271, 57467, 59838, 61569,
+ 62831, 63772, 64433, 64833, 65123, 65306, 65419, 65466, 65499, 65519, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub12[49] =
+{
+     0,    14,    34,    67,   107,   167,   245,   326,   449,   645,   861,
+  1155,  1508,  2003,  2669,  3544,  4592,  5961,  7583,  9887, 13256, 18765,
+ 26519, 34077, 40034, 44349, 47795, 50663, 53262, 55473, 57458, 59122, 60592,
+ 61742, 62690, 63391, 63997, 64463, 64794, 65045, 65207, 65309, 65394, 65443,
+ 65478, 65504, 65514, 65523, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const uint16_t* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+    WebRtcIsac_kLpcShapeCdfVec0Ub12, WebRtcIsac_kLpcShapeCdfVec1Ub12,
+    WebRtcIsac_kLpcShapeCdfVec2Ub12, WebRtcIsac_kLpcShapeCdfVec3Ub12,
+    WebRtcIsac_kLpcShapeCdfVec4Ub12, WebRtcIsac_kLpcShapeCdfVec5Ub12,
+    WebRtcIsac_kLpcShapeCdfVec6Ub12, WebRtcIsac_kLpcShapeCdfVec7Ub12
+};
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
new file mode 100644
index 0000000..7448a1e
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb12_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kMeanLpcGain;
+
+extern const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER]
+                                                     [UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb12[UB_LPC_VEC_PER_FRAME]
+                                                     [UB_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb12;
+
+extern const double
+    WebRtcIsac_kLpcShapeLeftRecPointUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const int16_t
+    WebRtcIsac_kLpcShapeNumRecPointUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const uint16_t
+    WebRtcIsac_kLpcShapeEntropySearchUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec0Ub12[14];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub12[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub12[20];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub12[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub12[20];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub12[25];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub12[33];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub12[49];
+
+extern const uint16_t*
+    WebRtcIsac_kLpcShapeCdfMatUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
new file mode 100644
index 0000000..59617fd
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
@@ -0,0 +1,247 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB16_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER] =
+{
+0.454978, 0.364747, 0.102999, 0.104523
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+    {-0.020528, -0.085858, -0.002431,  0.996093},
+    {-0.033155,  0.036102,  0.998786,  0.004866},
+    { 0.202627,  0.974853, -0.028940,  0.088132},
+    {-0.978479,  0.202454, -0.039785, -0.002811}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME] =
+{
+    { 0.291675, -0.515786,  0.644927,  0.482658},
+    {-0.647220,  0.479712,  0.289556,  0.516856},
+    { 0.643084,  0.485489, -0.289307,  0.516763},
+    {-0.287185, -0.517823, -0.645389,  0.482553}
+};
+
+/*
+* The following 16 vectors define CDF of 16 decorrelated LAR
+* coefficients.
+*/
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub16[14] =
+{
+     0,      2,     20,    159,   1034,   5688,  20892,  44653,
+ 59849,  64485,  65383,  65518,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub16[16] =
+{
+     0,      1,      7,     43,    276,   1496,   6681,  21653,
+ 43891,  58859,  64022,  65248,  65489,  65529,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub16[18] =
+{
+     0,      1,      9,     54,    238,    933,   3192,   9461,
+ 23226,  42146,  56138,  62413,  64623,  65300,  65473,  65521,
+ 65533,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub16[30] =
+{
+     0,      2,      4,      8,     17,     36,     75,    155,
+   329,    683,   1376,   2662,   5047,   9508,  17526,  29027,
+ 40363,  48997,  55096,  59180,  61789,  63407,  64400,  64967,
+ 65273,  65429,  65497,  65526,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub16[16] =
+{
+     0,      1,     10,     63,    361,   1785,   7407,  22242,
+ 43337,  58125,  63729,  65181,  65472,  65527,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub16[17] =
+{
+     0,      1,      7,     29,    134,    599,   2443,   8590,
+ 22962,  42635,  56911,  63060,  64940,  65408,  65513,  65531,
+ 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub16[21] =
+{
+     0,      1,      5,     16,     57,    191,    611,   1808,
+  4847,  11755,  24612,  40910,  53789,  60698,  63729,  64924,
+ 65346,  65486,  65523,  65532,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub16[36] =
+{
+     0,      1,      4,     12,     25,     55,    104,    184,
+   314,    539,    926,   1550,   2479,   3861,   5892,   8845,
+ 13281,  20018,  29019,  38029,  45581,  51557,  56057,  59284,
+ 61517,  63047,  64030,  64648,  65031,  65261,  65402,  65480,
+ 65518,  65530,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec8Ub16[21] =
+{
+     0,      1,      2,      7,     26,    103,    351,   1149,
+  3583,  10204,  23846,  41711,  55361,  61917,  64382,  65186,
+ 65433,  65506,  65528,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub160[21] =
+{
+     0,      6,     19,     63,    205,    638,   1799,   4784,
+ 11721,  24494,  40803,  53805,  60886,  63822,  64931,  65333,
+ 65472,  65517,  65530,  65533,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub161[28] =
+{
+     0,      1,      3,     11,     31,     86,    221,    506,
+  1101,   2296,   4486,   8477,  15356,  26079,  38941,  49952,
+ 57165,  61257,  63426,  64549,  65097,  65351,  65463,  65510,
+ 65526,  65532,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub162[55] =
+{
+     0,      3,     12,     23,     42,     65,     89,    115,
+   150,    195,    248,    327,    430,    580,    784,   1099,
+  1586,   2358,   3651,   5899,   9568,  14312,  19158,  23776,
+ 28267,  32663,  36991,  41153,  45098,  48680,  51870,  54729,
+ 57141,  59158,  60772,  62029,  63000,  63761,  64322,  64728,
+ 65000,  65192,  65321,  65411,  65463,  65496,  65514,  65523,
+ 65527,  65529,  65531,  65532,  65533,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub163[26] =
+{
+     0,      2,      4,     10,     21,     48,    114,    280,
+   701,   1765,   4555,  11270,  24267,  41213,  54285,  61003,
+ 63767,  64840,  65254,  65421,  65489,  65514,  65526,  65532,
+ 65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub164[28] =
+{
+     0,      1,      3,      6,     15,     36,     82,    196,
+   453,   1087,   2557,   5923,  13016,  25366,  40449,  52582,
+ 59539,  62896,  64389,  65033,  65316,  65442,  65494,  65519,
+ 65529,  65533,  65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub165[34] =
+{
+     0,      2,      4,      8,     18,     35,     73,    146,
+   279,    524,    980,   1789,   3235,   5784,  10040,  16998,
+ 27070,  38543,  48499,  55421,  59712,  62257,  63748,  64591,
+ 65041,  65278,  65410,  65474,  65508,  65522,  65530,  65533,
+ 65534,  65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub166[71] =
+{
+     0,      1,      2,      6,     13,     26,     55,     92,
+   141,    191,    242,    296,    355,    429,    522,    636,
+   777,    947,   1162,   1428,   1753,   2137,   2605,   3140,
+  3743,   4409,   5164,   6016,   6982,   8118,   9451,  10993,
+ 12754,  14810,  17130,  19780,  22864,  26424,  30547,  35222,
+ 40140,  44716,  48698,  52056,  54850,  57162,  59068,  60643,
+ 61877,  62827,  63561,  64113,  64519,  64807,  65019,  65167,
+ 65272,  65343,  65399,  65440,  65471,  65487,  65500,  65509,
+ 65518,  65524,  65527,  65531,  65533,  65534,  65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const uint16_t* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] = {
+     WebRtcIsac_kLpcShapeCdfVec01Ub16,
+     WebRtcIsac_kLpcShapeCdfVec1Ub16,
+     WebRtcIsac_kLpcShapeCdfVec2Ub16,
+     WebRtcIsac_kLpcShapeCdfVec3Ub16,
+     WebRtcIsac_kLpcShapeCdfVec4Ub16,
+     WebRtcIsac_kLpcShapeCdfVec5Ub16,
+     WebRtcIsac_kLpcShapeCdfVec6Ub16,
+     WebRtcIsac_kLpcShapeCdfVec7Ub16,
+     WebRtcIsac_kLpcShapeCdfVec8Ub16,
+     WebRtcIsac_kLpcShapeCdfVec01Ub160,
+     WebRtcIsac_kLpcShapeCdfVec01Ub161,
+     WebRtcIsac_kLpcShapeCdfVec01Ub162,
+     WebRtcIsac_kLpcShapeCdfVec01Ub163,
+     WebRtcIsac_kLpcShapeCdfVec01Ub164,
+     WebRtcIsac_kLpcShapeCdfVec01Ub165,
+     WebRtcIsac_kLpcShapeCdfVec01Ub166
+};
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ -0.8250,  -0.9750,  -1.1250,  -2.1750,  -0.9750,  -1.1250,  -1.4250,
+ -2.6250,  -1.4250,  -1.2750,  -1.8750,  -3.6750,  -1.7250,  -1.8750,
+ -2.3250,  -5.4750
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const int16_t WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+   13,    15,    17,    29,    15,    16,    20,    35,    20,
+   20,    27,    54,    25,    27,    33,    70
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+    6,     7,     8,    14,     7,     8,    10,    17,    10,
+   10,    13,    27,    12,    13,    16,    35
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb16 = 0.150000;
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
new file mode 100644
index 0000000..51101db
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb16_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER]
+                                                      [UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb16[UB16_LPC_VEC_PER_FRAME]
+                                                     [UB16_LPC_VEC_PER_FRAME];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub16[14];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub16[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub16[18];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub16[30];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub16[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub16[17];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub16[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub16[36];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec8Ub16[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub160[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub161[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub162[55];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub163[26];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub164[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub165[34];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub166[71];
+
+extern const uint16_t*
+    WebRtcIsac_kLpcShapeCdfMatUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double
+    WebRtcIsac_kLpcShapeLeftRecPointUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const int16_t
+    WebRtcIsac_kLpcShapeNumRecPointUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const uint16_t
+    WebRtcIsac_kLpcShapeEntropySearchUb16[UB_LPC_ORDER *
+                                          UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb16;
+
+#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
new file mode 100644
index 0000000..461b92e
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
@@ -0,0 +1,601 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* coding tables for the KLT coefficients */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* cdf array for model indicator */
+const uint16_t WebRtcIsac_kQKltModelCdf[4] = {
+    0,  15434,  37548,  65535 };
+
+/* pointer to cdf array for model indicator */
+const uint16_t *WebRtcIsac_kQKltModelCdfPtr[1] = {
+    WebRtcIsac_kQKltModelCdf };
+
+/* initial cdf index for decoder of model indicator */
+const uint16_t WebRtcIsac_kQKltModelInitIndex[1] = { 1 };
+
+/* offset to go from rounded value to quantization index */
+const short WebRtcIsac_kQKltQuantMinGain[12] = {
+    3,  6,  4,  6,  6,  9,  5,  16,  11,  34, 32,  47 };
+
+
+const short WebRtcIsac_kQKltQuantMinShape[108] = {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+    1,  1,  1,  1,  2,  2,  2,  3,  0,  0,
+    0,  0,  1,  0,  0,  0,  0,  1,  1,  1,
+    1,  1,  1,  2,  2,  3,  0,  0,  0,  0,
+    1,  0,  1,  1,  1,  1,  1,  1,  1,  2,
+    2,  4,  3,  5,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  2,  1,  2,  2,  3,  4,
+    4,  7,  0,  0,  1,  1,  1,  1,  1,  1,
+    1,  2,  3,  2,  3,  4,  4,  5,  7,  13,
+    0,  1,  1,  2,  3,  2,  2,  2,  4,  4,
+    5,  6,  7,  11,  9,  13,  12,  26 };
+
+/* maximum quantization index */
+const uint16_t WebRtcIsac_kQKltMaxIndGain[12] = {
+    6,  12,  8,  14,  10,  19,  12,  31,  22,  56, 52,  138 };
+
+const uint16_t WebRtcIsac_kQKltMaxIndShape[108] = {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+    2,  2,  2,  2,  4,  4,  5,  6,  0,  0,
+    0,  0,  1,  0,  0,  0,  0,  1,  2,  2,
+    2,  2,  3,  4,  5,  7,  0,  0,  0,  0,
+    2,  0,  2,  2,  2,  2,  3,  2,  2,  4,
+    4,  6,  6,  9,  0,  0,  0,  0,  2,  2,
+    2,  2,  2,  2,  3,  2,  4,  4,  7,  7,
+    9,  13,  0,  0,  2,  2,  2,  2,  2,  2,
+    3,  4,  5,  4,  6,  8,  8,  10,  16,  25,
+    0,  2,  2,  4,  5,  4,  4,  4,  7,  8,
+    9,  10,  13,  19,  17,  23,  25,  49 };
+
+/* index offset */
+const uint16_t WebRtcIsac_kQKltOffsetGain[12] = {
+    0,  7,  20,  29,  44,  55,  75,  88,  120,  143,  200,  253 };
+
+const uint16_t WebRtcIsac_kQKltOffsetShape[108] = {
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+    11,  14,  17,  20,  23,  28,  33,  39,  46,  47,
+    48,  49,  50,  52,  53,  54,  55,  56,  58,  61,
+    64,  67,  70,  74,  79,  85,  93,  94,  95,  96,
+    97,  100,  101,  104,  107,  110,  113,  117,  120,  123,
+    128,  133,  140,  147,  157,  158,  159,  160,  161,  164,
+    167,  170,  173,  176,  179,  183,  186,  191,  196,  204,
+    212,  222,  236,  237,  238,  241,  244,  247,  250,  253,
+    256,  260,  265,  271,  276,  283,  292,  301,  312,  329,
+    355,  356,  359,  362,  367,  373,  378,  383,  388,  396,
+    405,  415,  426,  440,  460,  478,  502,  528 };
+
+/* initial cdf index for KLT coefficients */
+const uint16_t WebRtcIsac_kQKltInitIndexGain[12] = {
+    3,  6,  4,  7,  5,  10,  6,  16,  11,  28, 26,  69};
+
+const uint16_t WebRtcIsac_kQKltInitIndexShape[108] = {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,
+    1,  1,  1,  1,  2,  2,  3,  3,  0,  0,
+    0,  0,  1,  0,  0,  0,  0,  1,  1,  1,
+    1,  1,  2,  2,  3,  4,  0,  0,  0,  0,
+    1,  0,  1,  1,  1,  1,  2,  1,  1,  2,
+    2,  3,  3,  5,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  2,  1,  2,  2,  4,  4,
+    5,  7,  0,  0,  1,  1,  1,  1,  1,  1,
+    2,  2,  3,  2,  3,  4,  4,  5,  8,  13,
+    0,  1,  1,  2,  3,  2,  2,  2,  4,  4,
+    5,  5,  7,  10,  9,  12,  13,  25 };
+
+
+/* quantizer representation levels */
+const double WebRtcIsac_kQKltLevelsGain[392] = {
+    -2.78127126, -1.76745590, -0.77913790, -0.00437329,  0.79961206,
+    1.81775776, 2.81389782, -5.78753143, -4.88384084, -3.89320940,
+    -2.88133610, -1.92859977, -0.86347396,  0.02003888,  0.86140400,
+    1.89667156,  2.97134967,  3.98781964,  4.91727277,  5.82865898,
+    -4.11195874, -2.80898424, -1.87547977, -0.80943825, -0.00679084,
+    0.79573851,  1.83953397,  2.67586037,  3.76274082, -6.10933968,
+    -4.93034581, -3.89281296, -2.91530625, -1.89684163, -0.85319130,
+    -0.02275767,  0.86862017,  1.91578276,  2.96107339,  3.96543056,
+    4.91369908,  5.91058154,  6.83848343,  8.07136925, -5.87470395,
+    -4.84703049, -3.84284597, -2.86168446, -1.89290192, -0.82798145,
+    -0.00080013,  0.82594974,  1.85754329,  2.88351798,  3.96172628,
+    -8.85684885, -7.87387461, -6.97811862, -5.93256270, -4.94301439,
+    -3.95513701, -2.96041544, -1.94031192, -0.87961478, -0.00456201,
+    0.89911505,  1.91723376,  2.94011511,  3.93302540,  4.97990967,
+    5.93133404,  7.02181199,  7.92407762,  8.80155440,  10.04665814,
+    -4.82396678, -3.85612158, -2.89482244, -1.89558408, -0.90036978,
+    -0.00677823,  0.90607989,  1.90937981,  2.91175777,  3.91637730,
+    4.97565723,  5.84771228,  7.11145863, -16.07879840, -15.03776309,
+    -13.93905670, -12.95671800, -11.89171202, -10.95820934, -9.95923714,
+    -8.94357334, -7.99068299, -6.97481009, -5.94826231, -4.96673988,
+    -3.97490466, -2.97846970, -1.95130435, -0.94215262, -0.01444043,
+    0.96770704,  1.95848598,  2.94107862,  3.95666119,  4.97253085,
+    5.97191122,  6.93277360,  7.96608727,  8.87958779,  10.00264269,
+    10.86560820,  12.07449071,  13.04491775,  13.97507061,  14.91845261,
+    -10.85696295, -9.83365357, -9.01245635, -7.95915145, -6.95625003,
+    -5.95362618, -4.93468444, -3.98760978, -2.95044407, -1.97041277,
+    -0.97701799, -0.00840234,  0.97834289,  1.98361415,  2.97802439,
+    3.96415871,  4.95369042,  5.94101770,  6.92756798,  7.94063998,
+    8.85951828,  9.97077022,  11.00068503, -33.92030406, -32.81426422,
+    -32.00000000, -31.13243639, -30.11886909, -29.06017570, -28.12598824,
+    -27.22045482, -25.81215858, -25.07849962, -23.93018013, -23.02097643,
+    -21.89529725, -20.99091085, -19.98889048, -18.94327044, -17.96562071,
+    -16.96126218, -15.95054062, -14.98516200, -13.97101012, -13.02106500,
+    -11.98438006, -11.03216748, -9.95930286, -8.97043946, -7.98085082,
+    -6.98360995, -5.98998802, -4.98668173, -4.00032906, -3.00420619,
+    -1.98701132, -0.99324682, -0.00609324,  0.98297834,  1.99483076,
+    3.00305044,  3.97142097,  4.97525759,  5.98612258,  6.97448236,
+    7.97575900,  9.01086211,  9.98665542,  11.00541438,  11.98078628,
+    12.92352471,  14.06849675,  14.99949430,  15.94904834,  16.97440321,
+    18.04040916,  18.88987609,  20.05312391,  21.00000000,  21.79443341,
+    -31.98578825, -31.00000000, -29.89060567, -28.98555686, -27.97114102,
+    -26.84935410, -26.02402230, -24.94195278, -23.92336849, -22.95552382,
+    -21.97932836, -20.96055470, -19.99649553, -19.03436122, -17.96706525,
+    -17.01139515, -16.01363516, -14.99154248, -14.00298333, -12.99630613,
+    -11.99955519, -10.99000421, -10.00819092, -8.99763648, -7.98431793,
+    -7.01769025, -5.99604690, -4.99980697, -3.99334671, -3.01748192,
+    -2.02051217, -1.00848371, -0.01942358,  1.00477757,  1.95477872,
+    2.98593031,  3.98779079,  4.96862849,  6.02694771,  6.93983733,
+    7.89874717,  8.99615862,  10.02367921,  10.96293452,  11.84351528,
+    12.92207187,  13.85122329,  15.05146877,  15.99371264,  17.00000000,
+    18.00000000,  19.00000000,  19.82763573, -47.00000000, -46.00000000,
+    -44.87138498, -44.00000000, -43.00000000, -42.00000000, -41.00000000,
+    -39.88966612, -38.98913239, -37.80306486, -37.23584325, -35.94200288,
+    -34.99881301, -34.11361858, -33.06507360, -32.13129135, -30.90891364,
+    -29.81511907, -28.99250380, -28.04535391, -26.99767800, -26.04418164,
+    -24.95687851, -24.04865595, -23.03392645, -21.89366707, -20.93517364,
+    -19.99388660, -18.91620943, -18.03749683, -16.99532379, -15.98683813,
+    -15.06421479, -13.99359211, -12.99714098, -11.97022520, -10.98500279,
+    -9.98834422, -8.95729330, -8.01232284, -7.00253661, -5.99681626,
+    -5.01207817, -3.95914904, -3.01232178, -1.96615919, -0.97687670,
+    0.01228030,  0.98412288,  2.01753544,  3.00580570,  3.97783510,
+    4.98846894,  6.01321400,  7.00867732,  8.00416375,  9.01771966,
+    9.98637729,  10.98255180,  11.99194163,  13.01807333,  14.00999545,
+    15.00118556,  16.00089224,  17.00584148,  17.98251763,  18.99942091,
+    19.96917690,  20.97839265,  21.98207297,  23.00171271,  23.99930737,
+    24.99746061,  26.00936304,  26.98240132,  28.01126868,  29.01395915,
+    29.98153507,  31.01376711,  31.99876818,  33.00475317,  33.99753994,
+    34.99493913,  35.98933585,  36.95620160,  37.98428461,  38.99317544,
+    40.01832073,  40.98048133,  41.95999283,  42.98232091,  43.96523612,
+    44.99574268,  45.99524194,  47.05464025,  48.03821548,  48.99354366,
+    49.96400411,  50.98017973,  51.95184408,  52.96291806,  54.00194392,
+    54.96603783,  55.95623778,  57.03076595,  58.05889901,  58.99081551,
+    59.97928121,  61.05071612,  62.03971580,  63.01286038,  64.01290338,
+    65.02074503,  65.99454594,  67.00399425,  67.96571257,  68.95305727,
+    69.92030664,  70.95594862,  71.98088567,  73.04764124,  74.00285480,
+    75.02696330,  75.89837673,  76.93459997,  78.16266309,  78.83317543,
+    80.00000000,  80.87251574,  82.09803524,  83.10671664,  84.00000000,
+    84.77023523,  86.00000000,  87.00000000,  87.92946897,  88.69159118,
+    90.00000000,  90.90535270 };
+
+const double WebRtcIsac_kQKltLevelsShape[578] = {
+    0.00032397,  0.00008053, -0.00061202, -0.00012620,  0.00030437,
+    0.00054764, -0.00027902,  0.00069360,  0.00029449, -0.80219239,
+    0.00091089, -0.74514927, -0.00094283,  0.64030631, -0.60509119,
+    0.00035575,  0.61851665, -0.62129957,  0.00375219,  0.60054900,
+    -0.61554359,  0.00054977,  0.63362016, -1.73118727, -0.65422341,
+    0.00524568,  0.66165298,  1.76785515, -1.83182018, -0.65997434,
+    -0.00011887,  0.67524299,  1.79933938, -1.76344480, -0.72547708,
+    -0.00133017,  0.73104704,  1.75305377,  2.85164534, -2.80423916,
+    -1.71959639, -0.75419722, -0.00329945,  0.77196760,  1.72211069,
+    2.87339653,  0.00031089, -0.00015311,  0.00018201, -0.00035035,
+    -0.77357251,  0.00154647, -0.00047625, -0.00045299,  0.00086590,
+    0.00044762, -0.83383829,  0.00024787, -0.68526258, -0.00122472,
+    0.64643255, -0.60904942, -0.00448987,  0.62309184, -0.59626442,
+    -0.00574132,  0.62296546, -0.63222115,  0.00013441,  0.63609545,
+    -0.66911055, -0.00369971,  0.66346095,  2.07281301, -1.77184694,
+    -0.67640425, -0.00010145,  0.64818392,  1.74948973, -1.69420224,
+    -0.71943894, -0.00004680,  0.75303493,  1.81075983,  2.80610041,
+    -2.80005755, -1.79866753, -0.77409777, -0.00084220,  0.80141293,
+    1.78291081,  2.73954236,  3.82994169,  0.00015140, -0.00012766,
+    -0.00034241, -0.00119125, -0.76113497,  0.00069246,  0.76722027,
+    0.00132862, -0.69107530,  0.00010656,  0.77061578, -0.78012970,
+    0.00095947,  0.77828502, -0.64787758,  0.00217168,  0.63050167,
+    -0.58601125,  0.00306596,  0.59466308, -0.58603410,  0.00059779,
+    0.64257970,  1.76512766, -0.61193600, -0.00259517,  0.59767574,
+    -0.61026273,  0.00315811,  0.61725479, -1.69169719, -0.65816029,
+    0.00067575,  0.65576890,  2.00000000, -1.72689193, -0.69780808,
+    -0.00040990,  0.70668487,  1.74198458, -3.79028154, -3.00000000,
+    -1.73194459, -0.70179341, -0.00106695,  0.71302629,  1.76849782,
+    -2.89332364, -1.78585007, -0.78731491, -0.00132610,  0.79692976,
+    1.75247009,  2.97828682, -5.26238694, -3.69559829, -2.87286122,
+    -1.84908818, -0.84434577, -0.01167975,  0.84641753,  1.84087672,
+    2.87628156,  3.83556679, -0.00190204,  0.00092642,  0.00354385,
+    -0.00012982, -0.67742785,  0.00229509,  0.64935672, -0.58444751,
+    0.00470733,  0.57299534, -0.58456202, -0.00097715,  0.64593607,
+    -0.64060330, -0.00638534,  0.59680157, -0.59287537,  0.00490772,
+    0.58919707, -0.60306173, -0.00417464,  0.60562100, -1.75218757,
+    -0.63018569, -0.00225922,  0.63863300, -0.63949939, -0.00126421,
+    0.64268914, -1.75851182, -0.68318060,  0.00510418,  0.69049211,
+    1.88178506, -1.71136148, -0.72710534, -0.00815559,  0.73412917,
+    1.79996711, -2.77111145, -1.73940498, -0.78212945,  0.01074476,
+    0.77688916,  1.76873972,  2.87281379,  3.77554698, -3.75832725,
+    -2.95463235, -1.80451491, -0.80017226,  0.00149902,  0.80729206,
+    1.78265046,  2.89391793, -3.78236148, -2.83640598, -1.82532067,
+    -0.88844327, -0.00620952,  0.88208030,  1.85757631,  2.81712391,
+    3.88430176,  5.16179367, -7.00000000, -5.93805408, -4.87172597,
+    -3.87524433, -2.89399744, -1.92359563, -0.92136341, -0.00172725,
+    0.93087018,  1.90528280,  2.89809686,  3.88085708,  4.89147740,
+    5.89078692, -0.00239502,  0.00312564, -1.00000000,  0.00178325,
+    1.00000000, -0.62198029,  0.00143254,  0.65344051, -0.59851220,
+    -0.00676987,  0.61510140, -0.58894151,  0.00385055,  0.59794203,
+    -0.59808568, -0.00038214,  0.57625703, -0.63009713, -0.01107985,
+    0.61278758, -0.64206758, -0.00154369,  0.65480598,  1.80604162,
+    -1.80909286, -0.67810514,  0.00205762,  0.68571097,  1.79453891,
+    -3.22682422, -1.73808453, -0.71870305, -0.00738594,  0.71486172,
+    1.73005326, -1.66891897, -0.73689615, -0.00616203,  0.74262409,
+    1.73807899, -2.92417482, -1.73866741, -0.78133871,  0.00764425,
+    0.80027264,  1.78668732,  2.74992588, -4.00000000, -2.75578740,
+    -1.83697516, -0.83117035, -0.00355191,  0.83527172,  1.82814700,
+    2.77377675,  3.80718693, -3.81667698, -2.83575471, -1.83372350,
+    -0.86579471,  0.00547578,  0.87582281,  1.82858793,  2.87265007,
+    3.91405377, -4.87521600, -3.78999094, -2.86437014, -1.86964365,
+    -0.90618018,  0.00128243,  0.91497811,  1.87374952,  2.83199819,
+    3.91519130,  4.76632822, -6.68713448, -6.01252467, -4.94587936,
+    -3.88795368, -2.91299088, -1.92592211, -0.95504570, -0.00089980,
+    0.94565200,  1.93239633,  2.91832808,  3.91363475,  4.88920034,
+    5.96471415,  6.83905252,  7.86195009,  8.81571018,-12.96141759,
+    -11.73039516,-10.96459719, -9.97382433, -9.04414433, -7.89460619,
+    -6.96628608, -5.93236595, -4.93337924, -3.95479990, -2.96451499,
+    -1.96635876, -0.97271229, -0.00402238,  0.98343930,  1.98348291,
+    2.96641164,  3.95456471,  4.95517089,  5.98975714,  6.90322073,
+    7.90468849,  8.85639467,  9.97255498, 10.79006309, 11.81988596,
+    0.04950500, -1.00000000, -0.01226628,  1.00000000, -0.59479469,
+    -0.10438305,  0.59822144, -2.00000000, -0.67109149, -0.09256692,
+    0.65171621,  2.00000000, -3.00000000, -1.68391999, -0.76681039,
+    -0.03354151,  0.71509146,  1.77615472, -2.00000000, -0.68661511,
+    -0.02497881,  0.66478398,  2.00000000, -2.00000000, -0.67032784,
+    -0.00920582,  0.64892756,  2.00000000, -2.00000000, -0.68561894,
+    0.03641869,  0.73021611,  1.68293863, -4.00000000, -2.72024184,
+    -1.80096059, -0.81696185,  0.03604685,  0.79232033,  1.70070730,
+    3.00000000, -4.00000000, -2.71795670, -1.80482986, -0.86001162,
+    0.03764903,  0.87723968,  1.79970771,  2.72685932,  3.67589143,
+    -5.00000000, -4.00000000, -2.85492548, -1.78996365, -0.83250358,
+    -0.01376828,  0.84195506,  1.78161105,  2.76754458,  4.00000000,
+    -6.00000000, -5.00000000, -3.82268811, -2.77563624, -1.82608163,
+    -0.86486114, -0.02671886,  0.86693165,  1.88422879,  2.86248347,
+    3.95632216, -7.00000000, -6.00000000, -5.00000000, -3.77533988,
+    -2.86391432, -1.87052039, -0.90513658,  0.06271236,  0.91083620,
+    1.85734756,  2.86031688,  3.82019418,  4.94420394,  6.00000000,
+    -11.00000000,-10.00000000, -9.00000000, -8.00000000, -6.91952415,
+    -6.00000000, -4.92044374, -3.87845165, -2.87392362, -1.88413020,
+    -0.91915740,  0.00318517,  0.91602800,  1.89664838,  2.88925058,
+    3.84123856,  4.78988651,  5.94526812,  6.81953917,  8.00000000,
+    -9.00000000, -8.00000000, -7.03319143, -5.94530963, -4.86669720,
+    -3.92438007, -2.88620396, -1.92848070, -0.94365985,  0.01671855,
+    0.97349410,  1.93419878,  2.89740109,  3.89662823,  4.83235583,
+    5.88106535,  6.80328232,  8.00000000,-13.00000000,-12.00000000,
+    -11.00000000,-10.00000000, -9.00000000, -7.86033489, -6.83344055,
+    -5.89844215, -4.90811454, -3.94841298, -2.95820490, -1.98627966,
+    -0.99161468, -0.02286136,  0.96055651,  1.95052433,  2.93969396,
+    3.94304346,  4.88522624,  5.87434241,  6.78309433,  7.87244101,
+    9.00000000, 10.00000000,-12.09117356,-11.00000000,-10.00000000,
+    -8.84766108, -7.86934236, -6.98544896, -5.94233429, -4.95583292,
+    -3.95575986, -2.97085529, -1.98955811, -0.99359873, -0.00485413,
+    0.98298870,  1.98093258,  2.96430203,  3.95540216,  4.96915010,
+    5.96775124,  6.99236918,  7.96503302,  8.99864542,  9.85857723,
+    10.96541926, 11.91647197, 12.71060069,-26.00000000,-25.00000000,
+    -24.00585596,-23.11642573,-22.14271284,-20.89800711,-19.87815799,
+    -19.05036354,-17.88555651,-16.86471209,-15.97711073,-14.94012359,
+    -14.02661226,-12.98243228,-11.97489256,-10.97402777, -9.96425624,
+    -9.01085220, -7.97372506, -6.98795002, -5.97271328, -5.00191694,
+    -3.98055849, -2.98458048, -1.99470442, -0.99656768, -0.00825666,
+    1.00272004,  1.99922218,  2.99357669,  4.01407905,  5.01003897,
+    5.98115528,  7.00018958,  8.00338125,  8.98981046,  9.98990318,
+    10.96341479, 11.96866930, 12.99175139, 13.94580443, 14.95745083,
+    15.98992869, 16.97484646, 17.99630043, 18.93396897, 19.88347741,
+    20.96532482, 21.92191032, 23.22314702 };
+
+
+/* cdf tables for quantizer indices */
+const uint16_t WebRtcIsac_kQKltCdfGain[404] = {
+    0,  13,  301,  3730,  61784,  65167,  65489,  65535,  0,  17,
+    142,  314,  929,  2466,  7678,  56450,  63463,  64740,  65204,  65426,
+    65527,  65535,  0,  8,  100,  724,  6301,  60105,  65125,  65510,
+    65531,  65535,  0,  13,  117,  368,  1068,  3010,  11928,  53603,
+    61177,  63404,  64505,  65108,  65422,  65502,  65531,  65535,  0,  4,
+    17,  96,  410,  1859,  12125,  54361,  64103,  65305,  65497,  65535,
+    0,  4,  88,  230,  469,  950,  1746,  3228,  6092,  16592,
+    44756,  56848,  61256,  63308,  64325,  64920,  65309,  65460,  65502,
+    65522, 65535,  0,  88,  352,  1675,  6339,  20749,  46686,  59284,  63525,
+    64949,  65359,  65502,  65527,  65535,  0,  13,  38,  63,  117,
+    234,  381,  641,  929,  1407,  2043,  2809,  4032,  5753,  8792,
+    14407,  24308,  38941,  48947,  55403,  59293,  61411,  62688,  63630,
+    64329, 64840,  65188,  65376,  65472,  65506,  65527,  65531,  65535,
+    0,  8, 29,  75,  222,  615,  1327,  2801,  5623,  9931,  16094,  24966,
+    34419, 43458,  50676,  56186,  60055,  62500,  63936,  64765,  65225,
+    65435, 65514,  65535,  0,  8,  13,  15,  17,  21,  33,  59,
+    71,  92,  151,  243,  360,  456,  674,  934,  1223,  1583,
+    1989,  2504,  3031,  3617,  4354,  5154,  6163,  7411,  8780,  10747,
+    12874,  15591,  18974,  23027,  27436,  32020,  36948,  41830,  46205,
+    49797,  53042,  56094,  58418,  60360,  61763,  62818,  63559,  64103,
+    64509,  64798,  65045,  65162,  65288,  65363,  65447,  65506,  65522,
+    65531,  65533,  65535,  0,  4,  6,  25,  38,  71,  138,  264,  519,  808,
+    1227,  1825,  2516,  3408,  4279,  5560,  7092,  9197,  11420,  14108,
+    16947,  20300,  23926,  27459,  31164,  34827,  38575,  42178,  45540,
+    48747,  51444,  54090,  56426,  58460,  60080,  61595,  62734,  63668,
+    64275,  64673,  64936,  65112,  65217,  65334,  65426,  65464,  65477,
+    65489,  65518,  65527,  65529,  65531,  65533,  65535,  0,  2,  4,  8,  10,
+    12,  14,  16,  21,  33,  50,  71,  84,  92,  105,  138, 180,  255,  318,
+    377,  435,  473,  511,  590,  682,  758,  913,  1097,  1256,  1449,  1671,
+    1884,  2169,  2445,  2772,  3157,  3563,  3944,  4375,  4848,  5334,  5820,
+    6448,  7101,  7716,  8378,  9102,  9956,  10752,  11648,  12707,  13670,
+    14758,  15910,  17187,  18472,  19627,  20649,  21951,  23169,  24283,
+    25552,  26862,  28227,  29391,  30764,  31882,  33213,  34432,  35600,
+    36910,  38116,  39464,  40729,  41872,  43144,  44371,  45514,  46762,
+    47813,  48968,  50069,  51032,  51974,  52908,  53737,  54603,  55445,
+    56282,  56990,  57572,  58191,  58840,  59410,  59887,  60264,  60607,
+    60946,  61269,  61516,  61771,  61960,  62198,  62408,  62558,  62776,
+    62985,  63207,  63408,  63546,  63739,  63906,  64070,  64237,  64371,
+    64551,  64677,  64836,  64999,  65095,  65213,  65284,  65338,  65380,
+    65426,  65447,  65472,  65485,  65487,  65489,  65502,  65510,  65512,
+    65514,  65516,  65518,  65522,  65531,  65533,  65535 };
+
+
+const uint16_t WebRtcIsac_kQKltCdfShape[686] = {
+    0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,
+    0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,  4,
+    65535,  0,  8,  65514,  65535,  0,  29,  65481,  65535,  0,
+    121,  65439,  65535,  0,  239,  65284,  65535,  0,  8,  779,
+    64999,  65527,  65535,  0,  8,  888,  64693,  65522,  65535,  0,
+    29,  2604,  62843,  65497,  65531,  65535,  0,  25,  176,  4576,
+    61164,  65275,  65527,  65535,  0,  65535,  0,  65535,  0,  65535,
+    0,  65535,  0,  4,  65535,  0,  65535,  0,  65535,  0,
+    65535,  0,  65535,  0,  4,  65535,  0,  33,  65502,  65535,
+    0,  54,  65481,  65535,  0,  251,  65309,  65535,  0,  611,
+    65074,  65535,  0,  1273,  64292,  65527,  65535,  0,  4,  1809,
+    63940,  65518,  65535,  0,  88,  4392,  60603,  65426,  65531,  65535,
+    0,  25,  419,  7046,  57756,  64961,  65514,  65531,  65535,  0,
+    65535,  0,  65535,  0,  65535,  0,  65535,  0,  4,  65531,
+    65535,  0,  65535,  0,  8,  65531,  65535,  0,  4,  65527,
+    65535,  0,  17,  65510,  65535,  0,  42,  65481,  65535,  0,
+    197,  65342,  65531,  65535,  0,  385,  65154,  65535,  0,  1005,
+    64522,  65535,  0,  8,  1985,  63469,  65533,  65535,  0,  38,
+    3119,  61884,  65514,  65535,  0,  4,  6,  67,  4961,  60804,
+    65472,  65535,  0,  17,  565,  9182,  56538,  65087,  65514,  65535,
+    0,  8,  63,  327,  2118,  14490,  52774,  63839,  65376,  65522,
+    65535,  0,  65535,  0,  65535,  0,  65535,  0,  65535,  0,
+    17,  65522,  65535,  0,  59,  65489,  65535,  0,  50,  65522,
+    65535,  0,  54,  65489,  65535,  0,  310,  65179,  65535,  0,
+    615,  64836,  65535,  0,  4,  1503,  63965,  65535,  0,  2780,
+    63383,  65535,  0,  21,  3919,  61051,  65527,  65535,  0,  84,
+    6674,  59929,  65435,  65535,  0,  4,  255,  7976,  55784,  65150,
+    65518,  65531,  65535,  0,  4,  8,  582,  10726,  53465,  64949,
+    65518,  65535,  0,  29,  339,  3006,  17555,  49517,  62956,  65200,
+    65497,  65531,  65535,  0,  2,  33,  138,  565,  2324,  7670,
+    22089,  45966,  58949,  63479,  64966,  65380,  65518,  65535,  0,  65535,
+    0,  65535,  0,  2,  65533,  65535,  0,  46,  65514,  65535,
+    0,  414,  65091,  65535,  0,  540,  64911,  65535,  0,  419,
+    65162,  65535,  0,  976,  64790,  65535,  0,  2977,  62495,  65531,
+    65535,  0,  4,  3852,  61034,  65527,  65535,  0,  4,  29,
+    6021,  60243,  65468,  65535,  0,  84,  6711,  58066,  65418,  65535,
+    0,  13,  281,  9550,  54917,  65125,  65506,  65535,  0,  2,
+    63,  984,  12108,  52644,  64342,  65435,  65527,  65535,  0,  29,
+    251,  2014,  14871,  47553,  62881,  65229,  65518,  65535,  0,  13,
+    142,  749,  4220,  18497,  45200,  60913,  64823,  65426,  65527,  65535,
+    0,  13,  71,  264,  1176,  3789,  10500,  24480,  43488,  56324,
+    62315,  64493,  65242,  65464,  65514,  65522,  65531,  65535,  0,  4,
+    13,  38,  109,  205,  448,  850,  1708,  3429,  6276,  11371,
+    19221,  29734,  40955,  49391,  55411,  59460,  62102,  63793,  64656,
+    65150, 65401,  65485,  65522,  65531,  65535,  0,  65535,  0,  2,  65533,
+    65535,  0,  1160,  65476,  65535,  0,  2,  6640,  64763,  65533,
+    65535,  0,  2,  38,  9923,  61009,  65527,  65535,  0,  2,
+    4949,  63092,  65533,  65535,  0,  2,  3090,  63398,  65533,  65535,
+    0,  2,  2520,  58744,  65510,  65535,  0,  2,  13,  544,
+    8784,  51403,  65148,  65533,  65535,  0,  2,  25,  1017,  10412,
+    43550,  63651,  65489,  65527,  65535,  0,  2,  4,  29,  783,
+    13377,  52462,  64524,  65495,  65533,  65535,  0,  2,  4,  6,
+    100,  1817,  18451,  52590,  63559,  65376,  65531,  65535,  0,  2,
+    4,  6,  46,  385,  2562,  11225,  37416,  60488,  65026,  65487,
+    65529,  65533,  65535,  0,  2,  4,  6,  8,  10,  12,
+    42,  222,  971,  5221,  19811,  45048,  60312,  64486,  65294,  65474,
+    65525,  65529,  65533,  65535,  0,  2,  4,  8,  71,  167,
+    666,  2533,  7875,  19622,  38082,  54359,  62108,  64633,  65290,  65495,
+    65529,  65533,  65535,  0,  2,  4,  6,  8,  10,  13,
+    109,  586,  1930,  4949,  11600,  22641,  36125,  48312,  56899,  61495,
+    63927,  64932,  65389,  65489,  65518,  65531,  65533,  65535,  0,  4,
+    6,  8,  67,  209,  712,  1838,  4195,  8432,  14432,  22834,
+    31723,  40523,  48139,  53929,  57865,  60657,  62403,  63584,  64363,
+    64907, 65167,  65372,  65472,  65514,  65535,  0,  2,  4,  13,  25,
+    42,  46,  50,  75,  113,  147,  281,  448,  657,  909,
+    1185,  1591,  1976,  2600,  3676,  5317,  7398,  9914,  12941,  16169,
+    19477,  22885,  26464,  29851,  33360,  37228,  41139,  44802,  48654,
+    52058, 55181,  57676,  59581,  61022,  62190,  63107,  63676,  64199,
+    64547,  64924, 65158,  65313,  65430,  65481,  65518,  65535 };
+
+
+/* pointers to cdf tables for quantizer indices */
+const uint16_t *WebRtcIsac_kQKltCdfPtrGain[12] = {
+    WebRtcIsac_kQKltCdfGain +0 +0, WebRtcIsac_kQKltCdfGain +0 +8,
+    WebRtcIsac_kQKltCdfGain +0 +22, WebRtcIsac_kQKltCdfGain +0 +32,
+    WebRtcIsac_kQKltCdfGain +0 +48, WebRtcIsac_kQKltCdfGain +0 +60,
+    WebRtcIsac_kQKltCdfGain +0 +81, WebRtcIsac_kQKltCdfGain +0 +95,
+    WebRtcIsac_kQKltCdfGain +0 +128, WebRtcIsac_kQKltCdfGain +0 +152,
+    WebRtcIsac_kQKltCdfGain +0 +210, WebRtcIsac_kQKltCdfGain +0 +264 };
+
+const uint16_t *WebRtcIsac_kQKltCdfPtrShape[108] = {
+    WebRtcIsac_kQKltCdfShape +0 +0, WebRtcIsac_kQKltCdfShape +0 +2,
+    WebRtcIsac_kQKltCdfShape +0 +4, WebRtcIsac_kQKltCdfShape +0 +6,
+    WebRtcIsac_kQKltCdfShape +0 +8, WebRtcIsac_kQKltCdfShape +0 +10,
+    WebRtcIsac_kQKltCdfShape +0 +12, WebRtcIsac_kQKltCdfShape +0 +14,
+    WebRtcIsac_kQKltCdfShape +0 +16, WebRtcIsac_kQKltCdfShape +0 +18,
+    WebRtcIsac_kQKltCdfShape +0 +21, WebRtcIsac_kQKltCdfShape +0 +25,
+    WebRtcIsac_kQKltCdfShape +0 +29, WebRtcIsac_kQKltCdfShape +0 +33,
+    WebRtcIsac_kQKltCdfShape +0 +37, WebRtcIsac_kQKltCdfShape +0 +43,
+    WebRtcIsac_kQKltCdfShape +0 +49, WebRtcIsac_kQKltCdfShape +0 +56,
+    WebRtcIsac_kQKltCdfShape +0 +64, WebRtcIsac_kQKltCdfShape +0 +66,
+    WebRtcIsac_kQKltCdfShape +0 +68, WebRtcIsac_kQKltCdfShape +0 +70,
+    WebRtcIsac_kQKltCdfShape +0 +72, WebRtcIsac_kQKltCdfShape +0 +75,
+    WebRtcIsac_kQKltCdfShape +0 +77, WebRtcIsac_kQKltCdfShape +0 +79,
+    WebRtcIsac_kQKltCdfShape +0 +81, WebRtcIsac_kQKltCdfShape +0 +83,
+    WebRtcIsac_kQKltCdfShape +0 +86, WebRtcIsac_kQKltCdfShape +0 +90,
+    WebRtcIsac_kQKltCdfShape +0 +94, WebRtcIsac_kQKltCdfShape +0 +98,
+    WebRtcIsac_kQKltCdfShape +0 +102, WebRtcIsac_kQKltCdfShape +0 +107,
+    WebRtcIsac_kQKltCdfShape +0 +113, WebRtcIsac_kQKltCdfShape +0 +120,
+    WebRtcIsac_kQKltCdfShape +0 +129, WebRtcIsac_kQKltCdfShape +0 +131,
+    WebRtcIsac_kQKltCdfShape +0 +133, WebRtcIsac_kQKltCdfShape +0 +135,
+    WebRtcIsac_kQKltCdfShape +0 +137, WebRtcIsac_kQKltCdfShape +0 +141,
+    WebRtcIsac_kQKltCdfShape +0 +143, WebRtcIsac_kQKltCdfShape +0 +147,
+    WebRtcIsac_kQKltCdfShape +0 +151, WebRtcIsac_kQKltCdfShape +0 +155,
+    WebRtcIsac_kQKltCdfShape +0 +159, WebRtcIsac_kQKltCdfShape +0 +164,
+    WebRtcIsac_kQKltCdfShape +0 +168, WebRtcIsac_kQKltCdfShape +0 +172,
+    WebRtcIsac_kQKltCdfShape +0 +178, WebRtcIsac_kQKltCdfShape +0 +184,
+    WebRtcIsac_kQKltCdfShape +0 +192, WebRtcIsac_kQKltCdfShape +0 +200,
+    WebRtcIsac_kQKltCdfShape +0 +211, WebRtcIsac_kQKltCdfShape +0 +213,
+    WebRtcIsac_kQKltCdfShape +0 +215, WebRtcIsac_kQKltCdfShape +0 +217,
+    WebRtcIsac_kQKltCdfShape +0 +219, WebRtcIsac_kQKltCdfShape +0 +223,
+    WebRtcIsac_kQKltCdfShape +0 +227, WebRtcIsac_kQKltCdfShape +0 +231,
+    WebRtcIsac_kQKltCdfShape +0 +235, WebRtcIsac_kQKltCdfShape +0 +239,
+    WebRtcIsac_kQKltCdfShape +0 +243, WebRtcIsac_kQKltCdfShape +0 +248,
+    WebRtcIsac_kQKltCdfShape +0 +252, WebRtcIsac_kQKltCdfShape +0 +258,
+    WebRtcIsac_kQKltCdfShape +0 +264, WebRtcIsac_kQKltCdfShape +0 +273,
+    WebRtcIsac_kQKltCdfShape +0 +282, WebRtcIsac_kQKltCdfShape +0 +293,
+    WebRtcIsac_kQKltCdfShape +0 +308, WebRtcIsac_kQKltCdfShape +0 +310,
+    WebRtcIsac_kQKltCdfShape +0 +312, WebRtcIsac_kQKltCdfShape +0 +316,
+    WebRtcIsac_kQKltCdfShape +0 +320, WebRtcIsac_kQKltCdfShape +0 +324,
+    WebRtcIsac_kQKltCdfShape +0 +328, WebRtcIsac_kQKltCdfShape +0 +332,
+    WebRtcIsac_kQKltCdfShape +0 +336, WebRtcIsac_kQKltCdfShape +0 +341,
+    WebRtcIsac_kQKltCdfShape +0 +347, WebRtcIsac_kQKltCdfShape +0 +354,
+    WebRtcIsac_kQKltCdfShape +0 +360, WebRtcIsac_kQKltCdfShape +0 +368,
+    WebRtcIsac_kQKltCdfShape +0 +378, WebRtcIsac_kQKltCdfShape +0 +388,
+    WebRtcIsac_kQKltCdfShape +0 +400, WebRtcIsac_kQKltCdfShape +0 +418,
+    WebRtcIsac_kQKltCdfShape +0 +445, WebRtcIsac_kQKltCdfShape +0 +447,
+    WebRtcIsac_kQKltCdfShape +0 +451, WebRtcIsac_kQKltCdfShape +0 +455,
+    WebRtcIsac_kQKltCdfShape +0 +461, WebRtcIsac_kQKltCdfShape +0 +468,
+    WebRtcIsac_kQKltCdfShape +0 +474, WebRtcIsac_kQKltCdfShape +0 +480,
+    WebRtcIsac_kQKltCdfShape +0 +486, WebRtcIsac_kQKltCdfShape +0 +495,
+    WebRtcIsac_kQKltCdfShape +0 +505, WebRtcIsac_kQKltCdfShape +0 +516,
+    WebRtcIsac_kQKltCdfShape +0 +528, WebRtcIsac_kQKltCdfShape +0 +543,
+    WebRtcIsac_kQKltCdfShape +0 +564, WebRtcIsac_kQKltCdfShape +0 +583,
+    WebRtcIsac_kQKltCdfShape +0 +608, WebRtcIsac_kQKltCdfShape +0 +635 };
+
+
+/* left KLT transforms */
+const double WebRtcIsac_kKltT1Gain[4] = {
+    -0.79742827,  0.60341375,  0.60341375,  0.79742827 };
+
+const double WebRtcIsac_kKltT1Shape[324] = {
+    0.00159597,  0.00049320,  0.00513821,  0.00021066,  0.01338581,
+    -0.00422367, -0.00272072,  0.00935107,  0.02047622,  0.02691189,
+    0.00478236,  0.03969702,  0.00886698,  0.04877604, -0.10898362,
+    -0.05930891, -0.03415047,  0.98889721,  0.00293558, -0.00035282,
+    0.01156321, -0.00195341, -0.00937631,  0.01052213, -0.02551163,
+    0.01644059,  0.03189927,  0.07754773, -0.08742313, -0.03026338,
+    0.05136248, -0.14395974,  0.17725040,  0.22664856,  0.93380230,
+    0.07076411,  0.00557890, -0.00222834,  0.01377569,  0.01466808,
+    0.02847361, -0.00603178,  0.02382480, -0.01210452,  0.03797267,
+    -0.02371480,  0.11260335, -0.07366682,  0.00453436, -0.04136941,
+    -0.07912843, -0.95031418,  0.25295337, -0.05302216, -0.00617554,
+    -0.00044040, -0.00653778,  0.01097838,  0.01529174,  0.01374431,
+    -0.00748512, -0.00020034,  0.02432713,  0.11101570, -0.08556891,
+    0.09282249, -0.01029446,  0.67556443, -0.67454300,  0.06910063,
+    0.20866865, -0.10318050,  0.00932175,  0.00524058,  0.00803610,
+    -0.00594676, -0.01082578,  0.01069906,  0.00546768,  0.01565291,
+    0.06816200,  0.10201227,  0.16812734,  0.22984074,  0.58213170,
+    -0.54138651, -0.51379962,  0.06847390, -0.01920037, -0.04592324,
+    -0.00467394,  0.00328858,  0.00377424, -0.00987448,  0.08222096,
+    -0.00377301,  0.04551941, -0.02592517,  0.16317082,  0.13077530,
+    0.22702921, -0.31215289, -0.69645962, -0.38047101, -0.39339411,
+    0.11124777,  0.02508035, -0.00708074,  0.00400344,  0.00040331,
+    0.01142402,  0.01725406,  0.01635170,  0.14285366,  0.03949233,
+    -0.05905676,  0.05877154, -0.17497577, -0.32479440,  0.80754464,
+    -0.38085603, -0.17055430, -0.03168622, -0.07531451,  0.02942002,
+    -0.02148095, -0.00754114, -0.00322372,  0.00567812, -0.01701521,
+    -0.12358320,  0.11473564,  0.09070136,  0.06533068, -0.22560802,
+    0.19209022,  0.81605094,  0.36592275, -0.09919829,  0.16667122,
+    0.16300725,  0.04803807,  0.06739263, -0.00156752, -0.01685302,
+    -0.00905240, -0.02297836, -0.00469939,  0.06310613, -0.16391930,
+    0.10919511,  0.12529293,  0.85581322, -0.32145522,  0.24539076,
+    0.07181839,  0.07289591,  0.14066759,  0.10406711,  0.05815518,
+    0.01072680, -0.00759339,  0.00053486, -0.00044865,  0.03407361,
+    0.01645348,  0.08758579,  0.27722240,  0.53665485, -0.74853376,
+    -0.01118192, -0.19805430,  0.06130619, -0.09675299,  0.08978480,
+    0.03405255, -0.00706867,  0.05102045,  0.03250746,  0.01849966,
+    -0.01216314, -0.01184187, -0.01579288,  0.00114807,  0.11376166,
+    0.88342114, -0.36425379,  0.13863190,  0.12524180, -0.13553892,
+    0.04715856, -0.12341103,  0.04531568,  0.01899360, -0.00206897,
+    0.00567768, -0.01444163,  0.00411946, -0.00855896,  0.00381663,
+    -0.01664861, -0.05534280,  0.21328278,  0.20161162,  0.72360394,
+    0.59130708, -0.08043791,  0.08757349, -0.13893918, -0.05147377,
+    0.02680690, -0.01144070,  0.00625162, -0.00634215, -0.01248947,
+    -0.00329455, -0.00609625, -0.00136305, -0.05097048, -0.01029851,
+    0.25065384, -0.16856837, -0.07123372,  0.15992623, -0.39487617,
+    -0.79972301,  0.18118185, -0.04826639, -0.01805578, -0.02927253,
+    -0.16400618,  0.07472763,  0.10376449,  0.01705406,  0.01065801,
+    -0.01500498,  0.02039914,  0.37776349, -0.84484186,  0.10434286,
+    0.15616990,  0.13474456, -0.00906238, -0.25238368, -0.03820885,
+    -0.10650905, -0.03880833, -0.03660028, -0.09640894,  0.00583314,
+    0.01922097,  0.01489911, -0.02431117, -0.09372217,  0.39404721,
+    -0.84786223, -0.31277121,  0.03193850,  0.01974060,  0.01887901,
+    0.00337911, -0.11359599, -0.02792521, -0.03220184, -0.01533311,
+    0.00015962, -0.04225043, -0.00933965,  0.00675311,  0.00206060,
+    0.15926771,  0.40199829, -0.80792558, -0.35591604, -0.17169764,
+    0.02830436,  0.02459982, -0.03438589,  0.00718705, -0.01798329,
+    -0.01594508, -0.00702430, -0.00952419, -0.00962701, -0.01307212,
+    -0.01749740,  0.01299602,  0.00587270, -0.36103108, -0.82039266,
+    -0.43092844, -0.08500097, -0.04361674, -0.00333482,  0.01250434,
+    -0.02538295, -0.00921797,  0.01645071, -0.01400872,  0.00317607,
+    0.00003277, -0.01617646, -0.00616863, -0.00882661,  0.00466157,
+    0.00353237,  0.91803104, -0.39503305, -0.02048964,  0.00060125,
+    0.01980634,  0.00300109,  0.00313880,  0.00657337,  0.00715163,
+    0.00000261,  0.00854276, -0.00154825, -0.00516128,  0.00909527,
+    0.00095609,  0.00701196, -0.00221867, -0.00156741 };
+
+/* right KLT transforms */
+const double WebRtcIsac_kKltT2Gain[36] = {
+    0.14572837, -0.45446306,  0.61990621, -0.52197033,  0.32145074,
+    -0.11026900, -0.20698282,  0.48962182, -0.27127933, -0.33627476,
+    0.65094037, -0.32715751,  0.40262573, -0.47844405, -0.33876075,
+    0.44130653,  0.37383966, -0.39964662, -0.51730480,  0.06611973,
+    0.49030187,  0.47512886, -0.02141226, -0.51129451, -0.58578569,
+    -0.39132064, -0.13187771,  0.15649421,  0.40735596,  0.54396897,
+    0.40381276,  0.40904942,  0.41179766,  0.41167576,  0.40840251,
+    0.40468132 };
+
+const double WebRtcIsac_kKltT2Shape[36] = {
+    0.13427386, -0.35132558,  0.52506528, -0.59419077,  0.45075085,
+    -0.16312057,  0.29857439, -0.58660147,  0.34265431,  0.20879510,
+    -0.56063262,  0.30238345,  0.43308283, -0.41186999, -0.35288681,
+    0.42768996,  0.36094634, -0.45284910, -0.47116680,  0.02893449,
+    0.54326135,  0.45249040, -0.06264420, -0.52283830,  0.57137758,
+    0.44298139,  0.12617554, -0.20819946, -0.42324603, -0.48876443,
+    0.39597050,  0.40713935,  0.41389880,  0.41512486,  0.41130400,
+    0.40575001 };
+
+/* means of log gains and LAR coefficients*/
+const double WebRtcIsac_kLpcMeansGain[12] = {
+    -6.86881911, -5.35075273, -6.86792680, -5.36200897, -6.86401538,
+    -5.36921533, -6.86802969, -5.36893966, -6.86538097, -5.36315063,
+    -6.85535304, -5.35155315 };
+
+const double WebRtcIsac_kLpcMeansShape[108] = {
+    -0.91232981,  0.26258634, -0.33716701,  0.08477430, -0.03378426,
+    0.14423909,  0.07036185,  0.06155019,  0.01490385,  0.04138740,
+    0.01427317,  0.01288970,  0.83872106,  0.25750199,  0.07988929,
+    -0.01957923,  0.00831390,  0.01770300, -0.90957164,  0.25732216,
+    -0.33385344,  0.08735740, -0.03715332,  0.14584917,  0.06998990,
+    0.06131968,  0.01504379,  0.04067339,  0.01428039,  0.01406460,
+    0.83846243,  0.26169862,  0.08109025, -0.01767055,  0.00970539,
+    0.01954310, -0.90490803,  0.24656405, -0.33578607,  0.08843286,
+    -0.03749139,  0.14443959,  0.07214669,  0.06170993,  0.01449947,
+    0.04134309,  0.01314762,  0.01413471,  0.83895203,  0.26748062,
+    0.08197507, -0.01781298,  0.00885967,  0.01922394, -0.90922472,
+    0.24495889, -0.33921540,  0.08877169, -0.03581332,  0.14199172,
+    0.07444032,  0.06185940,  0.01502054,  0.04185113,  0.01276579,
+    0.01355457,  0.83645358,  0.26631720,  0.08119697, -0.01835449,
+    0.00788512,  0.01846446, -0.90482253,  0.24658310, -0.34019734,
+    0.08281090, -0.03486038,  0.14359248,  0.07401336,  0.06001471,
+    0.01528421,  0.04254560,  0.01321472,  0.01240799,  0.83857127,
+    0.26281654,  0.08174380, -0.02099842,  0.00755176,  0.01699448,
+    -0.90132307,  0.25174308, -0.33838268,  0.07883863, -0.02877906,
+    0.14105407,  0.07220290,  0.06000352,  0.01684879,  0.04226844,
+    0.01331331,  0.01269244,  0.83832138,  0.25467485,  0.08118028,
+    -0.02120528,  0.00747832,  0.01567212 };
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
new file mode 100644
index 0000000..56ff22c
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define KLT_STEPSIZE 1.00000000
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_GAIN_SCALE 4.000f
+#define LPC_LOBAND_SCALE 2.100f
+#define LPC_LOBAND_ORDER ORDERLO
+#define LPC_HIBAND_SCALE 0.450f
+#define LPC_HIBAND_ORDER ORDERHI
+#define LPC_GAIN_ORDER 2
+
+#define LPC_SHAPE_ORDER (LPC_LOBAND_ORDER + LPC_HIBAND_ORDER)
+
+#define KLT_ORDER_GAIN (LPC_GAIN_ORDER * SUBFRAMES)
+#define KLT_ORDER_SHAPE (LPC_SHAPE_ORDER * SUBFRAMES)
+
+/* cdf array for model indicator */
+extern const uint16_t WebRtcIsac_kQKltModelCdf[KLT_NUM_MODELS + 1];
+
+/* pointer to cdf array for model indicator */
+extern const uint16_t* WebRtcIsac_kQKltModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const uint16_t WebRtcIsac_kQKltModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const short WebRtcIsac_kQKltQuantMinGain[12];
+
+extern const short WebRtcIsac_kQKltQuantMinShape[108];
+
+/* maximum quantization index */
+extern const uint16_t WebRtcIsac_kQKltMaxIndGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltMaxIndShape[108];
+
+/* index offset */
+extern const uint16_t WebRtcIsac_kQKltOffsetGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltOffsetShape[108];
+
+/* initial cdf index for KLT coefficients */
+extern const uint16_t WebRtcIsac_kQKltInitIndexGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltInitIndexShape[108];
+
+/* quantizer representation levels */
+extern const double WebRtcIsac_kQKltLevelsGain[392];
+
+extern const double WebRtcIsac_kQKltLevelsShape[578];
+
+/* cdf tables for quantizer indices */
+extern const uint16_t WebRtcIsac_kQKltCdfGain[404];
+
+extern const uint16_t WebRtcIsac_kQKltCdfShape[686];
+
+/* pointers to cdf tables for quantizer indices */
+extern const uint16_t* WebRtcIsac_kQKltCdfPtrGain[12];
+
+extern const uint16_t* WebRtcIsac_kQKltCdfPtrShape[108];
+
+/* left KLT transforms */
+extern const double WebRtcIsac_kKltT1Gain[4];
+
+extern const double WebRtcIsac_kKltT1Shape[324];
+
+/* right KLT transforms */
+extern const double WebRtcIsac_kKltT2Gain[36];
+
+extern const double WebRtcIsac_kKltT2Shape[36];
+
+/* means of log gains and LAR coefficients */
+extern const double WebRtcIsac_kLpcMeansGain[12];
+
+extern const double WebRtcIsac_kLpcMeansShape[108];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
new file mode 100644
index 0000000..080432c
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+const uint16_t WebRtcIsac_kQPitchGainCdf[255] = {
+  0,  2,  4,  6,  64,  901,  903,  905,  16954,  16956,
+  16961,  17360,  17362,  17364,  17366,  17368,  17370,  17372,  17374,  17411,
+  17514,  17516,  17583,  18790,  18796,  18802,  20760,  20777,  20782,  21722,
+  21724,  21728,  21738,  21740,  21742,  21744,  21746,  21748,  22224,  22227,
+  22230,  23214,  23229,  23239,  25086,  25108,  25120,  26088,  26094,  26098,
+  26175,  26177,  26179,  26181,  26183,  26185,  26484,  26507,  26522,  27705,
+  27731,  27750,  29767,  29799,  29817,  30866,  30883,  30885,  31025,  31029,
+  31031,  31033,  31035,  31037,  31114,  31126,  31134,  32687,  32722,  32767,
+  35718,  35742,  35757,  36943,  36952,  36954,  37115,  37128,  37130,  37132,
+  37134,  37136,  37143,  37145,  37152,  38843,  38863,  38897,  47458,  47467,
+  47474,  49040,  49061,  49063,  49145,  49157,  49159,  49161,  49163,  49165,
+  49167,  49169,  49171,  49757,  49770,  49782,  61333,  61344,  61346,  62860,
+  62883,  62885,  62887,  62889,  62891,  62893,  62895,  62897,  62899,  62901,
+  62903,  62905,  62907,  62909,  65496,  65498,  65500,  65521,  65523,  65525,
+  65527,  65529,  65531,  65533,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+  65535,  65535,  65535,  65535,  65535};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kIndexLowerLimitGain[3] = {
+  -7, -2, -1};
+
+const int16_t WebRtcIsac_kIndexUpperLimitGain[3] = {
+  0,  3,  1};
+
+const uint16_t WebRtcIsac_kIndexMultsGain[2] = {
+  18,  3};
+
+/* size of cdf table */
+const uint16_t WebRtcIsac_kQCdfTableSizeGain[1] = {
+  256};
+
+///////////////////////////FIXED POINT
+/* mean values of pitch filter gains in FIXED point */
+const int16_t WebRtcIsac_kQMeanGain1Q12[144] = {
+   843,    1092,    1336,    1222,    1405,    1656,    1500,    1815,    1843,    1838,    1839,    1843,    1843,    1843,    1843,    1843,
+  1843,    1843,     814,     846,    1092,    1013,    1174,    1383,    1391,    1511,    1584,    1734,    1753,    1843,    1843,    1843,
+  1843,    1843,    1843,    1843,     524,     689,     777,     845,     947,    1069,    1090,    1263,    1380,    1447,    1559,    1676,
+  1645,    1749,    1843,    1843,    1843,    1843,      81,     477,     563,     611,     706,     806,     849,    1012,    1192,    1128,
+  1330,    1489,    1425,    1576,    1826,    1741,    1843,    1843,       0,     290,     305,     356,     488,     575,     602,     741,
+   890,     835,    1079,    1196,    1182,    1376,    1519,    1506,    1680,    1843,       0,      47,      97,      69,     289,     381,
+   385,     474,     617,     664,     803,    1079,     935,    1160,    1269,    1265,    1506,    1741,       0,       0,       0,       0,
+   112,     120,     190,     283,     442,     343,     526,     809,     684,     935,    1134,    1020,    1265,    1506,       0,       0,
+     0,       0,       0,       0,       0,     111,     256,      87,     373,     597,     430,     684,     935,     770,    1020,    1265};
+
+const int16_t WebRtcIsac_kQMeanGain2Q12[144] = {
+  1760,    1525,    1285,    1747,    1671,    1393,    1843,    1826,    1555,    1843,    1784,    1606,    1843,    1843,    1711,    1843,
+  1843,    1814,    1389,    1275,    1040,    1564,    1414,    1252,    1610,    1495,    1343,    1753,    1592,    1405,    1804,    1720,
+  1475,    1843,    1814,    1581,    1208,    1061,    856,    1349,    1148,    994,    1390,    1253,    1111,    1495,    1343,    1178,
+  1770,    1465,    1234,    1814,    1581,    1342,    1040,    793,    713,    1053,    895,    737,    1128,    1003,    861,    1277,
+  1094,    981,    1475,    1192,    1019,    1581,    1342,    1098,    855,    570,    483,    833,    648,    540,    948,    744,
+  572,    1009,    844,    636,    1234,    934,    685,    1342,    1217,    984,    537,    318,    124,    603,    423,    350,
+  687,    479,    322,    791,    581,    430,    987,    671,    488,    1098,    849,    597,    283,    27,        0,    397,
+  222,    38,        513,    271,    124,    624,    325,    157,    737,    484,    233,    849,    597,    343,    27,        0,
+  0,    141,    0,    0,    256,    69,        0,    370,    87,        0,    484,    229,    0,    597,    343,    87};
+
+const int16_t WebRtcIsac_kQMeanGain3Q12[144] = {
+  1843,    1843,    1711,    1843,    1818,    1606,    1843,    1827,    1511,    1814,    1639,    1393,    1760,    1525,    1285,    1656,
+  1419,    1176,    1835,    1718,    1475,    1841,    1650,    1387,    1648,    1498,    1287,    1600,    1411,    1176,    1522,    1299,
+  1040,    1419,    1176,    928,    1773,    1461,    1128,    1532,    1355,    1202,    1429,    1260,    1115,    1398,    1151,    1025,
+  1172,    1080,    790,    1176,    928,    677,    1475,    1147,    1019,    1276,    1096,    922,    1214,    1010,    901,    1057,
+  893,    800,    1040,    796,    734,    928,    677,    424,    1137,    897,    753,    1120,    830,    710,    875,    751,
+  601,    795,    642,    583,    790,    544,    475,    677,    474,    140,    987,    750,    482,    697,    573,    450,
+  691,    487,    303,    661,    394,    332,    537,    303,    220,    424,    168,    0,    737,    484,    229,    624,
+  348,    153,    441,    261,    136,    397,    166,    51,        283,    27,        0,    168,    0,    0,    484,    229,
+  0,    370,    57,        0,    256,    43,        0,    141,    0,        0,    27,        0,    0,    0,    0,    0};
+
+
+const int16_t WebRtcIsac_kQMeanGain4Q12[144] = {
+  1843,    1843,    1843,    1843,    1841,    1843,    1500,    1821,    1843,    1222,    1434,    1656,    843,    1092,    1336,    504,
+  757,    1007,    1843,    1843,    1843,    1838,    1791,    1843,    1265,    1505,    1599,    965,    1219,    1425,    730,    821,
+  1092,    249,    504,    757,    1783,    1819,    1843,    1351,    1567,    1727,    1096,    1268,    1409,    805,    961,    1131,
+  444,    670,    843,    0,        249,    504,    1425,    1655,    1743,    1096,    1324,    1448,    822,    1019,    1199,    490,
+  704,    867,    81,        450,    555,    0,    0,        249,    1247,    1428,    1530,    881,    1073,    1283,    610,    759,
+  939,    278,    464,    645,    0,    200,    270,    0,    0,    0,        935,    1163,    1410,    528,    790,    1068,
+  377,    499,    717,    173,    240,    274,    0,    43,        62,        0,    0,    0,    684,    935,    1182,    343,
+  551,    735,    161,    262,    423,    0,    55,        27,        0,    0,    0,    0,    0,    0,    430,    684,
+  935,    87,        377,    597,    0,    46,        256,    0,    0,    0,    0,    0,    0,    0,    0,    0};
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
new file mode 100644
index 0000000..145fd4e
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include <stdint.h>
+
+/* header file for coding tables for the pitch filter side-info in the entropy
+ * coder */
+/********************* Pitch Filter Gain Coefficient Tables
+ * ************************/
+/* cdf for quantized pitch filter gains */
+extern const uint16_t WebRtcIsac_kQPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kIndexLowerLimitGain[3];
+
+extern const int16_t WebRtcIsac_kIndexUpperLimitGain[3];
+extern const uint16_t WebRtcIsac_kIndexMultsGain[2];
+
+/* mean values of pitch filter gains */
+//(Y)
+extern const int16_t WebRtcIsac_kQMeanGain1Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain2Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain3Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain4Q12[144];
+//(Y)
+
+/* size of cdf table */
+extern const uint16_t WebRtcIsac_kQCdfTableSizeGain[1];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
new file mode 100644
index 0000000..57d1202
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
@@ -0,0 +1,277 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Lo[127] = {
+ 0,  134,  336,  549,  778,  998,  1264,  1512,  1777,  2070,
+ 2423,  2794,  3051,  3361,  3708,  3979,  4315,  4610,  4933,  5269,
+ 5575,  5896,  6155,  6480,  6816,  7129,  7477,  7764,  8061,  8358,
+ 8718,  9020,  9390,  9783,  10177,  10543,  10885,  11342,  11795,  12213,
+ 12680,  13096,  13524,  13919,  14436,  14903,  15349,  15795,  16267,  16734,
+ 17266,  17697,  18130,  18632,  19080,  19447,  19884,  20315,  20735,  21288,
+ 21764,  22264,  22723,  23193,  23680,  24111,  24557,  25022,  25537,  26082,
+ 26543,  27090,  27620,  28139,  28652,  29149,  29634,  30175,  30692,  31273,
+ 31866,  32506,  33059,  33650,  34296,  34955,  35629,  36295,  36967,  37726,
+ 38559,  39458,  40364,  41293,  42256,  43215,  44231,  45253,  46274,  47359,
+ 48482,  49678,  50810,  51853,  53016,  54148,  55235,  56263,  57282,  58363,
+ 59288,  60179,  61076,  61806,  62474,  63129,  63656,  64160,  64533,  64856,
+ 65152,  65535,  65535,  65535,  65535,  65535,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Lo[20] = {
+ 0,  429,  3558,  5861,  8558,  11639,  15210,  19502,  24773,  31983,
+ 42602,  48567,  52601,  55676,  58160,  60172,  61889,  63235,  65383,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Lo[2] = {
+ 0,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Lo[10] = {
+ 0,  2966,  6368,  11182,  19431,  37793,  48532,  55353,  60626,  65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrLo[4] = {WebRtcIsac_kQPitchLagCdf1Lo, WebRtcIsac_kQPitchLagCdf2Lo, WebRtcIsac_kQPitchLagCdf3Lo, WebRtcIsac_kQPitchLagCdf4Lo};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeLo[1] = {128};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQIndexLowerLimitLagLo[4] = {
+-140, -9,  0, -4};
+
+const int16_t WebRtcIsac_kQIndexUpperLimitLagLo[4] = {
+-20,  9,  0,  4};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagLo[3] = {
+ 10,  1,  5};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Lo[19] = {
+-17.21385070, -15.82678944, -14.07123081, -12.03003877, -10.01311864, -8.00794627, -5.91162987, -3.89231876, -1.90220980, -0.01879275,
+ 1.89144232,  3.88123171,  5.92146992,  7.96435361,  9.98923648,  11.98266347,  13.96101002,  15.74855713,  17.10976611};
+
+const double WebRtcIsac_kQMeanLag3Lo[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Lo[9] = {
+-7.76246496, -5.92083980, -3.94095226, -1.89502305,  0.03724681,  1.93054221,  3.96443467,  5.91726366,  7.78434291};
+
+const double WebRtcIsac_kQPitchLagStepsizeLo = 2.000000;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Mid[255] = {
+ 0,  28,  61,  88,  121,  149,  233,  331,  475,  559,
+ 624,  661,  689,  712,  745,  791,  815,  843,  866,  922,
+ 959,  1024,  1061,  1117,  1178,  1238,  1280,  1350,  1453,  1513,
+ 1564,  1625,  1671,  1741,  1788,  1904,  2072,  2421,  2626,  2770,
+ 2840,  2900,  2942,  3012,  3068,  3115,  3147,  3194,  3254,  3319,
+ 3366,  3520,  3678,  3780,  3850,  3911,  3957,  4032,  4106,  4185,
+ 4292,  4474,  4683,  4842,  5019,  5191,  5321,  5428,  5540,  5675,
+ 5763,  5847,  5959,  6127,  6304,  6564,  6839,  7090,  7263,  7421,
+ 7556,  7728,  7872,  7984,  8142,  8361,  8580,  8743,  8938,  9227,
+ 9409,  9539,  9674,  9795,  9930,  10060,  10177,  10382,  10614,  10861,
+ 11038,  11271,  11415,  11629,  11792,  12044,  12193,  12416,  12574,  12821,
+ 13007,  13235,  13445,  13654,  13901,  14134,  14488,  15000,  15703,  16285,
+ 16504,  16797,  17086,  17328,  17579,  17807,  17998,  18268,  18538,  18836,
+ 19087,  19274,  19474,  19716,  19935,  20270,  20833,  21303,  21532,  21741,
+ 21978,  22207,  22523,  22770,  23054,  23613,  23943,  24204,  24399,  24651,
+ 24832,  25074,  25270,  25549,  25759,  26015,  26150,  26424,  26713,  27048,
+ 27342,  27504,  27681,  27854,  28021,  28207,  28412,  28664,  28859,  29064,
+ 29278,  29548,  29748,  30107,  30377,  30656,  30856,  31164,  31452,  31755,
+ 32011,  32328,  32626,  32919,  33319,  33789,  34329,  34925,  35396,  35973,
+ 36443,  36964,  37551,  38156,  38724,  39357,  40023,  40908,  41587,  42602,
+ 43924,  45037,  45810,  46597,  47421,  48291,  49092,  50051,  51448,  52719,
+ 53440,  54241,  54944,  55977,  56676,  57299,  57872,  58389,  59059,  59688,
+ 60237,  60782,  61094,  61573,  61890,  62290,  62658,  63030,  63217,  63454,
+ 63622,  63882,  64003,  64273,  64427,  64529,  64581,  64697,  64758,  64902,
+ 65414,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+ 65535,  65535,  65535,  65535,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Mid[36] = {
+ 0,  71,  335,  581,  836,  1039,  1323,  1795,  2258,  2608,
+ 3005,  3591,  4243,  5344,  7163,  10583,  16848,  28078,  49448,  57007,
+ 60357,  61850,  62837,  63437,  63872,  64188,  64377,  64614,  64774,  64949,
+ 65039,  65115,  65223,  65360,  65474,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Mid[2] = {
+ 0,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Mid[20] = {
+ 0,  28,  246,  459,  667,  1045,  1523,  2337,  4337,  11347,
+ 44231,  56709,  60781,  62243,  63161,  63969,  64608,  65062,  65502,  65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrMid[4] = {WebRtcIsac_kQPitchLagCdf1Mid, WebRtcIsac_kQPitchLagCdf2Mid, WebRtcIsac_kQPitchLagCdf3Mid, WebRtcIsac_kQPitchLagCdf4Mid};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeMid[1] = {256};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQIndexLowerLimitLagMid[4] = {
+-280, -17,  0, -9};
+
+const int16_t WebRtcIsac_kQIndexUpperLimitLagMid[4] = {
+-40,  17,  0,  9};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagMid[3] = {
+ 18,  1,  10};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Mid[35] = {
+-16.89183900, -15.86949778, -15.05476653, -14.00664348, -13.02793036, -12.07324237, -11.00542532, -10.11250602, -8.90792971, -8.02474753,
+-7.00426767, -5.94055287, -4.98251338, -3.91053158, -2.98820425, -1.93524245, -0.92978085, -0.01722509,  0.91317387,  1.92973955,
+ 2.96908851,  3.93728974,  4.96308471,  5.92244151,  7.08673497,  8.00993708,  9.04656316,  9.98538742,  10.97851694,  11.94772884,
+ 13.02426166,  14.00039951,  15.01347042,  15.80758023,  16.94086895};
+
+const double WebRtcIsac_kQMeanLag3Mid[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Mid[19] = {
+-8.60409403, -7.89198395, -7.03450280, -5.86260421, -4.93822322, -3.93078706, -2.91302322, -1.91824007, -0.87003282,  0.02822649,
+ 0.89951758,  1.87495484,  2.91802604,  3.96874074,  5.06571703,  5.93618227,  7.00520185,  7.88497726,  8.64160364};
+
+const double WebRtcIsac_kQPitchLagStepsizeMid = 1.000000;
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Hi[511] = {
+ 0,  7,  18,  33,  69,  105,  156,  228,  315,  612,
+ 680,  691,  709,  724,  735,  738,  742,  746,  749,  753,
+ 756,  760,  764,  774,  782,  785,  789,  796,  800,  803,
+ 807,  814,  818,  822,  829,  832,  847,  854,  858,  869,
+ 876,  883,  898,  908,  934,  977,  1010,  1050,  1060,  1064,
+ 1075,  1078,  1086,  1089,  1093,  1104,  1111,  1122,  1133,  1136,
+ 1151,  1162,  1183,  1209,  1252,  1281,  1339,  1364,  1386,  1401,
+ 1411,  1415,  1426,  1430,  1433,  1440,  1448,  1455,  1462,  1477,
+ 1487,  1495,  1502,  1506,  1509,  1516,  1524,  1531,  1535,  1542,
+ 1553,  1556,  1578,  1589,  1611,  1625,  1639,  1643,  1654,  1665,
+ 1672,  1687,  1694,  1705,  1708,  1719,  1730,  1744,  1752,  1759,
+ 1791,  1795,  1820,  1867,  1886,  1915,  1936,  1943,  1965,  1987,
+ 2041,  2099,  2161,  2175,  2200,  2211,  2226,  2233,  2244,  2251,
+ 2266,  2280,  2287,  2298,  2309,  2316,  2331,  2342,  2356,  2378,
+ 2403,  2418,  2447,  2497,  2544,  2602,  2863,  2895,  2903,  2935,
+ 2950,  2971,  3004,  3011,  3018,  3029,  3040,  3062,  3087,  3127,
+ 3152,  3170,  3199,  3243,  3293,  3322,  3340,  3377,  3402,  3427,
+ 3474,  3518,  3543,  3579,  3601,  3637,  3659,  3706,  3731,  3760,
+ 3818,  3847,  3869,  3901,  3920,  3952,  4068,  4169,  4220,  4271,
+ 4524,  4571,  4604,  4632,  4672,  4730,  4777,  4806,  4857,  4904,
+ 4951,  5002,  5031,  5060,  5107,  5150,  5212,  5266,  5331,  5382,
+ 5432,  5490,  5544,  5610,  5700,  5762,  5812,  5874,  5972,  6022,
+ 6091,  6163,  6232,  6305,  6402,  6540,  6685,  6880,  7090,  7271,
+ 7379,  7452,  7542,  7625,  7687,  7770,  7843,  7911,  7966,  8024,
+ 8096,  8190,  8252,  8320,  8411,  8501,  8585,  8639,  8751,  8842,
+ 8918,  8986,  9066,  9127,  9203,  9269,  9345,  9406,  9464,  9536,
+ 9612,  9667,  9735,  9844,  9931,  10036,  10119,  10199,  10260,  10358,
+ 10441,  10514,  10666,  10734,  10872,  10951,  11053,  11125,  11223,  11324,
+ 11516,  11664,  11737,  11816,  11892,  12008,  12120,  12200,  12280,  12392,
+ 12490,  12576,  12685,  12812,  12917,  13003,  13108,  13210,  13300,  13384,
+ 13470,  13579,  13673,  13771,  13879,  13999,  14136,  14201,  14368,  14614,
+ 14759,  14867,  14958,  15030,  15121,  15189,  15280,  15385,  15461,  15555,
+ 15653,  15768,  15884,  15971,  16069,  16145,  16210,  16279,  16380,  16463,
+ 16539,  16615,  16688,  16818,  16919,  17017,  18041,  18338,  18523,  18649,
+ 18790,  18917,  19047,  19167,  19315,  19460,  19601,  19731,  19858,  20068,
+ 20173,  20318,  20466,  20625,  20741,  20911,  21045,  21201,  21396,  21588,
+ 21816,  22022,  22305,  22547,  22786,  23072,  23322,  23600,  23879,  24168,
+ 24433,  24769,  25120,  25511,  25895,  26289,  26792,  27219,  27683,  28077,
+ 28566,  29094,  29546,  29977,  30491,  30991,  31573,  32105,  32594,  33173,
+ 33788,  34497,  35181,  35833,  36488,  37255,  37921,  38645,  39275,  39894,
+ 40505,  41167,  41790,  42431,  43096,  43723,  44385,  45134,  45858,  46607,
+ 47349,  48091,  48768,  49405,  49955,  50555,  51167,  51985,  52611,  53078,
+ 53494,  53965,  54435,  54996,  55601,  56125,  56563,  56838,  57244,  57566,
+ 57967,  58297,  58771,  59093,  59419,  59647,  59886,  60143,  60461,  60693,
+ 60917,  61170,  61416,  61634,  61891,  62122,  62310,  62455,  62632,  62839,
+ 63103,  63436,  63639,  63805,  63906,  64015,  64192,  64355,  64475,  64558,
+ 64663,  64742,  64811,  64865,  64916,  64956,  64981,  65025,  65068,  65115,
+ 65195,  65314,  65419,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+ 65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+ 65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+ 65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,  65535,
+ 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Hi[68] = {
+ 0,  7,  11,  22,  37,  52,  56,  59,  81,  85,
+ 89,  96,  115,  130,  137,  152,  170,  181,  193,  200,
+ 207,  233,  237,  259,  289,  318,  363,  433,  592,  992,
+ 1607,  3062,  6149,  12206,  25522,  48368,  58223,  61918,  63640,  64584,
+ 64943,  65098,  65206,  65268,  65294,  65335,  65350,  65372,  65387,  65402,
+ 65413,  65420,  65428,  65435,  65439,  65450,  65454,  65468,  65472,  65476,
+ 65483,  65491,  65498,  65505,  65516,  65520,  65528,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Hi[2] = {
+ 0,  65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Hi[35] = {
+ 0,  7,  19,  30,  41,  48,  63,  74,  82,  96,
+ 122,  152,  215,  330,  701,  2611,  10931,  48106,  61177,  64341,
+ 65112,  65238,  65309,  65338,  65364,  65379,  65401,  65427,  65453,  65465,
+ 65476,  65490,  65509,  65528,  65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrHi[4] = {WebRtcIsac_kQPitchLagCdf1Hi, WebRtcIsac_kQPitchLagCdf2Hi, WebRtcIsac_kQPitchLagCdf3Hi, WebRtcIsac_kQPitchLagCdf4Hi};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeHi[1] = {512};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQindexLowerLimitLagHi[4] = {
+-552, -34,  0, -16};
+
+const int16_t WebRtcIsac_kQindexUpperLimitLagHi[4] = {
+-80,  32,  0,  17};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagHi[3] = {
+ 34,  1,  18};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Hi[67] = {
+-17.07263295, -16.50000000, -15.83966081, -15.55613708, -14.96948007, -14.50000000, -14.00000000, -13.48377986, -13.00000000, -12.50000000,
+-11.93199636, -11.44530414, -11.04197641, -10.39910301, -10.15202337, -9.51322461, -8.93357741, -8.46456632, -8.10270672, -7.53751847,
+-6.98686404, -6.50000000, -6.08463150, -5.46872991, -5.00864717, -4.50163760, -4.01382410, -3.43856708, -2.96898001, -2.46554810,
+-1.96861004, -1.47106701, -0.97197237, -0.46561654, -0.00531409,  0.45767857,  0.96777907,  1.47507903,  1.97740425,  2.46695420,
+ 3.00695774,  3.47167185,  4.02712538,  4.49280007,  5.01087640,  5.48191963,  6.04916550,  6.51511058,  6.97297819,  7.46565499,
+ 8.01489405,  8.39912001,  8.91819757,  9.50000000,  10.11654065,  10.50000000,  11.03712583,  11.50000000,  12.00000000,  12.38964346,
+ 12.89466127,  13.43657881,  13.96013840,  14.46279912,  15.00000000,  15.39412269,  15.96662441};
+
+const double WebRtcIsac_kQMeanLag3Hi[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Hi[34] = {
+-7.98331221, -7.47988769, -7.03626557, -6.52708003, -6.06982173, -5.51856292, -5.05827033, -4.45909878, -3.99125864, -3.45308135,
+-3.02328139, -2.47297273, -1.94341995, -1.44699056, -0.93612243, -0.43012406,  0.01120357,  0.44054812,  0.93199883,  1.45669587,
+ 1.97218322,  2.50187419,  2.98748690,  3.49343202,  4.01660147,  4.50984306,  5.01402683,  5.58936797,  5.91787793,  6.59998900,
+ 6.85034315,  7.53503316,  7.87711194,  8.53631648};
+
+const double WebRtcIsac_kQPitchLagStepsizeHi = 0.500000;
+
+/* transform matrix */
+const double WebRtcIsac_kTransform[4][4] = {
+{-0.50000000, -0.50000000, -0.50000000, -0.50000000},
+{ 0.67082039,  0.22360680, -0.22360680, -0.67082039},
+{ 0.50000000, -0.50000000, -0.50000000,  0.50000000},
+{ 0.22360680, -0.67082039,  0.67082039, -0.22360680}};
+
+/* transpose transform matrix */
+const double WebRtcIsac_kTransformTranspose[4][4] = {
+{-0.50000000,  0.67082039,  0.50000000,  0.22360680},
+{-0.50000000,  0.22360680, -0.50000000, -0.67082039},
+{-0.50000000, -0.22360680, -0.50000000,  0.67082039},
+{-0.50000000, -0.67082039,  0.50000000, -0.22360680}};
+
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
new file mode 100644
index 0000000..b48e358
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+
+#include <stdint.h>
+
+/* header file for coding tables for the pitch filter side-info in the entropy
+ * coder */
+/********************* Pitch Filter Lag Coefficient Tables
+ * ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Lo[127];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Lo[20];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Lo[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Lo[10];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrLo[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeLo[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQIndexLowerLimitLagLo[4];
+extern const int16_t WebRtcIsac_kQIndexUpperLimitLagLo[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagLo[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Lo[19];
+extern const double WebRtcIsac_kQMeanLag3Lo[1];
+extern const double WebRtcIsac_kQMeanLag4Lo[9];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeLo;
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Mid[255];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Mid[36];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Mid[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Mid[20];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrMid[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeMid[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQIndexLowerLimitLagMid[4];
+extern const int16_t WebRtcIsac_kQIndexUpperLimitLagMid[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagMid[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Mid[35];
+extern const double WebRtcIsac_kQMeanLag3Mid[1];
+extern const double WebRtcIsac_kQMeanLag4Mid[19];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeMid;
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Hi[511];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Hi[68];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Hi[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Hi[35];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrHi[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeHi[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQindexLowerLimitLagHi[4];
+extern const int16_t WebRtcIsac_kQindexUpperLimitLagHi[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagHi[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Hi[67];
+extern const double WebRtcIsac_kQMeanLag3Hi[1];
+extern const double WebRtcIsac_kQMeanLag4Hi[34];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeHi;
+
+/* transform matrix */
+extern const double WebRtcIsac_kTransform[4][4];
+
+/* transpose transform matrix */
+extern const double WebRtcIsac_kTransformTranspose[4][4];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c b/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000..839d5d4
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
@@ -0,0 +1,139 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+const uint16_t WebRtcIsac_kQArRc1Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  129,  7707,  57485,  65495,  65527,  65529,  65531,
+ 65533,  65535};
+
+/* cdf for quantized reflection coefficient 2 */
+const uint16_t WebRtcIsac_kQArRc2Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  7,  531,  25298,  64525,  65526,  65529,  65531,
+ 65533,  65535};
+
+/* cdf for quantized reflection coefficient 3 */
+const uint16_t WebRtcIsac_kQArRc3Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  6,  620,  22898,  64843,  65527,  65529,  65531,
+ 65533,  65535};
+
+/* cdf for quantized reflection coefficient 4 */
+const uint16_t WebRtcIsac_kQArRc4Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  6,  35,  10034,  60733,  65506,  65529,  65531,
+ 65533,  65535};
+
+/* cdf for quantized reflection coefficient 5 */
+const uint16_t WebRtcIsac_kQArRc5Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  6,  36,  7567,  56727,  65385,  65529,  65531,
+ 65533,  65535};
+
+/* cdf for quantized reflection coefficient 6 */
+const uint16_t WebRtcIsac_kQArRc6Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0,  2,  4,  6,  14,  6579,  57360,  65409,  65529,  65531,
+ 65533,  65535};
+
+/* representation levels for quantized reflection coefficient 1 */
+const int16_t WebRtcIsac_kQArRc1Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const int16_t WebRtcIsac_kQArRc2Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const int16_t WebRtcIsac_kQArRc3Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const int16_t WebRtcIsac_kQArRc4Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const int16_t WebRtcIsac_kQArRc5Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const int16_t WebRtcIsac_kQArRc6Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const int16_t WebRtcIsac_kQArBoundaryLevels[NUM_AR_RC_QUANT_BAUNDARY] = {
+-32768, -31441, -27566, -21458, -13612, -4663, 4663, 13612, 21458, 27566, 31441,
+32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const uint16_t WebRtcIsac_kQArRcInitIndex[6] = {
+ 5,  5,  5,  5,  5,  5};
+
+/* pointers to AR cdf tables */
+const uint16_t *WebRtcIsac_kQArRcCdfPtr[AR_ORDER] = {
+  WebRtcIsac_kQArRc1Cdf, WebRtcIsac_kQArRc2Cdf, WebRtcIsac_kQArRc3Cdf,
+  WebRtcIsac_kQArRc4Cdf, WebRtcIsac_kQArRc5Cdf, WebRtcIsac_kQArRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const int16_t *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER] = {
+  WebRtcIsac_kQArRc1Levels, WebRtcIsac_kQArRc2Levels, WebRtcIsac_kQArRc3Levels,
+  WebRtcIsac_kQArRc4Levels, WebRtcIsac_kQArRc5Levels, WebRtcIsac_kQArRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+const uint16_t WebRtcIsac_kQGainCdf[19] = {
+ 0,  2,  4,  6,  8,  10,  12,  14,  16,  1172,
+ 11119,  29411,  51699,  64445,  65527,  65529,  65531,  65533,  65535};
+
+/* representation levels for quantized squared Gain coefficient */
+const int32_t WebRtcIsac_kQGain2Levels[18] = {
+// 17, 28, 46, 76, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+ 128, 128, 128, 128, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+/* quantization boundary levels for squared Gain coefficient */
+const int32_t WebRtcIsac_kQGain2BoundaryLevels[19] = {
+0, 21, 35, 59, 99, 166, 280, 475, 815, 1414, 2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF};
+
+/* pointers to Gain cdf table */
+const uint16_t *WebRtcIsac_kQGainCdf_ptr[1] = {WebRtcIsac_kQGainCdf};
+
+/* Gain initial index for gain quantizer and cdf table search */
+const uint16_t WebRtcIsac_kQGainInitIndex[1] = {11};
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+const int16_t WebRtcIsac_kCos[6][60] = {
+{512,  512,  511,  510,  508,  507,  505,  502,  499,  496,  493,  489,  485,  480,  476,  470,  465,  459,  453,  447,
+440,  433,  426,  418,  410,  402,  394,  385,  376,  367,  357,  348,  338,  327,  317,  306,  295,  284,  273,  262,
+250,  238,  226,  214,  202,  190,  177,  165,  152,  139,  126,  113,  100,  87,  73,  60,  47,  33,  20,  7},
+{512,  510,  508,  503,  498,  491,  483,  473,  462,  450,  437,  422,  406,  389,  371,  352,  333,  312,  290,  268,
+244,  220,  196,  171,  145,  120,  93,  67,  40,  13,  -13,  -40,  -67,  -93,  -120,  -145,  -171,  -196,  -220,  -244,
+-268,  -290,  -312,  -333,  -352,  -371,  -389,  -406,  -422,  -437,  -450,  -462,  -473,  -483,  -491,  -498,  -503,  -508,  -510,  -512},
+{512,  508,  502,  493,  480,  465,  447,  426,  402,  376,  348,  317,  284,  250,  214,  177,  139,  100,  60,  20,
+-20,  -60,  -100,  -139,  -177,  -214,  -250,  -284,  -317,  -348,  -376,  -402,  -426,  -447,  -465,  -480,  -493,  -502,  -508,  -512,
+-512,  -508,  -502,  -493,  -480,  -465,  -447,  -426,  -402,  -376,  -348,  -317,  -284,  -250,  -214,  -177,  -139,  -100,  -60,  -20},
+{511,  506,  495,  478,  456,  429,  398,  362,  322,  279,  232,  183,  133,  80,  27,  -27,  -80,  -133,  -183,  -232,
+-279,  -322,  -362,  -398,  -429,  -456,  -478,  -495,  -506,  -511,  -511,  -506,  -495,  -478,  -456,  -429,  -398,  -362,  -322,  -279,
+-232,  -183,  -133,  -80,  -27,  27,  80,  133,  183,  232,  279,  322,  362,  398,  429,  456,  478,  495,  506,  511},
+{511,  502,  485,  459,  426,  385,  338,  284,  226,  165,  100,  33,  -33,  -100,  -165,  -226,  -284,  -338,  -385,  -426,
+-459,  -485,  -502,  -511,  -511,  -502,  -485,  -459,  -426,  -385,  -338,  -284,  -226,  -165,  -100,  -33,  33,  100,  165,  226,
+284,  338,  385,  426,  459,  485,  502,  511,  511,  502,  485,  459,  426,  385,  338,  284,  226,  165,  100,  33},
+{510,  498,  473,  437,  389,  333,  268,  196,  120,  40,  -40,  -120,  -196,  -268,  -333,  -389,  -437,  -473,  -498,  -510,
+-510,  -498,  -473,  -437,  -389,  -333,  -268,  -196,  -120,  -40,  40,  120,  196,  268,  333,  389,  437,  473,  498,  510,
+510,  498,  473,  437,  389,  333,  268,  196,  120,  40,  -40,  -120,  -196,  -268,  -333,  -389,  -437,  -473,  -498,  -510}
+};
diff --git a/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h b/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000..d272be0
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define NUM_AR_RC_QUANT_BAUNDARY 12
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const uint16_t WebRtcIsac_kQArRc1Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const uint16_t WebRtcIsac_kQArRc2Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const uint16_t WebRtcIsac_kQArRc3Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const uint16_t WebRtcIsac_kQArRc4Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const uint16_t WebRtcIsac_kQArRc5Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const uint16_t WebRtcIsac_kQArRc6Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* quantization boundary levels for reflection coefficients */
+extern const int16_t WebRtcIsac_kQArBoundaryLevels[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search
+ */
+extern const uint16_t WebRtcIsac_kQArRcInitIndex[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const uint16_t* WebRtcIsac_kQArRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const int16_t* WebRtcIsac_kQArRcLevelsPtr[AR_ORDER];
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const uint16_t WebRtcIsac_kQGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const int32_t WebRtcIsac_kQGain2Levels[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const int32_t WebRtcIsac_kQGain2BoundaryLevels[19];
+
+/* pointer to Gain cdf table */
+extern const uint16_t* WebRtcIsac_kQGainCdf_ptr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const uint16_t WebRtcIsac_kQGainInitIndex[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const int16_t WebRtcIsac_kCos[6][60];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ \
+        */
diff --git a/modules/audio_coding/codecs/isac/main/source/transform.c b/modules/audio_coding/codecs/isac/main/source/transform.c
new file mode 100644
index 0000000..082ad94
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/source/transform.c
@@ -0,0 +1,126 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "modules/third_party/fft/fft.h"
+
+void WebRtcIsac_InitTransform(TransformTables* tables) {
+  int k;
+  double fact, phase;
+
+  fact = PI / (FRAMESAMPLES_HALF);
+  phase = 0.0;
+  for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+    tables->costab1[k] = cos(phase);
+    tables->sintab1[k] = sin(phase);
+    phase += fact;
+  }
+
+  fact = PI * ((double) (FRAMESAMPLES_HALF - 1)) / ((double) FRAMESAMPLES_HALF);
+  phase = 0.5 * fact;
+  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+    tables->costab2[k] = cos(phase);
+    tables->sintab2[k] = sin(phase);
+    phase += fact;
+  }
+}
+
+void WebRtcIsac_Time2Spec(const TransformTables* tables,
+                          double* inre1,
+                          double* inre2,
+                          int16_t* outreQ7,
+                          int16_t* outimQ7,
+                          FFTstr* fftstr_obj) {
+  int k;
+  int dims[1];
+  double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+  double tmpre[FRAMESAMPLES_HALF], tmpim[FRAMESAMPLES_HALF];
+
+
+  dims[0] = FRAMESAMPLES_HALF;
+
+
+  /* Multiply with complex exponentials and combine into one complex vector */
+  fact = 0.5 / sqrt(FRAMESAMPLES_HALF);
+  for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+    tmp1r = tables->costab1[k];
+    tmp1i = tables->sintab1[k];
+    tmpre[k] = (inre1[k] * tmp1r + inre2[k] * tmp1i) * fact;
+    tmpim[k] = (inre2[k] * tmp1r - inre1[k] * tmp1i) * fact;
+  }
+
+
+  /* Get DFT */
+  WebRtcIsac_Fftns(1, dims, tmpre, tmpim, -1, 1.0, fftstr_obj);
+
+  /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+    xr = tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+    yi = -tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+    xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k];
+    yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - k];
+
+    tmp1r = tables->costab2[k];
+    tmp1i = tables->sintab2[k];
+    outreQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1r - xi * tmp1i) * 128.0);
+    outimQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1i + xi * tmp1r) * 128.0);
+    outreQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1i - yi * tmp1r) * 128.0);
+    outimQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1r + yi * tmp1i) * 128.0);
+  }
+}
+
+void WebRtcIsac_Spec2time(const TransformTables* tables,
+                          double* inre,
+                          double* inim,
+                          double* outre1,
+                          double* outre2,
+                          FFTstr* fftstr_obj) {
+  int k;
+  double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+
+  int dims;
+
+  dims = FRAMESAMPLES_HALF;
+
+  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+    /* Move zero in time to beginning of frames */
+    tmp1r = tables->costab2[k];
+    tmp1i = tables->sintab2[k];
+    xr = inre[k] * tmp1r + inim[k] * tmp1i;
+    xi = inim[k] * tmp1r - inre[k] * tmp1i;
+    yr = -inim[FRAMESAMPLES_HALF - 1 - k] * tmp1r - inre[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+    yi = -inre[FRAMESAMPLES_HALF - 1 - k] * tmp1r + inim[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+
+    /* Combine into one vector,  z = x + j * y */
+    outre1[k] = xr - yi;
+    outre1[FRAMESAMPLES_HALF - 1 - k] = xr + yi;
+    outre2[k] = xi + yr;
+    outre2[FRAMESAMPLES_HALF - 1 - k] = -xi + yr;
+  }
+
+
+  /* Get IDFT */
+  WebRtcIsac_Fftns(1, &dims, outre1, outre2, 1, FRAMESAMPLES_HALF, fftstr_obj);
+
+
+  /* Demodulate and separate */
+  fact = sqrt(FRAMESAMPLES_HALF);
+  for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+    tmp1r = tables->costab1[k];
+    tmp1i = tables->sintab1[k];
+    xr = (outre1[k] * tmp1r - outre2[k] * tmp1i) * fact;
+    outre2[k] = (outre2[k] * tmp1r + outre1[k] * tmp1i) * fact;
+    outre1[k] = xr;
+  }
+}
diff --git a/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc b/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc
new file mode 100644
index 0000000..ee72b07
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc
@@ -0,0 +1,942 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// ReleaseTest-API.cpp : Defines the entry point for the console application.
+//
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <iostream>
+
+/* include API */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* Defines */
+#define SEED_FILE                                             \
+  "randseed.txt" /* Used when running decoder on garbage data \
+                  */
+#define MAX_FRAMESAMPLES                                         \
+  960                         /* max number of samples per frame \
+                                 (= 60 ms frame & 16 kHz) or     \
+                                 (= 30 ms frame & 32 kHz) */
+#define FRAMESAMPLES_10ms 160 /* number of samples per 10ms frame */
+#define SWBFRAMESAMPLES_10ms 320
+//#define FS 16000 /* sampling frequency (Hz) */
+
+#ifdef WIN32
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000 /* Runtime statistics */
+#endif
+#endif
+
+int main(int argc, char* argv[]) {
+  char inname[100], outname[100], bottleneck_file[100], vadfile[100];
+  FILE *inp, *outp, *f_bn = NULL, *vadp = NULL, *bandwidthp;
+  int framecnt, endfile;
+
+  size_t i;
+  int errtype, VADusage = 0, packetLossPercent = 0;
+  int16_t CodingMode;
+  int32_t bottleneck = 0;
+  int framesize = 30; /* ms */
+  int cur_framesmpls, err;
+
+  /* Runtime statistics */
+  double starttime, runtime, length_file;
+
+  size_t stream_len = 0;
+  int declen = 0, declenTC = 0;
+  bool lostFrame = false;
+
+  int16_t shortdata[SWBFRAMESAMPLES_10ms];
+  int16_t vaddata[SWBFRAMESAMPLES_10ms * 3];
+  int16_t decoded[MAX_FRAMESAMPLES << 1];
+  int16_t decodedTC[MAX_FRAMESAMPLES << 1];
+  uint16_t streamdata[500];
+  int16_t speechType[1];
+  int16_t rateBPS = 0;
+  int16_t fixedFL = 0;
+  int16_t payloadSize = 0;
+  int32_t payloadRate = 0;
+  int setControlBWE = 0;
+  short FL, testNum;
+  char version_number[20];
+  FILE* plFile;
+  int32_t sendBN;
+
+#if !defined(NDEBUG)
+  FILE* fy;
+  double kbps;
+#endif
+  size_t totalbits = 0;
+  int totalsmpls = 0;
+
+  /* If use GNS file */
+  FILE* fp_gns = NULL;
+  char gns_file[100];
+  size_t maxStreamLen30 = 0;
+  size_t maxStreamLen60 = 0;
+  short sampFreqKHz = 32;
+  short samplesIn10Ms;
+  // FILE logFile;
+  bool doTransCoding = false;
+  int32_t rateTransCoding = 0;
+  uint8_t streamDataTransCoding[1200];
+  size_t streamLenTransCoding = 0;
+  FILE* transCodingFile = NULL;
+  FILE* transcodingBitstream = NULL;
+  size_t numTransCodingBytes = 0;
+
+  /* only one structure used for ISAC encoder */
+  ISACStruct* ISAC_main_inst = NULL;
+  ISACStruct* decoderTransCoding = NULL;
+
+  BottleNeckModel BN_data;
+
+#if !defined(NDEBUG)
+  fy = fopen("bit_rate.dat", "w");
+  fclose(fy);
+  fy = fopen("bytes_frames.dat", "w");
+  fclose(fy);
+#endif
+
+  /* Handling wrong input arguments in the command line */
+  if ((argc < 3) || (argc > 17)) {
+    printf("\n\nWrong number of arguments or flag values.\n\n");
+
+    printf("\n");
+    WebRtcIsac_version(version_number);
+    printf("iSAC-swb version %s \n\n", version_number);
+
+    printf("Usage:\n\n");
+    printf("%s [-I] bottleneck_value infile outfile \n\n", argv[0]);
+    printf("with:\n");
+    printf("[-FS num]       : sampling frequency in kHz, valid values are\n");
+    printf("                  16 & 32, with 16 as default.\n");
+    printf("[-I]            : if -I option is specified, the coder will use\n");
+    printf("                  an instantaneous Bottleneck value. If not, it\n");
+    printf("                  will be an adaptive Bottleneck value.\n");
+    printf("[-assign]       : Use Assign API.\n");
+    printf("[-B num]        : the value of the bottleneck provided either\n");
+    printf("                  as a fixed value in bits/sec (e.g. 25000) or\n");
+    printf("                  read from a file (e.g. bottleneck.txt)\n");
+    printf("[-INITRATE num] : Set a new value for initial rate. Note! Only\n");
+    printf("                  used in adaptive mode.\n");
+    printf("[-FL num]       : Set (initial) frame length in msec. Valid\n");
+    printf("                  lengths are 30 and 60 msec.\n");
+    printf("[-FIXED_FL]     : Frame length will be fixed to initial value.\n");
+    printf("[-MAX num]      : Set the limit for the payload size of iSAC\n");
+    printf("                  in bytes. Minimum 100 maximum 400.\n");
+    printf("[-MAXRATE num]  : Set the maxrate for iSAC in bits per second.\n");
+    printf("                  Minimum 32000, maximum 53400.\n");
+    printf("[-F num]        : if -F option is specified, the test function\n");
+    printf("                  will run the iSAC API fault scenario\n");
+    printf("                  specified by the supplied number.\n");
+    printf("                  F 1 - Call encoder prior to init encoder call\n");
+    printf("                  F 2 - Call decoder prior to init decoder call\n");
+    printf("                  F 3 - Call decoder prior to encoder call\n");
+    printf("                  F 4 - Call decoder with a too short coded\n");
+    printf("                        sequence\n");
+    printf("                  F 5 - Call decoder with a too long coded\n");
+    printf("                        sequence\n");
+    printf("                  F 6 - Call decoder with random bit stream\n");
+    printf("                  F 7 - Call init encoder/decoder at random\n");
+    printf("                        during a call\n");
+    printf("                  F 8 - Call encoder/decoder without having\n");
+    printf("                        allocated memory for encoder/decoder\n");
+    printf("                        instance\n");
+    printf("                  F 9 - Call decodeB without calling decodeA\n");
+    printf("                  F 10 - Call decodeB with garbage data\n");
+    printf("[-PL num]       : if -PL option is specified \n");
+    printf("[-T rate file]  : test trans-coding with target bottleneck\n");
+    printf("                  'rate' bits/sec\n");
+    printf("                  the output file is written to 'file'\n");
+    printf("[-LOOP num]     : number of times to repeat coding the input\n");
+    printf("                  file for stress testing\n");
+    // printf("[-CE num]       : Test of APIs used by Conference Engine.\n");
+    // printf("                  CE 1 - getNewBitstream, getBWE \n");
+    // printf("                  (CE 2 - RESERVED for transcoding)\n");
+    // printf("                  CE 3 - getSendBWE, setSendBWE.  \n");
+    // printf("-L filename     : write the logging info into file
+    // (appending)\n");
+    printf("infile          :   Normal speech input file\n");
+    printf("outfile         :   Speech output file\n");
+    exit(0);
+  }
+
+  /* Print version number */
+  printf("-------------------------------------------------\n");
+  WebRtcIsac_version(version_number);
+  printf("iSAC version %s \n\n", version_number);
+
+  /* Loop over all command line arguments */
+  CodingMode = 0;
+  testNum = 0;
+  // logFile = NULL;
+  char transCodingFileName[500];
+  int16_t totFileLoop = 0;
+  int16_t numFileLoop = 0;
+  for (i = 1; i + 2 < static_cast<size_t>(argc); i++) {
+    if (!strcmp("-LOOP", argv[i])) {
+      i++;
+      totFileLoop = (int16_t)atol(argv[i]);
+      if (totFileLoop <= 0) {
+        fprintf(stderr, "Invalid number of runs for the given input file, %d.",
+                totFileLoop);
+        exit(0);
+      }
+    }
+
+    if (!strcmp("-T", argv[i])) {
+      doTransCoding = true;
+      i++;
+      rateTransCoding = atoi(argv[i]);
+      i++;
+      strcpy(transCodingFileName, argv[i]);
+    }
+
+    /* Set Sampling Rate */
+    if (!strcmp("-FS", argv[i])) {
+      i++;
+      sampFreqKHz = atoi(argv[i]);
+    }
+
+    /* Instantaneous mode */
+    if (!strcmp("-I", argv[i])) {
+      printf("Instantaneous BottleNeck\n");
+      CodingMode = 1;
+    }
+
+    /* Set (initial) bottleneck value */
+    if (!strcmp("-INITRATE", argv[i])) {
+      rateBPS = atoi(argv[i + 1]);
+      setControlBWE = 1;
+      if ((rateBPS < 10000) || (rateBPS > 32000)) {
+        printf(
+            "\n%d is not a initial rate. Valid values are in the range "
+            "10000 to 32000.\n",
+            rateBPS);
+        exit(0);
+      }
+      printf("New initial rate: %d\n", rateBPS);
+      i++;
+    }
+
+    /* Set (initial) framelength */
+    if (!strcmp("-FL", argv[i])) {
+      framesize = atoi(argv[i + 1]);
+      if ((framesize != 30) && (framesize != 60)) {
+        printf(
+            "\n%d is not a valid frame length. Valid length are 30 and 60 "
+            "msec.\n",
+            framesize);
+        exit(0);
+      }
+      setControlBWE = 1;
+      printf("Frame Length: %d\n", framesize);
+      i++;
+    }
+
+    /* Fixed frame length */
+    if (!strcmp("-FIXED_FL", argv[i])) {
+      fixedFL = 1;
+      setControlBWE = 1;
+      printf("Fixed Frame Length\n");
+    }
+
+    /* Set maximum allowed payload size in bytes */
+    if (!strcmp("-MAX", argv[i])) {
+      payloadSize = atoi(argv[i + 1]);
+      printf("Maximum Payload Size: %d\n", payloadSize);
+      i++;
+    }
+
+    /* Set maximum rate in bytes */
+    if (!strcmp("-MAXRATE", argv[i])) {
+      payloadRate = atoi(argv[i + 1]);
+      printf("Maximum Rate in kbps: %d\n", payloadRate);
+      i++;
+    }
+
+    /* Test of fault scenarious */
+    if (!strcmp("-F", argv[i])) {
+      testNum = atoi(argv[i + 1]);
+      printf("Fault test: %d\n", testNum);
+      if (testNum < 1 || testNum > 10) {
+        printf(
+            "\n%d is not a valid Fault Scenario number. Valid Fault "
+            "Scenarios are numbered 1-10.\n",
+            testNum);
+        exit(0);
+      }
+      i++;
+    }
+
+    /* Packet loss test */
+    if (!strcmp("-PL", argv[i])) {
+      if (isdigit(static_cast<unsigned char>(*argv[i + 1]))) {
+        packetLossPercent = atoi(argv[i + 1]);
+        if ((packetLossPercent < 0) | (packetLossPercent > 100)) {
+          printf("\nInvalid packet loss perentage \n");
+          exit(0);
+        }
+        if (packetLossPercent > 0) {
+          printf("Simulating %d %% of independent packet loss\n",
+                 packetLossPercent);
+        } else {
+          printf("\nNo Packet Loss Is Simulated \n");
+        }
+      } else {
+        plFile = fopen(argv[i + 1], "rb");
+        if (plFile == NULL) {
+          printf("\n couldn't open the frameloss file: %s\n", argv[i + 1]);
+          exit(0);
+        }
+        printf("Simulating packet loss through the given channel file: %s\n",
+               argv[i + 1]);
+      }
+      i++;
+    }
+
+    /* Random packetlosses */
+    if (!strcmp("-rnd", argv[i])) {
+      srand((unsigned int)time(NULL));
+      printf("Random pattern in lossed packets \n");
+    }
+
+    /* Use gns file */
+    if (!strcmp("-G", argv[i])) {
+      sscanf(argv[i + 1], "%s", gns_file);
+      fp_gns = fopen(gns_file, "rb");
+      if (fp_gns == NULL) {
+        printf("Cannot read file %s.\n", gns_file);
+        exit(0);
+      }
+      i++;
+    }
+
+    // make it with '-B'
+    /* Get Bottleneck value */
+    if (!strcmp("-B", argv[i])) {
+      i++;
+      bottleneck = atoi(argv[i]);
+      if (bottleneck == 0) {
+        sscanf(argv[i], "%s", bottleneck_file);
+        f_bn = fopen(bottleneck_file, "rb");
+        if (f_bn == NULL) {
+          printf(
+              "Error No value provided for BottleNeck and cannot read file "
+              "%s.\n",
+              bottleneck_file);
+          exit(0);
+        } else {
+          printf("reading bottleneck rates from file %s\n\n", bottleneck_file);
+          if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+            /* Set pointer to beginning of file */
+            fseek(f_bn, 0L, SEEK_SET);
+            if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+              exit(0);
+            }
+          }
+
+          /* Bottleneck is a cosine function
+           * Matlab code for writing the bottleneck file:
+           * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
+           * fid = fopen('bottleneck.txt', 'wb');
+           * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
+           */
+        }
+      } else {
+        printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+      }
+    }
+    /* Run Conference Engine APIs */
+    //     Do not test it in the first release
+    //
+    //     if(!strcmp ("-CE", argv[i]))
+    //     {
+    //         testCE = atoi(argv[i + 1]);
+    //         if(testCE==1)
+    //         {
+    //             i++;
+    //             scale = (float)atof( argv[i+1] );
+    //         }
+    //         else if(testCE == 2)
+    //         {
+    //             printf("\nCE-test 2 (transcoding) not implemented.\n");
+    //             exit(0);
+    //         }
+    //         else if(testCE < 1 || testCE > 3)
+    //         {
+    //             printf("\n%d is not a valid CE-test number. Valid CE tests
+    //             are 1-3.\n", testCE);
+    //             exit(0);
+    //         }
+    //         printf("CE-test number: %d\n", testCE);
+    //         i++;
+    //     }
+  }
+
+  if (CodingMode == 0) {
+    printf("\nAdaptive BottleNeck\n");
+  }
+
+  switch (sampFreqKHz) {
+    case 16: {
+      printf("iSAC Wideband.\n");
+      samplesIn10Ms = FRAMESAMPLES_10ms;
+      break;
+    }
+    case 32: {
+      printf("iSAC Supper-Wideband.\n");
+      samplesIn10Ms = SWBFRAMESAMPLES_10ms;
+      break;
+    }
+    default:
+      printf("Unsupported sampling frequency %d kHz", sampFreqKHz);
+      exit(0);
+  }
+
+  /* Get Input and Output files */
+  sscanf(argv[argc - 2], "%s", inname);
+  sscanf(argv[argc - 1], "%s", outname);
+  printf("\nInput file: %s\n", inname);
+  printf("Output file: %s\n\n", outname);
+  if ((inp = fopen(inname, "rb")) == NULL) {
+    printf("  Error iSAC Cannot read file %s.\n", inname);
+    std::cout << std::flush;
+    exit(1);
+  }
+
+  if ((outp = fopen(outname, "wb")) == NULL) {
+    printf("  Error iSAC Cannot write file %s.\n", outname);
+    std::cout << std::flush;
+    getc(stdin);
+    exit(1);
+  }
+  if (VADusage) {
+    if ((vadp = fopen(vadfile, "rb")) == NULL) {
+      printf("  Error iSAC Cannot read file %s.\n", vadfile);
+      std::cout << std::flush;
+      exit(1);
+    }
+  }
+
+  if ((bandwidthp = fopen("bwe.pcm", "wb")) == NULL) {
+    printf("  Error iSAC Cannot read file %s.\n", "bwe.pcm");
+    std::cout << std::flush;
+    exit(1);
+  }
+
+  starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
+
+  /* Initialize the ISAC and BN structs */
+  if (testNum != 8) {
+    err = WebRtcIsac_Create(&ISAC_main_inst);
+    WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
+    WebRtcIsac_SetDecSampRate(ISAC_main_inst,
+                              sampFreqKHz >= 32 ? 32000 : 16000);
+    /* Error check */
+    if (err < 0) {
+      printf("\n\n Error in create.\n\n");
+      std::cout << std::flush;
+      exit(EXIT_FAILURE);
+    }
+  }
+  BN_data.arrival_time = 0;
+  BN_data.sample_count = 0;
+  BN_data.rtp_number = 0;
+
+  /* Initialize encoder and decoder */
+  framecnt = 0;
+  endfile = 0;
+
+  if (doTransCoding) {
+    WebRtcIsac_Create(&decoderTransCoding);
+    WebRtcIsac_SetEncSampRate(decoderTransCoding, sampFreqKHz * 1000);
+    WebRtcIsac_SetDecSampRate(decoderTransCoding,
+                              sampFreqKHz >= 32 ? 32000 : 16000);
+    WebRtcIsac_DecoderInit(decoderTransCoding);
+    transCodingFile = fopen(transCodingFileName, "wb");
+    if (transCodingFile == NULL) {
+      printf("Could not open %s to output trans-coding.\n",
+             transCodingFileName);
+      exit(0);
+    }
+    strcat(transCodingFileName, ".bit");
+    transcodingBitstream = fopen(transCodingFileName, "wb");
+    if (transcodingBitstream == NULL) {
+      printf("Could not open %s to write the bit-stream of transcoder.\n",
+             transCodingFileName);
+      exit(0);
+    }
+  }
+
+  if (testNum != 1) {
+    if (WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode) < 0) {
+      printf("Error could not initialize the encoder \n");
+      std::cout << std::flush;
+      return 0;
+    }
+  }
+  if (testNum != 2)
+    WebRtcIsac_DecoderInit(ISAC_main_inst);
+  if (CodingMode == 1) {
+    err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+    if (err < 0) {
+      /* exit if returned with error */
+      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+      printf("\n\n Error in initialization (control): %d.\n\n", errtype);
+      std::cout << std::flush;
+      if (testNum == 0) {
+        exit(EXIT_FAILURE);
+      }
+    }
+  }
+
+  if ((setControlBWE) && (CodingMode == 0)) {
+    err = WebRtcIsac_ControlBwe(ISAC_main_inst, rateBPS, framesize, fixedFL);
+    if (err < 0) {
+      /* exit if returned with error */
+      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+
+      printf("\n\n Error in Control BWE: %d.\n\n", errtype);
+      std::cout << std::flush;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (payloadSize != 0) {
+    err = WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadSize);
+    if (err < 0) {
+      /* exit if returned with error */
+      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+      printf("\n\n Error in SetMaxPayloadSize: %d.\n\n", errtype);
+      std::cout << std::flush;
+      exit(EXIT_FAILURE);
+    }
+  }
+  if (payloadRate != 0) {
+    err = WebRtcIsac_SetMaxRate(ISAC_main_inst, payloadRate);
+    if (err < 0) {
+      /* exit if returned with error */
+      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+      printf("\n\n Error in SetMaxRateInBytes: %d.\n\n", errtype);
+      std::cout << std::flush;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  *speechType = 1;
+
+  std::cout << "\n" << std::flush;
+
+  length_file = 0;
+  int16_t bnIdxTC = 0;
+  int16_t jitterInfoTC = 0;
+  while (endfile == 0) {
+    /* Call init functions at random, fault test number 7 */
+    if (testNum == 7 && (rand() % 2 == 0)) {
+      err = WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
+      /* Error check */
+      if (err < 0) {
+        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+        printf("\n\n Error in encoderinit: %d.\n\n", errtype);
+        std::cout << std::flush;
+      }
+
+      WebRtcIsac_DecoderInit(ISAC_main_inst);
+    }
+
+    cur_framesmpls = 0;
+    while (1) {
+      int stream_len_int = 0;
+
+      /* Read 10 ms speech block */
+      endfile = readframe(shortdata, inp, samplesIn10Ms);
+
+      if (endfile) {
+        numFileLoop++;
+        if (numFileLoop < totFileLoop) {
+          rewind(inp);
+          framecnt = 0;
+          fprintf(stderr, "\n");
+          endfile = readframe(shortdata, inp, samplesIn10Ms);
+        }
+      }
+
+      if (testNum == 7) {
+        srand((unsigned int)time(NULL));
+      }
+
+      /* iSAC encoding */
+      if (!(testNum == 3 && framecnt == 0)) {
+        stream_len_int =
+            WebRtcIsac_Encode(ISAC_main_inst, shortdata, (uint8_t*)streamdata);
+        if ((payloadSize != 0) && (stream_len_int > payloadSize)) {
+          if (testNum == 0) {
+            printf("\n\n");
+          }
+
+          printf("\nError: Streamsize out of range %d\n",
+                 stream_len_int - payloadSize);
+          std::cout << std::flush;
+        }
+
+        WebRtcIsac_GetUplinkBw(ISAC_main_inst, &sendBN);
+
+        if (stream_len_int > 0) {
+          if (doTransCoding) {
+            int16_t indexStream;
+            uint8_t auxUW8;
+
+            /******************** Main Transcoding stream ********************/
+            WebRtcIsac_GetDownLinkBwIndex(ISAC_main_inst, &bnIdxTC,
+                                          &jitterInfoTC);
+            int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
+                ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
+                streamDataTransCoding, false);
+            if (streamLenTransCoding_int < 0) {
+              fprintf(stderr, "Error in trans-coding\n");
+              exit(0);
+            }
+            streamLenTransCoding =
+                static_cast<size_t>(streamLenTransCoding_int);
+            auxUW8 = (uint8_t)(((streamLenTransCoding & 0xFF00) >> 8) & 0x00FF);
+            if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
+                1) {
+              return -1;
+            }
+
+            auxUW8 = (uint8_t)(streamLenTransCoding & 0x00FF);
+            if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
+                1) {
+              return -1;
+            }
+
+            if (fwrite(streamDataTransCoding, sizeof(uint8_t),
+                       streamLenTransCoding,
+                       transcodingBitstream) != streamLenTransCoding) {
+              return -1;
+            }
+
+            WebRtcIsac_ReadBwIndex(streamDataTransCoding, &indexStream);
+            if (indexStream != bnIdxTC) {
+              fprintf(stderr,
+                      "Error in inserting Bandwidth index into transcoding "
+                      "stream.\n");
+              exit(0);
+            }
+            numTransCodingBytes += streamLenTransCoding;
+          }
+        }
+      } else {
+        break;
+      }
+
+      if (stream_len_int < 0) {
+        /* exit if returned with error */
+        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+        fprintf(stderr, "Error in encoder: %d.\n", errtype);
+        std::cout << std::flush;
+        exit(0);
+      }
+      stream_len = static_cast<size_t>(stream_len_int);
+
+      cur_framesmpls += samplesIn10Ms;
+      /* exit encoder loop if the encoder returned a bitstream */
+      if (stream_len != 0)
+        break;
+    }
+
+    /* read next bottleneck rate */
+    if (f_bn != NULL) {
+      if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+        /* Set pointer to beginning of file */
+        fseek(f_bn, 0L, SEEK_SET);
+        if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+          exit(0);
+        }
+      }
+      if (CodingMode == 1) {
+        WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+      }
+    }
+
+    length_file += cur_framesmpls;
+    if (cur_framesmpls == (3 * samplesIn10Ms)) {
+      maxStreamLen30 =
+          (stream_len > maxStreamLen30) ? stream_len : maxStreamLen30;
+    } else {
+      maxStreamLen60 =
+          (stream_len > maxStreamLen60) ? stream_len : maxStreamLen60;
+    }
+
+    if (!lostFrame) {
+      lostFrame = ((rand() % 100) < packetLossPercent);
+    } else {
+      lostFrame = false;
+    }
+
+    // RED.
+    if (lostFrame) {
+      int stream_len_int = WebRtcIsac_GetRedPayload(
+          ISAC_main_inst, reinterpret_cast<uint8_t*>(streamdata));
+      if (stream_len_int < 0) {
+        fprintf(stderr, "Error getting RED payload\n");
+        exit(0);
+      }
+      stream_len = static_cast<size_t>(stream_len_int);
+
+      if (doTransCoding) {
+        int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
+            ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
+            streamDataTransCoding, true);
+        if (streamLenTransCoding_int < 0) {
+          fprintf(stderr, "Error in RED trans-coding\n");
+          exit(0);
+        }
+        streamLenTransCoding = static_cast<size_t>(streamLenTransCoding_int);
+      }
+    }
+
+    /* make coded sequence to short be inreasing */
+    /* the length the decoder expects */
+    if (testNum == 4) {
+      stream_len += 10;
+    }
+
+    /* make coded sequence to long be decreasing */
+    /* the length the decoder expects */
+    if (testNum == 5) {
+      stream_len -= 10;
+    }
+
+    if (testNum == 6) {
+      srand((unsigned int)time(NULL));
+      for (i = 0; i < stream_len; i++) {
+        streamdata[i] = rand();
+      }
+    }
+
+    if (VADusage) {
+      readframe(vaddata, vadp, samplesIn10Ms * 3);
+    }
+
+    /* simulate packet handling through NetEq and the modem */
+    if (!(testNum == 3 && framecnt == 0)) {
+      get_arrival_time(cur_framesmpls, stream_len, bottleneck, &BN_data,
+                       sampFreqKHz * 1000, sampFreqKHz * 1000);
+    }
+
+    if (VADusage && (framecnt > 10 && vaddata[0] == 0)) {
+      BN_data.rtp_number--;
+    } else {
+      /* Error test number 10, garbage data */
+      if (testNum == 10) {
+        /* Test to run decoder with garbage data */
+        for (i = 0; i < stream_len; i++) {
+          streamdata[i] = (short)(streamdata[i]) + (short)rand();
+        }
+      }
+
+      if (testNum != 9) {
+        err = WebRtcIsac_UpdateBwEstimate(
+            ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
+            stream_len, BN_data.rtp_number, BN_data.sample_count,
+            BN_data.arrival_time);
+
+        if (err < 0) {
+          /* exit if returned with error */
+          errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+          if (testNum == 0) {
+            printf("\n\n");
+          }
+
+          printf("Error: in decoder: %d.", errtype);
+          std::cout << std::flush;
+          if (testNum == 0) {
+            printf("\n\n");
+          }
+        }
+      }
+
+      /* Call getFramelen, only used here for function test */
+      err = WebRtcIsac_ReadFrameLen(
+          ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata), &FL);
+      if (err < 0) {
+        /* exit if returned with error */
+        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+        printf("    Error: in getFrameLen %d.", errtype);
+        std::cout << std::flush;
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+      }
+
+      // iSAC decoding
+
+      if (lostFrame) {
+        declen = WebRtcIsac_DecodeRcu(
+            ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
+            stream_len, decoded, speechType);
+
+        if (doTransCoding) {
+          declenTC =
+              WebRtcIsac_DecodeRcu(decoderTransCoding, streamDataTransCoding,
+                                   streamLenTransCoding, decodedTC, speechType);
+        }
+      } else {
+        declen = WebRtcIsac_Decode(ISAC_main_inst,
+                                   reinterpret_cast<const uint8_t*>(streamdata),
+                                   stream_len, decoded, speechType);
+        if (doTransCoding) {
+          declenTC =
+              WebRtcIsac_Decode(decoderTransCoding, streamDataTransCoding,
+                                streamLenTransCoding, decodedTC, speechType);
+        }
+      }
+
+      if (declen < 0) {
+        /* exit if returned with error */
+        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+        printf("    Error: in decoder %d.", errtype);
+        std::cout << std::flush;
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+      }
+
+      if (declenTC < 0) {
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+        printf("    Error: in decoding the transcoded stream");
+        std::cout << std::flush;
+        if (testNum == 0) {
+          printf("\n\n");
+        }
+      }
+    }
+    /* Write decoded speech frame to file */
+    if ((declen > 0) && (numFileLoop == 0)) {
+      if (fwrite(decoded, sizeof(int16_t), declen, outp) !=
+          static_cast<size_t>(declen)) {
+        return -1;
+      }
+    }
+
+    if ((declenTC > 0) && (numFileLoop == 0)) {
+      if (fwrite(decodedTC, sizeof(int16_t), declen, transCodingFile) !=
+          static_cast<size_t>(declen)) {
+        return -1;
+      }
+    }
+
+    fprintf(stderr, "\rframe = %5d  ", framecnt);
+    fflush(stderr);
+    framecnt++;
+
+    /* Error test number 10, garbage data */
+    // if (testNum == 10)
+    // {
+    //   /* Test to run decoder with garbage data */
+    //   if ((seedfile = fopen(SEED_FILE, "a+t")) == NULL) {
+    //     fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
+    //   } else {
+    //     fprintf(seedfile, "ok\n\n");
+    //     fclose(seedfile);
+    //   }
+    // }
+    /* Error test number 10, garbage data */
+    // if (testNum == 10) {
+    //   /* Test to run decoder with garbage data */
+    //   for (i = 0; i < stream_len; i++) {
+    //     streamdata[i] = (short) (streamdata[i] + (short) rand());
+    //   }
+    // }
+
+    totalsmpls += declen;
+    totalbits += 8 * stream_len;
+#if !defined(NDEBUG)
+    kbps = ((double)sampFreqKHz * 1000.) / ((double)cur_framesmpls) * 8.0 *
+           stream_len / 1000.0;  // kbits/s
+    fy = fopen("bit_rate.dat", "a");
+    fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
+    fclose(fy);
+
+#endif
+  }
+  printf("\n");
+  printf("total bits               = %zu bits\n", totalbits);
+  printf("measured average bitrate = %0.3f kbits/s\n",
+         (double)totalbits * (sampFreqKHz) / totalsmpls);
+  if (doTransCoding) {
+    printf("Transcoding average bit-rate = %0.3f kbps\n",
+           (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
+    fclose(transCodingFile);
+  }
+  printf("\n");
+
+  /* Runtime statistics */
+  runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
+  length_file = length_file / (sampFreqKHz * 1000.);
+
+  printf("\n\nLength of speech file: %.1f s\n", length_file);
+  printf("Time to run iSAC:      %.2f s (%.2f %% of realtime)\n\n", runtime,
+         (100 * runtime / length_file));
+
+  if (maxStreamLen30 != 0) {
+    printf(
+        "Maximum payload size 30ms Frames %zu"
+        " bytes (%0.3f kbps)\n",
+        maxStreamLen30, maxStreamLen30 * 8 / 30.);
+  }
+  if (maxStreamLen60 != 0) {
+    printf(
+        "Maximum payload size 60ms Frames %zu"
+        " bytes (%0.3f kbps)\n",
+        maxStreamLen60, maxStreamLen60 * 8 / 60.);
+  }
+  // fprintf(stderr, "\n");
+
+  fprintf(stderr, "   %.1f s", length_file);
+  fprintf(stderr, "   %0.1f kbps",
+          (double)totalbits * (sampFreqKHz) / totalsmpls);
+  if (maxStreamLen30 != 0) {
+    fprintf(stderr, "   plmax-30ms %zu bytes (%0.0f kbps)", maxStreamLen30,
+            maxStreamLen30 * 8 / 30.);
+  }
+  if (maxStreamLen60 != 0) {
+    fprintf(stderr, "   plmax-60ms %zu bytes (%0.0f kbps)", maxStreamLen60,
+            maxStreamLen60 * 8 / 60.);
+  }
+  if (doTransCoding) {
+    fprintf(stderr, "  transcoding rate %.0f kbps",
+            (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
+  }
+
+  fclose(inp);
+  fclose(outp);
+  WebRtcIsac_Free(ISAC_main_inst);
+
+  exit(0);
+}
diff --git a/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc b/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc
new file mode 100644
index 0000000..549163f
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc
@@ -0,0 +1,425 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// SwitchingSampRate.cpp : Defines the entry point for the console
+// application.
+//
+
+#include <iostream>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+#define MAX_FILE_NAME 500
+#define MAX_NUM_CLIENTS 2
+
+#define NUM_CLIENTS 2
+
+int main(int argc, char* argv[]) {
+  char fileNameWB[MAX_FILE_NAME];
+  char fileNameSWB[MAX_FILE_NAME];
+
+  char outFileName[MAX_NUM_CLIENTS][MAX_FILE_NAME];
+
+  FILE* inFile[MAX_NUM_CLIENTS];
+  FILE* outFile[MAX_NUM_CLIENTS];
+
+  ISACStruct* codecInstance[MAX_NUM_CLIENTS];
+  int32_t resamplerState[MAX_NUM_CLIENTS][8];
+
+  int encoderSampRate[MAX_NUM_CLIENTS];
+
+  int minBn = 16000;
+  int maxBn = 56000;
+
+  int bnWB = 32000;
+  int bnSWB = 56000;
+
+  strcpy(outFileName[0], "switchSampRate_out1.pcm");
+  strcpy(outFileName[1], "switchSampRate_out2.pcm");
+
+  short clientCntr;
+
+  size_t lenEncodedInBytes[MAX_NUM_CLIENTS];
+  unsigned int lenAudioIn10ms[MAX_NUM_CLIENTS];
+  size_t lenEncodedInBytesTmp[MAX_NUM_CLIENTS];
+  unsigned int lenAudioIn10msTmp[MAX_NUM_CLIENTS];
+  BottleNeckModel* packetData[MAX_NUM_CLIENTS];
+
+  char versionNumber[100];
+  short samplesIn10ms[MAX_NUM_CLIENTS];
+  int bottleneck[MAX_NUM_CLIENTS];
+
+  printf("\n\n");
+  printf("____________________________________________\n\n");
+  WebRtcIsac_version(versionNumber);
+  printf("    iSAC-swb version %s\n", versionNumber);
+  printf("____________________________________________\n");
+
+  fileNameWB[0] = '\0';
+  fileNameSWB[0] = '\0';
+
+  char myFlag[20];
+  strcpy(myFlag, "-wb");
+  // READ THE WIDEBAND AND SUPER-WIDEBAND FILE NAMES
+  if (readParamString(argc, argv, myFlag, fileNameWB, MAX_FILE_NAME) <= 0) {
+    printf("No wideband file is specified");
+  }
+
+  strcpy(myFlag, "-swb");
+  if (readParamString(argc, argv, myFlag, fileNameSWB, MAX_FILE_NAME) <= 0) {
+    printf("No super-wideband file is specified");
+  }
+
+  // THE FIRST CLIENT STARTS IN WIDEBAND
+  encoderSampRate[0] = 16000;
+  OPEN_FILE_RB(inFile[0], fileNameWB);
+
+  // THE SECOND CLIENT STARTS IN SUPER-WIDEBAND
+  encoderSampRate[1] = 32000;
+  OPEN_FILE_RB(inFile[1], fileNameSWB);
+
+  strcpy(myFlag, "-I");
+  short codingMode = readSwitch(argc, argv, myFlag);
+
+  for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+    codecInstance[clientCntr] = NULL;
+
+    printf("\n");
+    printf("Client %d\n", clientCntr + 1);
+    printf("---------\n");
+    printf("Starting %s", (encoderSampRate[clientCntr] == 16000)
+                              ? "wideband"
+                              : "super-wideband");
+
+    // Open output File Name
+    OPEN_FILE_WB(outFile[clientCntr], outFileName[clientCntr]);
+    printf("Output File...................... %s\n", outFileName[clientCntr]);
+
+    samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10;
+
+    if (codingMode == 1) {
+      bottleneck[clientCntr] = (clientCntr) ? bnSWB : bnWB;
+    } else {
+      bottleneck[clientCntr] = (clientCntr) ? minBn : maxBn;
+    }
+
+    printf("Bottleneck....................... %0.3f kbits/sec \n",
+           bottleneck[clientCntr] / 1000.0);
+
+    // coding-mode
+    printf(
+        "Encoding Mode.................... %s\n",
+        (codingMode == 1) ? "Channel-Independent (Instantaneous)" : "Adaptive");
+
+    lenEncodedInBytes[clientCntr] = 0;
+    lenAudioIn10ms[clientCntr] = 0;
+    lenEncodedInBytesTmp[clientCntr] = 0;
+    lenAudioIn10msTmp[clientCntr] = 0;
+
+    packetData[clientCntr] = (BottleNeckModel*)new (BottleNeckModel);
+    if (packetData[clientCntr] == NULL) {
+      printf("Could not allocate memory for packetData \n");
+      return -1;
+    }
+    memset(packetData[clientCntr], 0, sizeof(BottleNeckModel));
+    memset(resamplerState[clientCntr], 0, sizeof(int32_t) * 8);
+  }
+
+  for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+    // Create
+    if (WebRtcIsac_Create(&codecInstance[clientCntr])) {
+      printf("Could not creat client %d\n", clientCntr + 1);
+      return -1;
+    }
+
+    WebRtcIsac_SetEncSampRate(codecInstance[clientCntr],
+                              encoderSampRate[clientCntr]);
+
+    WebRtcIsac_SetDecSampRate(
+        codecInstance[clientCntr],
+        encoderSampRate[clientCntr + (1 - ((clientCntr & 1) << 1))]);
+
+    // Initialize Encoder
+    if (WebRtcIsac_EncoderInit(codecInstance[clientCntr], codingMode) < 0) {
+      printf("Could not initialize client, %d\n", clientCntr + 1);
+      return -1;
+    }
+
+    WebRtcIsac_DecoderInit(codecInstance[clientCntr]);
+
+    // setup Rate if in Instantaneous mode
+    if (codingMode != 0) {
+      // ONLY Clients who are not in Adaptive mode
+      if (WebRtcIsac_Control(codecInstance[clientCntr], bottleneck[clientCntr],
+                             30) < 0) {
+        printf("Could not setup bottleneck and frame-size for client %d\n",
+               clientCntr + 1);
+        return -1;
+      }
+    }
+  }
+
+  size_t streamLen;
+  short numSamplesRead;
+  size_t lenDecodedAudio;
+  short senderIdx;
+  short receiverIdx;
+
+  printf("\n");
+  short num10ms[MAX_NUM_CLIENTS];
+  memset(num10ms, 0, sizeof(short) * MAX_NUM_CLIENTS);
+  FILE* arrivalTimeFile1 = fopen("arrivalTime1.dat", "wb");
+  FILE* arrivalTimeFile2 = fopen("arrivalTime2.dat", "wb");
+  short numPrint[MAX_NUM_CLIENTS];
+  memset(numPrint, 0, sizeof(short) * MAX_NUM_CLIENTS);
+
+  // Audio Buffers
+  short silence10ms[10 * 32];
+  memset(silence10ms, 0, 320 * sizeof(short));
+  short audioBuff10ms[10 * 32];
+  short audioBuff60ms[60 * 32];
+  short resampledAudio60ms[60 * 32];
+
+  unsigned short bitStream[600 + 600];
+  short speechType[1];
+
+  short numSampFreqChanged = 0;
+  while (numSampFreqChanged < 10) {
+    for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+      // Encoding/decoding for this pair of clients, if there is
+      // audio for any of them
+      // if(audioLeft[clientCntr] || audioLeft[clientCntr + 1])
+      //{
+      // for(pairCntr = 0; pairCntr < 2; pairCntr++)
+      //{
+      senderIdx = clientCntr;        // + pairCntr;
+      receiverIdx = 1 - clientCntr;  //  + (1 - pairCntr);
+
+      // if(num10ms[senderIdx] > 6)
+      //{
+      //    printf("Too many frames read for client %d",
+      //        senderIdx + 1);
+      //    return -1;
+      //}
+
+      numSamplesRead =
+          (short)fread(audioBuff10ms, sizeof(short), samplesIn10ms[senderIdx],
+                       inFile[senderIdx]);
+      if (numSamplesRead != samplesIn10ms[senderIdx]) {
+        // file finished switch encoder sampling frequency.
+        printf("Changing Encoder Sampling frequency in client %d to ",
+               senderIdx + 1);
+        fclose(inFile[senderIdx]);
+        numSampFreqChanged++;
+        if (encoderSampRate[senderIdx] == 16000) {
+          printf("super-wideband.\n");
+          OPEN_FILE_RB(inFile[senderIdx], fileNameSWB);
+          encoderSampRate[senderIdx] = 32000;
+        } else {
+          printf("wideband.\n");
+          OPEN_FILE_RB(inFile[senderIdx], fileNameWB);
+          encoderSampRate[senderIdx] = 16000;
+        }
+        WebRtcIsac_SetEncSampRate(codecInstance[senderIdx],
+                                  encoderSampRate[senderIdx]);
+        WebRtcIsac_SetDecSampRate(codecInstance[receiverIdx],
+                                  encoderSampRate[senderIdx]);
+
+        samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10;
+
+        numSamplesRead =
+            (short)fread(audioBuff10ms, sizeof(short), samplesIn10ms[senderIdx],
+                         inFile[senderIdx]);
+        if (numSamplesRead != samplesIn10ms[senderIdx]) {
+          printf(" File %s for client %d has not enough audio\n",
+                 (encoderSampRate[senderIdx] == 16000) ? "wideband"
+                                                       : "super-wideband",
+                 senderIdx + 1);
+          return -1;
+        }
+      }
+      num10ms[senderIdx]++;
+
+      // sanity check
+      // if(num10ms[senderIdx] > 6)
+      //{
+      //    printf("Client %d has got more than 60 ms audio and encoded no
+      //    packet.\n",
+      //        senderIdx);
+      //    return -1;
+      //}
+
+      // Encode
+
+      int streamLen_int = WebRtcIsac_Encode(codecInstance[senderIdx],
+                                            audioBuff10ms, (uint8_t*)bitStream);
+      int16_t ggg;
+      if (streamLen_int > 0) {
+        if ((WebRtcIsac_ReadFrameLen(
+                codecInstance[receiverIdx],
+                reinterpret_cast<const uint8_t*>(bitStream), &ggg)) < 0)
+          printf("ERROR\n");
+      }
+
+      // Sanity check
+      if (streamLen_int < 0) {
+        printf(" Encoder error in client %d \n", senderIdx + 1);
+        return -1;
+      }
+      streamLen = static_cast<size_t>(streamLen_int);
+
+      if (streamLen > 0) {
+        // Packet generated; model sending through a channel, do bandwidth
+        // estimation at the receiver and decode.
+        lenEncodedInBytes[senderIdx] += streamLen;
+        lenAudioIn10ms[senderIdx] += (unsigned int)num10ms[senderIdx];
+        lenEncodedInBytesTmp[senderIdx] += streamLen;
+        lenAudioIn10msTmp[senderIdx] += (unsigned int)num10ms[senderIdx];
+
+        // Print after ~5 sec.
+        if (lenAudioIn10msTmp[senderIdx] >= 100) {
+          numPrint[senderIdx]++;
+          printf("  %d,  %6.3f => %6.3f ", senderIdx + 1,
+                 bottleneck[senderIdx] / 1000.0,
+                 lenEncodedInBytesTmp[senderIdx] * 0.8 /
+                     lenAudioIn10msTmp[senderIdx]);
+
+          if (codingMode == 0) {
+            int32_t bn;
+            WebRtcIsac_GetUplinkBw(codecInstance[senderIdx], &bn);
+            printf("[%d] ", bn);
+          }
+          // int16_t rateIndexLB;
+          // int16_t rateIndexUB;
+          // WebRtcIsac_GetDownLinkBwIndex(codecInstance[receiverIdx],
+          //    &rateIndexLB, &rateIndexUB);
+          // printf(" (%2d, %2d) ", rateIndexLB, rateIndexUB);
+
+          std::cout << std::flush;
+          lenEncodedInBytesTmp[senderIdx] = 0;
+          lenAudioIn10msTmp[senderIdx] = 0;
+          // if(senderIdx == (NUM_CLIENTS - 1))
+          //{
+          printf("  %0.1f \n", lenAudioIn10ms[senderIdx] * 10. / 1000);
+          //}
+
+          // After ~20 sec change the bottleneck.
+          //    if((numPrint[senderIdx] == 4) && (codingMode == 0))
+          //    {
+          //        numPrint[senderIdx] = 0;
+          //        if(codingMode == 0)
+          //        {
+          //            int newBottleneck = bottleneck[senderIdx] +
+          //                (bottleneckChange[senderIdx] * 1000);
+
+          //            if(bottleneckChange[senderIdx] > 0)
+          //            {
+          //                if(newBottleneck >maxBn)
+          //                {
+          //                    bottleneckChange[senderIdx] = -1;
+          //                    newBottleneck = bottleneck[senderIdx] +
+          //                        (bottleneckChange[senderIdx] * 1000);
+          //                    if(newBottleneck > minBn)
+          //                    {
+          //                        bottleneck[senderIdx] = newBottleneck;
+          //                    }
+          //                }
+          //                else
+          //                {
+          //                    bottleneck[senderIdx] = newBottleneck;
+          //                }
+          //            }
+          //            else
+          //            {
+          //                if(newBottleneck < minBn)
+          //                {
+          //                    bottleneckChange[senderIdx] = 1;
+          //                    newBottleneck = bottleneck[senderIdx] +
+          //                        (bottleneckChange[senderIdx] * 1000);
+          //                    if(newBottleneck < maxBn)
+          //                    {
+          //                        bottleneck[senderIdx] = newBottleneck;
+          //                    }
+          //                }
+          //                else
+          //                {
+          //                    bottleneck[senderIdx] = newBottleneck;
+          //                }
+          //            }
+          //        }
+          //    }
+        }
+
+        // model a channel of given bottleneck, to get the receive timestamp
+        get_arrival_time(num10ms[senderIdx] * samplesIn10ms[senderIdx],
+                         streamLen, bottleneck[senderIdx],
+                         packetData[senderIdx],
+                         encoderSampRate[senderIdx] * 1000,
+                         encoderSampRate[senderIdx] * 1000);
+
+        // Write the arrival time.
+        if (senderIdx == 0) {
+          if (fwrite(&(packetData[senderIdx]->arrival_time),
+                     sizeof(unsigned int), 1, arrivalTimeFile1) != 1) {
+            return -1;
+          }
+        } else {
+          if (fwrite(&(packetData[senderIdx]->arrival_time),
+                     sizeof(unsigned int), 1, arrivalTimeFile2) != 1) {
+            return -1;
+          }
+        }
+
+        // BWE
+        if (WebRtcIsac_UpdateBwEstimate(
+                codecInstance[receiverIdx],
+                reinterpret_cast<const uint8_t*>(bitStream), streamLen,
+                packetData[senderIdx]->rtp_number,
+                packetData[senderIdx]->sample_count,
+                packetData[senderIdx]->arrival_time) < 0) {
+          printf(" BWE Error at client %d \n", receiverIdx + 1);
+          return -1;
+        }
+        /**/
+        // Decode
+        int lenDecodedAudio_int =
+            WebRtcIsac_Decode(codecInstance[receiverIdx],
+                              reinterpret_cast<const uint8_t*>(bitStream),
+                              streamLen, audioBuff60ms, speechType);
+        if (lenDecodedAudio_int < 0) {
+          printf(" Decoder error in client %d \n", receiverIdx + 1);
+          return -1;
+        }
+        lenDecodedAudio = static_cast<size_t>(lenDecodedAudio_int);
+
+        if (encoderSampRate[senderIdx] == 16000) {
+          WebRtcSpl_UpsampleBy2(audioBuff60ms, lenDecodedAudio,
+                                resampledAudio60ms,
+                                resamplerState[receiverIdx]);
+          if (fwrite(resampledAudio60ms, sizeof(short), lenDecodedAudio << 1,
+                     outFile[receiverIdx]) != lenDecodedAudio << 1) {
+            return -1;
+          }
+        } else {
+          if (fwrite(audioBuff60ms, sizeof(short), lenDecodedAudio,
+                     outFile[receiverIdx]) != lenDecodedAudio) {
+            return -1;
+          }
+        }
+        num10ms[senderIdx] = 0;
+      }
+      //}
+      //}
+    }
+  }
+  return 0;
+}
diff --git a/modules/audio_coding/codecs/isac/main/test/simpleKenny.c b/modules/audio_coding/codecs/isac/main/test/simpleKenny.c
new file mode 100644
index 0000000..4446ff7
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/test/simpleKenny.c
@@ -0,0 +1,461 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* kenny.c  - Main function for the iSAC coder */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "windows.h"
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000
+#endif
+#endif
+
+#include <math.h>
+
+/* include API */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES_SWB 1920
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_SWB_10ms 320
+#define FRAMESAMPLES_WB_10ms 160
+
+/* sampling frequency (Hz) */
+#define FS_SWB 32000
+#define FS_WB 16000
+
+unsigned long framecnt = 0;
+
+int main(int argc, char* argv[]) {
+  //--- File IO ----
+  FILE* inp;
+  FILE* outp;
+  char inname[500];
+  char outname[500];
+
+  /* Runtime statistics */
+  double rate;
+  double rateRCU;
+  size_t totalbits = 0;
+  unsigned long totalBitsRCU = 0;
+  unsigned long totalsmpls = 0;
+
+  int32_t bottleneck = 39;
+  int frameSize = 30; /* ms */
+  int16_t codingMode = 1;
+  int16_t shortdata[FRAMESAMPLES_SWB_10ms];
+  int16_t decoded[MAX_FRAMESAMPLES_SWB];
+  int16_t speechType[1];
+  int16_t payloadLimit;
+  int32_t rateLimit;
+  ISACStruct* ISAC_main_inst;
+
+  size_t stream_len = 0;
+  int declen = 0;
+  int16_t err;
+  int cur_framesmpls;
+  int endfile;
+#ifdef WIN32
+  double length_file;
+  double runtime;
+  char outDrive[10];
+  char outPath[500];
+  char outPrefix[500];
+  char outSuffix[500];
+  char bitrateFileName[500];
+  FILE* bitrateFile;
+  double starttime;
+  double rateLB = 0;
+  double rateUB = 0;
+#endif
+  FILE* histFile;
+  FILE* averageFile;
+  int sampFreqKHz;
+  int samplesIn10Ms;
+  size_t maxStreamLen = 0;
+  char histFileName[500];
+  char averageFileName[500];
+  unsigned int hist[600];
+  double tmpSumStreamLen = 0;
+  unsigned int packetCntr = 0;
+  unsigned int lostPacketCntr = 0;
+  uint8_t payload[1200];
+  uint8_t payloadRCU[1200];
+  uint16_t packetLossPercent = 0;
+  int16_t rcuStreamLen = 0;
+  int onlyEncode;
+  int onlyDecode;
+
+  BottleNeckModel packetData;
+  packetData.arrival_time = 0;
+  packetData.sample_count = 0;
+  packetData.rtp_number = 0;
+  memset(hist, 0, sizeof(hist));
+
+  /* handling wrong input arguments in the command line */
+  if (argc < 5) {
+    printf("\n\nWrong number of arguments or flag values.\n\n");
+
+    printf("Usage:\n\n");
+    printf("%s infile outfile -bn bottleneck [options]\n\n", argv[0]);
+    printf("with:\n");
+    printf("-I.............. indicates encoding in instantaneous mode.\n");
+    printf("-bn bottleneck.. the value of the bottleneck in bit/sec, e.g.\n");
+    printf("                 39742, in instantaneous (channel-independent)\n");
+    printf("                 mode.\n\n");
+    printf("infile.......... Normal speech input file\n\n");
+    printf("outfile......... Speech output file\n\n");
+    printf("OPTIONS\n");
+    printf("-------\n");
+    printf("-fs sampFreq.... sampling frequency of codec 16 or 32 (default)\n");
+    printf("                 kHz.\n");
+    printf("-plim payloadLim payload limit in bytes, default is the maximum\n");
+    printf("                 possible.\n");
+    printf("-rlim rateLim... rate limit in bits/sec, default is the maximum\n");
+    printf("                 possible.\n");
+    printf("-h file......... record histogram and *append* to 'file'.\n");
+    printf("-ave file....... record average rate of 3 sec intervales and\n");
+    printf("                 *append* to 'file'.\n");
+    printf("-ploss.......... packet-loss percentage.\n");
+    printf("-enc............ do only encoding and store the bit-stream\n");
+    printf("-dec............ the input file is a bit-stream, decode it.\n\n");
+    printf("Example usage:\n\n");
+    printf("%s speechIn.pcm speechOut.pcm -B 40000 -fs 32\n\n", argv[0]);
+
+    exit(0);
+  }
+
+  /* Get Bottleneck value */
+  bottleneck = readParamInt(argc, argv, "-bn", 50000);
+  fprintf(stderr, "\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+
+  /* Get Input and Output files */
+  sscanf(argv[1], "%s", inname);
+  sscanf(argv[2], "%s", outname);
+  codingMode = readSwitch(argc, argv, "-I");
+  sampFreqKHz = (int16_t)readParamInt(argc, argv, "-fs", 32);
+  if (readParamString(argc, argv, "-h", histFileName, 500) > 0) {
+    histFile = fopen(histFileName, "a");
+    if (histFile == NULL) {
+      printf("cannot open hist file %s", histFileName);
+      exit(0);
+    }
+  } else {
+    // NO recording of hitstogram
+    histFile = NULL;
+  }
+
+  packetLossPercent = readParamInt(argc, argv, "-ploss", 0);
+
+  if (readParamString(argc, argv, "-ave", averageFileName, 500) > 0) {
+    averageFile = fopen(averageFileName, "a");
+    if (averageFile == NULL) {
+      printf("cannot open file to write rate %s", averageFileName);
+      exit(0);
+    }
+  } else {
+    averageFile = NULL;
+  }
+
+  onlyEncode = readSwitch(argc, argv, "-enc");
+  onlyDecode = readSwitch(argc, argv, "-dec");
+
+  switch (sampFreqKHz) {
+    case 16: {
+      samplesIn10Ms = 160;
+      break;
+    }
+    case 32: {
+      samplesIn10Ms = 320;
+      break;
+    }
+    default:
+      printf("A sampling frequency of %d kHz is not supported, valid values are"
+             " 8 and 16.\n", sampFreqKHz);
+      exit(-1);
+  }
+  payloadLimit = (int16_t)readParamInt(argc, argv, "-plim", 400);
+  rateLimit = readParamInt(argc, argv, "-rlim", 106800);
+
+  if ((inp = fopen(inname, "rb")) == NULL) {
+    printf("  iSAC: Cannot read file %s.\n", inname);
+    exit(1);
+  }
+  if ((outp = fopen(outname, "wb")) == NULL) {
+    printf("  iSAC: Cannot write file %s.\n", outname);
+    exit(1);
+  }
+
+#ifdef WIN32
+  _splitpath(outname, outDrive, outPath, outPrefix, outSuffix);
+  _makepath(bitrateFileName, outDrive, outPath, "bitrate", ".txt");
+
+  bitrateFile = fopen(bitrateFileName, "a");
+  fprintf(bitrateFile, "%%  %s  \n", inname);
+#endif
+
+  printf("\n");
+  printf("Input.................... %s\n", inname);
+  printf("Output................... %s\n", outname);
+  printf("Encoding Mode............ %s\n",
+         (codingMode == 1) ? "Channel-Independent" : "Channel-Adaptive");
+  printf("Bottleneck............... %d bits/sec\n", bottleneck);
+  printf("Packet-loss Percentage... %d\n", packetLossPercent);
+  printf("\n");
+
+#ifdef WIN32
+  starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
+#endif
+
+  /* Initialize the ISAC and BN structs */
+  err = WebRtcIsac_Create(&ISAC_main_inst);
+
+  WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
+  WebRtcIsac_SetDecSampRate(ISAC_main_inst, sampFreqKHz >= 32 ? 32000 : 16000);
+  /* Error check */
+  if (err < 0) {
+    fprintf(stderr, "\n\n Error in create.\n\n");
+    exit(EXIT_FAILURE);
+  }
+
+  framecnt = 0;
+  endfile = 0;
+
+  /* Initialize encoder and decoder */
+  if (WebRtcIsac_EncoderInit(ISAC_main_inst, codingMode) < 0) {
+    printf("cannot initialize encoder\n");
+    return -1;
+  }
+  WebRtcIsac_DecoderInit(ISAC_main_inst);
+
+  if (codingMode == 1) {
+    if (WebRtcIsac_Control(ISAC_main_inst, bottleneck, frameSize) < 0) {
+      printf("cannot set bottleneck\n");
+      return -1;
+    }
+  } else {
+    if (WebRtcIsac_ControlBwe(ISAC_main_inst, 15000, 30, 1) < 0) {
+      printf("cannot configure BWE\n");
+      return -1;
+    }
+  }
+
+  if (WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadLimit) < 0) {
+    printf("cannot set maximum payload size %d.\n", payloadLimit);
+    return -1;
+  }
+
+  if (rateLimit < 106800) {
+    if (WebRtcIsac_SetMaxRate(ISAC_main_inst, rateLimit) < 0) {
+      printf("cannot set the maximum rate %d.\n", rateLimit);
+      return -1;
+    }
+  }
+
+  while (endfile == 0) {
+    fprintf(stderr, "  \rframe = %7li", framecnt);
+
+    //============== Readind from the file and encoding =================
+    cur_framesmpls = 0;
+    stream_len = 0;
+
+    if (onlyDecode) {
+      uint8_t auxUW8;
+      if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
+        break;
+      }
+      stream_len = auxUW8 << 8;
+      if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
+        break;
+      }
+      stream_len |= auxUW8;
+      if (fread(payload, 1, stream_len, inp) < stream_len) {
+        printf("last payload is corrupted\n");
+        break;
+      }
+    } else {
+      while (stream_len == 0) {
+        int stream_len_int;
+
+        // Read 10 ms speech block
+        endfile = readframe(shortdata, inp, samplesIn10Ms);
+        if (endfile) {
+          break;
+        }
+        cur_framesmpls += samplesIn10Ms;
+
+        //-------- iSAC encoding ---------
+        stream_len_int = WebRtcIsac_Encode(ISAC_main_inst, shortdata, payload);
+
+        if (stream_len_int < 0) {
+          // exit if returned with error
+          // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+          fprintf(stderr, "\nError in encoder\n");
+          getc(stdin);
+          exit(EXIT_FAILURE);
+        }
+        stream_len = (size_t)stream_len_int;
+      }
+      //===================================================================
+      if (endfile) {
+        break;
+      }
+
+      rcuStreamLen = WebRtcIsac_GetRedPayload(ISAC_main_inst, payloadRCU);
+      if (rcuStreamLen < 0) {
+        fprintf(stderr, "\nError getting RED payload\n");
+        getc(stdin);
+        exit(EXIT_FAILURE);
+      }
+
+      get_arrival_time(cur_framesmpls, stream_len, bottleneck, &packetData,
+                       sampFreqKHz * 1000, sampFreqKHz * 1000);
+      if (WebRtcIsac_UpdateBwEstimate(
+              ISAC_main_inst, payload, stream_len, packetData.rtp_number,
+              packetData.sample_count, packetData.arrival_time) < 0) {
+        printf(" BWE Error at client\n");
+        return -1;
+      }
+    }
+
+    if (endfile) {
+      break;
+    }
+
+    maxStreamLen = (stream_len > maxStreamLen) ? stream_len : maxStreamLen;
+    packetCntr++;
+
+    hist[stream_len]++;
+    if (averageFile != NULL) {
+      tmpSumStreamLen += stream_len;
+      if (packetCntr == 100) {
+        // kbps
+        fprintf(averageFile, "%8.3f ",
+                tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
+        packetCntr = 0;
+        tmpSumStreamLen = 0;
+      }
+    }
+
+    if (onlyEncode) {
+      uint8_t auxUW8;
+      auxUW8 = (uint8_t)(((stream_len & 0x7F00) >> 8) & 0xFF);
+      if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
+        return -1;
+      }
+
+      auxUW8 = (uint8_t)(stream_len & 0xFF);
+      if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
+        return -1;
+      }
+      if (fwrite(payload, 1, stream_len, outp) != stream_len) {
+        return -1;
+      }
+    } else {
+      //======================= iSAC decoding ===========================
+
+      if ((rand() % 100) < packetLossPercent) {
+        declen = WebRtcIsac_DecodeRcu(ISAC_main_inst, payloadRCU,
+                                      (size_t)rcuStreamLen, decoded,
+                                      speechType);
+        lostPacketCntr++;
+      } else {
+        declen = WebRtcIsac_Decode(ISAC_main_inst, payload, stream_len, decoded,
+                                   speechType);
+      }
+      if (declen <= 0) {
+        // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+        fprintf(stderr, "\nError in decoder.\n");
+        getc(stdin);
+        exit(1);
+      }
+
+      // Write decoded speech frame to file
+      if (fwrite(decoded, sizeof(int16_t), declen, outp) != (size_t)declen) {
+        return -1;
+      }
+      cur_framesmpls = declen;
+    }
+    // Update Statistics
+    framecnt++;
+    totalsmpls += cur_framesmpls;
+    if (stream_len > 0) {
+      totalbits += 8 * stream_len;
+    }
+    if (rcuStreamLen > 0) {
+      totalBitsRCU += 8 * rcuStreamLen;
+    }
+  }
+
+  rate = ((double)totalbits * (sampFreqKHz)) / (double)totalsmpls;
+  rateRCU = ((double)totalBitsRCU * (sampFreqKHz)) / (double)totalsmpls;
+
+  printf("\n\n");
+  printf("Sampling Rate............... %d kHz\n", sampFreqKHz);
+  printf("Payload Limit............... %d bytes \n", payloadLimit);
+  printf("Rate Limit.................. %d bits/sec \n", rateLimit);
+
+#ifdef WIN32
+  fprintf(bitrateFile, "%d  %10lu     %d     %6.3f  %6.3f    %6.3f\n",
+          sampFreqKHz, framecnt, bottleneck, rateLB, rateUB, rate);
+  fclose(bitrateFile);
+#endif  // WIN32
+
+  printf("\n");
+  printf("Measured bit-rate........... %0.3f kbps\n", rate);
+  printf("Measured RCU bit-ratre...... %0.3f kbps\n", rateRCU);
+  printf("Maximum bit-rate/payloadsize %0.3f / %zu\n",
+         maxStreamLen * 8 / 0.03, maxStreamLen);
+  printf("Measured packet-loss........ %0.1f%% \n",
+         100.0f * (float)lostPacketCntr / (float)packetCntr);
+
+  printf("\n");
+
+/* Runtime statistics */
+#ifdef WIN32
+  runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
+  length_file = ((double)framecnt * (double)declen / (sampFreqKHz * 1000));
+  printf("Length of speech file....... %.1f s\n", length_file);
+  printf("Time to run iSAC............ %.2f s (%.2f %% of realtime)\n\n",
+         runtime, (100 * runtime / length_file));
+#endif
+  printf("\n\n_______________________________________________\n");
+
+  if (histFile != NULL) {
+    int n;
+    for (n = 0; n < 600; n++) {
+      fprintf(histFile, "%6d ", hist[n]);
+    }
+    fprintf(histFile, "\n");
+    fclose(histFile);
+  }
+  if (averageFile != NULL) {
+    if (packetCntr > 0) {
+      fprintf(averageFile, "%8.3f ",
+              tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
+    }
+    fprintf(averageFile, "\n");
+    fclose(averageFile);
+  }
+
+  fclose(inp);
+  fclose(outp);
+
+  WebRtcIsac_Free(ISAC_main_inst);
+
+  exit(0);
+}
diff --git a/modules/audio_coding/codecs/isac/main/util/utility.c b/modules/audio_coding/codecs/isac/main/util/utility.c
new file mode 100644
index 0000000..56547b1
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/util/utility.c
@@ -0,0 +1,179 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* function for reading audio data from PCM file */
+int
+readframe(
+    short* data,
+    FILE*  inp,
+    int    length)
+{
+    short k, rlen, status = 0;
+	unsigned char* ptrUChar;
+	ptrUChar = (unsigned char*)data;
+
+    rlen = (short)fread(data, sizeof(short), length, inp);
+    if (rlen < length) {
+        for (k = rlen; k < length; k++)
+            data[k] = 0;
+        status = 1;
+    }
+
+	// Assuming that our PCM files are written in Intel machines
+	for(k = 0; k < length; k++)
+	{
+		data[k] = (short)ptrUChar[k<<1] | ((((short)ptrUChar[(k<<1) + 1]) << 8) & 0xFF00);
+	}
+
+    return status;
+}
+
+short
+readSwitch(
+    int   argc,
+    char* argv[],
+    char* strID)
+{
+    short n;
+    for(n = 0; n < argc; n++)
+    {
+        if(strcmp(argv[n], strID) == 0)
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+double
+readParamDouble(
+    int    argc,
+    char*  argv[],
+    char*  strID,
+    double defaultVal)
+{
+    double returnVal = defaultVal;
+    short n;
+    for(n = 0; n < argc; n++)
+    {
+        if(strcmp(argv[n], strID) == 0)
+        {
+            n++;
+            if(n < argc)
+            {
+                returnVal = atof(argv[n]);
+            }
+            break;
+        }
+    }
+    return returnVal;
+}
+
+int
+readParamInt(
+    int   argc,
+    char* argv[],
+    char* strID,
+    int   defaultVal)
+{
+    int returnVal = defaultVal;
+    short n;
+    for(n = 0; n < argc; n++)
+    {
+        if(strcmp(argv[n], strID) == 0)
+        {
+            n++;
+            if(n < argc)
+            {
+                returnVal = atoi(argv[n]);
+            }
+            break;
+        }
+    }
+    return returnVal;
+}
+
+int
+readParamString(
+    int   argc,
+    char* argv[],
+    char* strID,
+    char* stringParam,
+    int   maxSize)
+{
+    int paramLenght = 0;
+    short n;
+    for(n = 0; n < argc; n++)
+    {
+        if(strcmp(argv[n], strID) == 0)
+        {
+            n++;
+            if(n < argc)
+            {
+                strncpy(stringParam, argv[n], maxSize);
+                paramLenght = (int)strlen(argv[n]);
+            }
+            break;
+        }
+    }
+    return paramLenght;
+}
+
+void
+get_arrival_time(
+    int              current_framesamples,   /* samples */
+    size_t           packet_size,            /* bytes */
+    int              bottleneck,             /* excluding headers; bits/s */
+    BottleNeckModel* BN_data,
+    short            senderSampFreqHz,
+    short            receiverSampFreqHz)
+{
+    unsigned int travelTimeMs;
+	const int headerSizeByte = 35;
+
+	int headerRate;
+
+    BN_data->whenPackGeneratedMs += (current_framesamples / (senderSampFreqHz / 1000));
+
+	headerRate = headerSizeByte * 8 * senderSampFreqHz / current_framesamples;     /* bits/s */
+
+	/* everything in samples */
+	BN_data->sample_count = BN_data->sample_count + current_framesamples;
+
+    //travelTimeMs = ((packet_size + HeaderSize) * 8 * sampFreqHz) /
+    //    (bottleneck + HeaderRate)
+    travelTimeMs = (unsigned int)floor((double)((packet_size + headerSizeByte) * 8 * 1000)
+        / (double)(bottleneck + headerRate) + 0.5);
+
+    if(BN_data->whenPrevPackLeftMs > BN_data->whenPackGeneratedMs)
+    {
+        BN_data->whenPrevPackLeftMs += travelTimeMs;
+    }
+    else
+    {
+        BN_data->whenPrevPackLeftMs = BN_data->whenPackGeneratedMs +
+            travelTimeMs;
+    }
+
+    BN_data->arrival_time = (BN_data->whenPrevPackLeftMs *
+        (receiverSampFreqHz / 1000));
+
+//	if (BN_data->arrival_time < BN_data->sample_count)
+//		BN_data->arrival_time = BN_data->sample_count;
+
+	BN_data->rtp_number++;
+}
diff --git a/modules/audio_coding/codecs/isac/main/util/utility.h b/modules/audio_coding/codecs/isac/main/util/utility.h
new file mode 100644
index 0000000..1acc542
--- /dev/null
+++ b/modules/audio_coding/codecs/isac/main/util/utility.h
@@ -0,0 +1,108 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_UTIL_UTILITY_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_UTIL_UTILITY_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define OPEN_FILE_WB(filePtr, fullPath)                     \
+  do {                                                      \
+    if (fullPath != NULL) {                                 \
+      filePtr = fopen(fullPath, "wb");                      \
+      if (filePtr == NULL) {                                \
+        printf("could not open %s to write to.", fullPath); \
+        return -1;                                          \
+      }                                                     \
+    } else {                                                \
+      filePtr = NULL;                                       \
+    }                                                       \
+  } while (0)
+
+#define OPEN_FILE_AB(filePtr, fullPath)                     \
+  do {                                                      \
+    if (fullPath != NULL) {                                 \
+      filePtr = fopen(fullPath, "ab");                      \
+      if (filePtr == NULL) {                                \
+        printf("could not open %s to write to.", fullPath); \
+        return -1;                                          \
+      }                                                     \
+    } else {                                                \
+      filePtr = NULL;                                       \
+    }                                                       \
+  } while (0)
+
+#define OPEN_FILE_RB(filePtr, fullPath)                      \
+  do {                                                       \
+    if (fullPath != NULL) {                                  \
+      filePtr = fopen(fullPath, "rb");                       \
+      if (filePtr == NULL) {                                 \
+        printf("could not open %s to read from.", fullPath); \
+        return -1;                                           \
+      }                                                      \
+    } else {                                                 \
+      filePtr = NULL;                                        \
+    }                                                        \
+  } while (0)
+
+#define WRITE_FILE_D(bufferPtr, len, filePtr)      \
+  do {                                             \
+    if (filePtr != NULL) {                         \
+      double dummy[1000];                          \
+      int cntr;                                    \
+      for (cntr = 0; cntr < (len); cntr++) {       \
+        dummy[cntr] = (double)bufferPtr[cntr];     \
+      }                                            \
+      fwrite(dummy, sizeof(double), len, filePtr); \
+      fflush(filePtr);                             \
+    }                                              \
+  } while (0)
+
+typedef struct {
+  unsigned int whenPackGeneratedMs;
+  unsigned int whenPrevPackLeftMs;
+  unsigned int sendTimeMs;   /* milisecond */
+  unsigned int arrival_time; /* samples */
+  unsigned int sample_count; /* samples, also used as "send time stamp" */
+  unsigned int rtp_number;
+} BottleNeckModel;
+
+void get_arrival_time(int current_framesamples, /* samples */
+                      size_t packet_size,       /* bytes */
+                      int bottleneck,           /* excluding headers; bits/s */
+                      BottleNeckModel* BN_data,
+                      short senderSampFreqHz,
+                      short receiverSampFreqHz);
+
+/* function for reading audio data from PCM file */
+int readframe(short* data, FILE* inp, int length);
+
+short readSwitch(int argc, char* argv[], char* strID);
+
+double readParamDouble(int argc, char* argv[], char* strID, double defaultVal);
+
+int readParamInt(int argc, char* argv[], char* strID, int defaultVal);
+
+int readParamString(int argc,
+                    char* argv[],
+                    char* strID,
+                    char* stringParam,
+                    int maxSize);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/modules/audio_coding/neteq/audio_decoder_unittest.cc b/modules/audio_coding/neteq/audio_decoder_unittest.cc
index fef3c3c..bb5c6d1 100644
--- a/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -22,6 +22,10 @@
 #include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
 #include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
 #include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
+#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
+#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h"
+#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
 #include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
 #include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h"
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
@@ -191,8 +195,8 @@
       processed_samples += frame_size_;
     }
     // For some codecs it doesn't make sense to check expected number of bytes,
-    // since the number can vary for different platforms. Opus is such a codec.
-    // In this case expected_bytes is set to 0.
+    // since the number can vary for different platforms. Opus and iSAC are
+    // such codecs. In this case expected_bytes is set to 0.
     if (expected_bytes) {
       EXPECT_EQ(expected_bytes, encoded_bytes);
     }
@@ -343,6 +347,66 @@
   }
 };
 
+class AudioDecoderIsacFloatTest : public AudioDecoderTest {
+ protected:
+  AudioDecoderIsacFloatTest() : AudioDecoderTest() {
+    codec_input_rate_hz_ = 16000;
+    frame_size_ = 480;
+    data_length_ = 10 * frame_size_;
+    AudioEncoderIsacFloatImpl::Config config;
+    config.payload_type = payload_type_;
+    config.sample_rate_hz = codec_input_rate_hz_;
+    config.frame_size_ms =
+        1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
+    audio_encoder_.reset(new AudioEncoderIsacFloatImpl(config));
+    audio_encoder_->OnReceivedOverhead(kOverheadBytesPerPacket);
+
+    AudioDecoderIsacFloatImpl::Config decoder_config;
+    decoder_config.sample_rate_hz = codec_input_rate_hz_;
+    decoder_ = new AudioDecoderIsacFloatImpl(decoder_config);
+  }
+};
+
+class AudioDecoderIsacSwbTest : public AudioDecoderTest {
+ protected:
+  AudioDecoderIsacSwbTest() : AudioDecoderTest() {
+    codec_input_rate_hz_ = 32000;
+    frame_size_ = 960;
+    data_length_ = 10 * frame_size_;
+    AudioEncoderIsacFloatImpl::Config config;
+    config.payload_type = payload_type_;
+    config.sample_rate_hz = codec_input_rate_hz_;
+    config.frame_size_ms =
+        1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
+    audio_encoder_.reset(new AudioEncoderIsacFloatImpl(config));
+    audio_encoder_->OnReceivedOverhead(kOverheadBytesPerPacket);
+
+    AudioDecoderIsacFloatImpl::Config decoder_config;
+    decoder_config.sample_rate_hz = codec_input_rate_hz_;
+    decoder_ = new AudioDecoderIsacFloatImpl(decoder_config);
+  }
+};
+
+class AudioDecoderIsacFixTest : public AudioDecoderTest {
+ protected:
+  AudioDecoderIsacFixTest() : AudioDecoderTest() {
+    codec_input_rate_hz_ = 16000;
+    frame_size_ = 480;
+    data_length_ = 10 * frame_size_;
+    AudioEncoderIsacFixImpl::Config config;
+    config.payload_type = payload_type_;
+    config.sample_rate_hz = codec_input_rate_hz_;
+    config.frame_size_ms =
+        1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
+    audio_encoder_.reset(new AudioEncoderIsacFixImpl(config));
+    audio_encoder_->OnReceivedOverhead(kOverheadBytesPerPacket);
+
+    AudioDecoderIsacFixImpl::Config decoder_config;
+    decoder_config.sample_rate_hz = codec_input_rate_hz_;
+    decoder_ = new AudioDecoderIsacFixImpl(decoder_config);
+  }
+};
+
 class AudioDecoderG722Test : public AudioDecoderTest {
  protected:
   AudioDecoderG722Test() : AudioDecoderTest() {
@@ -469,6 +533,94 @@
   TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 13333);
 }
 
+TEST_F(AudioDecoderIsacFloatTest, EncodeDecode) {
+  int tolerance = 3399;
+  double mse = 434951.0;
+  int delay = 48;  // Delay from input to output.
+  EncodeDecodeTest(0, tolerance, mse, delay);
+  ReInitTest();
+  EXPECT_FALSE(decoder_->HasDecodePlc());
+}
+
+TEST_F(AudioDecoderIsacFloatTest, SetTargetBitrate) {
+  const int overhead_rate =
+      8 * kOverheadBytesPerPacket * codec_input_rate_hz_ / frame_size_;
+  EXPECT_EQ(10000,
+            SetAndGetTargetBitrate(audio_encoder_.get(), 9999 + overhead_rate));
+  EXPECT_EQ(10000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          10000 + overhead_rate));
+  EXPECT_EQ(23456, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          23456 + overhead_rate));
+  EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          32000 + overhead_rate));
+  EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          32001 + overhead_rate));
+}
+
+TEST_F(AudioDecoderIsacSwbTest, EncodeDecode) {
+  int tolerance = 19757;
+  double mse = 8.18e6;
+  int delay = 160;  // Delay from input to output.
+  EncodeDecodeTest(0, tolerance, mse, delay);
+  ReInitTest();
+  EXPECT_FALSE(decoder_->HasDecodePlc());
+}
+
+TEST_F(AudioDecoderIsacSwbTest, SetTargetBitrate) {
+  const int overhead_rate =
+      8 * kOverheadBytesPerPacket * codec_input_rate_hz_ / frame_size_;
+  EXPECT_EQ(10000,
+            SetAndGetTargetBitrate(audio_encoder_.get(), 9999 + overhead_rate));
+  EXPECT_EQ(10000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          10000 + overhead_rate));
+  EXPECT_EQ(23456, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          23456 + overhead_rate));
+  EXPECT_EQ(56000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          56000 + overhead_rate));
+  EXPECT_EQ(56000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          56001 + overhead_rate));
+}
+
+// Run bit exactness test only for release builds.
+#if defined(NDEBUG)
+TEST_F(AudioDecoderIsacFixTest, EncodeDecode) {
+  int tolerance = 11034;
+  double mse = 3.46e6;
+  int delay = 54;  // Delay from input to output.
+#if defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM)
+  static const int kEncodedBytes = 685;
+#elif defined(WEBRTC_MAC) && defined(WEBRTC_ARCH_ARM64)  // M1 Mac
+  static const int kEncodedBytes = 673;
+#elif defined(WEBRTC_ARCH_ARM64)
+  static const int kEncodedBytes = 673;
+#elif defined(WEBRTC_WIN) && defined(_MSC_VER) && !defined(__clang__)
+  static const int kEncodedBytes = 671;
+#elif defined(WEBRTC_IOS) && defined(WEBRTC_ARCH_X86_64)
+  static const int kEncodedBytes = 671;
+#else
+  static const int kEncodedBytes = 671;
+#endif
+  EncodeDecodeTest(kEncodedBytes, tolerance, mse, delay);
+  ReInitTest();
+  EXPECT_FALSE(decoder_->HasDecodePlc());
+}
+#endif
+
+TEST_F(AudioDecoderIsacFixTest, SetTargetBitrate) {
+  const int overhead_rate =
+      8 * kOverheadBytesPerPacket * codec_input_rate_hz_ / frame_size_;
+  EXPECT_EQ(10000,
+            SetAndGetTargetBitrate(audio_encoder_.get(), 9999 + overhead_rate));
+  EXPECT_EQ(10000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          10000 + overhead_rate));
+  EXPECT_EQ(23456, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          23456 + overhead_rate));
+  EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          32000 + overhead_rate));
+  EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder_.get(),
+                                          32001 + overhead_rate));
+}
+
 TEST_F(AudioDecoderG722Test, EncodeDecode) {
   int tolerance = 6176;
   double mse = 238630.0;
diff --git a/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc b/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc
new file mode 100644
index 0000000..6a096c3
--- /dev/null
+++ b/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc
@@ -0,0 +1,102 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "absl/flags/flag.h"
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+#include "modules/audio_coding/neteq/tools/neteq_quality_test.h"
+
+ABSL_FLAG(int, bit_rate_kbps, 32, "Target bit rate (kbps).");
+
+using ::testing::InitGoogleTest;
+
+namespace webrtc {
+namespace test {
+namespace {
+static const int kIsacBlockDurationMs = 30;
+static const int kIsacInputSamplingKhz = 16;
+static const int kIsacOutputSamplingKhz = 16;
+}  // namespace
+
+class NetEqIsacQualityTest : public NetEqQualityTest {
+ protected:
+  NetEqIsacQualityTest();
+  void SetUp() override;
+  void TearDown() override;
+  int EncodeBlock(int16_t* in_data,
+                  size_t block_size_samples,
+                  rtc::Buffer* payload,
+                  size_t max_bytes) override;
+
+ private:
+  ISACFIX_MainStruct* isac_encoder_;
+  int bit_rate_kbps_;
+};
+
+NetEqIsacQualityTest::NetEqIsacQualityTest()
+    : NetEqQualityTest(kIsacBlockDurationMs,
+                       kIsacInputSamplingKhz,
+                       kIsacOutputSamplingKhz,
+                       SdpAudioFormat("isac", 16000, 1)),
+      isac_encoder_(NULL),
+      bit_rate_kbps_(absl::GetFlag(FLAGS_bit_rate_kbps)) {
+  // Flag validation
+  RTC_CHECK(absl::GetFlag(FLAGS_bit_rate_kbps) >= 10 &&
+            absl::GetFlag(FLAGS_bit_rate_kbps) <= 32)
+      << "Invalid bit rate, should be between 10 and 32 kbps.";
+}
+
+void NetEqIsacQualityTest::SetUp() {
+  ASSERT_EQ(1u, channels_) << "iSAC supports only mono audio.";
+  // Create encoder memory.
+  WebRtcIsacfix_Create(&isac_encoder_);
+  ASSERT_TRUE(isac_encoder_ != NULL);
+  EXPECT_EQ(0, WebRtcIsacfix_EncoderInit(isac_encoder_, 1));
+  // Set bitrate and block length.
+  EXPECT_EQ(0, WebRtcIsacfix_Control(isac_encoder_, bit_rate_kbps_ * 1000,
+                                     kIsacBlockDurationMs));
+  NetEqQualityTest::SetUp();
+}
+
+void NetEqIsacQualityTest::TearDown() {
+  // Free memory.
+  EXPECT_EQ(0, WebRtcIsacfix_Free(isac_encoder_));
+  NetEqQualityTest::TearDown();
+}
+
+int NetEqIsacQualityTest::EncodeBlock(int16_t* in_data,
+                                      size_t block_size_samples,
+                                      rtc::Buffer* payload,
+                                      size_t max_bytes) {
+  // ISAC takes 10 ms for every call.
+  const int subblocks = kIsacBlockDurationMs / 10;
+  const int subblock_length = 10 * kIsacInputSamplingKhz;
+  int value = 0;
+
+  int pointer = 0;
+  for (int idx = 0; idx < subblocks; idx++, pointer += subblock_length) {
+    // The Isac encoder does not perform encoding (and returns 0) until it
+    // receives a sequence of sub-blocks that amount to the frame duration.
+    EXPECT_EQ(0, value);
+    payload->AppendData(max_bytes, [&](rtc::ArrayView<uint8_t> payload) {
+      value = WebRtcIsacfix_Encode(isac_encoder_, &in_data[pointer],
+                                   payload.data());
+      return (value >= 0) ? static_cast<size_t>(value) : 0;
+    });
+  }
+  EXPECT_GT(value, 0);
+  return value;
+}
+
+TEST_F(NetEqIsacQualityTest, Test) {
+  Simulate();
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/rtp_encode.cc b/modules/audio_coding/neteq/tools/rtp_encode.cc
index 8adca92..6aeeb6d 100644
--- a/modules/audio_coding/neteq/tools/rtp_encode.cc
+++ b/modules/audio_coding/neteq/tools/rtp_encode.cc
@@ -30,6 +30,7 @@
 #include "api/audio_codecs/g711/audio_encoder_g711.h"
 #include "api/audio_codecs/g722/audio_encoder_g722.h"
 #include "api/audio_codecs/ilbc/audio_encoder_ilbc.h"
+#include "api/audio_codecs/isac/audio_encoder_isac.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -70,6 +71,7 @@
   kPcm16b32,
   kPcm16b48,
   kIlbc,
+  kIsac
 };
 
 struct CodecTypeAndInfo {
@@ -92,7 +94,8 @@
           {"pcm16b_16", {CodecType::kPcm16b16, 94, false}},
           {"pcm16b_32", {CodecType::kPcm16b32, 95, false}},
           {"pcm16b_48", {CodecType::kPcm16b48, 96, false}},
-          {"ilbc", {CodecType::kIlbc, 102, false}}};
+          {"ilbc", {CodecType::kIlbc, 102, false}},
+          {"isac", {CodecType::kIsac, 103, false}}};
   return *codec_list;
 }
 
@@ -233,6 +236,11 @@
       return AudioEncoderIlbc::MakeAudioEncoder(
           GetCodecConfig<AudioEncoderIlbc>(), payload_type);
     }
+
+    case CodecType::kIsac: {
+      return AudioEncoderIsac::MakeAudioEncoder(
+          GetCodecConfig<AudioEncoderIsac>(), payload_type);
+    }
   }
   RTC_DCHECK_NOTREACHED();
   return nullptr;
diff --git a/modules/audio_coding/test/EncodeDecodeTest.cc b/modules/audio_coding/test/EncodeDecodeTest.cc
index 9f9c4aa..8d4bcce 100644
--- a/modules/audio_coding/test/EncodeDecodeTest.cc
+++ b/modules/audio_coding/test/EncodeDecodeTest.cc
@@ -110,7 +110,9 @@
   EXPECT_EQ(0, acm->InitializeReceiver());
 
   if (channels == 1) {
-    acm->SetReceiveCodecs({{107, {"L16", 8000, 1}},
+    acm->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                           {104, {"ISAC", 32000, 1}},
+                           {107, {"L16", 8000, 1}},
                            {108, {"L16", 16000, 1}},
                            {109, {"L16", 32000, 1}},
                            {0, {"PCMU", 8000, 1}},
@@ -230,6 +232,7 @@
 
 void EncodeDecodeTest::Perform() {
   const std::map<int, SdpAudioFormat> send_codecs = {
+      {103, {"ISAC", 16000, 1}}, {104, {"ISAC", 32000, 1}},
       {107, {"L16", 8000, 1}},   {108, {"L16", 16000, 1}},
       {109, {"L16", 32000, 1}},  {0, {"PCMU", 8000, 1}},
       {8, {"PCMA", 8000, 1}},
diff --git a/modules/audio_coding/test/TestAllCodecs.cc b/modules/audio_coding/test/TestAllCodecs.cc
index b44037d..e93df34 100644
--- a/modules/audio_coding/test/TestAllCodecs.cc
+++ b/modules/audio_coding/test/TestAllCodecs.cc
@@ -130,7 +130,9 @@
   acm_a_->InitializeReceiver();
   acm_b_->InitializeReceiver();
 
-  acm_b_->SetReceiveCodecs({{107, {"L16", 8000, 1}},
+  acm_b_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                            {104, {"ISAC", 32000, 1}},
+                            {107, {"L16", 8000, 1}},
                             {108, {"L16", 16000, 1}},
                             {109, {"L16", 32000, 1}},
                             {111, {"L16", 8000, 2}},
@@ -185,6 +187,33 @@
   Run(channel_a_to_b_);
   outfile_b_.Close();
 #endif
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+  test_count_++;
+  OpenOutFile(test_count_);
+  char codec_isac[] = "ISAC";
+  RegisterSendCodec('A', codec_isac, 16000, -1, 480, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 16000, -1, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 16000, 15000, 480, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 16000, 32000, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  outfile_b_.Close();
+#endif
+#ifdef WEBRTC_CODEC_ISAC
+  test_count_++;
+  OpenOutFile(test_count_);
+  RegisterSendCodec('A', codec_isac, 32000, -1, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 32000, 56000, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 32000, 37000, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_isac, 32000, 32000, 960, kVariableSize);
+  Run(channel_a_to_b_);
+  outfile_b_.Close();
+#endif
   test_count_++;
   OpenOutFile(test_count_);
   char codec_l16[] = "L16";
@@ -290,11 +319,15 @@
   // Store packet-size in samples, used to validate the received packet.
   // If G.722, store half the size to compensate for the timestamp bug in the
   // RFC for G.722.
+  // If iSAC runs in adaptive mode, packet size in samples can change on the
+  // fly, so we exclude this test by setting `packet_size_samples_` to -1.
   int clockrate_hz = sampling_freq_hz;
   size_t num_channels = 1;
   if (absl::EqualsIgnoreCase(codec_name, "G722")) {
     packet_size_samples_ = packet_size / 2;
     clockrate_hz = sampling_freq_hz / 2;
+  } else if (absl::EqualsIgnoreCase(codec_name, "ISAC") && (rate == -1)) {
+    packet_size_samples_ = -1;
   } else if (absl::EqualsIgnoreCase(codec_name, "OPUS")) {
     packet_size_samples_ = packet_size;
     num_channels = 2;
diff --git a/modules/audio_coding/test/TestRedFec.cc b/modules/audio_coding/test/TestRedFec.cc
index fff48b2..892fbc8 100644
--- a/modules/audio_coding/test/TestRedFec.cc
+++ b/modules/audio_coding/test/TestRedFec.cc
@@ -22,6 +22,8 @@
 #include "api/audio_codecs/g711/audio_encoder_g711.h"
 #include "api/audio_codecs/g722/audio_decoder_g722.h"
 #include "api/audio_codecs/g722/audio_encoder_g722.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
 #include "api/audio_codecs/opus/audio_decoder_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
@@ -36,10 +38,12 @@
 TestRedFec::TestRedFec()
     : encoder_factory_(CreateAudioEncoderFactory<AudioEncoderG711,
                                                  AudioEncoderG722,
+                                                 AudioEncoderIsacFloat,
                                                  AudioEncoderL16,
                                                  AudioEncoderOpus>()),
       decoder_factory_(CreateAudioDecoderFactory<AudioDecoderG711,
                                                  AudioDecoderG722,
+                                                 AudioDecoderIsacFloat,
                                                  AudioDecoderL16,
                                                  AudioDecoderOpus>()),
       _acmA(AudioCodingModule::Create(
@@ -91,6 +95,19 @@
   Run();
   _outFileB.Close();
 
+  RegisterSendCodec(_acmA, {"ISAC", 16000, 1}, Vad::kVadVeryAggressive, false);
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  // Switch to a 32 kHz codec; RED should be switched off.
+  RegisterSendCodec(_acmA, {"ISAC", 32000, 1}, Vad::kVadVeryAggressive, false);
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec(_acmA, {"ISAC", 32000, 1}, absl::nullopt, false);
+
   _channelA2B->SetFECTestWithPacketLoss(true);
   // Following tests are under packet losses.
 
@@ -101,6 +118,22 @@
   Run();
   _outFileB.Close();
 
+  // Switch to a 16 kHz codec, RED should have been switched off.
+  RegisterSendCodec(_acmA, {"ISAC", 16000, 1}, Vad::kVadVeryAggressive, false);
+
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  // Switch to a 32 kHz codec, RED should have been switched off.
+  RegisterSendCodec(_acmA, {"ISAC", 32000, 1}, Vad::kVadVeryAggressive, false);
+
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec(_acmA, {"ISAC", 32000, 1}, absl::nullopt, false);
+
   RegisterSendCodec(_acmA, {"opus", 48000, 2}, absl::nullopt, false);
 
   // _channelA2B imposes 25% packet loss rate.
diff --git a/modules/audio_coding/test/TestVADDTX.cc b/modules/audio_coding/test/TestVADDTX.cc
index 19367d9..cb05deb 100644
--- a/modules/audio_coding/test/TestVADDTX.cc
+++ b/modules/audio_coding/test/TestVADDTX.cc
@@ -18,6 +18,8 @@
 #include "api/audio_codecs/audio_encoder_factory_template.h"
 #include "api/audio_codecs/ilbc/audio_decoder_ilbc.h"
 #include "api/audio_codecs/ilbc/audio_encoder_ilbc.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
 #include "api/audio_codecs/opus/audio_decoder_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
@@ -66,10 +68,12 @@
 }
 
 TestVadDtx::TestVadDtx()
-    : encoder_factory_(
-          CreateAudioEncoderFactory<AudioEncoderIlbc, AudioEncoderOpus>()),
-      decoder_factory_(
-          CreateAudioDecoderFactory<AudioDecoderIlbc, AudioDecoderOpus>()),
+    : encoder_factory_(CreateAudioEncoderFactory<AudioEncoderIlbc,
+                                                 AudioEncoderIsacFloat,
+                                                 AudioEncoderOpus>()),
+      decoder_factory_(CreateAudioDecoderFactory<AudioDecoderIlbc,
+                                                 AudioDecoderIsacFloat,
+                                                 AudioDecoderOpus>()),
       acm_send_(AudioCodingModule::Create(
           AudioCodingModule::Config(decoder_factory_))),
       acm_receive_(AudioCodingModule::Create(
@@ -178,6 +182,8 @@
 TestWebRtcVadDtx::TestWebRtcVadDtx() : output_file_num_(0) {}
 
 void TestWebRtcVadDtx::Perform() {
+  RunTestCases({"ISAC", 16000, 1});
+  RunTestCases({"ISAC", 32000, 1});
   RunTestCases({"ILBC", 8000, 1});
   RunTestCases({"opus", 48000, 2});
 }
diff --git a/modules/audio_coding/test/Tester.cc b/modules/audio_coding/test/Tester.cc
index 7612aa4..113dbe0 100644
--- a/modules/audio_coding/test/Tester.cc
+++ b/modules/audio_coding/test/Tester.cc
@@ -21,6 +21,7 @@
 #include "modules/audio_coding/test/TestStereo.h"
 #include "modules/audio_coding/test/TestVADDTX.h"
 #include "modules/audio_coding/test/TwoWayCommunication.h"
+#include "modules/audio_coding/test/iSACTest.h"
 #include "modules/audio_coding/test/opus_test.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
@@ -41,6 +42,25 @@
   webrtc::TestRedFec().Perform();
 }
 
+#if defined(WEBRTC_ANDROID)
+TEST(AudioCodingModuleTest, DISABLED_TestIsac) {
+#else
+TEST(AudioCodingModuleTest, TestIsac) {
+#endif
+  webrtc::ISACTest().Perform();
+}
+
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
+    defined(WEBRTC_CODEC_ILBC)
+#if defined(WEBRTC_ANDROID)
+TEST(AudioCodingModuleTest, DISABLED_TwoWayCommunication) {
+#else
+TEST(AudioCodingModuleTest, TwoWayCommunication) {
+#endif
+  webrtc::TwoWayCommunication().Perform();
+}
+#endif
+
 // Disabled on ios as flaky, see https://crbug.com/webrtc/7057
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
 TEST(AudioCodingModuleTest, DISABLED_TestStereo) {
diff --git a/modules/audio_coding/test/iSACTest.cc b/modules/audio_coding/test/iSACTest.cc
new file mode 100644
index 0000000..246c485
--- /dev/null
+++ b/modules/audio_coding/test/iSACTest.cc
@@ -0,0 +1,273 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/test/iSACTest.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "absl/strings/match.h"
+#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
+#include "rtc_base/strings/string_builder.h"
+#include "rtc_base/time_utils.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+
+using ::testing::AnyOf;
+using ::testing::Eq;
+using ::testing::StrCaseEq;
+
+namespace {
+
+constexpr int kISAC16kPayloadType = 103;
+constexpr int kISAC32kPayloadType = 104;
+const SdpAudioFormat kISAC16kFormat = {"ISAC", 16000, 1};
+const SdpAudioFormat kISAC32kFormat = {"ISAC", 32000, 1};
+
+AudioEncoderIsacFloat::Config TweakConfig(
+    AudioEncoderIsacFloat::Config config,
+    const ACMTestISACConfig& test_config) {
+  if (test_config.currentRateBitPerSec > 0) {
+    config.bit_rate = test_config.currentRateBitPerSec;
+  }
+  if (test_config.currentFrameSizeMsec != 0) {
+    config.frame_size_ms = test_config.currentFrameSizeMsec;
+  }
+  EXPECT_THAT(config.IsOk(), Eq(true));
+  return config;
+}
+
+void SetISACConfigDefault(ACMTestISACConfig& isacConfig) {
+  isacConfig.currentRateBitPerSec = 0;
+  isacConfig.currentFrameSizeMsec = 0;
+  isacConfig.encodingMode = -1;
+  isacConfig.initRateBitPerSec = 0;
+  isacConfig.initFrameSizeInMsec = 0;
+  isacConfig.enforceFrameSize = false;
+}
+
+}  // namespace
+
+ISACTest::ISACTest()
+    : _acmA(AudioCodingModule::Create(
+          AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
+      _acmB(AudioCodingModule::Create(
+          AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))) {}
+
+ISACTest::~ISACTest() {}
+
+void ISACTest::Setup() {
+  // Register both iSAC-wb & iSAC-swb in both sides as receiver codecs.
+  std::map<int, SdpAudioFormat> receive_codecs = {
+      {kISAC16kPayloadType, kISAC16kFormat},
+      {kISAC32kPayloadType, kISAC32kFormat}};
+  _acmA->SetReceiveCodecs(receive_codecs);
+  _acmB->SetReceiveCodecs(receive_codecs);
+
+  //--- Set A-to-B channel
+  _channel_A2B.reset(new Channel);
+  EXPECT_EQ(0, _acmA->RegisterTransportCallback(_channel_A2B.get()));
+  _channel_A2B->RegisterReceiverACM(_acmB.get());
+
+  //--- Set B-to-A channel
+  _channel_B2A.reset(new Channel);
+  EXPECT_EQ(0, _acmB->RegisterTransportCallback(_channel_B2A.get()));
+  _channel_B2A->RegisterReceiverACM(_acmA.get());
+
+  file_name_swb_ =
+      webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+
+  _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
+      kISAC16kPayloadType));
+  _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
+      kISAC32kPayloadType));
+
+  _inFileA.Open(file_name_swb_, 32000, "rb");
+  // Set test length to 500 ms (50 blocks of 10 ms each).
+  _inFileA.SetNum10MsBlocksToRead(50);
+  // Fast-forward 1 second (100 blocks) since the files start with silence.
+  _inFileA.FastForward(100);
+  std::string fileNameA = webrtc::test::OutputPath() + "testisac_a.pcm";
+  std::string fileNameB = webrtc::test::OutputPath() + "testisac_b.pcm";
+  _outFileA.Open(fileNameA, 32000, "wb");
+  _outFileB.Open(fileNameB, 32000, "wb");
+
+  while (!_inFileA.EndOfFile()) {
+    Run10ms();
+  }
+
+  _inFileA.Close();
+  _outFileA.Close();
+  _outFileB.Close();
+}
+
+void ISACTest::Perform() {
+  Setup();
+
+  int16_t testNr = 0;
+  ACMTestISACConfig wbISACConfig;
+  ACMTestISACConfig swbISACConfig;
+
+  SetISACConfigDefault(wbISACConfig);
+  SetISACConfigDefault(swbISACConfig);
+
+  wbISACConfig.currentRateBitPerSec = -1;
+  swbISACConfig.currentRateBitPerSec = -1;
+  testNr++;
+  EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+  SetISACConfigDefault(wbISACConfig);
+  SetISACConfigDefault(swbISACConfig);
+  testNr++;
+  EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+  testNr++;
+  SwitchingSamplingRate(testNr, 4);
+}
+
+void ISACTest::Run10ms() {
+  AudioFrame audioFrame;
+  EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
+  EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
+  EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
+  bool muted;
+  EXPECT_EQ(0, _acmA->PlayoutData10Ms(32000, &audioFrame, &muted));
+  ASSERT_FALSE(muted);
+  _outFileA.Write10MsData(audioFrame);
+  EXPECT_EQ(0, _acmB->PlayoutData10Ms(32000, &audioFrame, &muted));
+  ASSERT_FALSE(muted);
+  _outFileB.Write10MsData(audioFrame);
+}
+
+void ISACTest::EncodeDecode(int testNr,
+                            ACMTestISACConfig& wbISACConfig,
+                            ACMTestISACConfig& swbISACConfig) {
+  // Files in Side A and B
+  _inFileA.Open(file_name_swb_, 32000, "rb", true);
+  _inFileB.Open(file_name_swb_, 32000, "rb", true);
+
+  std::string file_name_out;
+  rtc::StringBuilder file_stream_a;
+  rtc::StringBuilder file_stream_b;
+  file_stream_a << webrtc::test::OutputPath();
+  file_stream_b << webrtc::test::OutputPath();
+  file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
+  file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
+  file_name_out = file_stream_a.str();
+  _outFileA.Open(file_name_out, 32000, "wb");
+  file_name_out = file_stream_b.str();
+  _outFileB.Open(file_name_out, 32000, "wb");
+
+  // Side A is sending super-wideband, and side B is sending wideband.
+  _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
+                  swbISACConfig),
+      kISAC32kPayloadType));
+  _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
+                  wbISACConfig),
+      kISAC16kPayloadType));
+
+  _channel_A2B->ResetStats();
+  _channel_B2A->ResetStats();
+
+  while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
+    Run10ms();
+  }
+
+  _channel_A2B->ResetStats();
+  _channel_B2A->ResetStats();
+
+  _outFileA.Close();
+  _outFileB.Close();
+  _inFileA.Close();
+  _inFileB.Close();
+}
+
+void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) {
+  // Files in Side A
+  _inFileA.Open(file_name_swb_, 32000, "rb");
+  _inFileB.Open(file_name_swb_, 32000, "rb");
+
+  std::string file_name_out;
+  rtc::StringBuilder file_stream_a;
+  rtc::StringBuilder file_stream_b;
+  file_stream_a << webrtc::test::OutputPath();
+  file_stream_b << webrtc::test::OutputPath();
+  file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
+  file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
+  file_name_out = file_stream_a.str();
+  _outFileA.Open(file_name_out, 32000, "wb");
+  file_name_out = file_stream_b.str();
+  _outFileB.Open(file_name_out, 32000, "wb");
+
+  // Start with side A sending super-wideband and side B seding wideband.
+  // Toggle sending wideband/super-wideband in this test.
+  _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
+      kISAC32kPayloadType));
+  _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+      *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
+      kISAC16kPayloadType));
+
+  int numSendCodecChanged = 0;
+  while (numSendCodecChanged < (maxSampRateChange << 1)) {
+    Run10ms();
+    if (_inFileA.EndOfFile()) {
+      if (_inFileA.SamplingFrequency() == 16000) {
+        // Switch side A to send super-wideband.
+        _inFileA.Close();
+        _inFileA.Open(file_name_swb_, 32000, "rb");
+        _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+            *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
+            kISAC32kPayloadType));
+      } else {
+        // Switch side A to send wideband.
+        _inFileA.Close();
+        _inFileA.Open(file_name_swb_, 32000, "rb");
+        _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+            *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
+            kISAC16kPayloadType));
+      }
+      numSendCodecChanged++;
+    }
+
+    if (_inFileB.EndOfFile()) {
+      if (_inFileB.SamplingFrequency() == 16000) {
+        // Switch side B to send super-wideband.
+        _inFileB.Close();
+        _inFileB.Open(file_name_swb_, 32000, "rb");
+        _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+            *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
+            kISAC32kPayloadType));
+      } else {
+        // Switch side B to send wideband.
+        _inFileB.Close();
+        _inFileB.Open(file_name_swb_, 32000, "rb");
+        _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
+            *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
+            kISAC16kPayloadType));
+      }
+      numSendCodecChanged++;
+    }
+  }
+  _outFileA.Close();
+  _outFileB.Close();
+  _inFileA.Close();
+  _inFileB.Close();
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/test/iSACTest.h b/modules/audio_coding/test/iSACTest.h
new file mode 100644
index 0000000..f6efeea
--- /dev/null
+++ b/modules/audio_coding/test/iSACTest.h
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_TEST_ISACTEST_H_
+#define MODULES_AUDIO_CODING_TEST_ISACTEST_H_
+
+#include <string.h>
+
+#include <memory>
+
+#include "modules/audio_coding/include/audio_coding_module.h"
+#include "modules/audio_coding/test/Channel.h"
+#include "modules/audio_coding/test/PCMFile.h"
+
+namespace webrtc {
+
+struct ACMTestISACConfig {
+  int32_t currentRateBitPerSec;
+  int16_t currentFrameSizeMsec;
+  int16_t encodingMode;
+  uint32_t initRateBitPerSec;
+  int16_t initFrameSizeInMsec;
+  bool enforceFrameSize;
+};
+
+class ISACTest {
+ public:
+  ISACTest();
+  ~ISACTest();
+
+  void Perform();
+
+ private:
+  void Setup();
+
+  void Run10ms();
+
+  void EncodeDecode(int testNr,
+                    ACMTestISACConfig& wbISACConfig,
+                    ACMTestISACConfig& swbISACConfig);
+
+  void SwitchingSamplingRate(int testNr, int maxSampRateChange);
+
+  std::unique_ptr<AudioCodingModule> _acmA;
+  std::unique_ptr<AudioCodingModule> _acmB;
+
+  std::unique_ptr<Channel> _channel_A2B;
+  std::unique_ptr<Channel> _channel_B2A;
+
+  PCMFile _inFileA;
+  PCMFile _inFileB;
+
+  PCMFile _outFileA;
+  PCMFile _outFileB;
+
+  std::string file_name_swb_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_TEST_ISACTEST_H_