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