Adding a delay line to NetEq's output

This change adds an optional delay to NetEq's output. Note, this is not
equivalent to increasing the jitter buffer with the same extra length.

Bug: b/156734419
Change-Id: I8b70b6b3bffcfd3da296ccf29853864baa03d6bb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/175110
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31343}
diff --git a/api/audio/audio_frame.cc b/api/audio/audio_frame.cc
index 47459ac..c6e5cf4 100644
--- a/api/audio/audio_frame.cc
+++ b/api/audio/audio_frame.cc
@@ -11,6 +11,8 @@
 #include "api/audio/audio_frame.h"
 
 #include <string.h>
+#include <algorithm>
+#include <utility>
 
 #include "rtc_base/checks.h"
 #include "rtc_base/time_utils.h"
@@ -22,6 +24,28 @@
   static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
 }
 
+void swap(AudioFrame& a, AudioFrame& b) {
+  using std::swap;
+  swap(a.timestamp_, b.timestamp_);
+  swap(a.elapsed_time_ms_, b.elapsed_time_ms_);
+  swap(a.ntp_time_ms_, b.ntp_time_ms_);
+  swap(a.samples_per_channel_, b.samples_per_channel_);
+  swap(a.sample_rate_hz_, b.sample_rate_hz_);
+  swap(a.num_channels_, b.num_channels_);
+  swap(a.channel_layout_, b.channel_layout_);
+  swap(a.speech_type_, b.speech_type_);
+  swap(a.vad_activity_, b.vad_activity_);
+  swap(a.profile_timestamp_ms_, b.profile_timestamp_ms_);
+  swap(a.packet_infos_, b.packet_infos_);
+  const size_t length_a = a.samples_per_channel_ * a.num_channels_;
+  const size_t length_b = b.samples_per_channel_ * b.num_channels_;
+  RTC_DCHECK_LE(length_a, AudioFrame::kMaxDataSizeSamples);
+  RTC_DCHECK_LE(length_b, AudioFrame::kMaxDataSizeSamples);
+  std::swap_ranges(a.data_, a.data_ + std::max(length_a, length_b), b.data_);
+  swap(a.muted_, b.muted_);
+  swap(a.absolute_capture_timestamp_ms_, b.absolute_capture_timestamp_ms_);
+}
+
 void AudioFrame::Reset() {
   ResetWithoutMuting();
   muted_ = true;
diff --git a/api/audio/audio_frame.h b/api/audio/audio_frame.h
index 06b0b28..78539f5 100644
--- a/api/audio/audio_frame.h
+++ b/api/audio/audio_frame.h
@@ -14,6 +14,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <utility>
+
 #include "api/audio/channel_layout.h"
 #include "api/rtp_packet_infos.h"
 #include "rtc_base/constructor_magic.h"
@@ -58,6 +60,8 @@
 
   AudioFrame();
 
+  friend void swap(AudioFrame& a, AudioFrame& b);
+
   // Resets all members to their default state.
   void Reset();
   // Same as Reset(), but leaves mute state unchanged. Muting a frame requires
diff --git a/api/audio/test/audio_frame_unittest.cc b/api/audio/test/audio_frame_unittest.cc
index dbf45ce..f8d3318 100644
--- a/api/audio/test/audio_frame_unittest.cc
+++ b/api/audio/test/audio_frame_unittest.cc
@@ -133,4 +133,54 @@
   EXPECT_EQ(0, memcmp(frame2.data(), frame1.data(), sizeof(samples)));
 }
 
+TEST(AudioFrameTest, SwapFrames) {
+  AudioFrame frame1, frame2;
+  int16_t samples1[kNumChannelsMono * kSamplesPerChannel];
+  for (size_t i = 0; i < kNumChannelsMono * kSamplesPerChannel; ++i) {
+    samples1[i] = i;
+  }
+  frame1.UpdateFrame(kTimestamp, samples1, kSamplesPerChannel, kSampleRateHz,
+                     AudioFrame::kPLC, AudioFrame::kVadActive,
+                     kNumChannelsMono);
+  frame1.set_absolute_capture_timestamp_ms(12345678);
+  const auto frame1_channel_layout = frame1.channel_layout();
+
+  int16_t samples2[(kNumChannelsMono + 1) * (kSamplesPerChannel + 1)];
+  for (size_t i = 0; i < (kNumChannelsMono + 1) * (kSamplesPerChannel + 1);
+       ++i) {
+    samples2[i] = 1000 + i;
+  }
+  frame2.UpdateFrame(kTimestamp + 1, samples2, kSamplesPerChannel + 1,
+                     kSampleRateHz + 1, AudioFrame::kNormalSpeech,
+                     AudioFrame::kVadPassive, kNumChannelsMono + 1);
+  const auto frame2_channel_layout = frame2.channel_layout();
+
+  swap(frame1, frame2);
+
+  EXPECT_EQ(kTimestamp + 1, frame1.timestamp_);
+  ASSERT_EQ(kSamplesPerChannel + 1, frame1.samples_per_channel_);
+  EXPECT_EQ(kSampleRateHz + 1, frame1.sample_rate_hz_);
+  EXPECT_EQ(AudioFrame::kNormalSpeech, frame1.speech_type_);
+  EXPECT_EQ(AudioFrame::kVadPassive, frame1.vad_activity_);
+  ASSERT_EQ(kNumChannelsMono + 1, frame1.num_channels_);
+  for (size_t i = 0; i < (kNumChannelsMono + 1) * (kSamplesPerChannel + 1);
+       ++i) {
+    EXPECT_EQ(samples2[i], frame1.data()[i]);
+  }
+  EXPECT_FALSE(frame1.absolute_capture_timestamp_ms());
+  EXPECT_EQ(frame2_channel_layout, frame1.channel_layout());
+
+  EXPECT_EQ(kTimestamp, frame2.timestamp_);
+  ASSERT_EQ(kSamplesPerChannel, frame2.samples_per_channel_);
+  EXPECT_EQ(kSampleRateHz, frame2.sample_rate_hz_);
+  EXPECT_EQ(AudioFrame::kPLC, frame2.speech_type_);
+  EXPECT_EQ(AudioFrame::kVadActive, frame2.vad_activity_);
+  ASSERT_EQ(kNumChannelsMono, frame2.num_channels_);
+  for (size_t i = 0; i < kNumChannelsMono * kSamplesPerChannel; ++i) {
+    EXPECT_EQ(samples1[i], frame2.data()[i]);
+  }
+  EXPECT_EQ(12345678, frame2.absolute_capture_timestamp_ms());
+  EXPECT_EQ(frame1_channel_layout, frame2.channel_layout());
+}
+
 }  // namespace webrtc