Extend TestAudioDeviceModule API.

Extend TestAudioDeviceModule API to be able to create WavReader/WavWriter from rtc::PlatformFile

Bug: webrtc:8946
Change-Id: Ieea16be91c40a5928689cdeaa8a17d75fee0cf82
Reviewed-on: https://webrtc-review.googlesource.com/63266
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22576}
diff --git a/modules/audio_device/include/test_audio_device.cc b/modules/audio_device/include/test_audio_device.cc
index f888cd0..b67d529 100644
--- a/modules/audio_device/include/test_audio_device.cc
+++ b/modules/audio_device/include/test_audio_device.cc
@@ -21,7 +21,9 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/event.h"
+#include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
+#include "rtc_base/ptr_util.h"
 #include "rtc_base/random.h"
 #include "rtc_base/refcountedobject.h"
 #include "system_wrappers/include/event_wrapper.h"
@@ -276,12 +278,16 @@
   WavFileReader(std::string filename,
                 int sampling_frequency_in_hz,
                 int num_channels)
-      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
-        num_channels_(num_channels),
-        wav_reader_(filename) {
-    RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
-    RTC_CHECK_EQ(wav_reader_.num_channels(), num_channels);
-  }
+      : WavFileReader(rtc::MakeUnique<WavReader>(filename),
+                      sampling_frequency_in_hz,
+                      num_channels) {}
+
+  WavFileReader(rtc::PlatformFile file,
+                int sampling_frequency_in_hz,
+                int num_channels)
+      : WavFileReader(rtc::MakeUnique<WavReader>(file),
+                      sampling_frequency_in_hz,
+                      num_channels) {}
 
   int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
 
@@ -292,15 +298,25 @@
         TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
             num_channels_,
         [&](rtc::ArrayView<int16_t> data) {
-          return wav_reader_.ReadSamples(data.size(), data.data());
+          return wav_reader_->ReadSamples(data.size(), data.data());
         });
     return buffer->size() > 0;
   }
 
  private:
+  WavFileReader(std::unique_ptr<WavReader> wav_reader,
+                int sampling_frequency_in_hz,
+                int num_channels)
+      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+        num_channels_(num_channels),
+        wav_reader_(std::move(wav_reader)) {
+    RTC_CHECK_EQ(wav_reader_->sample_rate(), sampling_frequency_in_hz);
+    RTC_CHECK_EQ(wav_reader_->num_channels(), num_channels);
+  }
+
   int sampling_frequency_in_hz_;
   const int num_channels_;
-  WavReader wav_reader_;
+  std::unique_ptr<WavReader> wav_reader_;
 };
 
 class WavFileWriter final : public TestAudioDeviceModule::Renderer {
@@ -308,22 +324,40 @@
   WavFileWriter(std::string filename,
                 int sampling_frequency_in_hz,
                 int num_channels)
-      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
-        wav_writer_(filename, sampling_frequency_in_hz, num_channels),
-        num_channels_(num_channels) {}
+      : WavFileWriter(rtc::MakeUnique<WavWriter>(filename,
+                                                 sampling_frequency_in_hz,
+                                                 num_channels),
+                      sampling_frequency_in_hz,
+                      num_channels) {}
+
+  WavFileWriter(rtc::PlatformFile file,
+                int sampling_frequency_in_hz,
+                int num_channels)
+      : WavFileWriter(rtc::MakeUnique<WavWriter>(file,
+                                                 sampling_frequency_in_hz,
+                                                 num_channels),
+                      sampling_frequency_in_hz,
+                      num_channels) {}
 
   int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
 
   int NumChannels() const override { return num_channels_; }
 
   bool Render(rtc::ArrayView<const int16_t> data) override {
-    wav_writer_.WriteSamples(data.data(), data.size());
+    wav_writer_->WriteSamples(data.data(), data.size());
     return true;
   }
 
  private:
+  WavFileWriter(std::unique_ptr<WavWriter> wav_writer,
+                int sampling_frequency_in_hz,
+                int num_channels)
+      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+        wav_writer_(std::move(wav_writer)),
+        num_channels_(num_channels) {}
+
   int sampling_frequency_in_hz_;
-  WavWriter wav_writer_;
+  std::unique_ptr<WavWriter> wav_writer_;
   const int num_channels_;
 };
 
@@ -342,6 +376,19 @@
         started_writing_(false),
         trailing_zeros_(0) {}
 
+  BoundedWavFileWriter(rtc::PlatformFile file,
+                       int sampling_frequency_in_hz,
+                       int num_channels)
+      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+        wav_writer_(file, sampling_frequency_in_hz, num_channels),
+        num_channels_(num_channels),
+        silent_audio_(
+            TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) *
+                num_channels,
+            0),
+        started_writing_(false),
+        trailing_zeros_(0) {}
+
   int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
 
   int NumChannels() const override { return num_channels_; }
