WebRTC Opus C interface: Add support for non-48 kHz encode sample rate

Plus tests fo 16 kHz.

Bug: webrtc:10631
Change-Id: I162c40b6120d7e308e535faba7501e437b0b5dc4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137047
Reviewed-by: Minyue Li <minyue@webrtc.org>
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28029}
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index 18b9ac5..3331648 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -760,7 +760,8 @@
                       config.application ==
                               AudioEncoderOpusConfig::ApplicationMode::kVoip
                           ? 0
-                          : 1));
+                          : 1,
+                      48000));
   const int bitrate = GetBitrateBps(config);
   RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
   RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
index 008d8d6..14f8f6d 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
@@ -577,7 +577,8 @@
                    config.application ==
                            AudioEncoderOpusConfig::ApplicationMode::kVoip
                        ? 0
-                       : 1));
+                       : 1,
+                   48000));
 
   // Bitrate below minmum wideband. Expect narrowband.
   config.bitrate_bps = absl::optional<int>(7999);
diff --git a/modules/audio_coding/codecs/opus/opus_fec_test.cc b/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 7552c20..0af90fe 100644
--- a/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -109,7 +109,7 @@
   int app = channels_ == 1 ? 0 : 1;
 
   // Create encoder memory.
-  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
   EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
   // Set bitrate.
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/modules/audio_coding/codecs/opus/opus_interface.c b/modules/audio_coding/codecs/opus/opus_interface.c
index d07a5b4..817caac 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/modules/audio_coding/codecs/opus/opus_interface.c
@@ -39,7 +39,8 @@
 
 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
                                  size_t channels,
-                                 int32_t application) {
+                                 int32_t application,
+                                 int sample_rate_hz) {
   int opus_app;
   if (!inst)
     return -1;
@@ -59,7 +60,7 @@
   RTC_DCHECK(state);
 
   int error;
-  state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
+  state->encoder = opus_encoder_create(sample_rate_hz, (int)channels, opus_app,
                                        &error);
 
   if (error != OPUS_OK || (!state->encoder &&
diff --git a/modules/audio_coding/codecs/opus/opus_interface.h b/modules/audio_coding/codecs/opus/opus_interface.h
index f5bcc45..54ecadd 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.h
+++ b/modules/audio_coding/codecs/opus/opus_interface.h
@@ -35,6 +35,7 @@
  *                                 Favor speech intelligibility.
  *                             1 - Audio applications.
  *                                 Favor faithfulness to the original input.
+ *      - sample_rate_hz     : sample rate of input audio
  *
  * Output:
  *      - inst               : a pointer to Encoder context that is created
@@ -45,7 +46,8 @@
  */
 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
                                  size_t channels,
-                                 int32_t application);
+                                 int32_t application,
+                                 int sample_rate_hz);
 
 /****************************************************************************
  * WebRtcOpus_MultistreamEncoderCreate(...)
diff --git a/modules/audio_coding/codecs/opus/opus_speed_test.cc b/modules/audio_coding/codecs/opus/opus_speed_test.cc
index 1a629a8..52cb14b 100644
--- a/modules/audio_coding/codecs/opus/opus_speed_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -46,7 +46,7 @@
   // 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_, app));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
   EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
   /* Set bitrate. */
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/modules/audio_coding/codecs/opus/opus_unittest.cc b/modules/audio_coding/codecs/opus/opus_unittest.cc
index d506e60..d0b240d 100644
--- a/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -39,47 +39,57 @@
 void CreateSingleOrMultiStreamEncoder(WebRtcOpusEncInst** opus_encoder,
                                       int channels,
                                       int application,
-                                      bool force_multistream = false) {
-  if (!force_multistream && (channels == 1 || channels == 2)) {
-    EXPECT_EQ(0, WebRtcOpus_EncoderCreate(opus_encoder, channels, application));
-  } else if (force_multistream && channels == 1) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
-                     opus_encoder, channels, application, kMonoTotalStreams,
-                     kMonoCoupledStreams, kMonoChannelMapping));
-  } else if (force_multistream && channels == 2) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
-                     opus_encoder, channels, application, kStereoTotalStreams,
-                     kStereoCoupledStreams, kStereoChannelMapping));
-  } else if (channels == 4) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
-                     opus_encoder, channels, application, kQuadTotalStreams,
-                     kQuadCoupledStreams, kQuadChannelMapping));
+                                      bool use_multistream,
+                                      int encoder_sample_rate_hz) {
+  EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream);
+  if (use_multistream) {
+    EXPECT_EQ(encoder_sample_rate_hz, 48000);
+    if (channels == 1) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+                       opus_encoder, channels, application, kMonoTotalStreams,
+                       kMonoCoupledStreams, kMonoChannelMapping));
+    } else if (channels == 2) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+                       opus_encoder, channels, application, kStereoTotalStreams,
+                       kStereoCoupledStreams, kStereoChannelMapping));
+    } else if (channels == 4) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+                       opus_encoder, channels, application, kQuadTotalStreams,
+                       kQuadCoupledStreams, kQuadChannelMapping));
+    } else {
+      EXPECT_TRUE(false) << channels;
+    }
   } else {
-    EXPECT_TRUE(false) << channels;
+    EXPECT_EQ(0, WebRtcOpus_EncoderCreate(opus_encoder, channels, application,
+                                          encoder_sample_rate_hz));
   }
 }
 
 void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder,
                                       int channels,
