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" | |
9 #include "base/environment.h" | 8 #include "base/environment.h" |
10 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
11 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
13 #include "base/path_service.h" | 12 #include "base/path_service.h" |
14 #include "base/test/test_timeouts.h" | 13 #include "base/test/test_timeouts.h" |
15 #include "base/win/scoped_com_initializer.h" | 14 #include "base/win/scoped_com_initializer.h" |
16 #include "media/audio/audio_io.h" | 15 #include "media/audio/audio_io.h" |
17 #include "media/audio/audio_manager_base.h" | 16 #include "media/audio/audio_manager_base.h" |
18 #include "media/audio/audio_unittest_util.h" | 17 #include "media/audio/audio_unittest_util.h" |
(...skipping 15 matching lines...) Expand all Loading... |
34 if (++*count >= limit) { | 33 if (++*count >= limit) { |
35 loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | 34 loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
36 } | 35 } |
37 } | 36 } |
38 | 37 |
39 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 38 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
40 public: | 39 public: |
41 MOCK_METHOD4(OnData, | 40 MOCK_METHOD4(OnData, |
42 void(AudioInputStream* stream, | 41 void(AudioInputStream* stream, |
43 const AudioBus* src, | 42 const AudioBus* src, |
44 uint32 hardware_delay_bytes, | 43 uint32_t hardware_delay_bytes, |
45 double volume)); | 44 double volume)); |
46 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 45 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
47 }; | 46 }; |
48 | 47 |
49 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { | 48 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { |
50 public: | 49 public: |
51 FakeAudioInputCallback() | 50 FakeAudioInputCallback() |
52 : num_received_audio_frames_(0), | 51 : num_received_audio_frames_(0), |
53 data_event_(false, false), | 52 data_event_(false, false), |
54 error_(false) {} | 53 error_(false) {} |
55 | 54 |
56 bool error() const { return error_; } | 55 bool error() const { return error_; } |
57 int num_received_audio_frames() const { return num_received_audio_frames_; } | 56 int num_received_audio_frames() const { return num_received_audio_frames_; } |
58 | 57 |
59 // Waits until OnData() is called on another thread. | 58 // Waits until OnData() is called on another thread. |
60 void WaitForData() { | 59 void WaitForData() { |
61 data_event_.Wait(); | 60 data_event_.Wait(); |
62 } | 61 } |
63 | 62 |
64 void OnData(AudioInputStream* stream, | 63 void OnData(AudioInputStream* stream, |
65 const AudioBus* src, | 64 const AudioBus* src, |
66 uint32 hardware_delay_bytes, | 65 uint32_t hardware_delay_bytes, |
67 double volume) override { | 66 double volume) override { |
68 EXPECT_GE(hardware_delay_bytes, 0u); | 67 EXPECT_GE(hardware_delay_bytes, 0u); |
69 EXPECT_LT(hardware_delay_bytes, 0xFFFFu); // Arbitrarily picked. | 68 EXPECT_LT(hardware_delay_bytes, 0xFFFFu); // Arbitrarily picked. |
70 num_received_audio_frames_ += src->frames(); | 69 num_received_audio_frames_ += src->frames(); |
71 data_event_.Signal(); | 70 data_event_.Signal(); |
72 } | 71 } |
73 | 72 |
74 void OnError(AudioInputStream* stream) override { | 73 void OnError(AudioInputStream* stream) override { |
75 error_ = true; | 74 error_ = true; |
76 } | 75 } |
(...skipping 23 matching lines...) Expand all Loading... |
100 file_path = file_path.AppendASCII(file_name); | 99 file_path = file_path.AppendASCII(file_name); |
101 binary_file_ = base::OpenFile(file_path, "wb"); | 100 binary_file_ = base::OpenFile(file_path, "wb"); |
102 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; | 101 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; |
103 VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; | 102 VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; |
104 VLOG(0) << "bits_per_sample_:" << bits_per_sample_; | 103 VLOG(0) << "bits_per_sample_:" << bits_per_sample_; |
105 } | 104 } |
106 | 105 |
107 ~WriteToFileAudioSink() override { | 106 ~WriteToFileAudioSink() override { |
108 size_t bytes_written = 0; | 107 size_t bytes_written = 0; |
109 while (bytes_written < bytes_to_write_) { | 108 while (bytes_written < bytes_to_write_) { |
110 const uint8* chunk; | 109 const uint8_t* chunk; |
111 int chunk_size; | 110 int chunk_size; |
112 | 111 |
113 // Stop writing if no more data is available. | 112 // Stop writing if no more data is available. |
114 if (!buffer_.GetCurrentChunk(&chunk, &chunk_size)) | 113 if (!buffer_.GetCurrentChunk(&chunk, &chunk_size)) |
115 break; | 114 break; |
116 | 115 |
117 // Write recorded data chunk to the file and prepare for next chunk. | 116 // Write recorded data chunk to the file and prepare for next chunk. |
118 fwrite(chunk, 1, chunk_size, binary_file_); | 117 fwrite(chunk, 1, chunk_size, binary_file_); |
119 buffer_.Seek(chunk_size); | 118 buffer_.Seek(chunk_size); |
120 bytes_written += chunk_size; | 119 bytes_written += chunk_size; |
121 } | 120 } |
122 base::CloseFile(binary_file_); | 121 base::CloseFile(binary_file_); |
123 } | 122 } |
124 | 123 |
125 // AudioInputStream::AudioInputCallback implementation. | 124 // AudioInputStream::AudioInputCallback implementation. |
126 void OnData(AudioInputStream* stream, | 125 void OnData(AudioInputStream* stream, |
127 const AudioBus* src, | 126 const AudioBus* src, |
128 uint32 hardware_delay_bytes, | 127 uint32_t hardware_delay_bytes, |
129 double volume) override { | 128 double volume) override { |
130 EXPECT_EQ(bits_per_sample_, 16); | 129 EXPECT_EQ(bits_per_sample_, 16); |
131 const int num_samples = src->frames() * src->channels(); | 130 const int num_samples = src->frames() * src->channels(); |
132 scoped_ptr<int16> interleaved(new int16[num_samples]); | 131 scoped_ptr<int16_t> interleaved(new int16_t[num_samples]); |
133 const int bytes_per_sample = sizeof(*interleaved); | 132 const int bytes_per_sample = sizeof(*interleaved); |
134 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); | 133 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
135 | 134 |
136 // Store data data in a temporary buffer to avoid making blocking | 135 // Store data data in a temporary buffer to avoid making blocking |
137 // fwrite() calls in the audio callback. The complete buffer will be | 136 // fwrite() calls in the audio callback. The complete buffer will be |
138 // written to file in the destructor. | 137 // written to file in the destructor. |
139 const int size = bytes_per_sample * num_samples; | 138 const int size = bytes_per_sample * num_samples; |
140 if (buffer_.Append((const uint8*)interleaved.get(), size)) { | 139 if (buffer_.Append((const uint8_t*)interleaved.get(), size)) { |
141 bytes_to_write_ += size; | 140 bytes_to_write_ += size; |
142 } | 141 } |
143 } | 142 } |
144 | 143 |
145 void OnError(AudioInputStream* stream) override {} | 144 void OnError(AudioInputStream* stream) override {} |
146 | 145 |
147 private: | 146 private: |
148 int bits_per_sample_; | 147 int bits_per_sample_; |
149 media::SeekableBuffer buffer_; | 148 media::SeekableBuffer buffer_; |
150 FILE* binary_file_; | 149 FILE* binary_file_; |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 | 352 |
354 // Create default WASAPI input stream which records in stereo using | 353 // Create default WASAPI input stream which records in stereo using |
355 // the shared mixing rate. The default buffer size is 10ms. | 354 // the shared mixing rate. The default buffer size is 10ms. |
356 AudioInputStreamWrapper aisw(audio_manager.get()); | 355 AudioInputStreamWrapper aisw(audio_manager.get()); |
357 ScopedAudioInputStream ais(aisw.Create()); | 356 ScopedAudioInputStream ais(aisw.Create()); |
358 EXPECT_TRUE(ais->Open()); | 357 EXPECT_TRUE(ais->Open()); |
359 | 358 |
360 MockAudioInputCallback sink; | 359 MockAudioInputCallback sink; |
361 | 360 |
362 // Derive the expected size in bytes of each recorded packet. | 361 // Derive the expected size in bytes of each recorded packet. |
363 uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 362 uint32_t bytes_per_packet = |
364 (aisw.bits_per_sample() / 8); | 363 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
365 | 364 |
366 // We use 10ms packets and will run the test until ten packets are received. | 365 // We use 10ms packets and will run the test until ten packets are received. |
367 // All should contain valid packets of the same size and a valid delay | 366 // All should contain valid packets of the same size and a valid delay |
368 // estimate. | 367 // estimate. |
369 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 368 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) |
370 .Times(AtLeast(10)) | 369 .Times(AtLeast(10)) |
371 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 370 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); |
372 ais->Start(&sink); | 371 ais->Start(&sink); |
373 loop.Run(); | 372 loop.Run(); |
374 ais->Stop(); | 373 ais->Stop(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); | 462 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); |
464 VLOG(0) << ">> Speak into the default microphone while recording."; | 463 VLOG(0) << ">> Speak into the default microphone while recording."; |
465 ais->Start(&file_sink); | 464 ais->Start(&file_sink); |
466 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 465 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
467 ais->Stop(); | 466 ais->Stop(); |
468 VLOG(0) << ">> Recording has stopped."; | 467 VLOG(0) << ">> Recording has stopped."; |
469 ais.Close(); | 468 ais.Close(); |
470 } | 469 } |
471 | 470 |
472 } // namespace media | 471 } // namespace media |
OLD | NEW |