@@ -436,11 +483,11 @@
                                   num_channels));
 }
 
-std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>
-TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude,
-                                                 int sampling_frequency_in_hz) {
-  return std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>(
-      new PulsedNoiseCapturerImpl(max_amplitude, sampling_frequency_in_hz, 1));
+std::unique_ptr<TestAudioDeviceModule::Renderer>
+TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz,
+                                             int num_channels) {
+  return std::unique_ptr<TestAudioDeviceModule::Renderer>(
+      new DiscardRenderer(sampling_frequency_in_hz, num_channels));
 }
 
 std::unique_ptr<TestAudioDeviceModule::Capturer>
@@ -452,17 +499,10 @@
 }
 
 std::unique_ptr<TestAudioDeviceModule::Capturer>
-TestAudioDeviceModule::CreateWavFileReader(std::string filename,
-                                           int sampling_frequency_in_hz) {
-  return std::unique_ptr<TestAudioDeviceModule::Capturer>(
-      new WavFileReader(filename, sampling_frequency_in_hz, 1));
-}
-
-std::unique_ptr<TestAudioDeviceModule::Capturer>
 TestAudioDeviceModule::CreateWavFileReader(std::string filename) {
   WavReader reader(filename);
   int sampling_frequency_in_hz = reader.sample_rate();
-  int num_channels = static_cast<int>(reader.num_channels());
+  int num_channels = rtc::checked_cast<int>(reader.num_channels());
   return std::unique_ptr<TestAudioDeviceModule::Capturer>(
       new WavFileReader(filename, sampling_frequency_in_hz, num_channels));
 }
@@ -476,13 +516,6 @@
 }
 
 std::unique_ptr<TestAudioDeviceModule::Renderer>
-TestAudioDeviceModule::CreateWavFileWriter(std::string filename,
-                                           int sampling_frequency_in_hz) {
-  return std::unique_ptr<TestAudioDeviceModule::Renderer>(
-      new WavFileWriter(filename, sampling_frequency_in_hz, 1));
-}
-
-std::unique_ptr<TestAudioDeviceModule::Renderer>
 TestAudioDeviceModule::CreateBoundedWavFileWriter(std::string filename,
                                                   int sampling_frequency_in_hz,
                                                   int num_channels) {
@@ -491,25 +524,37 @@
                                num_channels));
 }
 
-std::unique_ptr<TestAudioDeviceModule::Renderer>
-TestAudioDeviceModule::CreateBoundedWavFileWriter(
-    std::string filename,
-    int sampling_frequency_in_hz) {
-  return std::unique_ptr<TestAudioDeviceModule::Renderer>(
-      new BoundedWavFileWriter(filename, sampling_frequency_in_hz, 1));
+std::unique_ptr<TestAudioDeviceModule::Capturer>
+TestAudioDeviceModule::CreateWavFileReader(rtc::PlatformFile file,
+                                           int sampling_frequency_in_hz,
+                                           int num_channels) {
+  return std::unique_ptr<TestAudioDeviceModule::Capturer>(
+      new WavFileReader(file, sampling_frequency_in_hz, num_channels));
+}
+
+std::unique_ptr<TestAudioDeviceModule::Capturer>
+TestAudioDeviceModule::CreateWavFileReader(rtc::PlatformFile file) {
+  WavReader reader(file);
+  int sampling_frequency_in_hz = reader.sample_rate();
+  int num_channels = rtc::checked_cast<int>(reader.num_channels());
+  return std::unique_ptr<TestAudioDeviceModule::Capturer>(
+      new WavFileReader(file, sampling_frequency_in_hz, num_channels));
 }
 
 std::unique_ptr<TestAudioDeviceModule::Renderer>
-TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz,
-                                             int num_channels) {
+TestAudioDeviceModule::CreateWavFileWriter(rtc::PlatformFile file,
+                                           int sampling_frequency_in_hz,
+                                           int num_channels) {
   return std::unique_ptr<TestAudioDeviceModule::Renderer>(
-      new DiscardRenderer(sampling_frequency_in_hz, num_channels));
+      new WavFileWriter(file, sampling_frequency_in_hz, num_channels));
 }
 
 std::unique_ptr<TestAudioDeviceModule::Renderer>
-TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz) {
+TestAudioDeviceModule::CreateBoundedWavFileWriter(rtc::PlatformFile file,
+                                                  int sampling_frequency_in_hz,
+                                                  int num_channels) {
   return std::unique_ptr<TestAudioDeviceModule::Renderer>(
-      new DiscardRenderer(sampling_frequency_in_hz, 1));
+      new BoundedWavFileWriter(file, sampling_frequency_in_hz, num_channels));
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_device/include/test_audio_device.h b/modules/audio_device/include/test_audio_device.h
index 58a922e..4a75df3 100644
--- a/modules/audio_device/include/test_audio_device.h
+++ b/modules/audio_device/include/test_audio_device.h
@@ -17,6 +17,7 @@
 #include "modules/audio_device/include/audio_device.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/event.h"
+#include "rtc_base/platform_file.h"
 #include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
@@ -85,40 +86,31 @@
   static std::unique_ptr<PulsedNoiseCapturer> CreatePulsedNoiseCapturer(
       int16_t max_amplitude,
       int sampling_frequency_in_hz,
-      int num_channels);
+      int num_channels = 1);
 
-  // Same as calling CreatePulsedNoiseCapturer(max_amplitude,
-  // sampling_frequency_in_hz, 1).
-  static std::unique_ptr<PulsedNoiseCapturer> CreatePulsedNoiseCapturer(
-      int16_t max_amplitude,
-      int sampling_frequency_in_hz);
+  // Returns a Renderer instance that does nothing with the audio data.
+  static std::unique_ptr<Renderer> CreateDiscardRenderer(
+      int sampling_frequency_in_hz,
+      int num_channels = 1);
+
+  // WavReader and WavWriter creation based on file name.
 
   // Returns a Capturer instance that gets its data from a file. The sample rate
-  // and channels will be check against the Wav file.
+  // and channels will be checked against the Wav file.
   static std::unique_ptr<Capturer> CreateWavFileReader(
       std::string filename,
       int sampling_frequency_in_hz,
-      int num_channels);
-
-  // Same as calling CreateWavFileReader(filename, sampling_frequency_in_hz, 1).
-  static std::unique_ptr<Capturer> CreateWavFileReader(
-      std::string filename,
-      int sampling_frequency_in_hz);
+      int num_channels = 1);
 
   // Returns a Capturer instance that gets its data from a file.
-  // Automatically detects sample rate.
+  // Automatically detects sample rate and num of channels.
   static std::unique_ptr<Capturer> CreateWavFileReader(std::string filename);
 
   // Returns a Renderer instance that writes its data to a file.
   static std::unique_ptr<Renderer> CreateWavFileWriter(
       std::string filename,
       int sampling_frequency_in_hz,
-      int num_channels);
-
-  // Same as calling CreateWavFileWriter(filename, sampling_frequency_in_hz, 1).
-  static std::unique_ptr<Renderer> CreateWavFileWriter(
-      std::string filename,
-      int sampling_frequency_in_hz);
+      int num_channels = 1);
 
   // Returns a Renderer instance that writes its data to a WAV file, cutting
   // off silence at the beginning (not necessarily perfect silence, see
@@ -126,22 +118,34 @@
   static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
       std::string filename,
       int sampling_frequency_in_hz,
-      int num_channels);
+      int num_channels = 1);
 
-  // Same as calling CreateBounderWavFileWriter(filename,
-  // sampling_frequency_in_hz, 1).
-  static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
-      std::string filename,
-      int sampling_frequency_in_hz);
+  // WavReader and WavWriter creation based on rtc::PlatformFile.
 
-  // Returns a Renderer instance that does nothing with the audio data.
-  static std::unique_ptr<Renderer> CreateDiscardRenderer(
+  // Returns a Capturer instance that gets its data from a file. The sample rate
+  // and channels will be checked against the Wav file.
+  static std::unique_ptr<Capturer> CreateWavFileReader(
+      rtc::PlatformFile file,
       int sampling_frequency_in_hz,
-      int num_channels);
+      int num_channels = 1);
 
-  // Same as calling CreateDiscardRenderer(sampling_frequency_in_hz, 1).
-  static std::unique_ptr<Renderer> CreateDiscardRenderer(
-      int sampling_frequency_in_hz);
+  // Returns a Capturer instance that gets its data from a file.
+  // Automatically detects sample rate and num of channels.
+  static std::unique_ptr<Capturer> CreateWavFileReader(rtc::PlatformFile file);
+
+  // Returns a Renderer instance that writes its data to a file.
+  static std::unique_ptr<Renderer> CreateWavFileWriter(
+      rtc::PlatformFile file,
+      int sampling_frequency_in_hz,
+      int num_channels = 1);
+
+  // Returns a Renderer instance that writes its data to a WAV file, cutting
+  // off silence at the beginning (not necessarily perfect silence, see
+  // kAmplitudeThreshold) and at the end (only actual 0 samples in this case).
+  static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
+      rtc::PlatformFile file,
+      int sampling_frequency_in_hz,
+      int num_channels = 1);
 
   virtual int32_t Init() = 0;
   virtual int32_t RegisterAudioCallback(AudioTransport* callback) = 0;
