Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: media/audio/android/audio_android_unittest.cc

Issue 23296008: Adding audio unit tests for Android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fixed includes Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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/gtest/include/gtest/gtest.h"
23
24 namespace media {
25
26 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
27 static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw";
28 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
29 static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw";
30
31 static const int kBitsPerSample = 16;
32 static const int kBytesPerSample = kBitsPerSample / 8;
33
34 // Implements AudioInputCallback and AudioSourceCallback with some trivial
35 // additional counting support to keep track of the number of callbacks,
36 // number or error callbacks etc. It also allows the user to set an expected
37 // number of callbacks, in any direction, before a provided event is signaled.
38 class MockAudioInputOutputCallbacks
DaleCurtis 2013/09/05 20:35:23 This seems like it could all be done much more cle
henrika (OOO until Aug 14) 2013/09/06 15:59:51 I feel that this approach gives me more flexibilit
DaleCurtis 2013/09/06 22:05:07 By choosing to manual mock objects you're increasi
39 : public AudioInputStream::AudioInputCallback,
40 public AudioOutputStream::AudioSourceCallback {
41 public:
42 MockAudioInputOutputCallbacks() {
43 Reset();
44 };
45 virtual ~MockAudioInputOutputCallbacks() {};
46
47 // Implementation of AudioInputCallback.
48 virtual void OnData(AudioInputStream* stream, const uint8* src,
49 uint32 size, uint32 hardware_delay_bytes,
50 double volume) OVERRIDE {
51 UpdateCountersAndSignalWhenDone(kInput);
52 };
53
54 virtual void OnError(AudioInputStream* stream) OVERRIDE {
55 errors_[kInput]++;
56 }
57
58 virtual void OnClose(AudioInputStream* stream) OVERRIDE {}
59
60 // Implementation of AudioSourceCallback.
61 virtual int OnMoreData(AudioBus* dest,
62 AudioBuffersState buffers_state) OVERRIDE {
63 UpdateCountersAndSignalWhenDone(kOutput);
64 dest->Zero();
65 return dest->frames();
66 }
67
68 virtual int OnMoreIOData(AudioBus* source,
69 AudioBus* dest,
70 AudioBuffersState buffers_state) OVERRIDE {
71 NOTREACHED();
72 return 0;
73 }
74
75 virtual void OnError(AudioOutputStream* stream) OVERRIDE {
76 errors_[kOutput]++;
77 }
78
79 void Reset() {
80 for (int i = 0; i < 2; ++i) {
81 callbacks_[i] = 0;
82 callback_limit_[i] = -1;
83 errors_[i] = 0;
84 }
85 }
86
87 int input_callbacks() { return callbacks_[kInput]; }
88
89 void set_input_callback_limit(base::WaitableEvent* event,
90 int input_callback_limit) {
91 event_[kInput] = event;
92 callback_limit_[kInput] = input_callback_limit;
93 }
94
95 int input_errors() { return errors_[kInput]; }
96
97 base::TimeTicks input_start_time() { return start_time_[kInput]; }
98
99 base::TimeTicks input_end_time() { return end_time_[kInput]; }
100
101 int output_callbacks() { return callbacks_[kOutput]; }
102
103 void set_output_callback_limit(base::WaitableEvent* event,
104 int output_callback_limit) {
105 event_[kOutput] = event;
106 callback_limit_[kOutput] = output_callback_limit;
107 }
108
109 int output_errors() { return errors_[kOutput]; }
110
111 base::TimeTicks output_start_time() { return start_time_[kOutput]; }
112
113 base::TimeTicks output_end_time() { return end_time_[kOutput]; }
114
115 double average_time_between_input_callbacks_ms() {
116 return ((input_end_time() - input_start_time()) /
117 (input_callbacks() - 1)).InMillisecondsF();
118 }
119
120 double average_time_between_output_callbacks_ms() {
121 return ((output_end_time() - output_start_time()) /
122 (output_callbacks() - 1)).InMillisecondsF();
123 }
124
125 private:
126 void UpdateCountersAndSignalWhenDone(int dir) {
127 if (callbacks_[dir] == 0)
128 start_time_[dir] = base::TimeTicks::Now();
129 callbacks_[dir]++;
130 if (callback_limit_[dir] > 0 &&
131 callbacks_[dir] == callback_limit_[dir]) {
132 end_time_[dir] = base::TimeTicks::Now();
133 event_[dir]->Signal();
134 }
135 }
136
137 enum {
138 kInput = 0,
139 kOutput = 1
140 };
141
142 int callbacks_[2];
143 int callback_limit_[2];
144 int errors_[2];
145 base::TimeTicks start_time_[2];
146 base::TimeTicks end_time_[2];
147 base::WaitableEvent* event_[2];
148
149 DISALLOW_COPY_AND_ASSIGN(MockAudioInputOutputCallbacks);
150 };
151
152 // Implements AudioOutputStream::AudioSourceCallback and provides audio data
153 // by reading from a data file.
154 class FileAudioSource : public AudioOutputStream::AudioSourceCallback {
155 public:
156 explicit FileAudioSource(base::WaitableEvent* event, const std::string& name)
157 : event_(event),
158 pos_(0),
159 previous_marker_time_(base::TimeTicks::Now()) {
160 // Reads a test file from media/test/data directory and stores it in
DaleCurtis 2013/09/05 20:35:23 Indent it way off. I'd run clang-format on the fil
henrika (OOO until Aug 14) 2013/09/06 15:59:51 Thanks. Did it on the complete CL. Thanks for the
161 // a DecoderBuffer.
162 file_ = ReadTestDataFile(name);
163
164 // Log the name of the file which is used as input for this test.
165 base::FilePath file_path = GetTestDataFilePath(name);
166 printf("Reading from file: %s\n", file_path.value().c_str());
DaleCurtis 2013/09/05 20:35:23 Generally we avoid visible log messages in unittes
henrika (OOO until Aug 14) 2013/09/06 15:59:51 I will remove it.
167 fflush(stdout);
168 }
169
170 virtual ~FileAudioSource() {}
171
172 // AudioOutputStream::AudioSourceCallback implementation.
173
174 // Use samples read from a data file and fill up the audio buffer
175 // provided to us in the callback.
176 virtual int OnMoreData(AudioBus* audio_bus,
177 AudioBuffersState buffers_state) OVERRIDE {
178 // Add a '.'-marker once every second.
179 const base::TimeTicks now_time = base::TimeTicks::Now();
180 const int diff = (now_time - previous_marker_time_).InMilliseconds();
181 if (diff > 1000) {
182 printf(".");
DaleCurtis 2013/09/05 20:35:23 Ditto.
183 fflush(stdout);
184 previous_marker_time_ = now_time;
185 }
186
187 bool stop_playing = false;
188 int max_size =
189 audio_bus->frames() * audio_bus->channels() * kBytesPerSample;
190
191 // Adjust data size and prepare for end signal if file has ended.
192 if (pos_ + max_size > file_size()) {
193 stop_playing = true;
194 max_size = file_size() - pos_;
195 }
196
197 // File data is stored as interleaved 16-bit values. Copy data samples from
198 // the file and deinterleave to match the audio bus format.
199 // FromInterleaved() will zero out any unfilled frames when there is not
200 // sufficient data remaining in the file to fill up the complete frame.
201 int frames = max_size / (audio_bus->channels() * kBytesPerSample);
202 if (max_size) {
203 audio_bus->FromInterleaved(
204 file_->data() + pos_, frames, kBytesPerSample);
205 pos_ += max_size;
206 }
207
208 // Set event to ensure that the test can stop when the file has ended.
209 if (stop_playing)
210 event_->Signal();
211
212 return frames;
213 }
214
215 virtual int OnMoreIOData(AudioBus* source,
216 AudioBus* dest,
217 AudioBuffersState buffers_state) OVERRIDE {
218 NOTREACHED();
219 return 0;
220 }
221
222 virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
223
224 int file_size() { return file_->data_size(); }
225
226 private:
227 base::WaitableEvent* event_;
228 int pos_;
229 scoped_refptr<DecoderBuffer> file_;
230 base::TimeTicks previous_marker_time_;
231
232 DISALLOW_COPY_AND_ASSIGN(FileAudioSource);
233 };
234
235 // Implements AudioInputStream::AudioInputCallback and writes the recorded
236 // audio data to a local output file.
237 class FileAudioSink : public AudioInputStream::AudioInputCallback {
238 public:
239 explicit FileAudioSink(base::WaitableEvent* event,
240 const AudioParameters& params,
241 const std::string& file_name)
242 : event_(event),
243 params_(params),
244 previous_marker_time_(base::TimeTicks::Now()) {
245 // Allocate space for ~10 seconds of data.
246 const int kMaxBufferSize = 10 * params.GetBytesPerSecond();
247 buffer_.reset(new media::SeekableBuffer(0, kMaxBufferSize));
248
249 // Open up the binary file which will be written to in the destructor.
250 base::FilePath file_path;
251 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
252 file_path = file_path.AppendASCII(file_name.c_str());
253 binary_file_ = file_util::OpenFile(file_path, "wb");
254 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
255 printf("Writing to file : %s ", file_path.value().c_str());
256 printf("of size %d bytes\n", buffer_->forward_capacity());
257 fflush(stdout);
258 }
259
260 virtual ~FileAudioSink() {
261 int bytes_written = 0;
262 while (bytes_written < buffer_->forward_capacity()) {
263 const uint8* chunk;
264 int chunk_size;
265
266 // Stop writing if no more data is available.
267 if (!buffer_->GetCurrentChunk(&chunk, &chunk_size))
268 break;
269
270 // Write recorded data chunk to the file and prepare for next chunk.
271 fwrite(chunk, 1, chunk_size, binary_file_);
272 buffer_->Seek(chunk_size);
273 bytes_written += chunk_size;
274 }
275 file_util::CloseFile(binary_file_);
276 }
277
278 // AudioInputStream::AudioInputCallback implementation.
279 virtual void OnData(AudioInputStream* stream,
280 const uint8* src,
281 uint32 size,
282 uint32 hardware_delay_bytes,
283 double volume) OVERRIDE {
284 // Add a '.'-marker once every second.
285 const base::TimeTicks now_time = base::TimeTicks::Now();
286 const int diff = (now_time - previous_marker_time_).InMilliseconds();
287 if (diff > 1000) {
288 printf(".");
289 fflush(stdout);
290 previous_marker_time_ = now_time;
291 }
292
293 // Store data data in a temporary buffer to avoid making blocking
294 // fwrite() calls in the audio callback. The complete buffer will be
295 // written to file in the destructor.
296 if (!buffer_->Append(src, size))
297 event_->Signal();
298 }
299
300 virtual void OnClose(AudioInputStream* stream) OVERRIDE {}
301 virtual void OnError(AudioInputStream* stream) OVERRIDE {}
302
303 private:
304 base::WaitableEvent* event_;
305 AudioParameters params_;
306 scoped_ptr<media::SeekableBuffer> buffer_;
307 FILE* binary_file_;
308 base::TimeTicks previous_marker_time_;
309
310 DISALLOW_COPY_AND_ASSIGN(FileAudioSink);
311 };
312
313 // Implements AudioInputCallback and AudioSourceCallback to support full
314 // duplex audio where captured samples are played out in loopback after
315 // reading from a temporary FIFO storage.
316 class FullDuplexAudioSinkSource
317 : public AudioInputStream::AudioInputCallback,
318 public AudioOutputStream::AudioSourceCallback {
319 public:
320 explicit FullDuplexAudioSinkSource(const AudioParameters& params)
321 : params_(params),
322 previous_marker_time_(base::TimeTicks::Now()),
323 started_(false) {
324 // Start with a reasonably small FIFO size. It will be increased
325 // dynamically during the test if required.
326 fifo_.reset(
327 new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer()));
328 buffer_.reset(new uint8[params_.GetBytesPerBuffer()]);
329 }
330
331 virtual ~FullDuplexAudioSinkSource() {}
332
333 // AudioInputStream::AudioInputCallback implementation
334 virtual void OnData(AudioInputStream* stream, const uint8* src,
335 uint32 size, uint32 hardware_delay_bytes,
336 double volume) OVERRIDE {
337 // Add a '.'-marker once every second.
338 const base::TimeTicks now_time = base::TimeTicks::Now();
339 const int diff = (now_time - previous_marker_time_).InMilliseconds();
340
341 base::AutoLock lock(lock_);
342 if (diff > 1000) {
343 started_ = true;
344 previous_marker_time_ = now_time;
345
346 // Print out the extra delay added by the FIFO. This is a best effort
347 // estimate. We might be +- 10ms off here.
348 int extra_fio_delay = static_cast<int>(
349 BytesToMilliseconds(fifo_->forward_bytes() + size));
350 printf("%d ", extra_fio_delay);
351 fflush(stdout);
352 }
353
354 // We add an initial delay of ~1 second before loopback starts to ensure
355 // a stable callback sequence and to avoid initial bursts which might add
356 // to the extra FIFO delay.
357 if (!started_)
358 return;
359
360 // Append new data to the FIFO and extend the size if the mac capacity
361 // was exceeded. Flush the FIFO if is extended just in case.
362 if (!fifo_->Append(src, size)) {
363 fifo_->set_forward_capacity(2 * fifo_->forward_capacity());
364 printf("+ ");
365 fflush(stdout);
366 fifo_->Clear();
367 }
368 }
369
370 virtual void OnClose(AudioInputStream* stream) OVERRIDE {}
371 virtual void OnError(AudioInputStream* stream) OVERRIDE {}
372
373 // AudioOutputStream::AudioSourceCallback implementation
374 virtual int OnMoreData(AudioBus* dest,
375 AudioBuffersState buffers_state) OVERRIDE {
376 const int size_in_bytes =
377 (params_.bits_per_sample() / 8) * dest->frames() * dest->channels();
378 EXPECT_EQ(size_in_bytes, params_.GetBytesPerBuffer());
379
380 base::AutoLock lock(lock_);
381
382 // We add an initial delay of ~1 second before loopback starts to ensure
383 // a stable callback sequences and to avoid initial bursts which might add
384 // to the extra FIFO delay.
385 if (!started_) {
386 dest->Zero();
387 return dest->frames();
388 }
389
390 // Fill up destination with zeros if the FIFO does not contain enough
391 // data to fulfill the request.
392 if (fifo_->forward_bytes() < size_in_bytes) {
393 dest->Zero();
394 } else {
395 fifo_->Read(buffer_.get(), size_in_bytes);
396 dest->FromInterleaved(
397 buffer_.get(), dest->frames(), params_.bits_per_sample() / 8);
398 }
399
400 return dest->frames();
401 }
402
403 virtual int OnMoreIOData(AudioBus* source,
404 AudioBus* dest,
405 AudioBuffersState buffers_state) OVERRIDE {
406 NOTREACHED();
407 return 0;
408 }
409
410 virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
411
412 private:
413 // Converts from bytes to milliseconds given number of bytes and existing
414 // audio parameters.
415 double BytesToMilliseconds(int bytes) const {
416 const int frames = bytes / params_.GetBytesPerFrame();
417 return (base::TimeDelta::FromMicroseconds(
418 frames * base::Time::kMicrosecondsPerSecond /
419 static_cast<float>(params_.sample_rate()))).InMillisecondsF();
420 }
421
422 AudioParameters params_;
423 base::TimeTicks previous_marker_time_;
424 base::Lock lock_;
425 scoped_ptr<media::SeekableBuffer> fifo_;
426 scoped_ptr<uint8[]> buffer_;
427 bool started_;
428
429 DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource);
430 };
431
432 // Test fixture class.
433 class AudioAndroidTest : public testing::Test {
434 public:
435 AudioAndroidTest()
436 : audio_manager_(AudioManager::Create()) {}
437
438 virtual ~AudioAndroidTest() {}
439
440 AudioManager* audio_manager() { return audio_manager_.get(); }
441
442 // Converts AudioParameters::Format enumerator to readable string.
443 std::string FormatToString(AudioParameters::Format format) {
444 switch (format) {
445 case AudioParameters::AUDIO_PCM_LINEAR:
446 return std::string("AUDIO_PCM_LINEAR");
447 case AudioParameters::AUDIO_PCM_LOW_LATENCY:
448 return std::string("AUDIO_PCM_LOW_LATENCY");
449 case AudioParameters::AUDIO_FAKE:
450 return std::string("AUDIO_FAKE");
451 case AudioParameters::AUDIO_LAST_FORMAT:
452 return std::string("AUDIO_LAST_FORMAT");
453 default:
454 return std::string();
455 }
456 }
457
458 // Converts ChannelLayout enumerator to readable string. Does not include
459 // multi-channel cases since these layouts are not supported on Android.
460 std::string ChannelLayoutToString(ChannelLayout channel_layout) {
461 switch (channel_layout) {
462 case CHANNEL_LAYOUT_NONE:
463 return std::string("CHANNEL_LAYOUT_NONE");
464 case CHANNEL_LAYOUT_UNSUPPORTED:
465 return std::string("CHANNEL_LAYOUT_UNSUPPORTED");
466 case CHANNEL_LAYOUT_MONO:
467 return std::string("CHANNEL_LAYOUT_MONO");
468 case CHANNEL_LAYOUT_STEREO:
469 return std::string("CHANNEL_LAYOUT_STEREO");
470 default:
471 return std::string("CHANNEL_LAYOUT_UNSUPPORTED");
472 }
473 }
474
475 void PrintAudioParameters(AudioParameters params) {
476 printf("format : %s\n", FormatToString(params.format()).c_str());
477 printf("channel_layout : %s\n",
478 ChannelLayoutToString(params.channel_layout()).c_str());
479 printf("sample_rate : %d\n", params.sample_rate());
480 printf("bits_per_sample : %d\n", params.bits_per_sample());
481 printf("frames_per_buffer: %d\n", params.frames_per_buffer());
482 printf("channels : %d\n", params.channels());
483 printf("bytes per buffer : %d\n", params.GetBytesPerBuffer());
484 printf("bytes per second : %d\n", params.GetBytesPerSecond());
485 printf("bytes per frame : %d\n", params.GetBytesPerFrame());
486 printf("frame size in ms : %.2f\n", ExpectedTimeBetweenCallbacks(params));
487 }
488
489 AudioParameters GetDefaultInputStreamParameters() {
490 return audio_manager()->GetInputStreamParameters(
491 AudioManagerBase::kDefaultDeviceId);
492 }
493
494 AudioParameters GetDefaultOutputStreamParameters() {
495 return audio_manager()->GetDefaultOutputStreamParameters();
496 }
497
498 double ExpectedTimeBetweenCallbacks(AudioParameters params) const {
499 return (base::TimeDelta::FromMicroseconds(
500 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
501 static_cast<float>(params.sample_rate()))).InMillisecondsF();
502 }
503
504 #define START_STREAM_AND_WAIT_FOR_EVENT(stream, dir) \
DaleCurtis 2013/09/05 20:35:23 Seems you could just make this a templated functio
henrika (OOO until Aug 14) 2013/09/06 15:59:51 Guess I could also have done it as a separate func
DaleCurtis 2013/09/06 22:05:07 Chrome is a C++ based project, so we try to avoid
tommi (sloooow) - chröme 2013/09/08 18:53:42 Agree. As an additional thing to think about, the
505 base::WaitableEvent event(false, false); \
506 io_callbacks_.set_ ## dir ## _callback_limit(&event, num_callbacks); \
507 EXPECT_TRUE(stream->Open()); \
508 stream->Start(&io_callbacks_); \
509 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout())); \
510 stream->Stop(); \
511 stream->Close(); \
512 EXPECT_GE(io_callbacks_.dir ## _callbacks(), num_callbacks); \
513 EXPECT_LE(io_callbacks_.dir ## _callbacks(), num_callbacks + 1); \
514 EXPECT_EQ(io_callbacks_.dir ## _errors(), 0); \
515 printf("expected time between callbacks: %.2fms\n", \
516 time_between_callbacks_ms); \
517 double actual_time_between_callbacks_ms = \
518 io_callbacks_.average_time_between_ ## dir ## _callbacks_ms(); \
519 printf("actual time between callbacks: %.2fms\n", \
520 actual_time_between_callbacks_ms); \
521 EXPECT_GE(actual_time_between_callbacks_ms, \
522 0.70 * time_between_callbacks_ms); \
523 EXPECT_LE(actual_time_between_callbacks_ms, \
524 1.30 * time_between_callbacks_ms) \
525
526 void StartInputStreamCallbacks(const AudioParameters& params) {
527 double time_between_callbacks_ms = ExpectedTimeBetweenCallbacks(params);
528 const int num_callbacks = (2000.0 / time_between_callbacks_ms);
529 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
530 params, AudioManagerBase::kDefaultDeviceId);
531 EXPECT_TRUE(ais);
532 START_STREAM_AND_WAIT_FOR_EVENT(ais, input);
533 }
534
535 void StartOutputStreamCallbacks(const AudioParameters& params) {
536 double time_between_callbacks_ms = ExpectedTimeBetweenCallbacks(params);
537 const int num_callbacks = (2000.0 / time_between_callbacks_ms);
538 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
539 params, std::string(), std::string());
540 EXPECT_TRUE(aos);
541 START_STREAM_AND_WAIT_FOR_EVENT(aos, output);
542 }
543
544 #undef START_STREAM_AND_WAIT_FOR_EVENT
545
546 #define MULTIPLE_START_STREAM_AND_WAIT_FOR_EVENT(stream, dir) \
DaleCurtis 2013/09/05 20:35:23 Ditto.
henrika (OOO until Aug 14) 2013/09/06 15:59:51 Now removed.
547 const int kNumCallbacks = 5; \
548 const int kNumIterations = 3; \
549 base::WaitableEvent event(false, false); \
550 EXPECT_TRUE(stream->Open()); \
551 for (int i = 0; i < kNumIterations; ++i) { \
552 io_callbacks_.Reset(); \
553 io_callbacks_.set_ ## dir ## _callback_limit(&event, kNumCallbacks); \
554 stream->Start(&io_callbacks_); \
555 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout())); \
556 stream->Stop(); \
557 EXPECT_EQ(io_callbacks_.dir ## _errors(), 0); \
558 EXPECT_GE(io_callbacks_.dir ## _callbacks(), kNumCallbacks); \
559 EXPECT_LE(io_callbacks_.dir ## _callbacks(), kNumCallbacks + 1); \
560 } \
561 stream->Close() \
562
563 void MultipleStartStopInputStreamCallbacks(const AudioParameters& params) {
564 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
565 params, AudioManagerBase::kDefaultDeviceId);
566 EXPECT_TRUE(ais);
567 MULTIPLE_START_STREAM_AND_WAIT_FOR_EVENT(ais, input);
568 }
569
570 void MultipleStartStopOutputStreamCallbacks(const AudioParameters& params) {
571 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
572 params, std::string(), std::string());
573 EXPECT_TRUE(aos);
574 MULTIPLE_START_STREAM_AND_WAIT_FOR_EVENT(aos, output);
575 }
576
577 #undef MULTIPLE_START_STREAM_AND_WAIT_FOR_EVENT
578
579 protected:
580 base::MessageLoopForUI message_loop_;
581 scoped_ptr<AudioManager> audio_manager_;
582 MockAudioInputOutputCallbacks io_callbacks_;
583
584 DISALLOW_COPY_AND_ASSIGN(AudioAndroidTest);
585 };
586
587 // Get the default audio input parameters and log the result.
588 TEST_F(AudioAndroidTest, GetInputStreamParameters) {
589 AudioParameters params = GetDefaultInputStreamParameters();
590 EXPECT_TRUE(params.IsValid());
591 PrintAudioParameters(params);
592 }
593
594 // Get the default audio output parameters and log the result.
595 TEST_F(AudioAndroidTest, GetDefaultOutputStreamParameters) {
596 AudioParameters params = GetDefaultOutputStreamParameters();
597 EXPECT_TRUE(params.IsValid());
598 PrintAudioParameters(params);
599 }
600
601 // Check if low-latency output is supported and log the result as output.
602 TEST_F(AudioAndroidTest, IsAudioLowLatencySupported) {
603 AudioManagerAndroid* manager =
604 static_cast<AudioManagerAndroid*>(audio_manager());
605 bool low_latency = manager->IsAudioLowLatencySupported();
606 low_latency ? printf("Low latency output is supported\n") :
DaleCurtis 2013/09/05 20:35:23 Weird style and use of printf. Why not just if (x
henrika (OOO until Aug 14) 2013/09/06 15:59:51 Done.
607 printf("Low latency output is *not* supported\n");
608 }
609
610 // Ensure that a default input stream can be created and closed.
611 TEST_F(AudioAndroidTest, CreateAndCloseInputStream) {
612 AudioParameters params = GetDefaultInputStreamParameters();
613 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
614 params, AudioManagerBase::kDefaultDeviceId);
615 EXPECT_TRUE(ais);
616 ais->Close();
617 }
618
619 // Ensure that a default output stream can be created and closed.
620 // TODO(henrika): should we also verify that this API changes the audio mode
621 // to communication mode, and calls RegisterHeadsetReceiver, the first time
622 // it is called?
623 TEST_F(AudioAndroidTest, CreateAndCloseOutputStream) {
624 AudioParameters params = GetDefaultOutputStreamParameters();
625 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
626 params, std::string(), std::string());
627 EXPECT_TRUE(aos);
628 aos->Close();
629 }
630
631 // Ensure that a default input stream can be opened and closed.
632 TEST_F(AudioAndroidTest, OpenAndCloseInputStream) {
633 AudioParameters params = GetDefaultInputStreamParameters();
634 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
635 params, AudioManagerBase::kDefaultDeviceId);
636 EXPECT_TRUE(ais);
637 EXPECT_TRUE(ais->Open());
638 ais->Close();
639 }
640
641 // Ensure that a default output stream can be opened and closed.
642 TEST_F(AudioAndroidTest, OpenAndCloseOutputStream) {
643 AudioParameters params = GetDefaultOutputStreamParameters();
644 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
645 params, std::string(), std::string());
646 EXPECT_TRUE(aos);
647 EXPECT_TRUE(aos->Open());
648 aos->Close();
649 }
650
651 // Start input streaming using default input parameters and ensure that the
652 // callback sequence is sane.
653 TEST_F(AudioAndroidTest, StartInputStreamCallbacks) {
654 AudioParameters params = GetDefaultInputStreamParameters();
655 StartInputStreamCallbacks(params);
656 }
657
658 // Start input streaming using non default input parameters and ensure that the
659 // callback sequence is sane. The only change we make in this test is to select
660 // a 10ms buffer size instead of the default size.
661 // TODO(henrika): possibly add support for more variations.
662 TEST_F(AudioAndroidTest, StartInputStreamCallbacksNonDefaultParameters) {
663 AudioParameters native_params = GetDefaultInputStreamParameters();
664 AudioParameters params(native_params.format(),
665 native_params.channel_layout(),
666 native_params.sample_rate(),
667 native_params.bits_per_sample(),
668 native_params.sample_rate() / 100);
669 StartInputStreamCallbacks(params);
670 }
671
672 // Do repeated Start/Stop calling sequences and verify that we are able to
673 // restart recording multiple times.
674 TEST_F(AudioAndroidTest, MultipleStartStopInputStreamCallbacks) {
675 AudioParameters params = GetDefaultInputStreamParameters();
676 MultipleStartStopInputStreamCallbacks(params);
677 }
678
679 // Do repeated Start/Stop calling sequences and verify that we are able to
680 // restart playout multiple times.
681 TEST_F(AudioAndroidTest, MultipleStartStopOutputStreamCallbacks) {
682 AudioParameters params = GetDefaultOutputStreamParameters();
683 MultipleStartStopOutputStreamCallbacks(params);
684 }
685
686 // Start output streaming using default output parameters and ensure that the
687 // callback sequence is sane.
688 TEST_F(AudioAndroidTest, StartOutputStreamCallbacks) {
689 AudioParameters params = GetDefaultOutputStreamParameters();
690 StartOutputStreamCallbacks(params);
691 }
692
693 // Start output streaming using non default output parameters and ensure that
694 // the callback sequence is sane. The only changed we make in this test is to
695 // select a 10ms buffer size instead of the default size and to open up the
696 // device in mono.
697 // TODO(henrika): possibly add support for more variations.
698 TEST_F(AudioAndroidTest, StartOutputStreamCallbacksNonDefaultParameters) {
699 AudioParameters native_params = GetDefaultOutputStreamParameters();
700 AudioParameters params(native_params.format(),
701 CHANNEL_LAYOUT_MONO,
702 native_params.sample_rate(),
703 native_params.bits_per_sample(),
704 native_params.sample_rate() / 100);
705 StartOutputStreamCallbacks(params);
706 }
707
708 // Play out a PCM file segment in real time and allow the user to verify that
709 // the rendered audio sounds OK.
710 // NOTE: this test requires user interaction and is not designed to run as an
711 // automatized test on bots.
712 TEST_F(AudioAndroidTest, DISABLED_RunOutputStreamWithFileAsSource) {
713 AudioParameters params = GetDefaultOutputStreamParameters();
714 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
715 params, std::string(), std::string());
716 EXPECT_TRUE(aos);
717
718 PrintAudioParameters(params);
719 fflush(stdout);
720
721 std::string file_name;
722 if (params.sample_rate() == 48000 && params.channels() == 2) {
723 file_name = kSpeechFile_16b_s_48k;
724 } else if (params.sample_rate() == 48000 && params.channels() == 1) {
725 file_name = kSpeechFile_16b_m_48k;
726 } else if (params.sample_rate() == 44100 && params.channels() == 2) {
727 file_name = kSpeechFile_16b_s_44k;
728 } else if (params.sample_rate() == 44100 && params.channels() == 1) {
729 file_name = kSpeechFile_16b_m_44k;
730 } else {
731 FAIL() << "This test supports 44.1kHz and 48kHz mono/stereo only.";
732 return;
733 }
734
735 base::WaitableEvent event(false, false);
736 FileAudioSource source(&event, file_name);
737
738 EXPECT_TRUE(aos->Open());
739 aos->SetVolume(1.0);
740 aos->Start(&source);
741 printf(">> Verify that file is played out correctly");
742 fflush(stdout);
743 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
744 printf("\n");
745 aos->Stop();
746 aos->Close();
747 }
748
749 // Start input streaming and run it for ten seconds while recording to a
750 // local audio file.
751 // NOTE: this test requires user interaction and is not designed to run as an
752 // automatized test on bots.
753 TEST_F(AudioAndroidTest, DISABLED_RunSimplexInputStreamWithFileAsSink) {
754 AudioParameters params = GetDefaultInputStreamParameters();
755 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
756 params, AudioManagerBase::kDefaultDeviceId);
757 EXPECT_TRUE(ais);
758
759 PrintAudioParameters(params);
760 fflush(stdout);
761
762 std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm",
763 params.sample_rate(), params.frames_per_buffer(), params.channels());
764
765 base::WaitableEvent event(false, false);
766 FileAudioSink sink(&event, params, file_name);
767
768 EXPECT_TRUE(ais->Open());
769 ais->Start(&sink);
770 printf(">> Speak into the microphone to record audio");
771 fflush(stdout);
772 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
773 printf("\n");
774 ais->Stop();
775 ais->Close();
776 }
777
778 // Same test as RunSimplexInputStreamWithFileAsSink but this time output
779 // streaming is active as well (reads zeros only).
780 // NOTE: this test requires user interaction and is not designed to run as an
781 // automatized test on bots.
782 TEST_F(AudioAndroidTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
783 AudioParameters in_params = GetDefaultInputStreamParameters();
784 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
785 in_params, AudioManagerBase::kDefaultDeviceId);
786 EXPECT_TRUE(ais);
787
788 PrintAudioParameters(in_params);
789 fflush(stdout);
790
791 AudioParameters out_params =
792 audio_manager()->GetDefaultOutputStreamParameters();
793 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
794 out_params, std::string(), std::string());
795 EXPECT_TRUE(aos);
796
797 PrintAudioParameters(out_params);
798 fflush(stdout);
799
800 std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
801 in_params.sample_rate(), in_params.frames_per_buffer(),
802 in_params.channels());
803
804 base::WaitableEvent event(false, false);
805 FileAudioSink sink(&event, in_params, file_name);
806
807 EXPECT_TRUE(ais->Open());
808 EXPECT_TRUE(aos->Open());
809 ais->Start(&sink);
810 aos->Start(&io_callbacks_);
811 printf(">> Speak into the microphone to record audio");
812 fflush(stdout);
813 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
814 printf("\n");
815 aos->Stop();
816 ais->Stop();
817 aos->Close();
818 ais->Close();
819 }
820
821 // Start audio in both directions while feeding captured data into a FIFO so
822 // it can be read directly (in loopback) by the render side. A small extra
823 // delay will be added by the FIFO and an estimate of this delay will be
824 // printed out during the test.
825 // NOTE: this test requires user interaction and is not designed to run as an
826 // automatized test on bots.
827 TEST_F(AudioAndroidTest,
828 DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) {
829 // Get native audio parameters for the input side.
830 AudioParameters default_input_params = GetDefaultInputStreamParameters();
831
832 // Modify the parameters so that both input and output can use the same
833 // parameters by selecting 10ms as buffer size. This will also ensure that
834 // the output stream will be a mono stream since mono is default for input
835 // audio on Android.
836 AudioParameters io_params(default_input_params.format(),
837 default_input_params.channel_layout(),
838 default_input_params.sample_rate(),
839 default_input_params.bits_per_sample(),
840 default_input_params.sample_rate() / 100);
841 PrintAudioParameters(io_params);
842 fflush(stdout);
843
844 // Create input and output streams using the common audio parameters.
845 AudioInputStream* ais = audio_manager()->MakeAudioInputStream(
846 io_params, AudioManagerBase::kDefaultDeviceId);
847 EXPECT_TRUE(ais);
848 AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
849 io_params, std::string(), std::string());
850 EXPECT_TRUE(aos);
851
852 FullDuplexAudioSinkSource full_duplex(io_params);
853
854 // Start a full duplex audio session and print out estimates of the extra
855 // delay we should expect from the FIFO. If real-time delay measurements are
856 // performed, the result should be reduced by this extra delay since it is
857 // something that has been added by the test.
858 EXPECT_TRUE(ais->Open());
859 EXPECT_TRUE(aos->Open());
860 ais->Start(&full_duplex);
861 aos->Start(&full_duplex);
862 printf("HINT: an estimate of the extra FIFO delay will be updated once per "
863 "second during this test.\n");
864 printf(">> Speak into the mic and listen to the audio in loopback...\n");
865 fflush(stdout);
866 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
867 printf("\n");
868 aos->Stop();
869 ais->Stop();
870 aos->Close();
871 ais->Close();
872 }
873
874 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/audio/android/audio_manager_android.h » ('j') | media/audio/android/opensles_input.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698