Merge "LoudnessEnhancer: Added test cases to validate effect processing." into main am: 309d65f0c4 am: 735bab03bf am: c2c32252dd

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2792432

Change-Id: If5d19d6dec369d747165dac671356e02574cdd88
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot 2023-10-31 18:37:36 +00:00 committed by Automerger Merge Worker
commit 3baa9d34d6

View file

@ -32,27 +32,19 @@ using aidl::android::hardware::audio::effect::LoudnessEnhancer;
using aidl::android::hardware::audio::effect::Parameter;
using android::hardware::audio::common::testing::detail::TestExecutionTracer;
/**
* Here we focus on specific parameter checking, general IEffect interfaces testing performed in
* VtsAudioEffectTargetTest.
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
using LoudnessEnhancerParamTestParam =
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
static constexpr float kMaxAudioSample = 1;
static constexpr int kZeroGain = 0;
static constexpr int kMaxGain = std::numeric_limits<int>::max();
static constexpr int kMinGain = std::numeric_limits<int>::min();
static constexpr float kAbsError = 0.0001;
// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
// TODO : Update the test values once range/capability is updated by implementation.
const std::vector<int> kGainMbValues = {std::numeric_limits<int>::min(), 100,
std::numeric_limits<int>::max()};
static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
public EffectHelper {
class LoudnessEnhancerEffectHelper : public EffectHelper {
public:
LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
void SetUp() override {
void SetUpLoudnessEnhancer() {
ASSERT_NE(nullptr, mFactory);
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
@ -60,13 +52,14 @@ class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhanc
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_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
ASSERT_NE(nullptr, mEffect);
}
void TearDown() override {
void TearDownLoudnessEnhancer() {
ASSERT_NO_FATAL_FAILURE(close(mEffect));
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
mOpenEffectReturn = IEffect::OpenEffectReturn{};
}
Parameter::Specific getDefaultParamSpecific() {
@ -76,52 +69,230 @@ class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhanc
return specific;
}
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
Descriptor mDescriptor;
int mParamGainMb = 0;
Parameter createLoudnessParam(int gainMb) {
LoudnessEnhancer le;
le.set<LoudnessEnhancer::gainMb>(gainMb);
Parameter param;
Parameter::Specific specific;
specific.set<Parameter::Specific::loudnessEnhancer>(le);
param.set<Parameter::specific>(specific);
return param;
}
void SetAndGetParameters() {
for (auto& it : mTags) {
auto& tag = it.first;
auto& le = it.second;
// set parameter
Parameter expectParam;
Parameter::Specific specific;
specific.set<Parameter::Specific::loudnessEnhancer>(le);
expectParam.set<Parameter::specific>(specific);
// All values are valid, set parameter should succeed
EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
// get parameter
Parameter getParam;
Parameter::Id id;
LoudnessEnhancer::Id leId;
leId.set<LoudnessEnhancer::Id::commonTag>(tag);
id.set<Parameter::Id::loudnessEnhancerTag>(leId);
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
<< "\ngetParam:" << getParam.toString();
binder_exception_t isGainValid(int gainMb) {
LoudnessEnhancer le;
le.set<LoudnessEnhancer::gainMb>(gainMb);
if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
return EX_NONE;
} else {
return EX_ILLEGAL_ARGUMENT;
}
}
void addGainMbParam(int gainMb) {
LoudnessEnhancer le;
le.set<LoudnessEnhancer::gainMb>(gainMb);
mTags.push_back({LoudnessEnhancer::gainMb, le});
void setParameters(int gain, binder_exception_t expected) {
// set parameter
auto param = createLoudnessParam(gain);
EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
}
private:
std::vector<std::pair<LoudnessEnhancer::Tag, LoudnessEnhancer>> mTags;
void CleanUp() { mTags.clear(); }
void validateParameters(int gain) {
// get parameter
LoudnessEnhancer::Id leId;
Parameter getParam;
Parameter::Id id;
LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
leId.set<LoudnessEnhancer::Id::commonTag>(tag);
id.set<Parameter::Id::loudnessEnhancerTag>(leId);
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
auto expectedParam = createLoudnessParam(gain);
EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
<< "\ngetParam:" << getParam.toString();
}
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
IEffect::OpenEffectReturn mOpenEffectReturn;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
Descriptor mDescriptor;
};
/**
* Here we focus on specific parameter checking, general IEffect interfaces testing performed in
* VtsAudioEffectTargetTest.
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
using LoudnessEnhancerParamTestParam =
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
public LoudnessEnhancerEffectHelper {
public:
LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
void SetUp() override { SetUpLoudnessEnhancer(); }
void TearDown() override { TearDownLoudnessEnhancer(); }
int mParamGainMb = 0;
};
TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb));
SetAndGetParameters();
binder_exception_t expected = isGainValid(mParamGainMb);
setParameters(mParamGainMb, expected);
if (expected == EX_NONE) {
validateParameters(mParamGainMb);
}
}
using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
public LoudnessEnhancerEffectHelper {
public:
LoudnessEnhancerDataTest() {
std::tie(mFactory, mDescriptor) = GetParam();
generateInputBuffer();
mOutputBuffer.resize(kBufferSize);
}
void SetUp() override {
SetUpLoudnessEnhancer();
// Creating AidlMessageQueues
mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
}
void TearDown() override { TearDownLoudnessEnhancer(); }
// Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
void generateInputBuffer() {
for (size_t i = 0; i < kBufferSize; i++) {
mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
kMaxAudioSample);
}
}
// Add gains to the mInputBuffer and store processed output to mOutputBuffer
void processAndWriteToOutput() {
// Check AidlMessageQueues are not null
ASSERT_TRUE(mStatusMQ->isValid());
ASSERT_TRUE(mInputMQ->isValid());
ASSERT_TRUE(mOutputMQ->isValid());
// Enabling the process
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
// Write from buffer to message queues and calling process
EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer));
// Read the updated message queues into buffer
EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
mOutputBuffer.size(), mOutputBuffer));
// Disable the process
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
}
void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
for (size_t i = 0; i < first.size(); i++) {
if (first[i] != 0) {
ASSERT_GT(abs(first[i]), abs(second[i]));
} else {
ASSERT_EQ(first[i], second[i]);
}
}
}
void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
std::vector<float> baseOutput(kBufferSize);
// Process a reference output buffer with 0 gain which gives compressed input values
binder_exception_t expected;
expected = isGainValid(kZeroGain);
ASSERT_EQ(expected, EX_NONE);
setParameters(kZeroGain, expected);
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
baseOutput = mOutputBuffer;
// Compare the outputs for increasing gain
for (int gain : gainValues) {
// Setting the parameters
binder_exception_t expected = isGainValid(gain);
if (expected != EX_NONE) {
GTEST_SKIP() << "Gains not supported.";
}
setParameters(gain, expected);
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
// Compare the mOutputBuffer values with baseOutput and update it
if (isIncreasing) {
ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
} else {
ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
}
baseOutput = mOutputBuffer;
}
}
std::unique_ptr<StatusMQ> mStatusMQ;
std::unique_ptr<DataMQ> mInputMQ;
std::unique_ptr<DataMQ> mOutputMQ;
std::vector<float> mInputBuffer;
std::vector<float> mOutputBuffer;
static constexpr float kBufferSize = 128;
};
TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
static const std::vector<int> kIncreasingGains = {50, 100};
assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
}
TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
static const std::vector<int> kDecreasingGains = {-50, -100};
assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
}
TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
// Setting the parameters
binder_exception_t expected = isGainValid(kMinGain);
if (expected != EX_NONE) {
GTEST_SKIP() << "Minimum integer value not supported";
}
setParameters(kMinGain, expected);
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
// Validate that mOutputBuffer has 0 values for INT_MIN gain
for (size_t i = 0; i < mOutputBuffer.size(); i++) {
ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
}
}
TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
// Setting the parameters
binder_exception_t expected = isGainValid(kMaxGain);
if (expected != EX_NONE) {
GTEST_SKIP() << "Maximum integer value not supported";
}
setParameters(kMaxGain, expected);
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
// Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
for (size_t i = 0; i < mOutputBuffer.size(); i++) {
if (mInputBuffer[i] != 0) {
EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
} else {
ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
}
}
}
INSTANTIATE_TEST_SUITE_P(
@ -140,6 +311,20 @@ INSTANTIATE_TEST_SUITE_P(
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
INSTANTIATE_TEST_SUITE_P(
LoudnessEnhancerTest, LoudnessEnhancerDataTest,
testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
[](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
auto descriptor = info.param;
std::string name = getPrefix(descriptor.second);
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
});
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());