15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmsystem.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/audio_low_latency_input_win.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Gt; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++*count >= limit) { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) MOCK_METHOD4(OnData, 426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void(AudioInputStream* stream, 436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) uint32 hardware_delay_bytes, 456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) double volume)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD1(OnError, void(AudioInputStream* stream)); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FakeAudioInputCallback() 526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : error_(false), 536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) data_event_(false, false), 546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) num_received_audio_frames_(0) {} 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool error() const { return error_; } 576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int num_received_audio_frames() const { return num_received_audio_frames_; } 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Waits until OnData() is called on another thread. 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void WaitForData() { 61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) data_event_.Wait(); 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnData(AudioInputStream* stream, 656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) uint32 hardware_delay_bytes, 676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) double volume) OVERRIDE { 686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_NE(hardware_delay_bytes, 0u); 696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) num_received_audio_frames_ += src->frames(); 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) data_event_.Signal(); 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(AudioInputStream* stream) OVERRIDE { 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) error_ = true; 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int num_received_audio_frames_; 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent data_event_; 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool error_; 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FakeAudioInputCallback); 83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This audio sink implementation should be used for manual tests only since 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the recorded data is stored on a raw binary data file. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocate space for ~10 seconds of data @ 48kHz in stereo: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 bytes per sample, 2 channels, 10ms @ 48kHz, 10 seconds <=> 1920000 bytes. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxBufferSize = 2 * 2 * 480 * 100 * 10; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) explicit WriteToFileAudioSink(const char* file_name, int bits_per_sample) 946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : bits_per_sample_(bits_per_sample), 956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) buffer_(0, kMaxBufferSize), 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write_(0) { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_path)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_path = file_path.AppendASCII(file_name); 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) binary_file_ = base::OpenFile(file_path, "wb"); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; 1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) VLOG(0) << "bits_per_sample_:" << bits_per_sample_; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WriteToFileAudioSink() { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_written = 0; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (bytes_written < bytes_to_write_) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* chunk; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int chunk_size; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop writing if no more data is available. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer_.GetCurrentChunk(&chunk, &chunk_size)) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write recorded data chunk to the file and prepare for next chunk. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fwrite(chunk, 1, chunk_size, binary_file_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.Seek(chunk_size); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_written += chunk_size; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CloseFile(binary_file_); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioInputStream::AudioInputCallback implementation. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnData(AudioInputStream* stream, 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 hardware_delay_bytes, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double volume) { 1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_EQ(bits_per_sample_, 16); 1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int num_samples = src->frames() * src->channels(); 1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<int16> interleaved(new int16[num_samples]); 1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int bytes_per_sample = sizeof(*interleaved); 1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); 1346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store data data in a temporary buffer to avoid making blocking 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fwrite() calls in the audio callback. The complete buffer will be 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // written to file in the destructor. 1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int size = bytes_per_sample * num_samples; 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (buffer_.Append((const uint8*)interleaved.get(), size)) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write_ += size; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnError(AudioInputStream* stream) {} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int bits_per_sample_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::SeekableBuffer buffer_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* binary_file_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_write_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which ensures that we are not running on the build 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bots and that at least one valid input device can be found. We also 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verify that we are not running on XP since the low-latency (WASAPI- 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// based) version requires Windows Vista or higher. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CanRunAudioTests(AudioManager* audio_man) { 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CoreAudioUtil::IsSupported()) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "This tests requires Windows Vista or higher."; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(henrika): note that we use Wave today to query the number of 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // existing input devices. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool input = audio_man->HasAudioInputDevices(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(WARNING, !input) << "No input device detected."; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return input; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioInputStream object but 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also allows the user to modify the default settings. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioInputStreamWrapper { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit AudioInputStreamWrapper(AudioManager* audio_manager) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : com_init_(ScopedCOMInitializer::kMTA), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_man_(audio_manager), 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_params_( 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_manager->GetInputStreamParameters( 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioManagerBase::kDefaultDeviceId)) { 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frames_per_buffer_ = default_params_.frames_per_buffer(); 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We expect the default buffer size to be a 10ms buffer. 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(frames_per_buffer_, sample_rate() / 100); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~AudioInputStreamWrapper() {} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates AudioInputStream object using default parameters. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStream* Create() { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateInputStream(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates AudioInputStream object using non-default parameters where the 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frame size is modified. 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioInputStream* Create(int frames_per_buffer) { 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frames_per_buffer_ = frames_per_buffer; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateInputStream(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters::Format format() const { return default_params_.format(); } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int channels() const { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ChannelLayoutToChannelCount(default_params_.channel_layout()); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int bits_per_sample() const { return default_params_.bits_per_sample(); } 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sample_rate() const { return default_params_.sample_rate(); } 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int frames_per_buffer() const { return frames_per_buffer_; } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStream* CreateInputStream() { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStream* ais = audio_man_->MakeAudioInputStream( 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters(format(), default_params_.channel_layout(), 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sample_rate(), bits_per_sample(), frames_per_buffer_, 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_params_.effects()), 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioManagerBase::kDefaultDeviceId); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ais; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCOMInitializer com_init_; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioManager* audio_man_; 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AudioParameters default_params_; 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int frames_per_buffer_; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioInputStream object. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static AudioInputStream* CreateDefaultAudioInputStream( 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioManager* audio_manager) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStreamWrapper aisw(audio_manager); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStream* ais = aisw.Create(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ais; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class ScopedAudioInputStream { 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit ScopedAudioInputStream(AudioInputStream* stream) 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : stream_(stream) {} 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ~ScopedAudioInputStream() { 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (stream_) 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_->Close(); 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void Close() { 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (stream_) 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_->Close(); 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_ = NULL; 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioInputStream* operator->() { 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return stream_; 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioInputStream* get() const { return stream_; } 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void Reset(AudioInputStream* new_stream) { 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Close(); 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_ = new_stream; 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioInputStream* stream_; 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream); 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can retrieve the current hardware/mixing sample rate 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for all available input devices. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) { 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve a list of all available input devices. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioDeviceNames device_names; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_manager->GetAudioInputDeviceNames(&device_names); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scan all available input devices and repeat the same test for all of them. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (media::AudioDeviceNames::const_iterator it = device_names.begin(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != device_names.end(); ++it) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the hardware sample rate given a specified audio input device. 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters params = WASAPIAudioInputStream::GetInputStreamParameters( 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->unique_id); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_GE(params.sample_rate(), 0); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Create(), Close() calling sequence. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais( 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateDefaultAudioInputStream(audio_manager.get())); 295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Close() calling sequence. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais( 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateDefaultAudioInputStream(audio_manager.get())); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Close() calling sequence. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais( 315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateDefaultAudioInputStream(audio_manager.get())); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockAudioInputCallback sink; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Stop(), Close() calling sequence. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais( 328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateDefaultAudioInputStream(audio_manager.get())); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockAudioInputCallback sink; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test some additional calling sequences. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais( 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateDefaultAudioInputStream(audio_manager.get())); 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WASAPIAudioInputStream* wais = 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<WASAPIAudioInputStream*>(ais.get()); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open(), Open() should fail the second time. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ais->Open()); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockAudioInputCallback sink; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start(), Start() is a valid calling sequence (second call does nothing). 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(wais->started()); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(wais->started()); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop(), Stop() is a valid calling sequence (second call does nothing). 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(wais->started()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(wais->started()); 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForUI loop; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10 ms packet size. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create default WASAPI input stream which records in stereo using 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the shared mixing rate. The default buffer size is 10ms. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStreamWrapper aisw(audio_manager.get()); 379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais(aisw.Create()); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockAudioInputCallback sink; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Derive the expected size in bytes of each recorded packet. 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (aisw.bits_per_sample() / 8); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use 10ms packets and will run the test until ten packets are received. 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All should contain valid packets of the same size and a valid delay 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // estimate. 3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _)) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AtLeast(10)) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loop.Run(); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store current packet size (to be used in the subsequent tests). 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int frames_per_buffer_10ms = aisw.frames_per_buffer(); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 20 ms packet size. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count = 0; 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (aisw.bits_per_sample() / 8); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _)) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AtLeast(10)) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loop.Run(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5 ms packet size. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count = 0; 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (aisw.bits_per_sample() / 8); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _)) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AtLeast(10)) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&sink); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loop.Run(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Test that we can capture a stream in loopback. 437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!audio_manager->HasAudioOutputDevices() || !CoreAudioUtil::IsSupported()) 440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters params = audio_manager->GetInputStreamParameters( 443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioManagerBase::kLoopbackInputDeviceId); 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(params.effects(), 0); 445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters output_params = 447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_manager->GetOutputStreamParameters(std::string()); 448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_EQ(params.sample_rate(), output_params.sample_rate()); 449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_EQ(params.channel_layout(), output_params.channel_layout()); 450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream( 452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params, AudioManagerBase::kLoopbackInputDeviceId)); 453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_TRUE(stream->Open()); 454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FakeAudioInputCallback sink; 455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream->Start(&sink); 456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_FALSE(sink.error()); 457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sink.WaitForData(); 459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream.Close(); 460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_GT(sink.num_received_audio_frames(), 0); 462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_FALSE(sink.error()); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is intended for manual tests and should only be enabled 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it is required to store the captured data on a local file. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By default, GTest will print out YOU HAVE 1 DISABLED TEST. 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To include disabled tests in test execution, just invoke the test program 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// environment variable to a value greater than 0. 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CanRunAudioTests(audio_manager.get())) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Name of the output PCM file containing captured data. The output file 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be stored in the directory containing 'media_unittests.exe'. 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Example of full name: \src\build\Debug\out_stereo_10sec.pcm. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* file_name = "out_stereo_10sec.pcm"; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputStreamWrapper aisw(audio_manager.get()); 482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScopedAudioInputStream ais(aisw.Create()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ais->Open()); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]"; 4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); 487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Speak into the default microphone while recording."; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Start(&file_sink); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(TestTimeouts::action_timeout()); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ais->Stop(); 491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Recording has stopped."; 492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ais.Close(); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 496