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

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