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