Setting Opus target application.

This CL is to allow to set Opus target application at the creation of an encoder.

According to Opus spec, there are three applications:

OPUS_APPLICATION_VOIP
OPUS_APPLICATION_AUDIO
OPUS_APPLICATION_RESTRICTED_LOWDELAY

BUG=
R=henrik.lundin@webrtc.org, tina.legrand@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/37479004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@8103 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index 1cfc302..358647f 100644
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -37,7 +37,10 @@
 }  // namespace
 
 AudioEncoderOpus::Config::Config()
-    : frame_size_ms(20), num_channels(1), payload_type(120) {
+    : frame_size_ms(20),
+      num_channels(1),
+      payload_type(120),
+      application(kVoip) {
 }
 
 bool AudioEncoderOpus::Config::IsOk() const {
@@ -52,10 +55,11 @@
     : num_10ms_frames_per_packet_(DivExact(config.frame_size_ms, 10)),
       num_channels_(config.num_channels),
       payload_type_(config.payload_type),
+      application_(config.application),
       samples_per_10ms_frame_(DivExact(kSampleRateHz, 100) * num_channels_) {
   CHECK(config.IsOk());
   input_buffer_.reserve(num_10ms_frames_per_packet_ * samples_per_10ms_frame_);
-  CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, num_channels_));
+  CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, num_channels_, application_));
 }
 
 AudioEncoderOpus::~AudioEncoderOpus() {
diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
index f44627d..e9d0fb8 100644
--- a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
+++ b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
@@ -20,12 +20,18 @@
 
 class AudioEncoderOpus : public AudioEncoder {
  public:
+  enum ApplicationMode {
+    kVoip = 0,
+    kAudio = 1,
+  };
+
   struct Config {
     Config();
     bool IsOk() const;
     int frame_size_ms;
     int num_channels;
     int payload_type;
+    ApplicationMode application;
   };
 
   explicit AudioEncoderOpus(const Config& config);
@@ -47,6 +53,7 @@
   const int num_10ms_frames_per_packet_;
   const int num_channels_;
   const int payload_type_;
+  const ApplicationMode application_;
   const int samples_per_10ms_frame_;
   std::vector<int16_t> input_buffer_;
   OpusEncInst* inst_;
diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
index d788af7..27009a8 100644
--- a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
+++ b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
@@ -21,7 +21,29 @@
 typedef struct WebRtcOpusEncInst OpusEncInst;
 typedef struct WebRtcOpusDecInst OpusDecInst;
 
-int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels);
+/****************************************************************************
+ * WebRtcOpus_EncoderCreate(...)
+ *
+ * This function create an Opus encoder.
+ *
+ * Input:
+ *      - channels           : number of channels.
+ *      - application        : 0 - VOIP applications.
+ *                                 Favor speech intelligibility.
+ *                             1 - Audio applications.
+ *                                 Favor faithfulness to the original input.
+ *
+ * Output:
+ *      - inst               : a pointer to Encoder context that is created
+ *                             if success.
+ *
+ * Return value              : 0 - Success
+ *                            -1 - Error
+ */
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
+                                 int32_t channels,
+                                 int32_t application);
+
 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst);
 
 /****************************************************************************
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc b/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 35f3972..b91aa45 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -103,8 +103,11 @@
   out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]);
   bit_stream_.reset(new uint8_t[max_bytes_]);
 
+  // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+  int app = channels_ == 1 ? 0 : 1;
+
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
   EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
   // Set bitrate.
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
index 1b99864..955fb00 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
@@ -31,17 +31,31 @@
   kWebRtcOpusDefaultFrameSize = 960,
 };
 
-int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels) {
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
+                                 int32_t channels,
+                                 int32_t application) {
   OpusEncInst* state;
   if (inst != NULL) {
     state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
     if (state) {
-      int error;
-      /* Default to VoIP application for mono, and AUDIO for stereo. */
-      int application = (channels == 1) ? OPUS_APPLICATION_VOIP :
-          OPUS_APPLICATION_AUDIO;
+      int opus_app;
+      switch (application) {
+        case 0: {
+          opus_app = OPUS_APPLICATION_VOIP;
+          break;
+        }
+        case 1: {
+          opus_app = OPUS_APPLICATION_AUDIO;
+          break;
+        }
+        default: {
+          free(state);
+          return -1;
+        }
+      }
 
