1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <list>
12 #include <numeric>
13
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webrtc/base/criticalsection.h"
17 #include "webrtc/base/scoped_ptr.h"
18 #include "webrtc/modules/audio_device/android/ensure_initialized.h"
19 #include "webrtc/modules/audio_device/audio_device_impl.h"
20 #include "webrtc/modules/audio_device/include/audio_device.h"
21 #include "webrtc/system_wrappers/interface/clock.h"
22 #include "webrtc/system_wrappers/interface/event_wrapper.h"
23 #include "webrtc/system_wrappers/interface/scoped_refptr.h"
24 #include "webrtc/system_wrappers/interface/sleep.h"
25 #include "webrtc/test/testsupport/fileutils.h"
26
27 using std::cout;
28 using std::endl;
29 using ::testing::_;
30 using ::testing::AtLeast;
31 using ::testing::Gt;
32 using ::testing::Invoke;
33 using ::testing::NiceMock;
34 using ::testing::NotNull;
35 using ::testing::Return;
36 using ::testing::TestWithParam;
37
38 // #define ENABLE_DEBUG_PRINTF
39 #ifdef ENABLE_DEBUG_PRINTF
40 #define PRINTD(...) fprintf(stderr, __VA_ARGS__);
41 #else
42 #define PRINTD(...) ((void)0)
43 #endif
44 #define PRINT(...) fprintf(stderr, __VA_ARGS__);
45
46 namespace webrtc {
47
48 // Perform all tests for the different audio layers listed in this array.
49 // See the INSTANTIATE_TEST_CASE_P statement for details.
50 // TODO(henrika): the test framework supports both Java and OpenSL ES based
51 // audio backends but there are currently some issues (crashes) in the
52 // OpenSL ES implementation, hence it is not added to kAudioLayers yet.
53 static const AudioDeviceModule::AudioLayer kAudioLayers[] = {
54 AudioDeviceModule::kAndroidJavaAudio
55 /*, AudioDeviceModule::kAndroidOpenSLESAudio */};
56 // Number of callbacks (input or output) the tests waits for before we set
57 // an event indicating that the test was OK.
58 static const int kNumCallbacks = 10;
59 // Max amount of time we wait for an event to be set while counting callbacks.
60 static const int kTestTimeOutInMilliseconds = 10 * 1000;
61 // Average number of audio callbacks per second assuming 10ms packet size.
62 static const int kNumCallbacksPerSecond = 100;
63 // Play out a test file during this time (unit is in seconds).
64 static const int kFilePlayTimeInSec = 5;
65 // Fixed value for the recording delay using Java based audio backend.
66 // TODO(henrika): harmonize with OpenSL ES and look for possible improvements.
67 static const uint32_t kFixedRecordingDelay = 100;
68 static const int kBitsPerSample = 16;
69 static const int kBytesPerSample = kBitsPerSample / 8;
70 // Run the full-duplex test during this time (unit is in seconds).
71 // Note that first |kNumIgnoreFirstCallbacks| are ignored.
72 static const int kFullDuplexTimeInSec = 5;
73 // Wait for the callback sequence to stabilize by ignoring this amount of the
74 // initial callbacks (avoids initial FIFO access).
75 // Only used in the RunPlayoutAndRecordingInFullDuplex test.
76 static const int kNumIgnoreFirstCallbacks = 50;
77 // Sets the number of impulses per second in the latency test.
78 static const int kImpulseFrequencyInHz = 1;
79 // Length of round-trip latency measurements. Number of transmitted impulses
80 // is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1.
81 static const int kMeasureLatencyTimeInSec = 11;
82 // Utilized in round-trip latency measurements to avoid capturing noise samples.
83 static const int kImpulseThreshold = 500;
84 static const char kTag[] = "[..........] ";
85
86 enum TransportType {
87 kPlayout = 0x1,
88 kRecording = 0x2,
89 };
90
91 // Simple helper struct for device specific audio parameters.
92 struct AudioParameters {
playout_frames_per_bufferwebrtc::AudioParameters93 int playout_frames_per_buffer() const {
94 return playout_sample_rate / 100; // WebRTC uses 10 ms as buffer size.
95 }
recording_frames_per_bufferwebrtc::AudioParameters96 int recording_frames_per_buffer() const {
97 return recording_sample_rate / 100;
98 }
99 int playout_sample_rate;
100 int recording_sample_rate;
101 int playout_channels;
102 int recording_channels;
103 };
104
105 // Interface for processing the audio stream. Real implementations can e.g.
106 // run audio in loopback, read audio from a file or perform latency
107 // measurements.
108 class AudioStreamInterface {
109 public:
110 virtual void Write(const void* source, int num_frames) = 0;
111 virtual void Read(void* destination, int num_frames) = 0;
112 protected:
~AudioStreamInterface()113 virtual ~AudioStreamInterface() {}
114 };
115
116 // Reads audio samples from a PCM file where the file is stored in memory at
117 // construction.
118 class FileAudioStream : public AudioStreamInterface {
119 public:
FileAudioStream(int num_callbacks,const std::string & file_name,int sample_rate)120 FileAudioStream(
121 int num_callbacks, const std::string& file_name, int sample_rate)
122 : file_size_in_bytes_(0),
123 sample_rate_(sample_rate),
124 file_pos_(0) {
125 file_size_in_bytes_ = test::GetFileSize(file_name);
126 sample_rate_ = sample_rate;
127 EXPECT_GE(file_size_in_callbacks(), num_callbacks)
128 << "Size of test file is not large enough to last during the test.";
129 const int num_16bit_samples =
130 test::GetFileSize(file_name) / kBytesPerSample;
131 file_.reset(new int16_t[num_16bit_samples]);
132 FILE* audio_file = fopen(file_name.c_str(), "rb");
133 EXPECT_NE(audio_file, nullptr);
134 int num_samples_read = fread(
135 file_.get(), sizeof(int16_t), num_16bit_samples, audio_file);
136 EXPECT_EQ(num_samples_read, num_16bit_samples);
137 fclose(audio_file);
138 }
139
140 // AudioStreamInterface::Write() is not implemented.
Write(const void * source,int num_frames)141 virtual void Write(const void* source, int num_frames) override {}
142
143 // Read samples from file stored in memory (at construction) and copy
144 // |num_frames| (<=> 10ms) to the |destination| byte buffer.
Read(void * destination,int num_frames)145 virtual void Read(void* destination, int num_frames) override {
146 memcpy(destination,
147 static_cast<int16_t*> (&file_[file_pos_]),
148 num_frames * sizeof(int16_t));
149 file_pos_ += num_frames;
150 }
151
file_size_in_seconds() const152 int file_size_in_seconds() const {
153 return (file_size_in_bytes_ / (kBytesPerSample * sample_rate_));
154 }
file_size_in_callbacks() const155 int file_size_in_callbacks() const {
156 return file_size_in_seconds() * kNumCallbacksPerSecond;
157 }
158
159 private:
160 int file_size_in_bytes_;
161 int sample_rate_;
162 rtc::scoped_ptr<int16_t[]> file_;
163 int file_pos_;
164 };
165
166 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio
167 // buffers of fixed size and allows Write and Read operations. The idea is to
168 // store recorded audio buffers (using Write) and then read (using Read) these
169 // stored buffers with as short delay as possible when the audio layer needs
170 // data to play out. The number of buffers in the FIFO will stabilize under
171 // normal conditions since there will be a balance between Write and Read calls.
172 // The container is a std::list container and access is protected with a lock
173 // since both sides (playout and recording) are driven by its own thread.
174 class FifoAudioStream : public AudioStreamInterface {
175 public:
FifoAudioStream(int frames_per_buffer)176 explicit FifoAudioStream(int frames_per_buffer)
177 : frames_per_buffer_(frames_per_buffer),
178 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
179 fifo_(new AudioBufferList),
180 largest_size_(0),
181 total_written_elements_(0),
182 write_count_(0) {
183 EXPECT_NE(fifo_.get(), nullptr);
184 }
185
~FifoAudioStream()186 ~FifoAudioStream() {
187 Flush();
188 PRINTD("[%4.3f]\n", average_size());
189 }
190
191 // Allocate new memory, copy |num_frames| samples from |source| into memory
192 // and add pointer to the memory location to end of the list.
193 // Increases the size of the FIFO by one element.
Write(const void * source,int num_frames)194 virtual void Write(const void* source, int num_frames) override {
195 ASSERT_EQ(num_frames, frames_per_buffer_);
196 PRINTD("+");
197 if (write_count_++ < kNumIgnoreFirstCallbacks) {
198 return;
199 }
200 int16_t* memory = new int16_t[frames_per_buffer_];
201 memcpy(static_cast<int16_t*> (&memory[0]),
202 source,
203 bytes_per_buffer_);
204 rtc::CritScope lock(&lock_);
205 fifo_->push_back(memory);
206 const int size = fifo_->size();
207 if (size > largest_size_) {
208 largest_size_ = size;
209 PRINTD("(%d)", largest_size_);
210 }
211 total_written_elements_ += size;
212 }
213
214 // Read pointer to data buffer from front of list, copy |num_frames| of stored
215 // data into |destination| and delete the utilized memory allocation.
216 // Decreases the size of the FIFO by one element.
Read(void * destination,int num_frames)217 virtual void Read(void* destination, int num_frames) override {
218 ASSERT_EQ(num_frames, frames_per_buffer_);
219 PRINTD("-");
220 rtc::CritScope lock(&lock_);
221 if (fifo_->empty()) {
222 memset(destination, 0, bytes_per_buffer_);
223 } else {
224 int16_t* memory = fifo_->front();
225 fifo_->pop_front();
226 memcpy(destination,
227 static_cast<int16_t*> (&memory[0]),
228 bytes_per_buffer_);
229 delete memory;
230 }
231 }
232
size() const233 int size() const {
234 return fifo_->size();
235 }
236
largest_size() const237 int largest_size() const {
238 return largest_size_;
239 }
240
average_size() const241 int average_size() const {
242 return (total_written_elements_ == 0) ? 0.0 : 0.5 + static_cast<float> (
243 total_written_elements_) / (write_count_ - kNumIgnoreFirstCallbacks);
244 }
245
246 private:
Flush()247 void Flush() {
248 for (auto it = fifo_->begin(); it != fifo_->end(); ++it) {
249 delete *it;
250 }
251 fifo_->clear();
252 }
253
254 using AudioBufferList = std::list<int16_t*>;
255 rtc::CriticalSection lock_;
256 const int frames_per_buffer_;
257 const int bytes_per_buffer_;
258 rtc::scoped_ptr<AudioBufferList> fifo_;
259 int largest_size_;
260 int total_written_elements_;
261 int write_count_;
262 };
263
264 // Inserts periodic impulses and measures the latency between the time of
265 // transmission and time of receiving the same impulse.
266 // Usage requires a special hardware called Audio Loopback Dongle.
267 // See http://source.android.com/devices/audio/loopback.html for details.
268 class LatencyMeasuringAudioStream : public AudioStreamInterface {
269 public:
LatencyMeasuringAudioStream(int frames_per_buffer)270 explicit LatencyMeasuringAudioStream(int frames_per_buffer)
271 : clock_(Clock::GetRealTimeClock()),
272 frames_per_buffer_(frames_per_buffer),
273 bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
274 play_count_(0),
275 rec_count_(0),
276 pulse_time_(0) {
277 }
278
279 // Insert periodic impulses in first two samples of |destination|.
Read(void * destination,int num_frames)280 virtual void Read(void* destination, int num_frames) override {
281 ASSERT_EQ(num_frames, frames_per_buffer_);
282 if (play_count_ == 0) {
283 PRINT("[");
284 }
285 play_count_++;
286 memset(destination, 0, bytes_per_buffer_);
287 if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) {
288 if (pulse_time_ == 0) {
289 pulse_time_ = clock_->TimeInMilliseconds();
290 }
291 PRINT(".");
292 const int16_t impulse = std::numeric_limits<int16_t>::max();
293 int16_t* ptr16 = static_cast<int16_t*> (destination);
294 for (int i = 0; i < 2; ++i) {
295 *ptr16++ = impulse;
296 }
297 }
298 }
299
300 // Detect received impulses in |source|, derive time between transmission and
301 // detection and add the calculated delay to list of latencies.
Write(const void * source,int num_frames)302 virtual void Write(const void* source, int num_frames) override {
303 ASSERT_EQ(num_frames, frames_per_buffer_);
304 rec_count_++;
305 if (pulse_time_ == 0) {
306 // Avoid detection of new impulse response until a new impulse has
307 // been transmitted (sets |pulse_time_| to value larger than zero).
308 return;
309 }
310 const int16_t* ptr16 = static_cast<const int16_t*> (source);
311 std::vector<int16_t> vec(ptr16, ptr16 + num_frames);
312 // Find max value in the audio buffer.
313 int max = *std::max_element(vec.begin(), vec.end());
314 // Find index (element position in vector) of the max element.
315 int index_of_max = std::distance(vec.begin(),
316 std::find(vec.begin(), vec.end(),
317 max));
318 if (max > kImpulseThreshold) {
319 PRINTD("(%d,%d)", max, index_of_max);
320 int64_t now_time = clock_->TimeInMilliseconds();
321 int extra_delay = IndexToMilliseconds(static_cast<double> (index_of_max));
322 PRINTD("[%d]", static_cast<int> (now_time - pulse_time_));
323 PRINTD("[%d]", extra_delay);
324 // Total latency is the difference between transmit time and detection
325 // tome plus the extra delay within the buffer in which we detected the
326 // received impulse. It is transmitted at sample 0 but can be received
327 // at sample N where N > 0. The term |extra_delay| accounts for N and it
328 // is a value between 0 and 10ms.
329 latencies_.push_back(now_time - pulse_time_ + extra_delay);
330 pulse_time_ = 0;
331 } else {
332 PRINTD("-");
333 }
334 }
335
num_latency_values() const336 int num_latency_values() const {
337 return latencies_.size();
338 }
339
min_latency() const340 int min_latency() const {
341 if (latencies_.empty())
342 return 0;
343 return *std::min_element(latencies_.begin(), latencies_.end());
344 }
345
max_latency() const346 int max_latency() const {
347 if (latencies_.empty())
348 return 0;
349 return *std::max_element(latencies_.begin(), latencies_.end());
350 }
351
average_latency() const352 int average_latency() const {
353 if (latencies_.empty())
354 return 0;
355 return 0.5 + static_cast<double> (
356 std::accumulate(latencies_.begin(), latencies_.end(), 0)) /
357 latencies_.size();
358 }
359
PrintResults() const360 void PrintResults() const {
361 PRINT("] ");
362 for (auto it = latencies_.begin(); it != latencies_.end(); ++it) {
363 PRINT("%d ", *it);
364 }
365 PRINT("\n");
366 PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag,
367 min_latency(), max_latency(), average_latency());
368 }
369
IndexToMilliseconds(double index) const370 int IndexToMilliseconds(double index) const {
371 return 10.0 * (index / frames_per_buffer_) + 0.5;
372 }
373
374 private:
375 Clock* clock_;
376 const int frames_per_buffer_;
377 const int bytes_per_buffer_;
378 int play_count_;
379 int rec_count_;
380 int64_t pulse_time_;
381 std::vector<int> latencies_;
382 };
383
384 // Mocks the AudioTransport object and proxies actions for the two callbacks
385 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations
386 // of AudioStreamInterface.
387 class MockAudioTransport : public AudioTransport {
388 public:
MockAudioTransport(int type)389 explicit MockAudioTransport(int type)
390 : num_callbacks_(0),
391 type_(type),
392 play_count_(0),
393 rec_count_(0),
394 audio_stream_(nullptr) {}
395
~MockAudioTransport()396 virtual ~MockAudioTransport() {}
397
398 MOCK_METHOD10(RecordedDataIsAvailable,
399 int32_t(const void* audioSamples,
400 const uint32_t nSamples,
401 const uint8_t nBytesPerSample,
402 const uint8_t nChannels,
403 const uint32_t samplesPerSec,
404 const uint32_t totalDelayMS,
405 const int32_t clockDrift,
406 const uint32_t currentMicLevel,
407 const bool keyPressed,
408 uint32_t& newMicLevel));
409 MOCK_METHOD8(NeedMorePlayData,
410 int32_t(const uint32_t nSamples,
411 const uint8_t nBytesPerSample,
412 const uint8_t nChannels,
413 const uint32_t samplesPerSec,
414 void* audioSamples,
415 uint32_t& nSamplesOut,
416 int64_t* elapsed_time_ms,
417 int64_t* ntp_time_ms));
418
419 // Set default actions of the mock object. We are delegating to fake
420 // implementations (of AudioStreamInterface) here.
HandleCallbacks(EventWrapper * test_is_done,AudioStreamInterface * audio_stream,int num_callbacks)421 void HandleCallbacks(EventWrapper* test_is_done,
422 AudioStreamInterface* audio_stream,
423 int num_callbacks) {
424 test_is_done_ = test_is_done;
425 audio_stream_ = audio_stream;
426 num_callbacks_ = num_callbacks;
427 if (play_mode()) {
428 ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _))
429 .WillByDefault(
430 Invoke(this, &MockAudioTransport::RealNeedMorePlayData));
431 }
432 if (rec_mode()) {
433 ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _))
434 .WillByDefault(
435 Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable));
436 }
437 }
438
RealRecordedDataIsAvailable(const void * audioSamples,const uint32_t nSamples,const uint8_t nBytesPerSample,const uint8_t nChannels,const uint32_t samplesPerSec,const uint32_t totalDelayMS,const int32_t clockDrift,const uint32_t currentMicLevel,const bool keyPressed,uint32_t & newMicLevel)439 int32_t RealRecordedDataIsAvailable(const void* audioSamples,
440 const uint32_t nSamples,
441 const uint8_t nBytesPerSample,
442 const uint8_t nChannels,
443 const uint32_t samplesPerSec,
444 const uint32_t totalDelayMS,
445 const int32_t clockDrift,
446 const uint32_t currentMicLevel,
447 const bool keyPressed,
448 uint32_t& newMicLevel) {
449 EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks.";
450 rec_count_++;
451 // Process the recorded audio stream if an AudioStreamInterface
452 // implementation exists.
453 if (audio_stream_) {
454 audio_stream_->Write(audioSamples, nSamples);
455 }
456 if (ReceivedEnoughCallbacks()) {
457 test_is_done_->Set();
458 }
459 return 0;
460 }
461
RealNeedMorePlayData(const uint32_t nSamples,const uint8_t nBytesPerSample,const uint8_t nChannels,const uint32_t samplesPerSec,void * audioSamples,uint32_t & nSamplesOut,int64_t * elapsed_time_ms,int64_t * ntp_time_ms)462 int32_t RealNeedMorePlayData(const uint32_t nSamples,
463 const uint8_t nBytesPerSample,
464 const uint8_t nChannels,
465 const uint32_t samplesPerSec,
466 void* audioSamples,
467 uint32_t& nSamplesOut,
468 int64_t* elapsed_time_ms,
469 int64_t* ntp_time_ms) {
470 EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks.";
471 play_count_++;
472 nSamplesOut = nSamples;
473 // Read (possibly processed) audio stream samples to be played out if an
474 // AudioStreamInterface implementation exists.
475 if (audio_stream_) {
476 audio_stream_->Read(audioSamples, nSamples);
477 }
478 if (ReceivedEnoughCallbacks()) {
479 test_is_done_->Set();
480 }
481 return 0;
482 }
483
ReceivedEnoughCallbacks()484 bool ReceivedEnoughCallbacks() {
485 bool recording_done = false;
486 if (rec_mode())
487 recording_done = rec_count_ >= num_callbacks_;
488 else
489 recording_done = true;
490
491 bool playout_done = false;
492 if (play_mode())
493 playout_done = play_count_ >= num_callbacks_;
494 else
495 playout_done = true;
496
497 return recording_done && playout_done;
498 }
499
play_mode() const500 bool play_mode() const { return type_ & kPlayout; }
rec_mode() const501 bool rec_mode() const { return type_ & kRecording; }
502
503 private:
504 EventWrapper* test_is_done_;
505 int num_callbacks_;
506 int type_;
507 int play_count_;
508 int rec_count_;
509 AudioStreamInterface* audio_stream_;
510 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream_;
511 };
512
513 // AudioDeviceTest is a value-parameterized test.
514 class AudioDeviceTest
515 : public testing::TestWithParam<AudioDeviceModule::AudioLayer> {
516 protected:
AudioDeviceTest()517 AudioDeviceTest()
518 : test_is_done_(EventWrapper::Create()) {
519 // One-time initialization of JVM and application context. Ensures that we
520 // can do calls between C++ and Java. Initializes both Java and OpenSL ES
521 // implementations.
522 webrtc::audiodevicemodule::EnsureInitialized();
523 // Creates an audio device based on the test parameter. See
524 // INSTANTIATE_TEST_CASE_P() for details.
525 audio_device_ = CreateAudioDevice();
526 EXPECT_NE(audio_device_.get(), nullptr);
527 EXPECT_EQ(0, audio_device_->Init());
528 CacheAudioParameters();
529 }
~AudioDeviceTest()530 virtual ~AudioDeviceTest() {
531 EXPECT_EQ(0, audio_device_->Terminate());
532 }
533
playout_sample_rate() const534 int playout_sample_rate() const {
535 return parameters_.playout_sample_rate;
536 }
recording_sample_rate() const537 int recording_sample_rate() const {
538 return parameters_.recording_sample_rate;
539 }
playout_channels() const540 int playout_channels() const {
541 return parameters_.playout_channels;
542 }
recording_channels() const543 int recording_channels() const {
544 return parameters_.playout_channels;
545 }
playout_frames_per_buffer() const546 int playout_frames_per_buffer() const {
547 return parameters_.playout_frames_per_buffer();
548 }
recording_frames_per_buffer() const549 int recording_frames_per_buffer() const {
550 return parameters_.recording_frames_per_buffer();
551 }
552
audio_device() const553 scoped_refptr<AudioDeviceModule> audio_device() const {
554 return audio_device_;
555 }
556
CreateAudioDevice()557 scoped_refptr<AudioDeviceModule> CreateAudioDevice() {
558 scoped_refptr<AudioDeviceModule> module(
559 AudioDeviceModuleImpl::Create(0, GetParam()));
560 return module;
561 }
562
CacheAudioParameters()563 void CacheAudioParameters() {
564 AudioDeviceBuffer* audio_buffer =
565 static_cast<AudioDeviceModuleImpl*> (
566 audio_device_.get())->GetAudioDeviceBuffer();
567 parameters_.playout_sample_rate = audio_buffer->PlayoutSampleRate();
568 parameters_.recording_sample_rate = audio_buffer->RecordingSampleRate();
569 parameters_.playout_channels = audio_buffer->PlayoutChannels();
570 parameters_.recording_channels = audio_buffer->RecordingChannels();
571 }
572
573 // Returns file name relative to the resource root given a sample rate.
GetFileName(int sample_rate)574 std::string GetFileName(int sample_rate) {
575 EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100);
576 char fname[64];
577 snprintf(fname,
578 sizeof(fname),
579 "audio_device/audio_short%d",
580 sample_rate / 1000);
581 std::string file_name(webrtc::test::ResourcePath(fname, "pcm"));
582 EXPECT_TRUE(test::FileExists(file_name));
583 #ifdef ENABLE_PRINTF
584 PRINT("file name: %s\n", file_name.c_str());
585 const int bytes = test::GetFileSize(file_name);
586 PRINT("file size: %d [bytes]\n", bytes);
587 PRINT("file size: %d [samples]\n", bytes / kBytesPerSample);
588 const int seconds = bytes / (sample_rate * kBytesPerSample);
589 PRINT("file size: %d [secs]\n", seconds);
590 PRINT("file size: %d [callbacks]\n", seconds * kNumCallbacksPerSecond);
591 #endif
592 return file_name;
593 }
594
SetMaxPlayoutVolume()595 void SetMaxPlayoutVolume() {
596 uint32_t max_volume;
597 EXPECT_EQ(0, audio_device()->MaxSpeakerVolume(&max_volume));
598 EXPECT_EQ(0, audio_device()->SetSpeakerVolume(max_volume));
599 }
600
StartPlayout()601 void StartPlayout() {
602 EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
603 EXPECT_FALSE(audio_device()->Playing());
604 EXPECT_EQ(0, audio_device()->InitPlayout());
605 EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
606 EXPECT_EQ(0, audio_device()->StartPlayout());
607 EXPECT_TRUE(audio_device()->Playing());
608 }
609
StopPlayout()610 void StopPlayout() {
611 EXPECT_EQ(0, audio_device()->StopPlayout());
612 EXPECT_FALSE(audio_device()->Playing());
613 }
614
StartRecording()615 void StartRecording() {
616 EXPECT_FALSE(audio_device()->RecordingIsInitialized());
617 EXPECT_FALSE(audio_device()->Recording());
618 EXPECT_EQ(0, audio_device()->InitRecording());
619 EXPECT_TRUE(audio_device()->RecordingIsInitialized());
620 EXPECT_EQ(0, audio_device()->StartRecording());
621 EXPECT_TRUE(audio_device()->Recording());
622 }
623
StopRecording()624 void StopRecording() {
625 EXPECT_EQ(0, audio_device()->StopRecording());
626 EXPECT_FALSE(audio_device()->Recording());
627 }
628
GetMaxSpeakerVolume() const629 int GetMaxSpeakerVolume() const {
630 uint32_t max_volume(0);
631 EXPECT_EQ(0, audio_device()->MaxSpeakerVolume(&max_volume));
632 return max_volume;
633 }
634
GetMinSpeakerVolume() const635 int GetMinSpeakerVolume() const {
636 uint32_t min_volume(0);
637 EXPECT_EQ(0, audio_device()->MinSpeakerVolume(&min_volume));
638 return min_volume;
639 }
640
GetSpeakerVolume() const641 int GetSpeakerVolume() const {
642 uint32_t volume(0);
643 EXPECT_EQ(0, audio_device()->SpeakerVolume(&volume));
644 return volume;
645 }
646
647 rtc::scoped_ptr<EventWrapper> test_is_done_;
648 scoped_refptr<AudioDeviceModule> audio_device_;
649 AudioParameters parameters_;
650 };
651
TEST_P(AudioDeviceTest,ConstructDestruct)652 TEST_P(AudioDeviceTest, ConstructDestruct) {
653 // Using the test fixture to create and destruct the audio device module.
654 }
655
656 // Create an audio device instance and print out the native audio parameters.
TEST_P(AudioDeviceTest,AudioParameters)657 TEST_P(AudioDeviceTest, AudioParameters) {
658 EXPECT_NE(0, playout_sample_rate());
659 PRINT("%splayout_sample_rate: %d\n", kTag, playout_sample_rate());
660 EXPECT_NE(0, recording_sample_rate());
661 PRINT("%srecording_sample_rate: %d\n", kTag, recording_sample_rate());
662 EXPECT_NE(0, playout_channels());
663 PRINT("%splayout_channels: %d\n", kTag, playout_channels());
664 EXPECT_NE(0, recording_channels());
665 PRINT("%srecording_channels: %d\n", kTag, recording_channels());
666 }
667
TEST_P(AudioDeviceTest,InitTerminate)668 TEST_P(AudioDeviceTest, InitTerminate) {
669 // Initialization is part of the test fixture.
670 EXPECT_TRUE(audio_device()->Initialized());
671 EXPECT_EQ(0, audio_device()->Terminate());
672 EXPECT_FALSE(audio_device()->Initialized());
673 }
674
TEST_P(AudioDeviceTest,Devices)675 TEST_P(AudioDeviceTest, Devices) {
676 // Device enumeration is not supported. Verify fixed values only.
677 EXPECT_EQ(1, audio_device()->PlayoutDevices());
678 EXPECT_EQ(1, audio_device()->RecordingDevices());
679 }
680
TEST_P(AudioDeviceTest,BuiltInAECIsAvailable)681 TEST_P(AudioDeviceTest, BuiltInAECIsAvailable) {
682 PRINT("%sBuiltInAECIsAvailable: %s\n",
683 kTag, audio_device()->BuiltInAECIsAvailable() ? "true" : "false");
684 }
685
TEST_P(AudioDeviceTest,SpeakerVolumeShouldBeAvailable)686 TEST_P(AudioDeviceTest, SpeakerVolumeShouldBeAvailable) {
687 bool available;
688 EXPECT_EQ(0, audio_device()->SpeakerVolumeIsAvailable(&available));
689 EXPECT_TRUE(available);
690 }
691
TEST_P(AudioDeviceTest,MaxSpeakerVolumeIsPositive)692 TEST_P(AudioDeviceTest, MaxSpeakerVolumeIsPositive) {
693 EXPECT_GT(GetMaxSpeakerVolume(), 0);
694 }
695
TEST_P(AudioDeviceTest,MinSpeakerVolumeIsZero)696 TEST_P(AudioDeviceTest, MinSpeakerVolumeIsZero) {
697 EXPECT_EQ(GetMinSpeakerVolume(), 0);
698 }
699
TEST_P(AudioDeviceTest,DefaultSpeakerVolumeIsWithinMinMax)700 TEST_P(AudioDeviceTest, DefaultSpeakerVolumeIsWithinMinMax) {
701 const int default_volume = GetSpeakerVolume();
702 EXPECT_GE(default_volume, GetMinSpeakerVolume());
703 EXPECT_LE(default_volume, GetMaxSpeakerVolume());
704 }
705
TEST_P(AudioDeviceTest,SetSpeakerVolumeActuallySetsVolume)706 TEST_P(AudioDeviceTest, SetSpeakerVolumeActuallySetsVolume) {
707 const int default_volume = GetSpeakerVolume();
708 const int max_volume = GetMaxSpeakerVolume();
709 EXPECT_EQ(0, audio_device()->SetSpeakerVolume(max_volume));
710 int new_volume = GetSpeakerVolume();
711 EXPECT_EQ(new_volume, max_volume);
712 EXPECT_EQ(0, audio_device()->SetSpeakerVolume(default_volume));
713 }
714
715 // Tests that playout can be initiated, started and stopped.
TEST_P(AudioDeviceTest,StartStopPlayout)716 TEST_P(AudioDeviceTest, StartStopPlayout) {
717 StartPlayout();
718 StopPlayout();
719 }
720
721 // Start playout and verify that the native audio layer starts asking for real
722 // audio samples to play out using the NeedMorePlayData callback.
TEST_P(AudioDeviceTest,StartPlayoutVerifyCallbacks)723 TEST_P(AudioDeviceTest, StartPlayoutVerifyCallbacks) {
724 MockAudioTransport mock(kPlayout);
725 mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
726 EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_buffer(),
727 kBytesPerSample,
728 playout_channels(),
729 playout_sample_rate(),
730 NotNull(),
731 _, _, _))
732 .Times(AtLeast(kNumCallbacks));
733 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
734 StartPlayout();
735 test_is_done_->Wait(kTestTimeOutInMilliseconds);
736 StopPlayout();
737 }
738
739 // Start recording and verify that the native audio layer starts feeding real
740 // audio samples via the RecordedDataIsAvailable callback.
TEST_P(AudioDeviceTest,StartRecordingVerifyCallbacks)741 TEST_P(AudioDeviceTest, StartRecordingVerifyCallbacks) {
742 MockAudioTransport mock(kRecording);
743 mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
744 EXPECT_CALL(mock, RecordedDataIsAvailable(NotNull(),
745 recording_frames_per_buffer(),
746 kBytesPerSample,
747 recording_channels(),
748 recording_sample_rate(),
749 kFixedRecordingDelay,
750 0,
751 0,
752 false,
753 _))
754 .Times(AtLeast(kNumCallbacks));
755
756 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
757 StartRecording();
758 test_is_done_->Wait(kTestTimeOutInMilliseconds);
759 StopRecording();
760 }
761
762
763 // Start playout and recording (full-duplex audio) and verify that audio is
764 // active in both directions.
TEST_P(AudioDeviceTest,StartPlayoutAndRecordingVerifyCallbacks)765 TEST_P(AudioDeviceTest, StartPlayoutAndRecordingVerifyCallbacks) {
766 MockAudioTransport mock(kPlayout | kRecording);
767 mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
768 EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_buffer(),
769 kBytesPerSample,
770 playout_channels(),
771 playout_sample_rate(),
772 NotNull(),
773 _, _, _))
774 .Times(AtLeast(kNumCallbacks));
775 EXPECT_CALL(mock, RecordedDataIsAvailable(NotNull(),
776 recording_frames_per_buffer(),
777 kBytesPerSample,
778 recording_channels(),
779 recording_sample_rate(),
780 Gt(kFixedRecordingDelay),
781 0,
782 0,
783 false,
784 _))
785 .Times(AtLeast(kNumCallbacks));
786 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
787 StartPlayout();
788 StartRecording();
789 test_is_done_->Wait(kTestTimeOutInMilliseconds);
790 StopRecording();
791 StopPlayout();
792 }
793
794 // Start playout and read audio from an external PCM file when the audio layer
795 // asks for data to play out. Real audio is played out in this test but it does
796 // not contain any explicit verification that the audio quality is perfect.
TEST_P(AudioDeviceTest,RunPlayoutWithFileAsSource)797 TEST_P(AudioDeviceTest, RunPlayoutWithFileAsSource) {
798 // TODO(henrika): extend test when mono output is supported.
799 EXPECT_EQ(1, playout_channels());
800 NiceMock<MockAudioTransport> mock(kPlayout);
801 const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond;
802 std::string file_name = GetFileName(playout_sample_rate());
803 rtc::scoped_ptr<FileAudioStream> file_audio_stream(
804 new FileAudioStream(num_callbacks, file_name, playout_sample_rate()));
805 mock.HandleCallbacks(test_is_done_.get(),
806 file_audio_stream.get(),
807 num_callbacks);
808 SetMaxPlayoutVolume();
809 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
810 StartPlayout();
811 test_is_done_->Wait(kTestTimeOutInMilliseconds);
812 StopPlayout();
813 }
814
815 // Start playout and recording and store recorded data in an intermediate FIFO
816 // buffer from which the playout side then reads its samples in the same order
817 // as they were stored. Under ideal circumstances, a callback sequence would
818 // look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-'
819 // means 'packet played'. Under such conditions, the FIFO would only contain
820 // one packet on average. However, under more realistic conditions, the size
821 // of the FIFO will vary more due to an unbalance between the two sides.
822 // This test tries to verify that the device maintains a balanced callback-
823 // sequence by running in loopback for ten seconds while measuring the size
824 // (max and average) of the FIFO. The size of the FIFO is increased by the
825 // recording side and decreased by the playout side.
826 // TODO(henrika): tune the final test parameters after running tests on several
827 // different devices.
TEST_P(AudioDeviceTest,RunPlayoutAndRecordingInFullDuplex)828 TEST_P(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) {
829 EXPECT_EQ(recording_channels(), playout_channels());
830 EXPECT_EQ(recording_sample_rate(), playout_sample_rate());
831 NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
832 rtc::scoped_ptr<FifoAudioStream> fifo_audio_stream(
833 new FifoAudioStream(playout_frames_per_buffer()));
834 mock.HandleCallbacks(test_is_done_.get(),
835 fifo_audio_stream.get(),
836 kFullDuplexTimeInSec * kNumCallbacksPerSecond);
837 SetMaxPlayoutVolume();
838 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
839 StartRecording();
840 StartPlayout();
841 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds,
842 1000 * kFullDuplexTimeInSec));
843 StopPlayout();
844 StopRecording();
845 EXPECT_LE(fifo_audio_stream->average_size(), 10);
846 EXPECT_LE(fifo_audio_stream->largest_size(), 20);
847 }
848
849 // Measures loopback latency and reports the min, max and average values for
850 // a full duplex audio session.
851 // The latency is measured like so:
852 // - Insert impulses periodically on the output side.
853 // - Detect the impulses on the input side.
854 // - Measure the time difference between the transmit time and receive time.
855 // - Store time differences in a vector and calculate min, max and average.
856 // This test requires a special hardware called Audio Loopback Dongle.
857 // See http://source.android.com/devices/audio/loopback.html for details.
TEST_P(AudioDeviceTest,DISABLED_MeasureLoopbackLatency)858 TEST_P(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) {
859 EXPECT_EQ(recording_channels(), playout_channels());
860 EXPECT_EQ(recording_sample_rate(), playout_sample_rate());
861 NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
862 rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream(
863 new LatencyMeasuringAudioStream(playout_frames_per_buffer()));
864 mock.HandleCallbacks(test_is_done_.get(),
865 latency_audio_stream.get(),
866 kMeasureLatencyTimeInSec * kNumCallbacksPerSecond);
867 EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
868 SetMaxPlayoutVolume();
869 StartRecording();
870 StartPlayout();
871 test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds,
872 1000 * kMeasureLatencyTimeInSec));
873 StopPlayout();
874 StopRecording();
875 // Verify that the correct number of transmitted impulses are detected.
876 EXPECT_EQ(latency_audio_stream->num_latency_values(),
877 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1);
878 latency_audio_stream->PrintResults();
879 }
880
881 INSTANTIATE_TEST_CASE_P(AudioDeviceTest, AudioDeviceTest,
882 ::testing::ValuesIn(kAudioLayers));
883
884 } // namespace webrtc
885