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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 return input; | 153 return input; |
154 } | 154 } |
155 | 155 |
156 // Convenience method which creates a default AudioInputStream object but | 156 // Convenience method which creates a default AudioInputStream object but |
157 // also allows the user to modify the default settings. | 157 // also allows the user to modify the default settings. |
158 class AudioInputStreamWrapper { | 158 class AudioInputStreamWrapper { |
159 public: | 159 public: |
160 explicit AudioInputStreamWrapper(AudioManager* audio_manager) | 160 explicit AudioInputStreamWrapper(AudioManager* audio_manager) |
161 : com_init_(ScopedCOMInitializer::kMTA), | 161 : com_init_(ScopedCOMInitializer::kMTA), |
162 audio_man_(audio_manager), | 162 audio_man_(audio_manager), |
163 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), | 163 default_params_( |
164 channel_layout_(CHANNEL_LAYOUT_STEREO), | 164 audio_manager->GetInputStreamParameters( |
165 bits_per_sample_(16) { | 165 AudioManagerBase::kDefaultDeviceId)) { |
166 // Use native/mixing sample rate and 10ms frame size as default. | 166 EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); |
167 sample_rate_ = static_cast<int>( | 167 frames_per_buffer_ = default_params_.frames_per_buffer(); |
168 WASAPIAudioInputStream::HardwareSampleRate( | 168 // We expect the default buffer size to be a 10ms buffer. |
169 AudioManagerBase::kDefaultDeviceId)); | 169 EXPECT_EQ(frames_per_buffer_, sample_rate() / 100); |
170 samples_per_packet_ = sample_rate_ / 100; | |
171 } | 170 } |
172 | 171 |
173 ~AudioInputStreamWrapper() {} | 172 ~AudioInputStreamWrapper() {} |
174 | 173 |
175 // Creates AudioInputStream object using default parameters. | 174 // Creates AudioInputStream object using default parameters. |
176 AudioInputStream* Create() { | 175 AudioInputStream* Create() { |
177 return CreateInputStream(); | 176 return CreateInputStream(); |
178 } | 177 } |
179 | 178 |
180 // Creates AudioInputStream object using non-default parameters where the | 179 // Creates AudioInputStream object using non-default parameters where the |
181 // frame size is modified. | 180 // frame size is modified. |
182 AudioInputStream* Create(int samples_per_packet) { | 181 AudioInputStream* Create(int frames_per_buffer) { |
183 samples_per_packet_ = samples_per_packet; | 182 frames_per_buffer_ = frames_per_buffer; |
184 return CreateInputStream(); | 183 return CreateInputStream(); |
185 } | 184 } |
186 | 185 |
187 AudioParameters::Format format() const { return format_; } | 186 AudioParameters::Format format() const { return default_params_.format(); } |
188 int channels() const { | 187 int channels() const { |
189 return ChannelLayoutToChannelCount(channel_layout_); | 188 return ChannelLayoutToChannelCount(default_params_.channel_layout()); |
190 } | 189 } |
191 int bits_per_sample() const { return bits_per_sample_; } | 190 int bits_per_sample() const { return default_params_.bits_per_sample(); } |
192 int sample_rate() const { return sample_rate_; } | 191 int sample_rate() const { return default_params_.sample_rate(); } |
193 int samples_per_packet() const { return samples_per_packet_; } | 192 int frames_per_buffer() const { return frames_per_buffer_; } |
194 | 193 |
195 private: | 194 private: |
196 AudioInputStream* CreateInputStream() { | 195 AudioInputStream* CreateInputStream() { |
197 AudioInputStream* ais = audio_man_->MakeAudioInputStream( | 196 AudioInputStream* ais = audio_man_->MakeAudioInputStream( |
198 AudioParameters(format_, channel_layout_, sample_rate_, | 197 AudioParameters(format(), default_params_.channel_layout(), |
199 bits_per_sample_, samples_per_packet_), | 198 default_params_.input_channels(), |
200 AudioManagerBase::kDefaultDeviceId); | 199 sample_rate(), bits_per_sample(), frames_per_buffer_, |
| 200 default_params_.effects()), |
| 201 AudioManagerBase::kDefaultDeviceId); |
201 EXPECT_TRUE(ais); | 202 EXPECT_TRUE(ais); |
202 return ais; | 203 return ais; |
203 } | 204 } |
204 | 205 |
205 ScopedCOMInitializer com_init_; | 206 ScopedCOMInitializer com_init_; |
206 AudioManager* audio_man_; | 207 AudioManager* audio_man_; |
207 AudioParameters::Format format_; | 208 const AudioParameters default_params_; |
208 ChannelLayout channel_layout_; | 209 int frames_per_buffer_; |
209 int bits_per_sample_; | |
210 int sample_rate_; | |
211 int samples_per_packet_; | |
212 }; | 210 }; |
213 | 211 |
214 // Convenience method which creates a default AudioInputStream object. | 212 // Convenience method which creates a default AudioInputStream object. |
215 static AudioInputStream* CreateDefaultAudioInputStream( | 213 static AudioInputStream* CreateDefaultAudioInputStream( |
216 AudioManager* audio_manager) { | 214 AudioManager* audio_manager) { |
217 AudioInputStreamWrapper aisw(audio_manager); | 215 AudioInputStreamWrapper aisw(audio_manager); |
218 AudioInputStream* ais = aisw.Create(); | 216 AudioInputStream* ais = aisw.Create(); |
219 return ais; | 217 return ais; |
220 } | 218 } |
221 | 219 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); | 260 ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); |
263 | 261 |
264 // Retrieve a list of all available input devices. | 262 // Retrieve a list of all available input devices. |
265 media::AudioDeviceNames device_names; | 263 media::AudioDeviceNames device_names; |
266 audio_manager->GetAudioInputDeviceNames(&device_names); | 264 audio_manager->GetAudioInputDeviceNames(&device_names); |
267 | 265 |
268 // Scan all available input devices and repeat the same test for all of them. | 266 // Scan all available input devices and repeat the same test for all of them. |
269 for (media::AudioDeviceNames::const_iterator it = device_names.begin(); | 267 for (media::AudioDeviceNames::const_iterator it = device_names.begin(); |
270 it != device_names.end(); ++it) { | 268 it != device_names.end(); ++it) { |
271 // Retrieve the hardware sample rate given a specified audio input device. | 269 // Retrieve the hardware sample rate given a specified audio input device. |
272 // TODO(tommi): ensure that we don't have to cast here. | 270 AudioParameters params = WASAPIAudioInputStream::GetInputStreamParameters( |
273 int fs = static_cast<int>(WASAPIAudioInputStream::HardwareSampleRate( | 271 it->unique_id); |
274 it->unique_id)); | 272 EXPECT_GE(params.sample_rate(), 0); |
275 EXPECT_GE(fs, 0); | |
276 } | 273 } |
277 } | 274 } |
278 | 275 |
279 // Test Create(), Close() calling sequence. | 276 // Test Create(), Close() calling sequence. |
280 TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { | 277 TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { |
281 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); | 278 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); |
282 if (!CanRunAudioTests(audio_manager.get())) | 279 if (!CanRunAudioTests(audio_manager.get())) |
283 return; | 280 return; |
284 ScopedAudioInputStream ais( | 281 ScopedAudioInputStream ais( |
285 CreateDefaultAudioInputStream(audio_manager.get())); | 282 CreateDefaultAudioInputStream(audio_manager.get())); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 | 363 |
367 // Create default WASAPI input stream which records in stereo using | 364 // Create default WASAPI input stream which records in stereo using |
368 // the shared mixing rate. The default buffer size is 10ms. | 365 // the shared mixing rate. The default buffer size is 10ms. |
369 AudioInputStreamWrapper aisw(audio_manager.get()); | 366 AudioInputStreamWrapper aisw(audio_manager.get()); |
370 ScopedAudioInputStream ais(aisw.Create()); | 367 ScopedAudioInputStream ais(aisw.Create()); |
371 EXPECT_TRUE(ais->Open()); | 368 EXPECT_TRUE(ais->Open()); |
372 | 369 |
373 MockAudioInputCallback sink; | 370 MockAudioInputCallback sink; |
374 | 371 |
375 // Derive the expected size in bytes of each recorded packet. | 372 // Derive the expected size in bytes of each recorded packet. |
376 uint32 bytes_per_packet = aisw.channels() * aisw.samples_per_packet() * | 373 uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
377 (aisw.bits_per_sample() / 8); | 374 (aisw.bits_per_sample() / 8); |
378 | 375 |
379 // We use 10ms packets and will run the test until ten packets are received. | 376 // We use 10ms packets and will run the test until ten packets are received. |
380 // All should contain valid packets of the same size and a valid delay | 377 // All should contain valid packets of the same size and a valid delay |
381 // estimate. | 378 // estimate. |
382 EXPECT_CALL(sink, OnData( | 379 EXPECT_CALL(sink, OnData( |
383 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) | 380 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) |
384 .Times(AtLeast(10)) | 381 .Times(AtLeast(10)) |
385 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 382 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); |
386 ais->Start(&sink); | 383 ais->Start(&sink); |
387 loop.Run(); | 384 loop.Run(); |
388 ais->Stop(); | 385 ais->Stop(); |
389 | 386 |
390 // Store current packet size (to be used in the subsequent tests). | 387 // Store current packet size (to be used in the subsequent tests). |
391 int samples_per_packet_10ms = aisw.samples_per_packet(); | 388 int frames_per_buffer_10ms = aisw.frames_per_buffer(); |
392 | 389 |
393 ais.Close(); | 390 ais.Close(); |
394 | 391 |
395 // 20 ms packet size. | 392 // 20 ms packet size. |
396 | 393 |
397 count = 0; | 394 count = 0; |
398 ais.Reset(aisw.Create(2 * samples_per_packet_10ms)); | 395 ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); |
399 EXPECT_TRUE(ais->Open()); | 396 EXPECT_TRUE(ais->Open()); |
400 bytes_per_packet = aisw.channels() * aisw.samples_per_packet() * | 397 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
401 (aisw.bits_per_sample() / 8); | 398 (aisw.bits_per_sample() / 8); |
402 | 399 |
403 EXPECT_CALL(sink, OnData( | 400 EXPECT_CALL(sink, OnData( |
404 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) | 401 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) |
405 .Times(AtLeast(10)) | 402 .Times(AtLeast(10)) |
406 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 403 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); |
407 ais->Start(&sink); | 404 ais->Start(&sink); |
408 loop.Run(); | 405 loop.Run(); |
409 ais->Stop(); | 406 ais->Stop(); |
410 ais.Close(); | 407 ais.Close(); |
411 | 408 |
412 // 5 ms packet size. | 409 // 5 ms packet size. |
413 | 410 |
414 count = 0; | 411 count = 0; |
415 ais.Reset(aisw.Create(samples_per_packet_10ms / 2)); | 412 ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); |
416 EXPECT_TRUE(ais->Open()); | 413 EXPECT_TRUE(ais->Open()); |
417 bytes_per_packet = aisw.channels() * aisw.samples_per_packet() * | 414 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
418 (aisw.bits_per_sample() / 8); | 415 (aisw.bits_per_sample() / 8); |
419 | 416 |
420 EXPECT_CALL(sink, OnData( | 417 EXPECT_CALL(sink, OnData( |
421 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) | 418 ais.get(), NotNull(), bytes_per_packet, Gt(bytes_per_packet), _)) |
422 .Times(AtLeast(10)) | 419 .Times(AtLeast(10)) |
423 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 420 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); |
424 ais->Start(&sink); | 421 ais->Start(&sink); |
425 loop.Run(); | 422 loop.Run(); |
426 ais->Stop(); | 423 ais->Stop(); |
427 ais.Close(); | 424 ais.Close(); |
428 } | 425 } |
429 | 426 |
430 // Test that we can capture loopback stream. | 427 // Test that we can capture loopback stream. |
431 TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { | 428 TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { |
432 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); | 429 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); |
433 if (!audio_manager->HasAudioOutputDevices() || !CoreAudioUtil::IsSupported()) | 430 if (!audio_manager->HasAudioOutputDevices() || !CoreAudioUtil::IsSupported()) |
434 return; | 431 return; |
435 | 432 |
436 AudioParameters params = audio_manager->GetInputStreamParameters( | 433 AudioParameters params = audio_manager->GetInputStreamParameters( |
437 AudioManagerBase::kLoopbackInputDeviceId); | 434 AudioManagerBase::kLoopbackInputDeviceId); |
| 435 EXPECT_EQ(params.effects(), 0); |
438 | 436 |
439 AudioParameters output_params = | 437 AudioParameters output_params = |
440 audio_manager->GetOutputStreamParameters(std::string()); | 438 audio_manager->GetOutputStreamParameters(std::string()); |
441 EXPECT_EQ(params.sample_rate(), output_params.sample_rate()); | 439 EXPECT_EQ(params.sample_rate(), output_params.sample_rate()); |
442 EXPECT_EQ(params.channel_layout(), output_params.channel_layout()); | 440 EXPECT_EQ(params.channel_layout(), output_params.channel_layout()); |
443 | 441 |
444 ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream( | 442 ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream( |
445 params, AudioManagerBase::kLoopbackInputDeviceId)); | 443 params, AudioManagerBase::kLoopbackInputDeviceId)); |
446 ASSERT_TRUE(stream->Open()); | 444 ASSERT_TRUE(stream->Open()); |
447 FakeAudioInputCallback sink; | 445 FakeAudioInputCallback sink; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 WriteToFileAudioSink file_sink(file_name); | 477 WriteToFileAudioSink file_sink(file_name); |
480 VLOG(0) << ">> Speak into the default microphone while recording."; | 478 VLOG(0) << ">> Speak into the default microphone while recording."; |
481 ais->Start(&file_sink); | 479 ais->Start(&file_sink); |
482 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 480 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
483 ais->Stop(); | 481 ais->Stop(); |
484 VLOG(0) << ">> Recording has stopped."; | 482 VLOG(0) << ">> Recording has stopped."; |
485 ais.Close(); | 483 ais.Close(); |
486 } | 484 } |
487 | 485 |
488 } // namespace media | 486 } // namespace media |
OLD | NEW |