-      state->encoder = opus_encoder_create(48000, channels, application,
+      int error;
+      state->encoder = opus_encoder_create(48000, channels, opus_app,
                                            &error);
       state->in_dtx_mode = 0;
       if (error == OPUS_OK && state->encoder != NULL) {
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
index e7811e3..ebe4a35 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -41,8 +41,10 @@
 
 void OpusSpeedTest::SetUp() {
   AudioCodecSpeedTest::SetUp();
+  // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+  int app = channels_ == 1 ? 0 : 1;
   /* Create encoder memory. */
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
   EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
   /* Set bitrate. */
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
index 5439df4..e93cd7c 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -18,6 +18,9 @@
 namespace webrtc {
 
 using test::AudioLoop;
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::Combine;
 
 // Maximum number of bytes in output bitstream.
 const size_t kMaxBytes = 1000;
@@ -28,11 +31,10 @@
 // Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
 const int kOpus10msFrameSamples = kOpusRateKhz * 10;
 
-class OpusTest : public ::testing::Test {
+class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
  protected:
   OpusTest();
 
-  void TestSetMaxPlaybackRate(opus_int32 expect, int32_t set);
   void TestDtxEffect(bool dtx);
 
   // Prepare |speech_data_| for encoding, read from a hard-coded file.
@@ -48,27 +50,33 @@
                    int16_t* output_audio,
                    int16_t* audio_type);
 
-  WebRtcOpusEncInst* opus_mono_encoder_;
-  WebRtcOpusEncInst* opus_stereo_encoder_;
-  WebRtcOpusDecInst* opus_mono_decoder_;
-  WebRtcOpusDecInst* opus_stereo_decoder_;
+  void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
+                          opus_int32 expect, int32_t set);
+
+  WebRtcOpusEncInst* opus_encoder_;
+  WebRtcOpusDecInst* opus_decoder_;
 
   AudioLoop speech_data_;
   uint8_t bitstream_[kMaxBytes];
   int encoded_bytes_;
+  int channels_;
+  int application_;
 };
 
 OpusTest::OpusTest()
-    : opus_mono_encoder_(NULL),
-      opus_stereo_encoder_(NULL),
-      opus_mono_decoder_(NULL),
-      opus_stereo_decoder_(NULL) {
+    : opus_encoder_(NULL),
+      opus_decoder_(NULL),
+      encoded_bytes_(0),
+      channels_(::testing::get<0>(GetParam())),
+      application_(::testing::get<1>(GetParam())) {
 }
 
 void OpusTest::PrepareSpeechData(int channel, int block_length_ms,
                                  int loop_length_ms) {
   const std::string file_name =
-        webrtc::test::ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm");
+        webrtc::test::ResourcePath((channel == 1) ?
+            "audio_coding/testfile32kHz" :
+            "audio_coding/teststereo32kHz", "pcm");
   if (loop_length_ms < block_length_ms) {
     loop_length_ms = block_length_ms;
   }
@@ -77,16 +85,12 @@
                                 block_length_ms * kOpusRateKhz * channel));
 }
 
-void OpusTest::TestSetMaxPlaybackRate(opus_int32 expect, int32_t set) {
+void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
+                                  opus_int32 expect,
+                                  int32_t set) {
   opus_int32 bandwidth;
-  // Test mono encoder.
-  EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_mono_encoder_, set));
-  opus_encoder_ctl(opus_mono_encoder_->encoder,
-                   OPUS_GET_MAX_BANDWIDTH(&bandwidth));
-  EXPECT_EQ(expect, bandwidth);
-  // Test stereo encoder.
-  EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_stereo_encoder_, set));
-  opus_encoder_ctl(opus_stereo_encoder_->encoder,
+  EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
+  opus_encoder_ctl(opus_encoder_->encoder,
                    OPUS_GET_MAX_BANDWIDTH(&bandwidth));
   EXPECT_EQ(expect, bandwidth);
 }
@@ -109,105 +113,109 @@
 // Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
 // they should not. This test is signal dependent.
 void OpusTest::TestDtxEffect(bool dtx) {
-  PrepareSpeechData(1, 20, 2000);
+  PrepareSpeechData(channels_, 20, 2000);
 
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
 
   // Set bitrate.
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
+                                     channels_ == 1 ? 32000 : 64000));
 
   // Set input audio as silence.
-  int16_t silence[kOpus20msFrameSamples] = {0};
+  int16_t* silence = new int16_t[kOpus20msFrameSamples * channels_];
+  memset(silence, 0, sizeof(int16_t) * kOpus20msFrameSamples * channels_);
 
   // Setting DTX.
-  EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_mono_encoder_) :
-      WebRtcOpus_DisableDtx(opus_mono_encoder_));
+  EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_) :
+      WebRtcOpus_DisableDtx(opus_encoder_));
 
   int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples];
+  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
 
   for (int i = 0; i < 100; ++i) {
     EXPECT_EQ(kOpus20msFrameSamples,
-              EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
-                           kOpus20msFrameSamples, opus_mono_decoder_,
+              EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+                           kOpus20msFrameSamples, opus_decoder_,
                            output_data_decode, &audio_type));
     // If not DTX, it should never enter DTX mode. If DTX, we do not care since
     // whether it enters DTX depends on the signal type.
     if (!dtx) {
       EXPECT_GT(encoded_bytes_, 1);
-      EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-      EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(0, audio_type);  // Speech.
     }
   }
 
   // We input some silent segments. In DTX mode, the encoder will stop sending.
   // However, DTX may happen after a while.
