Convert CNG into C++ and remove it from AudioDecoder

Broke out CNG from AudioDecoder as they didn't really share an interface.

Converted the CNG code to C++, to make initialization and resource handling easier. This includes several changes to the behavior, favoring RTC_CHECKs over returning error codes.

Review URL: https://codereview.webrtc.org/1868143002

Cr-Commit-Position: refs/heads/master@{#12491}
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index fac2274..7a07247 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -147,9 +147,7 @@
   sources = [
     "codecs/cng/audio_encoder_cng.cc",
     "codecs/cng/audio_encoder_cng.h",
-    "codecs/cng/cng_helpfuns.c",
-    "codecs/cng/cng_helpfuns.h",
-    "codecs/cng/webrtc_cng.c",
+    "codecs/cng/webrtc_cng.cc",
     "codecs/cng/webrtc_cng.h",
   ]
 
diff --git a/webrtc/modules/audio_coding/codecs/audio_decoder.cc b/webrtc/modules/audio_coding/codecs/audio_decoder.cc
index d2984b9..442ddc1 100644
--- a/webrtc/modules/audio_coding/codecs/audio_decoder.cc
+++ b/webrtc/modules/audio_coding/codecs/audio_decoder.cc
@@ -82,11 +82,6 @@
   return false;
 }
 
-CNG_dec_inst* AudioDecoder::CngDecoderInstance() {
-  FATAL() << "Not a CNG decoder";
-  return NULL;
-}
-
 AudioDecoder::SpeechType AudioDecoder::ConvertSpeechType(int16_t type) {
   switch (type) {
     case 0:  // TODO(hlundin): Both iSAC and Opus return 0 for speech.
diff --git a/webrtc/modules/audio_coding/codecs/audio_decoder.h b/webrtc/modules/audio_coding/codecs/audio_decoder.h
index 81ac873..580ddbf 100644
--- a/webrtc/modules/audio_coding/codecs/audio_decoder.h
+++ b/webrtc/modules/audio_coding/codecs/audio_decoder.h
@@ -14,7 +14,6 @@
 #include <stdlib.h>  // NULL
 
 #include "webrtc/base/constructormagic.h"
-#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "webrtc/typedefs.h"
 
 namespace webrtc {
@@ -94,10 +93,6 @@
   // Returns true if the packet has FEC and false otherwise.
   virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const;
 
-  // If this is a CNG decoder, return the underlying CNG_dec_inst*. If this
-  // isn't a CNG decoder, don't call this method.
-  virtual CNG_dec_inst* CngDecoderInstance();
-
   virtual size_t Channels() const = 0;
 
  protected:
diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
index 04b635d..09c25d9 100644
--- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
+++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
@@ -21,19 +21,6 @@
 
 const int kMaxFrameSizeMs = 60;
 
-std::unique_ptr<CNG_enc_inst, CngInstDeleter> CreateCngInst(
-    int sample_rate_hz,
-    int sid_frame_interval_ms,
-    int num_cng_coefficients) {
-  CNG_enc_inst* ci;
-  RTC_CHECK_EQ(0, WebRtcCng_CreateEnc(&ci));
-  std::unique_ptr<CNG_enc_inst, CngInstDeleter> cng_inst(ci);
-  RTC_CHECK_EQ(0,
-               WebRtcCng_InitEnc(cng_inst.get(), sample_rate_hz,
-                                 sid_frame_interval_ms, num_cng_coefficients));
-  return cng_inst;
-}
-
 }  // namespace
 
 AudioEncoderCng::Config::Config() = default;
@@ -65,9 +52,10 @@
       sid_frame_interval_ms_(config.sid_frame_interval_ms),
       last_frame_active_(true),
       vad_(config.vad ? std::unique_ptr<Vad>(config.vad)
-                      : CreateVad(config.vad_mode)) {
-  cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_,
-                            num_cng_coefficients_);
+           : CreateVad(config.vad_mode)),
+      cng_encoder_(new ComfortNoiseEncoder(SampleRateHz(),
+                                           sid_frame_interval_ms_,
+                                           num_cng_coefficients_)) {
 }
 
 AudioEncoderCng::~AudioEncoderCng() = default;
@@ -170,8 +158,9 @@
   rtp_timestamps_.clear();
   last_frame_active_ = true;
   vad_->Reset();
-  cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_,
-                            num_cng_coefficients_);
+  cng_encoder_.reset(
+      new ComfortNoiseEncoder(SampleRateHz(), sid_frame_interval_ms_,
+                              num_cng_coefficients_));
 }
 
 bool AudioEncoderCng::SetFec(bool enable) {
@@ -204,32 +193,27 @@
   bool force_sid = last_frame_active_;
   bool output_produced = false;
   const size_t samples_per_10ms_frame = SamplesPer10msFrame();
-  const size_t bytes_to_encode = frames_to_encode * samples_per_10ms_frame;
   AudioEncoder::EncodedInfo info;
 
-  encoded->AppendData(bytes_to_encode, [&] (rtc::ArrayView<uint8_t> encoded) {
-      for (size_t i = 0; i < frames_to_encode; ++i) {
-        // It's important not to pass &info.encoded_bytes directly to
-        // WebRtcCng_Encode(), since later loop iterations may return zero in
-        // that value, in which case we don't want to overwrite any value from
-        // an earlier iteration.
-        size_t encoded_bytes_tmp = 0;
-        RTC_CHECK_GE(
-            WebRtcCng_Encode(cng_inst_.get(),
-                             &speech_buffer_[i * samples_per_10ms_frame],
-                             samples_per_10ms_frame, encoded.data(),
-                             &encoded_bytes_tmp, force_sid),
-            0);
-        if (encoded_bytes_tmp > 0) {
-          RTC_CHECK(!output_produced);
-          info.encoded_bytes = encoded_bytes_tmp;
-          output_produced = true;
-          force_sid = false;
-        }
-      }
+  for (size_t i = 0; i < frames_to_encode; ++i) {
+    // It's important not to pass &info.encoded_bytes directly to
+    // WebRtcCng_Encode(), since later loop iterations may return zero in
+    // that value, in which case we don't want to overwrite any value from
+    // an earlier iteration.
+    size_t encoded_bytes_tmp =
+        cng_encoder_->Encode(
+            rtc::ArrayView<const int16_t>(
+                &speech_buffer_[i * samples_per_10ms_frame],
+                samples_per_10ms_frame),
+            force_sid, encoded);
 
-      return info.encoded_bytes;
-    });
+    if (encoded_bytes_tmp > 0) {
+      RTC_CHECK(!output_produced);
+      info.encoded_bytes = encoded_bytes_tmp;
+      output_produced = true;
+      force_sid = false;
+    }
+  }
 
   info.encoded_timestamp = rtp_timestamps_.front();
   info.payload_type = cng_payload_type_;
diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h
index b52665d..246e951 100644
--- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h
+++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h
@@ -21,11 +21,6 @@
 
 namespace webrtc {
 
-// Deleter for use with unique_ptr.
-struct CngInstDeleter {
-  void operator()(CNG_enc_inst* ptr) const { WebRtcCng_FreeEnc(ptr); }
-};
-
 class Vad;
 
 class AudioEncoderCng final : public AudioEncoder {
@@ -84,7 +79,7 @@
   std::vector<uint32_t> rtp_timestamps_;
   bool last_frame_active_;
   std::unique_ptr<Vad> vad_;
-  std::unique_ptr<CNG_enc_inst, CngInstDeleter> cng_inst_;
+  std::unique_ptr<ComfortNoiseEncoder> cng_encoder_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderCng);
 };
diff --git a/webrtc/modules/audio_coding/codecs/cng/cng.gypi b/webrtc/modules/audio_coding/codecs/cng/cng.gypi
index c020f47..bbff9f8 100644
--- a/webrtc/modules/audio_coding/codecs/cng/cng.gypi
+++ b/webrtc/modules/audio_coding/codecs/cng/cng.gypi
@@ -18,9 +18,7 @@
       'sources': [
         'audio_encoder_cng.cc',
         'audio_encoder_cng.h',
-        'cng_helpfuns.c',
-        'cng_helpfuns.h',
-        'webrtc_cng.c',
+        'webrtc_cng.cc',
         'webrtc_cng.h',
       ],
     },
diff --git a/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.c b/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.c
deleted file mode 100644
index bc08d43..0000000
--- a/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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 "cng_helpfuns.h"
-
-#include "signal_processing_library.h"
-#include "webrtc/typedefs.h"
-#include "webrtc_cng.h"
-
-/* Values in |k| are Q15, and |a| Q12. */
-void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a) {
-  int16_t any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
-  int16_t *aptr, *aptr2, *anyptr;
-  const int16_t *kptr;
-  int m, i;
-
-  kptr = k;
-  *a = 4096;  /* i.e., (Word16_MAX >> 3) + 1 */
-  *any = *a;
-  a[1] = (*k + 4) >> 3;
-  for (m = 1; m < useOrder; m++) {
-    kptr++;
-    aptr = a;
-    aptr++;
-    aptr2 = &a[m];
-    anyptr = any;
-    anyptr++;
-
-    any[m + 1] = (*kptr + 4) >> 3;
-    for (i = 0; i < m; i++) {
-      *anyptr++ = (*aptr++) +
-          (int16_t)((((int32_t)(*aptr2--) * (int32_t) * kptr) + 16384) >> 15);
-    }
-
-    aptr = a;
-    anyptr = any;
-    for (i = 0; i < (m + 2); i++) {
-      *aptr++ = *anyptr++;
-    }
-  }
-}
diff --git a/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.h b/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.h
deleted file mode 100644
index a553a76..0000000
--- a/webrtc/modules/audio_coding/codecs/cng/cng_helpfuns.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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 WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_CNG_HELPFUNS_H_
-#define WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_CNG_HELPFUNS_H_
-
-#include "webrtc/typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_CNG_HELPFUNS_H_
diff --git a/webrtc/modules/audio_coding/codecs/cng/cng_unittest.cc b/webrtc/modules/audio_coding/codecs/cng/cng_unittest.cc
index 1061dca..95132a9 100644
--- a/webrtc/modules/audio_coding/codecs/cng/cng_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/cng/cng_unittest.cc
@@ -7,11 +7,12 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
+#include <memory>
 #include <string>
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/test/testsupport/fileutils.h"
-#include "webrtc_cng.h"
+#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 
 namespace webrtc {
 
@@ -21,7 +22,7 @@
   kSidLongIntervalUpdate = 10000
 };
 
