diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp index d219fa41c3..337089db49 100644 --- a/audio/aidl/vts/Android.bp +++ b/audio/aidl/vts/Android.bp @@ -151,6 +151,9 @@ cc_test { name: "VtsHalVirtualizerTargetTest", defaults: ["VtsHalAudioEffectTargetTestDefaults"], srcs: ["VtsHalVirtualizerTargetTest.cpp"], + shared_libs: [ + "libaudioutils", + ], } cc_test { diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp index 0c24f90fce..b4a2f417f1 100644 --- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp +++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp @@ -16,11 +16,14 @@ #define LOG_TAG "VtsHalVirtualizerTest" #include +#include +#include #include "EffectHelper.h" using namespace android; +using aidl::android::hardware::audio::common::getChannelCount; using aidl::android::hardware::audio::effect::Descriptor; using aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer; using aidl::android::hardware::audio::effect::IEffect; @@ -29,6 +32,82 @@ using aidl::android::hardware::audio::effect::Parameter; using aidl::android::hardware::audio::effect::Virtualizer; using android::hardware::audio::common::testing::detail::TestExecutionTracer; +class VirtualizerHelper : public EffectHelper { + public: + void SetUpVirtualizer() { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + initFrameCount(); + Parameter::Specific specific = getDefaultParamSpecific(); + Parameter::Common common = EffectHelper::createParamCommon( + 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */, + kSamplingFrequency /* oSampleRate */, mInputFrameCount /* iFrameCount */, + mInputFrameCount /* oFrameCount */); + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDownVirtualizer() { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + mOpenEffectReturn = IEffect::OpenEffectReturn{}; + } + + Parameter::Specific getDefaultParamSpecific() { + Virtualizer vr = Virtualizer::make(0); + Parameter::Specific specific = + Parameter::Specific::make(vr); + return specific; + } + + Parameter createVirtualizerStrengthParam(int param) { + return Parameter::make( + Parameter::Specific::make( + Virtualizer::make(param))); + } + + void initFrameCount() { + mInputFrameCount = kBufferSize / kChannelCount; + mOutputFrameCount = kBufferSize / kChannelCount; + } + + bool isStrengthValid(int level) { + auto vir = Virtualizer::make(level); + return isParameterValid(vir, mDescriptor); + } + + void setAndVerifyStrength(int param, binder_exception_t expected) { + auto expectedParam = createVirtualizerStrengthParam(param); + EXPECT_STATUS(expected, mEffect->setParameter(expectedParam)) << expectedParam.toString(); + + if (expected == EX_NONE) { + Virtualizer::Id vrlId = + Virtualizer::Id::make(Virtualizer::strengthPm); + + auto id = Parameter::Id::make(vrlId); + // get parameter + Parameter getParam; + // if set success, then get should match + EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam)); + EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + + static constexpr int kSamplingFrequency = 44100; + static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO; + static constexpr int kDurationMilliSec = 2000; + static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000; + int kChannelCount = getChannelCount( + AudioChannelLayout::make(kDefaultChannelLayout)); + long mInputFrameCount; + long mOutputFrameCount; + std::shared_ptr mFactory; + std::shared_ptr mEffect; + IEffect::OpenEffectReturn mOpenEffectReturn; + Descriptor mDescriptor; +}; + /** * Here we focus on specific parameter checking, general IEffect interfaces testing performed in * VtsAudioEffectTargetTest. @@ -44,89 +123,82 @@ using VirtualizerParamTestParam = std::tuple */ class VirtualizerParamTest : public ::testing::TestWithParam, - public EffectHelper { + public VirtualizerHelper { public: VirtualizerParamTest() : mParamStrength(std::get(GetParam())) { std::tie(mFactory, mDescriptor) = std::get(GetParam()); } + void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVirtualizer()); } + void TearDown() override { TearDownVirtualizer(); } - void SetUp() override { - ASSERT_NE(nullptr, mFactory); - ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); - - Parameter::Specific specific = getDefaultParamSpecific(); - Parameter::Common common = EffectHelper::createParamCommon( - 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */, - kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */); - IEffect::OpenEffectReturn ret; - ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE)); - ASSERT_NE(nullptr, mEffect); - } - - void TearDown() override { - ASSERT_NO_FATAL_FAILURE(close(mEffect)); - ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); - } - - Parameter::Specific getDefaultParamSpecific() { - Virtualizer vr = Virtualizer::make(0); - Parameter::Specific specific = - Parameter::Specific::make(vr); - return specific; - } - - static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; - std::shared_ptr mFactory; - std::shared_ptr mEffect; - Descriptor mDescriptor; int mParamStrength = 0; +}; - void SetAndGetVirtualizerParameters() { - for (auto& it : mTags) { - auto& tag = it.first; - auto& vr = it.second; +TEST_P(VirtualizerParamTest, SetAndGetStrength) { + ASSERT_NO_FATAL_FAILURE(setAndVerifyStrength( + mParamStrength, isStrengthValid(mParamStrength) ? EX_NONE : EX_ILLEGAL_ARGUMENT)); +} - // validate parameter - Descriptor desc; - ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); - const bool valid = isParameterValid(it.second, desc); - const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; +enum ProcessTestParam { PROCESS_INSTANCE_NAME, PROCESS_ZERO_INPUT }; +using VirtualizerProcessTestParam = + std::tuple, Descriptor>, bool>; - // set parameter - Parameter expectParam; - Parameter::Specific specific; - specific.set(vr); - expectParam.set(specific); - EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); +class VirtualizerProcessTest : public ::testing::TestWithParam, + public VirtualizerHelper { + public: + VirtualizerProcessTest() : mZeroInput(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } - // only get if parameter in range and set success - if (expected == EX_NONE) { - Parameter getParam; - Parameter::Id id; - Virtualizer::Id vrId; - vrId.set(tag); - id.set(vrId); - // if set success, then get should match - EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam)); - EXPECT_EQ(expectParam, getParam); + void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVirtualizer()); } + void TearDown() override { TearDownVirtualizer(); } + + void generateInput(std::vector& buffer) { + if (mZeroInput) { + std::fill(buffer.begin(), buffer.end(), 0); + } else { + int frequency = 100; + for (size_t i = 0; i < buffer.size(); i++) { + buffer[i] = sin(2 * M_PI * frequency * i / kSamplingFrequency); } } } - void addStrengthParam(int strength) { - Virtualizer vr; - vr.set(strength); - mTags.push_back({Virtualizer::strengthPm, vr}); - } - - private: - std::vector> mTags; - void CleanUp() { mTags.clear(); } + static constexpr float kAbsError = 0.00001; + bool mZeroInput; }; -TEST_P(VirtualizerParamTest, SetAndGetStrength) { - EXPECT_NO_FATAL_FAILURE(addStrengthParam(mParamStrength)); - SetAndGetVirtualizerParameters(); +TEST_P(VirtualizerProcessTest, IncreasingStrength) { + std::vector input(kBufferSize); + std::vector output(kBufferSize); + std::vector strengths = {250, 500, 750, 1000}; + + generateInput(input); + + const float inputRmse = + audio_utils_compute_energy_mono(input.data(), AUDIO_FORMAT_PCM_FLOAT, input.size()); + + for (int strength : strengths) { + // Skipping the further steps for unnsupported Strength values + if (!isStrengthValid(strength)) { + continue; + } + setAndVerifyStrength(strength, EX_NONE); + ASSERT_NO_FATAL_FAILURE( + processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn)); + + const float outputRmse = audio_utils_compute_energy_mono( + output.data(), AUDIO_FORMAT_PCM_FLOAT, output.size()); + + if (inputRmse != 0) { + EXPECT_NE(outputRmse, 0); + if (strength != 0) { + EXPECT_GT(abs(outputRmse - inputRmse), kAbsError); + } + } else { + EXPECT_NEAR(outputRmse, inputRmse, kAbsError); + } + } } std::vector, Descriptor>> kDescPair; @@ -149,6 +221,22 @@ INSTANTIATE_TEST_SUITE_P( GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VirtualizerParamTest); +INSTANTIATE_TEST_SUITE_P( + VirtualizerTest, VirtualizerProcessTest, + ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, getEffectTypeUuidVirtualizer())), + testing::Bool()), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string isInputZero = std::to_string(std::get(info.param)); + std::string name = getPrefix(descriptor) + "_isInputZero_" + isInputZero; + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VirtualizerProcessTest); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());