-                                      bool force_multistream = false) {
-  if (!force_multistream && (channels == 1 || channels == 2)) {
-    EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels));
-  } else if (channels == 1) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
-                     opus_decoder, channels, kMonoTotalStreams,
-                     kMonoCoupledStreams, kMonoChannelMapping));
-  } else if (channels == 2) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
-                     opus_decoder, channels, kStereoTotalStreams,
-                     kStereoCoupledStreams, kStereoChannelMapping));
-  } else if (channels == 4) {
-    EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
-                     opus_decoder, channels, kQuadTotalStreams,
-                     kQuadCoupledStreams, kQuadChannelMapping));
+                                      bool use_multistream) {
+  EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream);
+  if (use_multistream) {
+    if (channels == 1) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+                       opus_decoder, channels, kMonoTotalStreams,
+                       kMonoCoupledStreams, kMonoChannelMapping));
+    } else if (channels == 2) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+                       opus_decoder, channels, kStereoTotalStreams,
+                       kStereoCoupledStreams, kStereoChannelMapping));
+    } else if (channels == 4) {
+      EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+                       opus_decoder, channels, kQuadTotalStreams,
+                       kQuadCoupledStreams, kQuadChannelMapping));
+    } else {
+      EXPECT_TRUE(false) << channels;
+    }
   } else {
-    EXPECT_TRUE(false) << channels;
+    EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels));
   }
 }
+
 }  // namespace
 
 using test::AudioLoop;
@@ -90,13 +100,13 @@
 // Maximum number of bytes in output bitstream.
 const size_t kMaxBytes = 2000;
 // Sample rate of Opus.
-const size_t kOpusRateKhz = 48;
+const size_t kOpusDecodeRateKhz = 48;
 // Number of samples-per-channel in a 20 ms frame, sampled at 48 kHz.
-const size_t kOpus20msFrameSamples = kOpusRateKhz * 20;
+const size_t kOpus20msFrameDecodeSamples = kOpusDecodeRateKhz * 20;
 // Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
-const size_t kOpus10msFrameSamples = kOpusRateKhz * 10;
+const size_t kOpus10msFrameDecodeSamples = kOpusDecodeRateKhz * 10;
 