-enum {
+enum : size_t {
   kCNGNumParamsLow = 0,
   kCNGNumParamsNormal = 8,
   kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
@@ -35,19 +36,13 @@
 
 class CngTest : public ::testing::Test {
  protected:
-  CngTest();
   virtual void SetUp();
 
-  CNG_enc_inst* cng_enc_inst_;
-  CNG_dec_inst* cng_dec_inst_;
+  void TestCngEncode(int sample_rate_hz, int quality);
+
   int16_t speech_data_[640];  // Max size of CNG internal buffers.
 };
 
-CngTest::CngTest()
-    : cng_enc_inst_(NULL),
-      cng_dec_inst_(NULL) {
-}
-
 void CngTest::SetUp() {
   FILE* input_file;
   const std::string file_name =
@@ -60,289 +55,187 @@
   input_file = NULL;
 }
 
-// Test failing Create.
-TEST_F(CngTest, CngCreateFail) {
-  // Test to see that an invalid pointer is caught.
-  EXPECT_EQ(-1, WebRtcCng_CreateEnc(NULL));
-  EXPECT_EQ(-1, WebRtcCng_CreateDec(NULL));
+void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
+  const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
+  rtc::Buffer sid_data;
+
+  ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
+                                  quality);
+  EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
+                                       speech_data_, num_samples_10ms),
+                                   kNoSid, &sid_data));
+  EXPECT_EQ(static_cast<size_t>(quality + 1),
+            cng_encoder.Encode(
+                rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
+                kForceSid, &sid_data));
 }
 
-// Test normal Create.
-TEST_F(CngTest, CngCreate) {
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
-  EXPECT_TRUE(cng_enc_inst_ != NULL);
-  EXPECT_TRUE(cng_dec_inst_ != NULL);
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
-}
-
+#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 // Create CNG encoder, init with faulty values, free CNG encoder.
 TEST_F(CngTest, CngInitFail) {
-  // Create encoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-
   // Call with too few parameters.
-  EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
-                                  kCNGNumParamsLow));
-  EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
-
+  EXPECT_DEATH({ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
+                                     kCNGNumParamsLow); }, "");
   // Call with too many parameters.
-  EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
-                                  kCNGNumParamsTooHigh));
-  EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
-
-  // Free encoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-}
-
-TEST_F(CngTest, CngEncode) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
-
-  // Create encoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-
-  // 8 kHz, Normal number of parameters
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 80, sid_data,
-                                &number_bytes, kNoSid));
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 80, sid_data, &number_bytes, kForceSid));
-
-  // 16 kHz, Normal number of parameters
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
-                                &number_bytes, kNoSid));
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
-
-  // 32 kHz, Max number of parameters
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 32000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsHigh));
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 320, sid_data,
-                                &number_bytes, kNoSid));
-  EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 320, sid_data, &number_bytes, kForceSid));
-
-  // 48 kHz, Normal number of parameters
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 48000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 480, sid_data,
-                                &number_bytes, kNoSid));
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 480, sid_data, &number_bytes, kForceSid));
-
-  // 64 kHz, Normal number of parameters
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 64000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
-                                &number_bytes, kNoSid));
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 640, sid_data, &number_bytes, kForceSid));
-
-  // Free encoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
+  EXPECT_DEATH({ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
+                                     kCNGNumParamsTooHigh); }, "");
 }
 
 // Encode Cng with too long input vector.
 TEST_F(CngTest, CngEncodeTooLong) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
+  rtc::Buffer sid_data;
 
-  // Create and init encoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-
+  // Create encoder.
+  ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
+                                  kCNGNumParamsNormal);
   // Run encoder with too much data.
-  EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 641, sid_data,
-                                 &number_bytes, kNoSid));
-  EXPECT_EQ(6140, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
+  EXPECT_DEATH(
+      cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
+                         kNoSid, &sid_data),
+      "");
+}
+#endif  // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 
-  // Free encoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
+TEST_F(CngTest, CngEncode8000) {
+  TestCngEncode(8000, kCNGNumParamsNormal);
 }
 
-// Call encode without calling init.
-TEST_F(CngTest, CngEncodeNoInit) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
+TEST_F(CngTest, CngEncode16000) {
+  TestCngEncode(16000, kCNGNumParamsNormal);
+}
 
-  // Create encoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
+TEST_F(CngTest, CngEncode32000) {
+  TestCngEncode(32000, kCNGNumParamsHigh);
+}
 
-  // Run encoder without calling init.
-  EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
-                                 &number_bytes, kNoSid));
-  EXPECT_EQ(6120, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
+TEST_F(CngTest, CngEncode48000) {
+  TestCngEncode(48000, kCNGNumParamsNormal);
+}
 
-  // Free encoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
+TEST_F(CngTest, CngEncode64000) {
+  TestCngEncode(64000, kCNGNumParamsNormal);
 }
 
 // Update SID parameters, for both 9 and 16 parameters.
 TEST_F(CngTest, CngUpdateSid) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
+  rtc::Buffer sid_data;
 
-  // Create and initialize encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  WebRtcCng_InitDec(cng_dec_inst_);
+  // Create and initialize encoder and decoder.
+  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+                                  kCNGNumParamsNormal);
+  ComfortNoiseDecoder cng_decoder;
 
   // Run normal Encode and UpdateSid.
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
-  EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                   kCNGNumParamsNormal + 1));
+  EXPECT_EQ(kCNGNumParamsNormal + 1,
+            cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+                               kForceSid, &sid_data));
+  cng_decoder.UpdateSid(sid_data);
 
   // Reinit with new length.
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsHigh));
-  WebRtcCng_InitDec(cng_dec_inst_);
+  cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
+  cng_decoder.Reset();
 
   // Expect 0 because of unstable parameters after switching length.
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
-                                &number_bytes, kForceSid));
-  EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_ + 160, 160, sid_data, &number_bytes,
-      kForceSid));
-  EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                   kCNGNumParamsNormal + 1));
-
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
+  EXPECT_EQ(0U,
+            cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+                               kForceSid, &sid_data));
+  EXPECT_EQ(
+      kCNGNumParamsHigh + 1,
+      cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
+                         kForceSid, &sid_data));
+  cng_decoder.UpdateSid(
+      rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
 }
 
 // Update SID parameters, with wrong parameters or without calling decode.
 TEST_F(CngTest, CngUpdateSidErroneous) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
-
-  // Create encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
+  rtc::Buffer sid_data;
 
   // Encode.
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
-
-  // Update Sid before initializing decoder.
-  EXPECT_EQ(-1, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                    kCNGNumParamsNormal + 1));
-  EXPECT_EQ(6220, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
-
-  // Initialize decoder.
-  WebRtcCng_InitDec(cng_dec_inst_);
+  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+                                  kCNGNumParamsNormal);
+  ComfortNoiseDecoder cng_decoder;
+  EXPECT_EQ(kCNGNumParamsNormal + 1,
+            cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+                               kForceSid, &sid_data));
 
   // First run with valid parameters, then with too many CNG parameters.
   // The function will operate correctly by only reading the maximum number of
   // parameters, skipping the extra.
-  EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                   kCNGNumParamsNormal + 1));
-  EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                   kCNGNumParamsTooHigh + 1));
+  EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
+  cng_decoder.UpdateSid(sid_data);
 
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
+  // Make sure the input buffer is large enough. Since Encode() appends data, we
+  // need to set the size manually only afterwards, or the buffer will be bigger
+  // than anticipated.
+  sid_data.SetSize(kCNGNumParamsTooHigh + 1);
+  cng_decoder.UpdateSid(sid_data);
 }
 
 // Test to generate cng data, by forcing SID. Both normal and faulty condition.
 TEST_F(CngTest, CngGenerate) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  rtc::Buffer sid_data;
   int16_t out_data[640];
-  size_t number_bytes;
 
-  // Create and initialize encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  WebRtcCng_InitDec(cng_dec_inst_);
+  // Create and initialize encoder and decoder.
+  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+                                  kCNGNumParamsNormal);
+  ComfortNoiseDecoder cng_decoder;
 
   // Normal Encode.
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
+  EXPECT_EQ(kCNGNumParamsNormal + 1,
+            cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+                               kForceSid, &sid_data));
 
   // Normal UpdateSid.
-  EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
-                                   kCNGNumParamsNormal + 1));
+  cng_decoder.UpdateSid(sid_data);
 
   // Two normal Generate, one with new_period.
-  EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 1));
-  EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 0));
+  EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
+  EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
 
   // Call Genereate with too much data.
-  EXPECT_EQ(-1, WebRtcCng_Generate(cng_dec_inst_, out_data, 641, 0));
-  EXPECT_EQ(6140, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
-
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
+  EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
 }
 
 // Test automatic SID.
 TEST_F(CngTest, CngAutoSid) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
+  rtc::Buffer sid_data;
 
-  // Create and initialize encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  WebRtcCng_InitDec(cng_dec_inst_);
+  // Create and initialize encoder and decoder.
+  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+                                  kCNGNumParamsNormal);
+  ComfortNoiseDecoder cng_decoder;
 
   // Normal Encode, 100 msec, where no SID data should be generated.
   for (int i = 0; i < 10; i++) {
-    EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
-                                  &number_bytes, kNoSid));
+    EXPECT_EQ(0U, cng_encoder.Encode(
+        rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
   }
 
   // We have reached 100 msec, and SID data should be generated.
-  EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-      cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
-
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
+  EXPECT_EQ(kCNGNumParamsNormal + 1, cng_encoder.Encode(
+      rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
 }
 
 // Test automatic SID, with very short interval.
 TEST_F(CngTest, CngAutoSidShort) {
-  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  size_t number_bytes;
+  rtc::Buffer sid_data;
 
-  // Create and initialize encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
-  EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidShortIntervalUpdate,
-                                 kCNGNumParamsNormal));
-  WebRtcCng_InitDec(cng_dec_inst_);
+  // Create and initialize encoder and decoder.
+  ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
+                                  kCNGNumParamsNormal);
+  ComfortNoiseDecoder cng_decoder;
 
   // First call will never generate SID, unless forced to.