-  for (int i = 0; i < 22; ++i) {
+  for (int i = 0; i < 30; ++i) {
     EXPECT_EQ(kOpus20msFrameSamples,
-              EncodeDecode(opus_mono_encoder_, silence,
-                           kOpus20msFrameSamples, opus_mono_decoder_,
+              EncodeDecode(opus_encoder_, silence,
+                           kOpus20msFrameSamples, opus_decoder_,
                            output_data_decode, &audio_type));
     if (!dtx) {
       EXPECT_GT(encoded_bytes_, 1);
-      EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-      EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(0, audio_type);  // Speech.
     } else if (1 == encoded_bytes_) {
-      EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
-      EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+      EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+      EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(2, audio_type);  // Comfort noise.
       break;
     }
   }
 
   // DTX mode is maintained 400 ms.
-  for (int i = 0; i < 20; ++i) {
+  for (int i = 0; i < 19; ++i) {
     EXPECT_EQ(kOpus20msFrameSamples,
-              EncodeDecode(opus_mono_encoder_, silence,
-                           kOpus20msFrameSamples, opus_mono_decoder_,
+              EncodeDecode(opus_encoder_, silence,
+                           kOpus20msFrameSamples, opus_decoder_,
                            output_data_decode, &audio_type));
     if (dtx) {
       EXPECT_EQ(0, encoded_bytes_)  // Send 0 byte.
           << "Opus should have entered DTX mode.";
-      EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
-      EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+      EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+      EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(2, audio_type);  // Comfort noise.
     } else {
       EXPECT_GT(encoded_bytes_, 1);
-      EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-      EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+      EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(0, audio_type);  // Speech.
     }
   }
 
   // Quit DTX after 400 ms
   EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_mono_encoder_, silence,
-                         kOpus20msFrameSamples, opus_mono_decoder_,
+            EncodeDecode(opus_encoder_, silence,
+                         kOpus20msFrameSamples, opus_decoder_,
                          output_data_decode, &audio_type));
 
   EXPECT_GT(encoded_bytes_, 1);
-  EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-  EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+  EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+  EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
   EXPECT_EQ(0, audio_type);  // Speech.
 
   // Enters DTX again immediately.
   EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_mono_encoder_, silence,
-                         kOpus20msFrameSamples, opus_mono_decoder_,
+            EncodeDecode(opus_encoder_, silence,
+                         kOpus20msFrameSamples, opus_decoder_,
                          output_data_decode, &audio_type));
   if (dtx) {
     EXPECT_EQ(1, encoded_bytes_);  // Send 1 byte.
-    EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
-    EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+    EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+    EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
     EXPECT_EQ(2, audio_type);  // Comfort noise.
   } else {
     EXPECT_GT(encoded_bytes_, 1);
-    EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-    EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+    EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+    EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
     EXPECT_EQ(0, audio_type);  // Speech.
   }
 
@@ -215,386 +223,340 @@
   if (dtx) {
     // Verify that encoder/decoder can jump out from DTX mode.
     EXPECT_EQ(kOpus20msFrameSamples,
-              EncodeDecode(opus_mono_encoder_, silence,
-                           kOpus20msFrameSamples, opus_mono_decoder_,
+              EncodeDecode(opus_encoder_, silence,
+                           kOpus20msFrameSamples, opus_decoder_,
                            output_data_decode, &audio_type));
     EXPECT_GT(encoded_bytes_, 1);
-    EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
-    EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+    EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+    EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
     EXPECT_EQ(0, audio_type);  // Speech.
   }
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
+  delete[] output_data_decode;
+  delete[] silence;
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
 // Test failing Create.
-TEST_F(OpusTest, OpusCreateFail) {
+TEST(OpusTest, OpusCreateFail) {
+  WebRtcOpusEncInst* opus_encoder;
+  WebRtcOpusDecInst* opus_decoder;
+
   // Test to see that an invalid pointer is caught.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1));
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 3));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
+  // Invalid channel number.
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 3, 0));
+  // Invalid applciation mode.
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
+
   EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
-  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 3));
+  // Invalid channel number.
+  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 3));
 }
 
 // Test failing Free.
-TEST_F(OpusTest, OpusFreeFail) {
+TEST(OpusTest, OpusFreeFail) {
   // Test to see that an invalid pointer is caught.
   EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL));
   EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL));
 }
 
 // Test normal Create and Free.