-class OpusTest : public TestWithParam<::testing::tuple<int, int, bool>> {
+class OpusTest : public TestWithParam<::testing::tuple<int, int, bool, int>> {
  protected:
   OpusTest();
 
@@ -108,9 +118,7 @@
   // After preparation, |speech_data_.GetNextBlock()| returns a pointer to a
   // block of |block_length_ms| milliseconds. The data is looped every
   // |loop_length_ms| milliseconds.
-  void PrepareSpeechData(size_t channel,
-                         int block_length_ms,
-                         int loop_length_ms);
+  void PrepareSpeechData(int block_length_ms, int loop_length_ms);
 
   int EncodeDecode(WebRtcOpusEncInst* encoder,
                    rtc::ArrayView<const int16_t> input_audio,
@@ -133,9 +141,10 @@
   AudioLoop speech_data_;
   uint8_t bitstream_[kMaxBytes];
   size_t encoded_bytes_;
-  size_t channels_;
-  int application_;
-  bool force_multistream_;
+  const size_t channels_;
+  const int application_;
+  const bool use_multistream_;
+  const int encoder_sample_rate_hz_;
 };
 
 OpusTest::OpusTest()
@@ -144,11 +153,10 @@
       encoded_bytes_(0),
       channels_(static_cast<size_t>(::testing::get<0>(GetParam()))),
       application_(::testing::get<1>(GetParam())),
-      force_multistream_(::testing::get<2>(GetParam())) {}
+      use_multistream_(::testing::get<2>(GetParam())),
+      encoder_sample_rate_hz_(::testing::get<3>(GetParam())) {}
 
-void OpusTest::PrepareSpeechData(size_t channel,
-                                 int block_length_ms,
-                                 int loop_length_ms) {
+void OpusTest::PrepareSpeechData(int block_length_ms, int loop_length_ms) {
   std::map<int, std::string> channel_to_basename = {
       {1, "audio_coding/testfile32kHz"},
       {2, "audio_coding/teststereo32kHz"},
@@ -156,13 +164,15 @@
   std::map<int, std::string> channel_to_suffix = {
       {1, "pcm"}, {2, "pcm"}, {4, "wav"}};
   const std::string file_name = webrtc::test::ResourcePath(
-      channel_to_basename[channel], channel_to_suffix[channel]);
+      channel_to_basename[channels_], channel_to_suffix[channels_]);
   if (loop_length_ms < block_length_ms) {
     loop_length_ms = block_length_ms;
   }
+  const int sample_rate_khz =
+      rtc::CheckedDivExact(encoder_sample_rate_hz_, 1000);
   EXPECT_TRUE(speech_data_.Init(file_name,
-                                loop_length_ms * kOpusRateKhz * channel,
-                                block_length_ms * kOpusRateKhz * channel));
+                                loop_length_ms * sample_rate_khz * channels_,
+                                block_length_ms * sample_rate_khz * channels_));
 }
 
 void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
@@ -207,33 +217,35 @@
 // 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, int block_length_ms) {
-  PrepareSpeechData(channels_, block_length_ms, 2000);
-  const size_t samples = kOpusRateKhz * block_length_ms;
+  PrepareSpeechData(block_length_ms, 2000);
+  const size_t input_samples =
+      rtc::CheckedDivExact(encoder_sample_rate_hz_, 1000) * block_length_ms;
+  const size_t output_samples = kOpusDecodeRateKhz * block_length_ms;
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // Set bitrate.
   EXPECT_EQ(
       0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
 
   // Set input audio as silence.
-  std::vector<int16_t> silence(samples * channels_, 0);
+  std::vector<int16_t> silence(input_samples * channels_, 0);
 
   // Setting DTX.
   EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_)
                    : WebRtcOpus_DisableDtx(opus_encoder_));
 
   int16_t audio_type;