-  EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
-                                &number_bytes, kNoSid));
+  EXPECT_EQ(0U, cng_encoder.Encode(
+      rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
 
   // Normal Encode, 100 msec, SID data should be generated all the time.
   for (int i = 0; i < 10; i++) {
-    EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
-        cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
+    EXPECT_EQ(kCNGNumParamsNormal + 1, cng_encoder.Encode(
+        rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
   }
-
-  // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
-  EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 }
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.c b/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.c
deleted file mode 100644
index 8dddc5c..0000000
--- a/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- *  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 "webrtc_cng.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "cng_helpfuns.h"
-#include "signal_processing_library.h"
-
-typedef struct WebRtcCngDecoder_ {
-  uint32_t dec_seed;
-  int32_t dec_target_energy;
-  int32_t dec_used_energy;
-  int16_t dec_target_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_used_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_filtstate[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_filtstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_Efiltstate[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_EfiltstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t dec_order;
-  int16_t dec_target_scale_factor;  /* Q29 */
-  int16_t dec_used_scale_factor;  /* Q29 */
-  int16_t target_scale_factor;  /* Q13 */
-  int16_t errorcode;
-  int16_t initflag;
-} WebRtcCngDecoder;
-
-typedef struct WebRtcCngEncoder_ {
-  size_t enc_nrOfCoefs;
-  int enc_sampfreq;
-  int16_t enc_interval;
-  int16_t enc_msSinceSID;
-  int32_t enc_Energy;
-  int16_t enc_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int32_t enc_corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  uint32_t enc_seed;
-  int16_t errorcode;
-  int16_t initflag;
-} WebRtcCngEncoder;
-
-const int32_t WebRtcCng_kDbov[94] = {
-  1081109975,  858756178,  682134279,  541838517,  430397633,  341876992,
-  271562548,  215709799,  171344384,  136103682,  108110997,   85875618,
-  68213428,   54183852,   43039763,   34187699,   27156255,   21570980,
-  17134438,   13610368,   10811100,    8587562,    6821343,    5418385,
-  4303976,    3418770,    2715625,    2157098,    1713444,    1361037,
-  1081110,     858756,     682134,     541839,     430398,     341877,
-  271563,     215710,     171344,     136104,     108111,      85876,
-  68213,      54184,      43040,      34188,      27156,      21571,
-  17134,      13610,      10811,       8588,       6821,       5418,
-  4304,       3419,       2716,       2157,       1713,       1361,
-  1081,        859,        682,        542,        430,        342,
-  272,        216,        171,        136,        108,         86,
-  68,         54,         43,         34,         27,         22,
-  17,         14,         11,          9,          7,          5,
-  4,          3,          3,          2,          2,           1,
-  1,          1,          1,          1
-};
-
-const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
-  32702, 32636, 32570, 32505, 32439, 32374,
-  32309, 32244, 32179, 32114, 32049, 31985
-};
-
-/****************************************************************************
- * WebRtcCng_CreateEnc/Dec(...)
- *
- * These functions create an instance to the specified structure
- *
- * Input:
- *      - XXX_inst      : Pointer to created instance that should be created
- *
- * Return value         :  0 - Ok
- *                        -1 - Error
- */
-int16_t WebRtcCng_CreateEnc(CNG_enc_inst** cng_inst) {
-  if (cng_inst != NULL) {
-    *cng_inst = (CNG_enc_inst*) malloc(sizeof(WebRtcCngEncoder));
-    if (*cng_inst != NULL) {
-      (*(WebRtcCngEncoder**) cng_inst)->errorcode = 0;
-      (*(WebRtcCngEncoder**) cng_inst)->initflag = 0;
-
-      /* Needed to get the right function pointers in SPLIB. */
-      WebRtcSpl_Init();
-
-      return 0;
-    } else {
-      /* The memory could not be allocated. */
-      return -1;
-    }
-  } else {
-    /* The input pointer is invalid (NULL). */
-    return -1;
-  }
-}
-
-int16_t WebRtcCng_CreateDec(CNG_dec_inst** cng_inst) {
-  if (cng_inst != NULL ) {
-    *cng_inst = (CNG_dec_inst*) malloc(sizeof(WebRtcCngDecoder));
-    if (*cng_inst != NULL ) {
-      (*(WebRtcCngDecoder**) cng_inst)->errorcode = 0;
-      (*(WebRtcCngDecoder**) cng_inst)->initflag = 0;
-
-      /* Needed to get the right function pointers in SPLIB. */
-      WebRtcSpl_Init();
-
-      return 0;
-    } else {
-      /* The memory could not be allocated */
-      return -1;
-    }
-  } else {
-    /* The input pointer is invalid (NULL). */
-    return -1;
-  }
-}
-
-/****************************************************************************
- * WebRtcCng_InitEnc/Dec(...)
- *
- * This function initializes a instance
- *
- * Input:
- *    - cng_inst      : Instance that should be initialized
- *
- *    - fs            : 8000 for narrowband and 16000 for wideband
- *    - interval      : generate SID data every interval ms
- *    - quality       : TBD
- *
- * Output:
- *    - cng_inst      : Initialized instance
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int WebRtcCng_InitEnc(CNG_enc_inst* cng_inst, int fs, int16_t interval,
-                      int16_t quality) {
-  int i;
-  WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst;
-  memset(inst, 0, sizeof(WebRtcCngEncoder));
-
-  /* Check LPC order */
-  if (quality > WEBRTC_CNG_MAX_LPC_ORDER || quality <= 0) {
-    inst->errorcode = CNG_DISALLOWED_LPC_ORDER;
-    return -1;
-  }
-
-  inst->enc_sampfreq = fs;
-  inst->enc_interval = interval;
-  inst->enc_nrOfCoefs = quality;
-  inst->enc_msSinceSID = 0;
-  inst->enc_seed = 7777;  /* For debugging only. */
-  inst->enc_Energy = 0;
-  for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) {
-    inst->enc_reflCoefs[i] = 0;
-    inst->enc_corrVector[i] = 0;
-  }
-  inst->initflag = 1;
-
-  return 0;
-}
-
-void WebRtcCng_InitDec(CNG_dec_inst* cng_inst) {
-  int i;
-
-  WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst;
-
-  memset(inst, 0, sizeof(WebRtcCngDecoder));
-  inst->dec_seed = 7777;  /* For debugging only. */
-  inst->dec_order = 5;
-  inst->dec_target_scale_factor = 0;
-  inst->dec_used_scale_factor = 0;
-  for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) {
-    inst->dec_filtstate[i] = 0;
-    inst->dec_target_reflCoefs[i] = 0;
-    inst->dec_used_reflCoefs[i] = 0;
-  }
-  inst->dec_target_reflCoefs[0] = 0;
-  inst->dec_used_reflCoefs[0] = 0;
-  inst->dec_used_energy = 0;
-  inst->initflag = 1;
-}
-
-/****************************************************************************
- * WebRtcCng_FreeEnc/Dec(...)
- *
- * These functions frees the dynamic memory of a specified instance
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_FreeEnc(CNG_enc_inst* cng_inst) {
-  free(cng_inst);
-  return 0;
-}
-
-int16_t WebRtcCng_FreeDec(CNG_dec_inst* cng_inst) {
-  free(cng_inst);
-  return 0;
-}
-
-/****************************************************************************
- * WebRtcCng_Encode(...)
- *
- * These functions analyzes background noise
- *
- * Input:
- *    - cng_inst      : Pointer to created instance
- *    - speech        : Signal (noise) to be analyzed
- *    - nrOfSamples   : Size of speech vector
- *    - bytesOut      : Nr of bytes to transmit, might be 0
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int WebRtcCng_Encode(CNG_enc_inst* cng_inst, int16_t* speech,
-                     size_t nrOfSamples, uint8_t* SIDdata,
-                     size_t* bytesOut, int16_t forceSID) {
-  WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst;
-
-  int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t hanningW[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
-  int16_t ReflBeta = 19661;  /* 0.6 in q15. */
-  int16_t ReflBetaComp = 13107;  /* 0.4 in q15. */
-  int32_t outEnergy;
-  int outShifts;
-  size_t i;
-  int stab;
-  int acorrScale;
-  size_t index;
-  size_t ind, factor;
-  int32_t* bptr;
-  int32_t blo, bhi;
-  int16_t negate;
-  const int16_t* aptr;
-  int16_t speechBuf[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
-
-  /* Check if encoder initiated. */
-  if (inst->initflag != 1) {
-    inst->errorcode = CNG_ENCODER_NOT_INITIATED;
-    return -1;
-  }
-
-  /* Check framesize. */
-  if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) {
-    inst->errorcode = CNG_DISALLOWED_FRAME_SIZE;
-    return -1;
-  }
-
-  for (i = 0; i < nrOfSamples; i++) {
-    speechBuf[i] = speech[i];
-  }
-
-  factor = nrOfSamples;
-
-  /* Calculate energy and a coefficients. */
-  outEnergy = WebRtcSpl_Energy(speechBuf, nrOfSamples, &outShifts);
-  while (outShifts > 0) {
-    /* We can only do 5 shifts without destroying accuracy in
-     * division factor. */
-    if (outShifts > 5) {
-      outEnergy <<= (outShifts - 5);
-      outShifts = 5;
-    } else {
-      factor /= 2;
-      outShifts--;
-    }
-  }
-  outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor);
-
-  if (outEnergy > 1) {
-    /* Create Hanning Window. */
-    WebRtcSpl_GetHanningWindow(hanningW, nrOfSamples / 2);
-    for (i = 0; i < (nrOfSamples / 2); i++)
-      hanningW[nrOfSamples - i - 1] = hanningW[i];
-
-    WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, nrOfSamples,
-                                    14);
-
-    WebRtcSpl_AutoCorrelation(speechBuf, nrOfSamples, inst->enc_nrOfCoefs,
-                              corrVector, &acorrScale);
-
-    if (*corrVector == 0)
-      *corrVector = WEBRTC_SPL_WORD16_MAX;
-
-    /* Adds the bandwidth expansion. */
-    aptr = WebRtcCng_kCorrWindow;
-    bptr = corrVector;
-
-    /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */
-    for (ind = 0; ind < inst->enc_nrOfCoefs; ind++) {
-      /* The below code multiplies the 16 b corrWindow values (Q15) with
-       * the 32 b corrvector (Q0) and shifts the result down 15 steps. */
-      negate = *bptr < 0;
-      if (negate)
-        *bptr = -*bptr;
-
-      blo = (int32_t) * aptr * (*bptr & 0xffff);
-      bhi = ((blo >> 16) & 0xffff)
-          + ((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff));
-      blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
-
-      *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t) blo >> 15);
-      if (negate)
-        *bptr = -*bptr;
-      bptr++;
-    }
-    /* End of bandwidth expansion. */
-
-    stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs,
-                                    inst->enc_nrOfCoefs);
-
-    if (!stab) {
-      /* Disregard from this frame */
-      *bytesOut = 0;
-      return 0;
-    }
-
-  } else {
-    for (i = 0; i < inst->enc_nrOfCoefs; i++)
-      refCs[i] = 0;
-  }
-
-  if (forceSID) {
-    /* Read instantaneous values instead of averaged. */
-    for (i = 0; i < inst->enc_nrOfCoefs; i++)
-      inst->enc_reflCoefs[i] = refCs[i];
-    inst->enc_Energy = outEnergy;
-  } else {
-    /* Average history with new values. */
-    for (i = 0; i < (inst->enc_nrOfCoefs); i++) {
-      inst->enc_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
-          inst->enc_reflCoefs[i], ReflBeta, 15);
-      inst->enc_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
-          refCs[i], ReflBetaComp, 15);
-    }
-    inst->enc_Energy = (outEnergy >> 2) + (inst->enc_Energy >> 1)
-        + (inst->enc_Energy >> 2);
-  }
-
-  if (inst->enc_Energy < 1) {
-    inst->enc_Energy = 1;
-  }
-
-  if ((inst->enc_msSinceSID > (inst->enc_interval - 1)) || forceSID) {
-
-    /* Search for best dbov value. */
-    index = 0;
-    for (i = 1; i < 93; i++) {
-      /* Always round downwards. */
-      if ((inst->enc_Energy - WebRtcCng_kDbov[i]) > 0) {
-        index = i;
-        break;
-      }
-    }
-    if ((i == 93) && (index == 0))
-      index = 94;
-    SIDdata[0] = (uint8_t)index;
-
-    /* Quantize coefficients with tweak for WebRtc implementation of RFC3389. */
-    if (inst->enc_nrOfCoefs == WEBRTC_CNG_MAX_LPC_ORDER) {
-      for (i = 0; i < inst->enc_nrOfCoefs; i++) {
-        /* Q15 to Q7 with rounding. */
-        SIDdata[i + 1] = ((inst->enc_reflCoefs[i] + 128) >> 8);
-      }
-    } else {
-      for (i = 0; i < inst->enc_nrOfCoefs; i++) {
-        /* Q15 to Q7 with rounding. */
-        SIDdata[i + 1] = (127 + ((inst->enc_reflCoefs[i] + 128) >> 8));
-      }
-    }
-
-    inst->enc_msSinceSID = 0;
-    *bytesOut = inst->enc_nrOfCoefs + 1;
-
-    inst->enc_msSinceSID +=
-        (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq);
-    return (int)(inst->enc_nrOfCoefs + 1);
-  } else {
-    inst->enc_msSinceSID +=
-        (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq);
-    *bytesOut = 0;
-    return 0;
-  }
-}
-
-/****************************************************************************
- * WebRtcCng_UpdateSid(...)
- *
- * These functions updates the CN state, when a new SID packet arrives
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *    - SID           : SID packet, all headers removed
- *    - length        : Length in bytes of SID packet
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_UpdateSid(CNG_dec_inst* cng_inst, uint8_t* SID,
-                            size_t length) {
-
-  WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst;
-  int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER];
-  int32_t targetEnergy;
-  int i;
-
-  if (inst->initflag != 1) {
-    inst->errorcode = CNG_DECODER_NOT_INITIATED;
-    return -1;
-  }
-
-  /* Throw away reflection coefficients of higher order than we can handle. */
-  if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1))
-    length = WEBRTC_CNG_MAX_LPC_ORDER + 1;
-
-  inst->dec_order = (int16_t)length - 1;
-
-  if (SID[0] > 93)
-    SID[0] = 93;
-  targetEnergy = WebRtcCng_kDbov[SID[0]];
-  /* Take down target energy to 75%. */
-  targetEnergy = targetEnergy >> 1;
-  targetEnergy += targetEnergy >> 2;
-
-  inst->dec_target_energy = targetEnergy;
-
-  /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */
-  if (inst->dec_order == WEBRTC_CNG_MAX_LPC_ORDER) {
-    for (i = 0; i < (inst->dec_order); i++) {
-      refCs[i] = SID[i + 1] << 8; /* Q7 to Q15*/
-      inst->dec_target_reflCoefs[i] = refCs[i];
-    }
-  } else {
-    for (i = 0; i < (inst->dec_order); i++) {
-      refCs[i] = (SID[i + 1] - 127) << 8; /* Q7 to Q15. */
-      inst->dec_target_reflCoefs[i] = refCs[i];
-    }
-  }
-
-  for (i = (inst->dec_order); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
-    refCs[i] = 0;
-    inst->dec_target_reflCoefs[i] = refCs[i];
-  }
-
-  return 0;
-}
-
-/****************************************************************************
- * WebRtcCng_Generate(...)
- *
- * These functions generates CN data when needed
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *    - outData       : pointer to area to write CN data
- *    - nrOfSamples   : How much data to generate
- *
- * Return value        :  0 - Ok
- *                       -1 - Error
- */
-int16_t WebRtcCng_Generate(CNG_dec_inst* cng_inst, int16_t* outData,
-                           size_t nrOfSamples, int16_t new_period) {
-  WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst;
-
-  size_t i;
-  int16_t excitation[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
-  int16_t low[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
-  int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1];
-  int16_t ReflBetaStd = 26214;  /* 0.8 in q15. */
-  int16_t ReflBetaCompStd = 6553;  /* 0.2 in q15. */
-  int16_t ReflBetaNewP = 19661;  /* 0.6 in q15. */
-  int16_t ReflBetaCompNewP = 13107;  /* 0.4 in q15. */
-  int16_t Beta, BetaC, tmp1, tmp2, tmp3;
-  int32_t targetEnergy;
-  int16_t En;
-  int16_t temp16;
-
-  if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) {
-    inst->errorcode = CNG_DISALLOWED_FRAME_SIZE;
-    return -1;
-  }
-
-  if (new_period) {
-    inst->dec_used_scale_factor = inst->dec_target_scale_factor;
-    Beta = ReflBetaNewP;
-    BetaC = ReflBetaCompNewP;
-  } else {
-    Beta = ReflBetaStd;
-    BetaC = ReflBetaCompStd;
-  }
-
-  /* Here we use a 0.5 weighting, should possibly be modified to 0.6. */
-  tmp1 = inst->dec_used_scale_factor << 2; /* Q13->Q15 */
-  tmp2 = inst->dec_target_scale_factor << 2; /* Q13->Q15 */
-  tmp3 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp1, Beta, 15);
-  tmp3 += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp2, BetaC, 15);
-  inst->dec_used_scale_factor = tmp3 >> 2; /* Q15->Q13 */
-
-  inst->dec_used_energy = inst->dec_used_energy >> 1;
-  inst->dec_used_energy += inst->dec_target_energy >> 1;
-
-  /* Do the same for the reflection coeffs. */
-  for (i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
-    inst->dec_used_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
-        inst->dec_used_reflCoefs[i], Beta, 15);
-    inst->dec_used_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
-        inst->dec_target_reflCoefs[i], BetaC, 15);
-  }
-
-  /* Compute the polynomial coefficients. */
-  WebRtcCng_K2a16(inst->dec_used_reflCoefs, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
-
-
-  targetEnergy = inst->dec_used_energy;
-
-  /* Calculate scaling factor based on filter energy. */
-  En = 8192;  /* 1.0 in Q13. */
-  for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) {
-
-    /* Floating point value for reference.
-       E *= 1.0 - (inst->dec_used_reflCoefs[i] / 32768.0) *
-       (inst->dec_used_reflCoefs[i] / 32768.0);
-     */
-
-    /* Same in fixed point. */
-    /* K(i).^2 in Q15. */
-    temp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
-        inst->dec_used_reflCoefs[i], inst->dec_used_reflCoefs[i], 15);
-    /* 1 - K(i).^2 in Q15. */
-    temp16 = 0x7fff - temp16;
-    En = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15);
-  }
-
-  /* float scaling= sqrt(E * inst->dec_target_energy / (1 << 24)); */
-
-  /* Calculate sqrt(En * target_energy / excitation energy) */
-  targetEnergy = WebRtcSpl_Sqrt(inst->dec_used_energy);
-
-  En = (int16_t) WebRtcSpl_Sqrt(En) << 6;
-  En = (En * 3) >> 1;  /* 1.5 estimates sqrt(2). */
-  inst->dec_used_scale_factor = (int16_t)((En * targetEnergy) >> 12);
-
-  /* Generate excitation. */
-  /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */
-  for (i = 0; i < nrOfSamples; i++) {
-    excitation[i] = WebRtcSpl_RandN(&inst->dec_seed) >> 1;
-  }
-
-  /* Scale to correct energy. */
-  WebRtcSpl_ScaleVector(excitation, excitation, inst->dec_used_scale_factor,
-                        nrOfSamples, 13);
-
-  /* |lpPoly| - Coefficients in Q12.
-   * |excitation| - Speech samples.
-   * |nst->dec_filtstate| - State preservation.
-   * |outData| - Filtered speech samples. */
-  WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation,
-                     nrOfSamples, inst->dec_filtstate, WEBRTC_CNG_MAX_LPC_ORDER,
-                     inst->dec_filtstateLow, WEBRTC_CNG_MAX_LPC_ORDER, outData,
-                     low, nrOfSamples);
-
-  return 0;
-}
-
-/****************************************************************************
- * WebRtcCng_GetErrorCodeEnc/Dec(...)
- *
- * This functions can be used to check the error code of a CNG 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:
- *    - CNG_inst    : CNG enc/dec instance
- *
- * Return value     : Error code
- */
-int16_t WebRtcCng_GetErrorCodeEnc(CNG_enc_inst* cng_inst) {
-  /* Typecast pointer to real structure. */
-  WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst;
-  return inst->errorcode;
-}
-
-int16_t WebRtcCng_GetErrorCodeDec(CNG_dec_inst* cng_inst) {
-  /* Typecast pointer to real structure. */
-  WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst;
-  return inst->errorcode;
-}
diff --git a/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc b/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc
new file mode 100644
index 0000000..b4da260
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc
@@ -0,0 +1,442 @@
+/*
+ *  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 "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
+
+#include <algorithm>
+
+#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
+
+namespace webrtc {
+
+namespace {
+
+const size_t kCngMaxOutsizeOrder = 640;
+
+// TODO(ossu): Rename the left-over WebRtcCng according to style guide.
+void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a);
+
+const int32_t WebRtcCng_kDbov[94] = {
+  1081109975, 858756178, 682134279, 541838517, 430397633, 341876992,
+  271562548,  215709799, 171344384, 136103682, 108110997, 85875618,
+  68213428,   54183852,  43039763,  34187699,  27156255,  21570980,
+  17134438,   13610368,  10811100,  8587562,   6821343,   5418385,
+  4303976,    3418770,   2715625,   2157098,   1713444,   1361037,
+  1081110,    858756,    682134,    541839,    430398,    341877,
+  271563,     215710,    171344,    136104,    108111,    85876,
+  68213,      54184,     43040,     34188,     27156,     21571,
+  17134,      13610,     10811,     8588,      6821,      5418,
+  4304,       3419,      2716,      2157,      1713,      1361,
+  1081,       859,       682,       542,       430,       342,
+  272,        216,       171,       136,       108,       86,
+  68,         54,        43,        34,        27,        22,
+  17,         14,        11,        9,         7,         5,
+  4,          3,         3,         2,         2,         1,
+  1,          1,         1,         1
+};
+
+const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
+  32702, 32636, 32570, 32505, 32439, 32374,
+  32309, 32244, 32179, 32114, 32049, 31985
+};
+
+}  // namespace
+
+ComfortNoiseDecoder::ComfortNoiseDecoder() {
+  /* Needed to get the right function pointers in SPLIB. */
+  WebRtcSpl_Init();
+  Reset();
+}
+
+void ComfortNoiseDecoder::Reset() {
+  dec_seed_ = 7777;  /* For debugging only. */
+  dec_target_energy_ = 0;
+  dec_used_energy_ = 0;
+  for (auto& c : dec_target_reflCoefs_)
+    c = 0;
+  for (auto& c : dec_used_reflCoefs_)
+    c = 0;
+  for (auto& c : dec_filtstate_)
+    c = 0;
+  for (auto& c : dec_filtstateLow_)
+    c = 0;
+  dec_order_ = 5;
+  dec_target_scale_factor_ = 0;
+  dec_used_scale_factor_ = 0;
+}
+
+void ComfortNoiseDecoder::UpdateSid(rtc::ArrayView<const uint8_t> sid) {
+  int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER];
+  int32_t targetEnergy;
+  size_t length = sid.size();
+  /* Throw away reflection coefficients of higher order than we can handle. */
+  if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1))
+    length = WEBRTC_CNG_MAX_LPC_ORDER + 1;
+
+  dec_order_ = static_cast<uint16_t>(length - 1);
+
+  uint8_t sid0 = std::min<uint8_t>(sid[0], 93);
+  targetEnergy = WebRtcCng_kDbov[sid0];
+  /* Take down target energy to 75%. */
+  targetEnergy = targetEnergy >> 1;
+  targetEnergy += targetEnergy >> 2;
+
+  dec_target_energy_ = targetEnergy;
+
+  /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */
+  if (dec_order_ == WEBRTC_CNG_MAX_LPC_ORDER) {
+    for (size_t i = 0; i < (dec_order_); i++) {
+      refCs[i] = sid[i + 1] << 8; /* Q7 to Q15*/
+      dec_target_reflCoefs_[i] = refCs[i];
+    }
+  } else {
+    for (size_t i = 0; i < (dec_order_); i++) {
+      refCs[i] = (sid[i + 1] - 127) << 8; /* Q7 to Q15. */
+      dec_target_reflCoefs_[i] = refCs[i];
+    }
+  }
+
+  for (size_t i = (dec_order_); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
+    refCs[i] = 0;
+    dec_target_reflCoefs_[i] = refCs[i];
+  }
+}
+
+bool ComfortNoiseDecoder::Generate(rtc::ArrayView<int16_t> out_data,
+                                   bool new_period) {
+  int16_t excitation[kCngMaxOutsizeOrder];
+  int16_t low[kCngMaxOutsizeOrder];
+  int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t ReflBetaStd = 26214;  /* 0.8 in q15. */
+  int16_t ReflBetaCompStd = 6553;  /* 0.2 in q15. */
+  int16_t ReflBetaNewP = 19661;  /* 0.6 in q15. */
+  int16_t ReflBetaCompNewP = 13107;  /* 0.4 in q15. */
+  int16_t Beta, BetaC, tmp1, tmp2, tmp3;
+  int32_t targetEnergy;
+  int16_t En;
+  int16_t temp16;
+  const size_t num_samples = out_data.size();
+
+  if (num_samples > kCngMaxOutsizeOrder) {
+    return false;
+  }
+
+  if (new_period) {
+    dec_used_scale_factor_ = dec_target_scale_factor_;
+    Beta = ReflBetaNewP;
+    BetaC = ReflBetaCompNewP;
+  } else {
+    Beta = ReflBetaStd;
+    BetaC = ReflBetaCompStd;
+  }
+
+  /* Here we use a 0.5 weighting, should possibly be modified to 0.6. */
+  tmp1 = dec_used_scale_factor_ << 2; /* Q13->Q15 */
+  tmp2 = dec_target_scale_factor_ << 2; /* Q13->Q15 */
+  tmp3 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp1, Beta, 15);
+  tmp3 += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp2, BetaC, 15);
+  dec_used_scale_factor_ = tmp3 >> 2; /* Q15->Q13 */
+
+  dec_used_energy_  = dec_used_energy_ >> 1;
+  dec_used_energy_ += dec_target_energy_ >> 1;
+
+  /* Do the same for the reflection coeffs. */
+  for (size_t i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
+    dec_used_reflCoefs_[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
+        dec_used_reflCoefs_[i], Beta, 15);
+    dec_used_reflCoefs_[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
+        dec_target_reflCoefs_[i], BetaC, 15);
+  }
+
+  /* Compute the polynomial coefficients. */
+  WebRtcCng_K2a16(dec_used_reflCoefs_, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
+
+
+  targetEnergy = dec_used_energy_;
+
+  /* Calculate scaling factor based on filter energy. */
+  En = 8192;  /* 1.0 in Q13. */
+  for (size_t i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) {
+    /* Floating point value for reference.
+       E *= 1.0 - (dec_used_reflCoefs_[i] / 32768.0) *
+       (dec_used_reflCoefs_[i] / 32768.0);
+     */
+
+    /* Same in fixed point. */
+    /* K(i).^2 in Q15. */
+    temp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
+        dec_used_reflCoefs_[i], dec_used_reflCoefs_[i], 15);
+    /* 1 - K(i).^2 in Q15. */
+    temp16 = 0x7fff - temp16;
+    En = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15);
+  }
+
+  /* float scaling= sqrt(E * dec_target_energy_ / (1 << 24)); */
+
+  /* Calculate sqrt(En * target_energy / excitation energy) */
+  targetEnergy = WebRtcSpl_Sqrt(dec_used_energy_);
+
+  En = (int16_t) WebRtcSpl_Sqrt(En) << 6;
+  En = (En * 3) >> 1;  /* 1.5 estimates sqrt(2). */
+  dec_used_scale_factor_ = (int16_t)((En * targetEnergy) >> 12);
+
+  /* Generate excitation. */
+  /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */
+  for (size_t i = 0; i < num_samples; i++) {
+    excitation[i] = WebRtcSpl_RandN(&dec_seed_) >> 1;
+  }
+
+  /* Scale to correct energy. */
+  WebRtcSpl_ScaleVector(excitation, excitation, dec_used_scale_factor_,
+                        num_samples, 13);
+
+  /* |lpPoly| - Coefficients in Q12.
+   * |excitation| - Speech samples.
+   * |nst->dec_filtstate| - State preservation.
+   * |out_data| - Filtered speech samples. */
+  WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation,
+                     num_samples, dec_filtstate_, WEBRTC_CNG_MAX_LPC_ORDER,
+                     dec_filtstateLow_, WEBRTC_CNG_MAX_LPC_ORDER,
+                     out_data.data(), low, num_samples);
+
+  return true;
+}
+
+ComfortNoiseEncoder::ComfortNoiseEncoder(int fs, int interval, int quality)
+    : enc_nrOfCoefs_(quality),
+      enc_sampfreq_(fs),
+      enc_interval_(interval),
+      enc_msSinceSid_(0),
+      enc_Energy_(0),
+      enc_reflCoefs_{0},
+      enc_corrVector_{0},
+      enc_seed_(7777)  /* For debugging only. */ {
+  RTC_CHECK(quality <= WEBRTC_CNG_MAX_LPC_ORDER && quality > 0);
+  /* Needed to get the right function pointers in SPLIB. */
+  WebRtcSpl_Init();
+}
+
+void ComfortNoiseEncoder::Reset(int fs, int interval, int quality) {
+  RTC_CHECK(quality <= WEBRTC_CNG_MAX_LPC_ORDER && quality > 0);
+  enc_nrOfCoefs_ = quality;
+  enc_sampfreq_ = fs;
+  enc_interval_ = interval;
+  enc_msSinceSid_ = 0;
+  enc_Energy_ = 0;
+  for (auto& c : enc_reflCoefs_)
+    c = 0;
+  for (auto& c : enc_corrVector_)
+    c = 0;
+  enc_seed_ = 7777;  /* For debugging only. */
+}
+
+size_t ComfortNoiseEncoder::Encode(rtc::ArrayView<const int16_t> speech,
+                                   bool force_sid,
+                                   rtc::Buffer* output) {
+  int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t hanningW[kCngMaxOutsizeOrder];
+  int16_t ReflBeta = 19661;     /* 0.6 in q15. */
+  int16_t ReflBetaComp = 13107; /* 0.4 in q15. */
+  int32_t outEnergy;
+  int outShifts;
+  size_t i;
+  int stab;
+  int acorrScale;
+  size_t index;
+  size_t ind, factor;
+  int32_t* bptr;
+  int32_t blo, bhi;
+  int16_t negate;
+  const int16_t* aptr;
+  int16_t speechBuf[kCngMaxOutsizeOrder];
+
+  const size_t num_samples = speech.size();
+  RTC_CHECK_LE(num_samples, static_cast<size_t>(kCngMaxOutsizeOrder));
+
+  for (i = 0; i < num_samples; i++) {
+    speechBuf[i] = speech[i];
+  }
+
+  factor = num_samples;
+
+  /* Calculate energy and a coefficients. */
+  outEnergy = WebRtcSpl_Energy(speechBuf, num_samples, &outShifts);
+  while (outShifts > 0) {
+    /* We can only do 5 shifts without destroying accuracy in
+     * division factor. */
+    if (outShifts > 5) {
+      outEnergy <<= (outShifts - 5);
+      outShifts = 5;
+    } else {
+      factor /= 2;
+      outShifts--;
+    }
+  }
+  outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor);
+
+  if (outEnergy > 1) {
+    /* Create Hanning Window. */
+    WebRtcSpl_GetHanningWindow(hanningW, num_samples / 2);
+    for (i = 0; i < (num_samples / 2); i++)
+      hanningW[num_samples - i - 1] = hanningW[i];
+
+    WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, num_samples,
+                                    14);
+
+    WebRtcSpl_AutoCorrelation(speechBuf, num_samples, enc_nrOfCoefs_,
+                              corrVector, &acorrScale);
+
+    if (*corrVector == 0)
+      *corrVector = WEBRTC_SPL_WORD16_MAX;
+
+    /* Adds the bandwidth expansion. */
+    aptr = WebRtcCng_kCorrWindow;
+    bptr = corrVector;
+
+    /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */
+    for (ind = 0; ind < enc_nrOfCoefs_; ind++) {
+      /* The below code multiplies the 16 b corrWindow values (Q15) with
+       * the 32 b corrvector (Q0) and shifts the result down 15 steps. */
+      negate = *bptr < 0;
+      if (negate)
+        *bptr = -*bptr;
+
+      blo = (int32_t) * aptr * (*bptr & 0xffff);
+      bhi = ((blo >> 16) & 0xffff)
+          + ((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff));
+      blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
+
+      *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t) blo >> 15);
+      if (negate)
+        *bptr = -*bptr;
+      bptr++;
+    }
+    /* End of bandwidth expansion. */
+
+    stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs,
+                                    enc_nrOfCoefs_);
+
+    if (!stab) {
+      /* Disregard from this frame */
+      return 0;
+    }
+
+  } else {
+    for (i = 0; i < enc_nrOfCoefs_; i++)
+      refCs[i] = 0;
+  }
+
+  if (force_sid) {
+    /* Read instantaneous values instead of averaged. */
+    for (i = 0; i < enc_nrOfCoefs_; i++)
+      enc_reflCoefs_[i] = refCs[i];
+    enc_Energy_ = outEnergy;
+  } else {
+    /* Average history with new values. */
+    for (i = 0; i < enc_nrOfCoefs_; i++) {
+      enc_reflCoefs_[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
+          enc_reflCoefs_[i], ReflBeta, 15);
+      enc_reflCoefs_[i] +=
+          (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(refCs[i], ReflBetaComp, 15);
+    }
+    enc_Energy_ =
+        (outEnergy >> 2) + (enc_Energy_ >> 1) + (enc_Energy_ >> 2);
+  }
+
+  if (enc_Energy_ < 1) {
+    enc_Energy_ = 1;
+  }
+
+  if ((enc_msSinceSid_ > (enc_interval_ - 1)) || force_sid) {
+    /* Search for best dbov value. */
+    index = 0;
+    for (i = 1; i < 93; i++) {
+      /* Always round downwards. */
+      if ((enc_Energy_ - WebRtcCng_kDbov[i]) > 0) {
+        index = i;
+        break;
+      }
+    }
+    if ((i == 93) && (index == 0))
+      index = 94;
+
+    const size_t output_coefs = enc_nrOfCoefs_ + 1;
+    output->AppendData(output_coefs, [&] (rtc::ArrayView<uint8_t> output) {
+        output[0] = (uint8_t)index;
+
+        /* Quantize coefficients with tweak for WebRtc implementation of
+         * RFC3389. */
+        if (enc_nrOfCoefs_ == WEBRTC_CNG_MAX_LPC_ORDER) {
+          for (i = 0; i < enc_nrOfCoefs_; i++) {
+            /* Q15 to Q7 with rounding. */
+            output[i + 1] = ((enc_reflCoefs_[i] + 128) >> 8);
+          }
+        } else {
+          for (i = 0; i < enc_nrOfCoefs_; i++) {
+            /* Q15 to Q7 with rounding. */
+            output[i + 1] = (127 + ((enc_reflCoefs_[i] + 128) >> 8));
+          }
+        }
+
+        return output_coefs;
+      });
+
+    enc_msSinceSid_ =
+        static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
+    return output_coefs;
+  } else {
+    enc_msSinceSid_ +=
+        static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
+    return 0;
+  }
+}
+
+namespace {
+/* Values in |k| are Q15, and |a| Q12. */
+void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a) {
+  int16_t any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
+  int16_t* aptr;
+  int16_t* aptr2;
+  int16_t* anyptr;
+  const int16_t* kptr;
+  int m, i;
+
+  kptr = k;
+  *a = 4096; /* i.e., (Word16_MAX >> 3) + 1 */
+  *any = *a;
+  a[1] = (*k + 4) >> 3;
+  for (m = 1; m < useOrder; m++) {
+    kptr++;
+    aptr = a;
+    aptr++;
+    aptr2 = &a[m];
+    anyptr = any;
+    anyptr++;
+
+    any[m + 1] = (*kptr + 4) >> 3;
+    for (i = 0; i < m; i++) {
+      *anyptr++ =
+          (*aptr++) +
+          (int16_t)((((int32_t)(*aptr2--) * (int32_t)*kptr) + 16384) >> 15);
+    }
+
+    aptr = a;
+    anyptr = any;
+    for (i = 0; i < (m + 2); i++) {
+      *aptr++ = *anyptr++;
+    }
+  }
+}
+
+}  // namespace
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h b/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h
index 64bea1e..fb0a53d 100644
--- a/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h
+++ b/webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h
@@ -12,152 +12,88 @@
 #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
 
