1 /*
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 
17 #define LOG_TAG "VtsHalEnvironmentalReverbTest"
18 #include <android-base/logging.h>
19 #include <audio_utils/power.h>
20 #include <system/audio.h>
21 
22 #include "EffectHelper.h"
23 
24 using namespace android;
25 using namespace aidl::android::hardware::audio::effect;
26 using aidl::android::hardware::audio::common::getChannelCount;
27 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
28 using TagVectorPair = std::pair<EnvironmentalReverb::Tag, std::vector<int>>;
29 using TagValuePair = std::pair<EnvironmentalReverb::Tag, int>;
30 
31 static constexpr int kMaxRoomLevel = 0;
32 static constexpr int kMinRoomLevel = -6000;
33 static constexpr int kMinRoomHfLevel = -4000;
34 static constexpr int kMinDecayTime = 0;
35 static constexpr int kMinHfRatio = 100;
36 static constexpr int kMinLevel = -6000;
37 static constexpr int kMinDensity = 0;
38 static constexpr int kMinDiffusion = 0;
39 static constexpr int kMinDelay = 0;
40 
41 static const std::vector<TagVectorPair> kParamsIncreasingVector = {
42 
43         {EnvironmentalReverb::roomLevelMb, {-3500, -2800, -2100, -1400, -700, 0}},
44         {EnvironmentalReverb::roomHfLevelMb, {-4000, -3200, -2400, -1600, -800, 0}},
45         {EnvironmentalReverb::decayTimeMs, {800, 1600, 2400, 3200, 4000}},
46         {EnvironmentalReverb::decayHfRatioPm, {100, 600, 1100, 1600, 2000}},
47         {EnvironmentalReverb::levelMb, {-3500, -2800, -2100, -1400, -700, 0}},
48 };
49 
50 static const std::vector<TagValuePair> kParamsMinimumValue = {
51         {EnvironmentalReverb::roomLevelMb, kMinRoomLevel},
52         {EnvironmentalReverb::decayTimeMs, kMinDecayTime},
53         {EnvironmentalReverb::levelMb, kMinLevel}};
54 
55 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
56 
57 using Maker = std::set<int> (*)();
58 static const std::array<Maker, static_cast<int>(EnvironmentalReverb::bypass) + 1>
59         kTestValueSetMaker = {
60                 nullptr,
__anon335364b70102() 61                 []() -> std::set<int> {
62                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
63                                                          Range::environmentalReverb,
64                                                          EnvironmentalReverb::roomLevelMb>(
65                             kDescPair, EffectHelper::expandTestValueBasic<int>);
66                 },
__anon335364b70202() 67                 []() -> std::set<int> {
68                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
69                                                          Range::environmentalReverb,
70                                                          EnvironmentalReverb::roomHfLevelMb>(
71                             kDescPair, EffectHelper::expandTestValueBasic<int>);
72                 },
__anon335364b70302() 73                 []() -> std::set<int> {
74                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
75                                                          Range::environmentalReverb,
76                                                          EnvironmentalReverb::decayTimeMs>(
77                             kDescPair, EffectHelper::expandTestValueBasic<int>);
78                 },
__anon335364b70402() 79                 []() -> std::set<int> {
80                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
81                                                          Range::environmentalReverb,
82                                                          EnvironmentalReverb::decayHfRatioPm>(
83                             kDescPair, EffectHelper::expandTestValueBasic<int>);
84                 },
85                 nullptr,
86                 nullptr,
__anon335364b70502() 87                 []() -> std::set<int> {
88                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
89                                                          Range::environmentalReverb,
90                                                          EnvironmentalReverb::levelMb>(
91                             kDescPair, EffectHelper::expandTestValueBasic<int>);
92                 },
__anon335364b70602() 93                 []() -> std::set<int> {
94                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
95                                                          Range::environmentalReverb,
96                                                          EnvironmentalReverb::delayMs>(
97                             kDescPair, EffectHelper::expandTestValueBasic<int>);
98                 },
__anon335364b70702() 99                 []() -> std::set<int> {
100                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
101                                                          Range::environmentalReverb,
102                                                          EnvironmentalReverb::diffusionPm>(
103                             kDescPair, EffectHelper::expandTestValueBasic<int>);
104                 },
__anon335364b70802() 105                 []() -> std::set<int> {
106                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
107                                                          Range::environmentalReverb,
108                                                          EnvironmentalReverb::densityPm>(
109                             kDescPair, EffectHelper::expandTestValueBasic<int>);
110                 },
__anon335364b70902() 111                 []() -> std::set<int> {
112                     return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
113                                                          Range::environmentalReverb,
114                                                          EnvironmentalReverb::bypass>(
115                             kDescPair, EffectHelper::expandTestValueBasic<int>);
116                 },
117 };
118 
buildSetAndGetTestParams()119 static std::vector<TagValuePair> buildSetAndGetTestParams() {
120     std::vector<TagValuePair> valueTag;
121     for (EnvironmentalReverb::Tag tag : ndk::enum_range<EnvironmentalReverb::Tag>()) {
122         std::set<int> values;
123         int intTag = static_cast<int>(tag);
124         if (intTag <= static_cast<int>(EnvironmentalReverb::bypass) &&
125             kTestValueSetMaker[intTag] != nullptr) {
126             values = kTestValueSetMaker[intTag]();
127         }
128 
129         for (const auto& value : values) {
130             valueTag.push_back(std::make_pair(tag, value));
131         }
132     }
133 
134     return valueTag;
135 }
136 /**
137  * Tests do the following:
138  * - Testing parameter range supported by the effect. Range is verified with IEffect.getDescriptor()
139  *   and range defined in the documentation.
140  * - Validating the effect by comparing the outputs of the supported parameters.
141  */
142 
143 enum ParamName { DESCRIPTOR_INDEX, TAG_VALUE_PAIR };
144 
145 class EnvironmentalReverbHelper : public EffectHelper {
146   public:
EnvironmentalReverbHelper(std::pair<std::shared_ptr<IFactory>,Descriptor> pair)147     EnvironmentalReverbHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair) {
148         std::tie(mFactory, mDescriptor) = pair;
149     }
150 
SetUpReverb()151     void SetUpReverb() {
152         ASSERT_NE(nullptr, mFactory);
153         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
154 
155         Parameter::Specific specific = getDefaultParamSpecific();
156         Parameter::Common common = createParamCommon(
157                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
158                 mFrameCount /* iFrameCount */, mFrameCount /* oFrameCount */);
159         ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
160         ASSERT_NE(nullptr, mEffect);
161     }
162 
TearDownReverb()163     void TearDownReverb() {
164         ASSERT_NO_FATAL_FAILURE(close(mEffect));
165         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
166     }
167 
getDefaultParamSpecific()168     Parameter::Specific getDefaultParamSpecific() {
169         EnvironmentalReverb er =
170                 EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(kMaxRoomLevel);
171         Parameter::Specific specific =
172                 Parameter::Specific::make<Parameter::Specific::environmentalReverb>(er);
173         return specific;
174     }
175 
isParamValid(EnvironmentalReverb env)176     bool isParamValid(EnvironmentalReverb env) {
177         return isParameterValid<EnvironmentalReverb, Range::environmentalReverb>(env, mDescriptor);
178     }
179 
createParam(EnvironmentalReverb env)180     Parameter createParam(EnvironmentalReverb env) {
181         return Parameter::make<Parameter::specific>(
182                 Parameter::Specific::make<Parameter::Specific::environmentalReverb>(env));
183     }
184 
setAndVerifyParam(binder_exception_t expected,EnvironmentalReverb env,EnvironmentalReverb::Tag tag)185     void setAndVerifyParam(binder_exception_t expected, EnvironmentalReverb env,
186                            EnvironmentalReverb::Tag tag) {
187         auto expectedParam = createParam(env);
188 
189         EXPECT_STATUS(expected, mEffect->setParameter(expectedParam)) << expectedParam.toString();
190 
191         if (expected == EX_NONE) {
192             auto erId = EnvironmentalReverb::Id::make<EnvironmentalReverb::Id::commonTag>(
193                     EnvironmentalReverb::Tag(tag));
194 
195             auto id = Parameter::Id::make<Parameter::Id::environmentalReverbTag>(erId);
196 
197             // get parameter
198             Parameter getParam;
199             EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
200             EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
201                                                << "\ngetParam:" << getParam.toString();
202         }
203     }
204 
isAuxiliary()205     bool isAuxiliary() {
206         return mDescriptor.common.flags.type ==
207                aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
208     }
209 
computeOutputEnergy(const std::vector<float> & input,std::vector<float> output)210     float computeOutputEnergy(const std::vector<float>& input, std::vector<float> output) {
211         if (!isAuxiliary()) {
212             // Extract auxiliary output
213             for (size_t i = 0; i < output.size(); i++) {
214                 output[i] -= input[i];
215             }
216         }
217         return audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT,
218                                                output.size());
219     }
220 
generateSineWaveInput(std::vector<float> & input)221     void generateSineWaveInput(std::vector<float>& input) {
222         int frequency = 1000;
223         size_t kSamplingFrequency = 44100;
224         for (size_t i = 0; i < input.size(); i++) {
225             input[i] = sin(2 * M_PI * frequency * i / kSamplingFrequency);
226         }
227     }
228     using Maker = EnvironmentalReverb (*)(int);
229 
230     static constexpr std::array<Maker, static_cast<int>(EnvironmentalReverb::bypass) + 1>
231             kEnvironmentalReverbParamMaker = {
232                     nullptr,
__anon335364b70a02() 233                     [](int value) -> EnvironmentalReverb {
234                         return EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(value);
235                     },
__anon335364b70b02() 236                     [](int value) -> EnvironmentalReverb {
237                         return EnvironmentalReverb::make<EnvironmentalReverb::roomHfLevelMb>(value);
238                     },
__anon335364b70c02() 239                     [](int value) -> EnvironmentalReverb {
240                         return EnvironmentalReverb::make<EnvironmentalReverb::decayTimeMs>(value);
241                     },
__anon335364b70d02() 242                     [](int value) -> EnvironmentalReverb {
243                         return EnvironmentalReverb::make<EnvironmentalReverb::decayHfRatioPm>(
244                                 value);
245                     },
246                     nullptr,
247                     nullptr,
__anon335364b70e02() 248                     [](int value) -> EnvironmentalReverb {
249                         return EnvironmentalReverb::make<EnvironmentalReverb::levelMb>(value);
250                     },
__anon335364b70f02() 251                     [](int value) -> EnvironmentalReverb {
252                         return EnvironmentalReverb::make<EnvironmentalReverb::delayMs>(value);
253                     },
__anon335364b71002() 254                     [](int value) -> EnvironmentalReverb {
255                         return EnvironmentalReverb::make<EnvironmentalReverb::diffusionPm>(value);
256                     },
__anon335364b71102() 257                     [](int value) -> EnvironmentalReverb {
258                         return EnvironmentalReverb::make<EnvironmentalReverb::densityPm>(value);
259                     },
__anon335364b71202() 260                     [](int value) -> EnvironmentalReverb {
261                         return EnvironmentalReverb::make<EnvironmentalReverb::bypass>(value);
262                     }};
263 
createEnvParam(EnvironmentalReverb::Tag tag,int paramValue)264     void createEnvParam(EnvironmentalReverb::Tag tag, int paramValue) {
265         int intTag = static_cast<int>(tag);
266         if (intTag <= static_cast<int>(EnvironmentalReverb::bypass) &&
267             kEnvironmentalReverbParamMaker[intTag] != NULL) {
268             mEnvParam = kEnvironmentalReverbParamMaker[intTag](paramValue);
269         } else {
270             GTEST_SKIP() << "Invalid parameter, skipping the test\n";
271         }
272     }
273 
setParameterAndProcess(std::vector<float> & input,std::vector<float> & output,int val,EnvironmentalReverb::Tag tag)274     void setParameterAndProcess(std::vector<float>& input, std::vector<float>& output, int val,
275                                 EnvironmentalReverb::Tag tag) {
276         createEnvParam(tag, val);
277         if (isParamValid(mEnvParam)) {
278             ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, tag));
279             ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(input, output, mEffect, &ret));
280         }
281     }
282 
283     static constexpr int kSamplingFrequency = 44100;
284     static constexpr int kDurationMilliSec = 500;
285     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
286 
287     int mStereoChannelCount =
288             getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
289                     AudioChannelLayout::LAYOUT_STEREO));
290     int mFrameCount = kBufferSize / mStereoChannelCount;
291 
292     std::shared_ptr<IFactory> mFactory;
293     std::shared_ptr<IEffect> mEffect;
294     IEffect::OpenEffectReturn ret;
295     Descriptor mDescriptor;
296     EnvironmentalReverb mEnvParam;
297 };
298 
299 class EnvironmentalReverbParamTest
300     : public ::testing::TestWithParam<
301               std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagValuePair>>,
302       public EnvironmentalReverbHelper {
303   public:
EnvironmentalReverbParamTest()304     EnvironmentalReverbParamTest()
305         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
306         std::tie(mTag, mParamValue) = std::get<TAG_VALUE_PAIR>(GetParam());
307     }
SetUp()308     void SetUp() override { SetUpReverb(); }
TearDown()309     void TearDown() override { TearDownReverb(); }
310 
311     EnvironmentalReverb::Tag mTag;
312     int mParamValue;
313 };
314 
TEST_P(EnvironmentalReverbParamTest,SetAndGetParameter)315 TEST_P(EnvironmentalReverbParamTest, SetAndGetParameter) {
316     createEnvParam(mTag, mParamValue);
317     ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(
318             isParamValid(mEnvParam) ? EX_NONE : EX_ILLEGAL_ARGUMENT, mEnvParam, mTag));
319 }
320 
321 INSTANTIATE_TEST_SUITE_P(
322         EnvironmentalReverbTest, EnvironmentalReverbParamTest,
323         ::testing::Combine(
324                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
325                                           IFactory::descriptor, getEffectTypeUuidEnvReverb())),
326                 testing::ValuesIn(buildSetAndGetTestParams())),
__anon335364b71302(const testing::TestParamInfo<EnvironmentalReverbParamTest::ParamType>& info) 327         [](const testing::TestParamInfo<EnvironmentalReverbParamTest::ParamType>& info) {
328             auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
329             auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
330             auto val = std::get<TAG_VALUE_PAIR>(info.param).second;
331             std::string name =
332                     getPrefix(descriptor) + "_Tag_" + toString(tag) + std::to_string(val);
333             std::replace_if(
334                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
335             return name;
336         });
337 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbParamTest);
338 
339 class EnvironmentalReverbDataTest
340     : public ::testing::TestWithParam<
341               std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagVectorPair>>,
342       public EnvironmentalReverbHelper {
343   public:
EnvironmentalReverbDataTest()344     EnvironmentalReverbDataTest()
345         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
346         std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
347         mInput.resize(kBufferSize);
348         generateSineWaveInput(mInput);
349     }
SetUp()350     void SetUp() override { SetUpReverb(); }
TearDown()351     void TearDown() override { TearDownReverb(); }
352 
assertEnergyIncreasingWithParameter(bool bypass)353     void assertEnergyIncreasingWithParameter(bool bypass) {
354         createEnvParam(EnvironmentalReverb::bypass, bypass);
355         ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::bypass));
356         float baseEnergy = 0;
357         for (int val : mParamValues) {
358             std::vector<float> output(kBufferSize);
359             setParameterAndProcess(mInput, output, val, mTag);
360             float energy = computeOutputEnergy(mInput, output);
361             ASSERT_GT(energy, baseEnergy);
362             baseEnergy = energy;
363         }
364     }
365 
assertZeroEnergyWithBypass(bool bypass)366     void assertZeroEnergyWithBypass(bool bypass) {
367         createEnvParam(EnvironmentalReverb::bypass, bypass);
368         ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::bypass));
369         for (int val : mParamValues) {
370             std::vector<float> output(kBufferSize);
371             setParameterAndProcess(mInput, output, val, mTag);
372             float energy = computeOutputEnergy(mInput, output);
373             ASSERT_EQ(energy, 0);
374         }
375     }
376 
377     EnvironmentalReverb::Tag mTag;
378     std::vector<int> mParamValues;
379     std::vector<float> mInput;
380 };
381 
TEST_P(EnvironmentalReverbDataTest,IncreasingParamValue)382 TEST_P(EnvironmentalReverbDataTest, IncreasingParamValue) {
383     assertEnergyIncreasingWithParameter(false);
384 }
385 
TEST_P(EnvironmentalReverbDataTest,WithBypassEnabled)386 TEST_P(EnvironmentalReverbDataTest, WithBypassEnabled) {
387     assertZeroEnergyWithBypass(true);
388 }
389 
390 INSTANTIATE_TEST_SUITE_P(
391         EnvironmentalReverbTest, EnvironmentalReverbDataTest,
392         ::testing::Combine(
393                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
394                                           IFactory::descriptor, getEffectTypeUuidEnvReverb())),
395                 testing::ValuesIn(kParamsIncreasingVector)),
__anon335364b71502(const testing::TestParamInfo<EnvironmentalReverbDataTest::ParamType>& info) 396         [](const testing::TestParamInfo<EnvironmentalReverbDataTest::ParamType>& info) {
397             auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
398             auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
399             std::string name = getPrefix(descriptor) + "_Tag_" + toString(tag);
400             return name;
401         });
402 
403 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDataTest);
404 
405 class EnvironmentalReverbMinimumParamTest
406     : public ::testing::TestWithParam<
407               std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagValuePair>>,
408       public EnvironmentalReverbHelper {
409   public:
EnvironmentalReverbMinimumParamTest()410     EnvironmentalReverbMinimumParamTest()
411         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
412         std::tie(mTag, mValue) = std::get<TAG_VALUE_PAIR>(GetParam());
413     }
SetUp()414     void SetUp() override {
415         SetUpReverb();
416         createEnvParam(EnvironmentalReverb::roomLevelMb, kMinRoomLevel);
417         ASSERT_NO_FATAL_FAILURE(
418                 setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::roomLevelMb));
419     }
TearDown()420     void TearDown() override { TearDownReverb(); }
421 
422     EnvironmentalReverb::Tag mTag;
423     int mValue;
424 };
425 
TEST_P(EnvironmentalReverbMinimumParamTest,MinimumValueTest)426 TEST_P(EnvironmentalReverbMinimumParamTest, MinimumValueTest) {
427     std::vector<float> input(kBufferSize);
428     generateSineWaveInput(input);
429     std::vector<float> output(kBufferSize);
430     setParameterAndProcess(input, output, mValue, mTag);
431     float energy = computeOutputEnergy(input, output);
432     // No Auxiliary output for minimum param values
433     ASSERT_EQ(energy, 0);
434 }
435 
436 INSTANTIATE_TEST_SUITE_P(
437         EnvironmentalReverbTest, EnvironmentalReverbMinimumParamTest,
438         ::testing::Combine(
439                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
440                                           IFactory::descriptor, getEffectTypeUuidEnvReverb())),
441                 testing::ValuesIn(kParamsMinimumValue)),
__anon335364b71602(const testing::TestParamInfo<EnvironmentalReverbMinimumParamTest::ParamType>& info) 442         [](const testing::TestParamInfo<EnvironmentalReverbMinimumParamTest::ParamType>& info) {
443             auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
444             auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
445             auto val = std::get<TAG_VALUE_PAIR>(info.param).second;
446             std::string name =
447                     getPrefix(descriptor) + "_Tag_" + toString(tag) + std::to_string(val);
448             std::replace_if(
449                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
450             return name;
451         });
452 
453 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbMinimumParamTest);
454 
main(int argc,char ** argv)455 int main(int argc, char** argv) {
456     ::testing::InitGoogleTest(&argc, argv);
457     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
458     ABinderProcess_setThreadPoolMaxThreadCount(1);
459     ABinderProcess_startThreadPool();
460     return RUN_ALL_TESTS();
461 }
462