-  int16_t* output_data_decode = new int16_t[samples * channels_];
+  int16_t* output_data_decode = new int16_t[output_samples * channels_];
 
   for (int i = 0; i < 100; ++i) {
-    EXPECT_EQ(samples, static_cast<size_t>(EncodeDecode(
-                           opus_encoder_, speech_data_.GetNextBlock(),
-                           opus_decoder_, output_data_decode, &audio_type)));
+    EXPECT_EQ(output_samples,
+              static_cast<size_t>(EncodeDecode(
+                  opus_encoder_, speech_data_.GetNextBlock(), 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) {
@@ -247,9 +259,9 @@
   // 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 < 30; ++i) {
-    EXPECT_EQ(samples, static_cast<size_t>(
-                           EncodeDecode(opus_encoder_, silence, opus_decoder_,
-                                        output_data_decode, &audio_type)));
+    EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+                                  opus_encoder_, silence, opus_decoder_,
+                                  output_data_decode, &audio_type)));
     if (!dtx) {
       EXPECT_GT(encoded_bytes_, 1U);
       EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
@@ -268,7 +280,9 @@
   // a certain number of frames.
 
   // |max_dtx_frames| is the maximum number of frames Opus can stay in DTX.
-  const int max_dtx_frames = 400 / block_length_ms + 1;
+  // TODO(kwiberg): Why does this number depend on the encoding sample rate?
+  const int max_dtx_frames =
+      (encoder_sample_rate_hz_ == 16000 ? 800 : 400) / block_length_ms + 1;
 
   // We run |kRunTimeMs| milliseconds of pure silence.
   const int kRunTimeMs = 4500;
@@ -295,9 +309,9 @@
     int i = 0;
     for (; i < max_dtx_frames; ++i) {
       time += block_length_ms;
-      EXPECT_EQ(samples, static_cast<size_t>(
-                             EncodeDecode(opus_encoder_, silence, opus_decoder_,
-                                          output_data_decode, &audio_type)));
+      EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+                                    opus_encoder_, silence, opus_decoder_,
+                                    output_data_decode, &audio_type)));
       if (dtx) {
         if (encoded_bytes_ > 1)
           break;
@@ -307,7 +321,7 @@
         EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
         EXPECT_EQ(2, audio_type);  // Comfort noise.
         if (time >= kCheckTimeMs) {
-          CheckAudioBounded(output_data_decode, samples, channels_,
+          CheckAudioBounded(output_data_decode, output_samples, channels_,
                             kOutputValueBound);
         }
       } else {
@@ -330,16 +344,16 @@
 
     // Enters DTX again immediately.
     time += block_length_ms;
-    EXPECT_EQ(samples, static_cast<size_t>(
-                           EncodeDecode(opus_encoder_, silence, opus_decoder_,
-                                        output_data_decode, &audio_type)));
+    EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+                                  opus_encoder_, silence, opus_decoder_,
+                                  output_data_decode, &audio_type)));
     if (dtx) {
       EXPECT_EQ(1U, encoded_bytes_);  // Send 1 byte.
       EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
       EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
       EXPECT_EQ(2, audio_type);  // Comfort noise.
       if (time >= kCheckTimeMs) {
-        CheckAudioBounded(output_data_decode, samples, channels_,
+        CheckAudioBounded(output_data_decode, output_samples, channels_,
                           kOutputValueBound);
       }
     } else {
@@ -353,9 +367,9 @@
   silence[0] = 10000;
   if (dtx) {
     // Verify that encoder/decoder can jump out from DTX mode.
-    EXPECT_EQ(samples, static_cast<size_t>(
-                           EncodeDecode(opus_encoder_, silence, opus_decoder_,
-                                        output_data_decode, &audio_type)));
+    EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+                                  opus_encoder_, silence, opus_decoder_,
+                                  output_data_decode, &audio_type)));
     EXPECT_GT(encoded_bytes_, 1U);
     EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
     EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
@@ -370,17 +384,16 @@
 
 // Test if CBR does what we expect.
 void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