-#include <stddef.h>
+#include <cstddef>
+
+#include "webrtc/base/array_view.h"
+#include "webrtc/base/buffer.h"
 #include "webrtc/typedefs.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define WEBRTC_CNG_MAX_LPC_ORDER 12
-#define WEBRTC_CNG_MAX_OUTSIZE_ORDER 640
 
-/* Define Error codes. */
+namespace webrtc {
 
-/* 6100 Encoder */
-#define CNG_ENCODER_NOT_INITIATED               6120
-#define CNG_DISALLOWED_LPC_ORDER                6130
-#define CNG_DISALLOWED_FRAME_SIZE               6140
-#define CNG_DISALLOWED_SAMPLING_FREQUENCY       6150
-/* 6200 Decoder */
-#define CNG_DECODER_NOT_INITIATED               6220
+class ComfortNoiseDecoder {
+ public:
+  ComfortNoiseDecoder();
+  ~ComfortNoiseDecoder() = default;
 
-typedef struct WebRtcCngEncInst CNG_enc_inst;
-typedef struct WebRtcCngDecInst CNG_dec_inst;
+  ComfortNoiseDecoder(const ComfortNoiseDecoder&) = delete;
+  ComfortNoiseDecoder& operator=(const ComfortNoiseDecoder&) = delete;
 
-/****************************************************************************
- * WebRtcCng_CreateEnc/Dec(...)
- *
- * These functions create an instance to the specified structure
- *
- * Input:
- *    - XXX_inst      : Pointer to created instance that should be created
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_CreateEnc(CNG_enc_inst** cng_inst);
-int16_t WebRtcCng_CreateDec(CNG_dec_inst** cng_inst);
+  void Reset();
 
-/****************************************************************************
- * WebRtcCng_InitEnc/Dec(...)
- *
- * This function initializes a instance
- *
- * Input:
- *    - cng_inst      : Instance that should be initialized
- *
- *    - fs            : 8000 for narrowband and 16000 for wideband
- *    - interval      : generate SID data every interval ms
- *    - quality       : Number of refl. coefs, maximum allowed is 12
- *
- * Output:
- *    - cng_inst      : Initialized instance
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
+  // Updates the CN state when a new SID packet arrives.
+  // |sid| is a view of the SID packet without the headers.
+  void UpdateSid(rtc::ArrayView<const uint8_t> sid);
 
-int WebRtcCng_InitEnc(CNG_enc_inst* cng_inst, int fs, int16_t interval,
-                      int16_t quality);
-void WebRtcCng_InitDec(CNG_dec_inst* cng_inst);
+  // Generates comfort noise.
+  // |out_data| will be filled with samples - its size determines the number of
+  // samples generated. When |new_period| is true, CNG history will be reset
+  // before any audio is generated.  Returns |false| if outData is too large -
+  // currently 640 bytes (equalling 10ms at 64kHz).
+  // TODO(ossu): Specify better limits for the size of out_data. Either let it
+  //             be unbounded or limit to 10ms in the current sample rate.
+  bool Generate(rtc::ArrayView<int16_t> out_data, bool new_period);
 
-/****************************************************************************
- * WebRtcCng_FreeEnc/Dec(...)
- *
- * These functions frees the dynamic memory of a specified instance
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_FreeEnc(CNG_enc_inst* cng_inst);
-int16_t WebRtcCng_FreeDec(CNG_dec_inst* cng_inst);
+ private:
+  uint32_t dec_seed_;
+  int32_t dec_target_energy_;
+  int32_t dec_used_energy_;
+  int16_t dec_target_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t dec_used_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t dec_filtstate_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int16_t dec_filtstateLow_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  uint16_t dec_order_;
+  int16_t dec_target_scale_factor_;  /* Q29 */
+  int16_t dec_used_scale_factor_;  /* Q29 */
+};
 
-/****************************************************************************
- * WebRtcCng_Encode(...)
- *
- * These functions analyzes background noise
- *
- * Input:
- *    - cng_inst      : Pointer to created instance
- *    - speech        : Signal to be analyzed
- *    - nrOfSamples   : Size of speech vector
- *    - forceSID      : not zero to force SID frame and reset
- *
- * Output:
- *    - bytesOut      : Nr of bytes to transmit, might be 0
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int WebRtcCng_Encode(CNG_enc_inst* cng_inst, int16_t* speech,
-                     size_t nrOfSamples, uint8_t* SIDdata,
-                     size_t* bytesOut, int16_t forceSID);
+class ComfortNoiseEncoder {
+ public:
+  // Creates a comfort noise encoder.
+  // |fs| selects sample rate: 8000 for narrowband or 16000 for wideband.
+  // |interval| sets the interval at which to generate SID data (in ms).
+  // |quality| selects the number of refl. coeffs. Maximum allowed is 12.
+  ComfortNoiseEncoder(int fs, int interval, int quality);
+  ~ComfortNoiseEncoder() = default;
 
-/****************************************************************************
- * WebRtcCng_UpdateSid(...)
- *
- * These functions updates the CN state, when a new SID packet arrives
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *    - SID           : SID packet, all headers removed
- *    - length        : Length in bytes of SID packet
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_UpdateSid(CNG_dec_inst* cng_inst, uint8_t* SID,
-                            size_t length);
+  ComfortNoiseEncoder(const ComfortNoiseEncoder&) = delete;
+  ComfortNoiseEncoder& operator=(const ComfortNoiseEncoder&) = delete;
 
-/****************************************************************************
- * WebRtcCng_Generate(...)
- *
- * These functions generates CN data when needed
- *
- * Input:
- *    - cng_inst      : Pointer to created instance that should be freed
- *    - outData       : pointer to area to write CN data
- *    - nrOfSamples   : How much data to generate
- *    - new_period    : >0 if a new period of CNG, will reset history
- *
- * Return value       :  0 - Ok
- *                      -1 - Error
- */
-int16_t WebRtcCng_Generate(CNG_dec_inst* cng_inst, int16_t* outData,
-                           size_t nrOfSamples, int16_t new_period);
+  // Resets the comfort noise encoder to its initial state.
+  // Parameters are set as during construction.
+  void Reset(int fs, int interval, int quality);
 
-/*****************************************************************************
- * WebRtcCng_GetErrorCodeEnc/Dec(...)
- *
- * This functions can be used to check the error code of a CNG 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:
- *    - CNG_inst    : CNG enc/dec instance
- *
- * Return value     : Error code
- */
-int16_t WebRtcCng_GetErrorCodeEnc(CNG_enc_inst* cng_inst);
-int16_t WebRtcCng_GetErrorCodeDec(CNG_dec_inst* cng_inst);
+  // Analyzes background noise from |speech| and appends coefficients to
+  // |output|.  Returns the number of coefficients generated.  If |force_sid| is
+  // true, a SID frame is forced and the internal sid interval counter is reset.
+  // Will fail if the input size is too large (> 640 samples, see
+  // ComfortNoiseDecoder::Generate).
+  size_t Encode(rtc::ArrayView<const int16_t> speech,
+                bool force_sid,
+                rtc::Buffer* output);
 
-#ifdef __cplusplus
-}
-#endif
+ private:
+  size_t enc_nrOfCoefs_;
+  int enc_sampfreq_;
+  int16_t enc_interval_;
+  int16_t enc_msSinceSid_;
+  int32_t enc_Energy_;
+  int16_t enc_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  int32_t enc_corrVector_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+  uint32_t enc_seed_;
+};
+
+}  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
index d800cc7..c9b9b6a 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
@@ -13,7 +13,6 @@
 #include <assert.h>
 
 #include "webrtc/base/checks.h"