-TEST_F(OpusTest, OpusCreateFree) {
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
-  EXPECT_TRUE(opus_mono_encoder_ != NULL);
-  EXPECT_TRUE(opus_mono_decoder_ != NULL);
-  EXPECT_TRUE(opus_stereo_encoder_ != NULL);
-  EXPECT_TRUE(opus_stereo_decoder_ != NULL);
+TEST_P(OpusTest, OpusCreateFree) {
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+  EXPECT_TRUE(opus_encoder_ != NULL);
+  EXPECT_TRUE(opus_decoder_ != NULL);
   // Free encoder and decoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
-TEST_F(OpusTest, OpusEncodeDecodeMono) {
-  PrepareSpeechData(1, 20, 20);
+TEST_P(OpusTest, OpusEncodeDecode) {
+  PrepareSpeechData(channels_, 20, 20);
 
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_,
+                                        channels_));
 
   // Set bitrate.
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
+                                     channels_ == 1 ? 32000 : 64000));
 
   // Check number of channels for decoder.
-  EXPECT_EQ(1, WebRtcOpus_DecoderChannels(opus_mono_decoder_));
+  EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
+
+  // Check application mode.
+  opus_int32 app;
+  opus_encoder_ctl(opus_encoder_->encoder,
+                   OPUS_GET_APPLICATION(&app));
+  EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
+            app);
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples];
+  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
   EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
-                         kOpus20msFrameSamples, opus_mono_decoder_,
+            EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+                         kOpus20msFrameSamples, opus_decoder_,
                          output_data_decode, &audio_type));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
+  delete[] output_data_decode;
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
-TEST_F(OpusTest, OpusEncodeDecodeStereo) {
-  PrepareSpeechData(2, 20, 20);
-
-  // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
-
-  // Set bitrate.
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 64000));
-
-  // Check number of channels for decoder.
-  EXPECT_EQ(2, WebRtcOpus_DecoderChannels(opus_stereo_decoder_));
-
-  // Encode & decode.
-  int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples * 2];
-  EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
-                         kOpus20msFrameSamples, opus_stereo_decoder_,
-                         output_data_decode, &audio_type));
-
-  // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
-}
-
-TEST_F(OpusTest, OpusSetBitRate) {
+TEST_P(OpusTest, OpusSetBitRate) {
   // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_mono_encoder_, 60000));
-  EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000));
+  EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
 
   // Create encoder memory, try with different bitrates.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 30000));
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000));
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 300000));
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 600000));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
 }
 
-TEST_F(OpusTest, OpusSetComplexity) {
+TEST_P(OpusTest, OpusSetComplexity) {
   // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 9));
-  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 9));
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
 
   // Create encoder memory, try with different complexities.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
 
-  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 0));
-  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 0));
-  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 10));
-  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 10));
-  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 11));
-  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 11));
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
 }
 
-// Encode and decode one frame (stereo), initialize the decoder and
+// Encode and decode one frame, initialize the decoder and
 // decode once more.
-TEST_F(OpusTest, OpusDecodeInit) {
-  PrepareSpeechData(2, 20, 20);
+TEST_P(OpusTest, OpusDecodeInit) {
+  PrepareSpeechData(channels_, 20, 20);
 
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples * 2];
+  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
   EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
-                         kOpus20msFrameSamples, opus_stereo_decoder_,
+            EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+                         kOpus20msFrameSamples, opus_decoder_,
                          output_data_decode, &audio_type));
 
-  EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_stereo_decoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_decoder_));
 
   EXPECT_EQ(kOpus20msFrameSamples,
-            WebRtcOpus_Decode(opus_stereo_decoder_, bitstream_,
+            WebRtcOpus_Decode(opus_decoder_, bitstream_,
                               encoded_bytes_, output_data_decode,
                               &audio_type));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+  delete[] output_data_decode;
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
-TEST_F(OpusTest, OpusEnableDisableFec) {
+TEST_P(OpusTest, OpusEnableDisableFec) {
   // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_mono_encoder_));
-  EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_stereo_encoder_));
+  EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_));
+  EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
 
-  // Create encoder memory, try with different bitrates.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
 
-  EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_stereo_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
 }
 
-TEST_F(OpusTest, OpusEnableDisableDtx) {
+TEST_P(OpusTest, OpusEnableDisableDtx) {
   // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_mono_encoder_));
-  EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_stereo_encoder_));
+  EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_));
+  EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
 
-  // Create encoder memory, try with different bitrates.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
 
   opus_int32 dtx;
 
   // DTX is off by default.