-  PrepareSpeechData(channels_, block_length_ms, 2000);
-  const size_t samples = kOpusRateKhz * block_length_ms;
+  PrepareSpeechData(block_length_ms, 2000);
+  const size_t output_samples = kOpusDecodeRateKhz * block_length_ms;
 
   int32_t max_pkt_size_diff = 0;
   int32_t prev_pkt_size = 0;
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // Set bitrate.
   EXPECT_EQ(
@@ -391,11 +404,12 @@
                    : WebRtcOpus_DisableCbr(opus_encoder_));
 
   int16_t audio_type;
-  std::vector<int16_t> audio_out(samples * channels_);
+  std::vector<int16_t> audio_out(output_samples * channels_);
   for (int i = 0; i < 100; ++i) {
-    EXPECT_EQ(samples, static_cast<size_t>(EncodeDecode(
-                           opus_encoder_, speech_data_.GetNextBlock(),
-                           opus_decoder_, audio_out.data(), &audio_type)));
+    EXPECT_EQ(output_samples,
+              static_cast<size_t>(
+                  EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+                               opus_decoder_, audio_out.data(), &audio_type)));
 
     if (prev_pkt_size > 0) {
       int32_t diff = std::abs((int32_t)encoded_bytes_ - prev_pkt_size);
@@ -421,11 +435,13 @@
   WebRtcOpusDecInst* opus_decoder;
 
   // Test to see that an invalid pointer is caught.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0, 48000));
   // Invalid channel number.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0, 48000));
   // Invalid applciation mode.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2, 48000));
+  // Invalid sample rate.
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 0, 12345));
 
   EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
   // Invalid channel number.
@@ -442,9 +458,8 @@
 // Test normal Create and Free.
 TEST_P(OpusTest, OpusCreateFree) {
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
   EXPECT_TRUE(opus_encoder_ != NULL);
   EXPECT_TRUE(opus_decoder_ != NULL);
   // Free encoder and decoder memory.
@@ -458,13 +473,12 @@
       : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs)
 
 TEST_P(OpusTest, OpusEncodeDecode) {
-  PrepareSpeechData(channels_, 20, 20);
+  PrepareSpeechData(20, 20);
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // Set bitrate.
   EXPECT_EQ(
@@ -481,8 +495,9 @@
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
-  EXPECT_EQ(kOpus20msFrameSamples,
+  int16_t* output_data_decode =
+      new int16_t[kOpus20msFrameDecodeSamples * channels_];
+  EXPECT_EQ(kOpus20msFrameDecodeSamples,
             static_cast<size_t>(
                 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
                              opus_decoder_, output_data_decode, &audio_type)));
@@ -499,7 +514,7 @@
 
   // Create encoder memory, try with different bitrates.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
   EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
@@ -515,7 +530,7 @@
 
   // Create encoder memory, try with different complexities.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
 
   EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
   EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
@@ -531,11 +546,11 @@
     // narrowband when it's configured with FULLBAND.
     return;
   }
-  PrepareSpeechData(channels_, 20, 20);
+  PrepareSpeechData(20, 20);
 
   int16_t audio_type;
   std::unique_ptr<int16_t[]> output_data_decode(
-      new int16_t[kOpus20msFrameSamples * channels_]());
+      new int16_t[kOpus20msFrameDecodeSamples * channels_]());
 
   // Test without creating encoder memory.
   EXPECT_EQ(-1,
@@ -544,9 +559,8 @@
 
   // Create encoder memory, try with different bandwidths.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
                                         OPUS_BANDWIDTH_NARROWBAND - 1));
@@ -558,12 +572,16 @@
   EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND));
   EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
                output_data_decode.get(), &audio_type);
-  EXPECT_EQ(OPUS_BANDWIDTH_FULLBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
+  EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND
+                                             : OPUS_BANDWIDTH_FULLBAND,
+            WebRtcOpus_GetBandwidth(opus_encoder_));
   EXPECT_EQ(
       -1, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND + 1));
   EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
                output_data_decode.get(), &audio_type);
