Index: media/audio/win/audio_low_latency_input_win_unittest.cc |
diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc |
index 7e16bae23fcaf65fb470ce310b5c13109c78021c..f546ad3d0762d206f19833ae8f2556455b5d2bbe 100644 |
--- a/media/audio/win/audio_low_latency_input_win_unittest.cc |
+++ b/media/audio/win/audio_low_latency_input_win_unittest.cc |
@@ -4,10 +4,10 @@ |
#include "media/audio/win/audio_low_latency_input_win.h" |
-#include <windows.h> |
#include <mmsystem.h> |
#include <stddef.h> |
#include <stdint.h> |
+#include <windows.h> |
#include <memory> |
@@ -18,6 +18,7 @@ |
#include "base/path_service.h" |
#include "base/run_loop.h" |
#include "base/single_thread_task_runner.h" |
+#include "base/strings/stringprintf.h" |
#include "base/test/test_timeouts.h" |
#include "base/win/scoped_com_initializer.h" |
#include "media/audio/audio_device_description.h" |
@@ -64,9 +65,7 @@ class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { |
int num_received_audio_frames() const { return num_received_audio_frames_; } |
// Waits until OnData() is called on another thread. |
- void WaitForData() { |
- data_event_.Wait(); |
- } |
+ void WaitForData() { data_event_.Wait(); } |
void OnData(AudioInputStream* stream, |
const AudioBus* src, |
@@ -78,9 +77,7 @@ class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { |
data_event_.Signal(); |
} |
- void OnError(AudioInputStream* stream) override { |
- error_ = true; |
- } |
+ void OnError(AudioInputStream* stream) override { error_ = true; } |
private: |
int num_received_audio_frames_; |
@@ -108,7 +105,7 @@ class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback { |
binary_file_ = base::OpenFile(file_path, "wb"); |
DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; |
VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; |
- VLOG(0) << "bits_per_sample_:" << bits_per_sample_; |
+ VLOG(0) << ">> bits_per_sample_:" << bits_per_sample_; |
} |
~WriteToFileAudioSink() override { |
@@ -177,12 +174,17 @@ class AudioInputStreamWrapper { |
frames_per_buffer_ = default_params_.frames_per_buffer(); |
} |
+ AudioInputStreamWrapper(AudioManager* audio_manager, |
+ const AudioParameters& default_params) |
+ : audio_man_(audio_manager), default_params_(default_params) { |
+ EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); |
+ frames_per_buffer_ = default_params_.frames_per_buffer(); |
+ } |
+ |
~AudioInputStreamWrapper() {} |
// Creates AudioInputStream object using default parameters. |
- AudioInputStream* Create() { |
- return CreateInputStream(); |
- } |
+ AudioInputStream* Create() { return CreateInputStream(); } |
// Creates AudioInputStream object using non-default parameters where the |
// frame size is modified. |
@@ -225,8 +227,7 @@ static AudioInputStream* CreateDefaultAudioInputStream( |
class ScopedAudioInputStream { |
public: |
- explicit ScopedAudioInputStream(AudioInputStream* stream) |
- : stream_(stream) {} |
+ explicit ScopedAudioInputStream(AudioInputStream* stream) : stream_(stream) {} |
~ScopedAudioInputStream() { |
if (stream_) |
@@ -239,9 +240,7 @@ class ScopedAudioInputStream { |
stream_ = NULL; |
} |
- AudioInputStream* operator->() { |
- return stream_; |
- } |
+ AudioInputStream* operator->() { return stream_; } |
AudioInputStream* get() const { return stream_; } |
@@ -404,8 +403,8 @@ TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { |
count = 0; |
ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); |
EXPECT_TRUE(ais->Open()); |
- bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
- (aisw.bits_per_sample() / 8); |
+ bytes_per_packet = |
+ aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
{ |
base::RunLoop run_loop; |
@@ -425,8 +424,8 @@ TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { |
count = 0; |
ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); |
EXPECT_TRUE(ais->Open()); |
- bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
- (aisw.bits_per_sample() / 8); |
+ bytes_per_packet = |
+ aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
{ |
base::RunLoop run_loop; |
@@ -483,11 +482,11 @@ TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { |
// Name of the output PCM file containing captured data. The output file |
// will be stored in the directory containing 'media_unittests.exe'. |
// Example of full name: \src\build\Debug\out_stereo_10sec.pcm. |
- const char* file_name = "out_stereo_10sec.pcm"; |
+ const char* file_name = "out_10sec.pcm"; |
AudioInputStreamWrapper aisw(audio_manager_.get()); |
ScopedAudioInputStream ais(aisw.Create()); |
- EXPECT_TRUE(ais->Open()); |
+ ASSERT_TRUE(ais->Open()); |
VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]"; |
WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); |
@@ -499,4 +498,63 @@ TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { |
ais.Close(); |
} |
+TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) { |
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); |
+ |
+ // This is basically the same test as WASAPIAudioInputStreamRecordToFile |
+ // except it forces use of a different sample rate than is preferred by |
+ // the hardware. This functionality is offered while we still have code |
+ // that doesn't ask the lower levels for what the preferred audio parameters |
+ // are (and previously depended on the old Wave API to do this automatically). |
+ |
+ struct TestData { |
+ const int rate; |
+ const int frames; |
+ ChannelLayout layout; |
+ } tests[] = { |
+ {8000, 80, CHANNEL_LAYOUT_MONO}, |
+ {8000, 80, CHANNEL_LAYOUT_STEREO}, |
+ {44100, 441, CHANNEL_LAYOUT_MONO}, |
+ {44100, 1024, CHANNEL_LAYOUT_STEREO}, |
+ }; |
+ |
+ for (const auto& test : tests) { |
+ AudioParameters params; |
+ ASSERT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( |
+ AudioDeviceDescription::kDefaultDeviceId, false, ¶ms))); |
+ |
+ VLOG(0) << ">> Hardware sample rate: " << params.sample_rate() << " [Hz]"; |
+ VLOG(0) << ">> Hardware channel layout: " |
+ << ChannelLayoutToString(params.channel_layout()); |
+ |
+ // Pick a somewhat difficult sample rate to convert too. |
+ // If the sample rate is 8kHz, 16kHz, 32kHz, 48kHz etc, we convert to |
+ // 44.1kHz. |
+ // Otherwise (e.g. 44.1kHz, 22.05kHz etc) we convert to 48kHz. |
+ const int hw_sample_rate = params.sample_rate(); |
+ params.Reset(params.format(), test.layout, test.rate, |
+ params.bits_per_sample(), test.frames); |
+ |
+ std::string file_name(base::StringPrintf( |
+ "resampled_10sec_%i_to_%i_%s.pcm", hw_sample_rate, params.sample_rate(), |
+ ChannelLayoutToString(params.channel_layout()))); |
+ |
+ AudioInputStreamWrapper aisw(audio_manager_.get(), params); |
+ ScopedAudioInputStream ais(aisw.Create()); |
+ ASSERT_TRUE(ais->Open()); |
+ |
+ VLOG(0) << ">> Resampled rate will be: " << aisw.sample_rate() << " [Hz]"; |
+ VLOG(0) << ">> New layout will be: " |
+ << ChannelLayoutToString(params.channel_layout()); |
+ WriteToFileAudioSink file_sink(file_name.c_str(), aisw.bits_per_sample()); |
+ VLOG(0) << ">> Speak into the default microphone while recording."; |
+ ais->Start(&file_sink); |
+ base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
+ // base::PlatformThread::Sleep(base::TimeDelta::FromMinutes(10)); |
+ ais->Stop(); |
+ VLOG(0) << ">> Recording has stopped."; |
+ ais.Close(); |
+ } |
+} |
+ |
} // namespace media |