-  opus_encoder_ctl(opus_mono_encoder_->encoder,
-                   OPUS_GET_DTX(&dtx));
-  EXPECT_EQ(0, dtx);
-
-  opus_encoder_ctl(opus_stereo_encoder_->encoder,
+  opus_encoder_ctl(opus_encoder_->encoder,
                    OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
   // Test to enable DTX.
-  EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_mono_encoder_));
-  opus_encoder_ctl(opus_mono_encoder_->encoder,
-                   OPUS_GET_DTX(&dtx));
-  EXPECT_EQ(1, dtx);
-
-  EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_stereo_encoder_));
-  opus_encoder_ctl(opus_stereo_encoder_->encoder,
+  EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
+  opus_encoder_ctl(opus_encoder_->encoder,
                    OPUS_GET_DTX(&dtx));
   EXPECT_EQ(1, dtx);
 
   // Test to disable DTX.
-  EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_mono_encoder_));
-  opus_encoder_ctl(opus_mono_encoder_->encoder,
+  EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
+  opus_encoder_ctl(opus_encoder_->encoder,
                    OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
-  EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_stereo_encoder_));
-  opus_encoder_ctl(opus_stereo_encoder_->encoder,
-                   OPUS_GET_DTX(&dtx));
-  EXPECT_EQ(0, dtx);
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
 }
 
-TEST_F(OpusTest, OpusDtxOff) {
+TEST_P(OpusTest, OpusDtxOff) {
   TestDtxEffect(false);
 }
 
-TEST_F(OpusTest, OpusDtxOn) {
+TEST_P(OpusTest, OpusDtxOn) {
+  if (application_ == 1) {
+    // We do not check DTX under OPUS_APPLICATION_AUDIO mode.
+    return;
+  }
   TestDtxEffect(true);
 }
 
-TEST_F(OpusTest, OpusSetPacketLossRate) {
+TEST_P(OpusTest, OpusSetPacketLossRate) {
   // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 50));
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 50));
-
-  // Create encoder memory, try with different bitrates.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-
-  EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 50));
-  EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 50));
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, -1));
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, -1));
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 101));
-  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 101));
-
-  // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-}
-
-TEST_F(OpusTest, OpusSetMaxPlaybackRate) {
-  // Test without creating encoder memory.
-  EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_mono_encoder_, 20000));
-  EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_stereo_encoder_, 20000));
-
-  // Create encoder memory, try with different bitrates.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_FULLBAND, 48000);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_FULLBAND, 24001);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_WIDEBAND, 16000);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_WIDEBAND, 12001);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_MEDIUMBAND, 12000);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_MEDIUMBAND, 8001);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_NARROWBAND, 8000);
-  TestSetMaxPlaybackRate(OPUS_BANDWIDTH_NARROWBAND, 4000);
-
-  // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-}
-
-// PLC in mono mode.
-TEST_F(OpusTest, OpusDecodePlcMono) {
-  PrepareSpeechData(1, 20, 20);
+  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
 
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+
+  EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
+  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
+  EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 101));
+
+  // Free memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusSetMaxPlaybackRate) {
+  // Test without creating encoder memory.
+  EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
+
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 16000);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 12001);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 12000);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 8001);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 8000);
+  SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 4000);
+
+  // Free memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+// Test PLC.
+TEST_P(OpusTest, OpusDecodePlc) {
+  PrepareSpeechData(channels_, 20, 20);
+
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
 
   // Set bitrate.
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000));
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
+                                     channels_== 1 ? 32000 : 64000));
 
   // Check number of channels for decoder.
-  EXPECT_EQ(1, WebRtcOpus_DecoderChannels(opus_mono_decoder_));
+  EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples];
+  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
   EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
-                         kOpus20msFrameSamples, opus_mono_decoder_,
+            EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+                         kOpus20msFrameSamples, opus_decoder_,
                          output_data_decode, &audio_type));
 
   // Call decoder PLC.
-  int16_t plc_buffer[kOpus20msFrameSamples];
+  int16_t* plc_buffer = new int16_t[kOpus20msFrameSamples * channels_];
   EXPECT_EQ(kOpus20msFrameSamples,
-            WebRtcOpus_DecodePlc(opus_mono_decoder_, plc_buffer, 1));
+            WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
-}
-
-// PLC in stereo mode.
-TEST_F(OpusTest, OpusDecodePlcStereo) {
-  PrepareSpeechData(2, 20, 20);
-
-  // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
-
-  // Set bitrate.
-  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 64000));
-
-  // Check number of channels for decoder.
-  EXPECT_EQ(2, WebRtcOpus_DecoderChannels(opus_stereo_decoder_));
-
-  // Encode & decode.
-  int16_t audio_type;
-  int16_t output_data_decode[kOpus20msFrameSamples * 2];
-  EXPECT_EQ(kOpus20msFrameSamples,
-            EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
-                         kOpus20msFrameSamples, opus_stereo_decoder_,
-                         output_data_decode, &audio_type));
-
-  // Call decoder PLC.
-  int16_t plc_buffer[kOpus20msFrameSamples * 2];
-  EXPECT_EQ(kOpus20msFrameSamples,
-            WebRtcOpus_DecodePlc(opus_stereo_decoder_, plc_buffer, 1));
-
-  // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+  delete[] plc_buffer;
+  delete[] output_data_decode;
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
 // Duration estimation.
