audio_android_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/basictypes.h"
6#include "base/file_util.h"
7#include "base/memory/scoped_ptr.h"
8#include "base/message_loop/message_loop.h"
9#include "base/path_service.h"
10#include "base/strings/stringprintf.h"
11#include "base/synchronization/lock.h"
12#include "base/synchronization/waitable_event.h"
13#include "base/test/test_timeouts.h"
14#include "base/time/time.h"
15#include "build/build_config.h"
16#include "media/audio/android/audio_manager_android.h"
17#include "media/audio/audio_io.h"
18#include "media/audio/audio_manager_base.h"
19#include "media/base/decoder_buffer.h"
20#include "media/base/seekable_buffer.h"
21#include "media/base/test_data_util.h"
22#include "testing/gmock/include/gmock/gmock.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25using ::testing::_;
26using ::testing::AtLeast;
27using ::testing::DoAll;
28using ::testing::Invoke;
29using ::testing::NotNull;
30using ::testing::Return;
31
32namespace media {
33
34ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
35  if (++*count >= limit) {
36    loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
37  }
38}
39
40static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
41static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw";
42static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
43static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw";
44
45static const float kCallbackTestTimeMs = 2000.0;
46static const int kBitsPerSample = 16;
47static const int kBytesPerSample = kBitsPerSample / 8;
48
49// Converts AudioParameters::Format enumerator to readable string.
50static std::string FormatToString(AudioParameters::Format format) {
51  switch (format) {
52    case AudioParameters::AUDIO_PCM_LINEAR:
53      return std::string("AUDIO_PCM_LINEAR");
54    case AudioParameters::AUDIO_PCM_LOW_LATENCY:
55      return std::string("AUDIO_PCM_LOW_LATENCY");
56    case AudioParameters::AUDIO_FAKE:
57      return std::string("AUDIO_FAKE");
58    case AudioParameters::AUDIO_LAST_FORMAT:
59      return std::string("AUDIO_LAST_FORMAT");
60    default:
61      return std::string();
62  }
63}
64
65// Converts ChannelLayout enumerator to readable string. Does not include
66// multi-channel cases since these layouts are not supported on Android.
67static std::string LayoutToString(ChannelLayout channel_layout) {
68  switch (channel_layout) {
69    case CHANNEL_LAYOUT_NONE:
70      return std::string("CHANNEL_LAYOUT_NONE");
71    case CHANNEL_LAYOUT_MONO:
72      return std::string("CHANNEL_LAYOUT_MONO");
73    case CHANNEL_LAYOUT_STEREO:
74      return std::string("CHANNEL_LAYOUT_STEREO");
75    case CHANNEL_LAYOUT_UNSUPPORTED:
76    default:
77      return std::string("CHANNEL_LAYOUT_UNSUPPORTED");
78  }
79}
80
81static double ExpectedTimeBetweenCallbacks(AudioParameters params) {
82  return (base::TimeDelta::FromMicroseconds(
83              params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
84              static_cast<double>(params.sample_rate()))).InMillisecondsF();
85}
86
87std::ostream& operator<<(std::ostream& os, const AudioParameters& params) {
88  using namespace std;
89  os << endl << "format: " << FormatToString(params.format()) << endl
90     << "channel layout: " << LayoutToString(params.channel_layout()) << endl
91     << "sample rate: " << params.sample_rate() << endl
92     << "bits per sample: " << params.bits_per_sample() << endl
93     << "frames per buffer: " << params.frames_per_buffer() << endl
94     << "channels: " << params.channels() << endl
95     << "bytes per buffer: " << params.GetBytesPerBuffer() << endl
96     << "bytes per second: " << params.GetBytesPerSecond() << endl
97     << "bytes per frame: " << params.GetBytesPerFrame() << endl
98     << "frame size in ms: " << ExpectedTimeBetweenCallbacks(params);
99  return os;
100}
101
102// Gmock implementation of AudioInputStream::AudioInputCallback.
103class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
104 public:
105  MOCK_METHOD5(OnData,
106               void(AudioInputStream* stream,
107                    const uint8* src,
108                    uint32 size,
109                    uint32 hardware_delay_bytes,
110                    double volume));
111  MOCK_METHOD1(OnClose, void(AudioInputStream* stream));
112  MOCK_METHOD1(OnError, void(AudioInputStream* stream));
113};
114
115// Gmock implementation of AudioOutputStream::AudioSourceCallback.
116class MockAudioOutputCallback : public AudioOutputStream::AudioSourceCallback {
117 public:
118  MOCK_METHOD2(OnMoreData,
119               int(AudioBus* dest, AudioBuffersState buffers_state));
120  MOCK_METHOD3(OnMoreIOData,
121               int(AudioBus* source,
122                   AudioBus* dest,
123                   AudioBuffersState buffers_state));
124  MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
125
126  // We clear the data bus to ensure that the test does not cause noise.
127  int RealOnMoreData(AudioBus* dest, AudioBuffersState buffers_state) {
128    dest->Zero();
129    return dest->frames();
130  }
131};
132
133// Implements AudioOutputStream::AudioSourceCallback and provides audio data
134// by reading from a data file.
135class FileAudioSource : public AudioOutputStream::AudioSourceCallback {
136 public:
137  explicit FileAudioSource(base::WaitableEvent* event, const std::string& name)
138      : event_(event), pos_(0) {
139    // Reads a test file from media/test/data directory and stores it in
140    // a DecoderBuffer.
141    file_ = ReadTestDataFile(name);
142
143    // Log the name of the file which is used as input for this test.
144    base::FilePath file_path = GetTestDataFilePath(name);
145    LOG(INFO) << "Reading from file: " << file_path.value().c_str();
146  }
147
148  virtual ~FileAudioSource() {}
149
150  // AudioOutputStream::AudioSourceCallback implementation.
151
152  // Use samples read from a data file and fill up the audio buffer
153  // provided to us in the callback.
154  virtual int OnMoreData(AudioBus* audio_bus,
155                         AudioBuffersState buffers_state) OVERRIDE {
156    bool stop_playing = false;
157    int max_size =
158        audio_bus->frames() * audio_bus->channels() * kBytesPerSample;
159
160    // Adjust data size and prepare for end signal if file has ended.
161    if (pos_ + max_size > file_size()) {
162      stop_playing = true;
163      max_size = file_size() - pos_;
164    }
165
166    // File data is stored as interleaved 16-bit values. Copy data samples from
167    // the file and deinterleave to match the audio bus format.
168    // FromInterleaved() will zero out any unfilled frames when there is not
169    // sufficient data remaining in the file to fill up the complete frame.
170    int frames = max_size / (audio_bus->channels() * kBytesPerSample);
171    if (max_size) {
172      audio_bus->FromInterleaved(file_->data() + pos_, frames, kBytesPerSample);
173      pos_ += max_size;
174    }
175
176    // Set event to ensure that the test can stop when the file has ended.
177    if (stop_playing)
178      event_->Signal();
179
180    return frames;
181  }
182
183  virtual int OnMoreIOData(AudioBus* source,
184                           AudioBus* dest,
185                           AudioBuffersState buffers_state) OVERRIDE {
186    NOTREACHED();
187    return 0;
188  }
189
190  virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
191
192  int file_size() { return file_->data_size(); }
193
194 private:
195  base::WaitableEvent* event_;
196  int pos_;
197  scoped_refptr<DecoderBuffer> file_;
198
199  DISALLOW_COPY_AND_ASSIGN(FileAudioSource);
200};
201
202// Implements AudioInputStream::AudioInputCallback and writes the recorded
203// audio data to a local output file. Note that this implementation should
204// only be used for manually invoked and evaluated tests, hence the created
205// file will not be destroyed after the test is done since the intention is
206// that it shall be available for off-line analysis.
207class FileAudioSink : public AudioInputStream::AudioInputCallback {
208 public:
209  explicit FileAudioSink(base::WaitableEvent* event,
210                         const AudioParameters& params,
211                         const std::string& file_name)
212      : event_(event), params_(params) {
213    // Allocate space for ~10 seconds of data.
214    const int kMaxBufferSize = 10 * params.GetBytesPerSecond();
215    buffer_.reset(new media::SeekableBuffer(0, kMaxBufferSize));
216
217    // Open up the binary file which will be written to in the destructor.
218    base::FilePath file_path;
219    EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
220    file_path = file_path.AppendASCII(file_name.c_str());
221    binary_file_ = file_util::OpenFile(file_path, "wb");
222    DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
223    LOG(INFO) << "Writing to file: " << file_path.value().c_str();
224  }
225
226  virtual ~FileAudioSink() {
227    int bytes_written = 0;
228    while (bytes_written < buffer_->forward_capacity()) {
229      const uint8* chunk;
230      int chunk_size;
231
232      // Stop writing if no more data is available.
233      if (!buffer_->GetCurrentChunk(&chunk, &chunk_size))
234        break;
235
236      // Write recorded data chunk to the file and prepare for next chunk.
237      // TODO(henrika): use file_util:: instead.
238      fwrite(chunk, 1, chunk_size, binary_file_);
239      buffer_->Seek(chunk_size);
240      bytes_written += chunk_size;
241    }
242    file_util::CloseFile(binary_file_);
243  }
244
245  // AudioInputStream::AudioInputCallback implementation.
246  virtual void OnData(AudioInputStream* stream,
247                      const uint8* src,
248                      uint32 size,
249                      uint32 hardware_delay_bytes,
250                      double volume) OVERRIDE {
251    // Store data data in a temporary buffer to avoid making blocking
252    // fwrite() calls in the audio callback. The complete buffer will be
253    // written to file in the destructor.
254    if (!buffer_->Append(src, size))
255      event_->Signal();
256  }
257
258  virtual void OnClose(AudioInputStream* stream) OVERRIDE {}
259  virtual void OnError(AudioInputStream* stream) OVERRIDE {}
260
261 private:
262  base::WaitableEvent* event_;
263  AudioParameters params_;
264  scoped_ptr<media::SeekableBuffer> buffer_;
265  FILE* binary_file_;
266
267  DISALLOW_COPY_AND_ASSIGN(FileAudioSink);
268};
269
270// Implements AudioInputCallback and AudioSourceCallback to support full
271// duplex audio where captured samples are played out in loopback after
272// reading from a temporary FIFO storage.
273class FullDuplexAudioSinkSource
274    : public AudioInputStream::AudioInputCallback,
275      public AudioOutputStream::AudioSourceCallback {
276 public:
277  explicit FullDuplexAudioSinkSource(const AudioParameters& params)
278      : params_(params),
279        previous_time_(base::TimeTicks::Now()),
280        started_(false) {
281    // Start with a reasonably small FIFO size. It will be increased
282    // dynamically during the test if required.
283    fifo_.reset(new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer()));
284    buffer_.reset(new uint8[params_.GetBytesPerBuffer()]);
285  }
286
287  virtual ~FullDuplexAudioSinkSource() {}
288
289  // AudioInputStream::AudioInputCallback implementation
290  virtual void OnData(AudioInputStream* stream,
291                      const uint8* src,
292                      uint32 size,
293                      uint32 hardware_delay_bytes,
294                      double volume) OVERRIDE {
295    const base::TimeTicks now_time = base::TimeTicks::Now();
296    const int diff = (now_time - previous_time_).InMilliseconds();
297
298    base::AutoLock lock(lock_);
299    if (diff > 1000) {
300      started_ = true;
301      previous_time_ = now_time;
302
303      // Log out the extra delay added by the FIFO. This is a best effort
304      // estimate. We might be +- 10ms off here.
305      int extra_fifo_delay =
306          static_cast<int>(BytesToMilliseconds(fifo_->forward_bytes() + size));
307      DVLOG(1) << extra_fifo_delay;
308    }
309
310    // We add an initial delay of ~1 second before loopback starts to ensure
311    // a stable callback sequence and to avoid initial bursts which might add
312    // to the extra FIFO delay.
313    if (!started_)
314      return;
315
316    // Append new data to the FIFO and extend the size if the max capacity
317    // was exceeded. Flush the FIFO when extended just in case.
318    if (!fifo_->Append(src, size)) {
319      fifo_->set_forward_capacity(2 * fifo_->forward_capacity());
320      fifo_->Clear();
321    }
322  }
323
324  virtual void OnClose(AudioInputStream* stream) OVERRIDE {}
325  virtual void OnError(AudioInputStream* stream) OVERRIDE {}
326
327  // AudioOutputStream::AudioSourceCallback implementation
328  virtual int OnMoreData(AudioBus* dest,
329                         AudioBuffersState buffers_state) OVERRIDE {
330    const int size_in_bytes =
331        (params_.bits_per_sample() / 8) * dest->frames() * dest->channels();
332    EXPECT_EQ(size_in_bytes, params_.GetBytesPerBuffer());
333
334    base::AutoLock lock(lock_);
335
336    // We add an initial delay of ~1 second before loopback starts to ensure
337    // a stable callback sequences and to avoid initial bursts which might add
338    // to the extra FIFO delay.
339    if (!started_) {
340      dest->Zero();
341      return dest->frames();
342    }
343
344    // Fill up destination with zeros if the FIFO does not contain enough
345    // data to fulfill the request.
346    if (fifo_->forward_bytes() < size_in_bytes) {
347      dest->Zero();
348    } else {
349      fifo_->Read(buffer_.get(), size_in_bytes);
350      dest->FromInterleaved(
351          buffer_.get(), dest->frames(), params_.bits_per_sample() / 8);
352    }
353
354    return dest->frames();
355  }
356
357  virtual int OnMoreIOData(AudioBus* source,
358                           AudioBus* dest,
359                           AudioBuffersState buffers_state) OVERRIDE {
360    NOTREACHED();
361    return 0;
362  }
363
364  virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
365
366 private:
367  // Converts from bytes to milliseconds given number of bytes and existing
368  // audio parameters.
369  double BytesToMilliseconds(int bytes) const {
370    const int frames = bytes / params_.GetBytesPerFrame();
371    return (base::TimeDelta::FromMicroseconds(
372                frames * base::Time::kMicrosecondsPerSecond /
373                static_cast<double>(params_.sample_rate()))).InMillisecondsF();
374  }
375
376  AudioParameters params_;
377  base::TimeTicks previous_time_;
378  base::Lock lock_;
379  scoped_ptr<media::SeekableBuffer> fifo_;
380  scoped_ptr<uint8[]> buffer_;
381  bool started_;
382
383  DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource);
384};
385
386// Test fixture class.
387class AudioAndroidTest : public testing::Test {
388 public:
389  AudioAndroidTest() {}
390
391 protected:
392  virtual void SetUp() {
393    audio_manager_.reset(AudioManager::Create());
394    loop_.reset(new base::MessageLoopForUI());
395  }
396
397  virtual void TearDown() {}
398
399  AudioManager* audio_manager() { return audio_manager_.get(); }
400  base::MessageLoopForUI* loop() { return loop_.get(); }
401
402  AudioParameters GetDefaultInputStreamParameters() {
403    return audio_manager()->GetInputStreamParameters(
404        AudioManagerBase::kDefaultDeviceId);
405  }
406
407  AudioParameters GetDefaultOutputStreamParameters() {
408    return audio_manager()->GetDefaultOutputStreamParameters();
409  }
410
411  double AverageTimeBetweenCallbacks(int num_callbacks) const {
412    return ((end_time_ - start_time_) / static_cast<double>(num_callbacks - 1))
413        .InMillisecondsF();
414  }
415
416  void StartInputStreamCallbacks(const AudioParameters& params) {
417    double expected_time_between_callbacks_ms =
418        ExpectedTimeBetweenCallbacks(params);
419    const int num_callbacks =
420        (kCallbackTestTimeMs / expected_time_between_callbacks_ms);
421    AudioInputStream* stream = audio_manager()->MakeAudioInputStream(
422        params, AudioManagerBase::kDefaultDeviceId);
423    EXPECT_TRUE(stream);
424
425    int count = 0;
426    MockAudioInputCallback sink;
427
428    EXPECT_CALL(sink,
429                OnData(stream, NotNull(), params.GetBytesPerBuffer(), _, _))
430        .Times(AtLeast(num_callbacks))
431        .WillRepeatedly(
432             CheckCountAndPostQuitTask(&count, num_callbacks, loop()));
433    EXPECT_CALL(sink, OnError(stream)).Times(0);
434    EXPECT_CALL(sink, OnClose(stream)).Times(1);
435
436    EXPECT_TRUE(stream->Open());
437    stream->Start(&sink);
438    start_time_ = base::TimeTicks::Now();
439    loop()->Run();
440    end_time_ = base::TimeTicks::Now();
441    stream->Stop();
442    stream->Close();
443
444    double average_time_between_callbacks_ms =
445        AverageTimeBetweenCallbacks(num_callbacks);
446    LOG(INFO) << "expected time between callbacks: "
447              << expected_time_between_callbacks_ms << " ms";
448    LOG(INFO) << "average time between callbacks: "
449              << average_time_between_callbacks_ms << " ms";
450    EXPECT_GE(average_time_between_callbacks_ms,
451              0.70 * expected_time_between_callbacks_ms);
452    EXPECT_LE(average_time_between_callbacks_ms,
453              1.30 * expected_time_between_callbacks_ms);
454  }
455
456  void StartOutputStreamCallbacks(const AudioParameters& params) {
457    double expected_time_between_callbacks_ms =
458        ExpectedTimeBetweenCallbacks(params);
459    const int num_callbacks =
460        (kCallbackTestTimeMs / expected_time_between_callbacks_ms);
461    AudioOutputStream* stream = audio_manager()->MakeAudioOutputStream(
462        params, std::string(), std::string());
463    EXPECT_TRUE(stream);
464
465    int count = 0;
466    MockAudioOutputCallback source;
467
468    EXPECT_CALL(source, OnMoreData(NotNull(), _))
469        .Times(AtLeast(num_callbacks))
470        .WillRepeatedly(
471             DoAll(CheckCountAndPostQuitTask(&count, num_callbacks, loop()),
472                   Invoke(&source, &MockAudioOutputCallback::RealOnMoreData)));
473    EXPECT_CALL(source, OnError(stream)).Times(0);
474    EXPECT_CALL(source, OnMoreIOData(_, _, _)).Times(0);
475
476    EXPECT_TRUE(stream->Open());
477    stream->Start(&source);
478    start_time_ = base::TimeTicks::Now();
479    loop()->Run();
480    end_time_ = base::TimeTicks::Now();
481    stream->Stop();
482    stream->Close();
483
484    double average_time_between_callbacks_ms =
485        AverageTimeBetweenCallbacks(num_callbacks);
486    LOG(INFO) << "expected time between callbacks: "
487              << expected_time_between_callbacks_ms << " ms";
488    LOG(INFO) << "average time between callbacks: "
489              << average_time_between_callbacks_ms << " ms";
490    EXPECT_GE(average_time_between_callbacks_ms,
491              0.70 * expected_time_between_callbacks_ms);
492    EXPECT_LE(average_time_between_callbacks_ms,
493              1.30 * expected_time_between_callbacks_ms);
494  }
495
496  scoped_ptr<base::MessageLoopForUI> loop_;
497  scoped_ptr<AudioManager> audio_manager_;
498  base::TimeTicks start_time_;
499  base::TimeTicks end_time_;
500
501  DISALLOW_COPY_AND_ASSIGN(AudioAndroidTest);
502};
503
504// Get the default audio input parameters and log the result.
505TEST_F(AudioAndroidTest, GetInputStreamParameters) {
506  AudioParameters params = GetDefaultInputStreamParameters();
507  EXPECT_TRUE(params.IsValid());
508  VLOG(1) << params;
509}
510
511// Get the default audio output parameters and log the result.
512TEST_F(AudioAndroidTest, GetDefaultOutputStreamParameters) {
513  AudioParameters params = GetDefaultOutputStreamParameters();
514  EXPECT_TRUE(params.IsValid());
515  VLOG(1) << params;
516}
517
518// Check if low-latency output is supported and log the result as output.
519TEST_F(AudioAndroidTest, IsAudioLowLatencySupported) {
520  AudioManagerAndroid* manager =
521      static_cast<AudioManagerAndroid*>(audio_manager());
522  bool low_latency = manager->IsAudioLowLatencySupported();
523  low_latency ? LOG(INFO) << "Low latency output is supported"
524              : LOG(INFO) << "Low latency output is *not* supported";
525}
526
527// Ensure that a default input stream can be created and closed.
528TEST_F(AudioAndroidTest, CreateAndCloseInputStream) {
529  AudioParameters params = GetDefaultInputStreamParameters();
530  AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
531      params, AudioManagerBase::kDefaultDeviceId);
532  EXPECT_TRUE(ais);
533  ais->Close();
534}
535
536// Ensure that a default output stream can be created and closed.
537// TODO(henrika): should we also verify that this API changes the audio mode
538// to communication mode, and calls RegisterHeadsetReceiver, the first time
539// it is called?
540TEST_F(AudioAndroidTest, CreateAndCloseOutputStream) {
541  AudioParameters params = GetDefaultOutputStreamParameters();
542  AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
543      params, std::string(), std::string());
544  EXPECT_TRUE(aos);
545  aos->Close();
546}
547
548// Ensure that a default input stream can be opened and closed.
549TEST_F(AudioAndroidTest, OpenAndCloseInputStream) {
550  AudioParameters params = GetDefaultInputStreamParameters();
551  AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
552      params, AudioManagerBase::kDefaultDeviceId);
553  EXPECT_TRUE(ais);
554  EXPECT_TRUE(ais->Open());
555  ais->Close();
556}
557
558// Ensure that a default output stream can be opened and closed.
559TEST_F(AudioAndroidTest, OpenAndCloseOutputStream) {
560  AudioParameters params = GetDefaultOutputStreamParameters();
561  AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
562      params, std::string(), std::string());
563  EXPECT_TRUE(aos);
564  EXPECT_TRUE(aos->Open());
565  aos->Close();
566}
567
568// Start input streaming using default input parameters and ensure that the
569// callback sequence is sane.
570TEST_F(AudioAndroidTest, StartInputStreamCallbacks) {
571  AudioParameters params = GetDefaultInputStreamParameters();
572  StartInputStreamCallbacks(params);
573}
574
575// Start input streaming using non default input parameters and ensure that the
576// callback sequence is sane. The only change we make in this test is to select
577// a 10ms buffer size instead of the default size.
578// TODO(henrika): possibly add support for more variations.
579TEST_F(AudioAndroidTest, StartInputStreamCallbacksNonDefaultParameters) {
580  AudioParameters native_params = GetDefaultInputStreamParameters();
581  AudioParameters params(native_params.format(),
582                         native_params.channel_layout(),
583                         native_params.sample_rate(),
584                         native_params.bits_per_sample(),
585                         native_params.sample_rate() / 100);
586  StartInputStreamCallbacks(params);
587}
588
589// Start output streaming using default output parameters and ensure that the
590// callback sequence is sane.
591TEST_F(AudioAndroidTest, StartOutputStreamCallbacks) {
592  AudioParameters params = GetDefaultOutputStreamParameters();
593  StartOutputStreamCallbacks(params);
594}
595
596// Start output streaming using non default output parameters and ensure that
597// the callback sequence is sane. The only change we make in this test is to
598// select a 10ms buffer size instead of the default size and to open up the
599// device in mono.
600// TODO(henrika): possibly add support for more variations.
601TEST_F(AudioAndroidTest, StartOutputStreamCallbacksNonDefaultParameters) {
602  AudioParameters native_params = GetDefaultOutputStreamParameters();
603  AudioParameters params(native_params.format(),
604                         CHANNEL_LAYOUT_MONO,
605                         native_params.sample_rate(),
606                         native_params.bits_per_sample(),
607                         native_params.sample_rate() / 100);
608  StartOutputStreamCallbacks(params);
609}
610
611// Play out a PCM file segment in real time and allow the user to verify that
612// the rendered audio sounds OK.
613// NOTE: this test requires user interaction and is not designed to run as an
614// automatized test on bots.
615TEST_F(AudioAndroidTest, DISABLED_RunOutputStreamWithFileAsSource) {
616  AudioParameters params = GetDefaultOutputStreamParameters();
617  VLOG(1) << params;
618  AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
619      params, std::string(), std::string());
620  EXPECT_TRUE(aos);
621
622  std::string file_name;
623  if (params.sample_rate() == 48000 && params.channels() == 2) {
624    file_name = kSpeechFile_16b_s_48k;
625  } else if (params.sample_rate() == 48000 && params.channels() == 1) {
626    file_name = kSpeechFile_16b_m_48k;
627  } else if (params.sample_rate() == 44100 && params.channels() == 2) {
628    file_name = kSpeechFile_16b_s_44k;
629  } else if (params.sample_rate() == 44100 && params.channels() == 1) {
630    file_name = kSpeechFile_16b_m_44k;
631  } else {
632    FAIL() << "This test supports 44.1kHz and 48kHz mono/stereo only.";
633    return;
634  }
635
636  base::WaitableEvent event(false, false);
637  FileAudioSource source(&event, file_name);
638
639  EXPECT_TRUE(aos->Open());
640  aos->SetVolume(1.0);
641  aos->Start(&source);
642  LOG(INFO) << ">> Verify that the file is played out correctly...";
643  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
644  aos->Stop();
645  aos->Close();
646}
647
648// Start input streaming and run it for ten seconds while recording to a
649// local audio file.
650// NOTE: this test requires user interaction and is not designed to run as an
651// automatized test on bots.
652TEST_F(AudioAndroidTest, DISABLED_RunSimplexInputStreamWithFileAsSink) {
653  AudioParameters params = GetDefaultInputStreamParameters();
654  VLOG(1) << params;
655  AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
656      params, AudioManagerBase::kDefaultDeviceId);
657  EXPECT_TRUE(ais);
658
659  std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm",
660                                             params.sample_rate(),
661                                             params.frames_per_buffer(),
662                                             params.channels());
663
664  base::WaitableEvent event(false, false);
665  FileAudioSink sink(&event, params, file_name);
666
667  EXPECT_TRUE(ais->Open());
668  ais->Start(&sink);
669  LOG(INFO) << ">> Speak into the microphone to record audio...";
670  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
671  ais->Stop();
672  ais->Close();
673}
674
675// Same test as RunSimplexInputStreamWithFileAsSink but this time output
676// streaming is active as well (reads zeros only).
677// NOTE: this test requires user interaction and is not designed to run as an
678// automatized test on bots.
679TEST_F(AudioAndroidTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
680  AudioParameters in_params = GetDefaultInputStreamParameters();
681  AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
682      in_params, AudioManagerBase::kDefaultDeviceId);
683  EXPECT_TRUE(ais);
684
685  AudioParameters out_params =
686      audio_manager()->GetDefaultOutputStreamParameters();
687  AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
688      out_params, std::string(), std::string());
689  EXPECT_TRUE(aos);
690
691  std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
692                                             in_params.sample_rate(),
693                                             in_params.frames_per_buffer(),
694                                             in_params.channels());
695
696  base::WaitableEvent event(false, false);
697  FileAudioSink sink(&event, in_params, file_name);
698  MockAudioOutputCallback source;
699
700  EXPECT_CALL(source, OnMoreData(NotNull(), _)).WillRepeatedly(
701      Invoke(&source, &MockAudioOutputCallback::RealOnMoreData));
702  EXPECT_CALL(source, OnError(aos)).Times(0);
703  EXPECT_CALL(source, OnMoreIOData(_, _, _)).Times(0);
704
705  EXPECT_TRUE(ais->Open());
706  EXPECT_TRUE(aos->Open());
707  ais->Start(&sink);
708  aos->Start(&source);
709  LOG(INFO) << ">> Speak into the microphone to record audio";
710  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
711  aos->Stop();
712  ais->Stop();
713  aos->Close();
714  ais->Close();
715}
716
717// Start audio in both directions while feeding captured data into a FIFO so
718// it can be read directly (in loopback) by the render side. A small extra
719// delay will be added by the FIFO and an estimate of this delay will be
720// printed out during the test.
721// NOTE: this test requires user interaction and is not designed to run as an
722// automatized test on bots.
723TEST_F(AudioAndroidTest,
724       DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) {
725  // Get native audio parameters for the input side.
726  AudioParameters default_input_params = GetDefaultInputStreamParameters();
727
728  // Modify the parameters so that both input and output can use the same
729  // parameters by selecting 10ms as buffer size. This will also ensure that
730  // the output stream will be a mono stream since mono is default for input
731  // audio on Android.
732  AudioParameters io_params(default_input_params.format(),
733                            default_input_params.channel_layout(),
734                            default_input_params.sample_rate(),
735                            default_input_params.bits_per_sample(),
736                            default_input_params.sample_rate() / 100);
737  VLOG(1) << io_params;
738
739  // Create input and output streams using the common audio parameters.
740  AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
741      io_params, AudioManagerBase::kDefaultDeviceId);
742  EXPECT_TRUE(ais);
743  AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
744      io_params, std::string(), std::string());
745  EXPECT_TRUE(aos);
746
747  FullDuplexAudioSinkSource full_duplex(io_params);
748
749  // Start a full duplex audio session and print out estimates of the extra
750  // delay we should expect from the FIFO. If real-time delay measurements are
751  // performed, the result should be reduced by this extra delay since it is
752  // something that has been added by the test.
753  EXPECT_TRUE(ais->Open());
754  EXPECT_TRUE(aos->Open());
755  ais->Start(&full_duplex);
756  aos->Start(&full_duplex);
757  VLOG(1) << "HINT: an estimate of the extra FIFO delay will be updated "
758          << "once per second during this test.";
759  LOG(INFO) << ">> Speak into the mic and listen to the audio in loopback...";
760  fflush(stdout);
761  base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
762  printf("\n");
763  aos->Stop();
764  ais->Stop();
765  aos->Close();
766  ais->Close();
767}
768
769}  // namespace media
770