diff --git a/modules/audio_device/include/test_audio_device_unittest.cc b/modules/audio_device/include/test_audio_device_unittest.cc
index 674df1b..bdb1285 100644
--- a/modules/audio_device/include/test_audio_device_unittest.cc
+++ b/modules/audio_device/include/test_audio_device_unittest.cc
@@ -11,30 +11,78 @@
 #include <algorithm>
 #include <array>
 
+#include "api/array_view.h"
 #include "common_audio/wav_file.h"
 #include "common_audio/wav_header.h"
 #include "modules/audio_device/include/test_audio_device.h"
+#include "rtc_base/logging.h"
+#include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
 
 namespace webrtc {
 
 namespace {
-void RunTest(const std::vector<int16_t>& input_samples,
-             const std::vector<int16_t>& expected_samples,
-             size_t samples_per_frame) {
+
+void RunTestViaRtcPlatformFileAPI(
+    rtc::ArrayView<const int16_t> input_samples,
+    rtc::ArrayView<const int16_t> expected_samples,
+    size_t samples_per_frame) {
   const ::testing::TestInfo* const test_info =
       ::testing::UnitTest::GetInstance()->current_test_info();
 
-  const std::string output_filename = test::OutputPath() +
-                                      "BoundedWavFileWriterTest_" +
-                                      test_info->name() + ".wav";
+  const std::string output_filename =
+      test::OutputPath() + "BoundedWavFileWriterTest_" + test_info->name() +
+      "_" + std::to_string(std::rand()) + ".wav";
 
   static const size_t kSamplesPerFrame = 8;
   static const int kSampleRate = kSamplesPerFrame * 100;
   EXPECT_EQ(TestAudioDeviceModule::SamplesPerFrame(kSampleRate),
             kSamplesPerFrame);
 
+  // Test through rtc::PlatformFile API.
+  {
+    auto file = rtc::CreatePlatformFile(output_filename);
+    std::unique_ptr<TestAudioDeviceModule::Renderer> writer =
+        TestAudioDeviceModule::CreateBoundedWavFileWriter(file, 800);
+
+    for (size_t i = 0; i < input_samples.size(); i += kSamplesPerFrame) {
+      EXPECT_TRUE(writer->Render(rtc::ArrayView<const int16_t>(
+          &input_samples[i],
+          std::min(kSamplesPerFrame, input_samples.size() - i))));
+    }
+  }
+
+  {
+    auto file = rtc::OpenPlatformFile(output_filename);
+    WavReader reader(file);
+    std::vector<int16_t> read_samples(expected_samples.size());
+    EXPECT_EQ(expected_samples.size(),
+              reader.ReadSamples(read_samples.size(), read_samples.data()));
+    EXPECT_THAT(expected_samples, testing::ElementsAreArray(read_samples));
+
+    EXPECT_EQ(0u, reader.ReadSamples(read_samples.size(), read_samples.data()));
+  }
+
+  remove(output_filename.c_str());
+}
+
+void RunTest(const std::vector<int16_t>& input_samples,
+             const std::vector<int16_t>& expected_samples,
+             size_t samples_per_frame) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+  const std::string output_filename =
+      test::OutputPath() + "BoundedWavFileWriterTest_" + test_info->name() +
+      "_" + std::to_string(std::rand()) + ".wav";
+
+  static const size_t kSamplesPerFrame = 8;
+  static const int kSampleRate = kSamplesPerFrame * 100;
+  EXPECT_EQ(TestAudioDeviceModule::SamplesPerFrame(kSampleRate),
+            kSamplesPerFrame);
+
+  // Test through file name API.
   {
     std::unique_ptr<TestAudioDeviceModule::Renderer> writer =
         TestAudioDeviceModule::CreateBoundedWavFileWriter(output_filename, 800);
@@ -76,6 +124,14 @@
   RunTest(kInputSamples, kExpectedSamples, 8);
 }
 
+TEST(BoundedWavFileWriterTest, SomeStartSilenceRtcFile) {
+  static const std::vector<int16_t> kInputSamples = {
+      0, 0, 0, 0, 3, 0, 0, 0, 0, 3, -13222, -7, -3525, 5787, -25247, 8};
+  static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 10,
+                                                     kInputSamples.end());
+  RunTestViaRtcPlatformFileAPI(kInputSamples, kExpectedSamples, 8);
+}
+
 TEST(BoundedWavFileWriterTest, NegativeStartSilence) {
   static const std::vector<int16_t> kInputSamples = {
       0, -4, -6, 0, 3, 0, 0, 0, 0, 3, -13222, -7, -3525, 5787, -25247, 8};