blob: c46309b06b7b9a263cf29aa3f3c268bf9d291d06 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/media/audio/audio_core/audio_input.h"
#include "src/media/audio/audio_core/audio_device_manager.h"
#include "src/media/audio/audio_core/audio_driver.h"
#include "src/media/audio/audio_core/loudness_transform.h"
#include "src/media/audio/audio_core/testing/fake_audio_driver.h"
#include "src/media/audio/audio_core/testing/threading_model_fixture.h"
namespace media::audio {
namespace {
constexpr size_t kRingBufferSizeBytes = 8 * PAGE_SIZE;
class AudioInputTest : public testing::ThreadingModelFixture,
public ::testing::WithParamInterface<uint32_t> {
protected:
AudioInputTest()
: ThreadingModelFixture(
ProcessConfig::Builder()
.AddDeviceProfile({std::nullopt, DeviceConfig::InputDeviceProfile(GetParam())})
.SetDefaultVolumeCurve(
VolumeCurve::DefaultForMinGain(VolumeCurve::kDefaultGainForMinVolume))
.Build()) {}
void SetUp() override {
ThreadingModelFixture::SetUp();
zx::channel c1, c2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &c1, &c2));
remote_driver_ = std::make_unique<testing::FakeAudioDriverV1>(
std::move(c1), threading_model().FidlDomain().dispatcher());
ASSERT_NE(remote_driver_, nullptr);
input_ = AudioInput::Create("", std::move(c2), &threading_model(), &context().device_manager(),
&context().link_matrix());
ASSERT_NE(input_, nullptr);
ring_buffer_mapper_ = remote_driver_->CreateRingBuffer(kRingBufferSizeBytes);
ASSERT_NE(ring_buffer_mapper_.start(), nullptr);
}
std::unique_ptr<testing::FakeAudioDriverV1> remote_driver_;
std::shared_ptr<AudioInput> input_;
fzl::VmoMapper ring_buffer_mapper_;
};
TEST_P(AudioInputTest, RequestHardwareRateInConfigIfSupported) {
// Publish a format that has a matching sample rate, and also formats with double and half the
// requested rate.
remote_driver_->set_formats({{
.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT,
.min_frames_per_second = GetParam(),
.max_frames_per_second = GetParam(),
.min_channels = 1,
.max_channels = 1,
.flags = ASF_RANGE_FLAG_FPS_CONTINUOUS,
},
{
.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT,
.min_frames_per_second = 2 * GetParam(),
.max_frames_per_second = 2 * GetParam(),
.min_channels = 1,
.max_channels = 1,
.flags = ASF_RANGE_FLAG_FPS_CONTINUOUS,
},
{
.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT,
.min_frames_per_second = GetParam() / 2,
.max_frames_per_second = GetParam() / 2,
.min_channels = 1,
.max_channels = 1,
.flags = ASF_RANGE_FLAG_FPS_CONTINUOUS,
}});
remote_driver_->Start();
threading_model().FidlDomain().ScheduleTask(input_->Startup());
RunLoopUntilIdle();
auto format = input_->driver()->GetFormat();
ASSERT_TRUE(format);
ASSERT_EQ(format->frames_per_second(), GetParam());
}
TEST_P(AudioInputTest, FallBackToAlternativeRateIfPreferredRateIsNotSupported) {
const uint32_t kSupportedRate = GetParam() * 2;
remote_driver_->set_formats({{
.sample_formats = AUDIO_SAMPLE_FORMAT_16BIT,
.min_frames_per_second = kSupportedRate,
.max_frames_per_second = kSupportedRate,
.min_channels = 1,
.max_channels = 1,
.flags = ASF_RANGE_FLAG_FPS_CONTINUOUS,
}});
remote_driver_->Start();
threading_model().FidlDomain().ScheduleTask(input_->Startup());
RunLoopUntilIdle();
auto format = input_->driver()->GetFormat();
ASSERT_TRUE(format);
ASSERT_EQ(format->frames_per_second(), kSupportedRate);
ASSERT_NE(kSupportedRate, GetParam());
}
INSTANTIATE_TEST_SUITE_P(AudioInputTestInstance, AudioInputTest,
::testing::Values(24000, 48000, 96000));
class AudioInputTestDriverV2 : public testing::ThreadingModelFixture,
public ::testing::WithParamInterface<uint32_t> {
protected:
AudioInputTestDriverV2()
: ThreadingModelFixture(
ProcessConfig::Builder()
.AddDeviceProfile({std::nullopt, DeviceConfig::InputDeviceProfile(GetParam())})
.SetDefaultVolumeCurve(
VolumeCurve::DefaultForMinGain(VolumeCurve::kDefaultGainForMinVolume))
.Build()) {}
void SetUp() override {
ThreadingModelFixture::SetUp();
zx::channel c1, c2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &c1, &c2));
remote_driver_ = std::make_unique<testing::FakeAudioDriverV2>(
std::move(c1), threading_model().FidlDomain().dispatcher());
ASSERT_NE(remote_driver_, nullptr);
fidl::InterfaceHandle<fuchsia::hardware::audio::StreamConfig> stream_config = {};
stream_config.set_channel(std::move(c2));
input_ = AudioInput::Create("", std::move(stream_config), &threading_model(),
&context().device_manager(), &context().link_matrix());
ASSERT_NE(input_, nullptr);
ring_buffer_mapper_ = remote_driver_->CreateRingBuffer(kRingBufferSizeBytes);
ASSERT_NE(ring_buffer_mapper_.start(), nullptr);
}
std::unique_ptr<testing::FakeAudioDriverV2> remote_driver_;
std::shared_ptr<AudioInput> input_;
fzl::VmoMapper ring_buffer_mapper_;
};
TEST_P(AudioInputTestDriverV2, RequestHardwareRateInConfigIfSupported) {
// Publish a format that has a matching sample rate, and also formats with double and half the
// requested rate.
fuchsia::hardware::audio::PcmSupportedFormats formats = {};
formats.number_of_channels.push_back(1);
formats.sample_formats.push_back(fuchsia::hardware::audio::SampleFormat::PCM_SIGNED);
formats.bytes_per_sample.push_back(2);
formats.valid_bits_per_sample.push_back(16);
formats.frame_rates.push_back(GetParam());
formats.frame_rates.push_back(2 * GetParam());
formats.frame_rates.push_back(GetParam() / 2);
remote_driver_->set_formats(std::move(formats));
remote_driver_->Start();
threading_model().FidlDomain().ScheduleTask(input_->Startup());
RunLoopUntilIdle();
auto format = input_->driver()->GetFormat();
ASSERT_TRUE(format);
ASSERT_EQ(format->frames_per_second(), GetParam());
}
TEST_P(AudioInputTestDriverV2, FallBackToAlternativeRateIfPreferredRateIsNotSupported) {
ASSERT_NE(GetParam(), static_cast<uint32_t>(0)); // Invalid frame rate passed as test parameter.
const uint32_t kSupportedRate = GetParam() * 2;
fuchsia::hardware::audio::PcmSupportedFormats formats = {};
formats.number_of_channels.push_back(1);
formats.sample_formats.push_back(fuchsia::hardware::audio::SampleFormat::PCM_SIGNED);
formats.bytes_per_sample.push_back(2);
formats.valid_bits_per_sample.push_back(16);
formats.frame_rates.push_back(kSupportedRate);
remote_driver_->set_formats(std::move(formats));
remote_driver_->Start();
threading_model().FidlDomain().ScheduleTask(input_->Startup());
RunLoopUntilIdle();
auto format = input_->driver()->GetFormat();
ASSERT_TRUE(format);
ASSERT_EQ(format->frames_per_second(), kSupportedRate);
}
INSTANTIATE_TEST_SUITE_P(AudioInputTestDriverV2Instance, AudioInputTestDriverV2,
::testing::Values(24000, 48000, 96000));
} // namespace
} // namespace media::audio