OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <windows.h> | 5 #include <windows.h> |
6 #include <mmsystem.h> | 6 #include <mmsystem.h> |
7 | 7 |
8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
9 #include "base/environment.h" | 9 #include "base/environment.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 using base::win::ScopedCOMInitializer; | 37 using base::win::ScopedCOMInitializer; |
38 | 38 |
39 namespace media { | 39 namespace media { |
40 | 40 |
41 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; | 41 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; |
42 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; | 42 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; |
43 static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw"; | 43 static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw"; |
44 static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw"; | 44 static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw"; |
45 static const size_t kFileDurationMs = 20000; | 45 static const size_t kFileDurationMs = 20000; |
46 static const size_t kNumFileSegments = 2; | 46 static const size_t kNumFileSegments = 2; |
| 47 static const int kBitsPerSample = 16; |
47 | 48 |
48 static const size_t kMaxDeltaSamples = 1000; | 49 static const size_t kMaxDeltaSamples = 1000; |
49 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; | 50 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; |
50 | 51 |
51 MATCHER_P(HasValidDelay, value, "") { | 52 MATCHER_P(HasValidDelay, value, "") { |
52 // It is difficult to come up with a perfect test condition for the delay | 53 // It is difficult to come up with a perfect test condition for the delay |
53 // estimation. For now, verify that the produced output delay is always | 54 // estimation. For now, verify that the produced output delay is always |
54 // larger than the selected buffer size. | 55 // larger than the selected buffer size. |
55 return arg.hardware_delay_bytes > value.hardware_delay_bytes; | 56 return arg.hardware_delay_bytes > value.hardware_delay_bytes; |
56 } | 57 } |
57 | 58 |
58 // Used to terminate a loop from a different thread than the loop belongs to. | 59 // Used to terminate a loop from a different thread than the loop belongs to. |
59 // |loop| should be a MessageLoopProxy. | 60 // |loop| should be a MessageLoopProxy. |
60 ACTION_P(QuitLoop, loop) { | 61 ACTION_P(QuitLoop, loop) { |
61 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 62 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
62 } | 63 } |
63 | 64 |
64 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { | 65 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { |
65 public: | 66 public: |
66 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, | 67 MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus, |
67 uint32 max_size, | 68 AudioBuffersState buffers_state)); |
68 AudioBuffersState buffers_state)); | |
69 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); | 69 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); |
70 }; | 70 }; |
71 | 71 |
72 // This audio source implementation should be used for manual tests only since | 72 // This audio source implementation should be used for manual tests only since |
73 // it takes about 20 seconds to play out a file. | 73 // it takes about 20 seconds to play out a file. |
74 class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback { | 74 class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback { |
75 public: | 75 public: |
76 explicit ReadFromFileAudioSource(const std::string& name) | 76 explicit ReadFromFileAudioSource(const std::string& name) |
77 : pos_(0), | 77 : pos_(0), |
78 previous_call_time_(base::Time::Now()), | 78 previous_call_time_(base::Time::Now()), |
(...skipping 24 matching lines...) Expand all Loading... |
103 size_t elements_written = 0; | 103 size_t elements_written = 0; |
104 while (elements_written < elements_to_write_) { | 104 while (elements_written < elements_to_write_) { |
105 fprintf(text_file_, "%d\n", delta_times_[elements_written]); | 105 fprintf(text_file_, "%d\n", delta_times_[elements_written]); |
106 ++elements_written; | 106 ++elements_written; |
107 } | 107 } |
108 | 108 |
109 file_util::CloseFile(text_file_); | 109 file_util::CloseFile(text_file_); |
110 } | 110 } |
111 | 111 |
112 // AudioOutputStream::AudioSourceCallback implementation. | 112 // AudioOutputStream::AudioSourceCallback implementation. |
113 virtual uint32 OnMoreData(uint8* dest, | 113 virtual int OnMoreData(AudioBus* audio_bus, |
114 uint32 max_size, | 114 AudioBuffersState buffers_state) { |
115 AudioBuffersState buffers_state) { | |
116 // Store time difference between two successive callbacks in an array. | 115 // Store time difference between two successive callbacks in an array. |
117 // These values will be written to a file in the destructor. | 116 // These values will be written to a file in the destructor. |
118 int diff = (base::Time::Now() - previous_call_time_).InMilliseconds(); | 117 int diff = (base::Time::Now() - previous_call_time_).InMilliseconds(); |
119 previous_call_time_ = base::Time::Now(); | 118 previous_call_time_ = base::Time::Now(); |
120 if (elements_to_write_ < kMaxDeltaSamples) { | 119 if (elements_to_write_ < kMaxDeltaSamples) { |
121 delta_times_[elements_to_write_] = diff; | 120 delta_times_[elements_to_write_] = diff; |
122 ++elements_to_write_; | 121 ++elements_to_write_; |
123 } | 122 } |
124 | 123 |
| 124 int max_size = |
| 125 audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8; |
| 126 |
125 // Use samples read from a data file and fill up the audio buffer | 127 // Use samples read from a data file and fill up the audio buffer |
126 // provided to us in the callback. | 128 // provided to us in the callback. |
127 if (pos_ + static_cast<int>(max_size) > file_size()) | 129 if (pos_ + static_cast<int>(max_size) > file_size()) |
128 max_size = file_size() - pos_; | 130 max_size = file_size() - pos_; |
| 131 int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8); |
129 if (max_size) { | 132 if (max_size) { |
130 memcpy(dest, file_->GetData() + pos_, max_size); | 133 audio_bus->FromInterleaved( |
| 134 file_->GetData() + pos_, frames, kBitsPerSample / 8); |
131 pos_ += max_size; | 135 pos_ += max_size; |
132 } | 136 } |
133 return max_size; | 137 return frames; |
134 } | 138 } |
135 | 139 |
136 virtual void OnError(AudioOutputStream* stream, int code) {} | 140 virtual void OnError(AudioOutputStream* stream, int code) {} |
137 | 141 |
138 int file_size() { return file_->GetDataSize(); } | 142 int file_size() { return file_->GetDataSize(); } |
139 | 143 |
140 private: | 144 private: |
141 scoped_refptr<DecoderBuffer> file_; | 145 scoped_refptr<DecoderBuffer> file_; |
142 scoped_array<int> delta_times_; | 146 scoped_array<int> delta_times_; |
143 int pos_; | 147 int pos_; |
(...skipping 25 matching lines...) Expand all Loading... |
169 | 173 |
170 // Convenience method which creates a default AudioOutputStream object but | 174 // Convenience method which creates a default AudioOutputStream object but |
171 // also allows the user to modify the default settings. | 175 // also allows the user to modify the default settings. |
172 class AudioOutputStreamWrapper { | 176 class AudioOutputStreamWrapper { |
173 public: | 177 public: |
174 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) | 178 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) |
175 : com_init_(ScopedCOMInitializer::kMTA), | 179 : com_init_(ScopedCOMInitializer::kMTA), |
176 audio_man_(audio_manager), | 180 audio_man_(audio_manager), |
177 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), | 181 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), |
178 channel_layout_(CHANNEL_LAYOUT_STEREO), | 182 channel_layout_(CHANNEL_LAYOUT_STEREO), |
179 bits_per_sample_(16) { | 183 bits_per_sample_(kBitsPerSample) { |
180 // Use native/mixing sample rate and 10ms frame size as default. | 184 // Use native/mixing sample rate and 10ms frame size as default. |
181 sample_rate_ = static_cast<int>( | 185 sample_rate_ = static_cast<int>( |
182 WASAPIAudioOutputStream::HardwareSampleRate(eConsole)); | 186 WASAPIAudioOutputStream::HardwareSampleRate(eConsole)); |
183 samples_per_packet_ = sample_rate_ / 100; | 187 samples_per_packet_ = sample_rate_ / 100; |
184 DCHECK(sample_rate_); | 188 DCHECK(sample_rate_); |
185 } | 189 } |
186 | 190 |
187 ~AudioOutputStreamWrapper() {} | 191 ~AudioOutputStreamWrapper() {} |
188 | 192 |
189 // Creates AudioOutputStream object using default parameters. | 193 // Creates AudioOutputStream object using default parameters. |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 EXPECT_TRUE(aos->Open()); | 458 EXPECT_TRUE(aos->Open()); |
455 | 459 |
456 // Derive the expected size in bytes of each packet. | 460 // Derive the expected size in bytes of each packet. |
457 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 461 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
458 (aosw.bits_per_sample() / 8); | 462 (aosw.bits_per_sample() / 8); |
459 | 463 |
460 // Set up expected minimum delay estimation. | 464 // Set up expected minimum delay estimation. |
461 AudioBuffersState state(0, bytes_per_packet); | 465 AudioBuffersState state(0, bytes_per_packet); |
462 | 466 |
463 // Wait for the first callback and verify its parameters. | 467 // Wait for the first callback and verify its parameters. |
464 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 468 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
465 HasValidDelay(state))) | |
466 .WillOnce(DoAll( | 469 .WillOnce(DoAll( |
467 QuitLoop(loop.message_loop_proxy()), | 470 QuitLoop(loop.message_loop_proxy()), |
468 Return(bytes_per_packet))); | 471 Return(aosw.samples_per_packet()))); |
469 | 472 |
470 aos->Start(&source); | 473 aos->Start(&source); |
471 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 474 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
472 TestTimeouts::action_timeout()); | 475 TestTimeouts::action_timeout()); |
473 loop.Run(); | 476 loop.Run(); |
474 aos->Stop(); | 477 aos->Stop(); |
475 aos->Close(); | 478 aos->Close(); |
476 } | 479 } |
477 | 480 |
478 // Use a fixed packets size (independent of sample rate) and verify | 481 // Use a fixed packets size (independent of sample rate) and verify |
(...skipping 14 matching lines...) Expand all Loading... |
493 EXPECT_TRUE(aos->Open()); | 496 EXPECT_TRUE(aos->Open()); |
494 | 497 |
495 // Derive the expected size in bytes of each packet. | 498 // Derive the expected size in bytes of each packet. |
496 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 499 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
497 (aosw.bits_per_sample() / 8); | 500 (aosw.bits_per_sample() / 8); |
498 | 501 |
499 // Set up expected minimum delay estimation. | 502 // Set up expected minimum delay estimation. |
500 AudioBuffersState state(0, bytes_per_packet); | 503 AudioBuffersState state(0, bytes_per_packet); |
501 | 504 |
502 // Ensure that callbacks start correctly. | 505 // Ensure that callbacks start correctly. |
503 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 506 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
504 HasValidDelay(state))) | |
505 .WillOnce(DoAll( | 507 .WillOnce(DoAll( |
506 QuitLoop(loop.message_loop_proxy()), | 508 QuitLoop(loop.message_loop_proxy()), |
507 Return(bytes_per_packet))) | 509 Return(aosw.samples_per_packet()))) |
508 .WillRepeatedly(Return(bytes_per_packet)); | 510 .WillRepeatedly(Return(aosw.samples_per_packet())); |
509 | 511 |
510 aos->Start(&source); | 512 aos->Start(&source); |
511 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 513 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
512 TestTimeouts::action_timeout()); | 514 TestTimeouts::action_timeout()); |
513 loop.Run(); | 515 loop.Run(); |
514 aos->Stop(); | 516 aos->Stop(); |
515 aos->Close(); | 517 aos->Close(); |
516 } | 518 } |
517 | 519 |
518 TEST(WASAPIAudioOutputStreamTest, Mono) { | 520 TEST(WASAPIAudioOutputStreamTest, Mono) { |
(...skipping 10 matching lines...) Expand all Loading... |
529 AudioOutputStream* aos = aosw.Create(CHANNEL_LAYOUT_MONO); | 531 AudioOutputStream* aos = aosw.Create(CHANNEL_LAYOUT_MONO); |
530 EXPECT_TRUE(aos->Open()); | 532 EXPECT_TRUE(aos->Open()); |
531 | 533 |
532 // Derive the expected size in bytes of each packet. | 534 // Derive the expected size in bytes of each packet. |
533 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 535 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
534 (aosw.bits_per_sample() / 8); | 536 (aosw.bits_per_sample() / 8); |
535 | 537 |
536 // Set up expected minimum delay estimation. | 538 // Set up expected minimum delay estimation. |
537 AudioBuffersState state(0, bytes_per_packet); | 539 AudioBuffersState state(0, bytes_per_packet); |
538 | 540 |
539 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 541 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
540 HasValidDelay(state))) | |
541 .WillOnce(DoAll( | 542 .WillOnce(DoAll( |
542 QuitLoop(loop.message_loop_proxy()), | 543 QuitLoop(loop.message_loop_proxy()), |
543 Return(bytes_per_packet))) | 544 Return(aosw.samples_per_packet()))) |
544 .WillRepeatedly(Return(bytes_per_packet)); | 545 .WillRepeatedly(Return(aosw.samples_per_packet())); |
545 | 546 |
546 aos->Start(&source); | 547 aos->Start(&source); |
547 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 548 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
548 TestTimeouts::action_timeout()); | 549 TestTimeouts::action_timeout()); |
549 loop.Run(); | 550 loop.Run(); |
550 aos->Stop(); | 551 aos->Stop(); |
551 aos->Close(); | 552 aos->Close(); |
552 } | 553 } |
553 | 554 |
554 // This test is intended for manual tests and should only be enabled | 555 // This test is intended for manual tests and should only be enabled |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 EXPECT_TRUE(aos->Open()); | 783 EXPECT_TRUE(aos->Open()); |
783 | 784 |
784 // Derive the expected size in bytes of each packet. | 785 // Derive the expected size in bytes of each packet. |
785 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 786 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
786 (aosw.bits_per_sample() / 8); | 787 (aosw.bits_per_sample() / 8); |
787 | 788 |
788 // Set up expected minimum delay estimation. | 789 // Set up expected minimum delay estimation. |
789 AudioBuffersState state(0, bytes_per_packet); | 790 AudioBuffersState state(0, bytes_per_packet); |
790 | 791 |
791 // Wait for the first callback and verify its parameters. | 792 // Wait for the first callback and verify its parameters. |
792 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 793 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
793 HasValidDelay(state))) | |
794 .WillOnce(DoAll( | 794 .WillOnce(DoAll( |
795 QuitLoop(loop.message_loop_proxy()), | 795 QuitLoop(loop.message_loop_proxy()), |
796 Return(bytes_per_packet))) | 796 Return(aosw.samples_per_packet()))) |
797 .WillRepeatedly(Return(bytes_per_packet)); | 797 .WillRepeatedly(Return(aosw.samples_per_packet())); |
798 | 798 |
799 aos->Start(&source); | 799 aos->Start(&source); |
800 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 800 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
801 TestTimeouts::action_timeout()); | 801 TestTimeouts::action_timeout()); |
802 loop.Run(); | 802 loop.Run(); |
803 aos->Stop(); | 803 aos->Stop(); |
804 aos->Close(); | 804 aos->Close(); |
805 } | 805 } |
806 | 806 |
807 // Verify that we can open and start the output stream in exclusive mode at | 807 // Verify that we can open and start the output stream in exclusive mode at |
(...skipping 16 matching lines...) Expand all Loading... |
824 EXPECT_TRUE(aos->Open()); | 824 EXPECT_TRUE(aos->Open()); |
825 | 825 |
826 // Derive the expected size in bytes of each packet. | 826 // Derive the expected size in bytes of each packet. |
827 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 827 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
828 (aosw.bits_per_sample() / 8); | 828 (aosw.bits_per_sample() / 8); |
829 | 829 |
830 // Set up expected minimum delay estimation. | 830 // Set up expected minimum delay estimation. |
831 AudioBuffersState state(0, bytes_per_packet); | 831 AudioBuffersState state(0, bytes_per_packet); |
832 | 832 |
833 // Wait for the first callback and verify its parameters. | 833 // Wait for the first callback and verify its parameters. |
834 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 834 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
835 HasValidDelay(state))) | |
836 .WillOnce(DoAll( | 835 .WillOnce(DoAll( |
837 QuitLoop(loop.message_loop_proxy()), | 836 QuitLoop(loop.message_loop_proxy()), |
838 Return(bytes_per_packet))) | 837 Return(aosw.samples_per_packet()))) |
839 .WillRepeatedly(Return(bytes_per_packet)); | 838 .WillRepeatedly(Return(aosw.samples_per_packet())); |
840 | 839 |
841 aos->Start(&source); | 840 aos->Start(&source); |
842 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 841 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
843 TestTimeouts::action_timeout()); | 842 TestTimeouts::action_timeout()); |
844 loop.Run(); | 843 loop.Run(); |
845 aos->Stop(); | 844 aos->Stop(); |
846 aos->Close(); | 845 aos->Close(); |
847 } | 846 } |
848 | 847 |
849 } // namespace media | 848 } // namespace media |
OLD | NEW |