-TEST_F(OpusTest, OpusDurationEstimation) {
-  PrepareSpeechData(2, 20, 20);
+TEST_P(OpusTest, OpusDurationEstimation) {
+  PrepareSpeechData(channels_, 20, 20);
 
   // Create.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
-  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+                                        channels_,
+                                        application_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
 
   // 10 ms. We use only first 10 ms of a 20 ms block.
-  encoded_bytes_ = WebRtcOpus_Encode(opus_stereo_encoder_,
+  encoded_bytes_ = WebRtcOpus_Encode(opus_encoder_,
                                      speech_data_.GetNextBlock(),
                                      kOpus10msFrameSamples, kMaxBytes,
                                      bitstream_);
   EXPECT_EQ(kOpus10msFrameSamples,
-            WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_,
+            WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
                                    encoded_bytes_));
 
   // 20 ms
-  encoded_bytes_ = WebRtcOpus_Encode(opus_stereo_encoder_,
+  encoded_bytes_ = WebRtcOpus_Encode(opus_encoder_,
                                      speech_data_.GetNextBlock(),
                                      kOpus20msFrameSamples, kMaxBytes,
                                      bitstream_);
   EXPECT_EQ(kOpus20msFrameSamples,
-            WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_,
+            WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
                                    encoded_bytes_));
 
   // Free memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
-  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
+INSTANTIATE_TEST_CASE_P(VariousMode,
+                        OpusTest,
+                        Combine(Values(1, 2), Values(0, 1)));
+
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
index b1c4214..6b18095 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -999,6 +999,12 @@
   return -1;
 }
 
+int ACMGenericCodec::SetOpusApplication(OpusApplicationMode /*application*/) {
+  WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
+      "The send-codec is not Opus, failed to set application.");
+  return -1;
+}
+
 int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) {
   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
       "The send-codec is not Opus, failed to set maximum playback rate.");
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
index d55d91e..b13719f 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -526,6 +526,20 @@
                                  int16_t* payload_len_bytes);
 
   ///////////////////////////////////////////////////////////////////////////
+  // int SetOpusApplication()
+  // Sets the intended application for the Opus encoder. Opus uses this to
+  // optimize the encoding for applications like VOIP and music.
+  //
+  // Input:
+  //   - application      : intended application.
+  //
+  // Return value:
+  //   -1 if failed or on codecs other than Opus.
+  //    0 if succeeded.
+  //
+  virtual int SetOpusApplication(OpusApplicationMode /*application*/);
+
+  ///////////////////////////////////////////////////////////////////////////
   // int SetOpusMaxPlaybackRate()
   // Sets maximum playback rate the receiver will render, if the codec is Opus.
   // This is to tell Opus that it is enough to code the input audio up to a
@@ -636,8 +650,8 @@
   // See InitEncoder() for the description of function, input(s)/output(s)
   // and return value.
   //
-  int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
-                          bool force_initialization)
+  virtual int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+                                  bool force_initialization)
       EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
 
   ///////////////////////////////////////////////////////////////////////////
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
index 8991dae..005e910 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
@@ -68,7 +68,8 @@
       sample_freq_(32000),  // Default sampling frequency.
       bitrate_(20000),  // Default bit-rate.
       channels_(1),  // Default mono.
-      packet_loss_rate_(0) {  // Initial packet loss rate.
+      packet_loss_rate_(0),  // Initial packet loss rate.
+      application_(kVoip) {  // Initial application mode.
   codec_id_ = codec_id;
   // Opus has internal DTX, but we dont use it for now.
   has_internal_dtx_ = false;
@@ -113,6 +114,16 @@
   return *bitstream_len_byte;
 }
 
+int16_t ACMOpus::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+                                 bool force_initialization) {
+  // Determine target application if codec is not initialized or a forced
+  // initialization is requested.
+  if (!encoder_initialized_ || force_initialization) {
+    application_ = (codec_params->codec_inst.channels == 1) ? kVoip : kAudio;
+  }
+  return ACMGenericCodec::InitEncoderSafe(codec_params, force_initialization);
+}
+
 int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
   int16_t ret;
   if (encoder_inst_ptr_ != NULL) {
@@ -120,7 +131,8 @@
     encoder_inst_ptr_ = NULL;
   }
   ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_,
-                                 codec_params->codec_inst.channels);
+                                 codec_params->codec_inst.channels,
+                                 application_);
   // Store number of channels.
   channels_ = codec_params->codec_inst.channels;
 
@@ -251,6 +263,13 @@
   return WebRtcOpus_SetMaxPlaybackRate(encoder_inst_ptr_, frequency_hz);
 }
 
