| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <limits> | 12 #include <limits> |
| 13 #include <list> | 13 #include <list> |
| 14 #include <numeric> | 14 #include <numeric> |
| 15 #include <string> | 15 #include <string> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 #include "webrtc/base/arraysize.h" | 20 #include "webrtc/base/arraysize.h" |
| 21 #include "webrtc/base/criticalsection.h" | 21 #include "webrtc/base/criticalsection.h" |
| 22 #include "webrtc/base/format_macros.h" |
| 22 #include "webrtc/base/scoped_ptr.h" | 23 #include "webrtc/base/scoped_ptr.h" |
| 23 #include "webrtc/base/scoped_ref_ptr.h" | 24 #include "webrtc/base/scoped_ref_ptr.h" |
| 24 #include "webrtc/modules/audio_device/android/audio_common.h" | 25 #include "webrtc/modules/audio_device/android/audio_common.h" |
| 25 #include "webrtc/modules/audio_device/android/audio_manager.h" | 26 #include "webrtc/modules/audio_device/android/audio_manager.h" |
| 26 #include "webrtc/modules/audio_device/android/build_info.h" | 27 #include "webrtc/modules/audio_device/android/build_info.h" |
| 27 #include "webrtc/modules/audio_device/android/ensure_initialized.h" | 28 #include "webrtc/modules/audio_device/android/ensure_initialized.h" |
| 28 #include "webrtc/modules/audio_device/audio_device_impl.h" | 29 #include "webrtc/modules/audio_device/audio_device_impl.h" |
| 29 #include "webrtc/modules/audio_device/include/audio_device.h" | 30 #include "webrtc/modules/audio_device/include/audio_device.h" |
| 30 #include "webrtc/system_wrappers/interface/clock.h" | 31 #include "webrtc/system_wrappers/interface/clock.h" |
| 31 #include "webrtc/system_wrappers/interface/event_wrapper.h" | 32 #include "webrtc/system_wrappers/interface/event_wrapper.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 56 // Number of callbacks (input or output) the tests waits for before we set | 57 // Number of callbacks (input or output) the tests waits for before we set |
| 57 // an event indicating that the test was OK. | 58 // an event indicating that the test was OK. |
| 58 static const int kNumCallbacks = 10; | 59 static const int kNumCallbacks = 10; |
| 59 // Max amount of time we wait for an event to be set while counting callbacks. | 60 // Max amount of time we wait for an event to be set while counting callbacks. |
| 60 static const int kTestTimeOutInMilliseconds = 10 * 1000; | 61 static const int kTestTimeOutInMilliseconds = 10 * 1000; |
| 61 // Average number of audio callbacks per second assuming 10ms packet size. | 62 // Average number of audio callbacks per second assuming 10ms packet size. |
| 62 static const int kNumCallbacksPerSecond = 100; | 63 static const int kNumCallbacksPerSecond = 100; |
| 63 // Play out a test file during this time (unit is in seconds). | 64 // Play out a test file during this time (unit is in seconds). |
| 64 static const int kFilePlayTimeInSec = 5; | 65 static const int kFilePlayTimeInSec = 5; |
| 65 static const int kBitsPerSample = 16; | 66 static const int kBitsPerSample = 16; |
| 66 static const int kBytesPerSample = kBitsPerSample / 8; | 67 static const size_t kBytesPerSample = kBitsPerSample / 8; |
| 67 // Run the full-duplex test during this time (unit is in seconds). | 68 // Run the full-duplex test during this time (unit is in seconds). |
| 68 // Note that first |kNumIgnoreFirstCallbacks| are ignored. | 69 // Note that first |kNumIgnoreFirstCallbacks| are ignored. |
| 69 static const int kFullDuplexTimeInSec = 5; | 70 static const int kFullDuplexTimeInSec = 5; |
| 70 // Wait for the callback sequence to stabilize by ignoring this amount of the | 71 // Wait for the callback sequence to stabilize by ignoring this amount of the |
| 71 // initial callbacks (avoids initial FIFO access). | 72 // initial callbacks (avoids initial FIFO access). |
| 72 // Only used in the RunPlayoutAndRecordingInFullDuplex test. | 73 // Only used in the RunPlayoutAndRecordingInFullDuplex test. |
| 73 static const int kNumIgnoreFirstCallbacks = 50; | 74 static const int kNumIgnoreFirstCallbacks = 50; |
| 74 // Sets the number of impulses per second in the latency test. | 75 // Sets the number of impulses per second in the latency test. |
| 75 static const int kImpulseFrequencyInHz = 1; | 76 static const int kImpulseFrequencyInHz = 1; |
| 76 // Length of round-trip latency measurements. Number of transmitted impulses | 77 // Length of round-trip latency measurements. Number of transmitted impulses |
| 77 // is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1. | 78 // is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1. |
| 78 static const int kMeasureLatencyTimeInSec = 11; | 79 static const int kMeasureLatencyTimeInSec = 11; |
| 79 // Utilized in round-trip latency measurements to avoid capturing noise samples. | 80 // Utilized in round-trip latency measurements to avoid capturing noise samples. |
| 80 static const int kImpulseThreshold = 1000; | 81 static const int kImpulseThreshold = 1000; |
| 81 static const char kTag[] = "[..........] "; | 82 static const char kTag[] = "[..........] "; |
| 82 | 83 |
| 83 enum TransportType { | 84 enum TransportType { |
| 84 kPlayout = 0x1, | 85 kPlayout = 0x1, |
| 85 kRecording = 0x2, | 86 kRecording = 0x2, |
| 86 }; | 87 }; |
| 87 | 88 |
| 88 // Interface for processing the audio stream. Real implementations can e.g. | 89 // Interface for processing the audio stream. Real implementations can e.g. |
| 89 // run audio in loopback, read audio from a file or perform latency | 90 // run audio in loopback, read audio from a file or perform latency |
| 90 // measurements. | 91 // measurements. |
| 91 class AudioStreamInterface { | 92 class AudioStreamInterface { |
| 92 public: | 93 public: |
| 93 virtual void Write(const void* source, int num_frames) = 0; | 94 virtual void Write(const void* source, size_t num_frames) = 0; |
| 94 virtual void Read(void* destination, int num_frames) = 0; | 95 virtual void Read(void* destination, size_t num_frames) = 0; |
| 95 protected: | 96 protected: |
| 96 virtual ~AudioStreamInterface() {} | 97 virtual ~AudioStreamInterface() {} |
| 97 }; | 98 }; |
| 98 | 99 |
| 99 // Reads audio samples from a PCM file where the file is stored in memory at | 100 // Reads audio samples from a PCM file where the file is stored in memory at |
| 100 // construction. | 101 // construction. |
| 101 class FileAudioStream : public AudioStreamInterface { | 102 class FileAudioStream : public AudioStreamInterface { |
| 102 public: | 103 public: |
| 103 FileAudioStream( | 104 FileAudioStream( |
| 104 int num_callbacks, const std::string& file_name, int sample_rate) | 105 int num_callbacks, const std::string& file_name, int sample_rate) |
| 105 : file_size_in_bytes_(0), | 106 : file_size_in_bytes_(0), |
| 106 sample_rate_(sample_rate), | 107 sample_rate_(sample_rate), |
| 107 file_pos_(0) { | 108 file_pos_(0) { |
| 108 file_size_in_bytes_ = test::GetFileSize(file_name); | 109 file_size_in_bytes_ = test::GetFileSize(file_name); |
| 109 sample_rate_ = sample_rate; | 110 sample_rate_ = sample_rate; |
| 110 EXPECT_GE(file_size_in_callbacks(), num_callbacks) | 111 EXPECT_GE(file_size_in_callbacks(), num_callbacks) |
| 111 << "Size of test file is not large enough to last during the test."; | 112 << "Size of test file is not large enough to last during the test."; |
| 112 const int num_16bit_samples = | 113 const size_t num_16bit_samples = |
| 113 test::GetFileSize(file_name) / kBytesPerSample; | 114 test::GetFileSize(file_name) / kBytesPerSample; |
| 114 file_.reset(new int16_t[num_16bit_samples]); | 115 file_.reset(new int16_t[num_16bit_samples]); |
| 115 FILE* audio_file = fopen(file_name.c_str(), "rb"); | 116 FILE* audio_file = fopen(file_name.c_str(), "rb"); |
| 116 EXPECT_NE(audio_file, nullptr); | 117 EXPECT_NE(audio_file, nullptr); |
| 117 int num_samples_read = fread( | 118 size_t num_samples_read = fread( |
| 118 file_.get(), sizeof(int16_t), num_16bit_samples, audio_file); | 119 file_.get(), sizeof(int16_t), num_16bit_samples, audio_file); |
| 119 EXPECT_EQ(num_samples_read, num_16bit_samples); | 120 EXPECT_EQ(num_samples_read, num_16bit_samples); |
| 120 fclose(audio_file); | 121 fclose(audio_file); |
| 121 } | 122 } |
| 122 | 123 |
| 123 // AudioStreamInterface::Write() is not implemented. | 124 // AudioStreamInterface::Write() is not implemented. |
| 124 void Write(const void* source, int num_frames) override {} | 125 void Write(const void* source, size_t num_frames) override {} |
| 125 | 126 |
| 126 // Read samples from file stored in memory (at construction) and copy | 127 // Read samples from file stored in memory (at construction) and copy |
| 127 // |num_frames| (<=> 10ms) to the |destination| byte buffer. | 128 // |num_frames| (<=> 10ms) to the |destination| byte buffer. |
| 128 void Read(void* destination, int num_frames) override { | 129 void Read(void* destination, size_t num_frames) override { |
| 129 memcpy(destination, | 130 memcpy(destination, |
| 130 static_cast<int16_t*> (&file_[file_pos_]), | 131 static_cast<int16_t*> (&file_[file_pos_]), |
| 131 num_frames * sizeof(int16_t)); | 132 num_frames * sizeof(int16_t)); |
| 132 file_pos_ += num_frames; | 133 file_pos_ += num_frames; |
| 133 } | 134 } |
| 134 | 135 |
| 135 int file_size_in_seconds() const { | 136 int file_size_in_seconds() const { |
| 136 return (file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); | 137 return static_cast<int>( |
| 138 file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); |
| 137 } | 139 } |
| 138 int file_size_in_callbacks() const { | 140 int file_size_in_callbacks() const { |
| 139 return file_size_in_seconds() * kNumCallbacksPerSecond; | 141 return file_size_in_seconds() * kNumCallbacksPerSecond; |
| 140 } | 142 } |
| 141 | 143 |
| 142 private: | 144 private: |
| 143 int file_size_in_bytes_; | 145 size_t file_size_in_bytes_; |
| 144 int sample_rate_; | 146 int sample_rate_; |
| 145 rtc::scoped_ptr<int16_t[]> file_; | 147 rtc::scoped_ptr<int16_t[]> file_; |
| 146 int file_pos_; | 148 size_t file_pos_; |
| 147 }; | 149 }; |
| 148 | 150 |
| 149 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio | 151 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio |
| 150 // buffers of fixed size and allows Write and Read operations. The idea is to | 152 // buffers of fixed size and allows Write and Read operations. The idea is to |
| 151 // store recorded audio buffers (using Write) and then read (using Read) these | 153 // store recorded audio buffers (using Write) and then read (using Read) these |
| 152 // stored buffers with as short delay as possible when the audio layer needs | 154 // stored buffers with as short delay as possible when the audio layer needs |
| 153 // data to play out. The number of buffers in the FIFO will stabilize under | 155 // data to play out. The number of buffers in the FIFO will stabilize under |
| 154 // normal conditions since there will be a balance between Write and Read calls. | 156 // normal conditions since there will be a balance between Write and Read calls. |
| 155 // The container is a std::list container and access is protected with a lock | 157 // The container is a std::list container and access is protected with a lock |
| 156 // since both sides (playout and recording) are driven by its own thread. | 158 // since both sides (playout and recording) are driven by its own thread. |
| 157 class FifoAudioStream : public AudioStreamInterface { | 159 class FifoAudioStream : public AudioStreamInterface { |
| 158 public: | 160 public: |
| 159 explicit FifoAudioStream(int frames_per_buffer) | 161 explicit FifoAudioStream(size_t frames_per_buffer) |
| 160 : frames_per_buffer_(frames_per_buffer), | 162 : frames_per_buffer_(frames_per_buffer), |
| 161 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 163 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), |
| 162 fifo_(new AudioBufferList), | 164 fifo_(new AudioBufferList), |
| 163 largest_size_(0), | 165 largest_size_(0), |
| 164 total_written_elements_(0), | 166 total_written_elements_(0), |
| 165 write_count_(0) { | 167 write_count_(0) { |
| 166 EXPECT_NE(fifo_.get(), nullptr); | 168 EXPECT_NE(fifo_.get(), nullptr); |
| 167 } | 169 } |
| 168 | 170 |
| 169 ~FifoAudioStream() { | 171 ~FifoAudioStream() { |
| 170 Flush(); | 172 Flush(); |
| 171 } | 173 } |
| 172 | 174 |
| 173 // Allocate new memory, copy |num_frames| samples from |source| into memory | 175 // Allocate new memory, copy |num_frames| samples from |source| into memory |
| 174 // and add pointer to the memory location to end of the list. | 176 // and add pointer to the memory location to end of the list. |
| 175 // Increases the size of the FIFO by one element. | 177 // Increases the size of the FIFO by one element. |
| 176 void Write(const void* source, int num_frames) override { | 178 void Write(const void* source, size_t num_frames) override { |
| 177 ASSERT_EQ(num_frames, frames_per_buffer_); | 179 ASSERT_EQ(num_frames, frames_per_buffer_); |
| 178 PRINTD("+"); | 180 PRINTD("+"); |
| 179 if (write_count_++ < kNumIgnoreFirstCallbacks) { | 181 if (write_count_++ < kNumIgnoreFirstCallbacks) { |
| 180 return; | 182 return; |
| 181 } | 183 } |
| 182 int16_t* memory = new int16_t[frames_per_buffer_]; | 184 int16_t* memory = new int16_t[frames_per_buffer_]; |
| 183 memcpy(static_cast<int16_t*> (&memory[0]), | 185 memcpy(static_cast<int16_t*> (&memory[0]), |
| 184 source, | 186 source, |
| 185 bytes_per_buffer_); | 187 bytes_per_buffer_); |
| 186 rtc::CritScope lock(&lock_); | 188 rtc::CritScope lock(&lock_); |
| 187 fifo_->push_back(memory); | 189 fifo_->push_back(memory); |
| 188 const int size = fifo_->size(); | 190 const int size = fifo_->size(); |
| 189 if (size > largest_size_) { | 191 if (size > largest_size_) { |
| 190 largest_size_ = size; | 192 largest_size_ = size; |
| 191 PRINTD("(%d)", largest_size_); | 193 PRINTD("(%d)", largest_size_); |
| 192 } | 194 } |
| 193 total_written_elements_ += size; | 195 total_written_elements_ += size; |
| 194 } | 196 } |
| 195 | 197 |
| 196 // Read pointer to data buffer from front of list, copy |num_frames| of stored | 198 // Read pointer to data buffer from front of list, copy |num_frames| of stored |
| 197 // data into |destination| and delete the utilized memory allocation. | 199 // data into |destination| and delete the utilized memory allocation. |
| 198 // Decreases the size of the FIFO by one element. | 200 // Decreases the size of the FIFO by one element. |
| 199 void Read(void* destination, int num_frames) override { | 201 void Read(void* destination, size_t num_frames) override { |
| 200 ASSERT_EQ(num_frames, frames_per_buffer_); | 202 ASSERT_EQ(num_frames, frames_per_buffer_); |
| 201 PRINTD("-"); | 203 PRINTD("-"); |
| 202 rtc::CritScope lock(&lock_); | 204 rtc::CritScope lock(&lock_); |
| 203 if (fifo_->empty()) { | 205 if (fifo_->empty()) { |
| 204 memset(destination, 0, bytes_per_buffer_); | 206 memset(destination, 0, bytes_per_buffer_); |
| 205 } else { | 207 } else { |
| 206 int16_t* memory = fifo_->front(); | 208 int16_t* memory = fifo_->front(); |
| 207 fifo_->pop_front(); | 209 fifo_->pop_front(); |
| 208 memcpy(destination, | 210 memcpy(destination, |
| 209 static_cast<int16_t*> (&memory[0]), | 211 static_cast<int16_t*> (&memory[0]), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 228 private: | 230 private: |
| 229 void Flush() { | 231 void Flush() { |
| 230 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { | 232 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { |
| 231 delete *it; | 233 delete *it; |
| 232 } | 234 } |
| 233 fifo_->clear(); | 235 fifo_->clear(); |
| 234 } | 236 } |
| 235 | 237 |
| 236 using AudioBufferList = std::list<int16_t*>; | 238 using AudioBufferList = std::list<int16_t*>; |
| 237 rtc::CriticalSection lock_; | 239 rtc::CriticalSection lock_; |
| 238 const int frames_per_buffer_; | 240 const size_t frames_per_buffer_; |
| 239 const int bytes_per_buffer_; | 241 const size_t bytes_per_buffer_; |
| 240 rtc::scoped_ptr<AudioBufferList> fifo_; | 242 rtc::scoped_ptr<AudioBufferList> fifo_; |
| 241 int largest_size_; | 243 int largest_size_; |
| 242 int total_written_elements_; | 244 int total_written_elements_; |
| 243 int write_count_; | 245 int write_count_; |
| 244 }; | 246 }; |
| 245 | 247 |
| 246 // Inserts periodic impulses and measures the latency between the time of | 248 // Inserts periodic impulses and measures the latency between the time of |
| 247 // transmission and time of receiving the same impulse. | 249 // transmission and time of receiving the same impulse. |
| 248 // Usage requires a special hardware called Audio Loopback Dongle. | 250 // Usage requires a special hardware called Audio Loopback Dongle. |
| 249 // See http://source.android.com/devices/audio/loopback.html for details. | 251 // See http://source.android.com/devices/audio/loopback.html for details. |
| 250 class LatencyMeasuringAudioStream : public AudioStreamInterface { | 252 class LatencyMeasuringAudioStream : public AudioStreamInterface { |
| 251 public: | 253 public: |
| 252 explicit LatencyMeasuringAudioStream(int frames_per_buffer) | 254 explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) |
| 253 : clock_(Clock::GetRealTimeClock()), | 255 : clock_(Clock::GetRealTimeClock()), |
| 254 frames_per_buffer_(frames_per_buffer), | 256 frames_per_buffer_(frames_per_buffer), |
| 255 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 257 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), |
| 256 play_count_(0), | 258 play_count_(0), |
| 257 rec_count_(0), | 259 rec_count_(0), |
| 258 pulse_time_(0) { | 260 pulse_time_(0) { |
| 259 } | 261 } |
| 260 | 262 |
| 261 // Insert periodic impulses in first two samples of |destination|. | 263 // Insert periodic impulses in first two samples of |destination|. |
| 262 void Read(void* destination, int num_frames) override { | 264 void Read(void* destination, size_t num_frames) override { |
| 263 ASSERT_EQ(num_frames, frames_per_buffer_); | 265 ASSERT_EQ(num_frames, frames_per_buffer_); |
| 264 if (play_count_ == 0) { | 266 if (play_count_ == 0) { |
| 265 PRINT("["); | 267 PRINT("["); |
| 266 } | 268 } |
| 267 play_count_++; | 269 play_count_++; |
| 268 memset(destination, 0, bytes_per_buffer_); | 270 memset(destination, 0, bytes_per_buffer_); |
| 269 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { | 271 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { |
| 270 if (pulse_time_ == 0) { | 272 if (pulse_time_ == 0) { |
| 271 pulse_time_ = clock_->TimeInMilliseconds(); | 273 pulse_time_ = clock_->TimeInMilliseconds(); |
| 272 } | 274 } |
| 273 PRINT("."); | 275 PRINT("."); |
| 274 const int16_t impulse = std::numeric_limits<int16_t>::max(); | 276 const int16_t impulse = std::numeric_limits<int16_t>::max(); |
| 275 int16_t* ptr16 = static_cast<int16_t*> (destination); | 277 int16_t* ptr16 = static_cast<int16_t*> (destination); |
| 276 for (int i = 0; i < 2; ++i) { | 278 for (int i = 0; i < 2; ++i) { |
| 277 *ptr16++ = impulse; | 279 *ptr16++ = impulse; |
| 278 } | 280 } |
| 279 } | 281 } |
| 280 } | 282 } |
| 281 | 283 |
| 282 // Detect received impulses in |source|, derive time between transmission and | 284 // Detect received impulses in |source|, derive time between transmission and |
| 283 // detection and add the calculated delay to list of latencies. | 285 // detection and add the calculated delay to list of latencies. |
| 284 void Write(const void* source, int num_frames) override { | 286 void Write(const void* source, size_t num_frames) override { |
| 285 ASSERT_EQ(num_frames, frames_per_buffer_); | 287 ASSERT_EQ(num_frames, frames_per_buffer_); |
| 286 rec_count_++; | 288 rec_count_++; |
| 287 if (pulse_time_ == 0) { | 289 if (pulse_time_ == 0) { |
| 288 // Avoid detection of new impulse response until a new impulse has | 290 // Avoid detection of new impulse response until a new impulse has |
| 289 // been transmitted (sets |pulse_time_| to value larger than zero). | 291 // been transmitted (sets |pulse_time_| to value larger than zero). |
| 290 return; | 292 return; |
| 291 } | 293 } |
| 292 const int16_t* ptr16 = static_cast<const int16_t*> (source); | 294 const int16_t* ptr16 = static_cast<const int16_t*> (source); |
| 293 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); | 295 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); |
| 294 // Find max value in the audio buffer. | 296 // Find max value in the audio buffer. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, | 350 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, |
| 349 min_latency(), max_latency(), average_latency()); | 351 min_latency(), max_latency(), average_latency()); |
| 350 } | 352 } |
| 351 | 353 |
| 352 int IndexToMilliseconds(double index) const { | 354 int IndexToMilliseconds(double index) const { |
| 353 return static_cast<int>(10.0 * (index / frames_per_buffer_) + 0.5); | 355 return static_cast<int>(10.0 * (index / frames_per_buffer_) + 0.5); |
| 354 } | 356 } |
| 355 | 357 |
| 356 private: | 358 private: |
| 357 Clock* clock_; | 359 Clock* clock_; |
| 358 const int frames_per_buffer_; | 360 const size_t frames_per_buffer_; |
| 359 const int bytes_per_buffer_; | 361 const size_t bytes_per_buffer_; |
| 360 int play_count_; | 362 int play_count_; |
| 361 int rec_count_; | 363 int rec_count_; |
| 362 int64_t pulse_time_; | 364 int64_t pulse_time_; |
| 363 std::vector<int> latencies_; | 365 std::vector<int> latencies_; |
| 364 }; | 366 }; |
| 365 | 367 |
| 366 // Mocks the AudioTransport object and proxies actions for the two callbacks | 368 // Mocks the AudioTransport object and proxies actions for the two callbacks |
| 367 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations | 369 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations |
| 368 // of AudioStreamInterface. | 370 // of AudioStreamInterface. |
| 369 class MockAudioTransport : public AudioTransport { | 371 class MockAudioTransport : public AudioTransport { |
| 370 public: | 372 public: |
| 371 explicit MockAudioTransport(int type) | 373 explicit MockAudioTransport(int type) |
| 372 : num_callbacks_(0), | 374 : num_callbacks_(0), |
| 373 type_(type), | 375 type_(type), |
| 374 play_count_(0), | 376 play_count_(0), |
| 375 rec_count_(0), | 377 rec_count_(0), |
| 376 audio_stream_(nullptr) {} | 378 audio_stream_(nullptr) {} |
| 377 | 379 |
| 378 virtual ~MockAudioTransport() {} | 380 virtual ~MockAudioTransport() {} |
| 379 | 381 |
| 380 MOCK_METHOD10(RecordedDataIsAvailable, | 382 MOCK_METHOD10(RecordedDataIsAvailable, |
| 381 int32_t(const void* audioSamples, | 383 int32_t(const void* audioSamples, |
| 382 const uint32_t nSamples, | 384 const size_t nSamples, |
| 383 const uint8_t nBytesPerSample, | 385 const size_t nBytesPerSample, |
| 384 const uint8_t nChannels, | 386 const uint8_t nChannels, |
| 385 const uint32_t samplesPerSec, | 387 const uint32_t samplesPerSec, |
| 386 const uint32_t totalDelayMS, | 388 const uint32_t totalDelayMS, |
| 387 const int32_t clockDrift, | 389 const int32_t clockDrift, |
| 388 const uint32_t currentMicLevel, | 390 const uint32_t currentMicLevel, |
| 389 const bool keyPressed, | 391 const bool keyPressed, |
| 390 uint32_t& newMicLevel)); | 392 uint32_t& newMicLevel)); |
| 391 MOCK_METHOD8(NeedMorePlayData, | 393 MOCK_METHOD8(NeedMorePlayData, |
| 392 int32_t(const uint32_t nSamples, | 394 int32_t(const size_t nSamples, |
| 393 const uint8_t nBytesPerSample, | 395 const size_t nBytesPerSample, |
| 394 const uint8_t nChannels, | 396 const uint8_t nChannels, |
| 395 const uint32_t samplesPerSec, | 397 const uint32_t samplesPerSec, |
| 396 void* audioSamples, | 398 void* audioSamples, |
| 397 uint32_t& nSamplesOut, | 399 size_t& nSamplesOut, |
| 398 int64_t* elapsed_time_ms, | 400 int64_t* elapsed_time_ms, |
| 399 int64_t* ntp_time_ms)); | 401 int64_t* ntp_time_ms)); |
| 400 | 402 |
| 401 // Set default actions of the mock object. We are delegating to fake | 403 // Set default actions of the mock object. We are delegating to fake |
| 402 // implementations (of AudioStreamInterface) here. | 404 // implementations (of AudioStreamInterface) here. |
| 403 void HandleCallbacks(EventWrapper* test_is_done, | 405 void HandleCallbacks(EventWrapper* test_is_done, |
| 404 AudioStreamInterface* audio_stream, | 406 AudioStreamInterface* audio_stream, |
| 405 int num_callbacks) { | 407 int num_callbacks) { |
| 406 test_is_done_ = test_is_done; | 408 test_is_done_ = test_is_done; |
| 407 audio_stream_ = audio_stream; | 409 audio_stream_ = audio_stream; |
| 408 num_callbacks_ = num_callbacks; | 410 num_callbacks_ = num_callbacks; |
| 409 if (play_mode()) { | 411 if (play_mode()) { |
| 410 ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _)) | 412 ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _)) |
| 411 .WillByDefault( | 413 .WillByDefault( |
| 412 Invoke(this, &MockAudioTransport::RealNeedMorePlayData)); | 414 Invoke(this, &MockAudioTransport::RealNeedMorePlayData)); |
| 413 } | 415 } |
| 414 if (rec_mode()) { | 416 if (rec_mode()) { |
| 415 ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _)) | 417 ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _)) |
| 416 .WillByDefault( | 418 .WillByDefault( |
| 417 Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable)); | 419 Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable)); |
| 418 } | 420 } |
| 419 } | 421 } |
| 420 | 422 |
| 421 int32_t RealRecordedDataIsAvailable(const void* audioSamples, | 423 int32_t RealRecordedDataIsAvailable(const void* audioSamples, |
| 422 const uint32_t nSamples, | 424 const size_t nSamples, |
| 423 const uint8_t nBytesPerSample, | 425 const size_t nBytesPerSample, |
| 424 const uint8_t nChannels, | 426 const uint8_t nChannels, |
| 425 const uint32_t samplesPerSec, | 427 const uint32_t samplesPerSec, |
| 426 const uint32_t totalDelayMS, | 428 const uint32_t totalDelayMS, |
| 427 const int32_t clockDrift, | 429 const int32_t clockDrift, |
| 428 const uint32_t currentMicLevel, | 430 const uint32_t currentMicLevel, |
| 429 const bool keyPressed, | 431 const bool keyPressed, |
| 430 uint32_t& newMicLevel) { | 432 uint32_t& newMicLevel) { |
| 431 EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks."; | 433 EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks."; |
| 432 rec_count_++; | 434 rec_count_++; |
| 433 // Process the recorded audio stream if an AudioStreamInterface | 435 // Process the recorded audio stream if an AudioStreamInterface |
| 434 // implementation exists. | 436 // implementation exists. |
| 435 if (audio_stream_) { | 437 if (audio_stream_) { |
| 436 audio_stream_->Write(audioSamples, nSamples); | 438 audio_stream_->Write(audioSamples, nSamples); |
| 437 } | 439 } |
| 438 if (ReceivedEnoughCallbacks()) { | 440 if (ReceivedEnoughCallbacks()) { |
| 439 test_is_done_->Set(); | 441 test_is_done_->Set(); |
| 440 } | 442 } |
| 441 return 0; | 443 return 0; |
| 442 } | 444 } |
| 443 | 445 |
| 444 int32_t RealNeedMorePlayData(const uint32_t nSamples, | 446 int32_t RealNeedMorePlayData(const size_t nSamples, |
| 445 const uint8_t nBytesPerSample, | 447 const size_t nBytesPerSample, |
| 446 const uint8_t nChannels, | 448 const uint8_t nChannels, |
| 447 const uint32_t samplesPerSec, | 449 const uint32_t samplesPerSec, |
| 448 void* audioSamples, | 450 void* audioSamples, |
| 449 uint32_t& nSamplesOut, | 451 size_t& nSamplesOut, |
| 450 int64_t* elapsed_time_ms, | 452 int64_t* elapsed_time_ms, |
| 451 int64_t* ntp_time_ms) { | 453 int64_t* ntp_time_ms) { |
| 452 EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks."; | 454 EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks."; |
| 453 play_count_++; | 455 play_count_++; |
| 454 nSamplesOut = nSamples; | 456 nSamplesOut = nSamples; |
| 455 // Read (possibly processed) audio stream samples to be played out if an | 457 // Read (possibly processed) audio stream samples to be played out if an |
| 456 // AudioStreamInterface implementation exists. | 458 // AudioStreamInterface implementation exists. |
| 457 if (audio_stream_) { | 459 if (audio_stream_) { |
| 458 audio_stream_->Read(audioSamples, nSamples); | 460 audio_stream_->Read(audioSamples, nSamples); |
| 459 } | 461 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 } | 520 } |
| 519 int record_sample_rate() const { | 521 int record_sample_rate() const { |
| 520 return record_parameters_.sample_rate(); | 522 return record_parameters_.sample_rate(); |
| 521 } | 523 } |
| 522 int playout_channels() const { | 524 int playout_channels() const { |
| 523 return playout_parameters_.channels(); | 525 return playout_parameters_.channels(); |
| 524 } | 526 } |
| 525 int record_channels() const { | 527 int record_channels() const { |
| 526 return record_parameters_.channels(); | 528 return record_parameters_.channels(); |
| 527 } | 529 } |
| 528 int playout_frames_per_10ms_buffer() const { | 530 size_t playout_frames_per_10ms_buffer() const { |
| 529 return playout_parameters_.frames_per_10ms_buffer(); | 531 return playout_parameters_.frames_per_10ms_buffer(); |
| 530 } | 532 } |
| 531 int record_frames_per_10ms_buffer() const { | 533 size_t record_frames_per_10ms_buffer() const { |
| 532 return record_parameters_.frames_per_10ms_buffer(); | 534 return record_parameters_.frames_per_10ms_buffer(); |
| 533 } | 535 } |
| 534 | 536 |
| 535 int total_delay_ms() const { | 537 int total_delay_ms() const { |
| 536 return audio_manager()->GetDelayEstimateInMilliseconds(); | 538 return audio_manager()->GetDelayEstimateInMilliseconds(); |
| 537 } | 539 } |
| 538 | 540 |
| 539 rtc::scoped_refptr<AudioDeviceModule> audio_device() const { | 541 rtc::scoped_refptr<AudioDeviceModule> audio_device() const { |
| 540 return audio_device_; | 542 return audio_device_; |
| 541 } | 543 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 569 EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100); | 571 EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100); |
| 570 char fname[64]; | 572 char fname[64]; |
| 571 snprintf(fname, | 573 snprintf(fname, |
| 572 sizeof(fname), | 574 sizeof(fname), |
| 573 "audio_device/audio_short%d", | 575 "audio_device/audio_short%d", |
| 574 sample_rate / 1000); | 576 sample_rate / 1000); |
| 575 std::string file_name(webrtc::test::ResourcePath(fname, "pcm")); | 577 std::string file_name(webrtc::test::ResourcePath(fname, "pcm")); |
| 576 EXPECT_TRUE(test::FileExists(file_name)); | 578 EXPECT_TRUE(test::FileExists(file_name)); |
| 577 #ifdef ENABLE_PRINTF | 579 #ifdef ENABLE_PRINTF |
| 578 PRINT("file name: %s\n", file_name.c_str()); | 580 PRINT("file name: %s\n", file_name.c_str()); |
| 579 const int bytes = test::GetFileSize(file_name); | 581 const size_t bytes = test::GetFileSize(file_name); |
| 580 PRINT("file size: %d [bytes]\n", bytes); | 582 PRINT("file size: %" PRIuS " [bytes]\n", bytes); |
| 581 PRINT("file size: %d [samples]\n", bytes / kBytesPerSample); | 583 PRINT("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample); |
| 582 const int seconds = bytes / (sample_rate * kBytesPerSample); | 584 const int seconds = |
| 585 static_cast<int>(bytes / (sample_rate * kBytesPerSample)); |
| 583 PRINT("file size: %d [secs]\n", seconds); | 586 PRINT("file size: %d [secs]\n", seconds); |
| 584 PRINT("file size: %d [callbacks]\n", seconds * kNumCallbacksPerSecond); | 587 PRINT("file size: %d [callbacks]\n", seconds * kNumCallbacksPerSecond); |
| 585 #endif | 588 #endif |
| 586 return file_name; | 589 return file_name; |
| 587 } | 590 } |
| 588 | 591 |
| 589 AudioDeviceModule::AudioLayer GetActiveAudioLayer() const { | 592 AudioDeviceModule::AudioLayer GetActiveAudioLayer() const { |
| 590 AudioDeviceModule::AudioLayer audio_layer; | 593 AudioDeviceModule::AudioLayer audio_layer; |
| 591 EXPECT_EQ(0, audio_device()->ActiveAudioLayer(&audio_layer)); | 594 EXPECT_EQ(0, audio_device()->ActiveAudioLayer(&audio_layer)); |
| 592 return audio_layer; | 595 return audio_layer; |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 1000 * kMeasureLatencyTimeInSec)); | 995 1000 * kMeasureLatencyTimeInSec)); |
| 993 StopPlayout(); | 996 StopPlayout(); |
| 994 StopRecording(); | 997 StopRecording(); |
| 995 // Verify that the correct number of transmitted impulses are detected. | 998 // Verify that the correct number of transmitted impulses are detected. |
| 996 EXPECT_EQ(latency_audio_stream->num_latency_values(), | 999 EXPECT_EQ(latency_audio_stream->num_latency_values(), |
| 997 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1); | 1000 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1); |
| 998 latency_audio_stream->PrintResults(); | 1001 latency_audio_stream->PrintResults(); |
| 999 } | 1002 } |
| 1000 | 1003 |
| 1001 } // namespace webrtc | 1004 } // namespace webrtc |
| OLD | NEW |