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/logging.h" | 23 #include "webrtc/base/logging.h" |
23 #include "webrtc/base/scoped_ptr.h" | 24 #include "webrtc/base/scoped_ptr.h" |
24 #include "webrtc/base/scoped_ref_ptr.h" | 25 #include "webrtc/base/scoped_ref_ptr.h" |
25 #include "webrtc/modules/audio_device/audio_device_impl.h" | 26 #include "webrtc/modules/audio_device/audio_device_impl.h" |
26 #include "webrtc/modules/audio_device/include/audio_device.h" | 27 #include "webrtc/modules/audio_device/include/audio_device.h" |
27 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" | 28 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" |
28 #include "webrtc/system_wrappers/interface/clock.h" | 29 #include "webrtc/system_wrappers/interface/clock.h" |
29 #include "webrtc/system_wrappers/interface/event_wrapper.h" | 30 #include "webrtc/system_wrappers/interface/event_wrapper.h" |
30 #include "webrtc/system_wrappers/interface/sleep.h" | 31 #include "webrtc/system_wrappers/interface/sleep.h" |
31 #include "webrtc/test/testsupport/fileutils.h" | 32 #include "webrtc/test/testsupport/fileutils.h" |
(...skipping 13 matching lines...) Expand all Loading... |
45 #define PRINTD(...) fprintf(stderr, __VA_ARGS__); | 46 #define PRINTD(...) fprintf(stderr, __VA_ARGS__); |
46 #else | 47 #else |
47 #define PRINTD(...) ((void)0) | 48 #define PRINTD(...) ((void)0) |
48 #endif | 49 #endif |
49 #define PRINT(...) fprintf(stderr, __VA_ARGS__); | 50 #define PRINT(...) fprintf(stderr, __VA_ARGS__); |
50 | 51 |
51 namespace webrtc { | 52 namespace webrtc { |
52 | 53 |
53 // Number of callbacks (input or output) the tests waits for before we set | 54 // Number of callbacks (input or output) the tests waits for before we set |
54 // an event indicating that the test was OK. | 55 // an event indicating that the test was OK. |
55 static const int kNumCallbacks = 10; | 56 static const size_t kNumCallbacks = 10; |
56 // Max amount of time we wait for an event to be set while counting callbacks. | 57 // Max amount of time we wait for an event to be set while counting callbacks. |
57 static const int kTestTimeOutInMilliseconds = 10 * 1000; | 58 static const int kTestTimeOutInMilliseconds = 10 * 1000; |
58 // Number of bits per PCM audio sample. | 59 // Number of bits per PCM audio sample. |
59 static const int kBitsPerSample = 16; | 60 static const size_t kBitsPerSample = 16; |
60 // Number of bytes per PCM audio sample. | 61 // Number of bytes per PCM audio sample. |
61 static const int kBytesPerSample = kBitsPerSample / 8; | 62 static const size_t kBytesPerSample = kBitsPerSample / 8; |
62 // Average number of audio callbacks per second assuming 10ms packet size. | 63 // Average number of audio callbacks per second assuming 10ms packet size. |
63 static const int kNumCallbacksPerSecond = 100; | 64 static const size_t kNumCallbacksPerSecond = 100; |
64 // Play out a test file during this time (unit is in seconds). | 65 // Play out a test file during this time (unit is in seconds). |
65 static const int kFilePlayTimeInSec = 15; | 66 static const int kFilePlayTimeInSec = 15; |
66 // Run the full-duplex test during this time (unit is in seconds). | 67 // Run the full-duplex test during this time (unit is in seconds). |
67 // Note that first |kNumIgnoreFirstCallbacks| are ignored. | 68 // Note that first |kNumIgnoreFirstCallbacks| are ignored. |
68 static const int kFullDuplexTimeInSec = 10; | 69 static const int kFullDuplexTimeInSec = 10; |
69 // Wait for the callback sequence to stabilize by ignoring this amount of the | 70 // Wait for the callback sequence to stabilize by ignoring this amount of the |
70 // initial callbacks (avoids initial FIFO access). | 71 // initial callbacks (avoids initial FIFO access). |
71 // Only used in the RunPlayoutAndRecordingInFullDuplex test. | 72 // Only used in the RunPlayoutAndRecordingInFullDuplex test. |
72 static const int kNumIgnoreFirstCallbacks = 50; | 73 static const size_t kNumIgnoreFirstCallbacks = 50; |
73 // Sets the number of impulses per second in the latency test. | 74 // Sets the number of impulses per second in the latency test. |
74 // TODO(henrika): fine tune this setting for iOS. | 75 // TODO(henrika): fine tune this setting for iOS. |
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 // TODO(henrika): fine tune this setting for iOS. | 79 // TODO(henrika): fine tune this setting for iOS. |
79 static const int kMeasureLatencyTimeInSec = 5; | 80 static const int kMeasureLatencyTimeInSec = 5; |
80 // Utilized in round-trip latency measurements to avoid capturing noise samples. | 81 // Utilized in round-trip latency measurements to avoid capturing noise samples. |
81 // TODO(henrika): fine tune this setting for iOS. | 82 // TODO(henrika): fine tune this setting for iOS. |
82 static const int kImpulseThreshold = 50; | 83 static const int kImpulseThreshold = 50; |
83 static const char kTag[] = "[..........] "; | 84 static const char kTag[] = "[..........] "; |
84 | 85 |
85 enum TransportType { | 86 enum TransportType { |
86 kPlayout = 0x1, | 87 kPlayout = 0x1, |
87 kRecording = 0x2, | 88 kRecording = 0x2, |
88 }; | 89 }; |
89 | 90 |
90 // Interface for processing the audio stream. Real implementations can e.g. | 91 // Interface for processing the audio stream. Real implementations can e.g. |
91 // run audio in loopback, read audio from a file or perform latency | 92 // run audio in loopback, read audio from a file or perform latency |
92 // measurements. | 93 // measurements. |
93 class AudioStreamInterface { | 94 class AudioStreamInterface { |
94 public: | 95 public: |
95 virtual void Write(const void* source, int num_frames) = 0; | 96 virtual void Write(const void* source, size_t num_frames) = 0; |
96 virtual void Read(void* destination, int num_frames) = 0; | 97 virtual void Read(void* destination, size_t num_frames) = 0; |
97 | 98 |
98 protected: | 99 protected: |
99 virtual ~AudioStreamInterface() {} | 100 virtual ~AudioStreamInterface() {} |
100 }; | 101 }; |
101 | 102 |
102 // Reads audio samples from a PCM file where the file is stored in memory at | 103 // Reads audio samples from a PCM file where the file is stored in memory at |
103 // construction. | 104 // construction. |
104 class FileAudioStream : public AudioStreamInterface { | 105 class FileAudioStream : public AudioStreamInterface { |
105 public: | 106 public: |
106 FileAudioStream(int num_callbacks, | 107 FileAudioStream(size_t num_callbacks, |
107 const std::string& file_name, | 108 const std::string& file_name, |
108 int sample_rate) | 109 int sample_rate) |
109 : file_size_in_bytes_(0), sample_rate_(sample_rate), file_pos_(0) { | 110 : file_size_in_bytes_(0), sample_rate_(sample_rate), file_pos_(0) { |
110 file_size_in_bytes_ = test::GetFileSize(file_name); | 111 file_size_in_bytes_ = test::GetFileSize(file_name); |
111 sample_rate_ = sample_rate; | 112 sample_rate_ = sample_rate; |
112 EXPECT_GE(file_size_in_callbacks(), num_callbacks) | 113 EXPECT_GE(file_size_in_callbacks(), num_callbacks) |
113 << "Size of test file is not large enough to last during the test."; | 114 << "Size of test file is not large enough to last during the test."; |
114 const int num_16bit_samples = | 115 const size_t num_16bit_samples = |
115 test::GetFileSize(file_name) / kBytesPerSample; | 116 test::GetFileSize(file_name) / kBytesPerSample; |
116 file_.reset(new int16_t[num_16bit_samples]); | 117 file_.reset(new int16_t[num_16bit_samples]); |
117 FILE* audio_file = fopen(file_name.c_str(), "rb"); | 118 FILE* audio_file = fopen(file_name.c_str(), "rb"); |
118 EXPECT_NE(audio_file, nullptr); | 119 EXPECT_NE(audio_file, nullptr); |
119 int num_samples_read = | 120 size_t num_samples_read = |
120 fread(file_.get(), sizeof(int16_t), num_16bit_samples, audio_file); | 121 fread(file_.get(), sizeof(int16_t), num_16bit_samples, audio_file); |
121 EXPECT_EQ(num_samples_read, num_16bit_samples); | 122 EXPECT_EQ(num_samples_read, num_16bit_samples); |
122 fclose(audio_file); | 123 fclose(audio_file); |
123 } | 124 } |
124 | 125 |
125 // AudioStreamInterface::Write() is not implemented. | 126 // AudioStreamInterface::Write() is not implemented. |
126 void Write(const void* source, int num_frames) override {} | 127 void Write(const void* source, size_t num_frames) override {} |
127 | 128 |
128 // Read samples from file stored in memory (at construction) and copy | 129 // Read samples from file stored in memory (at construction) and copy |
129 // |num_frames| (<=> 10ms) to the |destination| byte buffer. | 130 // |num_frames| (<=> 10ms) to the |destination| byte buffer. |
130 void Read(void* destination, int num_frames) override { | 131 void Read(void* destination, size_t num_frames) override { |
131 memcpy(destination, static_cast<int16_t*>(&file_[file_pos_]), | 132 memcpy(destination, static_cast<int16_t*>(&file_[file_pos_]), |
132 num_frames * sizeof(int16_t)); | 133 num_frames * sizeof(int16_t)); |
133 file_pos_ += num_frames; | 134 file_pos_ += num_frames; |
134 } | 135 } |
135 | 136 |
136 int file_size_in_seconds() const { | 137 int file_size_in_seconds() const { |
137 return (file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); | 138 return static_cast<int>( |
| 139 file_size_in_bytes_ / (kBytesPerSample * sample_rate_)); |
138 } | 140 } |
139 int file_size_in_callbacks() const { | 141 size_t file_size_in_callbacks() const { |
140 return file_size_in_seconds() * kNumCallbacksPerSecond; | 142 return file_size_in_seconds() * kNumCallbacksPerSecond; |
141 } | 143 } |
142 | 144 |
143 private: | 145 private: |
144 int file_size_in_bytes_; | 146 size_t file_size_in_bytes_; |
145 int sample_rate_; | 147 int sample_rate_; |
146 rtc::scoped_ptr<int16_t[]> file_; | 148 rtc::scoped_ptr<int16_t[]> file_; |
147 int file_pos_; | 149 size_t file_pos_; |
148 }; | 150 }; |
149 | 151 |
150 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio | 152 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio |
151 // buffers of fixed size and allows Write and Read operations. The idea is to | 153 // buffers of fixed size and allows Write and Read operations. The idea is to |
152 // store recorded audio buffers (using Write) and then read (using Read) these | 154 // store recorded audio buffers (using Write) and then read (using Read) these |
153 // stored buffers with as short delay as possible when the audio layer needs | 155 // stored buffers with as short delay as possible when the audio layer needs |
154 // data to play out. The number of buffers in the FIFO will stabilize under | 156 // data to play out. The number of buffers in the FIFO will stabilize under |
155 // normal conditions since there will be a balance between Write and Read calls. | 157 // normal conditions since there will be a balance between Write and Read calls. |
156 // The container is a std::list container and access is protected with a lock | 158 // The container is a std::list container and access is protected with a lock |
157 // since both sides (playout and recording) are driven by its own thread. | 159 // since both sides (playout and recording) are driven by its own thread. |
158 class FifoAudioStream : public AudioStreamInterface { | 160 class FifoAudioStream : public AudioStreamInterface { |
159 public: | 161 public: |
160 explicit FifoAudioStream(int frames_per_buffer) | 162 explicit FifoAudioStream(size_t frames_per_buffer) |
161 : frames_per_buffer_(frames_per_buffer), | 163 : frames_per_buffer_(frames_per_buffer), |
162 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 164 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), |
163 fifo_(new AudioBufferList), | 165 fifo_(new AudioBufferList), |
164 largest_size_(0), | 166 largest_size_(0), |
165 total_written_elements_(0), | 167 total_written_elements_(0), |
166 write_count_(0) { | 168 write_count_(0) { |
167 EXPECT_NE(fifo_.get(), nullptr); | 169 EXPECT_NE(fifo_.get(), nullptr); |
168 } | 170 } |
169 | 171 |
170 ~FifoAudioStream() { Flush(); } | 172 ~FifoAudioStream() { Flush(); } |
171 | 173 |
172 // Allocate new memory, copy |num_frames| samples from |source| into memory | 174 // Allocate new memory, copy |num_frames| samples from |source| into memory |
173 // and add pointer to the memory location to end of the list. | 175 // and add pointer to the memory location to end of the list. |
174 // Increases the size of the FIFO by one element. | 176 // Increases the size of the FIFO by one element. |
175 void Write(const void* source, int num_frames) override { | 177 void Write(const void* source, size_t num_frames) override { |
176 ASSERT_EQ(num_frames, frames_per_buffer_); | 178 ASSERT_EQ(num_frames, frames_per_buffer_); |
177 PRINTD("+"); | 179 PRINTD("+"); |
178 if (write_count_++ < kNumIgnoreFirstCallbacks) { | 180 if (write_count_++ < kNumIgnoreFirstCallbacks) { |
179 return; | 181 return; |
180 } | 182 } |
181 int16_t* memory = new int16_t[frames_per_buffer_]; | 183 int16_t* memory = new int16_t[frames_per_buffer_]; |
182 memcpy(static_cast<int16_t*>(&memory[0]), source, bytes_per_buffer_); | 184 memcpy(static_cast<int16_t*>(&memory[0]), source, bytes_per_buffer_); |
183 rtc::CritScope lock(&lock_); | 185 rtc::CritScope lock(&lock_); |
184 fifo_->push_back(memory); | 186 fifo_->push_back(memory); |
185 const int size = fifo_->size(); | 187 const size_t size = fifo_->size(); |
186 if (size > largest_size_) { | 188 if (size > largest_size_) { |
187 largest_size_ = size; | 189 largest_size_ = size; |
188 PRINTD("(%d)", largest_size_); | 190 PRINTD("(%" PRIuS ")", largest_size_); |
189 } | 191 } |
190 total_written_elements_ += size; | 192 total_written_elements_ += size; |
191 } | 193 } |
192 | 194 |
193 // Read pointer to data buffer from front of list, copy |num_frames| of stored | 195 // Read pointer to data buffer from front of list, copy |num_frames| of stored |
194 // data into |destination| and delete the utilized memory allocation. | 196 // data into |destination| and delete the utilized memory allocation. |
195 // Decreases the size of the FIFO by one element. | 197 // Decreases the size of the FIFO by one element. |
196 void Read(void* destination, int num_frames) override { | 198 void Read(void* destination, size_t num_frames) override { |
197 ASSERT_EQ(num_frames, frames_per_buffer_); | 199 ASSERT_EQ(num_frames, frames_per_buffer_); |
198 PRINTD("-"); | 200 PRINTD("-"); |
199 rtc::CritScope lock(&lock_); | 201 rtc::CritScope lock(&lock_); |
200 if (fifo_->empty()) { | 202 if (fifo_->empty()) { |
201 memset(destination, 0, bytes_per_buffer_); | 203 memset(destination, 0, bytes_per_buffer_); |
202 } else { | 204 } else { |
203 int16_t* memory = fifo_->front(); | 205 int16_t* memory = fifo_->front(); |
204 fifo_->pop_front(); | 206 fifo_->pop_front(); |
205 memcpy(destination, static_cast<int16_t*>(&memory[0]), bytes_per_buffer_); | 207 memcpy(destination, static_cast<int16_t*>(&memory[0]), bytes_per_buffer_); |
206 delete memory; | 208 delete memory; |
207 } | 209 } |
208 } | 210 } |
209 | 211 |
210 int size() const { return fifo_->size(); } | 212 size_t size() const { return fifo_->size(); } |
211 | 213 |
212 int largest_size() const { return largest_size_; } | 214 size_t largest_size() const { return largest_size_; } |
213 | 215 |
214 int average_size() const { | 216 size_t average_size() const { |
215 return (total_written_elements_ == 0) | 217 return (total_written_elements_ == 0) |
216 ? 0.0 | 218 ? 0.0 |
217 : 0.5 + | 219 : 0.5 + |
218 static_cast<float>(total_written_elements_) / | 220 static_cast<float>(total_written_elements_) / |
219 (write_count_ - kNumIgnoreFirstCallbacks); | 221 (write_count_ - kNumIgnoreFirstCallbacks); |
220 } | 222 } |
221 | 223 |
222 private: | 224 private: |
223 void Flush() { | 225 void Flush() { |
224 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { | 226 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) { |
225 delete *it; | 227 delete *it; |
226 } | 228 } |
227 fifo_->clear(); | 229 fifo_->clear(); |
228 } | 230 } |
229 | 231 |
230 using AudioBufferList = std::list<int16_t*>; | 232 using AudioBufferList = std::list<int16_t*>; |
231 rtc::CriticalSection lock_; | 233 rtc::CriticalSection lock_; |
232 const int frames_per_buffer_; | 234 const size_t frames_per_buffer_; |
233 const int bytes_per_buffer_; | 235 const size_t bytes_per_buffer_; |
234 rtc::scoped_ptr<AudioBufferList> fifo_; | 236 rtc::scoped_ptr<AudioBufferList> fifo_; |
235 int largest_size_; | 237 size_t largest_size_; |
236 int total_written_elements_; | 238 size_t total_written_elements_; |
237 int write_count_; | 239 size_t write_count_; |
238 }; | 240 }; |
239 | 241 |
240 // Inserts periodic impulses and measures the latency between the time of | 242 // Inserts periodic impulses and measures the latency between the time of |
241 // transmission and time of receiving the same impulse. | 243 // transmission and time of receiving the same impulse. |
242 // Usage requires a special hardware called Audio Loopback Dongle. | 244 // Usage requires a special hardware called Audio Loopback Dongle. |
243 // See http://source.android.com/devices/audio/loopback.html for details. | 245 // See http://source.android.com/devices/audio/loopback.html for details. |
244 class LatencyMeasuringAudioStream : public AudioStreamInterface { | 246 class LatencyMeasuringAudioStream : public AudioStreamInterface { |
245 public: | 247 public: |
246 explicit LatencyMeasuringAudioStream(int frames_per_buffer) | 248 explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) |
247 : clock_(Clock::GetRealTimeClock()), | 249 : clock_(Clock::GetRealTimeClock()), |
248 frames_per_buffer_(frames_per_buffer), | 250 frames_per_buffer_(frames_per_buffer), |
249 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 251 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), |
250 play_count_(0), | 252 play_count_(0), |
251 rec_count_(0), | 253 rec_count_(0), |
252 pulse_time_(0) {} | 254 pulse_time_(0) {} |
253 | 255 |
254 // Insert periodic impulses in first two samples of |destination|. | 256 // Insert periodic impulses in first two samples of |destination|. |
255 void Read(void* destination, int num_frames) override { | 257 void Read(void* destination, size_t num_frames) override { |
256 ASSERT_EQ(num_frames, frames_per_buffer_); | 258 ASSERT_EQ(num_frames, frames_per_buffer_); |
257 if (play_count_ == 0) { | 259 if (play_count_ == 0) { |
258 PRINT("["); | 260 PRINT("["); |
259 } | 261 } |
260 play_count_++; | 262 play_count_++; |
261 memset(destination, 0, bytes_per_buffer_); | 263 memset(destination, 0, bytes_per_buffer_); |
262 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { | 264 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { |
263 if (pulse_time_ == 0) { | 265 if (pulse_time_ == 0) { |
264 pulse_time_ = clock_->TimeInMilliseconds(); | 266 pulse_time_ = clock_->TimeInMilliseconds(); |
265 } | 267 } |
266 PRINT("."); | 268 PRINT("."); |
267 const int16_t impulse = std::numeric_limits<int16_t>::max(); | 269 const int16_t impulse = std::numeric_limits<int16_t>::max(); |
268 int16_t* ptr16 = static_cast<int16_t*>(destination); | 270 int16_t* ptr16 = static_cast<int16_t*>(destination); |
269 for (int i = 0; i < 2; ++i) { | 271 for (size_t i = 0; i < 2; ++i) { |
270 *ptr16++ = impulse; | 272 ptr16[i] = impulse; |
271 } | 273 } |
272 } | 274 } |
273 } | 275 } |
274 | 276 |
275 // Detect received impulses in |source|, derive time between transmission and | 277 // Detect received impulses in |source|, derive time between transmission and |
276 // detection and add the calculated delay to list of latencies. | 278 // detection and add the calculated delay to list of latencies. |
277 void Write(const void* source, int num_frames) override { | 279 void Write(const void* source, size_t num_frames) override { |
278 ASSERT_EQ(num_frames, frames_per_buffer_); | 280 ASSERT_EQ(num_frames, frames_per_buffer_); |
279 rec_count_++; | 281 rec_count_++; |
280 if (pulse_time_ == 0) { | 282 if (pulse_time_ == 0) { |
281 // Avoid detection of new impulse response until a new impulse has | 283 // Avoid detection of new impulse response until a new impulse has |
282 // been transmitted (sets |pulse_time_| to value larger than zero). | 284 // been transmitted (sets |pulse_time_| to value larger than zero). |
283 return; | 285 return; |
284 } | 286 } |
285 const int16_t* ptr16 = static_cast<const int16_t*>(source); | 287 const int16_t* ptr16 = static_cast<const int16_t*>(source); |
286 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); | 288 std::vector<int16_t> vec(ptr16, ptr16 + num_frames); |
287 // Find max value in the audio buffer. | 289 // Find max value in the audio buffer. |
(...skipping 12 matching lines...) Expand all Loading... |
300 // received impulse. It is transmitted at sample 0 but can be received | 302 // received impulse. It is transmitted at sample 0 but can be received |
301 // at sample N where N > 0. The term |extra_delay| accounts for N and it | 303 // at sample N where N > 0. The term |extra_delay| accounts for N and it |
302 // is a value between 0 and 10ms. | 304 // is a value between 0 and 10ms. |
303 latencies_.push_back(now_time - pulse_time_ + extra_delay); | 305 latencies_.push_back(now_time - pulse_time_ + extra_delay); |
304 pulse_time_ = 0; | 306 pulse_time_ = 0; |
305 } else { | 307 } else { |
306 PRINTD("-"); | 308 PRINTD("-"); |
307 } | 309 } |
308 } | 310 } |
309 | 311 |
310 int num_latency_values() const { return latencies_.size(); } | 312 size_t num_latency_values() const { return latencies_.size(); } |
311 | 313 |
312 int min_latency() const { | 314 int min_latency() const { |
313 if (latencies_.empty()) | 315 if (latencies_.empty()) |
314 return 0; | 316 return 0; |
315 return *std::min_element(latencies_.begin(), latencies_.end()); | 317 return *std::min_element(latencies_.begin(), latencies_.end()); |
316 } | 318 } |
317 | 319 |
318 int max_latency() const { | 320 int max_latency() const { |
319 if (latencies_.empty()) | 321 if (latencies_.empty()) |
320 return 0; | 322 return 0; |
(...skipping 18 matching lines...) Expand all Loading... |
339 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(), | 341 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(), |
340 max_latency(), average_latency()); | 342 max_latency(), average_latency()); |
341 } | 343 } |
342 | 344 |
343 int IndexToMilliseconds(double index) const { | 345 int IndexToMilliseconds(double index) const { |
344 return 10.0 * (index / frames_per_buffer_) + 0.5; | 346 return 10.0 * (index / frames_per_buffer_) + 0.5; |
345 } | 347 } |
346 | 348 |
347 private: | 349 private: |
348 Clock* clock_; | 350 Clock* clock_; |
349 const int frames_per_buffer_; | 351 const size_t frames_per_buffer_; |
350 const int bytes_per_buffer_; | 352 const size_t bytes_per_buffer_; |
351 int play_count_; | 353 size_t play_count_; |
352 int rec_count_; | 354 size_t rec_count_; |
353 int64_t pulse_time_; | 355 int64_t pulse_time_; |
354 std::vector<int> latencies_; | 356 std::vector<int> latencies_; |
355 }; | 357 }; |
356 // Mocks the AudioTransport object and proxies actions for the two callbacks | 358 // Mocks the AudioTransport object and proxies actions for the two callbacks |
357 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations | 359 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations |
358 // of AudioStreamInterface. | 360 // of AudioStreamInterface. |
359 class MockAudioTransport : public AudioTransport { | 361 class MockAudioTransport : public AudioTransport { |
360 public: | 362 public: |
361 explicit MockAudioTransport(int type) | 363 explicit MockAudioTransport(int type) |
362 : num_callbacks_(0), | 364 : num_callbacks_(0), |
363 type_(type), | 365 type_(type), |
364 play_count_(0), | 366 play_count_(0), |
365 rec_count_(0), | 367 rec_count_(0), |
366 audio_stream_(nullptr) {} | 368 audio_stream_(nullptr) {} |
367 | 369 |
368 virtual ~MockAudioTransport() {} | 370 virtual ~MockAudioTransport() {} |
369 | 371 |
370 MOCK_METHOD10(RecordedDataIsAvailable, | 372 MOCK_METHOD10(RecordedDataIsAvailable, |
371 int32_t(const void* audioSamples, | 373 int32_t(const void* audioSamples, |
372 const uint32_t nSamples, | 374 size_t uint32_t nSamples, |
373 const uint8_t nBytesPerSample, | 375 size_t uint8_t nBytesPerSample, |
374 const uint8_t nChannels, | 376 const uint8_t nChannels, |
375 const uint32_t samplesPerSec, | 377 const uint32_t samplesPerSec, |
376 const uint32_t totalDelayMS, | 378 const uint32_t totalDelayMS, |
377 const int32_t clockDrift, | 379 const int32_t clockDrift, |
378 const uint32_t currentMicLevel, | 380 const uint32_t currentMicLevel, |
379 const bool keyPressed, | 381 const bool keyPressed, |
380 uint32_t& newMicLevel)); | 382 uint32_t& newMicLevel)); |
381 MOCK_METHOD8(NeedMorePlayData, | 383 MOCK_METHOD8(NeedMorePlayData, |
382 int32_t(const uint32_t nSamples, | 384 int32_t(size_t uint32_t nSamples, |
383 const uint8_t nBytesPerSample, | 385 size_t uint8_t nBytesPerSample, |
384 const uint8_t nChannels, | 386 const uint8_t nChannels, |
385 const uint32_t samplesPerSec, | 387 const uint32_t samplesPerSec, |
386 void* audioSamples, | 388 void* audioSamples, |
387 uint32_t& nSamplesOut, | 389 size_t& nSamplesOut, |
388 int64_t* elapsed_time_ms, | 390 int64_t* elapsed_time_ms, |
389 int64_t* ntp_time_ms)); | 391 int64_t* ntp_time_ms)); |
390 | 392 |
391 // Set default actions of the mock object. We are delegating to fake | 393 // Set default actions of the mock object. We are delegating to fake |
392 // implementations (of AudioStreamInterface) here. | 394 // implementations (of AudioStreamInterface) here. |
393 void HandleCallbacks(EventWrapper* test_is_done, | 395 void HandleCallbacks(EventWrapper* test_is_done, |
394 AudioStreamInterface* audio_stream, | 396 AudioStreamInterface* audio_stream, |
395 int num_callbacks) { | 397 size_t num_callbacks) { |
396 test_is_done_ = test_is_done; | 398 test_is_done_ = test_is_done; |
397 audio_stream_ = audio_stream; | 399 audio_stream_ = audio_stream; |
398 num_callbacks_ = num_callbacks; | 400 num_callbacks_ = num_callbacks; |
399 if (play_mode()) { | 401 if (play_mode()) { |
400 ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _)) | 402 ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _)) |
401 .WillByDefault( | 403 .WillByDefault( |
402 Invoke(this, &MockAudioTransport::RealNeedMorePlayData)); | 404 Invoke(this, &MockAudioTransport::RealNeedMorePlayData)); |
403 } | 405 } |
404 if (rec_mode()) { | 406 if (rec_mode()) { |
405 ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _)) | 407 ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _)) |
406 .WillByDefault( | 408 .WillByDefault( |
407 Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable)); | 409 Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable)); |
408 } | 410 } |
409 } | 411 } |
410 | 412 |
411 int32_t RealRecordedDataIsAvailable(const void* audioSamples, | 413 int32_t RealRecordedDataIsAvailable(const void* audioSamples, |
412 const uint32_t nSamples, | 414 size_t uint32_t nSamples, |
413 const uint8_t nBytesPerSample, | 415 size_t uint8_t nBytesPerSample, |
414 const uint8_t nChannels, | 416 const uint8_t nChannels, |
415 const uint32_t samplesPerSec, | 417 const uint32_t samplesPerSec, |
416 const uint32_t totalDelayMS, | 418 const uint32_t totalDelayMS, |
417 const int32_t clockDrift, | 419 const int32_t clockDrift, |
418 const uint32_t currentMicLevel, | 420 const uint32_t currentMicLevel, |
419 const bool keyPressed, | 421 const bool keyPressed, |
420 uint32_t& newMicLevel) { | 422 uint32_t& newMicLevel) { |
421 EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks."; | 423 EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks."; |
422 rec_count_++; | 424 rec_count_++; |
423 // Process the recorded audio stream if an AudioStreamInterface | 425 // Process the recorded audio stream if an AudioStreamInterface |
424 // implementation exists. | 426 // implementation exists. |
425 if (audio_stream_) { | 427 if (audio_stream_) { |
426 audio_stream_->Write(audioSamples, nSamples); | 428 audio_stream_->Write(audioSamples, nSamples); |
427 } | 429 } |
428 if (ReceivedEnoughCallbacks()) { | 430 if (ReceivedEnoughCallbacks()) { |
429 test_is_done_->Set(); | 431 test_is_done_->Set(); |
430 } | 432 } |
431 return 0; | 433 return 0; |
432 } | 434 } |
433 | 435 |
434 int32_t RealNeedMorePlayData(const uint32_t nSamples, | 436 int32_t RealNeedMorePlayData(size_t uint32_t nSamples, |
435 const uint8_t nBytesPerSample, | 437 size_t uint8_t nBytesPerSample, |
436 const uint8_t nChannels, | 438 const uint8_t nChannels, |
437 const uint32_t samplesPerSec, | 439 const uint32_t samplesPerSec, |
438 void* audioSamples, | 440 void* audioSamples, |
439 uint32_t& nSamplesOut, | 441 size_t& nSamplesOut, |
440 int64_t* elapsed_time_ms, | 442 int64_t* elapsed_time_ms, |
441 int64_t* ntp_time_ms) { | 443 int64_t* ntp_time_ms) { |
442 EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks."; | 444 EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks."; |
443 play_count_++; | 445 play_count_++; |
444 nSamplesOut = nSamples; | 446 nSamplesOut = nSamples; |
445 // Read (possibly processed) audio stream samples to be played out if an | 447 // Read (possibly processed) audio stream samples to be played out if an |
446 // AudioStreamInterface implementation exists. | 448 // AudioStreamInterface implementation exists. |
447 if (audio_stream_) { | 449 if (audio_stream_) { |
448 audio_stream_->Read(audioSamples, nSamples); | 450 audio_stream_->Read(audioSamples, nSamples); |
449 } | 451 } |
(...skipping 17 matching lines...) Expand all Loading... |
467 playout_done = true; | 469 playout_done = true; |
468 | 470 |
469 return recording_done && playout_done; | 471 return recording_done && playout_done; |
470 } | 472 } |
471 | 473 |
472 bool play_mode() const { return type_ & kPlayout; } | 474 bool play_mode() const { return type_ & kPlayout; } |
473 bool rec_mode() const { return type_ & kRecording; } | 475 bool rec_mode() const { return type_ & kRecording; } |
474 | 476 |
475 private: | 477 private: |
476 EventWrapper* test_is_done_; | 478 EventWrapper* test_is_done_; |
477 int num_callbacks_; | 479 size_t num_callbacks_; |
478 int type_; | 480 int type_; |
479 int play_count_; | 481 size_t play_count_; |
480 int rec_count_; | 482 size_t rec_count_; |
481 AudioStreamInterface* audio_stream_; | 483 AudioStreamInterface* audio_stream_; |
482 }; | 484 }; |
483 | 485 |
484 // AudioDeviceTest test fixture. | 486 // AudioDeviceTest test fixture. |
485 class AudioDeviceTest : public ::testing::Test { | 487 class AudioDeviceTest : public ::testing::Test { |
486 protected: | 488 protected: |
487 AudioDeviceTest() : test_is_done_(EventWrapper::Create()) { | 489 AudioDeviceTest() : test_is_done_(EventWrapper::Create()) { |
488 old_sev_ = rtc::LogMessage::GetLogToDebug(); | 490 old_sev_ = rtc::LogMessage::GetLogToDebug(); |
489 // Set suitable logging level here. Change to rtc::LS_INFO for more verbose | 491 // Set suitable logging level here. Change to rtc::LS_INFO for more verbose |
490 // output. See webrtc/base/logging.h for complete list of options. | 492 // output. See webrtc/base/logging.h for complete list of options. |
(...skipping 12 matching lines...) Expand all Loading... |
503 virtual ~AudioDeviceTest() { | 505 virtual ~AudioDeviceTest() { |
504 EXPECT_EQ(0, audio_device_->Terminate()); | 506 EXPECT_EQ(0, audio_device_->Terminate()); |
505 rtc::LogMessage::LogToDebug(old_sev_); | 507 rtc::LogMessage::LogToDebug(old_sev_); |
506 } | 508 } |
507 | 509 |
508 // TODO(henrika): don't use hardcoded values below. | 510 // TODO(henrika): don't use hardcoded values below. |
509 int playout_sample_rate() const { return playout_parameters_.sample_rate(); } | 511 int playout_sample_rate() const { return playout_parameters_.sample_rate(); } |
510 int record_sample_rate() const { return record_parameters_.sample_rate(); } | 512 int record_sample_rate() const { return record_parameters_.sample_rate(); } |
511 int playout_channels() const { return playout_parameters_.channels(); } | 513 int playout_channels() const { return playout_parameters_.channels(); } |
512 int record_channels() const { return record_parameters_.channels(); } | 514 int record_channels() const { return record_parameters_.channels(); } |
513 int playout_frames_per_10ms_buffer() const { | 515 size_t playout_frames_per_10ms_buffer() const { |
514 return playout_parameters_.frames_per_10ms_buffer(); | 516 return playout_parameters_.frames_per_10ms_buffer(); |
515 } | 517 } |
516 int record_frames_per_10ms_buffer() const { | 518 size_t record_frames_per_10ms_buffer() const { |
517 return record_parameters_.frames_per_10ms_buffer(); | 519 return record_parameters_.frames_per_10ms_buffer(); |
518 } | 520 } |
519 | 521 |
520 int total_delay_ms() const { | 522 int total_delay_ms() const { |
521 // TODO(henrika): improve this part. | 523 // TODO(henrika): improve this part. |
522 return 100; | 524 return 100; |
523 } | 525 } |
524 | 526 |
525 rtc::scoped_refptr<AudioDeviceModule> audio_device() const { | 527 rtc::scoped_refptr<AudioDeviceModule> audio_device() const { |
526 return audio_device_; | 528 return audio_device_; |
(...skipping 18 matching lines...) Expand all Loading... |
545 std::string GetFileName(int sample_rate) { | 547 std::string GetFileName(int sample_rate) { |
546 EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100 || | 548 EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100 || |
547 sample_rate == 16000); | 549 sample_rate == 16000); |
548 char fname[64]; | 550 char fname[64]; |
549 snprintf(fname, sizeof(fname), "audio_device/audio_short%d", | 551 snprintf(fname, sizeof(fname), "audio_device/audio_short%d", |
550 sample_rate / 1000); | 552 sample_rate / 1000); |
551 std::string file_name(webrtc::test::ResourcePath(fname, "pcm")); | 553 std::string file_name(webrtc::test::ResourcePath(fname, "pcm")); |
552 EXPECT_TRUE(test::FileExists(file_name)); | 554 EXPECT_TRUE(test::FileExists(file_name)); |
553 #ifdef ENABLE_DEBUG_PRINTF | 555 #ifdef ENABLE_DEBUG_PRINTF |
554 PRINTD("file name: %s\n", file_name.c_str()); | 556 PRINTD("file name: %s\n", file_name.c_str()); |
555 const int bytes = test::GetFileSize(file_name); | 557 const size_t bytes = test::GetFileSize(file_name); |
556 PRINTD("file size: %d [bytes]\n", bytes); | 558 PRINTD("file size: %" PRIuS " [bytes]\n", bytes); |
557 PRINTD("file size: %d [samples]\n", bytes / kBytesPerSample); | 559 PRINTD("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample); |
558 const int seconds = bytes / (sample_rate * kBytesPerSample); | 560 const int seconds = |
| 561 static_cast<int>(bytes / (sample_rate * kBytesPerSample)); |
559 PRINTD("file size: %d [secs]\n", seconds); | 562 PRINTD("file size: %d [secs]\n", seconds); |
560 PRINTD("file size: %d [callbacks]\n", seconds * kNumCallbacksPerSecond); | 563 PRINTD("file size: %" PRIuS " [callbacks]\n", |
| 564 seconds * kNumCallbacksPerSecond); |
561 #endif | 565 #endif |
562 return file_name; | 566 return file_name; |
563 } | 567 } |
564 | 568 |
565 void StartPlayout() { | 569 void StartPlayout() { |
566 EXPECT_FALSE(audio_device()->PlayoutIsInitialized()); | 570 EXPECT_FALSE(audio_device()->PlayoutIsInitialized()); |
567 EXPECT_FALSE(audio_device()->Playing()); | 571 EXPECT_FALSE(audio_device()->Playing()); |
568 EXPECT_EQ(0, audio_device()->InitPlayout()); | 572 EXPECT_EQ(0, audio_device()->InitPlayout()); |
569 EXPECT_TRUE(audio_device()->PlayoutIsInitialized()); | 573 EXPECT_TRUE(audio_device()->PlayoutIsInitialized()); |
570 EXPECT_EQ(0, audio_device()->StartPlayout()); | 574 EXPECT_EQ(0, audio_device()->StartPlayout()); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 std::max(kTestTimeOutInMilliseconds, 1000 * kMeasureLatencyTimeInSec)); | 783 std::max(kTestTimeOutInMilliseconds, 1000 * kMeasureLatencyTimeInSec)); |
780 StopPlayout(); | 784 StopPlayout(); |
781 StopRecording(); | 785 StopRecording(); |
782 // Verify that the correct number of transmitted impulses are detected. | 786 // Verify that the correct number of transmitted impulses are detected. |
783 EXPECT_EQ(latency_audio_stream->num_latency_values(), | 787 EXPECT_EQ(latency_audio_stream->num_latency_values(), |
784 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1); | 788 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1); |
785 latency_audio_stream->PrintResults(); | 789 latency_audio_stream->PrintResults(); |
786 } | 790 } |
787 | 791 |
788 } // namespace webrtc | 792 } // namespace webrtc |
OLD | NEW |