blob: a263bfff62caef522943fc26547d5a57edb69482 [file] [log] [blame]
Shraddha Basantwani68041ca2022-11-04 15:13:32 +05301/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Shunkai Yaof0803cd2022-12-08 00:07:13 +000017#include <string>
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053018
19#define LOG_TAG "VtsHalLoudnessEnhancerTest"
Mikhail Naganov872d4a62023-03-09 18:19:01 -080020#include <android-base/logging.h>
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053021
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053022#include "EffectHelper.h"
23
24using namespace android;
25
Sneha Patil807c9522024-06-06 09:44:54 +000026using aidl::android::hardware::audio::common::getChannelCount;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053027using aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yaof8be1ac2023-03-06 18:41:27 +000028using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053029using aidl::android::hardware::audio::effect::IEffect;
30using aidl::android::hardware::audio::effect::IFactory;
31using aidl::android::hardware::audio::effect::LoudnessEnhancer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053032using aidl::android::hardware::audio::effect::Parameter;
Jaideep Sharma74498412023-09-13 15:25:25 +053033using android::hardware::audio::common::testing::detail::TestExecutionTracer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053034
Sneha Patil496e4412023-09-29 14:26:26 +053035static constexpr int kZeroGain = 0;
36static constexpr int kMaxGain = std::numeric_limits<int>::max();
37static constexpr int kMinGain = std::numeric_limits<int>::min();
38static constexpr float kAbsError = 0.0001;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053039
40// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
41// TODO : Update the test values once range/capability is updated by implementation.
Sneha Patil496e4412023-09-29 14:26:26 +053042static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053043
Sneha Patil496e4412023-09-29 14:26:26 +053044class LoudnessEnhancerEffectHelper : public EffectHelper {
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053045 public:
Sneha Patil496e4412023-09-29 14:26:26 +053046 void SetUpLoudnessEnhancer() {
Shunkai Yao812d5b42022-11-16 18:08:50 +000047 ASSERT_NE(nullptr, mFactory);
Shunkai Yaocb0fc412022-12-15 20:34:32 +000048 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053049
Shunkai Yao812d5b42022-11-16 18:08:50 +000050 Parameter::Specific specific = getDefaultParamSpecific();
Shunkai Yao61f9dd22024-05-08 22:34:36 +000051 Parameter::Common common = createParamCommon(
Shunkai Yao812d5b42022-11-16 18:08:50 +000052 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
Sneha Patil807c9522024-06-06 09:44:54 +000053 kFrameCount /* iFrameCount */, kFrameCount /* oFrameCount */);
Sneha Patil496e4412023-09-29 14:26:26 +053054 ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
Shunkai Yao812d5b42022-11-16 18:08:50 +000055 ASSERT_NE(nullptr, mEffect);
Shunkai Yaoef683a92024-04-18 04:38:17 +000056 mVersion = EffectFactoryHelper::getHalVersion(mFactory);
Shunkai Yao812d5b42022-11-16 18:08:50 +000057 }
Sneha Patil496e4412023-09-29 14:26:26 +053058
59 void TearDownLoudnessEnhancer() {
Shunkai Yao812d5b42022-11-16 18:08:50 +000060 ASSERT_NO_FATAL_FAILURE(close(mEffect));
61 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
Sneha Patil496e4412023-09-29 14:26:26 +053062 mOpenEffectReturn = IEffect::OpenEffectReturn{};
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053063 }
64
Shunkai Yao812d5b42022-11-16 18:08:50 +000065 Parameter::Specific getDefaultParamSpecific() {
66 LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
67 Parameter::Specific specific =
68 Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
69 return specific;
70 }
71
Sneha Patil496e4412023-09-29 14:26:26 +053072 Parameter createLoudnessParam(int gainMb) {
73 LoudnessEnhancer le;
74 le.set<LoudnessEnhancer::gainMb>(gainMb);
75 Parameter param;
76 Parameter::Specific specific;
77 specific.set<Parameter::Specific::loudnessEnhancer>(le);
78 param.set<Parameter::specific>(specific);
79 return param;
80 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053081
Sneha Patil496e4412023-09-29 14:26:26 +053082 binder_exception_t isGainValid(int gainMb) {
83 LoudnessEnhancer le;
84 le.set<LoudnessEnhancer::gainMb>(gainMb);
85 if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
86 return EX_NONE;
87 } else {
88 return EX_ILLEGAL_ARGUMENT;
Shunkai Yao812d5b42022-11-16 18:08:50 +000089 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053090 }
91
Sneha Patil496e4412023-09-29 14:26:26 +053092 void setParameters(int gain, binder_exception_t expected) {
93 // set parameter
94 auto param = createLoudnessParam(gain);
95 EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053096 }
97
Andy Hung28c51272025-03-03 16:24:44 -080098 void reset() { EXPECT_STATUS(EX_NONE, mEffect->command(CommandId::RESET)); }
99
Sneha Patil496e4412023-09-29 14:26:26 +0530100 void validateParameters(int gain) {
101 // get parameter
102 LoudnessEnhancer::Id leId;
103 Parameter getParam;
104 Parameter::Id id;
105
106 LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
107 leId.set<LoudnessEnhancer::Id::commonTag>(tag);
108 id.set<Parameter::Id::loudnessEnhancerTag>(leId);
109 EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
110 auto expectedParam = createLoudnessParam(gain);
111 EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
112 << "\ngetParam:" << getParam.toString();
113 }
114
Sneha Patil807c9522024-06-06 09:44:54 +0000115 static const long kFrameCount = 256;
Sneha Patil496e4412023-09-29 14:26:26 +0530116 IEffect::OpenEffectReturn mOpenEffectReturn;
117 std::shared_ptr<IFactory> mFactory;
118 std::shared_ptr<IEffect> mEffect;
119 Descriptor mDescriptor;
Shunkai Yaoef683a92024-04-18 04:38:17 +0000120 int mVersion = 0;
Sneha Patil496e4412023-09-29 14:26:26 +0530121};
122
123/**
124 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
125 * VtsAudioEffectTargetTest.
126 */
127enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
128using LoudnessEnhancerParamTestParam =
129 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
130
131class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
132 public LoudnessEnhancerEffectHelper {
133 public:
134 LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
135 std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
136 }
137
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000138 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer()); }
Sneha Patil496e4412023-09-29 14:26:26 +0530139 void TearDown() override { TearDownLoudnessEnhancer(); }
140 int mParamGainMb = 0;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530141};
142
143TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
Sneha Patil496e4412023-09-29 14:26:26 +0530144 binder_exception_t expected = isGainValid(mParamGainMb);
145 setParameters(mParamGainMb, expected);
146 if (expected == EX_NONE) {
147 validateParameters(mParamGainMb);
148 }
149}
150
151using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
152
153class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
154 public LoudnessEnhancerEffectHelper {
155 public:
156 LoudnessEnhancerDataTest() {
157 std::tie(mFactory, mDescriptor) = GetParam();
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000158 size_t channelCount = getChannelCount(
159 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
Aayush Sonibb001fb2024-09-11 13:51:14 +0000160 mBufferSizeInFrames = kFrameCount * channelCount;
161 mInputBuffer.resize(mBufferSizeInFrames);
162 generateInputBuffer(mInputBuffer, 0, true, channelCount, kMaxAudioSampleValue);
Sneha Patil807c9522024-06-06 09:44:54 +0000163
Aayush Sonibb001fb2024-09-11 13:51:14 +0000164 mOutputBuffer.resize(mBufferSizeInFrames);
Sneha Patil496e4412023-09-29 14:26:26 +0530165 }
166
167 void SetUp() override {
Shunkai Yao50e478b2024-03-14 01:54:58 +0000168 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000169 ASSERT_NO_FATAL_FAILURE(SetUpLoudnessEnhancer());
Sneha Patil496e4412023-09-29 14:26:26 +0530170
171 // Creating AidlMessageQueues
172 mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
173 mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
174 mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
175 }
176
Shunkai Yao50e478b2024-03-14 01:54:58 +0000177 void TearDown() override {
178 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
179 TearDownLoudnessEnhancer();
180 }
Sneha Patil496e4412023-09-29 14:26:26 +0530181
Sneha Patil496e4412023-09-29 14:26:26 +0530182 // Add gains to the mInputBuffer and store processed output to mOutputBuffer
183 void processAndWriteToOutput() {
184 // Check AidlMessageQueues are not null
185 ASSERT_TRUE(mStatusMQ->isValid());
186 ASSERT_TRUE(mInputMQ->isValid());
187 ASSERT_TRUE(mOutputMQ->isValid());
188
189 // Enabling the process
190 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
191 ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
192
193 // Write from buffer to message queues and calling process
Shunkai Yaoef683a92024-04-18 04:38:17 +0000194 EXPECT_NO_FATAL_FAILURE(
195 EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer, mVersion));
Sneha Patil496e4412023-09-29 14:26:26 +0530196
197 // Read the updated message queues into buffer
198 EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
199 mOutputBuffer.size(), mOutputBuffer));
200
201 // Disable the process
202 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
203 }
204
205 void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
206 for (size_t i = 0; i < first.size(); i++) {
207 if (first[i] != 0) {
208 ASSERT_GT(abs(first[i]), abs(second[i]));
209
210 } else {
211 ASSERT_EQ(first[i], second[i]);
212 }
213 }
214 }
215
216 void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
Aayush Sonibb001fb2024-09-11 13:51:14 +0000217 std::vector<float> baseOutput(mBufferSizeInFrames);
Sneha Patil496e4412023-09-29 14:26:26 +0530218
219 // Process a reference output buffer with 0 gain which gives compressed input values
220 binder_exception_t expected;
221 expected = isGainValid(kZeroGain);
222 ASSERT_EQ(expected, EX_NONE);
Andy Hung28c51272025-03-03 16:24:44 -0800223 // reset state to prevent prior signal history from affecting trial run.
224 ASSERT_NO_FATAL_FAILURE(reset());
Sneha Patil496e4412023-09-29 14:26:26 +0530225 setParameters(kZeroGain, expected);
226 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
227 baseOutput = mOutputBuffer;
228
229 // Compare the outputs for increasing gain
230 for (int gain : gainValues) {
231 // Setting the parameters
232 binder_exception_t expected = isGainValid(gain);
233 if (expected != EX_NONE) {
234 GTEST_SKIP() << "Gains not supported.";
235 }
Andy Hung28c51272025-03-03 16:24:44 -0800236 // reset state to prevent prior signal history from affecting trial run.
237 ASSERT_NO_FATAL_FAILURE(reset());
Sneha Patil496e4412023-09-29 14:26:26 +0530238 setParameters(gain, expected);
239 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
240
241 // Compare the mOutputBuffer values with baseOutput and update it
242 if (isIncreasing) {
243 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
244 } else {
245 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
246 }
247
248 baseOutput = mOutputBuffer;
249 }
250 }
251
252 std::unique_ptr<StatusMQ> mStatusMQ;
253 std::unique_ptr<DataMQ> mInputMQ;
254 std::unique_ptr<DataMQ> mOutputMQ;
255
256 std::vector<float> mInputBuffer;
257 std::vector<float> mOutputBuffer;
Aayush Sonibb001fb2024-09-11 13:51:14 +0000258 size_t mBufferSizeInFrames;
Sneha Patil496e4412023-09-29 14:26:26 +0530259};
260
261TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
262 static const std::vector<int> kIncreasingGains = {50, 100};
263
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000264 ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kIncreasingGains, true /*isIncreasing*/));
Sneha Patil496e4412023-09-29 14:26:26 +0530265}
266
267TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
268 static const std::vector<int> kDecreasingGains = {-50, -100};
269
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000270 ASSERT_NO_FATAL_FAILURE(assertSequentialGains(kDecreasingGains, false /*isIncreasing*/));
Sneha Patil496e4412023-09-29 14:26:26 +0530271}
272
273TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
274 // Setting the parameters
275 binder_exception_t expected = isGainValid(kMinGain);
276 if (expected != EX_NONE) {
277 GTEST_SKIP() << "Minimum integer value not supported";
278 }
279 setParameters(kMinGain, expected);
280 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
281
282 // Validate that mOutputBuffer has 0 values for INT_MIN gain
283 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
284 ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
285 }
286}
287
288TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
289 // Setting the parameters
290 binder_exception_t expected = isGainValid(kMaxGain);
291 if (expected != EX_NONE) {
292 GTEST_SKIP() << "Maximum integer value not supported";
293 }
294 setParameters(kMaxGain, expected);
295 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
296
Aayush Sonibb001fb2024-09-11 13:51:14 +0000297 // Validate that mOutputBuffer reaches to kMaxAudioSampleValue for INT_MAX gain
Sneha Patil496e4412023-09-29 14:26:26 +0530298 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
299 if (mInputBuffer[i] != 0) {
Aayush Sonibb001fb2024-09-11 13:51:14 +0000300 EXPECT_NEAR(kMaxAudioSampleValue, abs(mOutputBuffer[i]), kAbsError);
Sneha Patil496e4412023-09-29 14:26:26 +0530301 } else {
302 ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
303 }
304 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530305}
306
307INSTANTIATE_TEST_SUITE_P(
308 LoudnessEnhancerTest, LoudnessEnhancerParamTest,
Shunkai Yao812d5b42022-11-16 18:08:50 +0000309 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000310 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
Shunkai Yao812d5b42022-11-16 18:08:50 +0000311 testing::ValuesIn(kGainMbValues)),
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530312 [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
Shunkai Yaocb0fc412022-12-15 20:34:32 +0000313 auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530314 std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530315 std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530316 std::replace_if(
317 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
318 return name;
319 });
320
321GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
322
Sneha Patil496e4412023-09-29 14:26:26 +0530323INSTANTIATE_TEST_SUITE_P(
324 LoudnessEnhancerTest, LoudnessEnhancerDataTest,
325 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
326 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
327 [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
328 auto descriptor = info.param;
329 std::string name = getPrefix(descriptor.second);
330 std::replace_if(
331 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
332 return name;
333 });
334
335GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
336
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530337int main(int argc, char** argv) {
338 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +0530339 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530340 ABinderProcess_setThreadPoolMaxThreadCount(1);
341 ABinderProcess_startThreadPool();
342 return RUN_ALL_TESTS();
343}