1ba35d05a4918b3efa7ab88674781aadb48017ff8henrika/*
2ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *
4ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  Use of this source code is governed by a BSD-style license
5ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  that can be found in the LICENSE file in the root of the source
6ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  tree. An additional intellectual property rights grant can be found
7ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  in the file PATENTS.  All contributing project authors may
8ba35d05a4918b3efa7ab88674781aadb48017ff8henrika *  be found in the AUTHORS file in the root of the source tree.
9ba35d05a4918b3efa7ab88674781aadb48017ff8henrika */
10ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
11ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <algorithm>
12ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <limits>
13ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <list>
14ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <numeric>
15ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <string>
16ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include <vector>
17ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
18ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "testing/gmock/include/gmock/gmock.h"
19ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "testing/gtest/include/gtest/gtest.h"
20ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/base/arraysize.h"
21ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/base/criticalsection.h"
22dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting#include "webrtc/base/format_macros.h"
23ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/base/logging.h"
24ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/base/scoped_ptr.h"
25ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/base/scoped_ref_ptr.h"
26ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/modules/audio_device/audio_device_impl.h"
27ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/modules/audio_device/include/audio_device.h"
28ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/modules/audio_device/ios/audio_device_ios.h"
2998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/clock.h"
3098f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/event_wrapper.h"
3198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/sleep.h"
32ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#include "webrtc/test/testsupport/fileutils.h"
33ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
34ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing std::cout;
35ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing std::endl;
36ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::_;
37ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::AtLeast;
38ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::Gt;
39ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::Invoke;
40ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::NiceMock;
41ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::NotNull;
42ba35d05a4918b3efa7ab88674781aadb48017ff8henrikausing ::testing::Return;
43ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
44ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// #define ENABLE_DEBUG_PRINTF
45ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#ifdef ENABLE_DEBUG_PRINTF
46ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#define PRINTD(...) fprintf(stderr, __VA_ARGS__);
47ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#else
48ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#define PRINTD(...) ((void)0)
49ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#endif
50ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#define PRINT(...) fprintf(stderr, __VA_ARGS__);
51ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
52ba35d05a4918b3efa7ab88674781aadb48017ff8henrikanamespace webrtc {
53ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
54ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Number of callbacks (input or output) the tests waits for before we set
55ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// an event indicating that the test was OK.
56dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumCallbacks = 10;
57ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Max amount of time we wait for an event to be set while counting callbacks.
58ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kTestTimeOutInMilliseconds = 10 * 1000;
59ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Number of bits per PCM audio sample.
60dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kBitsPerSample = 16;
61ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Number of bytes per PCM audio sample.
62dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kBytesPerSample = kBitsPerSample / 8;
63ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Average number of audio callbacks per second assuming 10ms packet size.
64dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumCallbacksPerSecond = 100;
65ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Play out a test file during this time (unit is in seconds).
66ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kFilePlayTimeInSec = 15;
67ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Run the full-duplex test during this time (unit is in seconds).
68ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Note that first |kNumIgnoreFirstCallbacks| are ignored.
69ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kFullDuplexTimeInSec = 10;
70ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Wait for the callback sequence to stabilize by ignoring this amount of the
71ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// initial callbacks (avoids initial FIFO access).
72ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Only used in the RunPlayoutAndRecordingInFullDuplex test.
73dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumIgnoreFirstCallbacks = 50;
74ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Sets the number of impulses per second in the latency test.
75ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// TODO(henrika): fine tune this setting for iOS.
76ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kImpulseFrequencyInHz = 1;
77ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Length of round-trip latency measurements. Number of transmitted impulses
78ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1.
79ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// TODO(henrika): fine tune this setting for iOS.
80ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kMeasureLatencyTimeInSec = 5;
81ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Utilized in round-trip latency measurements to avoid capturing noise samples.
82ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// TODO(henrika): fine tune this setting for iOS.
83ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const int kImpulseThreshold = 50;
84ba35d05a4918b3efa7ab88674781aadb48017ff8henrikastatic const char kTag[] = "[..........] ";
85ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
86ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaenum TransportType {
87ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  kPlayout = 0x1,
88ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  kRecording = 0x2,
89ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
90ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
91ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Interface for processing the audio stream. Real implementations can e.g.
92ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// run audio in loopback, read audio from a file or perform latency
93ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// measurements.
94ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass AudioStreamInterface {
95ba35d05a4918b3efa7ab88674781aadb48017ff8henrika public:
96dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  virtual void Write(const void* source, size_t num_frames) = 0;
97dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  virtual void Read(void* destination, size_t num_frames) = 0;
98ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
99ba35d05a4918b3efa7ab88674781aadb48017ff8henrika protected:
100ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  virtual ~AudioStreamInterface() {}
101ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
102ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
103ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Reads audio samples from a PCM file where the file is stored in memory at
104ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// construction.
105ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass FileAudioStream : public AudioStreamInterface {
106ba35d05a4918b3efa7ab88674781aadb48017ff8henrika public:
107dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  FileAudioStream(size_t num_callbacks,
108ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  const std::string& file_name,
109ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  int sample_rate)
110ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      : file_size_in_bytes_(0), sample_rate_(sample_rate), file_pos_(0) {
111ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    file_size_in_bytes_ = test::GetFileSize(file_name);
112ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    sample_rate_ = sample_rate;
113ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_GE(file_size_in_callbacks(), num_callbacks)
114ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        << "Size of test file is not large enough to last during the test.";
115dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t num_16bit_samples =
116ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        test::GetFileSize(file_name) / kBytesPerSample;
117ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    file_.reset(new int16_t[num_16bit_samples]);
118ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    FILE* audio_file = fopen(file_name.c_str(), "rb");
119ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_NE(audio_file, nullptr);
120dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    size_t num_samples_read =
121ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        fread(file_.get(), sizeof(int16_t), num_16bit_samples, audio_file);
122ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(num_samples_read, num_16bit_samples);
123ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    fclose(audio_file);
124ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
125ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
126ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // AudioStreamInterface::Write() is not implemented.
127dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {}
128ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
129ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Read samples from file stored in memory (at construction) and copy
130ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // |num_frames| (<=> 10ms) to the |destination| byte buffer.
131dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
132ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    memcpy(destination, static_cast<int16_t*>(&file_[file_pos_]),
133ba35d05a4918b3efa7ab88674781aadb48017ff8henrika           num_frames * sizeof(int16_t));
134ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    file_pos_ += num_frames;
135ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
136ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
137ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int file_size_in_seconds() const {
138dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    return static_cast<int>(
139dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        file_size_in_bytes_ / (kBytesPerSample * sample_rate_));
140ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
141dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_size_in_callbacks() const {
142ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return file_size_in_seconds() * kNumCallbacksPerSecond;
143ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
144ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
145ba35d05a4918b3efa7ab88674781aadb48017ff8henrika private:
146dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_size_in_bytes_;
147ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int sample_rate_;
148ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<int16_t[]> file_;
149dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_pos_;
150ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
151ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
152ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Simple first in first out (FIFO) class that wraps a list of 16-bit audio
153ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// buffers of fixed size and allows Write and Read operations. The idea is to
154ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// store recorded audio buffers (using Write) and then read (using Read) these
155ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// stored buffers with as short delay as possible when the audio layer needs
156ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// data to play out. The number of buffers in the FIFO will stabilize under
157ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// normal conditions since there will be a balance between Write and Read calls.
158ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// The container is a std::list container and access is protected with a lock
159ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// since both sides (playout and recording) are driven by its own thread.
160ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass FifoAudioStream : public AudioStreamInterface {
161ba35d05a4918b3efa7ab88674781aadb48017ff8henrika public:
162dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  explicit FifoAudioStream(size_t frames_per_buffer)
163ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      : frames_per_buffer_(frames_per_buffer),
164ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
165ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        fifo_(new AudioBufferList),
166ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        largest_size_(0),
167ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        total_written_elements_(0),
168ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        write_count_(0) {
169ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_NE(fifo_.get(), nullptr);
170ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
171ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
172ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  ~FifoAudioStream() { Flush(); }
173ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
174ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Allocate new memory, copy |num_frames| samples from |source| into memory
175ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // and add pointer to the memory location to end of the list.
176ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Increases the size of the FIFO by one element.
177dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {
178ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    ASSERT_EQ(num_frames, frames_per_buffer_);
179ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINTD("+");
180ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (write_count_++ < kNumIgnoreFirstCallbacks) {
181ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      return;
182ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
183ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    int16_t* memory = new int16_t[frames_per_buffer_];
184ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    memcpy(static_cast<int16_t*>(&memory[0]), source, bytes_per_buffer_);
185ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::CritScope lock(&lock_);
186ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    fifo_->push_back(memory);
187dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t size = fifo_->size();
188ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (size > largest_size_) {
189ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      largest_size_ = size;
190dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      PRINTD("(%" PRIuS ")", largest_size_);
191ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
192ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    total_written_elements_ += size;
193ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
194ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
195ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Read pointer to data buffer from front of list, copy |num_frames| of stored
196ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // data into |destination| and delete the utilized memory allocation.
197ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Decreases the size of the FIFO by one element.
198dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
199ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    ASSERT_EQ(num_frames, frames_per_buffer_);
200ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINTD("-");
201ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::CritScope lock(&lock_);
202ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (fifo_->empty()) {
203ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      memset(destination, 0, bytes_per_buffer_);
204ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    } else {
205ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      int16_t* memory = fifo_->front();
206ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      fifo_->pop_front();
207ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      memcpy(destination, static_cast<int16_t*>(&memory[0]), bytes_per_buffer_);
208ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      delete memory;
209ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
210ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
211ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
212dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t size() const { return fifo_->size(); }
213ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
214dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t largest_size() const { return largest_size_; }
215ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
216dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t average_size() const {
217ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return (total_written_elements_ == 0)
218ba35d05a4918b3efa7ab88674781aadb48017ff8henrika               ? 0.0
219ba35d05a4918b3efa7ab88674781aadb48017ff8henrika               : 0.5 +
220ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                     static_cast<float>(total_written_elements_) /
221ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                         (write_count_ - kNumIgnoreFirstCallbacks);
222ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
223ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
224ba35d05a4918b3efa7ab88674781aadb48017ff8henrika private:
225ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void Flush() {
226ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    for (auto it = fifo_->begin(); it != fifo_->end(); ++it) {
227ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      delete *it;
228ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
229ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    fifo_->clear();
230ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
231ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
232ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  using AudioBufferList = std::list<int16_t*>;
233ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::CriticalSection lock_;
234dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t frames_per_buffer_;
235dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t bytes_per_buffer_;
236ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<AudioBufferList> fifo_;
237dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t largest_size_;
238dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t total_written_elements_;
239dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t write_count_;
240ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
241ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
242ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Inserts periodic impulses and measures the latency between the time of
243ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// transmission and time of receiving the same impulse.
244ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Usage requires a special hardware called Audio Loopback Dongle.
245ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// See http://source.android.com/devices/audio/loopback.html for details.
246ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass LatencyMeasuringAudioStream : public AudioStreamInterface {
247ba35d05a4918b3efa7ab88674781aadb48017ff8henrika public:
248dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  explicit LatencyMeasuringAudioStream(size_t frames_per_buffer)
249ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      : clock_(Clock::GetRealTimeClock()),
250ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        frames_per_buffer_(frames_per_buffer),
251ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
252ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        play_count_(0),
253ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        rec_count_(0),
254ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        pulse_time_(0) {}
255ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
256ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Insert periodic impulses in first two samples of |destination|.
257dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
258ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    ASSERT_EQ(num_frames, frames_per_buffer_);
259ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (play_count_ == 0) {
260ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINT("[");
261ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
262ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    play_count_++;
263ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    memset(destination, 0, bytes_per_buffer_);
264ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) {
265ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      if (pulse_time_ == 0) {
266ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        pulse_time_ = clock_->TimeInMilliseconds();
267ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      }
268ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINT(".");
269ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      const int16_t impulse = std::numeric_limits<int16_t>::max();
270ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      int16_t* ptr16 = static_cast<int16_t*>(destination);
271dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      for (size_t i = 0; i < 2; ++i) {
272dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        ptr16[i] = impulse;
273ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      }
274ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
275ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
276ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
277ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Detect received impulses in |source|, derive time between transmission and
278ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // detection and add the calculated delay to list of latencies.
279dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {
280ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    ASSERT_EQ(num_frames, frames_per_buffer_);
281ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rec_count_++;
282ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (pulse_time_ == 0) {
283ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // Avoid detection of new impulse response until a new impulse has
284ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // been transmitted (sets |pulse_time_| to value larger than zero).
285ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      return;
286ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
287ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    const int16_t* ptr16 = static_cast<const int16_t*>(source);
288ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    std::vector<int16_t> vec(ptr16, ptr16 + num_frames);
289ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Find max value in the audio buffer.
290ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    int max = *std::max_element(vec.begin(), vec.end());
291ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Find index (element position in vector) of the max element.
292ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    int index_of_max =
293ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        std::distance(vec.begin(), std::find(vec.begin(), vec.end(), max));
294ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (max > kImpulseThreshold) {
295ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINTD("(%d,%d)", max, index_of_max);
296ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      int64_t now_time = clock_->TimeInMilliseconds();
297ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      int extra_delay = IndexToMilliseconds(static_cast<double>(index_of_max));
298ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINTD("[%d]", static_cast<int>(now_time - pulse_time_));
299ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINTD("[%d]", extra_delay);
300ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // Total latency is the difference between transmit time and detection
301ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // tome plus the extra delay within the buffer in which we detected the
302ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // received impulse. It is transmitted at sample 0 but can be received
303ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // at sample N where N > 0. The term |extra_delay| accounts for N and it
304ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      // is a value between 0 and 10ms.
305ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      latencies_.push_back(now_time - pulse_time_ + extra_delay);
306ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      pulse_time_ = 0;
307ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    } else {
308ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINTD("-");
309ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
310ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
311ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
312dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num_latency_values() const { return latencies_.size(); }
313ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
314ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int min_latency() const {
315ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (latencies_.empty())
316ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      return 0;
317ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return *std::min_element(latencies_.begin(), latencies_.end());
318ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
319ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
320ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int max_latency() const {
321ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (latencies_.empty())
322ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      return 0;
323ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return *std::max_element(latencies_.begin(), latencies_.end());
324ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
325ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
326ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int average_latency() const {
327ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (latencies_.empty())
328ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      return 0;
329ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return 0.5 +
330ba35d05a4918b3efa7ab88674781aadb48017ff8henrika           static_cast<double>(
331ba35d05a4918b3efa7ab88674781aadb48017ff8henrika               std::accumulate(latencies_.begin(), latencies_.end(), 0)) /
332ba35d05a4918b3efa7ab88674781aadb48017ff8henrika               latencies_.size();
333ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
334ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
335ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void PrintResults() const {
336ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINT("] ");
337ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    for (auto it = latencies_.begin(); it != latencies_.end(); ++it) {
338ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      PRINT("%d ", *it);
339ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
340ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINT("\n");
341ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(),
342ba35d05a4918b3efa7ab88674781aadb48017ff8henrika          max_latency(), average_latency());
343ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
344ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
345ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int IndexToMilliseconds(double index) const {
346ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return 10.0 * (index / frames_per_buffer_) + 0.5;
347ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
348ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
349ba35d05a4918b3efa7ab88674781aadb48017ff8henrika private:
350ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  Clock* clock_;
351dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t frames_per_buffer_;
352dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t bytes_per_buffer_;
353dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t play_count_;
354dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t rec_count_;
355ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int64_t pulse_time_;
356ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  std::vector<int> latencies_;
357ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
358ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Mocks the AudioTransport object and proxies actions for the two callbacks
359ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// (RecordedDataIsAvailable and NeedMorePlayData) to different implementations
360ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// of AudioStreamInterface.
361ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass MockAudioTransport : public AudioTransport {
362ba35d05a4918b3efa7ab88674781aadb48017ff8henrika public:
363ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  explicit MockAudioTransport(int type)
364ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      : num_callbacks_(0),
365ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        type_(type),
366ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        play_count_(0),
367ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        rec_count_(0),
368ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        audio_stream_(nullptr) {}
369ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
370ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  virtual ~MockAudioTransport() {}
371ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
372ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  MOCK_METHOD10(RecordedDataIsAvailable,
373ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                int32_t(const void* audioSamples,
374deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                        const size_t nSamples,
375deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                        const size_t nBytesPerSample,
3766955870806624479723addfae6dcf5d13968796cPeter Kasting                        const size_t nChannels,
377ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        const uint32_t samplesPerSec,
378ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        const uint32_t totalDelayMS,
379ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        const int32_t clockDrift,
380ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        const uint32_t currentMicLevel,
381ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        const bool keyPressed,
382ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                        uint32_t& newMicLevel));
383ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  MOCK_METHOD8(NeedMorePlayData,
384deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting               int32_t(const size_t nSamples,
385deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                       const size_t nBytesPerSample,
3866955870806624479723addfae6dcf5d13968796cPeter Kasting                       const size_t nChannels,
387ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       const uint32_t samplesPerSec,
388ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       void* audioSamples,
389dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                       size_t& nSamplesOut,
390ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       int64_t* elapsed_time_ms,
391ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       int64_t* ntp_time_ms));
392ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
393ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Set default actions of the mock object. We are delegating to fake
394ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // implementations (of AudioStreamInterface) here.
395ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void HandleCallbacks(EventWrapper* test_is_done,
396ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       AudioStreamInterface* audio_stream,
397dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                       size_t num_callbacks) {
398ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    test_is_done_ = test_is_done;
399ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    audio_stream_ = audio_stream;
400ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    num_callbacks_ = num_callbacks;
401ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (play_mode()) {
402ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _))
403ba35d05a4918b3efa7ab88674781aadb48017ff8henrika          .WillByDefault(
404ba35d05a4918b3efa7ab88674781aadb48017ff8henrika              Invoke(this, &MockAudioTransport::RealNeedMorePlayData));
405ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
406ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (rec_mode()) {
407ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _))
408ba35d05a4918b3efa7ab88674781aadb48017ff8henrika          .WillByDefault(
409ba35d05a4918b3efa7ab88674781aadb48017ff8henrika              Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable));
410ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
411ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
412ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
413ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int32_t RealRecordedDataIsAvailable(const void* audioSamples,
414deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                                      const size_t nSamples,
415deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                                      const size_t nBytesPerSample,
4166955870806624479723addfae6dcf5d13968796cPeter Kasting                                      const size_t nChannels,
417ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      const uint32_t samplesPerSec,
418ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      const uint32_t totalDelayMS,
419ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      const int32_t clockDrift,
420ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      const uint32_t currentMicLevel,
421ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      const bool keyPressed,
422ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                      uint32_t& newMicLevel) {
423ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks.";
424ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rec_count_++;
425ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Process the recorded audio stream if an AudioStreamInterface
426ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // implementation exists.
427ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (audio_stream_) {
428ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      audio_stream_->Write(audioSamples, nSamples);
429ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
430ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (ReceivedEnoughCallbacks()) {
43146ea3ce5802f76bdd9177ec495cbc581bf021313henrika      if (test_is_done_) {
43246ea3ce5802f76bdd9177ec495cbc581bf021313henrika        test_is_done_->Set();
43346ea3ce5802f76bdd9177ec495cbc581bf021313henrika      }
434ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
435ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return 0;
436ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
437ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
438deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting  int32_t RealNeedMorePlayData(const size_t nSamples,
439deb4875b74bdafb0b11b8df383b5ee1692d89deaPeter Kasting                               const size_t nBytesPerSample,
4406955870806624479723addfae6dcf5d13968796cPeter Kasting                               const size_t nChannels,
441ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                               const uint32_t samplesPerSec,
442ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                               void* audioSamples,
443dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                               size_t& nSamplesOut,
444ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                               int64_t* elapsed_time_ms,
445ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                               int64_t* ntp_time_ms) {
446ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks.";
447ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    play_count_++;
448ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    nSamplesOut = nSamples;
449ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Read (possibly processed) audio stream samples to be played out if an
450ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // AudioStreamInterface implementation exists.
451ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (audio_stream_) {
452ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      audio_stream_->Read(audioSamples, nSamples);
453ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
454ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (ReceivedEnoughCallbacks()) {
45546ea3ce5802f76bdd9177ec495cbc581bf021313henrika      if (test_is_done_) {
45646ea3ce5802f76bdd9177ec495cbc581bf021313henrika        test_is_done_->Set();
45746ea3ce5802f76bdd9177ec495cbc581bf021313henrika      }
458ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    }
459ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return 0;
460ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
461ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
462ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  bool ReceivedEnoughCallbacks() {
463ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    bool recording_done = false;
464ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (rec_mode())
465ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      recording_done = rec_count_ >= num_callbacks_;
466ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    else
467ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      recording_done = true;
468ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
469ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    bool playout_done = false;
470ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    if (play_mode())
471ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      playout_done = play_count_ >= num_callbacks_;
472ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    else
473ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      playout_done = true;
474ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
475ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return recording_done && playout_done;
476ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
477ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
478ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  bool play_mode() const { return type_ & kPlayout; }
479ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  bool rec_mode() const { return type_ & kRecording; }
480ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
481ba35d05a4918b3efa7ab88674781aadb48017ff8henrika private:
482ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EventWrapper* test_is_done_;
483dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num_callbacks_;
484ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int type_;
485dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t play_count_;
486dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t rec_count_;
487ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioStreamInterface* audio_stream_;
488ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
489ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
490ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// AudioDeviceTest test fixture.
491ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaclass AudioDeviceTest : public ::testing::Test {
492ba35d05a4918b3efa7ab88674781aadb48017ff8henrika protected:
493ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioDeviceTest() : test_is_done_(EventWrapper::Create()) {
494ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    old_sev_ = rtc::LogMessage::GetLogToDebug();
495ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Set suitable logging level here. Change to rtc::LS_INFO for more verbose
496ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // output. See webrtc/base/logging.h for complete list of options.
497ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::LogMessage::LogToDebug(rtc::LS_INFO);
498ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Add extra logging fields here (timestamps and thread id).
499ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // rtc::LogMessage::LogTimestamps();
500ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::LogMessage::LogThreads();
501ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    // Creates an audio device using a default audio layer.
502ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    audio_device_ = CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
503ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_NE(audio_device_.get(), nullptr);
504ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device_->Init());
505ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0,
506ba35d05a4918b3efa7ab88674781aadb48017ff8henrika              audio_device()->GetPlayoutAudioParameters(&playout_parameters_));
507ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->GetRecordAudioParameters(&record_parameters_));
508ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
509ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  virtual ~AudioDeviceTest() {
510ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device_->Terminate());
511ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::LogMessage::LogToDebug(old_sev_);
512ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
513ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
514ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int playout_sample_rate() const { return playout_parameters_.sample_rate(); }
515ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int record_sample_rate() const { return record_parameters_.sample_rate(); }
516ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int playout_channels() const { return playout_parameters_.channels(); }
517ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  int record_channels() const { return record_parameters_.channels(); }
518dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t playout_frames_per_10ms_buffer() const {
519ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return playout_parameters_.frames_per_10ms_buffer();
520ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
521dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t record_frames_per_10ms_buffer() const {
522ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return record_parameters_.frames_per_10ms_buffer();
523ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
524ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
525ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_refptr<AudioDeviceModule> audio_device() const {
526ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return audio_device_;
527ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
528ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
529ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioDeviceModuleImpl* audio_device_impl() const {
530ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return static_cast<AudioDeviceModuleImpl*>(audio_device_.get());
531ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
532ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
533ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioDeviceBuffer* audio_device_buffer() const {
534ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return audio_device_impl()->GetAudioDeviceBuffer();
535ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
536ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
537ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_refptr<AudioDeviceModule> CreateAudioDevice(
538ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      AudioDeviceModule::AudioLayer audio_layer) {
539ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    rtc::scoped_refptr<AudioDeviceModule> module(
540ba35d05a4918b3efa7ab88674781aadb48017ff8henrika        AudioDeviceModuleImpl::Create(0, audio_layer));
541ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return module;
542ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
543ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
544ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Returns file name relative to the resource root given a sample rate.
545ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  std::string GetFileName(int sample_rate) {
546ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100 ||
547ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                sample_rate == 16000);
548ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    char fname[64];
549ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    snprintf(fname, sizeof(fname), "audio_device/audio_short%d",
550ba35d05a4918b3efa7ab88674781aadb48017ff8henrika             sample_rate / 1000);
551ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    std::string file_name(webrtc::test::ResourcePath(fname, "pcm"));
552ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(test::FileExists(file_name));
553ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#ifdef ENABLE_DEBUG_PRINTF
554ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINTD("file name: %s\n", file_name.c_str());
555dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t bytes = test::GetFileSize(file_name);
556dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINTD("file size: %" PRIuS " [bytes]\n", bytes);
557dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINTD("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample);
558dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const int seconds =
559dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        static_cast<int>(bytes / (sample_rate * kBytesPerSample));
560ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    PRINTD("file size: %d [secs]\n", seconds);
561dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINTD("file size: %" PRIuS " [callbacks]\n",
562dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting           seconds * kNumCallbacksPerSecond);
563ba35d05a4918b3efa7ab88674781aadb48017ff8henrika#endif
564ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    return file_name;
565ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
566ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
567ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void StartPlayout() {
568ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
569ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->Playing());
570ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->InitPlayout());
571ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
572ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->StartPlayout());
573ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(audio_device()->Playing());
574ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
575ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
576ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void StopPlayout() {
577ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->StopPlayout());
578ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->Playing());
579ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
580ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
581ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
582ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void StartRecording() {
583ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->RecordingIsInitialized());
584ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->Recording());
585ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->InitRecording());
586ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(audio_device()->RecordingIsInitialized());
587ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->StartRecording());
588ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_TRUE(audio_device()->Recording());
589ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
590ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
591ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  void StopRecording() {
592ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_EQ(0, audio_device()->StopRecording());
593ba35d05a4918b3efa7ab88674781aadb48017ff8henrika    EXPECT_FALSE(audio_device()->Recording());
594ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  }
595ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
596ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<EventWrapper> test_is_done_;
597ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_refptr<AudioDeviceModule> audio_device_;
598ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioParameters playout_parameters_;
599ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  AudioParameters record_parameters_;
600ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::LoggingSeverity old_sev_;
601ba35d05a4918b3efa7ab88674781aadb48017ff8henrika};
602ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
603ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, ConstructDestruct) {
604ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Using the test fixture to create and destruct the audio device module.
605ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
606ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
607ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, InitTerminate) {
608ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Initialization is part of the test fixture.
609ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_TRUE(audio_device()->Initialized());
610ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->Terminate());
611ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_FALSE(audio_device()->Initialized());
612ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
613ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
614ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Tests that playout can be initiated, started and stopped. No audio callback
615ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// is registered in this test.
616ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StartStopPlayout) {
617ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
618ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
619ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
620ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
621ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
622ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
623ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Tests that recording can be initiated, started and stopped. No audio callback
624ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// is registered in this test.
625ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StartStopRecording) {
626ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
627ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
628ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
629ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
630ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
631ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
632ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Verify that calling StopPlayout() will leave us in an uninitialized state
633ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// which will require a new call to InitPlayout(). This test does not call
63491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg// StartPlayout() while being uninitialized since doing so will hit a
63591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg// RTC_DCHECK.
636ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StopPlayoutRequiresInitToRestart) {
637ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->InitPlayout());
638ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->StartPlayout());
639ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->StopPlayout());
640ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
641ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
642ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
643c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika// Verify that we can create two ADMs and start playing on the second ADM.
644c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika// Only the first active instance shall activate an audio session and the
64546ea3ce5802f76bdd9177ec495cbc581bf021313henrika// last active instance shall deactivate the audio session. The test does not
64646ea3ce5802f76bdd9177ec495cbc581bf021313henrika// explicitly verify correct audio session calls but instead focuses on
64746ea3ce5802f76bdd9177ec495cbc581bf021313henrika// ensuring that audio starts for both ADMs.
648c729032b1b31e9064a37d3f862bcf60e3651bdffhenrikaTEST_F(AudioDeviceTest, StartPlayoutOnTwoInstances) {
649c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // Create and initialize a second/extra ADM instance. The default ADM is
650c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // created by the test harness.
651c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  rtc::scoped_refptr<AudioDeviceModule> second_audio_device =
652c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika      CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
653c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_NE(second_audio_device.get(), nullptr);
654c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->Init());
655c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika
65646ea3ce5802f76bdd9177ec495cbc581bf021313henrika  // Start playout for the default ADM but don't wait here. Instead use the
65746ea3ce5802f76bdd9177ec495cbc581bf021313henrika  // upcoming second stream for that. We set the same expectation on number
65846ea3ce5802f76bdd9177ec495cbc581bf021313henrika  // of callbacks as for the second stream.
659c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  NiceMock<MockAudioTransport> mock(kPlayout);
66046ea3ce5802f76bdd9177ec495cbc581bf021313henrika  mock.HandleCallbacks(nullptr, nullptr, 0);
66146ea3ce5802f76bdd9177ec495cbc581bf021313henrika  EXPECT_CALL(
66246ea3ce5802f76bdd9177ec495cbc581bf021313henrika      mock, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
66346ea3ce5802f76bdd9177ec495cbc581bf021313henrika                             playout_channels(), playout_sample_rate(),
66446ea3ce5802f76bdd9177ec495cbc581bf021313henrika                             NotNull(), _, _, _))
66546ea3ce5802f76bdd9177ec495cbc581bf021313henrika      .Times(AtLeast(kNumCallbacks));
666c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
667c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  StartPlayout();
668c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika
669c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // Initialize playout for the second ADM. If all is OK, the second ADM shall
670c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // reuse the audio session activated when the first ADM started playing.
671c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // This call will also ensure that we avoid a problem related to initializing
672c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // two different audio unit instances back to back (see webrtc:5166 for
673c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // details).
674c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->InitPlayout());
675c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_TRUE(second_audio_device->PlayoutIsInitialized());
676c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika
677c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // Start playout for the second ADM and verify that it starts as intended.
678c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  // Passing this test ensures that initialization of the second audio unit
67946ea3ce5802f76bdd9177ec495cbc581bf021313henrika  // has been done successfully and that there is no conflict with the already
68046ea3ce5802f76bdd9177ec495cbc581bf021313henrika  // playing first ADM.
681c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  MockAudioTransport mock2(kPlayout);
682c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  mock2.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
683c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_CALL(
684c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika      mock2, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
685c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika                              playout_channels(), playout_sample_rate(),
686c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika                              NotNull(), _, _, _))
687c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika      .Times(AtLeast(kNumCallbacks));
688c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->RegisterAudioCallback(&mock2));
689c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->StartPlayout());
690c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_TRUE(second_audio_device->Playing());
691c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  test_is_done_->Wait(kTestTimeOutInMilliseconds);
692c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->StopPlayout());
693c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_FALSE(second_audio_device->Playing());
694c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_FALSE(second_audio_device->PlayoutIsInitialized());
695c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika
696c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika  EXPECT_EQ(0, second_audio_device->Terminate());
697c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika}
698c729032b1b31e9064a37d3f862bcf60e3651bdffhenrika
699ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Start playout and verify that the native audio layer starts asking for real
700ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// audio samples to play out using the NeedMorePlayData callback.
701ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StartPlayoutVerifyCallbacks) {
702ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  MockAudioTransport mock(kPlayout);
703ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
704ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
705ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                     kBytesPerSample, playout_channels(),
706ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                     playout_sample_rate(), NotNull(), _, _, _))
707ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      .Times(AtLeast(kNumCallbacks));
708ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
709ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
710ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(kTestTimeOutInMilliseconds);
711ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
712ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
713ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
714ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Start recording and verify that the native audio layer starts feeding real
715ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// audio samples via the RecordedDataIsAvailable callback.
716ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StartRecordingVerifyCallbacks) {
717ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  MockAudioTransport mock(kRecording);
718ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
719ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_CALL(mock,
720ba35d05a4918b3efa7ab88674781aadb48017ff8henrika              RecordedDataIsAvailable(
721ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
722ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  record_channels(), record_sample_rate(),
723ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  _,  // TODO(henrika): fix delay
724ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  0, 0, false, _)).Times(AtLeast(kNumCallbacks));
725ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
726ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
727ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
728ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(kTestTimeOutInMilliseconds);
729ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
730ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
731ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
732ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Start playout and recording (full-duplex audio) and verify that audio is
733ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// active in both directions.
734ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, StartPlayoutAndRecordingVerifyCallbacks) {
735ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  MockAudioTransport mock(kPlayout | kRecording);
736ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
737ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
738ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                     kBytesPerSample, playout_channels(),
739ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                                     playout_sample_rate(), NotNull(), _, _, _))
740ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      .Times(AtLeast(kNumCallbacks));
741ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_CALL(mock,
742ba35d05a4918b3efa7ab88674781aadb48017ff8henrika              RecordedDataIsAvailable(
743ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
744ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  record_channels(), record_sample_rate(),
745ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  _,  // TODO(henrika): fix delay
746ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                  0, 0, false, _)).Times(AtLeast(kNumCallbacks));
747ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
748ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
749ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
750ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(kTestTimeOutInMilliseconds);
751ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
752ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
753ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
754ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
755ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Start playout and read audio from an external PCM file when the audio layer
756ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// asks for data to play out. Real audio is played out in this test but it does
757ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// not contain any explicit verification that the audio quality is perfect.
758ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) {
759ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // TODO(henrika): extend test when mono output is supported.
760ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(1, playout_channels());
761ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  NiceMock<MockAudioTransport> mock(kPlayout);
762ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond;
763ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  std::string file_name = GetFileName(playout_sample_rate());
764ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<FileAudioStream> file_audio_stream(
765ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      new FileAudioStream(num_callbacks, file_name, playout_sample_rate()));
766ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), file_audio_stream.get(),
767ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       num_callbacks);
768ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // SetMaxPlayoutVolume();
769ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
770ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
771ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(kTestTimeOutInMilliseconds);
772ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
773ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
774ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
775ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, Devices) {
776ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Device enumeration is not supported. Verify fixed values only.
777ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(1, audio_device()->PlayoutDevices());
778ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(1, audio_device()->RecordingDevices());
779ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
780ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
781ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Start playout and recording and store recorded data in an intermediate FIFO
782ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// buffer from which the playout side then reads its samples in the same order
783ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// as they were stored. Under ideal circumstances, a callback sequence would
784ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-'
785ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// means 'packet played'. Under such conditions, the FIFO would only contain
786ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// one packet on average. However, under more realistic conditions, the size
787ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// of the FIFO will vary more due to an unbalance between the two sides.
788ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// This test tries to verify that the device maintains a balanced callback-
789ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// sequence by running in loopback for ten seconds while measuring the size
790ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// (max and average) of the FIFO. The size of the FIFO is increased by the
791ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// recording side and decreased by the playout side.
792ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// TODO(henrika): tune the final test parameters after running tests on several
793ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// different devices.
794ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) {
795ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(record_channels(), playout_channels());
796ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(record_sample_rate(), playout_sample_rate());
797ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
798ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<FifoAudioStream> fifo_audio_stream(
799ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      new FifoAudioStream(playout_frames_per_10ms_buffer()));
800ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), fifo_audio_stream.get(),
801ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       kFullDuplexTimeInSec * kNumCallbacksPerSecond);
802ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // SetMaxPlayoutVolume();
803ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
804ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
805ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
806ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(
807ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      std::max(kTestTimeOutInMilliseconds, 1000 * kFullDuplexTimeInSec));
808ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
809ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
81041eeff49fa0c44afefa581189805a9bda0db2182Peter Kasting  EXPECT_LE(fifo_audio_stream->average_size(), 10u);
81141eeff49fa0c44afefa581189805a9bda0db2182Peter Kasting  EXPECT_LE(fifo_audio_stream->largest_size(), 20u);
812ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
813ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
814ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// Measures loopback latency and reports the min, max and average values for
815ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// a full duplex audio session.
816ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// The latency is measured like so:
817ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// - Insert impulses periodically on the output side.
818ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// - Detect the impulses on the input side.
819ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// - Measure the time difference between the transmit time and receive time.
820ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// - Store time differences in a vector and calculate min, max and average.
821ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// This test requires a special hardware called Audio Loopback Dongle.
822ba35d05a4918b3efa7ab88674781aadb48017ff8henrika// See http://source.android.com/devices/audio/loopback.html for details.
823ba35d05a4918b3efa7ab88674781aadb48017ff8henrikaTEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) {
824ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(record_channels(), playout_channels());
825ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(record_sample_rate(), playout_sample_rate());
826ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
827ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream(
828ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer()));
829ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  mock.HandleCallbacks(test_is_done_.get(), latency_audio_stream.get(),
830ba35d05a4918b3efa7ab88674781aadb48017ff8henrika                       kMeasureLatencyTimeInSec * kNumCallbacksPerSecond);
831ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
832ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // SetMaxPlayoutVolume();
833ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // DisableBuiltInAECIfAvailable();
834ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartRecording();
835ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StartPlayout();
836ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  test_is_done_->Wait(
837ba35d05a4918b3efa7ab88674781aadb48017ff8henrika      std::max(kTestTimeOutInMilliseconds, 1000 * kMeasureLatencyTimeInSec));
838ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopPlayout();
839ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  StopRecording();
840ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  // Verify that the correct number of transmitted impulses are detected.
841ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  EXPECT_EQ(latency_audio_stream->num_latency_values(),
84241eeff49fa0c44afefa581189805a9bda0db2182Peter Kasting            static_cast<size_t>(
84341eeff49fa0c44afefa581189805a9bda0db2182Peter Kasting                kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1));
844ba35d05a4918b3efa7ab88674781aadb48017ff8henrika  latency_audio_stream->PrintResults();
845ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}
846ba35d05a4918b3efa7ab88674781aadb48017ff8henrika
847ba35d05a4918b3efa7ab88674781aadb48017ff8henrika}  // namespace webrtc
848