+int ACMOpus::SetOpusApplication(OpusApplicationMode application) {
+  WriteLockScoped lockCodec(codec_wrapper_lock_);
+  application_ = application;
+  // Set Opus application invokes a reset of the encoder.
+  return InternalResetEncoder();
+}
+
 #endif  // WEBRTC_CODEC_OPUS
 
 }  // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.h b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
index 8ef6406..3c7aea6 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
@@ -29,23 +29,29 @@
   ACMGenericCodec* CreateInstance(void);
 
   int16_t InternalEncode(uint8_t* bitstream,
-                         int16_t* bitstream_len_byte) OVERRIDE
+                         int16_t* bitstream_len_byte) override
+      EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
+
+  int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+                          bool force_initialization) override
       EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
 
   int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
 
-  virtual int SetFEC(bool enable_fec) OVERRIDE;
+  int SetFEC(bool enable_fec) override;
 
-  virtual int SetPacketLossRate(int loss_rate) OVERRIDE;
+  int SetOpusApplication(OpusApplicationMode mode) override;
 
-  virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;
+  int SetPacketLossRate(int loss_rate) override;
+
+  int SetOpusMaxPlaybackRate(int frequency_hz) override;
 
  protected:
   void DestructEncoderSafe();
 
   int16_t InternalCreateEncoder();
 
-  int16_t SetBitRateSafe(const int32_t rate) OVERRIDE
+  int16_t SetBitRateSafe(const int32_t rate) override
       EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
 
   WebRtcOpusEncInst* encoder_inst_ptr_;
@@ -54,6 +60,8 @@
   int channels_;
 
   int packet_loss_rate_;
+
+  OpusApplicationMode application_;
 };
 
 }  // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
index e33c9d3..421bbe5 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
@@ -35,6 +35,11 @@
       : ACMOpus(codec_id) {}
   ~AcmOpusTest() {}
   int packet_loss_rate() { return packet_loss_rate_; }
+  OpusApplicationMode application() { return application_; }
+  bool encoder_initialized() {
+    ReadLockScoped cs(codec_wrapper_lock_);
+    return encoder_initialized_;
+  }
 
   void TestSetPacketLossRate(int from, int to, int expected_return);
 };
@@ -82,6 +87,54 @@
                              kPacketLossRate1);
   opus.TestSetPacketLossRate(0, 0, 0);
 }
+
+TEST(AcmOpusTest, DefaultApplicationMode) {
+  AcmOpusTest opus(ACMCodecDB::kOpus);
+  WebRtcACMCodecParams params;
+  memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
+
+  params.codec_inst.channels = 2;
+  // Codec is not initialized, and hence without force initialization (2nd
+  // argument being false), an initialization will take place.
+  EXPECT_FALSE(opus.encoder_initialized());
+  EXPECT_EQ(0, opus.InitEncoder(&params, false));
+  EXPECT_EQ(kAudio, opus.application());
+
+  params.codec_inst.channels = 1;
+  EXPECT_EQ(0, opus.InitEncoder(&params, true));
+  EXPECT_EQ(kVoip, opus.application());
+}
+
+TEST(AcmOpusTest, ChangeApplicationMode) {
+  AcmOpusTest opus(ACMCodecDB::kOpus);
+  WebRtcACMCodecParams params;
+  memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
+
+  params.codec_inst.channels = 2;
+  // Codec is not initialized, and hence without force initialization (2nd
+  // argument being false), an initialization will take place.
+  EXPECT_EQ(0, opus.InitEncoder(&params, false));
+  EXPECT_EQ(kAudio, opus.application());
+
+  opus.SetOpusApplication(kVoip);
+  EXPECT_EQ(kVoip, opus.application());
+}
+
+TEST(AcmOpusTest, ResetWontChangeApplicationMode) {
+  AcmOpusTest opus(ACMCodecDB::kOpus);
+  WebRtcACMCodecParams params;
+  memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
+
+  params.codec_inst.channels = 2;
+  // Codec is not initialized, and hence without force initialization (2nd
+  // argument being false), an initialization will take place.
+  EXPECT_EQ(0, opus.InitEncoder(&params, false));
+  EXPECT_EQ(kAudio, opus.application());
+
+  opus.ResetEncoder();
+  EXPECT_EQ(kAudio, opus.application());
+}
+
 #else
 void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */,
                                        int /* expected_return */) {
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
index e990284..5953cab 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
@@ -54,6 +54,8 @@
       size_t payload_len_bytes,
       const RTPFragmentationHeader* fragmentation) OVERRIDE;
 
+  AudioCodingModule* acm() { return acm_.get(); }
+
  private:
   static const int kBlockSizeMs = 10;
 
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index fe2b547..c9139bd 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -1544,6 +1544,14 @@
       frame_size_ms, rate_bit_per_sec, enforce_frame_size);
 }
 
