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