-#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
 #ifdef WEBRTC_CODEC_G722
 #include "webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h"
@@ -36,43 +35,6 @@
 
 namespace webrtc {
 
-AudioDecoderCng::AudioDecoderCng() {
-  RTC_CHECK_EQ(0, WebRtcCng_CreateDec(&dec_state_));
-  WebRtcCng_InitDec(dec_state_);
-}
-
-AudioDecoderCng::~AudioDecoderCng() {
-  WebRtcCng_FreeDec(dec_state_);
-}
-
-void AudioDecoderCng::Reset() {
-  WebRtcCng_InitDec(dec_state_);
-}
-
-int AudioDecoderCng::IncomingPacket(const uint8_t* payload,
-                                    size_t payload_len,
-                                    uint16_t rtp_sequence_number,
-                                    uint32_t rtp_timestamp,
-                                    uint32_t arrival_timestamp) {
-  return -1;
-}
-
-CNG_dec_inst* AudioDecoderCng::CngDecoderInstance() {
-  return dec_state_;
-}
-
-size_t AudioDecoderCng::Channels() const {
-  return 1;
-}
-
-int AudioDecoderCng::DecodeInternal(const uint8_t* encoded,
-                                    size_t encoded_len,
-                                    int sample_rate_hz,
-                                    int16_t* decoded,
-                                    SpeechType* speech_type) {
-  return -1;
-}
-
 bool CodecSupported(NetEqDecoder codec_type) {
   switch (codec_type) {
     case NetEqDecoder::kDecoderPCMu:
@@ -228,7 +190,7 @@
     case NetEqDecoder::kDecoderCNGwb:
     case NetEqDecoder::kDecoderCNGswb32kHz:
     case NetEqDecoder::kDecoderCNGswb48kHz:
-      return new AudioDecoderCng;
+      RTC_CHECK(false) << "CNG should not be created like this anymore!";
     case NetEqDecoder::kDecoderRED:
     case NetEqDecoder::kDecoderAVT:
     case NetEqDecoder::kDecoderArbitrary:
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
index bc8bdd9..d9a1d81 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
@@ -16,7 +16,6 @@
 #include "webrtc/engine_configurations.h"
 #include "webrtc/base/constructormagic.h"
 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
-#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #ifdef WEBRTC_CODEC_G722
 #include "webrtc/modules/audio_coding/codecs/g722/g722_interface.h"
 #endif
@@ -25,38 +24,6 @@
 
 namespace webrtc {
 
-// AudioDecoderCng is a special type of AudioDecoder. It inherits from
-// AudioDecoder just to fit in the DecoderDatabase. None of the class methods
-// should be used, except constructor, destructor, and accessors.
-// TODO(hlundin): Consider the possibility to create a super-class to
-// AudioDecoder that is stored in DecoderDatabase. Then AudioDecoder and a
-// specific CngDecoder class could both inherit from that class.
-class AudioDecoderCng : public AudioDecoder {
- public:
-  explicit AudioDecoderCng();
-  ~AudioDecoderCng() override;
-  void Reset() override;
-  int IncomingPacket(const uint8_t* payload,
-                     size_t payload_len,
-                     uint16_t rtp_sequence_number,
-                     uint32_t rtp_timestamp,
-                     uint32_t arrival_timestamp) override;
-
-  CNG_dec_inst* CngDecoderInstance() override;
-  size_t Channels() const override;
-
- protected:
-  int DecodeInternal(const uint8_t* encoded,
-                     size_t encoded_len,
-                     int sample_rate_hz,
-                     int16_t* decoded,
-                     SpeechType* speech_type) override;
-
- private:
-  CNG_dec_inst* dec_state_;
-  RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderCng);
-};
-
 using NetEqDecoder = acm2::RentACodec::NetEqDecoder;
 
 // Returns true if |codec_type| is supported.
diff --git a/webrtc/modules/audio_coding/neteq/comfort_noise.cc b/webrtc/modules/audio_coding/neteq/comfort_noise.cc
index a5b0846..2a512bd 100644
--- a/webrtc/modules/audio_coding/neteq/comfort_noise.cc
+++ b/webrtc/modules/audio_coding/neteq/comfort_noise.cc
@@ -14,7 +14,6 @@
 
 #include "webrtc/base/logging.h"
 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
-#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
 #include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
 #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
@@ -23,31 +22,23 @@
 
 void ComfortNoise::Reset() {
   first_call_ = true;
-  internal_error_code_ = 0;
 }
 
 int ComfortNoise::UpdateParameters(Packet* packet) {
   assert(packet);  // Existence is verified by caller.
   // Get comfort noise decoder.
-  AudioDecoder* cng_decoder = decoder_database_->GetDecoder(
-      packet->header.payloadType);
-  if (!cng_decoder) {
+  if (decoder_database_->SetActiveCngDecoder(packet->header.payloadType)
+      != kOK) {
     delete [] packet->payload;
     delete packet;
     return kUnknownPayloadType;
   }
-  decoder_database_->SetActiveCngDecoder(packet->header.payloadType);
-  CNG_dec_inst* cng_inst = cng_decoder->CngDecoderInstance();
-  int16_t ret = WebRtcCng_UpdateSid(cng_inst,
-                                    packet->payload,
-                                    packet->payload_length);
+  ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
+  RTC_DCHECK(cng_decoder);
+  cng_decoder->UpdateSid(rtc::ArrayView<const uint8_t>(
+      packet->payload, packet->payload_length));
   delete [] packet->payload;
   delete packet;
-  if (ret < 0) {
-    internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
-    LOG(LS_ERROR) << "WebRtcCng_UpdateSid produced " << internal_error_code_;
-    return kInternalError;
-  }
   return kOK;
 }
 
@@ -63,28 +54,28 @@
   }
 
   size_t number_of_samples = requested_length;
-  int16_t new_period = 0;
+  bool new_period = false;
   if (first_call_) {
     // Generate noise and overlap slightly with old data.
     number_of_samples = requested_length + overlap_length_;
-    new_period = 1;
+    new_period = true;
   }
   output->AssertSize(number_of_samples);
   // Get the decoder from the database.
-  AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
+  ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
   if (!cng_decoder) {
     LOG(LS_ERROR) << "Unknwown payload type";
     return kUnknownPayloadType;
   }
-  CNG_dec_inst* cng_inst = cng_decoder->CngDecoderInstance();
   // The expression &(*output)[0][0] is a pointer to the first element in
   // the first channel.
-  if (WebRtcCng_Generate(cng_inst, &(*output)[0][0], number_of_samples,
-                         new_period) < 0) {
+  if (!cng_decoder->Generate(
+          rtc::ArrayView<int16_t>(&(*output)[0][0], number_of_samples),
+          new_period)) {
     // Error returned.
     output->Zeros(requested_length);
-    internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
-    LOG(LS_ERROR) << "WebRtcCng_Generate produced " << internal_error_code_;
+    LOG(LS_ERROR) <<
+        "ComfortNoiseDecoder::Genererate failed to generate comfort noise";
     return kInternalError;
   }
 
diff --git a/webrtc/modules/audio_coding/neteq/comfort_noise.h b/webrtc/modules/audio_coding/neteq/comfort_noise.h
index 1fc2258..f877bf6 100644
--- a/webrtc/modules/audio_coding/neteq/comfort_noise.h
+++ b/webrtc/modules/audio_coding/neteq/comfort_noise.h
@@ -38,8 +38,7 @@
         first_call_(true),
         overlap_length_(5 * fs_hz_ / 8000),
         decoder_database_(decoder_database),
-        sync_buffer_(sync_buffer),
-        internal_error_code_(0) {
+        sync_buffer_(sync_buffer) {
   }
 
   // Resets the state. Should be called before each new comfort noise period.
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc
index d501f3e..c163bbd 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.cc
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc
@@ -20,9 +20,10 @@
 namespace webrtc {
 
 DecoderDatabase::DecoderDatabase()
-    : active_decoder_(-1), active_cng_decoder_(-1) {}
+    : active_decoder_type_(-1), active_cng_decoder_type_(-1) {
+}
 
-DecoderDatabase::~DecoderDatabase() {}
+DecoderDatabase::~DecoderDatabase() = default;
 
 DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
                                           const std::string& nm,
@@ -54,8 +55,8 @@
 
 void DecoderDatabase::Reset() {
   decoders_.clear();
-  active_decoder_ = -1;
-  active_cng_decoder_ = -1;
+  active_decoder_type_ = -1;
+  active_cng_decoder_type_ = -1;
 }
 
 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
@@ -110,11 +111,11 @@
     // No decoder with that |rtp_payload_type|.
     return kDecoderNotFound;
   }
-  if (active_decoder_ == rtp_payload_type) {
-    active_decoder_ = -1;  // No active decoder.
+  if (active_decoder_type_ == rtp_payload_type) {
+    active_decoder_type_ = -1;  // No active decoder.
   }
-  if (active_cng_decoder_ == rtp_payload_type) {
-    active_cng_decoder_ = -1;  // No active CNG decoder.
+  if (active_cng_decoder_type_ == rtp_payload_type) {
+    active_cng_decoder_type_ = -1;  // No active CNG decoder.
   }
   return kOK;
 }
@@ -143,7 +144,8 @@
 }
 
 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
-  if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) {
+  if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type) ||
+      IsComfortNoise(rtp_payload_type)) {
     // These are not real decoders.
     return NULL;
   }
@@ -193,14 +195,15 @@
     // Decoder not found.
     return kDecoderNotFound;
   }
+  RTC_CHECK(!IsComfortNoise(rtp_payload_type));
   assert(new_decoder);
   *new_decoder = false;
-  if (active_decoder_ < 0) {
+  if (active_decoder_type_ < 0) {
     // This is the first active decoder.
     *new_decoder = true;
-  } else if (active_decoder_ != rtp_payload_type) {
+  } else if (active_decoder_type_ != rtp_payload_type) {
     // Moving from one active decoder to another. Delete the first one.
-    DecoderMap::iterator it = decoders_.find(active_decoder_);
+    DecoderMap::iterator it = decoders_.find(active_decoder_type_);
     if (it == decoders_.end()) {
       // Decoder not found. This should not be possible.
       assert(false);
@@ -209,16 +212,16 @@
     it->second.DropDecoder();
     *new_decoder = true;
   }
-  active_decoder_ = rtp_payload_type;
+  active_decoder_type_ = rtp_payload_type;
   return kOK;
 }
 
 AudioDecoder* DecoderDatabase::GetActiveDecoder() {
-  if (active_decoder_ < 0) {
+  if (active_decoder_type_ < 0) {
     // No active decoder.
     return NULL;
   }
-  return GetDecoder(active_decoder_);
+  return GetDecoder(active_decoder_type_);
 }
 
 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
@@ -228,26 +231,32 @@
     // Decoder not found.
     return kDecoderNotFound;
   }
-  if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) {
+  if (active_cng_decoder_type_ >= 0 &&
+      active_cng_decoder_type_ != rtp_payload_type) {
     // Moving from one active CNG decoder to another. Delete the first one.
-    DecoderMap::iterator it = decoders_.find(active_cng_decoder_);
+    DecoderMap::iterator it = decoders_.find(active_cng_decoder_type_);
     if (it == decoders_.end()) {
       // Decoder not found. This should not be possible.
       assert(false);
       return kDecoderNotFound;
     }
-    it->second.DropDecoder();
+    // The CNG decoder should never be provided externally.
+    RTC_CHECK(!it->second.external_decoder);
+    active_cng_decoder_.reset();
   }
-  active_cng_decoder_ = rtp_payload_type;
+  active_cng_decoder_type_ = rtp_payload_type;
   return kOK;
 }
 
-AudioDecoder* DecoderDatabase::GetActiveCngDecoder() {
-  if (active_cng_decoder_ < 0) {
+ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() {
+  if (active_cng_decoder_type_ < 0) {
     // No active CNG decoder.
     return NULL;
   }
-  return GetDecoder(active_cng_decoder_);
+  if (!active_cng_decoder_) {
+    active_cng_decoder_.reset(new ComfortNoiseDecoder);
+  }
+  return active_cng_decoder_.get();
 }
 
 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h
index 37dbb53..8dbec22 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.h
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.h
@@ -16,6 +16,7 @@
 
 #include "webrtc/base/constructormagic.h"
 #include "webrtc/common_types.h"  // NULL
+#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h"
 #include "webrtc/modules/audio_coding/neteq/packet.h"
 #include "webrtc/typedefs.h"
@@ -142,7 +143,7 @@
 
   // Returns the current active comfort noise decoder, or NULL if no active
   // comfort noise decoder exists.
-  virtual AudioDecoder* GetActiveCngDecoder();
+  virtual ComfortNoiseDecoder* GetActiveCngDecoder();
 
   // Returns kOK if all packets in |packet_list| carry payload types that are
   // registered in the database. Otherwise, returns kDecoderNotFound.
@@ -152,8 +153,9 @@
   typedef std::map<uint8_t, DecoderInfo> DecoderMap;
 
   DecoderMap decoders_;
-  int active_decoder_;
-  int active_cng_decoder_;
+  int active_decoder_type_;
+  int active_cng_decoder_type_;
+  std::unique_ptr<ComfortNoiseDecoder> active_cng_decoder_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DecoderDatabase);
 };
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
index 929f844..0da4d64 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
@@ -231,8 +231,8 @@
 
   // Set active CNG codec.
   EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveCngDecoder(13));
-  decoder = db.GetActiveCngDecoder();
-  ASSERT_FALSE(decoder == NULL);  // Should get a decoder here.
+  ComfortNoiseDecoder* cng = db.GetActiveCngDecoder();
+  ASSERT_FALSE(cng == NULL);  // Should get a decoder here.
 
   // Remove the active CNG decoder, and verify that the active becomes NULL.
   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(13));
diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h
index 1b4a3c9..d04181d 100644
--- a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h
+++ b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h
@@ -59,7 +59,7 @@
   MOCK_METHOD1(SetActiveCngDecoder,
       int(uint8_t rtp_payload_type));
   MOCK_METHOD0(GetActiveCngDecoder,
-      AudioDecoder*());
+      ComfortNoiseDecoder*());
   MOCK_CONST_METHOD1(CheckPayloadTypes,
       int(const PacketList& packet_list));
 };
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
index db37e71..b6ec655 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -14,6 +14,7 @@
 #include <memory.h>  // memset
 
 #include <algorithm>
+#include <vector>
 
 #include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
@@ -664,13 +665,15 @@
     }
   }
 
-  // Update bandwidth estimate, if the packet is not sync-packet.
-  if (!packet_list.empty() && !packet_list.front()->sync_packet) {
+  // Update bandwidth estimate, if the packet is not sync-packet nor comfort
+  // noise.
+  if (!packet_list.empty() && !packet_list.front()->sync_packet &&
+      !decoder_database_->IsComfortNoise(main_header.payloadType)) {
     // The list can be empty here if we got nothing but DTMF payloads.
     AudioDecoder* decoder =
         decoder_database_->GetDecoder(main_header.payloadType);
     assert(decoder);  // Should always get a valid object, since we have
-                      // already checked that the payload types are known.
+    // already checked that the payload types are known.
     decoder->IncomingPacket(packet_list.front()->payload,
                             packet_list.front()->payload_length,
                             packet_list.front()->header.sequenceNumber,
@@ -728,14 +731,18 @@
     const RTPHeader* rtp_header = packet_buffer_->NextRtpHeader();
     assert(rtp_header);
     int payload_type = rtp_header->payloadType;
-    AudioDecoder* decoder = decoder_database_->GetDecoder(payload_type);
-    assert(decoder);  // Payloads are already checked to be valid.
+    size_t channels = 1;
+    if (!decoder_database_->IsComfortNoise(payload_type)) {
+      AudioDecoder* decoder = decoder_database_->GetDecoder(payload_type);
+      assert(decoder);  // Payloads are already checked to be valid.
+      channels = decoder->Channels();
+    }
     const DecoderDatabase::DecoderInfo* decoder_info =
         decoder_database_->GetDecoderInfo(payload_type);
     assert(decoder_info);
     if (decoder_info->fs_hz != fs_hz_ ||
-        decoder->Channels() != algorithm_buffer_->Channels()) {
-      SetSampleRateAndChannels(decoder_info->fs_hz, decoder->Channels());
+        channels != algorithm_buffer_->Channels()) {
+      SetSampleRateAndChannels(decoder_info->fs_hz, channels);
     }
     if (nack_enabled_) {
       RTC_DCHECK(nack_);
@@ -1297,7 +1304,7 @@
       decoder->Reset();
 
     // Reset comfort noise decoder.
-    AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
+    ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
     if (cng_decoder)
       cng_decoder->Reset();
 
@@ -1955,7 +1962,7 @@
           stats_.SecondaryDecodedSamples(packet_duration);
         }
       }
-    } else {
+    } else if (!decoder_database_->IsComfortNoise(packet->header.payloadType)) {
       LOG(LS_WARNING) << "Unknown payload type "
                       << static_cast<int>(packet->header.payloadType);
       assert(false);
@@ -2023,7 +2030,7 @@
     mute_factor_array_[i] = 16384;  // 1.0 in Q14.
   }
 
-  AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
+  ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
   if (cng_decoder)
     cng_decoder->Reset();
 
diff --git a/webrtc/modules/audio_coding/neteq/normal.cc b/webrtc/modules/audio_coding/neteq/normal.cc
index 9bddfe7..4400afb 100644
--- a/webrtc/modules/audio_coding/neteq/normal.cc
+++ b/webrtc/modules/audio_coding/neteq/normal.cc
@@ -16,7 +16,6 @@
 
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
-#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h"
 #include "webrtc/modules/audio_coding/neteq/background_noise.h"
 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
@@ -149,12 +148,11 @@
     int16_t cng_output[kCngLength];
     // Reset mute factor and start up fresh.
     external_mute_factor_array[0] = 16384;
-    AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
+    ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
 
     if (cng_decoder) {
       // Generate long enough for 32kHz.
-      if (WebRtcCng_Generate(cng_decoder->CngDecoderInstance(), cng_output,
-                             kCngLength, 0) < 0) {
+      if (!cng_decoder->Generate(cng_output, 0)) {
         // Error returned; set return vector to all zeros.
         memset(cng_output, 0, sizeof(cng_output));
       }
diff --git a/webrtc/modules/audio_coding/neteq/payload_splitter.cc b/webrtc/modules/audio_coding/neteq/payload_splitter.cc
index 8530718..5428639 100644
--- a/webrtc/modules/audio_coding/neteq/payload_splitter.cc
+++ b/webrtc/modules/audio_coding/neteq/payload_splitter.cc
@@ -143,8 +143,9 @@
 
     // Not an FEC packet.
     AudioDecoder* decoder = decoder_database->GetDecoder(payload_type);
-    // decoder should not return NULL.
-    assert(decoder != NULL);
+    // decoder should not return NULL, except for comfort noise payloads which
+    // are handled separately.
+    assert(decoder != NULL || decoder_database->IsComfortNoise(payload_type));
     if (!decoder ||
         !decoder->PacketHasFec(packet->payload, packet->payload_length)) {
       ++it;
diff --git a/webrtc/modules/audio_coding/neteq/test/RTPencode.cc b/webrtc/modules/audio_coding/neteq/test/RTPencode.cc
index 45586ee..149f282 100644
--- a/webrtc/modules/audio_coding/neteq/test/RTPencode.cc
+++ b/webrtc/modules/audio_coding/neteq/test/RTPencode.cc
@@ -265,7 +265,7 @@
 #endif
 #if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
      defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
-CNG_enc_inst* CNGenc_inst[2];
+webrtc::ComfortNoiseEncoder *CNG_encoder[2];
 #endif
 #ifdef CODEC_SPEEX_8
 SPEEX_encinst_t* SPEEX8enc_inst[2];
@@ -928,18 +928,8 @@
 
 #if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
      defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
-    ok = WebRtcCng_CreateEnc(&CNGenc_inst[k]);
-    if (ok != 0) {
-      printf("Error: Couldn't allocate memory for CNG encoding instance\n");
-      exit(0);
-    }
     if (sampfreq <= 16000) {
-      ok = WebRtcCng_InitEnc(CNGenc_inst[k], sampfreq, 200, 5);
-      if (ok == -1) {
-        printf("Error: Initialization of CNG struct failed. Error code %d\n",
-               WebRtcCng_GetErrorCodeEnc(CNGenc_inst[k]));
-        exit(0);
-      }
+      CNG_encoder[k] = new webrtc::ComfortNoiseEncoder(sampfreq, 200, 5);
     }
 #endif
 
@@ -1461,7 +1451,8 @@
     WebRtcVad_Free(VAD_inst[k]);
 #if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
      defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
-    WebRtcCng_FreeEnc(CNGenc_inst[k]);
+    delete CNG_encoder[k];
+    CNG_encoder[k] = nullptr;
 #endif
 
     switch (coder) {
@@ -1600,7 +1591,7 @@
                         size_t numChannels) {
   size_t cdlen = 0;
   int16_t* tempdata;
-  static int first_cng = 1;
+  static bool first_cng = true;
   size_t tempLen;
   *vad = 1;
 
@@ -1608,9 +1599,9 @@
   if (useVAD) {
     *vad = 0;
 
-    size_t sampleRate_10 = static_cast<size_t>(10 * sampleRate / 1000);
-    size_t sampleRate_20 = static_cast<size_t>(20 * sampleRate / 1000);
-    size_t sampleRate_30 = static_cast<size_t>(30 * sampleRate / 1000);
+    const size_t sampleRate_10 = static_cast<size_t>(10 * sampleRate / 1000);
+    const size_t sampleRate_20 = static_cast<size_t>(20 * sampleRate / 1000);
+    const size_t sampleRate_30 = static_cast<size_t>(30 * sampleRate / 1000);
     for (size_t k = 0; k < numChannels; k++) {
       tempLen = frameLen;
       tempdata = &indata[k * frameLen];
@@ -1642,16 +1633,22 @@
 
     if (!*vad) {
       // all channels are silent
+      rtc::Buffer workaround;
       cdlen = 0;
       for (size_t k = 0; k < numChannels; k++) {
-        WebRtcCng_Encode(CNGenc_inst[k], &indata[k * frameLen],
-                         (frameLen <= 640 ? frameLen : 640) /* max 640 */,
-                         encoded, &tempLen, first_cng);
+        workaround.Clear();
+        tempLen = CNG_encoder[k]->Encode(
+            rtc::ArrayView<const int16_t>(
+                &indata[k * frameLen],
+                (frameLen <= 640 ? frameLen : 640) /* max 640 */),
+            first_cng,
+            &workaround);
+        memcpy(encoded, workaround.data(), tempLen);
         encoded += tempLen;
         cdlen += tempLen;
       }
       *vad = 0;
-      first_cng = 0;
+      first_cng = false;
       return (cdlen);
     }
   }
@@ -1734,7 +1731,7 @@
 
   }  // end for
 
-  first_cng = 1;
+  first_cng = true;
   return (totalLen);
 }