| 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
|
|
|