blob: f127c81a4e40d83c8bb7df84fe42f09d6232dffd [file] [log] [blame]
Sham Rathod73aa2c32022-12-20 17:03:40 +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
Mikhail Naganov872d4a62023-03-09 18:19:01 -080017#define LOG_TAG "VtsHalPresetReverbTargetTest"
18#include <android-base/logging.h>
Sham Rathod73aa2c32022-12-20 17:03:40 +053019#include <android/binder_enums.h>
Sneha Patil94abce02024-04-03 12:15:03 +053020#include <audio_utils/power.h>
21#include <system/audio.h>
Mikhail Naganov872d4a62023-03-09 18:19:01 -080022
Sham Rathod73aa2c32022-12-20 17:03:40 +053023#include "EffectHelper.h"
24
25using namespace android;
26
Sneha Patil94abce02024-04-03 12:15:03 +053027using aidl::android::hardware::audio::common::getChannelCount;
Sham Rathod73aa2c32022-12-20 17:03:40 +053028using aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yaof8be1ac2023-03-06 18:41:27 +000029using aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb;
Sham Rathod73aa2c32022-12-20 17:03:40 +053030using aidl::android::hardware::audio::effect::IEffect;
31using aidl::android::hardware::audio::effect::IFactory;
Sham Rathod73aa2c32022-12-20 17:03:40 +053032using aidl::android::hardware::audio::effect::Parameter;
33using aidl::android::hardware::audio::effect::PresetReverb;
Jaideep Sharma74498412023-09-13 15:25:25 +053034using android::hardware::audio::common::testing::detail::TestExecutionTracer;
Sham Rathod73aa2c32022-12-20 17:03:40 +053035
Sneha Patil94abce02024-04-03 12:15:03 +053036class PresetReverbHelper : public EffectHelper {
37 public:
38 void SetUpPresetReverb() {
39 ASSERT_NE(nullptr, mFactory);
40 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
41 Parameter::Specific specific = getDefaultParamSpecific();
Shunkai Yao61f9dd22024-05-08 22:34:36 +000042 Parameter::Common common = createParamCommon(
Sneha Patil94abce02024-04-03 12:15:03 +053043 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
50 void TearDownPresetReverb() {
51 ASSERT_NO_FATAL_FAILURE(close(mEffect));
52 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
53 mOpenEffectReturn = IEffect::OpenEffectReturn{};
54 }
55
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
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
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
Sneha Patila9171f92024-06-06 09:42:39 +000084 static constexpr int kDurationMilliSec = 500;
Sneha Patil94abce02024-04-03 12:15:03 +053085 static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
86 int mStereoChannelCount =
87 getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
88 AudioChannelLayout::LAYOUT_STEREO));
89 PresetReverb::Presets kDefaultPreset = PresetReverb::Presets::NONE;
90 int mFrameCount = kBufferSize / mStereoChannelCount;
91 std::shared_ptr<IFactory> mFactory;
92 std::shared_ptr<IEffect> mEffect;
93 IEffect::OpenEffectReturn mOpenEffectReturn;
94 Descriptor mDescriptor;
95};
96
Sham Rathod73aa2c32022-12-20 17:03:40 +053097/**
98 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
99 * VtsAudioEffectTargetTest.
100 */
101enum ParamName { PARAM_INSTANCE_NAME, PARAM_PRESETS };
102using PresetReverbParamTestParam =
103 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, PresetReverb::Presets>;
104
105// Testing for enum values
106const std::vector<PresetReverb::Presets> kPresetsValues{
107 ndk::enum_range<PresetReverb::Presets>().begin(),
108 ndk::enum_range<PresetReverb::Presets>().end()};
109
110class PresetReverbParamTest : public ::testing::TestWithParam<PresetReverbParamTestParam>,
Sneha Patil94abce02024-04-03 12:15:03 +0530111 public PresetReverbHelper {
Sham Rathod73aa2c32022-12-20 17:03:40 +0530112 public:
Sneha Patil94abce02024-04-03 12:15:03 +0530113 PresetReverbParamTest() : mParamPreset(std::get<PARAM_PRESETS>(GetParam())) {
Sham Rathod73aa2c32022-12-20 17:03:40 +0530114 std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
115 }
116
Sneha Patil94abce02024-04-03 12:15:03 +0530117 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb()); }
Sham Rathod73aa2c32022-12-20 17:03:40 +0530118
Sneha Patil94abce02024-04-03 12:15:03 +0530119 void TearDown() override { TearDownPresetReverb(); }
Sham Rathod73aa2c32022-12-20 17:03:40 +0530120
Sneha Patil94abce02024-04-03 12:15:03 +0530121 const PresetReverb::Presets mParamPreset;
Sham Rathod73aa2c32022-12-20 17:03:40 +0530122};
123
124TEST_P(PresetReverbParamTest, SetAndGetPresets) {
Sneha Patil94abce02024-04-03 12:15:03 +0530125 ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(mParamPreset));
126}
127
128using PresetReverbProcessTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
129
130class PresetReverbProcessTest : public ::testing::TestWithParam<PresetReverbProcessTestParam>,
131 public PresetReverbHelper {
132 public:
133 PresetReverbProcessTest() {
134 std::tie(mFactory, mDescriptor) = GetParam();
Sneha Patiled98f7b2024-10-22 13:07:47 +0000135 mInput.resize(kBufferSize);
Sneha Patil94abce02024-04-03 12:15:03 +0530136 }
137
138 void SetUp() override {
139 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000140 ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, mInput));
Sneha Patil94abce02024-04-03 12:15:03 +0530141 ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb());
142 }
143 void TearDown() override {
144 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
145 ASSERT_NO_FATAL_FAILURE(TearDownPresetReverb());
146 }
147
Sneha Patil94abce02024-04-03 12:15:03 +0530148 bool isAuxiliary() {
149 return mDescriptor.common.flags.type ==
150 aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
151 }
152
153 float computeReverbOutputEnergy(std::vector<float> output) {
154 if (!isAuxiliary()) {
155 // Extract auxiliary output
156 for (size_t i = 0; i < output.size(); i++) {
157 output[i] -= mInput[i];
158 }
159 }
160 return (audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT,
161 output.size()));
162 }
163
164 void setPresetAndProcess(const PresetReverb::Presets& preset, std::vector<float>& output) {
165 ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(preset));
166 ASSERT_NO_FATAL_FAILURE(
167 processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
168 }
169
170 void validateIncreasingEnergy(const std::vector<PresetReverb::Presets>& presets) {
171 float baseOutputEnergy = 0;
172
173 for (PresetReverb::Presets preset : presets) {
174 std::vector<float> output(kBufferSize);
175 setPresetAndProcess(preset, output);
176 float outputEnergy = computeReverbOutputEnergy(output);
177
178 ASSERT_GT(outputEnergy, baseOutputEnergy);
179 baseOutputEnergy = outputEnergy;
180 }
181 }
182
183 std::vector<float> mInput;
184};
185
186TEST_P(PresetReverbProcessTest, DecreasingRoomSize) {
187 std::vector<PresetReverb::Presets> roomPresets = {PresetReverb::Presets::LARGEROOM,
188 PresetReverb::Presets::MEDIUMROOM,
189 PresetReverb::Presets::SMALLROOM};
190 validateIncreasingEnergy(roomPresets);
191}
192
193TEST_P(PresetReverbProcessTest, DecreasingHallSize) {
194 std::vector<PresetReverb::Presets> hallPresets = {PresetReverb::Presets::LARGEHALL,
195 PresetReverb::Presets::MEDIUMHALL};
196 validateIncreasingEnergy(hallPresets);
197}
198
199TEST_P(PresetReverbProcessTest, PresetPlate) {
200 std::vector<float> output(kBufferSize);
201
202 setPresetAndProcess(PresetReverb::Presets::PLATE, output);
203 float outputEnergy = computeReverbOutputEnergy(output);
204 // Since there is no comparator preset, validating it is greater than zero
205 ASSERT_GT(outputEnergy, 0);
206}
207
208TEST_P(PresetReverbProcessTest, PresetNone) {
209 std::vector<float> output(kBufferSize);
210
211 setPresetAndProcess(kDefaultPreset, output);
212 float outputEnergy = computeReverbOutputEnergy(output);
213 // NONE type doesn't create reverb effect
214 ASSERT_EQ(outputEnergy, 0);
Sham Rathod73aa2c32022-12-20 17:03:40 +0530215}
216
217INSTANTIATE_TEST_SUITE_P(
218 PresetReverbTest, PresetReverbParamTest,
219 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000220 IFactory::descriptor, getEffectTypeUuidPresetReverb())),
Sham Rathod73aa2c32022-12-20 17:03:40 +0530221 testing::ValuesIn(kPresetsValues)),
222 [](const testing::TestParamInfo<PresetReverbParamTest::ParamType>& info) {
223 auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
224 std::string preset =
225 std::to_string(static_cast<int>(std::get<PARAM_PRESETS>(info.param)));
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530226 std::string name = getPrefix(descriptor) + "_preset" + preset;
Sham Rathod73aa2c32022-12-20 17:03:40 +0530227 std::replace_if(
228 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
229 return name;
230 });
231
232GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbParamTest);
233
Sneha Patil94abce02024-04-03 12:15:03 +0530234INSTANTIATE_TEST_SUITE_P(
235 PresetReverbTest, PresetReverbProcessTest,
236 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
237 IFactory::descriptor, getEffectTypeUuidPresetReverb())),
238 [](const testing::TestParamInfo<PresetReverbProcessTest::ParamType>& info) {
239 auto descriptor = info.param;
240 return getPrefix(descriptor.second);
241 });
242
243GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbProcessTest);
244
Sham Rathod73aa2c32022-12-20 17:03:40 +0530245int main(int argc, char** argv) {
246 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +0530247 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Sham Rathod73aa2c32022-12-20 17:03:40 +0530248 ABinderProcess_setThreadPoolMaxThreadCount(1);
249 ABinderProcess_startThreadPool();
250 return RUN_ALL_TESTS();
251}