blob: 1fe8beba7beab11a0a014515585954d62ca229d5 [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 float kMaxAudioSample = 1;
36static constexpr int kZeroGain = 0;
37static constexpr int kMaxGain = std::numeric_limits<int>::max();
38static constexpr int kMinGain = std::numeric_limits<int>::min();
39static constexpr float kAbsError = 0.0001;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053040
41// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
42// TODO : Update the test values once range/capability is updated by implementation.
Sneha Patil496e4412023-09-29 14:26:26 +053043static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053044
Sneha Patil496e4412023-09-29 14:26:26 +053045class LoudnessEnhancerEffectHelper : public EffectHelper {
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053046 public:
Sneha Patil496e4412023-09-29 14:26:26 +053047 void SetUpLoudnessEnhancer() {
Shunkai Yao812d5b42022-11-16 18:08:50 +000048 ASSERT_NE(nullptr, mFactory);
Shunkai Yaocb0fc412022-12-15 20:34:32 +000049 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053050
Shunkai Yao812d5b42022-11-16 18:08:50 +000051 Parameter::Specific specific = getDefaultParamSpecific();
Shunkai Yao61f9dd22024-05-08 22:34:36 +000052 Parameter::Common common = createParamCommon(
Shunkai Yao812d5b42022-11-16 18:08:50 +000053 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
Sneha Patil807c9522024-06-06 09:44:54 +000054 kFrameCount /* iFrameCount */, kFrameCount /* oFrameCount */);
Sneha Patil496e4412023-09-29 14:26:26 +053055 ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
Shunkai Yao812d5b42022-11-16 18:08:50 +000056 ASSERT_NE(nullptr, mEffect);
Shunkai Yaoef683a92024-04-18 04:38:17 +000057 mVersion = EffectFactoryHelper::getHalVersion(mFactory);
Shunkai Yao812d5b42022-11-16 18:08:50 +000058 }
Sneha Patil496e4412023-09-29 14:26:26 +053059
60 void TearDownLoudnessEnhancer() {
Shunkai Yao812d5b42022-11-16 18:08:50 +000061 ASSERT_NO_FATAL_FAILURE(close(mEffect));
62 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
Sneha Patil496e4412023-09-29 14:26:26 +053063 mOpenEffectReturn = IEffect::OpenEffectReturn{};
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053064 }
65
Shunkai Yao812d5b42022-11-16 18:08:50 +000066 Parameter::Specific getDefaultParamSpecific() {
67 LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
68 Parameter::Specific specific =
69 Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
70 return specific;
71 }
72
Sneha Patil496e4412023-09-29 14:26:26 +053073 Parameter createLoudnessParam(int gainMb) {
74 LoudnessEnhancer le;
75 le.set<LoudnessEnhancer::gainMb>(gainMb);
76 Parameter param;
77 Parameter::Specific specific;
78 specific.set<Parameter::Specific::loudnessEnhancer>(le);
79 param.set<Parameter::specific>(specific);
80 return param;
81 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053082
Sneha Patil496e4412023-09-29 14:26:26 +053083 binder_exception_t isGainValid(int gainMb) {
84 LoudnessEnhancer le;
85 le.set<LoudnessEnhancer::gainMb>(gainMb);
86 if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
87 return EX_NONE;
88 } else {
89 return EX_ILLEGAL_ARGUMENT;
Shunkai Yao812d5b42022-11-16 18:08:50 +000090 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053091 }
92
Sneha Patil496e4412023-09-29 14:26:26 +053093 void setParameters(int gain, binder_exception_t expected) {
94 // set parameter
95 auto param = createLoudnessParam(gain);
96 EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053097 }
98
Sneha Patil496e4412023-09-29 14:26:26 +053099 void validateParameters(int gain) {
100 // get parameter
101 LoudnessEnhancer::Id leId;
102 Parameter getParam;
103 Parameter::Id id;
104
105 LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
106 leId.set<LoudnessEnhancer::Id::commonTag>(tag);
107 id.set<Parameter::Id::loudnessEnhancerTag>(leId);
108 EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
109 auto expectedParam = createLoudnessParam(gain);
110 EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
111 << "\ngetParam:" << getParam.toString();
112 }
113
Sneha Patil807c9522024-06-06 09:44:54 +0000114 static const long kFrameCount = 256;
Sneha Patil496e4412023-09-29 14:26:26 +0530115 IEffect::OpenEffectReturn mOpenEffectReturn;
116 std::shared_ptr<IFactory> mFactory;
117 std::shared_ptr<IEffect> mEffect;
118 Descriptor mDescriptor;
Shunkai Yaoef683a92024-04-18 04:38:17 +0000119 int mVersion = 0;
Sneha Patil496e4412023-09-29 14:26:26 +0530120};
121
122/**
123 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
124 * VtsAudioEffectTargetTest.
125 */
126enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
127using LoudnessEnhancerParamTestParam =
128 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
129
130class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
131 public LoudnessEnhancerEffectHelper {
132 public:
133 LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
134 std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
135 }
136
137 void SetUp() override { SetUpLoudnessEnhancer(); }
138 void TearDown() override { TearDownLoudnessEnhancer(); }
139 int mParamGainMb = 0;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530140};
141
142TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
Sneha Patil496e4412023-09-29 14:26:26 +0530143 binder_exception_t expected = isGainValid(mParamGainMb);
144 setParameters(mParamGainMb, expected);
145 if (expected == EX_NONE) {
146 validateParameters(mParamGainMb);
147 }
148}
149
150using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
151
152class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
153 public LoudnessEnhancerEffectHelper {
154 public:
155 LoudnessEnhancerDataTest() {
156 std::tie(mFactory, mDescriptor) = GetParam();
Sneha Patil807c9522024-06-06 09:44:54 +0000157 mBufferSize = kFrameCount *
158 getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
159 AudioChannelLayout::LAYOUT_STEREO));
Sneha Patil496e4412023-09-29 14:26:26 +0530160 generateInputBuffer();
Sneha Patil807c9522024-06-06 09:44:54 +0000161
162 mOutputBuffer.resize(mBufferSize);
Sneha Patil496e4412023-09-29 14:26:26 +0530163 }
164
165 void SetUp() override {
Shunkai Yao50e478b2024-03-14 01:54:58 +0000166 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
Sneha Patil496e4412023-09-29 14:26:26 +0530167 SetUpLoudnessEnhancer();
168
169 // Creating AidlMessageQueues
170 mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
171 mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
172 mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
173 }
174
Shunkai Yao50e478b2024-03-14 01:54:58 +0000175 void TearDown() override {
176 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
177 TearDownLoudnessEnhancer();
178 }
Sneha Patil496e4412023-09-29 14:26:26 +0530179
180 // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
181 void generateInputBuffer() {
Sneha Patil807c9522024-06-06 09:44:54 +0000182 for (size_t i = 0; i < mBufferSize; i++) {
Sneha Patil496e4412023-09-29 14:26:26 +0530183 mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
184 kMaxAudioSample);
185 }
186 }
187
188 // Add gains to the mInputBuffer and store processed output to mOutputBuffer
189 void processAndWriteToOutput() {
190 // Check AidlMessageQueues are not null
191 ASSERT_TRUE(mStatusMQ->isValid());
192 ASSERT_TRUE(mInputMQ->isValid());
193 ASSERT_TRUE(mOutputMQ->isValid());
194
195 // Enabling the process
196 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
197 ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
198
199 // Write from buffer to message queues and calling process
Shunkai Yaoef683a92024-04-18 04:38:17 +0000200 EXPECT_NO_FATAL_FAILURE(
201 EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer, mVersion));
Sneha Patil496e4412023-09-29 14:26:26 +0530202
203 // Read the updated message queues into buffer
204 EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
205 mOutputBuffer.size(), mOutputBuffer));
206
207 // Disable the process
208 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
209 }
210
211 void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
212 for (size_t i = 0; i < first.size(); i++) {
213 if (first[i] != 0) {
214 ASSERT_GT(abs(first[i]), abs(second[i]));
215
216 } else {
217 ASSERT_EQ(first[i], second[i]);
218 }
219 }
220 }
221
222 void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
Sneha Patil807c9522024-06-06 09:44:54 +0000223 std::vector<float> baseOutput(mBufferSize);
Sneha Patil496e4412023-09-29 14:26:26 +0530224
225 // Process a reference output buffer with 0 gain which gives compressed input values
226 binder_exception_t expected;
227 expected = isGainValid(kZeroGain);
228 ASSERT_EQ(expected, EX_NONE);
229 setParameters(kZeroGain, expected);
230 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
231 baseOutput = mOutputBuffer;
232
233 // Compare the outputs for increasing gain
234 for (int gain : gainValues) {
235 // Setting the parameters
236 binder_exception_t expected = isGainValid(gain);
237 if (expected != EX_NONE) {
238 GTEST_SKIP() << "Gains not supported.";
239 }
240 setParameters(gain, expected);
241 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
242
243 // Compare the mOutputBuffer values with baseOutput and update it
244 if (isIncreasing) {
245 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
246 } else {
247 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
248 }
249
250 baseOutput = mOutputBuffer;
251 }
252 }
253
254 std::unique_ptr<StatusMQ> mStatusMQ;
255 std::unique_ptr<DataMQ> mInputMQ;
256 std::unique_ptr<DataMQ> mOutputMQ;
257
258 std::vector<float> mInputBuffer;
259 std::vector<float> mOutputBuffer;
Sneha Patil807c9522024-06-06 09:44:54 +0000260 size_t mBufferSize;
Sneha Patil496e4412023-09-29 14:26:26 +0530261};
262
263TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
264 static const std::vector<int> kIncreasingGains = {50, 100};
265
266 assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
267}
268
269TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
270 static const std::vector<int> kDecreasingGains = {-50, -100};
271
272 assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
273}
274
275TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
276 // Setting the parameters
277 binder_exception_t expected = isGainValid(kMinGain);
278 if (expected != EX_NONE) {
279 GTEST_SKIP() << "Minimum integer value not supported";
280 }
281 setParameters(kMinGain, expected);
282 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
283
284 // Validate that mOutputBuffer has 0 values for INT_MIN gain
285 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
286 ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
287 }
288}
289
290TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
291 // Setting the parameters
292 binder_exception_t expected = isGainValid(kMaxGain);
293 if (expected != EX_NONE) {
294 GTEST_SKIP() << "Maximum integer value not supported";
295 }
296 setParameters(kMaxGain, expected);
297 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
298
299 // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
300 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
301 if (mInputBuffer[i] != 0) {
302 EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
303 } else {
304 ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
305 }
306 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530307}
308
309INSTANTIATE_TEST_SUITE_P(
310 LoudnessEnhancerTest, LoudnessEnhancerParamTest,
Shunkai Yao812d5b42022-11-16 18:08:50 +0000311 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000312 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
Shunkai Yao812d5b42022-11-16 18:08:50 +0000313 testing::ValuesIn(kGainMbValues)),
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530314 [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
Shunkai Yaocb0fc412022-12-15 20:34:32 +0000315 auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530316 std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530317 std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530318 std::replace_if(
319 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
320 return name;
321 });
322
323GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
324
Sneha Patil496e4412023-09-29 14:26:26 +0530325INSTANTIATE_TEST_SUITE_P(
326 LoudnessEnhancerTest, LoudnessEnhancerDataTest,
327 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
328 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
329 [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
330 auto descriptor = info.param;
331 std::string name = getPrefix(descriptor.second);
332 std::replace_if(
333 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
334 return name;
335 });
336
337GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
338
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530339int main(int argc, char** argv) {
340 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +0530341 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530342 ABinderProcess_setThreadPoolMaxThreadCount(1);
343 ABinderProcess_startThreadPool();
344 return RUN_ALL_TESTS();
345}