blob: 95bcaf0d6e8dc305ddc7bf75ef38f180b8810eba [file] [log] [blame]
Ram Mohane4064ce2022-12-20 18:05:14 +05301/*
2 * Copyright (C) 2023 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
Ram Mohane4064ce2022-12-20 18:05:14 +053017#include <set>
18#include <string>
Ram Mohane4064ce2022-12-20 18:05:14 +053019#include <unordered_set>
20
Mikhail Naganov872d4a62023-03-09 18:19:01 -080021#define LOG_TAG "VtsHalDynamicsProcessingTest"
22#include <android-base/logging.h>
Sneha Patilabc94642024-11-13 08:41:05 +000023#include <audio_utils/power.h>
24#include <audio_utils/primitives.h>
Mikhail Naganov872d4a62023-03-09 18:19:01 -080025
Ram Mohane4064ce2022-12-20 18:05:14 +053026#include <Utils.h>
Mikhail Naganov872d4a62023-03-09 18:19:01 -080027
Ram Mohane4064ce2022-12-20 18:05:14 +053028#include "EffectHelper.h"
Ram Mohanafdf90b2023-03-23 08:48:25 +053029#include "EffectRangeSpecific.h"
Ram Mohane4064ce2022-12-20 18:05:14 +053030
31using namespace android;
Ram Mohanafdf90b2023-03-23 08:48:25 +053032using namespace aidl::android::hardware::audio::effect::DynamicsProcessingRanges;
Ram Mohane4064ce2022-12-20 18:05:14 +053033
Ram Mohane4064ce2022-12-20 18:05:14 +053034using aidl::android::hardware::audio::effect::Descriptor;
35using aidl::android::hardware::audio::effect::DynamicsProcessing;
Shunkai Yaof8be1ac2023-03-06 18:41:27 +000036using aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing;
Ram Mohane4064ce2022-12-20 18:05:14 +053037using aidl::android::hardware::audio::effect::IEffect;
38using aidl::android::hardware::audio::effect::IFactory;
Ram Mohane4064ce2022-12-20 18:05:14 +053039using aidl::android::hardware::audio::effect::Parameter;
Jaideep Sharma74498412023-09-13 15:25:25 +053040using android::hardware::audio::common::testing::detail::TestExecutionTracer;
Ram Mohane4064ce2022-12-20 18:05:14 +053041
42/**
43 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
44 * VtsAudioEffectTargetTest.
45 */
46class DynamicsProcessingTestHelper : public EffectHelper {
47 public:
48 DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair,
Aayush Sonifbb5cd32024-11-21 10:51:46 +000049 int32_t channelLayout = kDefaultChannelLayout)
50 : mChannelLayout(channelLayout),
Sneha Patilabc94642024-11-13 08:41:05 +000051 mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
52 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout))) {
Ram Mohane4064ce2022-12-20 18:05:14 +053053 std::tie(mFactory, mDescriptor) = pair;
Ram Mohane4064ce2022-12-20 18:05:14 +053054 }
55
56 // setup
57 void SetUpDynamicsProcessingEffect() {
58 ASSERT_NE(nullptr, mFactory);
59 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Ram Mohane4064ce2022-12-20 18:05:14 +053060 Parameter::Specific specific = getDefaultParamSpecific();
Shunkai Yao61f9dd22024-05-08 22:34:36 +000061 Parameter::Common common = createParamCommon(
Sneha Patilabc94642024-11-13 08:41:05 +000062 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
63 kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
64 kFrameCount /* oFrameCount */,
Ram Mohane4064ce2022-12-20 18:05:14 +053065 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout),
66 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
Sneha Patilabc94642024-11-13 08:41:05 +000067 ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
Ram Mohane4064ce2022-12-20 18:05:14 +053068 ASSERT_NE(nullptr, mEffect);
69 mEngineConfigApplied = mEngineConfigPreset;
70 }
71
72 Parameter::Specific getDefaultParamSpecific() {
73 DynamicsProcessing dp = DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
74 mEngineConfigPreset);
75 Parameter::Specific specific =
76 Parameter::Specific::make<Parameter::Specific::dynamicsProcessing>(dp);
77 return specific;
78 }
79
80 // teardown
81 void TearDownDynamicsProcessingEffect() {
82 ASSERT_NO_FATAL_FAILURE(close(mEffect));
83 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
84 }
85
86 // utils functions for parameter checking
Ram Mohane4064ce2022-12-20 18:05:14 +053087 bool isParamEqual(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dpRef,
88 const DynamicsProcessing& dpTest);
Ram Mohane4064ce2022-12-20 18:05:14 +053089 bool isEngineConfigEqual(const DynamicsProcessing::EngineArchitecture& refCfg,
90 const DynamicsProcessing::EngineArchitecture& testCfg);
91
92 template <typename T>
93 std::vector<T> filterEnabledVector(const std::vector<T>& vec);
94
95 template <typename T>
96 bool isAidlVectorEqualAfterFilter(const std::vector<T>& source, const std::vector<T>& target);
97
98 template <typename T>
99 bool isAidlVectorEqual(const std::vector<T>& source, const std::vector<T>& target);
100
Ram Mohanafdf90b2023-03-23 08:48:25 +0530101 template <typename T>
102 bool isChannelConfigValid(const std::vector<T>& cfgs) {
103 auto& channelCount = mChannelCount;
104 return std::all_of(cfgs.cbegin(), cfgs.cend(), [channelCount](const T& cfg) {
105 return (cfg.channel >= 0 && cfg.channel < channelCount);
106 });
107 }
108
109 template <typename T>
110 bool isBandConfigValid(const std::vector<T>& cfgs, int bandCount);
111
112 bool isParamValid(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dp);
113
Ram Mohane4064ce2022-12-20 18:05:14 +0530114 // get set params and validate
115 void SetAndGetDynamicsProcessingParameters();
116
Sneha Patilabc94642024-11-13 08:41:05 +0000117 bool isAllParamsValid();
118
Sneha Patilcbf86a42024-11-26 10:41:54 +0000119 void setParamsAndProcess(std::vector<float>& input, std::vector<float>& output);
120
121 float calculateDb(const std::vector<float>& input, size_t startSamplePos);
122
Ram Mohane4064ce2022-12-20 18:05:14 +0530123 // enqueue test parameters
124 void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
125 void addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
126 void addPostEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
127 void addMbcChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
128 void addPreEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
129 void addPostEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
130 void addMbcBandConfigs(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs);
131 void addLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfg);
132 void addInputGain(const std::vector<DynamicsProcessing::InputGain>& inputGain);
133
134 static constexpr float kPreferredProcessingDurationMs = 10.0f;
135 static constexpr int kBandCount = 5;
Sneha Patilabc94642024-11-13 08:41:05 +0000136 static constexpr int kSamplingFrequency = 44100;
137 static constexpr int kFrameCount = 2048;
Sneha Patilcbf86a42024-11-26 10:41:54 +0000138 static constexpr int kInputFrequency = 1000;
139 static constexpr size_t kStartIndex = 15 * kSamplingFrequency / 1000; // skip 15ms
140 static constexpr float kToleranceDb = 0.05;
Ram Mohane4064ce2022-12-20 18:05:14 +0530141 std::shared_ptr<IFactory> mFactory;
142 std::shared_ptr<IEffect> mEffect;
143 Descriptor mDescriptor;
Sneha Patilabc94642024-11-13 08:41:05 +0000144 IEffect::OpenEffectReturn mOpenEffectReturn;
Ram Mohane4064ce2022-12-20 18:05:14 +0530145 DynamicsProcessing::EngineArchitecture mEngineConfigApplied;
146 DynamicsProcessing::EngineArchitecture mEngineConfigPreset{
147 .resolutionPreference =
148 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
149 .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
150 .preEqStage = {.inUse = true, .bandCount = kBandCount},
151 .postEqStage = {.inUse = true, .bandCount = kBandCount},
152 .mbcStage = {.inUse = true, .bandCount = kBandCount},
153 .limiterInUse = true,
154 };
155
156 std::unordered_set<int /* channelId */> mPreEqChannelEnable;
157 std::unordered_set<int /* channelId */> mPostEqChannelEnable;
158 std::unordered_set<int /* channelId */> mMbcChannelEnable;
159 std::unordered_set<int /* channelId */> mLimiterChannelEnable;
160 static const std::set<std::vector<DynamicsProcessing::ChannelConfig>> kChannelConfigTestSet;
161 static const std::set<DynamicsProcessing::StageEnablement> kStageEnablementTestSet;
162 static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
163
164 private:
Ram Mohane4064ce2022-12-20 18:05:14 +0530165 std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
Sneha Patilabc94642024-11-13 08:41:05 +0000166
167 protected:
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000168 const int32_t mChannelLayout;
Sneha Patilabc94642024-11-13 08:41:05 +0000169 const int mChannelCount;
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000170
Ram Mohane4064ce2022-12-20 18:05:14 +0530171 void CleanUp() {
172 mTags.clear();
173 mPreEqChannelEnable.clear();
174 mPostEqChannelEnable.clear();
175 mMbcChannelEnable.clear();
176 mLimiterChannelEnable.clear();
177 }
178};
179
180// test value set for DynamicsProcessing::StageEnablement
181const std::set<DynamicsProcessing::StageEnablement>
182 DynamicsProcessingTestHelper::kStageEnablementTestSet = {
183 {.inUse = true, .bandCount = DynamicsProcessingTestHelper::kBandCount},
184 {.inUse = true, .bandCount = 0},
185 {.inUse = true, .bandCount = -1},
Ram Mohanafdf90b2023-03-23 08:48:25 +0530186 {.inUse = false, .bandCount = 0},
187 {.inUse = false, .bandCount = -1},
Ram Mohane4064ce2022-12-20 18:05:14 +0530188 {.inUse = false, .bandCount = DynamicsProcessingTestHelper::kBandCount}};
189
190// test value set for DynamicsProcessing::ChannelConfig
191const std::set<std::vector<DynamicsProcessing::ChannelConfig>>
192 DynamicsProcessingTestHelper::kChannelConfigTestSet = {
193 {{.channel = -1, .enable = false},
194 {.channel = 0, .enable = true},
195 {.channel = 1, .enable = false},
196 {.channel = 2, .enable = true}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530197 {{.channel = -1, .enable = false}, {.channel = 2, .enable = true}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530198 {{.channel = 0, .enable = true}, {.channel = 1, .enable = true}}};
199
200// test value set for DynamicsProcessing::InputGain
201const std::set<std::vector<DynamicsProcessing::InputGain>>
202 DynamicsProcessingTestHelper::kInputGainTestSet = {
203 {{.channel = 0, .gainDb = 10.f},
204 {.channel = 1, .gainDb = 0.f},
205 {.channel = 2, .gainDb = -10.f}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530206 {{.channel = -1, .gainDb = -10.f}, {.channel = -2, .gainDb = 10.f}},
Ram Mohanafdf90b2023-03-23 08:48:25 +0530207 {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}},
208 {{.channel = 0, .gainDb = 10.f}, {.channel = 1, .gainDb = -10.f}}};
Ram Mohane4064ce2022-12-20 18:05:14 +0530209
Ram Mohanafdf90b2023-03-23 08:48:25 +0530210template <typename T>
211bool DynamicsProcessingTestHelper::isBandConfigValid(const std::vector<T>& cfgs, int bandCount) {
Shunkai Yao53238b12024-03-29 23:09:04 +0000212 std::unordered_set<int> freqs;
Ram Mohanafdf90b2023-03-23 08:48:25 +0530213 for (auto cfg : cfgs) {
214 if (cfg.channel < 0 || cfg.channel >= mChannelCount) return false;
215 if (cfg.band < 0 || cfg.band >= bandCount) return false;
Shunkai Yao53238b12024-03-29 23:09:04 +0000216 // duplicated band index
217 if (freqs.find(cfg.band) != freqs.end()) return false;
218 freqs.insert(cfg.band);
Ram Mohanafdf90b2023-03-23 08:48:25 +0530219 }
Shunkai Yao53238b12024-03-29 23:09:04 +0000220 return true;
Ram Mohanafdf90b2023-03-23 08:48:25 +0530221}
222
223bool DynamicsProcessingTestHelper::isParamValid(const DynamicsProcessing::Tag& tag,
224 const DynamicsProcessing& dp) {
225 switch (tag) {
226 case DynamicsProcessing::preEq: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530227 return isChannelConfigValid(dp.get<DynamicsProcessing::preEq>());
228 }
229 case DynamicsProcessing::postEq: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530230 return isChannelConfigValid(dp.get<DynamicsProcessing::postEq>());
231 }
232 case DynamicsProcessing::mbc: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530233 return isChannelConfigValid(dp.get<DynamicsProcessing::mbc>());
234 }
235 case DynamicsProcessing::preEqBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530236 return isBandConfigValid(dp.get<DynamicsProcessing::preEqBand>(),
237 mEngineConfigApplied.preEqStage.bandCount);
238 }
239 case DynamicsProcessing::postEqBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530240 return isBandConfigValid(dp.get<DynamicsProcessing::postEqBand>(),
241 mEngineConfigApplied.postEqStage.bandCount);
242 }
243 case DynamicsProcessing::mbcBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530244 return isBandConfigValid(dp.get<DynamicsProcessing::mbcBand>(),
245 mEngineConfigApplied.mbcStage.bandCount);
246 }
247 case DynamicsProcessing::limiter: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530248 return isChannelConfigValid(dp.get<DynamicsProcessing::limiter>());
249 }
250 case DynamicsProcessing::inputGain: {
251 return isChannelConfigValid(dp.get<DynamicsProcessing::inputGain>());
252 }
253 default: {
254 return true;
255 }
256 }
257 return true;
258}
Ram Mohane4064ce2022-12-20 18:05:14 +0530259
Ram Mohane4064ce2022-12-20 18:05:14 +0530260bool DynamicsProcessingTestHelper::isParamEqual(const DynamicsProcessing::Tag& tag,
261 const DynamicsProcessing& dpRef,
262 const DynamicsProcessing& dpTest) {
263 switch (tag) {
264 case DynamicsProcessing::engineArchitecture: {
265 return isEngineConfigEqual(dpRef.get<DynamicsProcessing::engineArchitecture>(),
266 dpTest.get<DynamicsProcessing::engineArchitecture>());
267 }
268 case DynamicsProcessing::preEq: {
269 const auto& source = dpRef.get<DynamicsProcessing::preEq>();
270 const auto& target = dpTest.get<DynamicsProcessing::preEq>();
271 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(source, target);
272 }
273 case DynamicsProcessing::postEq: {
274 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
275 dpRef.get<DynamicsProcessing::postEq>(),
276 dpTest.get<DynamicsProcessing::postEq>());
277 }
278 case DynamicsProcessing::mbc: {
279 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
280 dpRef.get<DynamicsProcessing::mbc>(), dpTest.get<DynamicsProcessing::mbc>());
281 }
282 case DynamicsProcessing::preEqBand: {
283 return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
284 dpRef.get<DynamicsProcessing::preEqBand>(),
285 dpTest.get<DynamicsProcessing::preEqBand>());
286 }
287 case DynamicsProcessing::postEqBand: {
288 return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
289 dpRef.get<DynamicsProcessing::postEqBand>(),
290 dpTest.get<DynamicsProcessing::postEqBand>());
291 }
292 case DynamicsProcessing::mbcBand: {
293 return isAidlVectorEqualAfterFilter<DynamicsProcessing::MbcBandConfig>(
294 dpRef.get<DynamicsProcessing::mbcBand>(),
295 dpTest.get<DynamicsProcessing::mbcBand>());
296 }
297 case DynamicsProcessing::limiter: {
298 return isAidlVectorEqualAfterFilter<DynamicsProcessing::LimiterConfig>(
299 dpRef.get<DynamicsProcessing::limiter>(),
300 dpTest.get<DynamicsProcessing::limiter>());
301 }
302 case DynamicsProcessing::inputGain: {
303 return isAidlVectorEqual<DynamicsProcessing::InputGain>(
304 dpRef.get<DynamicsProcessing::inputGain>(),
305 dpTest.get<DynamicsProcessing::inputGain>());
306 }
Shunkai Yaob2325e52023-03-03 19:34:47 +0000307 case DynamicsProcessing::vendor: {
Ram Mohane4064ce2022-12-20 18:05:14 +0530308 return false;
309 }
310 }
311}
312
Ram Mohane4064ce2022-12-20 18:05:14 +0530313bool DynamicsProcessingTestHelper::isEngineConfigEqual(
314 const DynamicsProcessing::EngineArchitecture& ref,
315 const DynamicsProcessing::EngineArchitecture& test) {
316 return ref == test;
317}
318
319template <typename T>
320std::vector<T> DynamicsProcessingTestHelper::filterEnabledVector(const std::vector<T>& vec) {
321 std::vector<T> ret;
322 std::copy_if(vec.begin(), vec.end(), std::back_inserter(ret),
323 [](const auto& v) { return v.enable; });
324 return ret;
325}
326
327template <typename T>
328bool DynamicsProcessingTestHelper::isAidlVectorEqual(const std::vector<T>& source,
329 const std::vector<T>& target) {
330 if (source.size() != target.size()) return false;
331
332 auto tempS = source;
333 auto tempT = target;
334 std::sort(tempS.begin(), tempS.end());
335 std::sort(tempT.begin(), tempT.end());
336 return tempS == tempT;
337}
338
339template <typename T>
340bool DynamicsProcessingTestHelper::isAidlVectorEqualAfterFilter(const std::vector<T>& source,
341 const std::vector<T>& target) {
342 return isAidlVectorEqual<T>(filterEnabledVector<T>(source), filterEnabledVector<T>(target));
343}
344
345void DynamicsProcessingTestHelper::SetAndGetDynamicsProcessingParameters() {
Sneha Patilabc94642024-11-13 08:41:05 +0000346 for (const auto& [tag, dp] : mTags) {
Ram Mohane4064ce2022-12-20 18:05:14 +0530347 // validate parameter
348 Descriptor desc;
349 ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
Ram Mohanafdf90b2023-03-23 08:48:25 +0530350 bool valid = isParamInRange(dp, desc.capability.range.get<Range::dynamicsProcessing>());
351 if (valid) valid = isParamValid(tag, dp);
Ram Mohane4064ce2022-12-20 18:05:14 +0530352 const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
353
354 // set parameter
355 Parameter expectParam;
356 Parameter::Specific specific;
357 specific.set<Parameter::Specific::dynamicsProcessing>(dp);
358 expectParam.set<Parameter::specific>(specific);
Shunkai Yao0a0c45e2023-02-13 17:41:11 +0000359 ASSERT_STATUS(expected, mEffect->setParameter(expectParam))
360 << "\n"
361 << expectParam.toString() << "\n"
362 << desc.toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530363
364 // only get if parameter in range and set success
365 if (expected == EX_NONE) {
366 Parameter getParam;
367 Parameter::Id id;
368 DynamicsProcessing::Id dpId;
369 dpId.set<DynamicsProcessing::Id::commonTag>(tag);
370 id.set<Parameter::Id::dynamicsProcessingTag>(dpId);
371 // if set success, then get should match
372 EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
373 Parameter::Specific specificTest = getParam.get<Parameter::specific>();
374 const auto& target = specificTest.get<Parameter::Specific::dynamicsProcessing>();
375 EXPECT_TRUE(isParamEqual(tag, dp, target)) << dp.toString() << "\n"
376 << target.toString();
377 // update mEngineConfigApplied after setting successfully
378 if (tag == DynamicsProcessing::engineArchitecture) {
379 mEngineConfigApplied = target.get<DynamicsProcessing::engineArchitecture>();
380 }
381 }
382 }
383}
384
Sneha Patilabc94642024-11-13 08:41:05 +0000385bool DynamicsProcessingTestHelper::isAllParamsValid() {
386 if (mTags.empty()) {
387 return false;
388 }
389 for (const auto& [tag, dp] : mTags) {
390 // validate parameter
391 if (!isParamInRange(dp, mDescriptor.capability.range.get<Range::dynamicsProcessing>())) {
392 return false;
393 }
394 if (!isParamValid(tag, dp)) {
395 return false;
396 }
397 }
398 return true;
399}
400
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000401// This function calculates power for both and mono and stereo data as the total power for
402// interleaved multichannel data can be calculated by treating it as a continuous mono input.
Sneha Patilcbf86a42024-11-26 10:41:54 +0000403float DynamicsProcessingTestHelper::calculateDb(const std::vector<float>& input,
404 size_t startSamplePos = 0) {
405 return audio_utils_compute_power_mono(input.data() + startSamplePos, AUDIO_FORMAT_PCM_FLOAT,
406 input.size() - startSamplePos);
407}
408
409void DynamicsProcessingTestHelper::setParamsAndProcess(std::vector<float>& input,
410 std::vector<float>& output) {
411 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
412 if (isAllParamsValid()) {
413 ASSERT_NO_FATAL_FAILURE(
414 processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn));
415 ASSERT_GT(output.size(), kStartIndex);
416 }
417}
418
Ram Mohane4064ce2022-12-20 18:05:14 +0530419void DynamicsProcessingTestHelper::addEngineConfig(
420 const DynamicsProcessing::EngineArchitecture& cfg) {
421 DynamicsProcessing dp;
422 dp.set<DynamicsProcessing::engineArchitecture>(cfg);
423 mTags.push_back({DynamicsProcessing::engineArchitecture, dp});
424}
425
426void DynamicsProcessingTestHelper::addPreEqChannelConfig(
427 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
428 DynamicsProcessing dp;
429 dp.set<DynamicsProcessing::preEq>(cfgs);
430 mTags.push_back({DynamicsProcessing::preEq, dp});
431 for (auto& cfg : cfgs) {
432 if (cfg.enable) mPreEqChannelEnable.insert(cfg.channel);
433 }
434}
435
436void DynamicsProcessingTestHelper::addPostEqChannelConfig(
437 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
438 DynamicsProcessing dp;
439 dp.set<DynamicsProcessing::postEq>(cfgs);
440 mTags.push_back({DynamicsProcessing::postEq, dp});
441 for (auto& cfg : cfgs) {
442 if (cfg.enable) mPostEqChannelEnable.insert(cfg.channel);
443 }
444}
445
446void DynamicsProcessingTestHelper::addMbcChannelConfig(
447 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
448 DynamicsProcessing dp;
449 dp.set<DynamicsProcessing::mbc>(cfgs);
450 mTags.push_back({DynamicsProcessing::mbc, dp});
451 for (auto& cfg : cfgs) {
452 if (cfg.enable) mMbcChannelEnable.insert(cfg.channel);
453 }
454}
455
456void DynamicsProcessingTestHelper::addPreEqBandConfigs(
457 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
458 DynamicsProcessing dp;
459 dp.set<DynamicsProcessing::preEqBand>(cfgs);
460 mTags.push_back({DynamicsProcessing::preEqBand, dp});
461}
462
463void DynamicsProcessingTestHelper::addPostEqBandConfigs(
464 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
465 DynamicsProcessing dp;
466 dp.set<DynamicsProcessing::postEqBand>(cfgs);
467 mTags.push_back({DynamicsProcessing::postEqBand, dp});
468}
469
470void DynamicsProcessingTestHelper::addMbcBandConfigs(
471 const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
472 DynamicsProcessing dp;
473 dp.set<DynamicsProcessing::mbcBand>(cfgs);
474 mTags.push_back({DynamicsProcessing::mbcBand, dp});
475}
476
477void DynamicsProcessingTestHelper::addLimiterConfig(
478 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
479 DynamicsProcessing dp;
480 dp.set<DynamicsProcessing::limiter>(cfgs);
481 mTags.push_back({DynamicsProcessing::limiter, dp});
482 for (auto& cfg : cfgs) {
483 if (cfg.enable) mLimiterChannelEnable.insert(cfg.channel);
484 }
485}
486
487void DynamicsProcessingTestHelper::addInputGain(
488 const std::vector<DynamicsProcessing::InputGain>& inputGains) {
489 DynamicsProcessing dp;
490 dp.set<DynamicsProcessing::inputGain>(inputGains);
491 mTags.push_back({DynamicsProcessing::inputGain, dp});
492}
493
Sneha Patilabc94642024-11-13 08:41:05 +0000494void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& limiterConfigList,
495 int channelIndex, bool enable, int linkGroup, float attackTime,
496 float releaseTime, float ratio, float threshold, float postGain) {
497 DynamicsProcessing::LimiterConfig cfg;
498 cfg.channel = channelIndex;
499 cfg.enable = enable;
500 cfg.linkGroup = linkGroup;
501 cfg.attackTimeMs = attackTime;
502 cfg.releaseTimeMs = releaseTime;
503 cfg.ratio = ratio;
504 cfg.thresholdDb = threshold;
505 cfg.postGainDb = postGain;
506 limiterConfigList.push_back(cfg);
507}
508
Sneha Patilc3252762024-11-21 10:51:46 +0000509DynamicsProcessing::MbcBandConfig createMbcBandConfig(int channel, int band, float cutoffFreqHz,
510 float attackTimeMs, float releaseTimeMs,
511 float ratio, float thresholdDb,
512 float kneeWidthDb, float noiseGate,
513 float expanderRatio, float preGainDb,
514 float postGainDb) {
515 return DynamicsProcessing::MbcBandConfig{.channel = channel,
516 .band = band,
517 .enable = true,
518 .cutoffFrequencyHz = cutoffFreqHz,
519 .attackTimeMs = attackTimeMs,
520 .releaseTimeMs = releaseTimeMs,
521 .ratio = ratio,
522 .thresholdDb = thresholdDb,
523 .kneeWidthDb = kneeWidthDb,
524 .noiseGateThresholdDb = noiseGate,
525 .expanderRatio = expanderRatio,
526 .preGainDb = preGainDb,
527 .postGainDb = postGainDb};
528}
529
Ram Mohane4064ce2022-12-20 18:05:14 +0530530/**
531 * Test DynamicsProcessing Engine Configuration
532 */
533enum EngineArchitectureTestParamName {
534 ENGINE_TEST_INSTANCE_NAME,
535 ENGINE_TEST_RESOLUTION_PREFERENCE,
536 ENGINE_TEST_PREFERRED_DURATION,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000537 ENGINE_TEST_STAGE_ENABLEMENT
Ram Mohane4064ce2022-12-20 18:05:14 +0530538};
539using EngineArchitectureTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
540 DynamicsProcessing::ResolutionPreference, float,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000541 DynamicsProcessing::StageEnablement>;
Ram Mohane4064ce2022-12-20 18:05:14 +0530542
543void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg,
544 const EngineArchitectureTestParams& params) {
545 cfg.resolutionPreference = std::get<ENGINE_TEST_RESOLUTION_PREFERENCE>(params);
546 cfg.preferredProcessingDurationMs = std::get<ENGINE_TEST_PREFERRED_DURATION>(params);
547 cfg.preEqStage = cfg.postEqStage = cfg.mbcStage =
548 std::get<ENGINE_TEST_STAGE_ENABLEMENT>(params);
Shunkai Yaof137ba42024-04-11 17:11:03 +0000549 cfg.limiterInUse = true;
Ram Mohane4064ce2022-12-20 18:05:14 +0530550}
551
552class DynamicsProcessingTestEngineArchitecture
553 : public ::testing::TestWithParam<EngineArchitectureTestParams>,
554 public DynamicsProcessingTestHelper {
555 public:
556 DynamicsProcessingTestEngineArchitecture()
557 : DynamicsProcessingTestHelper(std::get<ENGINE_TEST_INSTANCE_NAME>(GetParam())) {
558 fillEngineArchConfig(mCfg, GetParam());
559 };
560
561 void SetUp() override { SetUpDynamicsProcessingEffect(); }
562
563 void TearDown() override { TearDownDynamicsProcessingEffect(); }
564
565 DynamicsProcessing::EngineArchitecture mCfg;
566};
567
568TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000569 addEngineConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +0000570 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530571}
572
573INSTANTIATE_TEST_SUITE_P(
574 DynamicsProcessingTest, DynamicsProcessingTestEngineArchitecture,
575 ::testing::Combine(
576 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000577 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohanafdf90b2023-03-23 08:48:25 +0530578 testing::Values(
579 DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
580 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
581 static_cast<DynamicsProcessing::ResolutionPreference>(-1)), // variant
582 testing::Values(-10.f, 0.f, 10.f), // processing duration
Ram Mohane4064ce2022-12-20 18:05:14 +0530583 testing::ValuesIn(
Shunkai Yaof137ba42024-04-11 17:11:03 +0000584 DynamicsProcessingTestHelper::kStageEnablementTestSet) // preEQ/postEQ/mbc
585 ),
Ram Mohane4064ce2022-12-20 18:05:14 +0530586 [](const auto& info) {
587 auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
588 DynamicsProcessing::EngineArchitecture cfg;
589 fillEngineArchConfig(cfg, info.param);
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530590 std::string name = getPrefix(descriptor) + "_Cfg_" + cfg.toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530591 std::replace_if(
592 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
593 return name;
594 });
595GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEngineArchitecture);
596
597/**
598 * Test DynamicsProcessing Input Gain
599 */
600enum InputGainTestParamName {
601 INPUT_GAIN_INSTANCE_NAME,
602 INPUT_GAIN_PARAM,
603};
604class DynamicsProcessingTestInputGain
605 : public ::testing::TestWithParam<std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
606 std::vector<DynamicsProcessing::InputGain>>>,
607 public DynamicsProcessingTestHelper {
608 public:
609 DynamicsProcessingTestInputGain()
610 : DynamicsProcessingTestHelper(std::get<INPUT_GAIN_INSTANCE_NAME>(GetParam())),
Sneha Patilabc94642024-11-13 08:41:05 +0000611 mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())) {};
Ram Mohane4064ce2022-12-20 18:05:14 +0530612
613 void SetUp() override { SetUpDynamicsProcessingEffect(); }
614
615 void TearDown() override { TearDownDynamicsProcessingEffect(); }
616
617 const std::vector<DynamicsProcessing::InputGain> mInputGain;
618};
619
620TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000621 addInputGain(mInputGain);
Sneha Patilabc94642024-11-13 08:41:05 +0000622 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530623}
624
625INSTANTIATE_TEST_SUITE_P(
626 DynamicsProcessingTest, DynamicsProcessingTestInputGain,
627 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000628 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohane4064ce2022-12-20 18:05:14 +0530629 testing::ValuesIn(DynamicsProcessingTestInputGain::kInputGainTestSet)),
630 [](const auto& info) {
631 auto descriptor = std::get<INPUT_GAIN_INSTANCE_NAME>(info.param).second;
632 std::string gains =
633 ::android::internal::ToString(std::get<INPUT_GAIN_PARAM>(info.param));
634 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
635 descriptor.common.name + "_UUID_" +
Shunkai Yao6f822452024-03-29 18:45:30 +0000636 toString(descriptor.common.id.uuid) + "_inputGains_" + gains;
Ram Mohane4064ce2022-12-20 18:05:14 +0530637 std::replace_if(
638 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
639 return name;
640 });
641GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestInputGain);
642
Sneha Patilcbf86a42024-11-26 10:41:54 +0000643class DynamicsProcessingInputGainDataTest
644 : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
645 public DynamicsProcessingTestHelper {
646 public:
647 DynamicsProcessingInputGainDataTest()
648 : DynamicsProcessingTestHelper((GetParam()), AudioChannelLayout::LAYOUT_MONO) {
649 mInput.resize(kFrameCount * mChannelCount);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000650 }
651
652 void SetUp() override {
653 SetUpDynamicsProcessingEffect();
654 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000655 ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency /*Input Frequency*/, mInput, 1.0,
656 kSamplingFrequency, mChannelLayout));
657 mInputDb = calculateDb(mInput);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000658 }
659
660 void TearDown() override { TearDownDynamicsProcessingEffect(); }
661
662 void cleanUpInputGainConfig() {
663 CleanUp();
664 mInputGain.clear();
665 }
666
667 std::vector<DynamicsProcessing::InputGain> mInputGain;
668 std::vector<float> mInput;
669 float mInputDb;
670};
671
672TEST_P(DynamicsProcessingInputGainDataTest, SetAndGetInputGain) {
673 std::vector<float> gainDbValues = {-85, -40, 0, 40, 85};
674 for (float gainDb : gainDbValues) {
675 cleanUpInputGainConfig();
676 for (int i = 0; i < mChannelCount; i++) {
677 mInputGain.push_back(DynamicsProcessing::InputGain(i, gainDb));
678 }
679 std::vector<float> output(mInput.size());
Sneha Patil3587ae52025-01-06 05:59:08 +0000680 addInputGain(mInputGain);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000681 EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
682 if (!isAllParamsValid()) {
683 continue;
684 }
685 float outputDb = calculateDb(output, kStartIndex);
686 EXPECT_NEAR(outputDb, mInputDb + gainDb, kToleranceDb)
687 << "InputGain: " << gainDb << ", OutputDb: " << outputDb;
688 }
689}
690
691INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingInputGainDataTest,
692 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
693 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
694 [](const auto& info) {
695 auto descriptor = info.param;
696 std::string name = getPrefix(descriptor.second);
697 std::replace_if(
698 name.begin(), name.end(),
699 [](const char c) { return !std::isalnum(c); }, '_');
700 return name;
701 });
702GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingInputGainDataTest);
703
Ram Mohane4064ce2022-12-20 18:05:14 +0530704/**
705 * Test DynamicsProcessing Limiter Config
706 */
707enum LimiterConfigTestParamName {
708 LIMITER_INSTANCE_NAME,
709 LIMITER_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +0530710 LIMITER_LINK_GROUP,
Ram Mohane4064ce2022-12-20 18:05:14 +0530711 LIMITER_ATTACK_TIME,
712 LIMITER_RELEASE_TIME,
713 LIMITER_RATIO,
714 LIMITER_THRESHOLD,
715 LIMITER_POST_GAIN,
Ram Mohane4064ce2022-12-20 18:05:14 +0530716};
Ram Mohane4064ce2022-12-20 18:05:14 +0530717
Shunkai Yaof137ba42024-04-11 17:11:03 +0000718using LimiterConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
Sneha Patilabc94642024-11-13 08:41:05 +0000719 int32_t, int32_t, float, float, float, float, float>;
Ram Mohane4064ce2022-12-20 18:05:14 +0530720
Sneha Patilabc94642024-11-13 08:41:05 +0000721void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& cfg,
Ram Mohane4064ce2022-12-20 18:05:14 +0530722 const LimiterConfigTestParams& params) {
Sneha Patilabc94642024-11-13 08:41:05 +0000723 fillLimiterConfig(cfg, std::get<LIMITER_CHANNEL>(params), true,
724 std::get<LIMITER_LINK_GROUP>(params), std::get<LIMITER_ATTACK_TIME>(params),
725 std::get<LIMITER_RELEASE_TIME>(params), std::get<LIMITER_RATIO>(params),
726 std::get<LIMITER_THRESHOLD>(params), std::get<LIMITER_POST_GAIN>(params));
Ram Mohane4064ce2022-12-20 18:05:14 +0530727}
728
729class DynamicsProcessingTestLimiterConfig
730 : public ::testing::TestWithParam<LimiterConfigTestParams>,
731 public DynamicsProcessingTestHelper {
732 public:
733 DynamicsProcessingTestLimiterConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +0000734 : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())) {
Sneha Patilabc94642024-11-13 08:41:05 +0000735 fillLimiterConfig(mLimiterConfigList, GetParam());
Ram Mohane4064ce2022-12-20 18:05:14 +0530736 }
737
738 void SetUp() override { SetUpDynamicsProcessingEffect(); }
739
740 void TearDown() override { TearDownDynamicsProcessingEffect(); }
741
742 DynamicsProcessing::LimiterConfig mCfg;
Sneha Patilabc94642024-11-13 08:41:05 +0000743 std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
Ram Mohane4064ce2022-12-20 18:05:14 +0530744};
745
746TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000747 addEngineConfig(mEngineConfigPreset);
748 addLimiterConfig(mLimiterConfigList);
Sneha Patilabc94642024-11-13 08:41:05 +0000749 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530750}
751
752INSTANTIATE_TEST_SUITE_P(
753 DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
754 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000755 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +0000756 testing::Values(-1, 0, 1, 2), // channel index
757 testing::Values(3), // link group
758 testing::Values(-1, 1), // attackTime
759 testing::Values(-60, 60), // releaseTime
760 testing::Values(-2.5, 2.5), // ratio
761 testing::Values(-2, 2), // thresh
762 testing::Values(-3.14, 3.14) // postGain
763 ),
Ram Mohane4064ce2022-12-20 18:05:14 +0530764 [](const auto& info) {
765 auto descriptor = std::get<LIMITER_INSTANCE_NAME>(info.param).second;
Sneha Patilabc94642024-11-13 08:41:05 +0000766 std::vector<DynamicsProcessing::LimiterConfig> cfg;
Ram Mohane4064ce2022-12-20 18:05:14 +0530767 fillLimiterConfig(cfg, info.param);
Sneha Patilabc94642024-11-13 08:41:05 +0000768 std::string name =
769 "Implementer_" + getPrefix(descriptor) + "_limiterConfig_" + cfg[0].toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530770 std::replace_if(
771 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
772 return name;
773 });
774GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfig);
775
Sneha Patilabc94642024-11-13 08:41:05 +0000776using LimiterConfigDataTestParams = std::pair<std::shared_ptr<IFactory>, Descriptor>;
777
778class DynamicsProcessingLimiterConfigDataTest
779 : public ::testing::TestWithParam<LimiterConfigDataTestParams>,
780 public DynamicsProcessingTestHelper {
781 public:
782 DynamicsProcessingLimiterConfigDataTest()
783 : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
784 mBufferSize = kFrameCount * mChannelCount;
785 mInput.resize(mBufferSize);
Sneha Patilabc94642024-11-13 08:41:05 +0000786 }
787
788 void SetUp() override {
789 SetUpDynamicsProcessingEffect();
790 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
Sneha Patil903c6202025-01-30 06:37:10 +0000791 ASSERT_NO_FATAL_FAILURE(
792 generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000793 mInputDb = calculateDb(mInput);
Sneha Patil903c6202025-01-30 06:37:10 +0000794 ASSERT_NEAR(mInputDb, kSineFullScaleDb, kToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000795 }
796
797 void TearDown() override { TearDownDynamicsProcessingEffect(); }
798
Sneha Patilabc94642024-11-13 08:41:05 +0000799 void computeThreshold(float ratio, float outputDb, float& threshold) {
800 EXPECT_NE(ratio, 0);
801 threshold = (mInputDb - (ratio * outputDb)) / (1 - ratio);
802 }
803
804 void computeRatio(float threshold, float outputDb, float& ratio) {
805 float inputOverThreshold = mInputDb - threshold;
806 float outputOverThreshold = outputDb - threshold;
807 EXPECT_NE(outputOverThreshold, 0);
808 ratio = inputOverThreshold / outputOverThreshold;
809 }
810
Sneha Patilcbf86a42024-11-26 10:41:54 +0000811 void setLimiterParamsAndProcess(std::vector<float>& input, std::vector<float>& output) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000812 addEngineConfig(mEngineConfigPreset);
813 addLimiterConfig(mLimiterConfigList);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000814 EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(input, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000815 }
816
817 void cleanUpLimiterConfig() {
818 CleanUp();
819 mLimiterConfigList.clear();
820 }
821 static constexpr float kDefaultLinkerGroup = 3;
822 static constexpr float kDefaultAttackTime = 0;
823 static constexpr float kDefaultReleaseTime = 0;
824 static constexpr float kDefaultRatio = 4;
Sneha Patilcbf86a42024-11-26 10:41:54 +0000825 static constexpr float kDefaultThreshold = -10;
Sneha Patilabc94642024-11-13 08:41:05 +0000826 static constexpr float kDefaultPostGain = 0;
Sneha Patil903c6202025-01-30 06:37:10 +0000827 static constexpr float kInputFrequency = 1000;
828 // Full scale sine wave with 1000 Hz frequency is -3 dB
829 static constexpr float kSineFullScaleDb = -3;
Sneha Patilabc94642024-11-13 08:41:05 +0000830 std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
831 std::vector<float> mInput;
832 float mInputDb;
833 int mBufferSize;
834};
835
836TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingThresholdDb) {
837 std::vector<float> thresholdValues = {-200, -150, -100, -50, -5, 0};
838 std::vector<float> output(mInput.size());
839 float previousThreshold = -FLT_MAX;
840 for (float threshold : thresholdValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000841 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000842 for (int i = 0; i < mChannelCount; i++) {
843 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
844 kDefaultReleaseTime, kDefaultRatio, threshold, kDefaultPostGain);
845 }
Sneha Patilc3252762024-11-21 10:51:46 +0000846 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000847 if (!isAllParamsValid()) {
848 continue;
849 }
850 float outputDb = calculateDb(output, kStartIndex);
851 if (threshold >= mInputDb || kDefaultRatio == 1) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000852 EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000853 } else {
854 float calculatedThreshold = 0;
Sneha Patilc3252762024-11-21 10:51:46 +0000855 ASSERT_NO_FATAL_FAILURE(computeThreshold(kDefaultRatio, outputDb, calculatedThreshold));
Sneha Patilabc94642024-11-13 08:41:05 +0000856 ASSERT_GT(calculatedThreshold, previousThreshold);
857 previousThreshold = calculatedThreshold;
858 }
859 }
860}
861
862TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingRatio) {
863 std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
864 std::vector<float> output(mInput.size());
Sneha Patilabc94642024-11-13 08:41:05 +0000865 float previousRatio = 0;
866 for (float ratio : ratioValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000867 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000868 for (int i = 0; i < mChannelCount; i++) {
869 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
Sneha Patilcbf86a42024-11-26 10:41:54 +0000870 kDefaultReleaseTime, ratio, kDefaultThreshold, kDefaultPostGain);
Sneha Patilabc94642024-11-13 08:41:05 +0000871 }
Sneha Patilc3252762024-11-21 10:51:46 +0000872 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000873 if (!isAllParamsValid()) {
874 continue;
875 }
876 float outputDb = calculateDb(output, kStartIndex);
877
Sneha Patilcbf86a42024-11-26 10:41:54 +0000878 if (kDefaultThreshold >= mInputDb) {
879 EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000880 } else {
881 float calculatedRatio = 0;
Sneha Patilc3252762024-11-21 10:51:46 +0000882 ASSERT_NO_FATAL_FAILURE(computeRatio(kDefaultThreshold, outputDb, calculatedRatio));
Sneha Patilabc94642024-11-13 08:41:05 +0000883 ASSERT_GT(calculatedRatio, previousRatio);
884 previousRatio = calculatedRatio;
885 }
886 }
887}
888
Sneha Patilcbf86a42024-11-26 10:41:54 +0000889TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingPostGain) {
890 std::vector<float> postGainDbValues = {-85, -40, 0, 40, 85};
891 std::vector<float> output(mInput.size());
892 for (float postGainDb : postGainDbValues) {
893 cleanUpLimiterConfig();
Sneha Patil903c6202025-01-30 06:37:10 +0000894 ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, dBToAmplitude(postGainDb),
895 kSamplingFrequency, mChannelLayout));
896 mInputDb = calculateDb(mInput);
897 EXPECT_NEAR(mInputDb, kSineFullScaleDb - postGainDb, kToleranceDb);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000898 for (int i = 0; i < mChannelCount; i++) {
899 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
Sneha Patil903c6202025-01-30 06:37:10 +0000900 kDefaultReleaseTime, 1, kDefaultThreshold, postGainDb);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000901 }
Sneha Patilc3252762024-11-21 10:51:46 +0000902 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilcbf86a42024-11-26 10:41:54 +0000903 if (!isAllParamsValid()) {
904 continue;
905 }
906 float outputDb = calculateDb(output, kStartIndex);
907 EXPECT_NEAR(outputDb, mInputDb + postGainDb, kToleranceDb)
908 << "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
909 }
910}
911
Sneha Patilabc94642024-11-13 08:41:05 +0000912TEST_P(DynamicsProcessingLimiterConfigDataTest, LimiterEnableDisable) {
913 std::vector<bool> limiterEnableValues = {false, true};
914 std::vector<float> output(mInput.size());
915 for (bool isEnabled : limiterEnableValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000916 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000917 for (int i = 0; i < mChannelCount; i++) {
918 // Set non-default values
919 fillLimiterConfig(mLimiterConfigList, i, isEnabled, kDefaultLinkerGroup,
920 5 /*attack time*/, 5 /*release time*/, 10 /*ratio*/,
921 -10 /*threshold*/, 5 /*postgain*/);
922 }
Sneha Patilc3252762024-11-21 10:51:46 +0000923 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000924 if (!isAllParamsValid()) {
925 continue;
926 }
927 if (isEnabled) {
928 EXPECT_NE(mInputDb, calculateDb(output, kStartIndex));
929 } else {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000930 EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), kToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000931 }
932 }
933}
934
935INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingLimiterConfigDataTest,
936 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
937 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
938 [](const auto& info) {
939 auto descriptor = info.param;
940 std::string name = getPrefix(descriptor.second);
941 std::replace_if(
942 name.begin(), name.end(),
943 [](const char c) { return !std::isalnum(c); }, '_');
944 return name;
945 });
Sneha Patild341d6f2024-11-28 06:27:19 +0000946GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingLimiterConfigDataTest);
Sneha Patilabc94642024-11-13 08:41:05 +0000947
Ram Mohane4064ce2022-12-20 18:05:14 +0530948/**
949 * Test DynamicsProcessing ChannelConfig
950 */
951enum ChannelConfigTestParamName {
952 BAND_CHANNEL_TEST_INSTANCE_NAME,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000953 BAND_CHANNEL_TEST_CHANNEL_CONFIG
Ram Mohane4064ce2022-12-20 18:05:14 +0530954};
955using ChannelConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000956 std::vector<DynamicsProcessing::ChannelConfig>>;
Ram Mohane4064ce2022-12-20 18:05:14 +0530957
958class DynamicsProcessingTestChannelConfig
959 : public ::testing::TestWithParam<ChannelConfigTestParams>,
960 public DynamicsProcessingTestHelper {
961 public:
962 DynamicsProcessingTestChannelConfig()
963 : DynamicsProcessingTestHelper(std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(GetParam())),
Shunkai Yaof137ba42024-04-11 17:11:03 +0000964 mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())) {}
Ram Mohane4064ce2022-12-20 18:05:14 +0530965
966 void SetUp() override { SetUpDynamicsProcessingEffect(); }
967
968 void TearDown() override { TearDownDynamicsProcessingEffect(); }
969
970 std::vector<DynamicsProcessing::ChannelConfig> mCfg;
Ram Mohane4064ce2022-12-20 18:05:14 +0530971};
972
973TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000974 addEngineConfig(mEngineConfigPreset);
975 addPreEqChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +0000976 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530977}
978
979TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000980 addEngineConfig(mEngineConfigPreset);
981 addPostEqChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +0000982 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530983}
984
985TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000986 addEngineConfig(mEngineConfigPreset);
987 addMbcChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +0000988 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530989}
990
991INSTANTIATE_TEST_SUITE_P(
992 DynamicsProcessingTest, DynamicsProcessingTestChannelConfig,
993 ::testing::Combine(
994 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000995 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohane4064ce2022-12-20 18:05:14 +0530996 testing::ValuesIn(
Shunkai Yaof137ba42024-04-11 17:11:03 +0000997 DynamicsProcessingTestHelper::kChannelConfigTestSet)), // channel config
Ram Mohane4064ce2022-12-20 18:05:14 +0530998 [](const auto& info) {
999 auto descriptor = std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(info.param).second;
Ram Mohane4064ce2022-12-20 18:05:14 +05301000 std::string channelConfig = ::android::internal::ToString(
1001 std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(info.param));
1002
1003 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1004 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001005 toString(descriptor.common.id.uuid) + "_" + channelConfig;
Ram Mohane4064ce2022-12-20 18:05:14 +05301006 std::replace_if(
1007 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1008 return name;
1009 });
1010GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestChannelConfig);
1011
1012/**
1013 * Test DynamicsProcessing EqBandConfig
1014 */
1015enum EqBandConfigTestParamName {
1016 EQ_BAND_INSTANCE_NAME,
1017 EQ_BAND_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +05301018 EQ_BAND_CUT_OFF_FREQ,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001019 EQ_BAND_GAIN
Ram Mohane4064ce2022-12-20 18:05:14 +05301020};
1021using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
Sneha Patilabc94642024-11-13 08:41:05 +00001022 std::vector<std::pair<int, float>>, float>;
Ram Mohane4064ce2022-12-20 18:05:14 +05301023
1024void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
1025 const EqBandConfigTestParams& params) {
1026 const std::vector<std::pair<int, float>> cutOffFreqs = std::get<EQ_BAND_CUT_OFF_FREQ>(params);
1027 int bandCount = cutOffFreqs.size();
1028 cfgs.resize(bandCount);
1029 for (int i = 0; i < bandCount; i++) {
1030 cfgs[i].channel = std::get<EQ_BAND_CHANNEL>(params);
1031 cfgs[i].band = cutOffFreqs[i].first;
Sneha Patilabc94642024-11-13 08:41:05 +00001032 cfgs[i].enable = true /*Eqband Enable*/;
Ram Mohane4064ce2022-12-20 18:05:14 +05301033 cfgs[i].cutoffFrequencyHz = cutOffFreqs[i].second;
1034 cfgs[i].gainDb = std::get<EQ_BAND_GAIN>(params);
1035 }
1036}
1037
1038class DynamicsProcessingTestEqBandConfig : public ::testing::TestWithParam<EqBandConfigTestParams>,
1039 public DynamicsProcessingTestHelper {
1040 public:
1041 DynamicsProcessingTestEqBandConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +00001042 : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301043 fillEqBandConfig(mCfgs, GetParam());
1044 }
1045
1046 void SetUp() override { SetUpDynamicsProcessingEffect(); }
1047
1048 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1049
1050 std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
Ram Mohane4064ce2022-12-20 18:05:14 +05301051};
1052
1053TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301054 mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001055 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301056 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1057 for (int i = 0; i < mChannelCount; i++) {
1058 cfgs[i].channel = i;
1059 cfgs[i].enable = true;
1060 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001061 addPreEqChannelConfig(cfgs);
1062 addPreEqBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001063 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301064}
1065
1066TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301067 mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001068 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301069 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1070 for (int i = 0; i < mChannelCount; i++) {
1071 cfgs[i].channel = i;
1072 cfgs[i].enable = true;
1073 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001074 addPostEqChannelConfig(cfgs);
1075 addPostEqBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001076 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301077}
1078
1079std::vector<std::vector<std::pair<int, float>>> kBands{
1080 {
1081 {0, 600},
1082 {1, 2000},
1083 {2, 6000},
1084 {3, 10000},
1085 {4, 16000},
Sneha Patil0ecc1782025-02-17 11:21:32 +00001086 {5, 20000},
1087 {6, 26000},
1088 {7, 30000},
1089 {8, 36000},
1090 {9, 40000},
1091 }, // 10 bands
Ram Mohane4064ce2022-12-20 18:05:14 +05301092 {
1093 {0, 800},
1094 {3, 15000},
1095 {2, 6000},
1096 {1, 2000},
1097 }, // 4 bands, unsorted
1098 {
1099 {0, 650},
1100 {1, 2000},
1101 {2, 6000},
1102 {3, 10000},
1103 {3, 16000},
1104 }, // 5 bands, missing band
1105 {
1106 {0, 900},
1107 {1, 8000},
1108 {2, 4000},
1109 {3, 12000},
1110 }, // 4 bands, cutoff freq not increasing
1111 {
1112 {0, 450},
1113 {1, 2000},
1114 {7, 6000},
1115 {3, 10000},
1116 {4, 16000},
1117 }, // bad band index
1118 {
1119 {0, 1},
1120 {1, 8000},
1121 }, // too low cutoff freq
1122 {
1123 {0, 1200},
1124 {1, 80000},
1125 }, // too high cutoff freq
1126};
1127
1128INSTANTIATE_TEST_SUITE_P(
1129 DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
Ram Mohanafdf90b2023-03-23 08:48:25 +05301130 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1131 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +00001132 testing::Values(-1, 0, 10), // channel index
1133 testing::ValuesIn(kBands), // band index, cut off frequencies
Shunkai Yaof137ba42024-04-11 17:11:03 +00001134 testing::Values(-3.14f, 3.14f) // gain
1135 ),
Ram Mohane4064ce2022-12-20 18:05:14 +05301136 [](const auto& info) {
1137 auto descriptor = std::get<EQ_BAND_INSTANCE_NAME>(info.param).second;
1138 std::vector<DynamicsProcessing::EqBandConfig> cfgs;
1139 fillEqBandConfig(cfgs, info.param);
Ram Mohane4064ce2022-12-20 18:05:14 +05301140 std::string bands = ::android::internal::ToString(cfgs);
Ram Mohane4064ce2022-12-20 18:05:14 +05301141 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1142 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001143 toString(descriptor.common.id.uuid) + "_bands_" + bands;
Ram Mohane4064ce2022-12-20 18:05:14 +05301144 std::replace_if(
1145 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1146 return name;
1147 });
1148GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEqBandConfig);
1149
1150/**
1151 * Test DynamicsProcessing MbcBandConfig
1152 */
1153
1154enum MbcBandConfigParamName {
1155 MBC_BAND_INSTANCE_NAME,
1156 MBC_BAND_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +05301157 MBC_BAND_CUTOFF_FREQ,
Ram Mohane4064ce2022-12-20 18:05:14 +05301158 MBC_BAND_ADDITIONAL
1159};
1160enum MbcBandConfigAdditional {
1161 MBC_ADD_ATTACK_TIME,
1162 MBC_ADD_RELEASE_TIME,
1163 MBC_ADD_RATIO,
1164 MBC_ADD_THRESHOLD,
1165 MBC_ADD_KNEE_WIDTH,
1166 MBC_ADD_NOISE_GATE_THRESHOLD,
1167 MBC_ADD_EXPENDER_RATIO,
1168 MBC_ADD_PRE_GAIN,
1169 MBC_ADD_POST_GAIN,
1170 MBC_ADD_MAX_NUM
1171};
1172using TestParamsMbcBandConfigAdditional = std::array<float, MBC_ADD_MAX_NUM>;
1173
Ram Mohanafdf90b2023-03-23 08:48:25 +05301174// attackTime, releaseTime, ratio, thresh, kneeWidth, noise, expander, preGain, postGain
Ram Mohane4064ce2022-12-20 18:05:14 +05301175static constexpr std::array<TestParamsMbcBandConfigAdditional, 4> kMbcBandConfigAdditionalParam = {
1176 {{-3, -10, -2, -2, -5, -90, -2.5, -2, -2},
1177 {0, 0, 0, 0, 0, 0, 0, 0, 0},
1178 {-3, 10, -2, 2, -5, 90, -2.5, 2, -2},
Ram Mohanafdf90b2023-03-23 08:48:25 +05301179 {3, 10, 2, -2, -5, 90, 2.5, 2, 2}}};
Ram Mohane4064ce2022-12-20 18:05:14 +05301180
1181using TestParamsMbcBandConfig =
Sneha Patilabc94642024-11-13 08:41:05 +00001182 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001183 std::vector<std::pair<int, float>>, TestParamsMbcBandConfigAdditional>;
Ram Mohane4064ce2022-12-20 18:05:14 +05301184
1185void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
1186 const TestParamsMbcBandConfig& params) {
Sneha Patilc3252762024-11-21 10:51:46 +00001187 const auto& cutOffFreqs = std::get<MBC_BAND_CUTOFF_FREQ>(params);
1188 const auto& additional = std::get<MBC_BAND_ADDITIONAL>(params);
1189
1190 cfgs.resize(cutOffFreqs.size());
1191
1192 for (size_t i = 0; i < cutOffFreqs.size(); ++i) {
1193 cfgs[i] = createMbcBandConfig(std::get<MBC_BAND_CHANNEL>(params),
1194 cutOffFreqs[i].first, // band channel
1195 cutOffFreqs[i].second, // band cutoff frequency
1196 additional[MBC_ADD_ATTACK_TIME],
1197 additional[MBC_ADD_RELEASE_TIME], additional[MBC_ADD_RATIO],
1198 additional[MBC_ADD_THRESHOLD], additional[MBC_ADD_KNEE_WIDTH],
1199 additional[MBC_ADD_NOISE_GATE_THRESHOLD],
1200 additional[MBC_ADD_EXPENDER_RATIO],
1201 additional[MBC_ADD_PRE_GAIN], additional[MBC_ADD_POST_GAIN]);
Ram Mohane4064ce2022-12-20 18:05:14 +05301202 }
1203}
1204
1205class DynamicsProcessingTestMbcBandConfig
1206 : public ::testing::TestWithParam<TestParamsMbcBandConfig>,
1207 public DynamicsProcessingTestHelper {
1208 public:
1209 DynamicsProcessingTestMbcBandConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +00001210 : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301211 fillMbcBandConfig(mCfgs, GetParam());
1212 }
1213
1214 void SetUp() override { SetUpDynamicsProcessingEffect(); }
1215
1216 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1217
1218 std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
Ram Mohane4064ce2022-12-20 18:05:14 +05301219};
1220
1221TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301222 mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001223 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301224 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1225 for (int i = 0; i < mChannelCount; i++) {
1226 cfgs[i].channel = i;
1227 cfgs[i].enable = true;
1228 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001229 addMbcChannelConfig(cfgs);
1230 addMbcBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001231 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301232}
1233
1234INSTANTIATE_TEST_SUITE_P(
1235 DynamicsProcessingTest, DynamicsProcessingTestMbcBandConfig,
Ram Mohanafdf90b2023-03-23 08:48:25 +05301236 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1237 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +00001238 testing::Values(-1, 0, 10), // channel index
1239 testing::ValuesIn(kBands), // band index, cut off frequencies
Ram Mohanafdf90b2023-03-23 08:48:25 +05301240 testing::ValuesIn(kMbcBandConfigAdditionalParam)), // Additional
Ram Mohane4064ce2022-12-20 18:05:14 +05301241 [](const auto& info) {
1242 auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
1243 std::vector<DynamicsProcessing::MbcBandConfig> cfgs;
1244 fillMbcBandConfig(cfgs, info.param);
Ram Mohane4064ce2022-12-20 18:05:14 +05301245 std::string mbcBands = ::android::internal::ToString(cfgs);
Ram Mohane4064ce2022-12-20 18:05:14 +05301246 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1247 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001248 toString(descriptor.common.id.uuid) + "_bands_" + mbcBands;
Ram Mohane4064ce2022-12-20 18:05:14 +05301249 std::replace_if(
1250 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1251 return name;
1252 });
1253GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestMbcBandConfig);
1254
Sneha Patilc3252762024-11-21 10:51:46 +00001255class DynamicsProcessingMbcBandConfigDataTest
1256 : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
1257 public DynamicsProcessingTestHelper {
1258 public:
1259 DynamicsProcessingMbcBandConfigDataTest()
1260 : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
1261 mInput.resize(kFrameCount * mChannelCount);
1262 mBinOffsets.resize(mTestFrequencies.size());
1263 }
1264
1265 void SetUp() override {
1266 SetUpDynamicsProcessingEffect();
1267 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
1268 ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput, 1.0, kSamplingFrequency,
1269 mChannelLayout));
Sneha Patil7ba121b2025-01-22 09:19:39 +00001270 mInputDb = calculateDb(mInput);
Sneha Patil903c6202025-01-30 06:37:10 +00001271 ASSERT_NEAR(mInputDb, kFullScaleDb, kToleranceDb);
Sneha Patilc3252762024-11-21 10:51:46 +00001272 }
1273
1274 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1275
1276 void setMbcParamsAndProcess(std::vector<float>& output) {
1277 for (int i = 0; i < mChannelCount; i++) {
1278 mChannelConfig.push_back(DynamicsProcessing::ChannelConfig(i, true));
1279 }
1280 mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
1281 addEngineConfig(mEngineConfigPreset);
1282 addMbcChannelConfig(mChannelConfig);
1283 addMbcBandConfigs(mCfgs);
Sneha Patil903c6202025-01-30 06:37:10 +00001284 ASSERT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
Sneha Patilc3252762024-11-21 10:51:46 +00001285 }
1286
1287 void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs, int channelIndex,
1288 float threshold, float ratio, float noiseGate, float expanderRatio,
Sneha Patil7ba121b2025-01-22 09:19:39 +00001289 int bandIndex, int cutoffFreqHz, float preGain, float postGain) {
1290 cfgs.push_back(createMbcBandConfig(channelIndex, bandIndex,
1291 static_cast<float>(cutoffFreqHz), kDefaultAttackTime,
1292 kDefaultReleaseTime, ratio, threshold, kDefaultKneeWidth,
1293 noiseGate, expanderRatio, preGain, postGain));
Sneha Patilc3252762024-11-21 10:51:46 +00001294 }
1295
1296 void getMagnitudeValue(const std::vector<float>& output, std::vector<float>& bufferMag) {
1297 std::vector<float> subOutput(output.begin() + kStartIndex, output.end());
1298 EXPECT_NO_FATAL_FAILURE(
1299 calculateMagnitudeMono(bufferMag, subOutput, mBinOffsets, kNPointFFT));
1300 }
1301
1302 void validateOutput(const std::vector<float>& output, float threshold, float ratio,
1303 size_t bandIndex) {
Sneha Patilc3252762024-11-21 10:51:46 +00001304 std::vector<float> outputMag(mBinOffsets.size());
1305 EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
Sneha Patil7ba121b2025-01-22 09:19:39 +00001306 if (threshold >= mInputDb || ratio == 1) {
Sneha Patilc3252762024-11-21 10:51:46 +00001307 std::vector<float> inputMag(mBinOffsets.size());
1308 EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(mInput, inputMag));
1309 for (size_t i = 0; i < inputMag.size(); i++) {
1310 EXPECT_NEAR(calculateDb({inputMag[i] / mNormalizingFactor}),
1311 calculateDb({outputMag[i] / mNormalizingFactor}), kToleranceDb);
1312 }
1313 } else {
1314 // Current band's magnitude is less than the other band's magnitude
1315 EXPECT_LT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
1316 }
1317 }
1318
1319 void analyseMultiBandOutput(float threshold, float ratio) {
1320 std::vector<float> output(mInput.size());
1321 roundToFreqCenteredToFftBin(mTestFrequencies, mBinOffsets, kBinWidth);
1322 std::vector<int> cutoffFreqHz = {200 /*0th band cutoff*/, 2000 /*1st band cutoff*/};
1323 // Set MBC values for two bands
1324 for (size_t i = 0; i < cutoffFreqHz.size(); i++) {
1325 for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
1326 fillMbcBandConfig(mCfgs, channelIndex, threshold, ratio, kDefaultNoiseGateDb,
Sneha Patil7ba121b2025-01-22 09:19:39 +00001327 kDefaultExpanderRatio, i, cutoffFreqHz[i], kDefaultPreGainDb,
1328 kDefaultPostGainDb);
Sneha Patilc3252762024-11-21 10:51:46 +00001329 fillMbcBandConfig(mCfgs, channelIndex, kDefaultThresholdDb, kDefaultRatio,
1330 kDefaultNoiseGateDb, kDefaultExpanderRatio, i ^ 1,
Sneha Patil7ba121b2025-01-22 09:19:39 +00001331 cutoffFreqHz[i ^ 1], kDefaultPreGainDb, kDefaultPostGainDb);
Sneha Patilc3252762024-11-21 10:51:46 +00001332 }
1333 ASSERT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
1334
1335 if (isAllParamsValid()) {
1336 ASSERT_NO_FATAL_FAILURE(validateOutput(output, threshold, ratio, i));
1337 }
1338 cleanUpMbcConfig();
1339 }
1340 }
1341
1342 void cleanUpMbcConfig() {
1343 CleanUp();
1344 mCfgs.clear();
1345 mChannelConfig.clear();
1346 }
1347
1348 static constexpr int kNPointFFT = 1024;
1349 static constexpr float kToleranceDb = 0.5;
1350 static constexpr float kDefaultPostGainDb = 0;
1351 static constexpr float kDefaultPreGainDb = 0;
1352 static constexpr float kDefaultAttackTime = 0;
1353 static constexpr float kDefaultReleaseTime = 0;
1354 static constexpr float kDefaultKneeWidth = 0;
1355 static constexpr float kDefaultThresholdDb = 0;
1356 static constexpr float kDefaultNoiseGateDb = -10;
1357 static constexpr float kDefaultExpanderRatio = 1;
1358 static constexpr float kDefaultRatio = 1;
1359 static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
Sneha Patil7ba121b2025-01-22 09:19:39 +00001360 // Full scale sine wave with 100 Hz and 1000 Hz frequency is -6 dB
1361 static constexpr float kFullScaleDb = -6;
Sneha Patilc3252762024-11-21 10:51:46 +00001362 std::vector<int> mTestFrequencies = {100, 1000};
1363 // Calculating normalizing factor by dividing the number of FFT points by half and the number of
1364 // test frequencies. The normalization accounts for the FFT splitting the signal into positive
1365 // and negative frequencies. Additionally, during multi-tone input generation, sample values are
1366 // normalized to the range [-1, 1] by dividing them by the number of test frequencies.
1367 float mNormalizingFactor = (kNPointFFT / (2 * mTestFrequencies.size()));
1368 std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
1369 std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
1370 std::vector<int> mBinOffsets;
1371 std::vector<float> mInput;
Sneha Patil7ba121b2025-01-22 09:19:39 +00001372 float mInputDb;
Sneha Patilc3252762024-11-21 10:51:46 +00001373};
1374
1375TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingThreshold) {
1376 float ratio = 20;
1377 std::vector<float> thresholdValues = {-200, -100, 0, 100, 200};
1378
1379 for (float threshold : thresholdValues) {
1380 cleanUpMbcConfig();
1381 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(threshold, ratio));
1382 }
1383}
1384
1385TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingRatio) {
1386 float threshold = -20;
1387 std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
1388
1389 for (float ratio : ratioValues) {
1390 cleanUpMbcConfig();
1391 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(threshold, ratio));
1392 }
1393}
1394
Sneha Patil7ba121b2025-01-22 09:19:39 +00001395TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingPostGain) {
1396 std::vector<float> postGainDbValues = {-55, -30, 0, 30, 55};
1397 std::vector<float> output(mInput.size());
1398 for (float postGainDb : postGainDbValues) {
Sneha Patil903c6202025-01-30 06:37:10 +00001399 ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput,
1400 dBToAmplitude(postGainDb), kSamplingFrequency,
1401 mChannelLayout));
Sneha Patil7ba121b2025-01-22 09:19:39 +00001402 mInputDb = calculateDb(mInput);
1403 EXPECT_NEAR(mInputDb, kFullScaleDb - postGainDb, kToleranceDb);
1404 cleanUpMbcConfig();
1405 for (int i = 0; i < mChannelCount; i++) {
1406 fillMbcBandConfig(mCfgs, i, kDefaultThresholdDb, kDefaultRatio, kDefaultNoiseGateDb,
1407 kDefaultExpanderRatio, 0 /*band index*/, 2000 /*cutoffFrequency*/,
1408 kDefaultPreGainDb, postGainDb);
1409 }
1410 EXPECT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
1411 if (!isAllParamsValid()) {
1412 continue;
1413 }
1414 float outputDb = calculateDb(output, kStartIndex);
1415 EXPECT_NEAR(outputDb, mInputDb + postGainDb, kToleranceDb)
1416 << "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
1417 }
1418}
1419
Sneha Patilc3252762024-11-21 10:51:46 +00001420INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingMbcBandConfigDataTest,
1421 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1422 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1423 [](const auto& info) {
1424 auto descriptor = info.param;
1425 std::string name = getPrefix(descriptor.second);
1426 std::replace_if(
1427 name.begin(), name.end(),
1428 [](const char c) { return !std::isalnum(c); }, '_');
1429 return name;
1430 });
1431
1432GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingMbcBandConfigDataTest);
1433
Ram Mohane4064ce2022-12-20 18:05:14 +05301434int main(int argc, char** argv) {
1435 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +05301436 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Ram Mohane4064ce2022-12-20 18:05:14 +05301437 ABinderProcess_setThreadPoolMaxThreadCount(1);
1438 ABinderProcess_startThreadPool();
1439 return RUN_ALL_TESTS();
1440}