-  EXPECT_EQ(OPUS_BANDWIDTH_FULLBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
+  EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND
+                                             : OPUS_BANDWIDTH_FULLBAND,
+            WebRtcOpus_GetBandwidth(opus_encoder_));
 
   // Free memory.
   EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
@@ -575,7 +593,7 @@
   EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
 
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
   ASSERT_NE(nullptr, opus_encoder_);
 
   if (channels_ >= 2) {
@@ -595,25 +613,25 @@
 // Encode and decode one frame, initialize the decoder and
 // decode once more.
 TEST_P(OpusTest, OpusDecodeInit) {
-  PrepareSpeechData(channels_, 20, 20);
+  PrepareSpeechData(20, 20);
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
-  EXPECT_EQ(kOpus20msFrameSamples,
+  int16_t* output_data_decode =
+      new int16_t[kOpus20msFrameDecodeSamples * channels_];
+  EXPECT_EQ(kOpus20msFrameDecodeSamples,
             static_cast<size_t>(
                 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
                              opus_decoder_, output_data_decode, &audio_type)));
 
   WebRtcOpus_DecoderInit(opus_decoder_);
 
-  EXPECT_EQ(kOpus20msFrameSamples,
+  EXPECT_EQ(kOpus20msFrameDecodeSamples,
             static_cast<size_t>(
                 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
                                   output_data_decode, &audio_type)));
@@ -631,7 +649,7 @@
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
 
   EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
   EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
@@ -647,7 +665,7 @@
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
 
   opus_int32 dtx;
 
@@ -704,7 +722,7 @@
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
 
   EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
   EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
@@ -720,7 +738,7 @@
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
 
   SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
   SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
@@ -739,13 +757,12 @@
 
 // Test PLC.
 TEST_P(OpusTest, OpusDecodePlc) {
-  PrepareSpeechData(channels_, 20, 20);
+  PrepareSpeechData(20, 20);
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // Set bitrate.
   EXPECT_EQ(
@@ -756,16 +773,18 @@
 
   // Encode & decode.
   int16_t audio_type;
-  int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
-  EXPECT_EQ(kOpus20msFrameSamples,
+  int16_t* output_data_decode =
+      new int16_t[kOpus20msFrameDecodeSamples * channels_];
+  EXPECT_EQ(kOpus20msFrameDecodeSamples,
             static_cast<size_t>(
                 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
                              opus_decoder_, output_data_decode, &audio_type)));
 
   // Call decoder PLC.
-  int16_t* plc_buffer = new int16_t[kOpus20msFrameSamples * channels_];
-  EXPECT_EQ(kOpus20msFrameSamples, static_cast<size_t>(WebRtcOpus_DecodePlc(
-                                       opus_decoder_, plc_buffer, 1)));
+  int16_t* plc_buffer = new int16_t[kOpus20msFrameDecodeSamples * channels_];
+  EXPECT_EQ(
+      kOpus20msFrameDecodeSamples,
+      static_cast<size_t>(WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1)));
 
   // Free memory.
   delete[] plc_buffer;
@@ -776,13 +795,12 @@
 
 // Duration estimation.
 TEST_P(OpusTest, OpusDurationEstimation) {
-  PrepareSpeechData(channels_, 20, 20);
+  PrepareSpeechData(20, 20);
 
   // Create.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
 
   // 10 ms. We use only first 10 ms of a 20 ms block.
   auto speech_block = speech_data_.GetNextBlock();
@@ -792,7 +810,7 @@
       bitstream_);
   EXPECT_GE(encoded_bytes_int, 0);
   EXPECT_EQ(
-      kOpus10msFrameSamples,
+      kOpus10msFrameDecodeSamples,
       static_cast<size_t>(WebRtcOpus_DurationEst(
           opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
 
@@ -804,7 +822,7 @@
                         kMaxBytes, bitstream_);
   EXPECT_GE(encoded_bytes_int, 0);
   EXPECT_EQ(
-      kOpus20msFrameSamples,
+      kOpus20msFrameDecodeSamples,
       static_cast<size_t>(WebRtcOpus_DurationEst(
           opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
 
@@ -822,14 +840,13 @@
   }
   constexpr size_t kPackets = 6;
 
-  PrepareSpeechData(channels_, 20, 20 * kPackets);
+  PrepareSpeechData(20, 20 * kPackets);
 
   // Create encoder memory.
   CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
-                                   force_multistream_);
+                                   use_multistream_, encoder_sample_rate_hz_);
   ASSERT_NE(nullptr, opus_encoder_);
-  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
-                                   force_multistream_);
+  CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
   ASSERT_NE(nullptr, opus_decoder_);
 
   // Set bitrate.
@@ -842,7 +859,7 @@
   // Encode & decode.
   int16_t audio_type;
   std::unique_ptr<int16_t[]> output_data_decode(
-      new int16_t[kPackets * kOpus20msFrameSamples * channels_]);
+      new int16_t[kPackets * kOpus20msFrameDecodeSamples * channels_]);
   OpusRepacketizer* rp = opus_repacketizer_create();
 
   size_t num_packets = 0;
@@ -870,11 +887,11 @@
 
   encoded_bytes_ = opus_repacketizer_out(rp, bitstream_, kMaxBytes);
 
-  EXPECT_EQ(kOpus20msFrameSamples * kPackets,
+  EXPECT_EQ(kOpus20msFrameDecodeSamples * kPackets,
             static_cast<size_t>(WebRtcOpus_DurationEst(
                 opus_decoder_, bitstream_, encoded_bytes_)));
 
-  EXPECT_EQ(kOpus20msFrameSamples * kPackets,
+  EXPECT_EQ(kOpus20msFrameDecodeSamples * kPackets,
             static_cast<size_t>(
                 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
                                   output_data_decode.get(), &audio_type)));
@@ -888,12 +905,18 @@
 INSTANTIATE_TEST_SUITE_P(VariousMode,
                          OpusTest,
                          ::testing::ValuesIn({
-                             std::make_tuple(1, 0, true),
-                             std::make_tuple(2, 1, true),
-                             std::make_tuple(2, 0, false),
-                             std::make_tuple(4, 0, false),
-                             std::make_tuple(1, 1, false),
-                             std::make_tuple(4, 1, false),
+                             std::make_tuple(1, 0, false, 16000),
+                             std::make_tuple(1, 1, false, 16000),
+                             std::make_tuple(2, 0, false, 16000),
+                             std::make_tuple(2, 1, false, 16000),
+                             std::make_tuple(1, 0, false, 48000),
+                             std::make_tuple(1, 1, false, 48000),
+                             std::make_tuple(2, 0, false, 48000),
+                             std::make_tuple(2, 1, false, 48000),
+                             std::make_tuple(1, 0, true, 48000),
+                             std::make_tuple(2, 1, true, 48000),
+                             std::make_tuple(4, 0, true, 48000),
+                             std::make_tuple(4, 1, true, 48000),
                          }));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc b/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc
index e56c817..6a6b665 100644
--- a/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc
+++ b/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc
@@ -111,7 +111,7 @@
 
 void NetEqOpusQualityTest::SetUp() {
   // Create encoder memory.
-  WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_);
+  WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_, 48000);
   ASSERT_TRUE(opus_encoder_);
 
   // Create repacketizer.
diff --git a/modules/audio_coding/test/opus_test.cc b/modules/audio_coding/test/opus_test.cc
index 38b2362..38d97a7 100644
--- a/modules/audio_coding/test/opus_test.cc
+++ b/modules/audio_coding/test/opus_test.cc
@@ -73,8 +73,8 @@
   in_file_mono_.ReadStereo(false);
 
   // Create Opus encoders for mono and stereo.
-  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0), -1);
-  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1), -1);
+  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0, 48000), -1);
+  ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1, 48000), -1);
 
   // Create Opus decoders for mono and stereo for stand-alone testing of Opus.
   ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1);