blob: 2ce7b51a2655128f71dfdd8c369e11fd999058f4 [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
Sneha Patilba665282025-02-06 08:37:48 +000042constexpr int32_t kMinDataTestHalVersion = 3;
43
Ram Mohane4064ce2022-12-20 18:05:14 +053044/**
45 * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
46 * VtsAudioEffectTargetTest.
47 */
48class DynamicsProcessingTestHelper : public EffectHelper {
49 public:
50 DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair,
Aayush Sonifbb5cd32024-11-21 10:51:46 +000051 int32_t channelLayout = kDefaultChannelLayout)
52 : mChannelLayout(channelLayout),
Sneha Patilabc94642024-11-13 08:41:05 +000053 mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
54 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout))) {
Ram Mohane4064ce2022-12-20 18:05:14 +053055 std::tie(mFactory, mDescriptor) = pair;
Ram Mohane4064ce2022-12-20 18:05:14 +053056 }
57
58 // setup
59 void SetUpDynamicsProcessingEffect() {
60 ASSERT_NE(nullptr, mFactory);
61 ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Ram Mohane4064ce2022-12-20 18:05:14 +053062 Parameter::Specific specific = getDefaultParamSpecific();
Shunkai Yao61f9dd22024-05-08 22:34:36 +000063 Parameter::Common common = createParamCommon(
Sneha Patilabc94642024-11-13 08:41:05 +000064 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
65 kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
66 kFrameCount /* oFrameCount */,
Ram Mohane4064ce2022-12-20 18:05:14 +053067 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout),
68 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
Sneha Patilabc94642024-11-13 08:41:05 +000069 ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
Ram Mohane4064ce2022-12-20 18:05:14 +053070 ASSERT_NE(nullptr, mEffect);
71 mEngineConfigApplied = mEngineConfigPreset;
72 }
73
74 Parameter::Specific getDefaultParamSpecific() {
75 DynamicsProcessing dp = DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
76 mEngineConfigPreset);
77 Parameter::Specific specific =
78 Parameter::Specific::make<Parameter::Specific::dynamicsProcessing>(dp);
79 return specific;
80 }
81
82 // teardown
83 void TearDownDynamicsProcessingEffect() {
84 ASSERT_NO_FATAL_FAILURE(close(mEffect));
85 ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
86 }
87
88 // utils functions for parameter checking
Ram Mohane4064ce2022-12-20 18:05:14 +053089 bool isParamEqual(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dpRef,
90 const DynamicsProcessing& dpTest);
Ram Mohane4064ce2022-12-20 18:05:14 +053091 bool isEngineConfigEqual(const DynamicsProcessing::EngineArchitecture& refCfg,
92 const DynamicsProcessing::EngineArchitecture& testCfg);
93
94 template <typename T>
95 std::vector<T> filterEnabledVector(const std::vector<T>& vec);
96
97 template <typename T>
98 bool isAidlVectorEqualAfterFilter(const std::vector<T>& source, const std::vector<T>& target);
99
100 template <typename T>
101 bool isAidlVectorEqual(const std::vector<T>& source, const std::vector<T>& target);
102
Ram Mohanafdf90b2023-03-23 08:48:25 +0530103 template <typename T>
104 bool isChannelConfigValid(const std::vector<T>& cfgs) {
105 auto& channelCount = mChannelCount;
106 return std::all_of(cfgs.cbegin(), cfgs.cend(), [channelCount](const T& cfg) {
107 return (cfg.channel >= 0 && cfg.channel < channelCount);
108 });
109 }
110
111 template <typename T>
112 bool isBandConfigValid(const std::vector<T>& cfgs, int bandCount);
113
114 bool isParamValid(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dp);
115
Ram Mohane4064ce2022-12-20 18:05:14 +0530116 // get set params and validate
117 void SetAndGetDynamicsProcessingParameters();
118
Sneha Patilabc94642024-11-13 08:41:05 +0000119 bool isAllParamsValid();
120
Sneha Patilcbf86a42024-11-26 10:41:54 +0000121 void setParamsAndProcess(std::vector<float>& input, std::vector<float>& output);
122
123 float calculateDb(const std::vector<float>& input, size_t startSamplePos);
124
Sneha Patil2da23d72025-02-25 10:54:18 +0000125 void getMagnitudeValue(const std::vector<float>& output, std::vector<float>& bufferMag);
126
127 void checkInputAndOutputEquality(const std::vector<float>& outputMag);
128
129 void setUpDataTest(const std::vector<int>& testFrequencies, float fullScaleSineDb);
130
131 void createChannelConfig();
132
Ram Mohane4064ce2022-12-20 18:05:14 +0530133 // enqueue test parameters
134 void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
135 void addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
136 void addPostEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
137 void addMbcChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
138 void addPreEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
139 void addPostEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
140 void addMbcBandConfigs(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs);
141 void addLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfg);
142 void addInputGain(const std::vector<DynamicsProcessing::InputGain>& inputGain);
143
Sneha Patilba665282025-02-06 08:37:48 +0000144 void checkHalVersion();
145
Ram Mohane4064ce2022-12-20 18:05:14 +0530146 static constexpr float kPreferredProcessingDurationMs = 10.0f;
147 static constexpr int kBandCount = 5;
Sneha Patilabc94642024-11-13 08:41:05 +0000148 static constexpr int kSamplingFrequency = 44100;
149 static constexpr int kFrameCount = 2048;
Sneha Patilcbf86a42024-11-26 10:41:54 +0000150 static constexpr int kInputFrequency = 1000;
151 static constexpr size_t kStartIndex = 15 * kSamplingFrequency / 1000; // skip 15ms
Sneha Patil2da23d72025-02-25 10:54:18 +0000152 static constexpr float kToleranceDb = 0.5;
153 static constexpr int kNPointFFT = 1024;
154 static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
155 // Full scale sine wave with 1000 Hz frequency is -3 dB
156 static constexpr float kSineFullScaleDb = -3;
157 // Full scale sine wave with 100 Hz and 1000 Hz frequency is -6 dB
158 static constexpr float kSineMultitoneFullScaleDb = -6;
159 const std::vector<int> kCutoffFreqHz = {200 /*0th band cutoff*/, 2000 /*1st band cutoff*/};
160 std::vector<int> mMultitoneTestFrequencies = {100, 1000};
161 // Calculating normalizing factor by dividing the number of FFT points by half and the number of
162 // test frequencies. The normalization accounts for the FFT splitting the signal into positive
163 // and negative frequencies. Additionally, during multi-tone input generation, sample values are
164 // normalized to the range [-1, 1] by dividing them by the number of test frequencies.
165 float mNormalizingFactor = (kNPointFFT / (2 * mMultitoneTestFrequencies.size()));
166 std::vector<int> mBinOffsets;
167 std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
168 std::vector<float> mInput;
169 float mInputDb;
Ram Mohane4064ce2022-12-20 18:05:14 +0530170 std::shared_ptr<IFactory> mFactory;
171 std::shared_ptr<IEffect> mEffect;
172 Descriptor mDescriptor;
Sneha Patilabc94642024-11-13 08:41:05 +0000173 IEffect::OpenEffectReturn mOpenEffectReturn;
Ram Mohane4064ce2022-12-20 18:05:14 +0530174 DynamicsProcessing::EngineArchitecture mEngineConfigApplied;
175 DynamicsProcessing::EngineArchitecture mEngineConfigPreset{
176 .resolutionPreference =
177 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
178 .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
179 .preEqStage = {.inUse = true, .bandCount = kBandCount},
180 .postEqStage = {.inUse = true, .bandCount = kBandCount},
181 .mbcStage = {.inUse = true, .bandCount = kBandCount},
182 .limiterInUse = true,
183 };
184
185 std::unordered_set<int /* channelId */> mPreEqChannelEnable;
186 std::unordered_set<int /* channelId */> mPostEqChannelEnable;
187 std::unordered_set<int /* channelId */> mMbcChannelEnable;
188 std::unordered_set<int /* channelId */> mLimiterChannelEnable;
189 static const std::set<std::vector<DynamicsProcessing::ChannelConfig>> kChannelConfigTestSet;
190 static const std::set<DynamicsProcessing::StageEnablement> kStageEnablementTestSet;
191 static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
192
193 private:
Ram Mohane4064ce2022-12-20 18:05:14 +0530194 std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
Sneha Patilabc94642024-11-13 08:41:05 +0000195
196 protected:
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000197 const int32_t mChannelLayout;
Sneha Patilabc94642024-11-13 08:41:05 +0000198 const int mChannelCount;
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000199
Ram Mohane4064ce2022-12-20 18:05:14 +0530200 void CleanUp() {
201 mTags.clear();
202 mPreEqChannelEnable.clear();
203 mPostEqChannelEnable.clear();
204 mMbcChannelEnable.clear();
205 mLimiterChannelEnable.clear();
206 }
207};
208
209// test value set for DynamicsProcessing::StageEnablement
210const std::set<DynamicsProcessing::StageEnablement>
211 DynamicsProcessingTestHelper::kStageEnablementTestSet = {
212 {.inUse = true, .bandCount = DynamicsProcessingTestHelper::kBandCount},
213 {.inUse = true, .bandCount = 0},
214 {.inUse = true, .bandCount = -1},
Ram Mohanafdf90b2023-03-23 08:48:25 +0530215 {.inUse = false, .bandCount = 0},
216 {.inUse = false, .bandCount = -1},
Ram Mohane4064ce2022-12-20 18:05:14 +0530217 {.inUse = false, .bandCount = DynamicsProcessingTestHelper::kBandCount}};
218
219// test value set for DynamicsProcessing::ChannelConfig
220const std::set<std::vector<DynamicsProcessing::ChannelConfig>>
221 DynamicsProcessingTestHelper::kChannelConfigTestSet = {
222 {{.channel = -1, .enable = false},
223 {.channel = 0, .enable = true},
224 {.channel = 1, .enable = false},
225 {.channel = 2, .enable = true}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530226 {{.channel = -1, .enable = false}, {.channel = 2, .enable = true}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530227 {{.channel = 0, .enable = true}, {.channel = 1, .enable = true}}};
228
229// test value set for DynamicsProcessing::InputGain
230const std::set<std::vector<DynamicsProcessing::InputGain>>
231 DynamicsProcessingTestHelper::kInputGainTestSet = {
232 {{.channel = 0, .gainDb = 10.f},
233 {.channel = 1, .gainDb = 0.f},
234 {.channel = 2, .gainDb = -10.f}},
Ram Mohane4064ce2022-12-20 18:05:14 +0530235 {{.channel = -1, .gainDb = -10.f}, {.channel = -2, .gainDb = 10.f}},
Ram Mohanafdf90b2023-03-23 08:48:25 +0530236 {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}},
237 {{.channel = 0, .gainDb = 10.f}, {.channel = 1, .gainDb = -10.f}}};
Ram Mohane4064ce2022-12-20 18:05:14 +0530238
Ram Mohanafdf90b2023-03-23 08:48:25 +0530239template <typename T>
240bool DynamicsProcessingTestHelper::isBandConfigValid(const std::vector<T>& cfgs, int bandCount) {
Shunkai Yao53238b12024-03-29 23:09:04 +0000241 std::unordered_set<int> freqs;
Ram Mohanafdf90b2023-03-23 08:48:25 +0530242 for (auto cfg : cfgs) {
243 if (cfg.channel < 0 || cfg.channel >= mChannelCount) return false;
244 if (cfg.band < 0 || cfg.band >= bandCount) return false;
Shunkai Yao53238b12024-03-29 23:09:04 +0000245 // duplicated band index
246 if (freqs.find(cfg.band) != freqs.end()) return false;
247 freqs.insert(cfg.band);
Ram Mohanafdf90b2023-03-23 08:48:25 +0530248 }
Shunkai Yao53238b12024-03-29 23:09:04 +0000249 return true;
Ram Mohanafdf90b2023-03-23 08:48:25 +0530250}
251
252bool DynamicsProcessingTestHelper::isParamValid(const DynamicsProcessing::Tag& tag,
253 const DynamicsProcessing& dp) {
254 switch (tag) {
255 case DynamicsProcessing::preEq: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530256 return isChannelConfigValid(dp.get<DynamicsProcessing::preEq>());
257 }
258 case DynamicsProcessing::postEq: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530259 return isChannelConfigValid(dp.get<DynamicsProcessing::postEq>());
260 }
261 case DynamicsProcessing::mbc: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530262 return isChannelConfigValid(dp.get<DynamicsProcessing::mbc>());
263 }
264 case DynamicsProcessing::preEqBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530265 return isBandConfigValid(dp.get<DynamicsProcessing::preEqBand>(),
266 mEngineConfigApplied.preEqStage.bandCount);
267 }
268 case DynamicsProcessing::postEqBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530269 return isBandConfigValid(dp.get<DynamicsProcessing::postEqBand>(),
270 mEngineConfigApplied.postEqStage.bandCount);
271 }
272 case DynamicsProcessing::mbcBand: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530273 return isBandConfigValid(dp.get<DynamicsProcessing::mbcBand>(),
274 mEngineConfigApplied.mbcStage.bandCount);
275 }
276 case DynamicsProcessing::limiter: {
Ram Mohanafdf90b2023-03-23 08:48:25 +0530277 return isChannelConfigValid(dp.get<DynamicsProcessing::limiter>());
278 }
279 case DynamicsProcessing::inputGain: {
280 return isChannelConfigValid(dp.get<DynamicsProcessing::inputGain>());
281 }
282 default: {
283 return true;
284 }
285 }
286 return true;
287}
Ram Mohane4064ce2022-12-20 18:05:14 +0530288
Ram Mohane4064ce2022-12-20 18:05:14 +0530289bool DynamicsProcessingTestHelper::isParamEqual(const DynamicsProcessing::Tag& tag,
290 const DynamicsProcessing& dpRef,
291 const DynamicsProcessing& dpTest) {
292 switch (tag) {
293 case DynamicsProcessing::engineArchitecture: {
294 return isEngineConfigEqual(dpRef.get<DynamicsProcessing::engineArchitecture>(),
295 dpTest.get<DynamicsProcessing::engineArchitecture>());
296 }
297 case DynamicsProcessing::preEq: {
298 const auto& source = dpRef.get<DynamicsProcessing::preEq>();
299 const auto& target = dpTest.get<DynamicsProcessing::preEq>();
300 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(source, target);
301 }
302 case DynamicsProcessing::postEq: {
303 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
304 dpRef.get<DynamicsProcessing::postEq>(),
305 dpTest.get<DynamicsProcessing::postEq>());
306 }
307 case DynamicsProcessing::mbc: {
308 return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
309 dpRef.get<DynamicsProcessing::mbc>(), dpTest.get<DynamicsProcessing::mbc>());
310 }
311 case DynamicsProcessing::preEqBand: {
312 return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
313 dpRef.get<DynamicsProcessing::preEqBand>(),
314 dpTest.get<DynamicsProcessing::preEqBand>());
315 }
316 case DynamicsProcessing::postEqBand: {
317 return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
318 dpRef.get<DynamicsProcessing::postEqBand>(),
319 dpTest.get<DynamicsProcessing::postEqBand>());
320 }
321 case DynamicsProcessing::mbcBand: {
322 return isAidlVectorEqualAfterFilter<DynamicsProcessing::MbcBandConfig>(
323 dpRef.get<DynamicsProcessing::mbcBand>(),
324 dpTest.get<DynamicsProcessing::mbcBand>());
325 }
326 case DynamicsProcessing::limiter: {
327 return isAidlVectorEqualAfterFilter<DynamicsProcessing::LimiterConfig>(
328 dpRef.get<DynamicsProcessing::limiter>(),
329 dpTest.get<DynamicsProcessing::limiter>());
330 }
331 case DynamicsProcessing::inputGain: {
332 return isAidlVectorEqual<DynamicsProcessing::InputGain>(
333 dpRef.get<DynamicsProcessing::inputGain>(),
334 dpTest.get<DynamicsProcessing::inputGain>());
335 }
Shunkai Yaob2325e52023-03-03 19:34:47 +0000336 case DynamicsProcessing::vendor: {
Ram Mohane4064ce2022-12-20 18:05:14 +0530337 return false;
338 }
339 }
340}
341
Ram Mohane4064ce2022-12-20 18:05:14 +0530342bool DynamicsProcessingTestHelper::isEngineConfigEqual(
343 const DynamicsProcessing::EngineArchitecture& ref,
344 const DynamicsProcessing::EngineArchitecture& test) {
345 return ref == test;
346}
347
348template <typename T>
349std::vector<T> DynamicsProcessingTestHelper::filterEnabledVector(const std::vector<T>& vec) {
350 std::vector<T> ret;
351 std::copy_if(vec.begin(), vec.end(), std::back_inserter(ret),
352 [](const auto& v) { return v.enable; });
353 return ret;
354}
355
356template <typename T>
357bool DynamicsProcessingTestHelper::isAidlVectorEqual(const std::vector<T>& source,
358 const std::vector<T>& target) {
359 if (source.size() != target.size()) return false;
360
361 auto tempS = source;
362 auto tempT = target;
363 std::sort(tempS.begin(), tempS.end());
364 std::sort(tempT.begin(), tempT.end());
365 return tempS == tempT;
366}
367
368template <typename T>
369bool DynamicsProcessingTestHelper::isAidlVectorEqualAfterFilter(const std::vector<T>& source,
370 const std::vector<T>& target) {
371 return isAidlVectorEqual<T>(filterEnabledVector<T>(source), filterEnabledVector<T>(target));
372}
373
374void DynamicsProcessingTestHelper::SetAndGetDynamicsProcessingParameters() {
Sneha Patilabc94642024-11-13 08:41:05 +0000375 for (const auto& [tag, dp] : mTags) {
Ram Mohane4064ce2022-12-20 18:05:14 +0530376 // validate parameter
377 Descriptor desc;
378 ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
Ram Mohanafdf90b2023-03-23 08:48:25 +0530379 bool valid = isParamInRange(dp, desc.capability.range.get<Range::dynamicsProcessing>());
380 if (valid) valid = isParamValid(tag, dp);
Ram Mohane4064ce2022-12-20 18:05:14 +0530381 const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
382
383 // set parameter
384 Parameter expectParam;
385 Parameter::Specific specific;
386 specific.set<Parameter::Specific::dynamicsProcessing>(dp);
387 expectParam.set<Parameter::specific>(specific);
Shunkai Yao0a0c45e2023-02-13 17:41:11 +0000388 ASSERT_STATUS(expected, mEffect->setParameter(expectParam))
389 << "\n"
390 << expectParam.toString() << "\n"
391 << desc.toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530392
393 // only get if parameter in range and set success
394 if (expected == EX_NONE) {
395 Parameter getParam;
396 Parameter::Id id;
397 DynamicsProcessing::Id dpId;
398 dpId.set<DynamicsProcessing::Id::commonTag>(tag);
399 id.set<Parameter::Id::dynamicsProcessingTag>(dpId);
400 // if set success, then get should match
401 EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
402 Parameter::Specific specificTest = getParam.get<Parameter::specific>();
403 const auto& target = specificTest.get<Parameter::Specific::dynamicsProcessing>();
404 EXPECT_TRUE(isParamEqual(tag, dp, target)) << dp.toString() << "\n"
405 << target.toString();
406 // update mEngineConfigApplied after setting successfully
407 if (tag == DynamicsProcessing::engineArchitecture) {
408 mEngineConfigApplied = target.get<DynamicsProcessing::engineArchitecture>();
409 }
410 }
411 }
412}
413
Sneha Patilabc94642024-11-13 08:41:05 +0000414bool DynamicsProcessingTestHelper::isAllParamsValid() {
415 if (mTags.empty()) {
416 return false;
417 }
418 for (const auto& [tag, dp] : mTags) {
419 // validate parameter
420 if (!isParamInRange(dp, mDescriptor.capability.range.get<Range::dynamicsProcessing>())) {
421 return false;
422 }
423 if (!isParamValid(tag, dp)) {
424 return false;
425 }
426 }
427 return true;
428}
429
Aayush Sonifbb5cd32024-11-21 10:51:46 +0000430// This function calculates power for both and mono and stereo data as the total power for
431// interleaved multichannel data can be calculated by treating it as a continuous mono input.
Sneha Patilcbf86a42024-11-26 10:41:54 +0000432float DynamicsProcessingTestHelper::calculateDb(const std::vector<float>& input,
433 size_t startSamplePos = 0) {
434 return audio_utils_compute_power_mono(input.data() + startSamplePos, AUDIO_FORMAT_PCM_FLOAT,
435 input.size() - startSamplePos);
436}
437
438void DynamicsProcessingTestHelper::setParamsAndProcess(std::vector<float>& input,
439 std::vector<float>& output) {
440 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
441 if (isAllParamsValid()) {
442 ASSERT_NO_FATAL_FAILURE(
443 processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn));
444 ASSERT_GT(output.size(), kStartIndex);
445 }
446}
447
Sneha Patil2da23d72025-02-25 10:54:18 +0000448void DynamicsProcessingTestHelper::getMagnitudeValue(const std::vector<float>& output,
449 std::vector<float>& bufferMag) {
450 std::vector<float> subOutput(output.begin() + kStartIndex, output.end());
451 EXPECT_NO_FATAL_FAILURE(calculateMagnitudeMono(bufferMag, subOutput, mBinOffsets, kNPointFFT));
452}
453
454void DynamicsProcessingTestHelper::checkInputAndOutputEquality(
455 const std::vector<float>& outputMag) {
456 std::vector<float> inputMag(mBinOffsets.size());
457 EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(mInput, inputMag));
458 for (size_t i = 0; i < inputMag.size(); i++) {
459 EXPECT_NEAR(calculateDb({inputMag[i] / mNormalizingFactor}),
460 calculateDb({outputMag[i] / mNormalizingFactor}), kToleranceDb);
461 }
462}
463
464void DynamicsProcessingTestHelper::setUpDataTest(const std::vector<int>& testFrequencies,
465 float fullScaleSineDb) {
466 ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect());
467 SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
468 ASSERT_NO_FATAL_FAILURE(
469 generateSineWave(testFrequencies, mInput, 1.0, kSamplingFrequency, mChannelLayout));
470 mInputDb = calculateDb(mInput);
471 ASSERT_NEAR(mInputDb, fullScaleSineDb, kToleranceDb);
472}
473
474void DynamicsProcessingTestHelper::createChannelConfig() {
475 for (int i = 0; i < mChannelCount; i++) {
476 mChannelConfig.push_back(DynamicsProcessing::ChannelConfig(i, true));
477 }
478}
479
Ram Mohane4064ce2022-12-20 18:05:14 +0530480void DynamicsProcessingTestHelper::addEngineConfig(
481 const DynamicsProcessing::EngineArchitecture& cfg) {
482 DynamicsProcessing dp;
483 dp.set<DynamicsProcessing::engineArchitecture>(cfg);
484 mTags.push_back({DynamicsProcessing::engineArchitecture, dp});
485}
486
487void DynamicsProcessingTestHelper::addPreEqChannelConfig(
488 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
489 DynamicsProcessing dp;
490 dp.set<DynamicsProcessing::preEq>(cfgs);
491 mTags.push_back({DynamicsProcessing::preEq, dp});
492 for (auto& cfg : cfgs) {
493 if (cfg.enable) mPreEqChannelEnable.insert(cfg.channel);
494 }
495}
496
497void DynamicsProcessingTestHelper::addPostEqChannelConfig(
498 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
499 DynamicsProcessing dp;
500 dp.set<DynamicsProcessing::postEq>(cfgs);
501 mTags.push_back({DynamicsProcessing::postEq, dp});
502 for (auto& cfg : cfgs) {
503 if (cfg.enable) mPostEqChannelEnable.insert(cfg.channel);
504 }
505}
506
507void DynamicsProcessingTestHelper::addMbcChannelConfig(
508 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
509 DynamicsProcessing dp;
510 dp.set<DynamicsProcessing::mbc>(cfgs);
511 mTags.push_back({DynamicsProcessing::mbc, dp});
512 for (auto& cfg : cfgs) {
513 if (cfg.enable) mMbcChannelEnable.insert(cfg.channel);
514 }
515}
516
517void DynamicsProcessingTestHelper::addPreEqBandConfigs(
518 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
519 DynamicsProcessing dp;
520 dp.set<DynamicsProcessing::preEqBand>(cfgs);
521 mTags.push_back({DynamicsProcessing::preEqBand, dp});
522}
523
524void DynamicsProcessingTestHelper::addPostEqBandConfigs(
525 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
526 DynamicsProcessing dp;
527 dp.set<DynamicsProcessing::postEqBand>(cfgs);
528 mTags.push_back({DynamicsProcessing::postEqBand, dp});
529}
530
531void DynamicsProcessingTestHelper::addMbcBandConfigs(
532 const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
533 DynamicsProcessing dp;
534 dp.set<DynamicsProcessing::mbcBand>(cfgs);
535 mTags.push_back({DynamicsProcessing::mbcBand, dp});
536}
537
538void DynamicsProcessingTestHelper::addLimiterConfig(
539 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
540 DynamicsProcessing dp;
541 dp.set<DynamicsProcessing::limiter>(cfgs);
542 mTags.push_back({DynamicsProcessing::limiter, dp});
543 for (auto& cfg : cfgs) {
544 if (cfg.enable) mLimiterChannelEnable.insert(cfg.channel);
545 }
546}
547
548void DynamicsProcessingTestHelper::addInputGain(
549 const std::vector<DynamicsProcessing::InputGain>& inputGains) {
550 DynamicsProcessing dp;
551 dp.set<DynamicsProcessing::inputGain>(inputGains);
552 mTags.push_back({DynamicsProcessing::inputGain, dp});
553}
554
Sneha Patilba665282025-02-06 08:37:48 +0000555void DynamicsProcessingTestHelper::checkHalVersion() {
556 if (int32_t version;
557 mEffect->getInterfaceVersion(&version).isOk() && version < kMinDataTestHalVersion) {
558 GTEST_SKIP() << "Skipping the data test for version: " << version << "\n";
559 }
560}
561
Sneha Patilabc94642024-11-13 08:41:05 +0000562void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& limiterConfigList,
563 int channelIndex, bool enable, int linkGroup, float attackTime,
564 float releaseTime, float ratio, float threshold, float postGain) {
565 DynamicsProcessing::LimiterConfig cfg;
566 cfg.channel = channelIndex;
567 cfg.enable = enable;
568 cfg.linkGroup = linkGroup;
569 cfg.attackTimeMs = attackTime;
570 cfg.releaseTimeMs = releaseTime;
571 cfg.ratio = ratio;
572 cfg.thresholdDb = threshold;
573 cfg.postGainDb = postGain;
574 limiterConfigList.push_back(cfg);
575}
576
Sneha Patilc3252762024-11-21 10:51:46 +0000577DynamicsProcessing::MbcBandConfig createMbcBandConfig(int channel, int band, float cutoffFreqHz,
578 float attackTimeMs, float releaseTimeMs,
579 float ratio, float thresholdDb,
580 float kneeWidthDb, float noiseGate,
581 float expanderRatio, float preGainDb,
582 float postGainDb) {
583 return DynamicsProcessing::MbcBandConfig{.channel = channel,
584 .band = band,
585 .enable = true,
586 .cutoffFrequencyHz = cutoffFreqHz,
587 .attackTimeMs = attackTimeMs,
588 .releaseTimeMs = releaseTimeMs,
589 .ratio = ratio,
590 .thresholdDb = thresholdDb,
591 .kneeWidthDb = kneeWidthDb,
592 .noiseGateThresholdDb = noiseGate,
593 .expanderRatio = expanderRatio,
594 .preGainDb = preGainDb,
595 .postGainDb = postGainDb};
596}
597
Sneha Patil2da23d72025-02-25 10:54:18 +0000598DynamicsProcessing::EqBandConfig creatEqBandConfig(int channel, int band, float cutOffFreqHz,
Sneha Patil4d8a91c2025-03-03 08:03:43 +0000599 float gainDb, bool enable) {
Sneha Patil2da23d72025-02-25 10:54:18 +0000600 return DynamicsProcessing::EqBandConfig{.channel = channel,
601 .band = band,
Sneha Patil4d8a91c2025-03-03 08:03:43 +0000602 .enable = enable,
Sneha Patil2da23d72025-02-25 10:54:18 +0000603 .cutoffFrequencyHz = cutOffFreqHz,
604 .gainDb = gainDb};
605}
606
Ram Mohane4064ce2022-12-20 18:05:14 +0530607/**
608 * Test DynamicsProcessing Engine Configuration
609 */
610enum EngineArchitectureTestParamName {
611 ENGINE_TEST_INSTANCE_NAME,
612 ENGINE_TEST_RESOLUTION_PREFERENCE,
613 ENGINE_TEST_PREFERRED_DURATION,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000614 ENGINE_TEST_STAGE_ENABLEMENT
Ram Mohane4064ce2022-12-20 18:05:14 +0530615};
616using EngineArchitectureTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
617 DynamicsProcessing::ResolutionPreference, float,
Shunkai Yaof137ba42024-04-11 17:11:03 +0000618 DynamicsProcessing::StageEnablement>;
Ram Mohane4064ce2022-12-20 18:05:14 +0530619
620void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg,
621 const EngineArchitectureTestParams& params) {
622 cfg.resolutionPreference = std::get<ENGINE_TEST_RESOLUTION_PREFERENCE>(params);
623 cfg.preferredProcessingDurationMs = std::get<ENGINE_TEST_PREFERRED_DURATION>(params);
624 cfg.preEqStage = cfg.postEqStage = cfg.mbcStage =
625 std::get<ENGINE_TEST_STAGE_ENABLEMENT>(params);
Shunkai Yaof137ba42024-04-11 17:11:03 +0000626 cfg.limiterInUse = true;
Ram Mohane4064ce2022-12-20 18:05:14 +0530627}
628
629class DynamicsProcessingTestEngineArchitecture
630 : public ::testing::TestWithParam<EngineArchitectureTestParams>,
631 public DynamicsProcessingTestHelper {
632 public:
633 DynamicsProcessingTestEngineArchitecture()
634 : DynamicsProcessingTestHelper(std::get<ENGINE_TEST_INSTANCE_NAME>(GetParam())) {
635 fillEngineArchConfig(mCfg, GetParam());
636 };
637
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000638 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +0530639
640 void TearDown() override { TearDownDynamicsProcessingEffect(); }
641
642 DynamicsProcessing::EngineArchitecture mCfg;
643};
644
645TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000646 addEngineConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +0000647 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530648}
649
650INSTANTIATE_TEST_SUITE_P(
651 DynamicsProcessingTest, DynamicsProcessingTestEngineArchitecture,
652 ::testing::Combine(
653 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000654 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohanafdf90b2023-03-23 08:48:25 +0530655 testing::Values(
656 DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
657 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
658 static_cast<DynamicsProcessing::ResolutionPreference>(-1)), // variant
659 testing::Values(-10.f, 0.f, 10.f), // processing duration
Ram Mohane4064ce2022-12-20 18:05:14 +0530660 testing::ValuesIn(
Shunkai Yaof137ba42024-04-11 17:11:03 +0000661 DynamicsProcessingTestHelper::kStageEnablementTestSet) // preEQ/postEQ/mbc
662 ),
Ram Mohane4064ce2022-12-20 18:05:14 +0530663 [](const auto& info) {
664 auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
665 DynamicsProcessing::EngineArchitecture cfg;
666 fillEngineArchConfig(cfg, info.param);
Jaideep Sharmae4c7a962023-06-14 19:14:44 +0530667 std::string name = getPrefix(descriptor) + "_Cfg_" + cfg.toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530668 std::replace_if(
669 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
670 return name;
671 });
672GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEngineArchitecture);
673
674/**
675 * Test DynamicsProcessing Input Gain
676 */
677enum InputGainTestParamName {
678 INPUT_GAIN_INSTANCE_NAME,
679 INPUT_GAIN_PARAM,
680};
681class DynamicsProcessingTestInputGain
682 : public ::testing::TestWithParam<std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
683 std::vector<DynamicsProcessing::InputGain>>>,
684 public DynamicsProcessingTestHelper {
685 public:
686 DynamicsProcessingTestInputGain()
687 : DynamicsProcessingTestHelper(std::get<INPUT_GAIN_INSTANCE_NAME>(GetParam())),
Sneha Patilabc94642024-11-13 08:41:05 +0000688 mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())) {};
Ram Mohane4064ce2022-12-20 18:05:14 +0530689
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000690 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +0530691
692 void TearDown() override { TearDownDynamicsProcessingEffect(); }
693
694 const std::vector<DynamicsProcessing::InputGain> mInputGain;
695};
696
697TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000698 addInputGain(mInputGain);
Sneha Patilabc94642024-11-13 08:41:05 +0000699 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530700}
701
702INSTANTIATE_TEST_SUITE_P(
703 DynamicsProcessingTest, DynamicsProcessingTestInputGain,
704 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000705 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohane4064ce2022-12-20 18:05:14 +0530706 testing::ValuesIn(DynamicsProcessingTestInputGain::kInputGainTestSet)),
707 [](const auto& info) {
708 auto descriptor = std::get<INPUT_GAIN_INSTANCE_NAME>(info.param).second;
709 std::string gains =
710 ::android::internal::ToString(std::get<INPUT_GAIN_PARAM>(info.param));
711 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
712 descriptor.common.name + "_UUID_" +
Shunkai Yao6f822452024-03-29 18:45:30 +0000713 toString(descriptor.common.id.uuid) + "_inputGains_" + gains;
Ram Mohane4064ce2022-12-20 18:05:14 +0530714 std::replace_if(
715 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
716 return name;
717 });
718GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestInputGain);
719
Sneha Patilcbf86a42024-11-26 10:41:54 +0000720class DynamicsProcessingInputGainDataTest
721 : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
722 public DynamicsProcessingTestHelper {
723 public:
724 DynamicsProcessingInputGainDataTest()
725 : DynamicsProcessingTestHelper((GetParam()), AudioChannelLayout::LAYOUT_MONO) {
726 mInput.resize(kFrameCount * mChannelCount);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000727 }
728
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000729 void SetUp() override {
730 ASSERT_NO_FATAL_FAILURE(
731 setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb));
732 }
Sneha Patilcbf86a42024-11-26 10:41:54 +0000733
734 void TearDown() override { TearDownDynamicsProcessingEffect(); }
735
736 void cleanUpInputGainConfig() {
737 CleanUp();
738 mInputGain.clear();
739 }
740
741 std::vector<DynamicsProcessing::InputGain> mInputGain;
Sneha Patilcbf86a42024-11-26 10:41:54 +0000742};
743
744TEST_P(DynamicsProcessingInputGainDataTest, SetAndGetInputGain) {
745 std::vector<float> gainDbValues = {-85, -40, 0, 40, 85};
746 for (float gainDb : gainDbValues) {
747 cleanUpInputGainConfig();
748 for (int i = 0; i < mChannelCount; i++) {
749 mInputGain.push_back(DynamicsProcessing::InputGain(i, gainDb));
750 }
751 std::vector<float> output(mInput.size());
Sneha Patil3587ae52025-01-06 05:59:08 +0000752 addInputGain(mInputGain);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000753 EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
754 if (!isAllParamsValid()) {
755 continue;
756 }
757 float outputDb = calculateDb(output, kStartIndex);
758 EXPECT_NEAR(outputDb, mInputDb + gainDb, kToleranceDb)
759 << "InputGain: " << gainDb << ", OutputDb: " << outputDb;
760 }
761}
762
763INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingInputGainDataTest,
764 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
765 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
766 [](const auto& info) {
767 auto descriptor = info.param;
768 std::string name = getPrefix(descriptor.second);
769 std::replace_if(
770 name.begin(), name.end(),
771 [](const char c) { return !std::isalnum(c); }, '_');
772 return name;
773 });
774GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingInputGainDataTest);
775
Ram Mohane4064ce2022-12-20 18:05:14 +0530776/**
777 * Test DynamicsProcessing Limiter Config
778 */
779enum LimiterConfigTestParamName {
780 LIMITER_INSTANCE_NAME,
781 LIMITER_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +0530782 LIMITER_LINK_GROUP,
Ram Mohane4064ce2022-12-20 18:05:14 +0530783 LIMITER_ATTACK_TIME,
784 LIMITER_RELEASE_TIME,
785 LIMITER_RATIO,
786 LIMITER_THRESHOLD,
787 LIMITER_POST_GAIN,
Ram Mohane4064ce2022-12-20 18:05:14 +0530788};
Ram Mohane4064ce2022-12-20 18:05:14 +0530789
Shunkai Yaof137ba42024-04-11 17:11:03 +0000790using LimiterConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
Sneha Patilabc94642024-11-13 08:41:05 +0000791 int32_t, int32_t, float, float, float, float, float>;
Ram Mohane4064ce2022-12-20 18:05:14 +0530792
Sneha Patilabc94642024-11-13 08:41:05 +0000793void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& cfg,
Ram Mohane4064ce2022-12-20 18:05:14 +0530794 const LimiterConfigTestParams& params) {
Sneha Patilabc94642024-11-13 08:41:05 +0000795 fillLimiterConfig(cfg, std::get<LIMITER_CHANNEL>(params), true,
796 std::get<LIMITER_LINK_GROUP>(params), std::get<LIMITER_ATTACK_TIME>(params),
797 std::get<LIMITER_RELEASE_TIME>(params), std::get<LIMITER_RATIO>(params),
798 std::get<LIMITER_THRESHOLD>(params), std::get<LIMITER_POST_GAIN>(params));
Ram Mohane4064ce2022-12-20 18:05:14 +0530799}
800
801class DynamicsProcessingTestLimiterConfig
802 : public ::testing::TestWithParam<LimiterConfigTestParams>,
803 public DynamicsProcessingTestHelper {
804 public:
805 DynamicsProcessingTestLimiterConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +0000806 : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())) {
Sneha Patilabc94642024-11-13 08:41:05 +0000807 fillLimiterConfig(mLimiterConfigList, GetParam());
Ram Mohane4064ce2022-12-20 18:05:14 +0530808 }
809
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000810 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +0530811
812 void TearDown() override { TearDownDynamicsProcessingEffect(); }
813
814 DynamicsProcessing::LimiterConfig mCfg;
Sneha Patilabc94642024-11-13 08:41:05 +0000815 std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
Ram Mohane4064ce2022-12-20 18:05:14 +0530816};
817
818TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000819 addEngineConfig(mEngineConfigPreset);
820 addLimiterConfig(mLimiterConfigList);
Sneha Patilabc94642024-11-13 08:41:05 +0000821 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +0530822}
823
824INSTANTIATE_TEST_SUITE_P(
825 DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
826 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +0000827 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +0000828 testing::Values(-1, 0, 1, 2), // channel index
829 testing::Values(3), // link group
830 testing::Values(-1, 1), // attackTime
831 testing::Values(-60, 60), // releaseTime
832 testing::Values(-2.5, 2.5), // ratio
833 testing::Values(-2, 2), // thresh
834 testing::Values(-3.14, 3.14) // postGain
835 ),
Ram Mohane4064ce2022-12-20 18:05:14 +0530836 [](const auto& info) {
837 auto descriptor = std::get<LIMITER_INSTANCE_NAME>(info.param).second;
Sneha Patilabc94642024-11-13 08:41:05 +0000838 std::vector<DynamicsProcessing::LimiterConfig> cfg;
Ram Mohane4064ce2022-12-20 18:05:14 +0530839 fillLimiterConfig(cfg, info.param);
Sneha Patilabc94642024-11-13 08:41:05 +0000840 std::string name =
841 "Implementer_" + getPrefix(descriptor) + "_limiterConfig_" + cfg[0].toString();
Ram Mohane4064ce2022-12-20 18:05:14 +0530842 std::replace_if(
843 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
844 return name;
845 });
846GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfig);
847
Sneha Patilabc94642024-11-13 08:41:05 +0000848using LimiterConfigDataTestParams = std::pair<std::shared_ptr<IFactory>, Descriptor>;
849
850class DynamicsProcessingLimiterConfigDataTest
851 : public ::testing::TestWithParam<LimiterConfigDataTestParams>,
852 public DynamicsProcessingTestHelper {
853 public:
854 DynamicsProcessingLimiterConfigDataTest()
855 : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
856 mBufferSize = kFrameCount * mChannelCount;
857 mInput.resize(mBufferSize);
Sneha Patilabc94642024-11-13 08:41:05 +0000858 }
859
Aayush Soni63d6e2a2025-03-04 13:37:28 +0000860 void SetUp() override {
861 ASSERT_NO_FATAL_FAILURE(
862 setUpDataTest({static_cast<int>(kInputFrequency)}, kSineFullScaleDb));
863 }
Sneha Patilabc94642024-11-13 08:41:05 +0000864
865 void TearDown() override { TearDownDynamicsProcessingEffect(); }
866
Sneha Patilabc94642024-11-13 08:41:05 +0000867 void computeThreshold(float ratio, float outputDb, float& threshold) {
868 EXPECT_NE(ratio, 0);
869 threshold = (mInputDb - (ratio * outputDb)) / (1 - ratio);
870 }
871
872 void computeRatio(float threshold, float outputDb, float& ratio) {
873 float inputOverThreshold = mInputDb - threshold;
874 float outputOverThreshold = outputDb - threshold;
875 EXPECT_NE(outputOverThreshold, 0);
876 ratio = inputOverThreshold / outputOverThreshold;
877 }
878
Sneha Patilcbf86a42024-11-26 10:41:54 +0000879 void setLimiterParamsAndProcess(std::vector<float>& input, std::vector<float>& output) {
Sneha Patil3587ae52025-01-06 05:59:08 +0000880 addEngineConfig(mEngineConfigPreset);
881 addLimiterConfig(mLimiterConfigList);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000882 EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(input, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000883 }
884
885 void cleanUpLimiterConfig() {
886 CleanUp();
887 mLimiterConfigList.clear();
888 }
889 static constexpr float kDefaultLinkerGroup = 3;
890 static constexpr float kDefaultAttackTime = 0;
891 static constexpr float kDefaultReleaseTime = 0;
892 static constexpr float kDefaultRatio = 4;
Sneha Patilcbf86a42024-11-26 10:41:54 +0000893 static constexpr float kDefaultThreshold = -10;
Sneha Patilabc94642024-11-13 08:41:05 +0000894 static constexpr float kDefaultPostGain = 0;
Sneha Patil903c6202025-01-30 06:37:10 +0000895 static constexpr float kInputFrequency = 1000;
Sneha Patil2da23d72025-02-25 10:54:18 +0000896 static constexpr float kLimiterTestToleranceDb = 0.05;
Sneha Patilabc94642024-11-13 08:41:05 +0000897 std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
Sneha Patilabc94642024-11-13 08:41:05 +0000898 int mBufferSize;
899};
900
901TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingThresholdDb) {
902 std::vector<float> thresholdValues = {-200, -150, -100, -50, -5, 0};
903 std::vector<float> output(mInput.size());
904 float previousThreshold = -FLT_MAX;
905 for (float threshold : thresholdValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000906 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000907 for (int i = 0; i < mChannelCount; i++) {
908 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
909 kDefaultReleaseTime, kDefaultRatio, threshold, kDefaultPostGain);
910 }
Sneha Patilc3252762024-11-21 10:51:46 +0000911 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000912 if (!isAllParamsValid()) {
913 continue;
914 }
915 float outputDb = calculateDb(output, kStartIndex);
916 if (threshold >= mInputDb || kDefaultRatio == 1) {
Sneha Patil2da23d72025-02-25 10:54:18 +0000917 EXPECT_NEAR(mInputDb, outputDb, kLimiterTestToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000918 } else {
919 float calculatedThreshold = 0;
Sneha Patilc3252762024-11-21 10:51:46 +0000920 ASSERT_NO_FATAL_FAILURE(computeThreshold(kDefaultRatio, outputDb, calculatedThreshold));
Sneha Patilabc94642024-11-13 08:41:05 +0000921 ASSERT_GT(calculatedThreshold, previousThreshold);
922 previousThreshold = calculatedThreshold;
923 }
924 }
925}
926
927TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingRatio) {
928 std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
929 std::vector<float> output(mInput.size());
Sneha Patilabc94642024-11-13 08:41:05 +0000930 float previousRatio = 0;
931 for (float ratio : ratioValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000932 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000933 for (int i = 0; i < mChannelCount; i++) {
934 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
Sneha Patilcbf86a42024-11-26 10:41:54 +0000935 kDefaultReleaseTime, ratio, kDefaultThreshold, kDefaultPostGain);
Sneha Patilabc94642024-11-13 08:41:05 +0000936 }
Sneha Patilc3252762024-11-21 10:51:46 +0000937 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000938 if (!isAllParamsValid()) {
939 continue;
940 }
941 float outputDb = calculateDb(output, kStartIndex);
942
Sneha Patilcbf86a42024-11-26 10:41:54 +0000943 if (kDefaultThreshold >= mInputDb) {
Sneha Patil2da23d72025-02-25 10:54:18 +0000944 EXPECT_NEAR(mInputDb, outputDb, kLimiterTestToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000945 } else {
946 float calculatedRatio = 0;
Sneha Patilc3252762024-11-21 10:51:46 +0000947 ASSERT_NO_FATAL_FAILURE(computeRatio(kDefaultThreshold, outputDb, calculatedRatio));
Sneha Patilabc94642024-11-13 08:41:05 +0000948 ASSERT_GT(calculatedRatio, previousRatio);
949 previousRatio = calculatedRatio;
950 }
951 }
952}
953
Sneha Patilcbf86a42024-11-26 10:41:54 +0000954TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingPostGain) {
955 std::vector<float> postGainDbValues = {-85, -40, 0, 40, 85};
956 std::vector<float> output(mInput.size());
957 for (float postGainDb : postGainDbValues) {
958 cleanUpLimiterConfig();
Sneha Patil903c6202025-01-30 06:37:10 +0000959 ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, dBToAmplitude(postGainDb),
960 kSamplingFrequency, mChannelLayout));
961 mInputDb = calculateDb(mInput);
Sneha Patil2da23d72025-02-25 10:54:18 +0000962 EXPECT_NEAR(mInputDb, kSineFullScaleDb - postGainDb, kLimiterTestToleranceDb);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000963 for (int i = 0; i < mChannelCount; i++) {
964 fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
Sneha Patil903c6202025-01-30 06:37:10 +0000965 kDefaultReleaseTime, 1, kDefaultThreshold, postGainDb);
Sneha Patilcbf86a42024-11-26 10:41:54 +0000966 }
Sneha Patilc3252762024-11-21 10:51:46 +0000967 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilcbf86a42024-11-26 10:41:54 +0000968 if (!isAllParamsValid()) {
969 continue;
970 }
971 float outputDb = calculateDb(output, kStartIndex);
Sneha Patil2da23d72025-02-25 10:54:18 +0000972 EXPECT_NEAR(outputDb, mInputDb + postGainDb, kLimiterTestToleranceDb)
Sneha Patilcbf86a42024-11-26 10:41:54 +0000973 << "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
974 }
975}
976
Sneha Patilabc94642024-11-13 08:41:05 +0000977TEST_P(DynamicsProcessingLimiterConfigDataTest, LimiterEnableDisable) {
978 std::vector<bool> limiterEnableValues = {false, true};
979 std::vector<float> output(mInput.size());
980 for (bool isEnabled : limiterEnableValues) {
Sneha Patilcbf86a42024-11-26 10:41:54 +0000981 cleanUpLimiterConfig();
Sneha Patilabc94642024-11-13 08:41:05 +0000982 for (int i = 0; i < mChannelCount; i++) {
983 // Set non-default values
984 fillLimiterConfig(mLimiterConfigList, i, isEnabled, kDefaultLinkerGroup,
985 5 /*attack time*/, 5 /*release time*/, 10 /*ratio*/,
986 -10 /*threshold*/, 5 /*postgain*/);
987 }
Sneha Patilc3252762024-11-21 10:51:46 +0000988 ASSERT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
Sneha Patilabc94642024-11-13 08:41:05 +0000989 if (!isAllParamsValid()) {
990 continue;
991 }
992 if (isEnabled) {
993 EXPECT_NE(mInputDb, calculateDb(output, kStartIndex));
994 } else {
Sneha Patil2da23d72025-02-25 10:54:18 +0000995 EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), kLimiterTestToleranceDb);
Sneha Patilabc94642024-11-13 08:41:05 +0000996 }
997 }
998}
999
1000INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingLimiterConfigDataTest,
1001 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1002 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1003 [](const auto& info) {
1004 auto descriptor = info.param;
1005 std::string name = getPrefix(descriptor.second);
1006 std::replace_if(
1007 name.begin(), name.end(),
1008 [](const char c) { return !std::isalnum(c); }, '_');
1009 return name;
1010 });
Sneha Patild341d6f2024-11-28 06:27:19 +00001011GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingLimiterConfigDataTest);
Sneha Patilabc94642024-11-13 08:41:05 +00001012
Ram Mohane4064ce2022-12-20 18:05:14 +05301013/**
1014 * Test DynamicsProcessing ChannelConfig
1015 */
1016enum ChannelConfigTestParamName {
1017 BAND_CHANNEL_TEST_INSTANCE_NAME,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001018 BAND_CHANNEL_TEST_CHANNEL_CONFIG
Ram Mohane4064ce2022-12-20 18:05:14 +05301019};
1020using ChannelConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001021 std::vector<DynamicsProcessing::ChannelConfig>>;
Ram Mohane4064ce2022-12-20 18:05:14 +05301022
1023class DynamicsProcessingTestChannelConfig
1024 : public ::testing::TestWithParam<ChannelConfigTestParams>,
1025 public DynamicsProcessingTestHelper {
1026 public:
1027 DynamicsProcessingTestChannelConfig()
1028 : DynamicsProcessingTestHelper(std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(GetParam())),
Shunkai Yaof137ba42024-04-11 17:11:03 +00001029 mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())) {}
Ram Mohane4064ce2022-12-20 18:05:14 +05301030
Aayush Soni63d6e2a2025-03-04 13:37:28 +00001031 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +05301032
1033 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1034
1035 std::vector<DynamicsProcessing::ChannelConfig> mCfg;
Ram Mohane4064ce2022-12-20 18:05:14 +05301036};
1037
1038TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +00001039 addEngineConfig(mEngineConfigPreset);
1040 addPreEqChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +00001041 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301042}
1043
1044TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +00001045 addEngineConfig(mEngineConfigPreset);
1046 addPostEqChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +00001047 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301048}
1049
1050TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
Sneha Patil3587ae52025-01-06 05:59:08 +00001051 addEngineConfig(mEngineConfigPreset);
1052 addMbcChannelConfig(mCfg);
Sneha Patilabc94642024-11-13 08:41:05 +00001053 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301054}
1055
1056INSTANTIATE_TEST_SUITE_P(
1057 DynamicsProcessingTest, DynamicsProcessingTestChannelConfig,
1058 ::testing::Combine(
1059 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
Shunkai Yaof8be1ac2023-03-06 18:41:27 +00001060 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Ram Mohane4064ce2022-12-20 18:05:14 +05301061 testing::ValuesIn(
Shunkai Yaof137ba42024-04-11 17:11:03 +00001062 DynamicsProcessingTestHelper::kChannelConfigTestSet)), // channel config
Ram Mohane4064ce2022-12-20 18:05:14 +05301063 [](const auto& info) {
1064 auto descriptor = std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(info.param).second;
Ram Mohane4064ce2022-12-20 18:05:14 +05301065 std::string channelConfig = ::android::internal::ToString(
1066 std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(info.param));
1067
1068 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1069 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001070 toString(descriptor.common.id.uuid) + "_" + channelConfig;
Ram Mohane4064ce2022-12-20 18:05:14 +05301071 std::replace_if(
1072 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1073 return name;
1074 });
1075GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestChannelConfig);
1076
1077/**
1078 * Test DynamicsProcessing EqBandConfig
1079 */
1080enum EqBandConfigTestParamName {
1081 EQ_BAND_INSTANCE_NAME,
1082 EQ_BAND_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +05301083 EQ_BAND_CUT_OFF_FREQ,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001084 EQ_BAND_GAIN
Ram Mohane4064ce2022-12-20 18:05:14 +05301085};
1086using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
Sneha Patilabc94642024-11-13 08:41:05 +00001087 std::vector<std::pair<int, float>>, float>;
Ram Mohane4064ce2022-12-20 18:05:14 +05301088
1089void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
1090 const EqBandConfigTestParams& params) {
1091 const std::vector<std::pair<int, float>> cutOffFreqs = std::get<EQ_BAND_CUT_OFF_FREQ>(params);
1092 int bandCount = cutOffFreqs.size();
Ram Mohane4064ce2022-12-20 18:05:14 +05301093 for (int i = 0; i < bandCount; i++) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001094 cfgs.push_back(creatEqBandConfig(std::get<EQ_BAND_CHANNEL>(params), cutOffFreqs[i].first,
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001095 cutOffFreqs[i].second, std::get<EQ_BAND_GAIN>(params),
1096 true));
Ram Mohane4064ce2022-12-20 18:05:14 +05301097 }
1098}
1099
1100class DynamicsProcessingTestEqBandConfig : public ::testing::TestWithParam<EqBandConfigTestParams>,
1101 public DynamicsProcessingTestHelper {
1102 public:
1103 DynamicsProcessingTestEqBandConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +00001104 : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301105 fillEqBandConfig(mCfgs, GetParam());
1106 }
1107
Aayush Soni63d6e2a2025-03-04 13:37:28 +00001108 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +05301109
1110 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1111
1112 std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
Ram Mohane4064ce2022-12-20 18:05:14 +05301113};
1114
1115TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301116 mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001117 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301118 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1119 for (int i = 0; i < mChannelCount; i++) {
1120 cfgs[i].channel = i;
1121 cfgs[i].enable = true;
1122 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001123 addPreEqChannelConfig(cfgs);
1124 addPreEqBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001125 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301126}
1127
1128TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301129 mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001130 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301131 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1132 for (int i = 0; i < mChannelCount; i++) {
1133 cfgs[i].channel = i;
1134 cfgs[i].enable = true;
1135 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001136 addPostEqChannelConfig(cfgs);
1137 addPostEqBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001138 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301139}
1140
1141std::vector<std::vector<std::pair<int, float>>> kBands{
1142 {
1143 {0, 600},
1144 {1, 2000},
1145 {2, 6000},
1146 {3, 10000},
1147 {4, 16000},
Sneha Patil0ecc1782025-02-17 11:21:32 +00001148 {5, 20000},
1149 {6, 26000},
1150 {7, 30000},
1151 {8, 36000},
1152 {9, 40000},
1153 }, // 10 bands
Ram Mohane4064ce2022-12-20 18:05:14 +05301154 {
1155 {0, 800},
1156 {3, 15000},
1157 {2, 6000},
1158 {1, 2000},
1159 }, // 4 bands, unsorted
1160 {
1161 {0, 650},
1162 {1, 2000},
1163 {2, 6000},
1164 {3, 10000},
1165 {3, 16000},
1166 }, // 5 bands, missing band
1167 {
1168 {0, 900},
1169 {1, 8000},
1170 {2, 4000},
1171 {3, 12000},
1172 }, // 4 bands, cutoff freq not increasing
1173 {
1174 {0, 450},
1175 {1, 2000},
1176 {7, 6000},
1177 {3, 10000},
1178 {4, 16000},
1179 }, // bad band index
1180 {
1181 {0, 1},
1182 {1, 8000},
1183 }, // too low cutoff freq
1184 {
1185 {0, 1200},
1186 {1, 80000},
1187 }, // too high cutoff freq
1188};
1189
1190INSTANTIATE_TEST_SUITE_P(
1191 DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
Ram Mohanafdf90b2023-03-23 08:48:25 +05301192 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1193 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +00001194 testing::Values(-1, 0, 10), // channel index
1195 testing::ValuesIn(kBands), // band index, cut off frequencies
Shunkai Yaof137ba42024-04-11 17:11:03 +00001196 testing::Values(-3.14f, 3.14f) // gain
1197 ),
Ram Mohane4064ce2022-12-20 18:05:14 +05301198 [](const auto& info) {
1199 auto descriptor = std::get<EQ_BAND_INSTANCE_NAME>(info.param).second;
1200 std::vector<DynamicsProcessing::EqBandConfig> cfgs;
1201 fillEqBandConfig(cfgs, info.param);
Ram Mohane4064ce2022-12-20 18:05:14 +05301202 std::string bands = ::android::internal::ToString(cfgs);
Ram Mohane4064ce2022-12-20 18:05:14 +05301203 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1204 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001205 toString(descriptor.common.id.uuid) + "_bands_" + bands;
Ram Mohane4064ce2022-12-20 18:05:14 +05301206 std::replace_if(
1207 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1208 return name;
1209 });
1210GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEqBandConfig);
1211
Sneha Patil2da23d72025-02-25 10:54:18 +00001212class DynamicsProcessingEqBandConfigDataTest
1213 : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
1214 public DynamicsProcessingTestHelper {
1215 public:
1216 DynamicsProcessingEqBandConfigDataTest()
1217 : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
1218 mInput.resize(kFrameCount * mChannelCount);
1219 mBinOffsets.resize(mMultitoneTestFrequencies.size());
1220 }
1221
1222 void SetUp() override {
1223 ASSERT_NO_FATAL_FAILURE(
1224 setUpDataTest(mMultitoneTestFrequencies, kSineMultitoneFullScaleDb));
1225 }
1226
1227 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1228
1229 void addEqParam(bool isPreEq) {
1230 createChannelConfig();
1231 auto stage = isPreEq ? mEngineConfigPreset.preEqStage : mEngineConfigPreset.postEqStage;
1232 stage.bandCount = mCfgs.size();
1233 addEngineConfig(mEngineConfigPreset);
1234 isPreEq ? addPreEqChannelConfig(mChannelConfig) : addPostEqChannelConfig(mChannelConfig);
1235 isPreEq ? addPreEqBandConfigs(mCfgs) : addPostEqBandConfigs(mCfgs);
1236 }
1237
1238 void setEqParamAndProcess(std::vector<float>& output, bool isPreEq) {
1239 addEqParam(isPreEq);
1240 ASSERT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
1241 }
1242
1243 void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs, int channelIndex,
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001244 int bandIndex, int cutOffFreqHz, float gainDb, bool enable) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001245 cfgs.push_back(creatEqBandConfig(channelIndex, bandIndex, static_cast<float>(cutOffFreqHz),
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001246 gainDb, enable));
Sneha Patil2da23d72025-02-25 10:54:18 +00001247 }
1248
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001249 void validateOutput(const std::vector<float>& output, float gainDb, size_t bandIndex,
1250 bool enable) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001251 std::vector<float> outputMag(mBinOffsets.size());
1252 EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001253 if (gainDb == 0 || !enable) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001254 EXPECT_NO_FATAL_FAILURE(checkInputAndOutputEquality(outputMag));
1255 } else if (gainDb > 0) {
1256 // For positive gain, current band's magnitude is greater than the other band's
1257 // magnitude
1258 EXPECT_GT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
1259 } else {
1260 // For negative gain, current band's magnitude is less than the other band's magnitude
1261 EXPECT_LT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
1262 }
1263 }
1264
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001265 void analyseMultiBandOutput(float gainDb, bool isPreEq, bool enable = true) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001266 std::vector<float> output(mInput.size());
1267 roundToFreqCenteredToFftBin(mMultitoneTestFrequencies, mBinOffsets, kBinWidth);
1268 // Set Equalizer values for two bands
1269 for (size_t i = 0; i < kCutoffFreqHz.size(); i++) {
1270 for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001271 fillEqBandConfig(mCfgs, channelIndex, i, kCutoffFreqHz[i], gainDb, enable);
1272 fillEqBandConfig(mCfgs, channelIndex, i ^ 1, kCutoffFreqHz[i ^ 1], 0, enable);
Sneha Patil2da23d72025-02-25 10:54:18 +00001273 }
1274 ASSERT_NO_FATAL_FAILURE(setEqParamAndProcess(output, isPreEq));
1275
1276 if (isAllParamsValid()) {
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001277 ASSERT_NO_FATAL_FAILURE(validateOutput(output, gainDb, i, enable));
Sneha Patil2da23d72025-02-25 10:54:18 +00001278 }
1279 cleanUpEqConfig();
1280 }
1281 }
1282
1283 void cleanUpEqConfig() {
1284 CleanUp();
1285 mCfgs.clear();
1286 mChannelConfig.clear();
1287 }
1288
1289 const std::vector<float> kTestGainDbValues = {-200, -100, 0, 100, 200};
1290 std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
1291};
1292
1293TEST_P(DynamicsProcessingEqBandConfigDataTest, IncreasingPreEqGain) {
1294 for (float gainDb : kTestGainDbValues) {
1295 ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
1296 dBToAmplitude(gainDb), kSamplingFrequency,
1297 mChannelLayout));
1298 cleanUpEqConfig();
1299 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(gainDb, true /*pre-equalizer*/));
1300 }
1301}
1302
1303TEST_P(DynamicsProcessingEqBandConfigDataTest, IncreasingPostEqGain) {
1304 for (float gainDb : kTestGainDbValues) {
1305 ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
1306 dBToAmplitude(gainDb), kSamplingFrequency,
1307 mChannelLayout));
1308 cleanUpEqConfig();
1309 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(gainDb, false /*post-equalizer*/));
1310 }
1311}
1312
Sneha Patil4d8a91c2025-03-03 08:03:43 +00001313TEST_P(DynamicsProcessingEqBandConfigDataTest, PreEqEnableDisable) {
1314 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(10 /*gain dB*/, true /*pre-equalizer*/,
1315 false /*disable equalizer*/));
1316}
1317
1318TEST_P(DynamicsProcessingEqBandConfigDataTest, PostEqEnableDisable) {
1319 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(10 /*gain dB*/, false /*post-equalizer*/,
1320 false /*disable equalizer*/));
1321}
1322
Sneha Patil2da23d72025-02-25 10:54:18 +00001323INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingEqBandConfigDataTest,
1324 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1325 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1326 [](const auto& info) {
1327 auto descriptor = info.param;
1328 std::string name = getPrefix(descriptor.second);
1329 std::replace_if(
1330 name.begin(), name.end(),
1331 [](const char c) { return !std::isalnum(c); }, '_');
1332 return name;
1333 });
1334GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingEqBandConfigDataTest);
1335
Ram Mohane4064ce2022-12-20 18:05:14 +05301336/**
1337 * Test DynamicsProcessing MbcBandConfig
1338 */
1339
1340enum MbcBandConfigParamName {
1341 MBC_BAND_INSTANCE_NAME,
1342 MBC_BAND_CHANNEL,
Ram Mohane4064ce2022-12-20 18:05:14 +05301343 MBC_BAND_CUTOFF_FREQ,
Ram Mohane4064ce2022-12-20 18:05:14 +05301344 MBC_BAND_ADDITIONAL
1345};
1346enum MbcBandConfigAdditional {
1347 MBC_ADD_ATTACK_TIME,
1348 MBC_ADD_RELEASE_TIME,
1349 MBC_ADD_RATIO,
1350 MBC_ADD_THRESHOLD,
1351 MBC_ADD_KNEE_WIDTH,
1352 MBC_ADD_NOISE_GATE_THRESHOLD,
1353 MBC_ADD_EXPENDER_RATIO,
1354 MBC_ADD_PRE_GAIN,
1355 MBC_ADD_POST_GAIN,
1356 MBC_ADD_MAX_NUM
1357};
1358using TestParamsMbcBandConfigAdditional = std::array<float, MBC_ADD_MAX_NUM>;
1359
Ram Mohanafdf90b2023-03-23 08:48:25 +05301360// attackTime, releaseTime, ratio, thresh, kneeWidth, noise, expander, preGain, postGain
Ram Mohane4064ce2022-12-20 18:05:14 +05301361static constexpr std::array<TestParamsMbcBandConfigAdditional, 4> kMbcBandConfigAdditionalParam = {
1362 {{-3, -10, -2, -2, -5, -90, -2.5, -2, -2},
1363 {0, 0, 0, 0, 0, 0, 0, 0, 0},
1364 {-3, 10, -2, 2, -5, 90, -2.5, 2, -2},
Ram Mohanafdf90b2023-03-23 08:48:25 +05301365 {3, 10, 2, -2, -5, 90, 2.5, 2, 2}}};
Ram Mohane4064ce2022-12-20 18:05:14 +05301366
1367using TestParamsMbcBandConfig =
Sneha Patilabc94642024-11-13 08:41:05 +00001368 std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
Shunkai Yaof137ba42024-04-11 17:11:03 +00001369 std::vector<std::pair<int, float>>, TestParamsMbcBandConfigAdditional>;
Ram Mohane4064ce2022-12-20 18:05:14 +05301370
1371void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
1372 const TestParamsMbcBandConfig& params) {
Sneha Patilc3252762024-11-21 10:51:46 +00001373 const auto& cutOffFreqs = std::get<MBC_BAND_CUTOFF_FREQ>(params);
1374 const auto& additional = std::get<MBC_BAND_ADDITIONAL>(params);
1375
1376 cfgs.resize(cutOffFreqs.size());
1377
1378 for (size_t i = 0; i < cutOffFreqs.size(); ++i) {
1379 cfgs[i] = createMbcBandConfig(std::get<MBC_BAND_CHANNEL>(params),
1380 cutOffFreqs[i].first, // band channel
1381 cutOffFreqs[i].second, // band cutoff frequency
1382 additional[MBC_ADD_ATTACK_TIME],
1383 additional[MBC_ADD_RELEASE_TIME], additional[MBC_ADD_RATIO],
1384 additional[MBC_ADD_THRESHOLD], additional[MBC_ADD_KNEE_WIDTH],
1385 additional[MBC_ADD_NOISE_GATE_THRESHOLD],
1386 additional[MBC_ADD_EXPENDER_RATIO],
1387 additional[MBC_ADD_PRE_GAIN], additional[MBC_ADD_POST_GAIN]);
Ram Mohane4064ce2022-12-20 18:05:14 +05301388 }
1389}
1390
1391class DynamicsProcessingTestMbcBandConfig
1392 : public ::testing::TestWithParam<TestParamsMbcBandConfig>,
1393 public DynamicsProcessingTestHelper {
1394 public:
1395 DynamicsProcessingTestMbcBandConfig()
Shunkai Yaof137ba42024-04-11 17:11:03 +00001396 : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301397 fillMbcBandConfig(mCfgs, GetParam());
1398 }
1399
Aayush Soni63d6e2a2025-03-04 13:37:28 +00001400 void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpDynamicsProcessingEffect()); }
Ram Mohane4064ce2022-12-20 18:05:14 +05301401
1402 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1403
1404 std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
Ram Mohane4064ce2022-12-20 18:05:14 +05301405};
1406
1407TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
Ram Mohane4064ce2022-12-20 18:05:14 +05301408 mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
Sneha Patil3587ae52025-01-06 05:59:08 +00001409 addEngineConfig(mEngineConfigPreset);
Ram Mohanafdf90b2023-03-23 08:48:25 +05301410 std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1411 for (int i = 0; i < mChannelCount; i++) {
1412 cfgs[i].channel = i;
1413 cfgs[i].enable = true;
1414 }
Sneha Patil3587ae52025-01-06 05:59:08 +00001415 addMbcChannelConfig(cfgs);
1416 addMbcBandConfigs(mCfgs);
Sneha Patilabc94642024-11-13 08:41:05 +00001417 ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
Ram Mohane4064ce2022-12-20 18:05:14 +05301418}
1419
1420INSTANTIATE_TEST_SUITE_P(
1421 DynamicsProcessingTest, DynamicsProcessingTestMbcBandConfig,
Ram Mohanafdf90b2023-03-23 08:48:25 +05301422 ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1423 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
Sneha Patilabc94642024-11-13 08:41:05 +00001424 testing::Values(-1, 0, 10), // channel index
1425 testing::ValuesIn(kBands), // band index, cut off frequencies
Ram Mohanafdf90b2023-03-23 08:48:25 +05301426 testing::ValuesIn(kMbcBandConfigAdditionalParam)), // Additional
Ram Mohane4064ce2022-12-20 18:05:14 +05301427 [](const auto& info) {
1428 auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
1429 std::vector<DynamicsProcessing::MbcBandConfig> cfgs;
1430 fillMbcBandConfig(cfgs, info.param);
Ram Mohane4064ce2022-12-20 18:05:14 +05301431 std::string mbcBands = ::android::internal::ToString(cfgs);
Ram Mohane4064ce2022-12-20 18:05:14 +05301432 std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1433 descriptor.common.name + "_UUID_" +
Shunkai Yaof137ba42024-04-11 17:11:03 +00001434 toString(descriptor.common.id.uuid) + "_bands_" + mbcBands;
Ram Mohane4064ce2022-12-20 18:05:14 +05301435 std::replace_if(
1436 name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1437 return name;
1438 });
1439GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestMbcBandConfig);
1440
Sneha Patilc3252762024-11-21 10:51:46 +00001441class DynamicsProcessingMbcBandConfigDataTest
1442 : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
1443 public DynamicsProcessingTestHelper {
1444 public:
1445 DynamicsProcessingMbcBandConfigDataTest()
1446 : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
1447 mInput.resize(kFrameCount * mChannelCount);
Sneha Patil2da23d72025-02-25 10:54:18 +00001448 mBinOffsets.resize(mMultitoneTestFrequencies.size());
Sneha Patilc3252762024-11-21 10:51:46 +00001449 }
1450
1451 void SetUp() override {
Sneha Patil2da23d72025-02-25 10:54:18 +00001452 ASSERT_NO_FATAL_FAILURE(
1453 setUpDataTest(mMultitoneTestFrequencies, kSineMultitoneFullScaleDb));
Sneha Patilc3252762024-11-21 10:51:46 +00001454 }
1455
1456 void TearDown() override { TearDownDynamicsProcessingEffect(); }
1457
1458 void setMbcParamsAndProcess(std::vector<float>& output) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001459 createChannelConfig();
Sneha Patilc3252762024-11-21 10:51:46 +00001460 mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
1461 addEngineConfig(mEngineConfigPreset);
1462 addMbcChannelConfig(mChannelConfig);
1463 addMbcBandConfigs(mCfgs);
Sneha Patil903c6202025-01-30 06:37:10 +00001464 ASSERT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
Sneha Patilc3252762024-11-21 10:51:46 +00001465 }
1466
1467 void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs, int channelIndex,
1468 float threshold, float ratio, float noiseGate, float expanderRatio,
Sneha Patil7ba121b2025-01-22 09:19:39 +00001469 int bandIndex, int cutoffFreqHz, float preGain, float postGain) {
1470 cfgs.push_back(createMbcBandConfig(channelIndex, bandIndex,
1471 static_cast<float>(cutoffFreqHz), kDefaultAttackTime,
1472 kDefaultReleaseTime, ratio, threshold, kDefaultKneeWidth,
1473 noiseGate, expanderRatio, preGain, postGain));
Sneha Patilc3252762024-11-21 10:51:46 +00001474 }
1475
Sneha Patilc3252762024-11-21 10:51:46 +00001476 void validateOutput(const std::vector<float>& output, float threshold, float ratio,
1477 size_t bandIndex) {
Sneha Patilc3252762024-11-21 10:51:46 +00001478 std::vector<float> outputMag(mBinOffsets.size());
1479 EXPECT_NO_FATAL_FAILURE(getMagnitudeValue(output, outputMag));
Sneha Patil7ba121b2025-01-22 09:19:39 +00001480 if (threshold >= mInputDb || ratio == 1) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001481 EXPECT_NO_FATAL_FAILURE(checkInputAndOutputEquality(outputMag));
Sneha Patilc3252762024-11-21 10:51:46 +00001482 } else {
1483 // Current band's magnitude is less than the other band's magnitude
1484 EXPECT_LT(outputMag[bandIndex], outputMag[bandIndex ^ 1]);
1485 }
1486 }
1487
1488 void analyseMultiBandOutput(float threshold, float ratio) {
1489 std::vector<float> output(mInput.size());
Sneha Patil2da23d72025-02-25 10:54:18 +00001490 roundToFreqCenteredToFftBin(mMultitoneTestFrequencies, mBinOffsets, kBinWidth);
Sneha Patilc3252762024-11-21 10:51:46 +00001491 // Set MBC values for two bands
Sneha Patil2da23d72025-02-25 10:54:18 +00001492 for (size_t i = 0; i < kCutoffFreqHz.size(); i++) {
Sneha Patilc3252762024-11-21 10:51:46 +00001493 for (int channelIndex = 0; channelIndex < mChannelCount; channelIndex++) {
1494 fillMbcBandConfig(mCfgs, channelIndex, threshold, ratio, kDefaultNoiseGateDb,
Sneha Patil2da23d72025-02-25 10:54:18 +00001495 kDefaultExpanderRatio, i, kCutoffFreqHz[i], kDefaultPreGainDb,
Sneha Patil7ba121b2025-01-22 09:19:39 +00001496 kDefaultPostGainDb);
Sneha Patilc3252762024-11-21 10:51:46 +00001497 fillMbcBandConfig(mCfgs, channelIndex, kDefaultThresholdDb, kDefaultRatio,
1498 kDefaultNoiseGateDb, kDefaultExpanderRatio, i ^ 1,
Sneha Patil2da23d72025-02-25 10:54:18 +00001499 kCutoffFreqHz[i ^ 1], kDefaultPreGainDb, kDefaultPostGainDb);
Sneha Patilc3252762024-11-21 10:51:46 +00001500 }
1501 ASSERT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
1502
1503 if (isAllParamsValid()) {
1504 ASSERT_NO_FATAL_FAILURE(validateOutput(output, threshold, ratio, i));
1505 }
1506 cleanUpMbcConfig();
1507 }
1508 }
1509
1510 void cleanUpMbcConfig() {
1511 CleanUp();
1512 mCfgs.clear();
1513 mChannelConfig.clear();
1514 }
1515
Sneha Patilc3252762024-11-21 10:51:46 +00001516 static constexpr float kDefaultPostGainDb = 0;
1517 static constexpr float kDefaultPreGainDb = 0;
1518 static constexpr float kDefaultAttackTime = 0;
1519 static constexpr float kDefaultReleaseTime = 0;
1520 static constexpr float kDefaultKneeWidth = 0;
1521 static constexpr float kDefaultThresholdDb = 0;
1522 static constexpr float kDefaultNoiseGateDb = -10;
1523 static constexpr float kDefaultExpanderRatio = 1;
1524 static constexpr float kDefaultRatio = 1;
Sneha Patilc3252762024-11-21 10:51:46 +00001525 std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
Sneha Patilc3252762024-11-21 10:51:46 +00001526};
1527
1528TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingThreshold) {
1529 float ratio = 20;
1530 std::vector<float> thresholdValues = {-200, -100, 0, 100, 200};
1531
1532 for (float threshold : thresholdValues) {
1533 cleanUpMbcConfig();
1534 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(threshold, ratio));
1535 }
1536}
1537
1538TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingRatio) {
1539 float threshold = -20;
1540 std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
1541
1542 for (float ratio : ratioValues) {
1543 cleanUpMbcConfig();
1544 ASSERT_NO_FATAL_FAILURE(analyseMultiBandOutput(threshold, ratio));
1545 }
1546}
1547
Sneha Patil7ba121b2025-01-22 09:19:39 +00001548TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingPostGain) {
1549 std::vector<float> postGainDbValues = {-55, -30, 0, 30, 55};
1550 std::vector<float> output(mInput.size());
1551 for (float postGainDb : postGainDbValues) {
Sneha Patil2da23d72025-02-25 10:54:18 +00001552 ASSERT_NO_FATAL_FAILURE(generateSineWave(mMultitoneTestFrequencies, mInput,
Sneha Patil903c6202025-01-30 06:37:10 +00001553 dBToAmplitude(postGainDb), kSamplingFrequency,
1554 mChannelLayout));
Sneha Patil7ba121b2025-01-22 09:19:39 +00001555 mInputDb = calculateDb(mInput);
Sneha Patil2da23d72025-02-25 10:54:18 +00001556 EXPECT_NEAR(mInputDb, kSineMultitoneFullScaleDb - postGainDb, kToleranceDb);
Sneha Patil7ba121b2025-01-22 09:19:39 +00001557 cleanUpMbcConfig();
1558 for (int i = 0; i < mChannelCount; i++) {
1559 fillMbcBandConfig(mCfgs, i, kDefaultThresholdDb, kDefaultRatio, kDefaultNoiseGateDb,
1560 kDefaultExpanderRatio, 0 /*band index*/, 2000 /*cutoffFrequency*/,
1561 kDefaultPreGainDb, postGainDb);
1562 }
1563 EXPECT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
1564 if (!isAllParamsValid()) {
1565 continue;
1566 }
1567 float outputDb = calculateDb(output, kStartIndex);
1568 EXPECT_NEAR(outputDb, mInputDb + postGainDb, kToleranceDb)
1569 << "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
1570 }
1571}
1572
Sneha Patilba665282025-02-06 08:37:48 +00001573TEST_P(DynamicsProcessingMbcBandConfigDataTest, IncreasingPreGain) {
1574 /*
1575 Depending on the pregain values, samples undergo either compression or expansion process.
1576 At -6 dB input,
1577 - Expansion is expected at -60 dB,
1578 - Compression at 10, 34 and 60 dB
1579 - No compression or expansion at -34, -10, -1 dB.
1580 */
1581 std::vector<float> preGainDbValues = {-60, -34, -10, -1, 10, 34, 60};
1582 std::vector<float> output(mInput.size());
1583 float thresholdDb = -7;
1584 float noiseGateDb = -40;
1585 std::vector<float> ratioValues = {1, 1.5, 2, 2.5, 3};
1586 for (float ratio : ratioValues) {
1587 for (float preGainDb : preGainDbValues) {
1588 float expectedOutputDb;
1589 float inputWithPreGain = mInputDb + preGainDb;
1590 if (inputWithPreGain > thresholdDb) {
1591 SCOPED_TRACE("Compressor ratio: " + std::to_string(ratio));
1592 expectedOutputDb =
1593 (inputWithPreGain - thresholdDb) / ratio + thresholdDb - preGainDb;
1594 } else if (inputWithPreGain < noiseGateDb) {
1595 SCOPED_TRACE("Expander ratio: " + std::to_string(ratio));
1596 expectedOutputDb =
1597 (inputWithPreGain - noiseGateDb) * ratio + noiseGateDb - preGainDb;
1598 } else {
1599 expectedOutputDb = mInputDb;
1600 }
1601 cleanUpMbcConfig();
1602 for (int i = 0; i < mChannelCount; i++) {
1603 fillMbcBandConfig(mCfgs, i, thresholdDb, ratio /*compressor ratio*/, noiseGateDb,
1604 ratio /*expander ratio*/, 0 /*band index*/,
1605 2000 /*cutoffFrequency*/, preGainDb, kDefaultPostGainDb);
1606 }
1607 EXPECT_NO_FATAL_FAILURE(setMbcParamsAndProcess(output));
1608 if (!isAllParamsValid()) {
1609 continue;
1610 }
1611 float outputDb = calculateDb(output, kStartIndex);
1612 EXPECT_NEAR(outputDb, expectedOutputDb, kToleranceDb)
1613 << "PreGain: " << preGainDb << ", OutputDb: " << outputDb;
1614 }
1615 }
1616}
1617
Sneha Patilc3252762024-11-21 10:51:46 +00001618INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingMbcBandConfigDataTest,
1619 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1620 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1621 [](const auto& info) {
1622 auto descriptor = info.param;
1623 std::string name = getPrefix(descriptor.second);
1624 std::replace_if(
1625 name.begin(), name.end(),
1626 [](const char c) { return !std::isalnum(c); }, '_');
1627 return name;
1628 });
1629
1630GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingMbcBandConfigDataTest);
1631
Ram Mohane4064ce2022-12-20 18:05:14 +05301632int main(int argc, char** argv) {
1633 ::testing::InitGoogleTest(&argc, argv);
Jaideep Sharma74498412023-09-13 15:25:25 +05301634 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
Ram Mohane4064ce2022-12-20 18:05:14 +05301635 ABinderProcess_setThreadPoolMaxThreadCount(1);
1636 ABinderProcess_startThreadPool();
1637 return RUN_ALL_TESTS();
1638}