PresetReverb: Add test to validate PresetReverb Effect

Added tests to verify increase in energy with decrease in room and hall size.
Remove preset reverb default implementation from the config file.

Bug: 305866207
Test: atest VtsHalPresetReverbTargetTest
Change-Id: I565612d90b7c7e52cb23bd5dbfaf02235f65cc67
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 1453495..300939e 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -17,11 +17,14 @@
 #define LOG_TAG "VtsHalPresetReverbTargetTest"
 #include <android-base/logging.h>
 #include <android/binder_enums.h>
+#include <audio_utils/power.h>
+#include <system/audio.h>
 
 #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::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<PresetReverb::preset>(kDefaultPreset);
+        Parameter::Specific specific =
+                Parameter::Specific::make<Parameter::Specific::presetReverb>(pr);
+        return specific;
+    }
+
+    Parameter createPresetReverbParam(const PresetReverb::Presets& param) {
+        return Parameter::make<Parameter::specific>(
+                Parameter::Specific::make<Parameter::Specific::presetReverb>(
+                        PresetReverb::make<PresetReverb::preset>(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::Id::commonTag>(PresetReverb::preset);
+
+        auto id = Parameter::Id::make<Parameter::Id::presetReverbTag>(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::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO));
+    PresetReverb::Presets kDefaultPreset = PresetReverb::Presets::NONE;
+    int mFrameCount = kBufferSize / mStereoChannelCount;
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+    Descriptor mDescriptor;
+};
+
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
@@ -44,88 +109,116 @@
         ndk::enum_range<PresetReverb::Presets>().end()};
 
 class PresetReverbParamTest : public ::testing::TestWithParam<PresetReverbParamTestParam>,
-                              public EffectHelper {
+                              public PresetReverbHelper {
   public:
-    PresetReverbParamTest() : mParamPresets(std::get<PARAM_PRESETS>(GetParam())) {
+    PresetReverbParamTest() : mParamPreset(std::get<PARAM_PRESETS>(GetParam())) {
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(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<IFactory> mFactory;
-    std::shared_ptr<IEffect> 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<PresetReverb, Range::presetReverb>(it.second, desc);
-            const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
-
-            // set parameter
-            Parameter expectParam;
-            Parameter::Specific specific;
-            specific.set<Parameter::Specific::presetReverb>(pr);
-            expectParam.set<Parameter::specific>(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<PresetReverb::Id::commonTag>(tag);
-            id.set<Parameter::Id::presetReverbTag>(prId);
-            EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
-
-            EXPECT_EQ(expectParam, getParam);
-        }
-    }
-
-    void addPresetsParam(PresetReverb::Presets preset) {
-        PresetReverb pr;
-        pr.set<PresetReverb::preset>(preset);
-        mTags.push_back({PresetReverb::preset, pr});
-    }
-
-    Parameter::Specific getDefaultParamSpecific() {
-        PresetReverb pr = PresetReverb::make<PresetReverb::preset>(PresetReverb::Presets::NONE);
-        Parameter::Specific specific =
-                Parameter::Specific::make<Parameter::Specific::presetReverb>(pr);
-        return specific;
-    }
-
-  private:
-    std::vector<std::pair<PresetReverb::Tag, PresetReverb>> 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<std::shared_ptr<IFactory>, Descriptor>;
+
+class PresetReverbProcessTest : public ::testing::TestWithParam<PresetReverbProcessTestParam>,
+                                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<float> 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<float>& output) {
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(preset));
+        ASSERT_NO_FATAL_FAILURE(
+                processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
+    }
+
+    void validateIncreasingEnergy(const std::vector<PresetReverb::Presets>& presets) {
+        float baseOutputEnergy = 0;
+
+        for (PresetReverb::Presets preset : presets) {
+            std::vector<float> output(kBufferSize);
+            setPresetAndProcess(preset, output);
+            float outputEnergy = computeReverbOutputEnergy(output);
+
+            ASSERT_GT(outputEnergy, baseOutputEnergy);
+            baseOutputEnergy = outputEnergy;
+        }
+    }
+
+    std::vector<float> mInput;
+};
+
+TEST_P(PresetReverbProcessTest, DecreasingRoomSize) {
+    std::vector<PresetReverb::Presets> roomPresets = {PresetReverb::Presets::LARGEROOM,
+                                                      PresetReverb::Presets::MEDIUMROOM,
+                                                      PresetReverb::Presets::SMALLROOM};
+    validateIncreasingEnergy(roomPresets);
+}
+
+TEST_P(PresetReverbProcessTest, DecreasingHallSize) {
+    std::vector<PresetReverb::Presets> hallPresets = {PresetReverb::Presets::LARGEHALL,
+                                                      PresetReverb::Presets::MEDIUMHALL};
+    validateIncreasingEnergy(hallPresets);
+}
+
+TEST_P(PresetReverbProcessTest, PresetPlate) {
+    std::vector<float> 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<float> 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 @@
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbParamTest);
 
+INSTANTIATE_TEST_SUITE_P(
+        PresetReverbTest, PresetReverbProcessTest,
+        testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                IFactory::descriptor, getEffectTypeUuidPresetReverb())),
+        [](const testing::TestParamInfo<PresetReverbProcessTest::ParamType>& 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());