blob: 7f0091f22104269a5390589603e83ba5a3954b50 [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
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053026using aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yaof8be1ac2023-03-06 18:41:27 +000027using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053028using aidl::android::hardware::audio::effect::IEffect;
29using aidl::android::hardware::audio::effect::IFactory;
30using aidl::android::hardware::audio::effect::LoudnessEnhancer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053031using aidl::android::hardware::audio::effect::Parameter;
Jaideep Sharma74498412023-09-13 15:25:25 +053032using android::hardware::audio::common::testing::detail::TestExecutionTracer;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053033
Sneha Patil496e4412023-09-29 14:26:26 +053034static constexpr float kMaxAudioSample = 1;
35static 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();
51 Parameter::Common common = EffectHelper::createParamCommon(
52 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
53 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* 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);
56 }
Sneha Patil496e4412023-09-29 14:26:26 +053057
58 void TearDownLoudnessEnhancer() {
Shunkai Yao812d5b42022-11-16 18:08:50 +000059 ASSERT_NO_FATAL_FAILURE(close(mEffect));
60 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
Sneha Patil496e4412023-09-29 14:26:26 +053061 mOpenEffectReturn = IEffect::OpenEffectReturn{};
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053062 }
63
Shunkai Yao812d5b42022-11-16 18:08:50 +000064 Parameter::Specific getDefaultParamSpecific() {
65 LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
66 Parameter::Specific specific =
67 Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
68 return specific;
69 }
70
Sneha Patil496e4412023-09-29 14:26:26 +053071 Parameter createLoudnessParam(int gainMb) {
72 LoudnessEnhancer le;
73 le.set<LoudnessEnhancer::gainMb>(gainMb);
74 Parameter param;
75 Parameter::Specific specific;
76 specific.set<Parameter::Specific::loudnessEnhancer>(le);
77 param.set<Parameter::specific>(specific);
78 return param;
79 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053080
Sneha Patil496e4412023-09-29 14:26:26 +053081 binder_exception_t isGainValid(int gainMb) {
82 LoudnessEnhancer le;
83 le.set<LoudnessEnhancer::gainMb>(gainMb);
84 if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
85 return EX_NONE;
86 } else {
87 return EX_ILLEGAL_ARGUMENT;
Shunkai Yao812d5b42022-11-16 18:08:50 +000088 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053089 }
90
Sneha Patil496e4412023-09-29 14:26:26 +053091 void setParameters(int gain, binder_exception_t expected) {
92 // set parameter
93 auto param = createLoudnessParam(gain);
94 EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
Shraddha Basantwani68041ca2022-11-04 15:13:32 +053095 }
96
Sneha Patil496e4412023-09-29 14:26:26 +053097 void validateParameters(int gain) {
98 // get parameter
99 LoudnessEnhancer::Id leId;
100 Parameter getParam;
101 Parameter::Id id;
102
103 LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
104 leId.set<LoudnessEnhancer::Id::commonTag>(tag);
105 id.set<Parameter::Id::loudnessEnhancerTag>(leId);
106 EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
107 auto expectedParam = createLoudnessParam(gain);
108 EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
109 << "\ngetParam:" << getParam.toString();
110 }
111
112 static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
113 IEffect::OpenEffectReturn mOpenEffectReturn;
114 std::shared_ptr<IFactory> mFactory;
115 std::shared_ptr<IEffect> mEffect;
116 Descriptor mDescriptor;
117};
118
119/**
120 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
121 * VtsAudioEffectTargetTest.
122 */
123enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
124using LoudnessEnhancerParamTestParam =
125 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
126
127class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
128 public LoudnessEnhancerEffectHelper {
129 public:
130 LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
131 std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
132 }
133
134 void SetUp() override { SetUpLoudnessEnhancer(); }
135 void TearDown() override { TearDownLoudnessEnhancer(); }
136 int mParamGainMb = 0;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530137};
138
139TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
Sneha Patil496e4412023-09-29 14:26:26 +0530140 binder_exception_t expected = isGainValid(mParamGainMb);
141 setParameters(mParamGainMb, expected);
142 if (expected == EX_NONE) {
143 validateParameters(mParamGainMb);
144 }
145}
146
147using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
148
149class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
150 public LoudnessEnhancerEffectHelper {
151 public:
152 LoudnessEnhancerDataTest() {
153 std::tie(mFactory, mDescriptor) = GetParam();
154 generateInputBuffer();
155 mOutputBuffer.resize(kBufferSize);
156 }
157
158 void SetUp() override {
159 SetUpLoudnessEnhancer();
160
161 // Creating AidlMessageQueues
162 mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
163 mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
164 mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
165 }
166
167 void TearDown() override { TearDownLoudnessEnhancer(); }
168
169 // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
170 void generateInputBuffer() {
171 for (size_t i = 0; i < kBufferSize; i++) {
172 mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
173 kMaxAudioSample);
174 }
175 }
176
177 // Add gains to the mInputBuffer and store processed output to mOutputBuffer
178 void processAndWriteToOutput() {
179 // Check AidlMessageQueues are not null
180 ASSERT_TRUE(mStatusMQ->isValid());
181 ASSERT_TRUE(mInputMQ->isValid());
182 ASSERT_TRUE(mOutputMQ->isValid());
183
184 // Enabling the process
185 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
186 ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
187
188 // Write from buffer to message queues and calling process
189 EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer));
190
191 // Read the updated message queues into buffer
192 EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
193 mOutputBuffer.size(), mOutputBuffer));
194
195 // Disable the process
196 ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
197 }
198
199 void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
200 for (size_t i = 0; i < first.size(); i++) {
201 if (first[i] != 0) {
202 ASSERT_GT(abs(first[i]), abs(second[i]));
203
204 } else {
205 ASSERT_EQ(first[i], second[i]);
206 }
207 }
208 }
209
210 void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
211 std::vector<float> baseOutput(kBufferSize);
212
213 // Process a reference output buffer with 0 gain which gives compressed input values
214 binder_exception_t expected;
215 expected = isGainValid(kZeroGain);
216 ASSERT_EQ(expected, EX_NONE);
217 setParameters(kZeroGain, expected);
218 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
219 baseOutput = mOutputBuffer;
220
221 // Compare the outputs for increasing gain
222 for (int gain : gainValues) {
223 // Setting the parameters
224 binder_exception_t expected = isGainValid(gain);
225 if (expected != EX_NONE) {
226 GTEST_SKIP() << "Gains not supported.";
227 }
228 setParameters(gain, expected);
229 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
230
231 // Compare the mOutputBuffer values with baseOutput and update it
232 if (isIncreasing) {
233 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
234 } else {
235 ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
236 }
237
238 baseOutput = mOutputBuffer;
239 }
240 }
241
242 std::unique_ptr<StatusMQ> mStatusMQ;
243 std::unique_ptr<DataMQ> mInputMQ;
244 std::unique_ptr<DataMQ> mOutputMQ;
245
246 std::vector<float> mInputBuffer;
247 std::vector<float> mOutputBuffer;
248 static constexpr float kBufferSize = 128;
249};
250
251TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
252 static const std::vector<int> kIncreasingGains = {50, 100};
253
254 assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
255}
256
257TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
258 static const std::vector<int> kDecreasingGains = {-50, -100};
259
260 assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
261}
262
263TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
264 // Setting the parameters
265 binder_exception_t expected = isGainValid(kMinGain);
266 if (expected != EX_NONE) {
267 GTEST_SKIP() << "Minimum integer value not supported";
268 }
269 setParameters(kMinGain, expected);
270 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
271
272 // Validate that mOutputBuffer has 0 values for INT_MIN gain
273 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
274 ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
275 }
276}
277
278TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
279 // Setting the parameters
280 binder_exception_t expected = isGainValid(kMaxGain);
281 if (expected != EX_NONE) {
282 GTEST_SKIP() << "Maximum integer value not supported";
283 }
284 setParameters(kMaxGain, expected);
285 ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
286
287 // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
288 for (size_t i = 0; i < mOutputBuffer.size(); i++) {
289 if (mInputBuffer[i] != 0) {
290 EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
291 } else {
292 ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
293 }
294 }
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530295}
296
297INSTANTIATE_TEST_SUITE_P(
298 LoudnessEnhancerTest, LoudnessEnhancerParamTest,
Shunkai Yao812d5b42022-11-16 18:08:50 +0000299 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000300 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
Shunkai Yao812d5b42022-11-16 18:08:50 +0000301 testing::ValuesIn(kGainMbValues)),
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530302 [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
Shunkai Yaocb0fc412022-12-15 20:34:32 +0000303 auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530304 std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530305 std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530306 std::replace_if(
307 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
308 return name;
309 });
310
311GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
312
Sneha Patil496e4412023-09-29 14:26:26 +0530313INSTANTIATE_TEST_SUITE_P(
314 LoudnessEnhancerTest, LoudnessEnhancerDataTest,
315 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
316 IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
317 [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
318 auto descriptor = info.param;
319 std::string name = getPrefix(descriptor.second);
320 std::replace_if(
321 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
322 return name;
323 });
324
325GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
326
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530327int main(int argc, char** argv) {
328 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +0530329 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Shraddha Basantwani68041ca2022-11-04 15:13:32 +0530330 ABinderProcess_setThreadPoolMaxThreadCount(1);
331 ABinderProcess_startThreadPool();
332 return RUN_ALL_TESTS();
333}