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