NetEq: Fix bug in PLC for multi-channel audio

There is currently a bug in NetEq that causes audio to leak from the
first channel to all others during loss concealment. This CL fixes the
problem and also adds a unit test to verify.

Bug: webrtc:11145
Change-Id: Ia6c4a234ff7f78e9a6080f1cb17eb80af671c3dc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161091
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29974}
diff --git a/modules/audio_coding/neteq/expand.cc b/modules/audio_coding/neteq/expand.cc
index bf9cfbf..8df2c7a 100644
--- a/modules/audio_coding/neteq/expand.cc
+++ b/modules/audio_coding/neteq/expand.cc
@@ -469,6 +469,14 @@
 
   for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
     ChannelParameters& parameters = channel_parameters_[channel_ix];
+    if (channel_ix > 0) {
+      // When channel_ix == 0, audio_history contains the correct audio. For the
+      // other cases, we will have to copy the correct channel into
+      // audio_history.
+      (*sync_buffer_)[channel_ix].CopyTo(signal_length, audio_history_position,
+                                         audio_history.get());
+    }
+
     // Calculate suitable scaling.
     int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
         &audio_history[signal_length - correlation_length - start_index -
diff --git a/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
index 515fd9b..6fa56fd 100644
--- a/modules/audio_coding/neteq/neteq_stereo_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
@@ -111,8 +111,7 @@
     }
     int next_send_time = rtp_generator_mono_.GetRtpHeader(
         kPayloadTypeMono, frame_size_samples_, &rtp_header_mono_);
-    test::InputAudioFile::DuplicateInterleaved(
-        input_, frame_size_samples_, num_channels_, input_multi_channel_);
+    MakeMultiChannelInput();
     multi_payload_size_bytes_ = WebRtcPcm16b_Encode(
         input_multi_channel_, frame_size_samples_ * num_channels_,
         encoded_multi_channel_);
@@ -124,6 +123,11 @@
     return next_send_time;
   }
 
+  virtual void MakeMultiChannelInput() {
+    test::InputAudioFile::DuplicateInterleaved(
+        input_, frame_size_samples_, num_channels_, input_multi_channel_);
+  }
+
   virtual void VerifyOutput(size_t num_samples) {
     const int16_t* output_data = output_.data();
     const int16_t* output_multi_channel_data = output_multi_channel_.data();
@@ -330,6 +334,36 @@
   RunTest(100);
 }
 
+class NetEqStereoTestSingleActiveChannelPlc : public NetEqStereoTestLosses {
+ protected:
+  NetEqStereoTestSingleActiveChannelPlc() : NetEqStereoTestLosses() {}
+
+  virtual void MakeMultiChannelInput() override {
+    // Create a multi-channel input by copying the mono channel from file to the
+    // first channel, and setting the others to zero.
+    memset(input_multi_channel_, 0,
+           frame_size_samples_ * num_channels_ * sizeof(int16_t));
+    for (size_t i = 0; i < frame_size_samples_; ++i) {
+      input_multi_channel_[i * num_channels_] = input_[i];
+    }
+  }
+
+  virtual void VerifyOutput(size_t num_samples) override {
+    // Simply verify that all samples in channels other than the first are zero.
+    const int16_t* output_multi_channel_data = output_multi_channel_.data();
+    for (size_t i = 0; i < num_samples; ++i) {
+      for (size_t j = 1; j < num_channels_; ++j) {
+        EXPECT_EQ(0, output_multi_channel_data[i * num_channels_ + j])
+            << "Sample " << i << ", channel " << j << " is non-zero.";
+      }
+    }
+  }
+};
+
+TEST_P(NetEqStereoTestSingleActiveChannelPlc, RunTest) {
+  RunTest(100);
+}
+
 // Creates a list of parameter sets.
 std::list<TestParameters> GetTestParameters() {
   std::list<TestParameters> l;
@@ -384,4 +418,7 @@
                          NetEqStereoTestLosses,
                          ::testing::ValuesIn(GetTestParameters()));
 
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestSingleActiveChannelPlc,
+                         ::testing::ValuesIn(GetTestParameters()));
 }  // namespace webrtc