+int AudioCodingModuleImpl::SetOpusApplication(OpusApplicationMode application) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  if (!HaveValidEncoder("SetOpusApplication")) {
+    return -1;
+  }
+  return codecs_[current_send_codec_idx_]->SetOpusApplication(application);
+}
+
 // Informs Opus encoder of the maximum playback rate the receiver will render.
 int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) {
   CriticalSectionScoped lock(acm_crit_sect_);
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
index df9e334..d393427 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -224,6 +224,8 @@
       int rate_bit_per_sec,
       bool enforce_frame_size = false) OVERRIDE;
 
+  int SetOpusApplication(OpusApplicationMode application) override;
+
   // If current send codec is Opus, informs it about the maximum playback rate
   // the receiver will render.
   virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
index 0151568..84d5558 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
@@ -977,6 +977,22 @@
       test::AcmReceiveTestOldApi::kStereoOutput);
 }
 
+TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms_voip) {
+  ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
+  // If not set, default will be kAudio in case of stereo.
+  send_test_->acm()->SetOpusApplication(kVoip);
+  Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
+          "9b9e12bc3cc793740966e11cbfa8b35b",
+          "57412a4b5771d19ff03ec35deffe7067",
+          "9b9e12bc3cc793740966e11cbfa8b35b"),
+      AcmReceiverBitExactnessOldApi::PlatformChecksum(
+          "c7340b1189652ab6b5e80dade7390cb4",
+          "cdfe85939c411d12b61701c566e22d26",
+          "c7340b1189652ab6b5e80dade7390cb4"),
+      50,
+      test::AcmReceiveTestOldApi::kStereoOutput);
+}
+
 // This test fixture is implemented to run ACM and change the desired output
 // frequency during the call. The input packets are simply PCM16b-wb encoded
 // payloads with a constant value of |kSampleValue|. The test fixture itself
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
index a16b005..7de0a12 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
@@ -875,6 +875,20 @@
       bool enforce_frame_size = false) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
+  // int SetOpusApplication()
+  // Sets the intended application for the Opus encoder. Opus uses this to
+  // optimize the encoding for applications like VOIP and music.
+  //
+  // Input:
+  //   - application      : intended application.
+  //
+  // Return value:
+  //   -1 if failed or on codecs other than Opus.
+  //    0 if succeeded.
+  //
+  virtual int SetOpusApplication(OpusApplicationMode /*application*/) = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
   // int SetOpusMaxPlaybackRate()
   // If current send codec is Opus, informs it about maximum playback rate the
   // receiver will render. Opus can use this information to optimize the bit
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
index 199be96..dce5352 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
@@ -200,6 +200,18 @@
   Off
 };
 
+///////////////////////////////////////////////////////////////////////////
+//
+// Enumeration of Opus mode for intended application.
+//
+// kVoip              : optimized for voice signals.
+// kAudio             : optimized for non-voice signals like music.
+//
+enum OpusApplicationMode {
+ kVoip = 0,
+ kAudio = 1,
+};
+
 }  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_INTERFACE_AUDIO_CODING_MODULE_TYPEDEFS_H_
diff --git a/webrtc/modules/audio_coding/main/test/opus_test.cc b/webrtc/modules/audio_coding/main/test/opus_test.cc
index ecc056a..8fda4b3 100644
--- a/webrtc/modules/audio_coding/main/test/opus_test.cc
+++ b/webrtc/modules/audio_coding/main/test/opus_test.cc
@@ -79,8 +79,8 @@
   in_file_mono_.ReadStereo(false);
 
   // Create Opus encoders for mono and stereo.
-  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1), -1);
-  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2), -1);
+  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0), -1);
+  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1), -1);
 
   // Create Opus decoders for mono and stereo for stand-alone testing of Opus.
   ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1);
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 0f058d0..bcbc4c2 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -447,6 +447,7 @@
     AudioEncoderOpus::Config config;
     config.frame_size_ms = static_cast<int>(frame_size_) / 48;
     config.payload_type = payload_type_;
+    config.application = AudioEncoderOpus::kVoip;
     audio_encoder_.reset(new AudioEncoderOpus(config));
   }
 };
@@ -461,6 +462,7 @@
     config.frame_size_ms = static_cast<int>(frame_size_) / 48;
     config.num_channels = 2;
     config.payload_type = payload_type_;
+    config.application = AudioEncoderOpus::kAudio;
     audio_encoder_.reset(new AudioEncoderOpus(config));
   }
 };
diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
index eddbffd..e1f53af 100644
--- a/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
+++ b/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
@@ -145,8 +145,10 @@
 }
 
 void NetEqOpusFecQualityTest::SetUp() {
+  // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+  int app = channels_ == 1 ? 0 : 1;
   // Create encoder memory.
-  WebRtcOpus_EncoderCreate(&opus_encoder_, channels_);
+  WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app);
   ASSERT_TRUE(opus_encoder_ != NULL);
   // Set bitrate.
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000));