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 "VtsHalPresetReverbTargetTest"
18 #include <android-base/logging.h>
19 #include <android/binder_enums.h>
20 #include <audio_utils/power.h>
21 #include <system/audio.h>
22
23 #include "EffectHelper.h"
24
25 using namespace android;
26
27 using aidl::android::hardware::audio::common::getChannelCount;
28 using aidl::android::hardware::audio::effect::Descriptor;
29 using aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb;
30 using aidl::android::hardware::audio::effect::IEffect;
31 using aidl::android::hardware::audio::effect::IFactory;
32 using aidl::android::hardware::audio::effect::Parameter;
33 using aidl::android::hardware::audio::effect::PresetReverb;
34 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
35
36 class PresetReverbHelper : public EffectHelper {
37 public:
SetUpPresetReverb()38 void SetUpPresetReverb() {
39 ASSERT_NE(nullptr, mFactory);
40 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
41 Parameter::Specific specific = getDefaultParamSpecific();
42 Parameter::Common common = createParamCommon(
43 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
44 kSamplingFrequency /* oSampleRate */, mFrameCount /* iFrameCount */,
45 mFrameCount /* oFrameCount */);
46 ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
47 ASSERT_NE(nullptr, mEffect);
48 }
49
TearDownPresetReverb()50 void TearDownPresetReverb() {
51 ASSERT_NO_FATAL_FAILURE(close(mEffect));
52 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
53 mOpenEffectReturn = IEffect::OpenEffectReturn{};
54 }
55
getDefaultParamSpecific()56 Parameter::Specific getDefaultParamSpecific() {
57 PresetReverb pr = PresetReverb::make<PresetReverb::preset>(kDefaultPreset);
58 Parameter::Specific specific =
59 Parameter::Specific::make<Parameter::Specific::presetReverb>(pr);
60 return specific;
61 }
62
createPresetReverbParam(const PresetReverb::Presets & param)63 Parameter createPresetReverbParam(const PresetReverb::Presets& param) {
64 return Parameter::make<Parameter::specific>(
65 Parameter::Specific::make<Parameter::Specific::presetReverb>(
66 PresetReverb::make<PresetReverb::preset>(param)));
67 }
68
setAndVerifyPreset(const PresetReverb::Presets & param)69 void setAndVerifyPreset(const PresetReverb::Presets& param) {
70 auto expectedParam = createPresetReverbParam(param);
71 EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectedParam)) << expectedParam.toString();
72
73 PresetReverb::Id revId =
74 PresetReverb::Id::make<PresetReverb::Id::commonTag>(PresetReverb::preset);
75
76 auto id = Parameter::Id::make<Parameter::Id::presetReverbTag>(revId);
77 // get parameter
78 Parameter getParam;
79 EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
80 EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
81 << "\ngetParam:" << getParam.toString();
82 }
83
84 static constexpr int kSamplingFrequency = 44100;
85 static constexpr int kDurationMilliSec = 500;
86 static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
87 int mStereoChannelCount =
88 getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
89 AudioChannelLayout::LAYOUT_STEREO));
90 PresetReverb::Presets kDefaultPreset = PresetReverb::Presets::NONE;
91 int mFrameCount = kBufferSize / mStereoChannelCount;
92 std::shared_ptr<IFactory> mFactory;
93 std::shared_ptr<IEffect> mEffect;
94 IEffect::OpenEffectReturn mOpenEffectReturn;
95 Descriptor mDescriptor;
96 };
97
98 /**
99 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
100 * VtsAudioEffectTargetTest.
101 */
102 enum ParamName { PARAM_INSTANCE_NAME, PARAM_PRESETS };
103 using PresetReverbParamTestParam =
104 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, PresetReverb::Presets>;
105
106 // Testing for enum values
107 const std::vector<PresetReverb::Presets> kPresetsValues{
108 ndk::enum_range<PresetReverb::Presets>().begin(),
109 ndk::enum_range<PresetReverb::Presets>().end()};
110
111 class PresetReverbParamTest : public ::testing::TestWithParam<PresetReverbParamTestParam>,
112 public PresetReverbHelper {
113 public:
PresetReverbParamTest()114 PresetReverbParamTest() : mParamPreset(std::get<PARAM_PRESETS>(GetParam())) {
115 std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
116 }
117
SetUp()118 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb()); }
119
TearDown()120 void TearDown() override { TearDownPresetReverb(); }
121
122 const PresetReverb::Presets mParamPreset;
123 };
124
TEST_P(PresetReverbParamTest,SetAndGetPresets)125 TEST_P(PresetReverbParamTest, SetAndGetPresets) {
126 ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(mParamPreset));
127 }
128
129 using PresetReverbProcessTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
130
131 class PresetReverbProcessTest : public ::testing::TestWithParam<PresetReverbProcessTestParam>,
132 public PresetReverbHelper {
133 public:
PresetReverbProcessTest()134 PresetReverbProcessTest() {
135 std::tie(mFactory, mDescriptor) = GetParam();
136 generateSineWaveInput();
137 }
138
SetUp()139 void SetUp() override {
140 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
141 ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb());
142 }
TearDown()143 void TearDown() override {
144 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
145 ASSERT_NO_FATAL_FAILURE(TearDownPresetReverb());
146 }
147
generateSineWaveInput()148 void generateSineWaveInput() {
149 int frequency = 1000;
150 for (size_t i = 0; i < kBufferSize; i++) {
151 mInput.push_back(sin(2 * M_PI * frequency * i / kSamplingFrequency));
152 }
153 }
154
isAuxiliary()155 bool isAuxiliary() {
156 return mDescriptor.common.flags.type ==
157 aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
158 }
159
computeReverbOutputEnergy(std::vector<float> output)160 float computeReverbOutputEnergy(std::vector<float> output) {
161 if (!isAuxiliary()) {
162 // Extract auxiliary output
163 for (size_t i = 0; i < output.size(); i++) {
164 output[i] -= mInput[i];
165 }
166 }
167 return (audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT,
168 output.size()));
169 }
170
setPresetAndProcess(const PresetReverb::Presets & preset,std::vector<float> & output)171 void setPresetAndProcess(const PresetReverb::Presets& preset, std::vector<float>& output) {
172 ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(preset));
173 ASSERT_NO_FATAL_FAILURE(
174 processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
175 }
176
validateIncreasingEnergy(const std::vector<PresetReverb::Presets> & presets)177 void validateIncreasingEnergy(const std::vector<PresetReverb::Presets>& presets) {
178 float baseOutputEnergy = 0;
179
180 for (PresetReverb::Presets preset : presets) {
181 std::vector<float> output(kBufferSize);
182 setPresetAndProcess(preset, output);
183 float outputEnergy = computeReverbOutputEnergy(output);
184
185 ASSERT_GT(outputEnergy, baseOutputEnergy);
186 baseOutputEnergy = outputEnergy;
187 }
188 }
189
190 std::vector<float> mInput;
191 };
192
TEST_P(PresetReverbProcessTest,DecreasingRoomSize)193 TEST_P(PresetReverbProcessTest, DecreasingRoomSize) {
194 std::vector<PresetReverb::Presets> roomPresets = {PresetReverb::Presets::LARGEROOM,
195 PresetReverb::Presets::MEDIUMROOM,
196 PresetReverb::Presets::SMALLROOM};
197 validateIncreasingEnergy(roomPresets);
198 }
199
TEST_P(PresetReverbProcessTest,DecreasingHallSize)200 TEST_P(PresetReverbProcessTest, DecreasingHallSize) {
201 std::vector<PresetReverb::Presets> hallPresets = {PresetReverb::Presets::LARGEHALL,
202 PresetReverb::Presets::MEDIUMHALL};
203 validateIncreasingEnergy(hallPresets);
204 }
205
TEST_P(PresetReverbProcessTest,PresetPlate)206 TEST_P(PresetReverbProcessTest, PresetPlate) {
207 std::vector<float> output(kBufferSize);
208
209 setPresetAndProcess(PresetReverb::Presets::PLATE, output);
210 float outputEnergy = computeReverbOutputEnergy(output);
211 // Since there is no comparator preset, validating it is greater than zero
212 ASSERT_GT(outputEnergy, 0);
213 }
214
TEST_P(PresetReverbProcessTest,PresetNone)215 TEST_P(PresetReverbProcessTest, PresetNone) {
216 std::vector<float> output(kBufferSize);
217
218 setPresetAndProcess(kDefaultPreset, output);
219 float outputEnergy = computeReverbOutputEnergy(output);
220 // NONE type doesn't create reverb effect
221 ASSERT_EQ(outputEnergy, 0);
222 }
223
224 INSTANTIATE_TEST_SUITE_P(
225 PresetReverbTest, PresetReverbParamTest,
226 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
227 IFactory::descriptor, getEffectTypeUuidPresetReverb())),
228 testing::ValuesIn(kPresetsValues)),
__anon618d9b680102(const testing::TestParamInfo<PresetReverbParamTest::ParamType>& info) 229 [](const testing::TestParamInfo<PresetReverbParamTest::ParamType>& info) {
230 auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
231 std::string preset =
232 std::to_string(static_cast<int>(std::get<PARAM_PRESETS>(info.param)));
233 std::string name = getPrefix(descriptor) + "_preset" + preset;
234 std::replace_if(
235 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
236 return name;
237 });
238
239 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbParamTest);
240
241 INSTANTIATE_TEST_SUITE_P(
242 PresetReverbTest, PresetReverbProcessTest,
243 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
244 IFactory::descriptor, getEffectTypeUuidPresetReverb())),
__anon618d9b680302(const testing::TestParamInfo<PresetReverbProcessTest::ParamType>& info) 245 [](const testing::TestParamInfo<PresetReverbProcessTest::ParamType>& info) {
246 auto descriptor = info.param;
247 return getPrefix(descriptor.second);
248 });
249
250 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbProcessTest);
251
main(int argc,char ** argv)252 int main(int argc, char** argv) {
253 ::testing::InitGoogleTest(&argc, argv);
254 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
255 ABinderProcess_setThreadPoolMaxThreadCount(1);
256 ABinderProcess_startThreadPool();
257 return RUN_ALL_TESTS();
258 }
259