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 16 matching lines...) Expand all Loading... |
48 #define PRINTD(...) fprintf(stderr, __VA_ARGS__); | 49 #define PRINTD(...) fprintf(stderr, __VA_ARGS__); |
49 #else | 50 #else |
50 #define PRINTD(...) ((void)0) | 51 #define PRINTD(...) ((void)0) |
51 #endif | 52 #endif |
52 #define PRINT(...) fprintf(stderr, __VA_ARGS__); | 53 #define PRINT(...) fprintf(stderr, __VA_ARGS__); |
53 | 54 |
54 namespace webrtc { | 55 namespace webrtc { |
55 | 56 |
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 size_t 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 size_t 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 size_t 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 size_t 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 size_t 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 size_t 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 size_t 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("(%" PRIuS ")", 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]), |
210 bytes_per_buffer_); | 212 bytes_per_buffer_); |
211 delete memory; | 213 delete memory; |
212 } | 214 } |
213 } | 215 } |
214 | 216 |
215 int size() const { | 217 size_t size() const { |
216 return fifo_->size(); | 218 return fifo_->size(); |
217 } | 219 } |
218 | 220 |
219 int largest_size() const { | 221 size_t largest_size() const { |
220 return largest_size_; | 222 return largest_size_; |
221 } | 223 } |
222 | 224 |
223 int average_size() const { | 225 size_t average_size() const { |
224 return (total_written_elements_ == 0) ? 0.0 : 0.5 + static_cast<float> ( | 226 return (total_written_elements_ == 0) ? 0.0 : 0.5 + static_cast<float> ( |
225 total_written_elements_) / (write_count_ - kNumIgnoreFirstCallbacks); | 227 total_written_elements_) / (write_count_ - kNumIgnoreFirstCallbacks); |
226 } | 228 } |
227 | 229 |
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 size_t largest_size_; |
242 int total_written_elements_; | 244 size_t total_written_elements_; |
243 int write_count_; | 245 size_t 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 (size_t i = 0; i < 2; ++i) { |
277 *ptr16++ = impulse; | 279 ptr16[i] = 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 13 matching lines...) Expand all Loading... |
308 // received impulse. It is transmitted at sample 0 but can be received | 310 // received impulse. It is transmitted at sample 0 but can be received |
309 // at sample N where N > 0. The term |extra_delay| accounts for N and it | 311 // at sample N where N > 0. The term |extra_delay| accounts for N and it |
310 // is a value between 0 and 10ms. | 312 // is a value between 0 and 10ms. |
311 latencies_.push_back(now_time - pulse_time_ + extra_delay); | 313 latencies_.push_back(now_time - pulse_time_ + extra_delay); |
312 pulse_time_ = 0; | 314 pulse_time_ = 0; |
313 } else { | 315 } else { |
314 PRINTD("-"); | 316 PRINTD("-"); |
315 } | 317 } |
316 } | 318 } |
317 | 319 |
318 int num_latency_values() const { | 320 size_t num_latency_values() const { |
319 return latencies_.size(); | 321 return latencies_.size(); |
320 } | 322 } |
321 | 323 |
322 int min_latency() const { | 324 int min_latency() const { |
323 if (latencies_.empty()) | 325 if (latencies_.empty()) |
324 return 0; | 326 return 0; |
325 return *std::min_element(latencies_.begin(), latencies_.end()); | 327 return *std::min_element(latencies_.begin(), latencies_.end()); |
326 } | 328 } |
327 | 329 |
328 int max_latency() const { | 330 int max_latency() const { |
(...skipping 19 matching lines...) Expand all 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 size_t play_count_; |
361 int rec_count_; | 363 size_t 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 17 matching lines...) Expand all Loading... |
477 playout_done = true; | 479 playout_done = true; |
478 | 480 |
479 return recording_done && playout_done; | 481 return recording_done && playout_done; |
480 } | 482 } |
481 | 483 |
482 bool play_mode() const { return type_ & kPlayout; } | 484 bool play_mode() const { return type_ & kPlayout; } |
483 bool rec_mode() const { return type_ & kRecording; } | 485 bool rec_mode() const { return type_ & kRecording; } |
484 | 486 |
485 private: | 487 private: |
486 EventWrapper* test_is_done_; | 488 EventWrapper* test_is_done_; |
487 int num_callbacks_; | 489 size_t num_callbacks_; |
488 int type_; | 490 int type_; |
489 int play_count_; | 491 size_t play_count_; |
490 int rec_count_; | 492 size_t rec_count_; |
491 AudioStreamInterface* audio_stream_; | 493 AudioStreamInterface* audio_stream_; |
492 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream_; | 494 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream_; |
493 }; | 495 }; |
494 | 496 |
495 // AudioDeviceTest test fixture. | 497 // AudioDeviceTest test fixture. |
496 class AudioDeviceTest : public ::testing::Test { | 498 class AudioDeviceTest : public ::testing::Test { |
497 protected: | 499 protected: |
498 AudioDeviceTest() | 500 AudioDeviceTest() |
499 : test_is_done_(EventWrapper::Create()) { | 501 : test_is_done_(EventWrapper::Create()) { |
500 // One-time initialization of JVM and application context. Ensures that we | 502 // One-time initialization of JVM and application context. Ensures that we |
(...skipping 17 matching lines...) Expand all 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: %" PRIuS " [callbacks]\n", |
| 588 seconds * kNumCallbacksPerSecond); |
585 #endif | 589 #endif |
586 return file_name; | 590 return file_name; |
587 } | 591 } |
588 | 592 |
589 AudioDeviceModule::AudioLayer GetActiveAudioLayer() const { | 593 AudioDeviceModule::AudioLayer GetActiveAudioLayer() const { |
590 AudioDeviceModule::AudioLayer audio_layer; | 594 AudioDeviceModule::AudioLayer audio_layer; |
591 EXPECT_EQ(0, audio_device()->ActiveAudioLayer(&audio_layer)); | 595 EXPECT_EQ(0, audio_device()->ActiveAudioLayer(&audio_layer)); |
592 return audio_layer; | 596 return audio_layer; |
593 } | 597 } |
594 | 598 |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 fifo_audio_stream.get(), | 958 fifo_audio_stream.get(), |
955 kFullDuplexTimeInSec * kNumCallbacksPerSecond); | 959 kFullDuplexTimeInSec * kNumCallbacksPerSecond); |
956 SetMaxPlayoutVolume(); | 960 SetMaxPlayoutVolume(); |
957 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); | 961 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock)); |
958 StartRecording(); | 962 StartRecording(); |
959 StartPlayout(); | 963 StartPlayout(); |
960 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, | 964 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, |
961 1000 * kFullDuplexTimeInSec)); | 965 1000 * kFullDuplexTimeInSec)); |
962 StopPlayout(); | 966 StopPlayout(); |
963 StopRecording(); | 967 StopRecording(); |
964 EXPECT_LE(fifo_audio_stream->average_size(), 10); | 968 EXPECT_LE(fifo_audio_stream->average_size(), 10u); |
965 EXPECT_LE(fifo_audio_stream->largest_size(), 20); | 969 EXPECT_LE(fifo_audio_stream->largest_size(), 20u); |
966 } | 970 } |
967 | 971 |
968 // Measures loopback latency and reports the min, max and average values for | 972 // Measures loopback latency and reports the min, max and average values for |
969 // a full duplex audio session. | 973 // a full duplex audio session. |
970 // The latency is measured like so: | 974 // The latency is measured like so: |
971 // - Insert impulses periodically on the output side. | 975 // - Insert impulses periodically on the output side. |
972 // - Detect the impulses on the input side. | 976 // - Detect the impulses on the input side. |
973 // - Measure the time difference between the transmit time and receive time. | 977 // - Measure the time difference between the transmit time and receive time. |
974 // - Store time differences in a vector and calculate min, max and average. | 978 // - Store time differences in a vector and calculate min, max and average. |
975 // This test requires a special hardware called Audio Loopback Dongle. | 979 // This test requires a special hardware called Audio Loopback Dongle. |
(...skipping 11 matching lines...) Expand all Loading... |
987 SetMaxPlayoutVolume(); | 991 SetMaxPlayoutVolume(); |
988 DisableBuiltInAECIfAvailable(); | 992 DisableBuiltInAECIfAvailable(); |
989 StartRecording(); | 993 StartRecording(); |
990 StartPlayout(); | 994 StartPlayout(); |
991 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, | 995 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds, |
992 1000 * kMeasureLatencyTimeInSec)); | 996 1000 * kMeasureLatencyTimeInSec)); |
993 StopPlayout(); | 997 StopPlayout(); |
994 StopRecording(); | 998 StopRecording(); |
995 // Verify that the correct number of transmitted impulses are detected. | 999 // Verify that the correct number of transmitted impulses are detected. |
996 EXPECT_EQ(latency_audio_stream->num_latency_values(), | 1000 EXPECT_EQ(latency_audio_stream->num_latency_values(), |
997 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1); | 1001 static_cast<size_t>( |
| 1002 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); |
998 latency_audio_stream->PrintResults(); | 1003 latency_audio_stream->PrintResults(); |
999 } | 1004 } |
1000 | 1005 |
1001 } // namespace webrtc | 1006 } // namespace webrtc |
OLD | NEW |