diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml index e859a0e083..9547865085 100644 --- a/audio/aidl/default/audio_effects_config.xml +++ b/audio/aidl/default/audio_effects_config.xml @@ -78,7 +78,6 @@ - diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp index 337089db49..b2368319b5 100644 --- a/audio/aidl/vts/Android.bp +++ b/audio/aidl/vts/Android.bp @@ -145,6 +145,9 @@ cc_test { name: "VtsHalPresetReverbTargetTest", defaults: ["VtsHalAudioEffectTargetTestDefaults"], srcs: ["VtsHalPresetReverbTargetTest.cpp"], + shared_libs: [ + "libaudioutils", + ], } cc_test { diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h index 82a07fdc10..0d1e0dce0e 100644 --- a/audio/aidl/vts/EffectHelper.h +++ b/audio/aidl/vts/EffectHelper.h @@ -70,6 +70,8 @@ typedef ::android::AidlMessageQueue #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::getEffectTypeUuidPresetReverb; using aidl::android::hardware::audio::effect::IEffect; @@ -30,6 +33,68 @@ using aidl::android::hardware::audio::effect::Parameter; using aidl::android::hardware::audio::effect::PresetReverb; using android::hardware::audio::common::testing::detail::TestExecutionTracer; +class PresetReverbHelper : public EffectHelper { + public: + void SetUpPresetReverb() { + 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 */, kSamplingFrequency /* iSampleRate */, + kSamplingFrequency /* oSampleRate */, mFrameCount /* iFrameCount */, + mFrameCount /* oFrameCount */); + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDownPresetReverb() { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + mOpenEffectReturn = IEffect::OpenEffectReturn{}; + } + + Parameter::Specific getDefaultParamSpecific() { + PresetReverb pr = PresetReverb::make(kDefaultPreset); + Parameter::Specific specific = + Parameter::Specific::make(pr); + return specific; + } + + Parameter createPresetReverbParam(const PresetReverb::Presets& param) { + return Parameter::make( + Parameter::Specific::make( + PresetReverb::make(param))); + } + + void setAndVerifyPreset(const PresetReverb::Presets& param) { + auto expectedParam = createPresetReverbParam(param); + EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectedParam)) << expectedParam.toString(); + + PresetReverb::Id revId = + PresetReverb::Id::make(PresetReverb::preset); + + auto id = Parameter::Id::make(revId); + // get parameter + Parameter getParam; + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString() + << "\ngetParam:" << getParam.toString(); + } + + static constexpr int kSamplingFrequency = 44100; + static constexpr int kDurationMilliSec = 2000; + static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000; + int mStereoChannelCount = + getChannelCount(AudioChannelLayout::make( + AudioChannelLayout::LAYOUT_STEREO)); + PresetReverb::Presets kDefaultPreset = PresetReverb::Presets::NONE; + int mFrameCount = kBufferSize / mStereoChannelCount; + 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,88 +109,116 @@ const std::vector kPresetsValues{ ndk::enum_range().end()}; class PresetReverbParamTest : public ::testing::TestWithParam, - public EffectHelper { + public PresetReverbHelper { public: - PresetReverbParamTest() : mParamPresets(std::get(GetParam())) { + PresetReverbParamTest() : mParamPreset(std::get(GetParam())) { std::tie(mFactory, mDescriptor) = std::get(GetParam()); } - void SetUp() override { - ASSERT_NE(nullptr, mFactory); - ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb()); } - 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 { TearDownPresetReverb(); } - void TearDown() override { - ASSERT_NO_FATAL_FAILURE(close(mEffect)); - ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); - } - - static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; - std::shared_ptr mFactory; - std::shared_ptr mEffect; - Descriptor mDescriptor; - PresetReverb::Presets mParamPresets = PresetReverb::Presets::NONE; - - void SetAndGetPresetReverbParameters() { - for (auto& it : mTags) { - auto& tag = it.first; - auto& pr = it.second; - - // 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; - - // set parameter - Parameter expectParam; - Parameter::Specific specific; - specific.set(pr); - expectParam.set(specific); - // All values are valid, set parameter should succeed - EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); - - // get parameter - Parameter getParam; - Parameter::Id id; - PresetReverb::Id prId; - prId.set(tag); - id.set(prId); - EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam)); - - EXPECT_EQ(expectParam, getParam); - } - } - - void addPresetsParam(PresetReverb::Presets preset) { - PresetReverb pr; - pr.set(preset); - mTags.push_back({PresetReverb::preset, pr}); - } - - Parameter::Specific getDefaultParamSpecific() { - PresetReverb pr = PresetReverb::make(PresetReverb::Presets::NONE); - Parameter::Specific specific = - Parameter::Specific::make(pr); - return specific; - } - - private: - std::vector> mTags; - void CleanUp() { mTags.clear(); } + const PresetReverb::Presets mParamPreset; }; TEST_P(PresetReverbParamTest, SetAndGetPresets) { - EXPECT_NO_FATAL_FAILURE(addPresetsParam(mParamPresets)); - SetAndGetPresetReverbParameters(); + ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(mParamPreset)); +} + +using PresetReverbProcessTestParam = std::pair, Descriptor>; + +class PresetReverbProcessTest : public ::testing::TestWithParam, + public PresetReverbHelper { + public: + PresetReverbProcessTest() { + std::tie(mFactory, mDescriptor) = GetParam(); + generateSineWaveInput(); + } + + void SetUp() override { + SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags); + ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb()); + } + void TearDown() override { + SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags); + ASSERT_NO_FATAL_FAILURE(TearDownPresetReverb()); + } + + void generateSineWaveInput() { + int frequency = 1000; + for (size_t i = 0; i < kBufferSize; i++) { + mInput.push_back(sin(2 * M_PI * frequency * i / kSamplingFrequency)); + } + } + + bool isAuxiliary() { + return mDescriptor.common.flags.type == + aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY; + } + + float computeReverbOutputEnergy(std::vector output) { + if (!isAuxiliary()) { + // Extract auxiliary output + for (size_t i = 0; i < output.size(); i++) { + output[i] -= mInput[i]; + } + } + return (audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT, + output.size())); + } + + void setPresetAndProcess(const PresetReverb::Presets& preset, std::vector& output) { + ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(preset)); + ASSERT_NO_FATAL_FAILURE( + processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn)); + } + + void validateIncreasingEnergy(const std::vector& presets) { + float baseOutputEnergy = 0; + + for (PresetReverb::Presets preset : presets) { + std::vector output(kBufferSize); + setPresetAndProcess(preset, output); + float outputEnergy = computeReverbOutputEnergy(output); + + ASSERT_GT(outputEnergy, baseOutputEnergy); + baseOutputEnergy = outputEnergy; + } + } + + std::vector mInput; +}; + +TEST_P(PresetReverbProcessTest, DecreasingRoomSize) { + std::vector roomPresets = {PresetReverb::Presets::LARGEROOM, + PresetReverb::Presets::MEDIUMROOM, + PresetReverb::Presets::SMALLROOM}; + validateIncreasingEnergy(roomPresets); +} + +TEST_P(PresetReverbProcessTest, DecreasingHallSize) { + std::vector hallPresets = {PresetReverb::Presets::LARGEHALL, + PresetReverb::Presets::MEDIUMHALL}; + validateIncreasingEnergy(hallPresets); +} + +TEST_P(PresetReverbProcessTest, PresetPlate) { + std::vector output(kBufferSize); + + setPresetAndProcess(PresetReverb::Presets::PLATE, output); + float outputEnergy = computeReverbOutputEnergy(output); + // Since there is no comparator preset, validating it is greater than zero + ASSERT_GT(outputEnergy, 0); +} + +TEST_P(PresetReverbProcessTest, PresetNone) { + std::vector output(kBufferSize); + + setPresetAndProcess(kDefaultPreset, output); + float outputEnergy = computeReverbOutputEnergy(output); + // NONE type doesn't create reverb effect + ASSERT_EQ(outputEnergy, 0); } INSTANTIATE_TEST_SUITE_P( @@ -145,6 +238,17 @@ INSTANTIATE_TEST_SUITE_P( GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbParamTest); +INSTANTIATE_TEST_SUITE_P( + PresetReverbTest, PresetReverbProcessTest, + testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, getEffectTypeUuidPresetReverb())), + [](const testing::TestParamInfo& info) { + auto descriptor = info.param; + return getPrefix(descriptor.second); + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbProcessTest); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());