xref: /aosp_15_r20/hardware/interfaces/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
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 
17 #include <set>
18 #include <string>
19 #include <unordered_set>
20 
21 #define LOG_TAG "VtsHalDynamicsProcessingTest"
22 #include <android-base/logging.h>
23 #include <audio_utils/power.h>
24 #include <audio_utils/primitives.h>
25 
26 #include <Utils.h>
27 
28 #include "EffectHelper.h"
29 #include "EffectRangeSpecific.h"
30 
31 using namespace android;
32 using namespace aidl::android::hardware::audio::effect::DynamicsProcessingRanges;
33 
34 using aidl::android::hardware::audio::effect::Descriptor;
35 using aidl::android::hardware::audio::effect::DynamicsProcessing;
36 using aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing;
37 using aidl::android::hardware::audio::effect::IEffect;
38 using aidl::android::hardware::audio::effect::IFactory;
39 using aidl::android::hardware::audio::effect::Parameter;
40 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
41 
42 /**
43  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
44  * VtsAudioEffectTargetTest.
45  */
46 class DynamicsProcessingTestHelper : public EffectHelper {
47   public:
DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>,Descriptor> pair,int32_t channelLayOut=AudioChannelLayout::LAYOUT_STEREO)48     DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair,
49                                  int32_t channelLayOut = AudioChannelLayout::LAYOUT_STEREO)
50         : mChannelLayout(channelLayOut),
51           mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
52                   AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout))) {
53         std::tie(mFactory, mDescriptor) = pair;
54     }
55 
56     // setup
SetUpDynamicsProcessingEffect()57     void SetUpDynamicsProcessingEffect() {
58         ASSERT_NE(nullptr, mFactory);
59         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
60         Parameter::Specific specific = getDefaultParamSpecific();
61         Parameter::Common common = createParamCommon(
62                 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
63                 kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
64                 kFrameCount /* oFrameCount */,
65                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout),
66                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
67         ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
68         ASSERT_NE(nullptr, mEffect);
69         mEngineConfigApplied = mEngineConfigPreset;
70     }
71 
getDefaultParamSpecific()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
TearDownDynamicsProcessingEffect()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
87     bool isParamEqual(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dpRef,
88                       const DynamicsProcessing& dpTest);
89     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 
101     template <typename T>
isChannelConfigValid(const std::vector<T> & cfgs)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 
114     // get set params and validate
115     void SetAndGetDynamicsProcessingParameters();
116 
117     bool isAllParamsValid();
118 
119     // enqueue test parameters
120     void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
121     void addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
122     void addPostEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
123     void addMbcChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
124     void addPreEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
125     void addPostEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
126     void addMbcBandConfigs(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs);
127     void addLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfg);
128     void addInputGain(const std::vector<DynamicsProcessing::InputGain>& inputGain);
129 
130     static constexpr float kPreferredProcessingDurationMs = 10.0f;
131     static constexpr int kBandCount = 5;
132     static constexpr int kSamplingFrequency = 44100;
133     static constexpr int kFrameCount = 2048;
134     std::shared_ptr<IFactory> mFactory;
135     std::shared_ptr<IEffect> mEffect;
136     Descriptor mDescriptor;
137     IEffect::OpenEffectReturn mOpenEffectReturn;
138     DynamicsProcessing::EngineArchitecture mEngineConfigApplied;
139     DynamicsProcessing::EngineArchitecture mEngineConfigPreset{
140             .resolutionPreference =
141                     DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
142             .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
143             .preEqStage = {.inUse = true, .bandCount = kBandCount},
144             .postEqStage = {.inUse = true, .bandCount = kBandCount},
145             .mbcStage = {.inUse = true, .bandCount = kBandCount},
146             .limiterInUse = true,
147     };
148 
149     std::unordered_set<int /* channelId */> mPreEqChannelEnable;
150     std::unordered_set<int /* channelId */> mPostEqChannelEnable;
151     std::unordered_set<int /* channelId */> mMbcChannelEnable;
152     std::unordered_set<int /* channelId */> mLimiterChannelEnable;
153     static const std::set<std::vector<DynamicsProcessing::ChannelConfig>> kChannelConfigTestSet;
154     static const std::set<DynamicsProcessing::StageEnablement> kStageEnablementTestSet;
155     static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
156 
157   private:
158     const int32_t mChannelLayout;
159     std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
160 
161   protected:
162     const int mChannelCount;
CleanUp()163     void CleanUp() {
164         mTags.clear();
165         mPreEqChannelEnable.clear();
166         mPostEqChannelEnable.clear();
167         mMbcChannelEnable.clear();
168         mLimiterChannelEnable.clear();
169     }
170 };
171 
172 // test value set for DynamicsProcessing::StageEnablement
173 const std::set<DynamicsProcessing::StageEnablement>
174         DynamicsProcessingTestHelper::kStageEnablementTestSet = {
175                 {.inUse = true, .bandCount = DynamicsProcessingTestHelper::kBandCount},
176                 {.inUse = true, .bandCount = 0},
177                 {.inUse = true, .bandCount = -1},
178                 {.inUse = false, .bandCount = 0},
179                 {.inUse = false, .bandCount = -1},
180                 {.inUse = false, .bandCount = DynamicsProcessingTestHelper::kBandCount}};
181 
182 // test value set for DynamicsProcessing::ChannelConfig
183 const std::set<std::vector<DynamicsProcessing::ChannelConfig>>
184         DynamicsProcessingTestHelper::kChannelConfigTestSet = {
185                 {{.channel = -1, .enable = false},
186                  {.channel = 0, .enable = true},
187                  {.channel = 1, .enable = false},
188                  {.channel = 2, .enable = true}},
189                 {{.channel = -1, .enable = false}, {.channel = 2, .enable = true}},
190                 {{.channel = 0, .enable = true}, {.channel = 1, .enable = true}}};
191 
192 // test value set for DynamicsProcessing::InputGain
193 const std::set<std::vector<DynamicsProcessing::InputGain>>
194         DynamicsProcessingTestHelper::kInputGainTestSet = {
195                 {{.channel = 0, .gainDb = 10.f},
196                  {.channel = 1, .gainDb = 0.f},
197                  {.channel = 2, .gainDb = -10.f}},
198                 {{.channel = -1, .gainDb = -10.f}, {.channel = -2, .gainDb = 10.f}},
199                 {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}},
200                 {{.channel = 0, .gainDb = 10.f}, {.channel = 1, .gainDb = -10.f}}};
201 
202 template <typename T>
isBandConfigValid(const std::vector<T> & cfgs,int bandCount)203 bool DynamicsProcessingTestHelper::isBandConfigValid(const std::vector<T>& cfgs, int bandCount) {
204     std::unordered_set<int> freqs;
205     for (auto cfg : cfgs) {
206         if (cfg.channel < 0 || cfg.channel >= mChannelCount) return false;
207         if (cfg.band < 0 || cfg.band >= bandCount) return false;
208         // duplicated band index
209         if (freqs.find(cfg.band) != freqs.end()) return false;
210         freqs.insert(cfg.band);
211     }
212     return true;
213 }
214 
isParamValid(const DynamicsProcessing::Tag & tag,const DynamicsProcessing & dp)215 bool DynamicsProcessingTestHelper::isParamValid(const DynamicsProcessing::Tag& tag,
216                                                 const DynamicsProcessing& dp) {
217     switch (tag) {
218         case DynamicsProcessing::preEq: {
219             return isChannelConfigValid(dp.get<DynamicsProcessing::preEq>());
220         }
221         case DynamicsProcessing::postEq: {
222             return isChannelConfigValid(dp.get<DynamicsProcessing::postEq>());
223         }
224         case DynamicsProcessing::mbc: {
225             return isChannelConfigValid(dp.get<DynamicsProcessing::mbc>());
226         }
227         case DynamicsProcessing::preEqBand: {
228             return isBandConfigValid(dp.get<DynamicsProcessing::preEqBand>(),
229                                      mEngineConfigApplied.preEqStage.bandCount);
230         }
231         case DynamicsProcessing::postEqBand: {
232             return isBandConfigValid(dp.get<DynamicsProcessing::postEqBand>(),
233                                      mEngineConfigApplied.postEqStage.bandCount);
234         }
235         case DynamicsProcessing::mbcBand: {
236             return isBandConfigValid(dp.get<DynamicsProcessing::mbcBand>(),
237                                      mEngineConfigApplied.mbcStage.bandCount);
238         }
239         case DynamicsProcessing::limiter: {
240             return isChannelConfigValid(dp.get<DynamicsProcessing::limiter>());
241         }
242         case DynamicsProcessing::inputGain: {
243             return isChannelConfigValid(dp.get<DynamicsProcessing::inputGain>());
244         }
245         default: {
246             return true;
247         }
248     }
249     return true;
250 }
251 
isParamEqual(const DynamicsProcessing::Tag & tag,const DynamicsProcessing & dpRef,const DynamicsProcessing & dpTest)252 bool DynamicsProcessingTestHelper::isParamEqual(const DynamicsProcessing::Tag& tag,
253                                                 const DynamicsProcessing& dpRef,
254                                                 const DynamicsProcessing& dpTest) {
255     switch (tag) {
256         case DynamicsProcessing::engineArchitecture: {
257             return isEngineConfigEqual(dpRef.get<DynamicsProcessing::engineArchitecture>(),
258                                        dpTest.get<DynamicsProcessing::engineArchitecture>());
259         }
260         case DynamicsProcessing::preEq: {
261             const auto& source = dpRef.get<DynamicsProcessing::preEq>();
262             const auto& target = dpTest.get<DynamicsProcessing::preEq>();
263             return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(source, target);
264         }
265         case DynamicsProcessing::postEq: {
266             return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
267                     dpRef.get<DynamicsProcessing::postEq>(),
268                     dpTest.get<DynamicsProcessing::postEq>());
269         }
270         case DynamicsProcessing::mbc: {
271             return isAidlVectorEqualAfterFilter<DynamicsProcessing::ChannelConfig>(
272                     dpRef.get<DynamicsProcessing::mbc>(), dpTest.get<DynamicsProcessing::mbc>());
273         }
274         case DynamicsProcessing::preEqBand: {
275             return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
276                     dpRef.get<DynamicsProcessing::preEqBand>(),
277                     dpTest.get<DynamicsProcessing::preEqBand>());
278         }
279         case DynamicsProcessing::postEqBand: {
280             return isAidlVectorEqualAfterFilter<DynamicsProcessing::EqBandConfig>(
281                     dpRef.get<DynamicsProcessing::postEqBand>(),
282                     dpTest.get<DynamicsProcessing::postEqBand>());
283         }
284         case DynamicsProcessing::mbcBand: {
285             return isAidlVectorEqualAfterFilter<DynamicsProcessing::MbcBandConfig>(
286                     dpRef.get<DynamicsProcessing::mbcBand>(),
287                     dpTest.get<DynamicsProcessing::mbcBand>());
288         }
289         case DynamicsProcessing::limiter: {
290             return isAidlVectorEqualAfterFilter<DynamicsProcessing::LimiterConfig>(
291                     dpRef.get<DynamicsProcessing::limiter>(),
292                     dpTest.get<DynamicsProcessing::limiter>());
293         }
294         case DynamicsProcessing::inputGain: {
295             return isAidlVectorEqual<DynamicsProcessing::InputGain>(
296                     dpRef.get<DynamicsProcessing::inputGain>(),
297                     dpTest.get<DynamicsProcessing::inputGain>());
298         }
299         case DynamicsProcessing::vendor: {
300             return false;
301         }
302     }
303 }
304 
isEngineConfigEqual(const DynamicsProcessing::EngineArchitecture & ref,const DynamicsProcessing::EngineArchitecture & test)305 bool DynamicsProcessingTestHelper::isEngineConfigEqual(
306         const DynamicsProcessing::EngineArchitecture& ref,
307         const DynamicsProcessing::EngineArchitecture& test) {
308     return ref == test;
309 }
310 
311 template <typename T>
filterEnabledVector(const std::vector<T> & vec)312 std::vector<T> DynamicsProcessingTestHelper::filterEnabledVector(const std::vector<T>& vec) {
313     std::vector<T> ret;
314     std::copy_if(vec.begin(), vec.end(), std::back_inserter(ret),
315                  [](const auto& v) { return v.enable; });
316     return ret;
317 }
318 
319 template <typename T>
isAidlVectorEqual(const std::vector<T> & source,const std::vector<T> & target)320 bool DynamicsProcessingTestHelper::isAidlVectorEqual(const std::vector<T>& source,
321                                                      const std::vector<T>& target) {
322     if (source.size() != target.size()) return false;
323 
324     auto tempS = source;
325     auto tempT = target;
326     std::sort(tempS.begin(), tempS.end());
327     std::sort(tempT.begin(), tempT.end());
328     return tempS == tempT;
329 }
330 
331 template <typename T>
isAidlVectorEqualAfterFilter(const std::vector<T> & source,const std::vector<T> & target)332 bool DynamicsProcessingTestHelper::isAidlVectorEqualAfterFilter(const std::vector<T>& source,
333                                                                 const std::vector<T>& target) {
334     return isAidlVectorEqual<T>(filterEnabledVector<T>(source), filterEnabledVector<T>(target));
335 }
336 
SetAndGetDynamicsProcessingParameters()337 void DynamicsProcessingTestHelper::SetAndGetDynamicsProcessingParameters() {
338     for (const auto& [tag, dp] : mTags) {
339         // validate parameter
340         Descriptor desc;
341         ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
342         bool valid = isParamInRange(dp, desc.capability.range.get<Range::dynamicsProcessing>());
343         if (valid) valid = isParamValid(tag, dp);
344         const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
345 
346         // set parameter
347         Parameter expectParam;
348         Parameter::Specific specific;
349         specific.set<Parameter::Specific::dynamicsProcessing>(dp);
350         expectParam.set<Parameter::specific>(specific);
351         ASSERT_STATUS(expected, mEffect->setParameter(expectParam))
352                 << "\n"
353                 << expectParam.toString() << "\n"
354                 << desc.toString();
355 
356         // only get if parameter in range and set success
357         if (expected == EX_NONE) {
358             Parameter getParam;
359             Parameter::Id id;
360             DynamicsProcessing::Id dpId;
361             dpId.set<DynamicsProcessing::Id::commonTag>(tag);
362             id.set<Parameter::Id::dynamicsProcessingTag>(dpId);
363             // if set success, then get should match
364             EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
365             Parameter::Specific specificTest = getParam.get<Parameter::specific>();
366             const auto& target = specificTest.get<Parameter::Specific::dynamicsProcessing>();
367             EXPECT_TRUE(isParamEqual(tag, dp, target)) << dp.toString() << "\n"
368                                                        << target.toString();
369             // update mEngineConfigApplied after setting successfully
370             if (tag == DynamicsProcessing::engineArchitecture) {
371                 mEngineConfigApplied = target.get<DynamicsProcessing::engineArchitecture>();
372             }
373         }
374     }
375 }
376 
isAllParamsValid()377 bool DynamicsProcessingTestHelper::isAllParamsValid() {
378     if (mTags.empty()) {
379         return false;
380     }
381     for (const auto& [tag, dp] : mTags) {
382         // validate parameter
383         if (!isParamInRange(dp, mDescriptor.capability.range.get<Range::dynamicsProcessing>())) {
384             return false;
385         }
386         if (!isParamValid(tag, dp)) {
387             return false;
388         }
389     }
390     return true;
391 }
392 
addEngineConfig(const DynamicsProcessing::EngineArchitecture & cfg)393 void DynamicsProcessingTestHelper::addEngineConfig(
394         const DynamicsProcessing::EngineArchitecture& cfg) {
395     DynamicsProcessing dp;
396     dp.set<DynamicsProcessing::engineArchitecture>(cfg);
397     mTags.push_back({DynamicsProcessing::engineArchitecture, dp});
398 }
399 
addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig> & cfgs)400 void DynamicsProcessingTestHelper::addPreEqChannelConfig(
401         const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
402     DynamicsProcessing dp;
403     dp.set<DynamicsProcessing::preEq>(cfgs);
404     mTags.push_back({DynamicsProcessing::preEq, dp});
405     for (auto& cfg : cfgs) {
406         if (cfg.enable) mPreEqChannelEnable.insert(cfg.channel);
407     }
408 }
409 
addPostEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig> & cfgs)410 void DynamicsProcessingTestHelper::addPostEqChannelConfig(
411         const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
412     DynamicsProcessing dp;
413     dp.set<DynamicsProcessing::postEq>(cfgs);
414     mTags.push_back({DynamicsProcessing::postEq, dp});
415     for (auto& cfg : cfgs) {
416         if (cfg.enable) mPostEqChannelEnable.insert(cfg.channel);
417     }
418 }
419 
addMbcChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig> & cfgs)420 void DynamicsProcessingTestHelper::addMbcChannelConfig(
421         const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
422     DynamicsProcessing dp;
423     dp.set<DynamicsProcessing::mbc>(cfgs);
424     mTags.push_back({DynamicsProcessing::mbc, dp});
425     for (auto& cfg : cfgs) {
426         if (cfg.enable) mMbcChannelEnable.insert(cfg.channel);
427     }
428 }
429 
addPreEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig> & cfgs)430 void DynamicsProcessingTestHelper::addPreEqBandConfigs(
431         const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
432     DynamicsProcessing dp;
433     dp.set<DynamicsProcessing::preEqBand>(cfgs);
434     mTags.push_back({DynamicsProcessing::preEqBand, dp});
435 }
436 
addPostEqBandConfigs(const std::vector<DynamicsProcessing::EqBandConfig> & cfgs)437 void DynamicsProcessingTestHelper::addPostEqBandConfigs(
438         const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
439     DynamicsProcessing dp;
440     dp.set<DynamicsProcessing::postEqBand>(cfgs);
441     mTags.push_back({DynamicsProcessing::postEqBand, dp});
442 }
443 
addMbcBandConfigs(const std::vector<DynamicsProcessing::MbcBandConfig> & cfgs)444 void DynamicsProcessingTestHelper::addMbcBandConfigs(
445         const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
446     DynamicsProcessing dp;
447     dp.set<DynamicsProcessing::mbcBand>(cfgs);
448     mTags.push_back({DynamicsProcessing::mbcBand, dp});
449 }
450 
addLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig> & cfgs)451 void DynamicsProcessingTestHelper::addLimiterConfig(
452         const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
453     DynamicsProcessing dp;
454     dp.set<DynamicsProcessing::limiter>(cfgs);
455     mTags.push_back({DynamicsProcessing::limiter, dp});
456     for (auto& cfg : cfgs) {
457         if (cfg.enable) mLimiterChannelEnable.insert(cfg.channel);
458     }
459 }
460 
addInputGain(const std::vector<DynamicsProcessing::InputGain> & inputGains)461 void DynamicsProcessingTestHelper::addInputGain(
462         const std::vector<DynamicsProcessing::InputGain>& inputGains) {
463     DynamicsProcessing dp;
464     dp.set<DynamicsProcessing::inputGain>(inputGains);
465     mTags.push_back({DynamicsProcessing::inputGain, dp});
466 }
467 
fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig> & limiterConfigList,int channelIndex,bool enable,int linkGroup,float attackTime,float releaseTime,float ratio,float threshold,float postGain)468 void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& limiterConfigList,
469                        int channelIndex, bool enable, int linkGroup, float attackTime,
470                        float releaseTime, float ratio, float threshold, float postGain) {
471     DynamicsProcessing::LimiterConfig cfg;
472     cfg.channel = channelIndex;
473     cfg.enable = enable;
474     cfg.linkGroup = linkGroup;
475     cfg.attackTimeMs = attackTime;
476     cfg.releaseTimeMs = releaseTime;
477     cfg.ratio = ratio;
478     cfg.thresholdDb = threshold;
479     cfg.postGainDb = postGain;
480     limiterConfigList.push_back(cfg);
481 }
482 
483 /**
484  * Test DynamicsProcessing Engine Configuration
485  */
486 enum EngineArchitectureTestParamName {
487     ENGINE_TEST_INSTANCE_NAME,
488     ENGINE_TEST_RESOLUTION_PREFERENCE,
489     ENGINE_TEST_PREFERRED_DURATION,
490     ENGINE_TEST_STAGE_ENABLEMENT
491 };
492 using EngineArchitectureTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
493                                                 DynamicsProcessing::ResolutionPreference, float,
494                                                 DynamicsProcessing::StageEnablement>;
495 
fillEngineArchConfig(DynamicsProcessing::EngineArchitecture & cfg,const EngineArchitectureTestParams & params)496 void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg,
497                           const EngineArchitectureTestParams& params) {
498     cfg.resolutionPreference = std::get<ENGINE_TEST_RESOLUTION_PREFERENCE>(params);
499     cfg.preferredProcessingDurationMs = std::get<ENGINE_TEST_PREFERRED_DURATION>(params);
500     cfg.preEqStage = cfg.postEqStage = cfg.mbcStage =
501             std::get<ENGINE_TEST_STAGE_ENABLEMENT>(params);
502     cfg.limiterInUse = true;
503 }
504 
505 class DynamicsProcessingTestEngineArchitecture
506     : public ::testing::TestWithParam<EngineArchitectureTestParams>,
507       public DynamicsProcessingTestHelper {
508   public:
DynamicsProcessingTestEngineArchitecture()509     DynamicsProcessingTestEngineArchitecture()
510         : DynamicsProcessingTestHelper(std::get<ENGINE_TEST_INSTANCE_NAME>(GetParam())) {
511         fillEngineArchConfig(mCfg, GetParam());
512     };
513 
SetUp()514     void SetUp() override { SetUpDynamicsProcessingEffect(); }
515 
TearDown()516     void TearDown() override { TearDownDynamicsProcessingEffect(); }
517 
518     DynamicsProcessing::EngineArchitecture mCfg;
519 };
520 
TEST_P(DynamicsProcessingTestEngineArchitecture,SetAndGetEngineArch)521 TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
522     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mCfg));
523     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
524 }
525 
526 INSTANTIATE_TEST_SUITE_P(
527         DynamicsProcessingTest, DynamicsProcessingTestEngineArchitecture,
528         ::testing::Combine(
529                 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
530                         IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
531                 testing::Values(
532                         DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
533                         DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
534                         static_cast<DynamicsProcessing::ResolutionPreference>(-1)),  // variant
535                 testing::Values(-10.f, 0.f, 10.f),  // processing duration
536                 testing::ValuesIn(
537                         DynamicsProcessingTestHelper::kStageEnablementTestSet)  // preEQ/postEQ/mbc
538                 ),
__anondf4c0d330302(const auto& info) 539         [](const auto& info) {
540             auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
541             DynamicsProcessing::EngineArchitecture cfg;
542             fillEngineArchConfig(cfg, info.param);
543             std::string name = getPrefix(descriptor) + "_Cfg_" + cfg.toString();
544             std::replace_if(
545                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
546             return name;
547         });
548 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEngineArchitecture);
549 
550 /**
551  * Test DynamicsProcessing Input Gain
552  */
553 enum InputGainTestParamName {
554     INPUT_GAIN_INSTANCE_NAME,
555     INPUT_GAIN_PARAM,
556 };
557 class DynamicsProcessingTestInputGain
558     : public ::testing::TestWithParam<std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
559                                                  std::vector<DynamicsProcessing::InputGain>>>,
560       public DynamicsProcessingTestHelper {
561   public:
DynamicsProcessingTestInputGain()562     DynamicsProcessingTestInputGain()
563         : DynamicsProcessingTestHelper(std::get<INPUT_GAIN_INSTANCE_NAME>(GetParam())),
564           mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())) {};
565 
SetUp()566     void SetUp() override { SetUpDynamicsProcessingEffect(); }
567 
TearDown()568     void TearDown() override { TearDownDynamicsProcessingEffect(); }
569 
570     const std::vector<DynamicsProcessing::InputGain> mInputGain;
571 };
572 
TEST_P(DynamicsProcessingTestInputGain,SetAndGetInputGain)573 TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
574     EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
575     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
576 }
577 
578 INSTANTIATE_TEST_SUITE_P(
579         DynamicsProcessingTest, DynamicsProcessingTestInputGain,
580         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
581                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
582                            testing::ValuesIn(DynamicsProcessingTestInputGain::kInputGainTestSet)),
__anondf4c0d330502(const auto& info) 583         [](const auto& info) {
584             auto descriptor = std::get<INPUT_GAIN_INSTANCE_NAME>(info.param).second;
585             std::string gains =
586                     ::android::internal::ToString(std::get<INPUT_GAIN_PARAM>(info.param));
587             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
588                                descriptor.common.name + "_UUID_" +
589                                toString(descriptor.common.id.uuid) + "_inputGains_" + gains;
590             std::replace_if(
591                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
592             return name;
593         });
594 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestInputGain);
595 
596 /**
597  * Test DynamicsProcessing Limiter Config
598  */
599 enum LimiterConfigTestParamName {
600     LIMITER_INSTANCE_NAME,
601     LIMITER_CHANNEL,
602     LIMITER_LINK_GROUP,
603     LIMITER_ATTACK_TIME,
604     LIMITER_RELEASE_TIME,
605     LIMITER_RATIO,
606     LIMITER_THRESHOLD,
607     LIMITER_POST_GAIN,
608 };
609 
610 using LimiterConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
611                                            int32_t, int32_t, float, float, float, float, float>;
612 
fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig> & cfg,const LimiterConfigTestParams & params)613 void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& cfg,
614                        const LimiterConfigTestParams& params) {
615     fillLimiterConfig(cfg, std::get<LIMITER_CHANNEL>(params), true,
616                       std::get<LIMITER_LINK_GROUP>(params), std::get<LIMITER_ATTACK_TIME>(params),
617                       std::get<LIMITER_RELEASE_TIME>(params), std::get<LIMITER_RATIO>(params),
618                       std::get<LIMITER_THRESHOLD>(params), std::get<LIMITER_POST_GAIN>(params));
619 }
620 
621 class DynamicsProcessingTestLimiterConfig
622     : public ::testing::TestWithParam<LimiterConfigTestParams>,
623       public DynamicsProcessingTestHelper {
624   public:
DynamicsProcessingTestLimiterConfig()625     DynamicsProcessingTestLimiterConfig()
626         : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())) {
627         fillLimiterConfig(mLimiterConfigList, GetParam());
628     }
629 
SetUp()630     void SetUp() override { SetUpDynamicsProcessingEffect(); }
631 
TearDown()632     void TearDown() override { TearDownDynamicsProcessingEffect(); }
633 
634     DynamicsProcessing::LimiterConfig mCfg;
635     std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
636 };
637 
TEST_P(DynamicsProcessingTestLimiterConfig,SetAndGetLimiterConfig)638 TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
639     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
640     EXPECT_NO_FATAL_FAILURE(addLimiterConfig(mLimiterConfigList));
641     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
642 }
643 
644 INSTANTIATE_TEST_SUITE_P(
645         DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
646         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
647                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
648                            testing::Values(-1, 0, 1, 2),  // channel index
649                            testing::Values(3),            // link group
650                            testing::Values(-1, 1),        // attackTime
651                            testing::Values(-60, 60),      // releaseTime
652                            testing::Values(-2.5, 2.5),    // ratio
653                            testing::Values(-2, 2),        // thresh
654                            testing::Values(-3.14, 3.14)   // postGain
655                            ),
__anondf4c0d330702(const auto& info) 656         [](const auto& info) {
657             auto descriptor = std::get<LIMITER_INSTANCE_NAME>(info.param).second;
658             std::vector<DynamicsProcessing::LimiterConfig> cfg;
659             fillLimiterConfig(cfg, info.param);
660             std::string name =
661                     "Implementer_" + getPrefix(descriptor) + "_limiterConfig_" + cfg[0].toString();
662             std::replace_if(
663                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
664             return name;
665         });
666 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfig);
667 
668 using LimiterConfigDataTestParams = std::pair<std::shared_ptr<IFactory>, Descriptor>;
669 
670 class DynamicsProcessingLimiterConfigDataTest
671     : public ::testing::TestWithParam<LimiterConfigDataTestParams>,
672       public DynamicsProcessingTestHelper {
673   public:
DynamicsProcessingLimiterConfigDataTest()674     DynamicsProcessingLimiterConfigDataTest()
675         : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
676         mBufferSize = kFrameCount * mChannelCount;
677         mInput.resize(mBufferSize);
678         generateSineWave(1000 /*Input Frequency*/, mInput);
679         mInputDb = calculateDb(mInput);
680     }
681 
SetUp()682     void SetUp() override {
683         SetUpDynamicsProcessingEffect();
684         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
685     }
686 
TearDown()687     void TearDown() override { TearDownDynamicsProcessingEffect(); }
688 
calculateDb(std::vector<float> input,size_t start=0)689     float calculateDb(std::vector<float> input, size_t start = 0) {
690         return audio_utils_compute_power_mono(input.data() + start, AUDIO_FORMAT_PCM_FLOAT,
691                                               input.size() - start);
692     }
693 
computeThreshold(float ratio,float outputDb,float & threshold)694     void computeThreshold(float ratio, float outputDb, float& threshold) {
695         EXPECT_NE(ratio, 0);
696         threshold = (mInputDb - (ratio * outputDb)) / (1 - ratio);
697     }
698 
computeRatio(float threshold,float outputDb,float & ratio)699     void computeRatio(float threshold, float outputDb, float& ratio) {
700         float inputOverThreshold = mInputDb - threshold;
701         float outputOverThreshold = outputDb - threshold;
702         EXPECT_NE(outputOverThreshold, 0);
703         ratio = inputOverThreshold / outputOverThreshold;
704     }
705 
setParamsAndProcess(std::vector<float> & output)706     void setParamsAndProcess(std::vector<float>& output) {
707         EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
708         EXPECT_NO_FATAL_FAILURE(addLimiterConfig(mLimiterConfigList));
709         ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
710         if (isAllParamsValid()) {
711             ASSERT_NO_FATAL_FAILURE(
712                     processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
713             EXPECT_GT(output.size(), kStartIndex);
714         }
715         cleanUpLimiterConfig();
716     }
717 
cleanUpLimiterConfig()718     void cleanUpLimiterConfig() {
719         CleanUp();
720         mLimiterConfigList.clear();
721     }
722     static constexpr float kDefaultLinkerGroup = 3;
723     static constexpr float kDefaultAttackTime = 0;
724     static constexpr float kDefaultReleaseTime = 0;
725     static constexpr float kDefaultRatio = 4;
726     static constexpr float kDefaultThreshold = 0;
727     static constexpr float kDefaultPostGain = 0;
728     static constexpr int kInputFrequency = 1000;
729     static constexpr size_t kStartIndex = 15 * kSamplingFrequency / 1000;  // skip 15ms
730     std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
731     std::vector<float> mInput;
732     float mInputDb;
733     int mBufferSize;
734 };
735 
TEST_P(DynamicsProcessingLimiterConfigDataTest,IncreasingThresholdDb)736 TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingThresholdDb) {
737     std::vector<float> thresholdValues = {-200, -150, -100, -50, -5, 0};
738     std::vector<float> output(mInput.size());
739     float previousThreshold = -FLT_MAX;
740     for (float threshold : thresholdValues) {
741         for (int i = 0; i < mChannelCount; i++) {
742             fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
743                               kDefaultReleaseTime, kDefaultRatio, threshold, kDefaultPostGain);
744         }
745         EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(output));
746         if (!isAllParamsValid()) {
747             continue;
748         }
749         float outputDb = calculateDb(output, kStartIndex);
750         if (threshold >= mInputDb || kDefaultRatio == 1) {
751             EXPECT_EQ(std::round(mInputDb), std::round(outputDb));
752         } else {
753             float calculatedThreshold = 0;
754             EXPECT_NO_FATAL_FAILURE(computeThreshold(kDefaultRatio, outputDb, calculatedThreshold));
755             ASSERT_GT(calculatedThreshold, previousThreshold);
756             previousThreshold = calculatedThreshold;
757         }
758     }
759 }
760 
TEST_P(DynamicsProcessingLimiterConfigDataTest,IncreasingRatio)761 TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingRatio) {
762     std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
763     std::vector<float> output(mInput.size());
764     float threshold = -10;
765     float previousRatio = 0;
766     for (float ratio : ratioValues) {
767         for (int i = 0; i < mChannelCount; i++) {
768             fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
769                               kDefaultReleaseTime, ratio, threshold, kDefaultPostGain);
770         }
771         EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(output));
772         if (!isAllParamsValid()) {
773             continue;
774         }
775         float outputDb = calculateDb(output, kStartIndex);
776 
777         if (threshold >= mInputDb) {
778             EXPECT_EQ(std::round(mInputDb), std::round(outputDb));
779         } else {
780             float calculatedRatio = 0;
781             EXPECT_NO_FATAL_FAILURE(computeRatio(threshold, outputDb, calculatedRatio));
782             ASSERT_GT(calculatedRatio, previousRatio);
783             previousRatio = calculatedRatio;
784         }
785     }
786 }
787 
TEST_P(DynamicsProcessingLimiterConfigDataTest,LimiterEnableDisable)788 TEST_P(DynamicsProcessingLimiterConfigDataTest, LimiterEnableDisable) {
789     std::vector<bool> limiterEnableValues = {false, true};
790     std::vector<float> output(mInput.size());
791     for (bool isEnabled : limiterEnableValues) {
792         for (int i = 0; i < mChannelCount; i++) {
793             // Set non-default values
794             fillLimiterConfig(mLimiterConfigList, i, isEnabled, kDefaultLinkerGroup,
795                               5 /*attack time*/, 5 /*release time*/, 10 /*ratio*/,
796                               -10 /*threshold*/, 5 /*postgain*/);
797         }
798         EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(output));
799         if (!isAllParamsValid()) {
800             continue;
801         }
802         if (isEnabled) {
803             EXPECT_NE(mInputDb, calculateDb(output, kStartIndex));
804         } else {
805             EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), 0.05);
806         }
807     }
808 }
809 
810 INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingLimiterConfigDataTest,
811                          testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
812                                  IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
__anondf4c0d330902(const auto& info) 813                          [](const auto& info) {
814                              auto descriptor = info.param;
815                              std::string name = getPrefix(descriptor.second);
816                              std::replace_if(
817                                      name.begin(), name.end(),
818                                      [](const char c) { return !std::isalnum(c); }, '_');
819                              return name;
820                          });
821 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingLimiterConfigDataTest);
822 
823 /**
824  * Test DynamicsProcessing ChannelConfig
825  */
826 enum ChannelConfigTestParamName {
827     BAND_CHANNEL_TEST_INSTANCE_NAME,
828     BAND_CHANNEL_TEST_CHANNEL_CONFIG
829 };
830 using ChannelConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
831                                            std::vector<DynamicsProcessing::ChannelConfig>>;
832 
833 class DynamicsProcessingTestChannelConfig
834     : public ::testing::TestWithParam<ChannelConfigTestParams>,
835       public DynamicsProcessingTestHelper {
836   public:
DynamicsProcessingTestChannelConfig()837     DynamicsProcessingTestChannelConfig()
838         : DynamicsProcessingTestHelper(std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(GetParam())),
839           mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())) {}
840 
SetUp()841     void SetUp() override { SetUpDynamicsProcessingEffect(); }
842 
TearDown()843     void TearDown() override { TearDownDynamicsProcessingEffect(); }
844 
845     std::vector<DynamicsProcessing::ChannelConfig> mCfg;
846 };
847 
TEST_P(DynamicsProcessingTestChannelConfig,SetAndGetPreEqChannelConfig)848 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
849     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
850     EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg));
851     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
852 }
853 
TEST_P(DynamicsProcessingTestChannelConfig,SetAndGetPostEqChannelConfig)854 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
855     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
856     EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg));
857     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
858 }
859 
TEST_P(DynamicsProcessingTestChannelConfig,SetAndGetMbcChannelConfig)860 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
861     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
862     EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg));
863     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
864 }
865 
866 INSTANTIATE_TEST_SUITE_P(
867         DynamicsProcessingTest, DynamicsProcessingTestChannelConfig,
868         ::testing::Combine(
869                 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
870                         IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
871                 testing::ValuesIn(
872                         DynamicsProcessingTestHelper::kChannelConfigTestSet)),  // channel config
__anondf4c0d330b02(const auto& info) 873         [](const auto& info) {
874             auto descriptor = std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(info.param).second;
875             std::string channelConfig = ::android::internal::ToString(
876                     std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(info.param));
877 
878             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
879                                descriptor.common.name + "_UUID_" +
880                                toString(descriptor.common.id.uuid) + "_" + channelConfig;
881             std::replace_if(
882                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
883             return name;
884         });
885 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestChannelConfig);
886 
887 /**
888  * Test DynamicsProcessing EqBandConfig
889  */
890 enum EqBandConfigTestParamName {
891     EQ_BAND_INSTANCE_NAME,
892     EQ_BAND_CHANNEL,
893     EQ_BAND_CUT_OFF_FREQ,
894     EQ_BAND_GAIN
895 };
896 using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
897                                           std::vector<std::pair<int, float>>, float>;
898 
fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig> & cfgs,const EqBandConfigTestParams & params)899 void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
900                       const EqBandConfigTestParams& params) {
901     const std::vector<std::pair<int, float>> cutOffFreqs = std::get<EQ_BAND_CUT_OFF_FREQ>(params);
902     int bandCount = cutOffFreqs.size();
903     cfgs.resize(bandCount);
904     for (int i = 0; i < bandCount; i++) {
905         cfgs[i].channel = std::get<EQ_BAND_CHANNEL>(params);
906         cfgs[i].band = cutOffFreqs[i].first;
907         cfgs[i].enable = true /*Eqband Enable*/;
908         cfgs[i].cutoffFrequencyHz = cutOffFreqs[i].second;
909         cfgs[i].gainDb = std::get<EQ_BAND_GAIN>(params);
910     }
911 }
912 
913 class DynamicsProcessingTestEqBandConfig : public ::testing::TestWithParam<EqBandConfigTestParams>,
914                                            public DynamicsProcessingTestHelper {
915   public:
DynamicsProcessingTestEqBandConfig()916     DynamicsProcessingTestEqBandConfig()
917         : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())) {
918         fillEqBandConfig(mCfgs, GetParam());
919     }
920 
SetUp()921     void SetUp() override { SetUpDynamicsProcessingEffect(); }
922 
TearDown()923     void TearDown() override { TearDownDynamicsProcessingEffect(); }
924 
925     std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
926 };
927 
TEST_P(DynamicsProcessingTestEqBandConfig,SetAndGetPreEqBandConfig)928 TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
929     mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
930     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
931     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
932     for (int i = 0; i < mChannelCount; i++) {
933         cfgs[i].channel = i;
934         cfgs[i].enable = true;
935     }
936     EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(cfgs));
937     EXPECT_NO_FATAL_FAILURE(addPreEqBandConfigs(mCfgs));
938     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
939 }
940 
TEST_P(DynamicsProcessingTestEqBandConfig,SetAndGetPostEqBandConfig)941 TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
942     mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
943     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
944     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
945     for (int i = 0; i < mChannelCount; i++) {
946         cfgs[i].channel = i;
947         cfgs[i].enable = true;
948     }
949     EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(cfgs));
950     EXPECT_NO_FATAL_FAILURE(addPostEqBandConfigs(mCfgs));
951     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
952 }
953 
954 std::vector<std::vector<std::pair<int, float>>> kBands{
955         {
956                 {0, 600},
957                 {1, 2000},
958                 {2, 6000},
959                 {3, 10000},
960                 {4, 16000},
961         },  // 5 bands
962         {
963                 {0, 800},
964                 {3, 15000},
965                 {2, 6000},
966                 {1, 2000},
967         },  // 4 bands, unsorted
968         {
969                 {0, 650},
970                 {1, 2000},
971                 {2, 6000},
972                 {3, 10000},
973                 {3, 16000},
974         },  // 5 bands, missing band
975         {
976                 {0, 900},
977                 {1, 8000},
978                 {2, 4000},
979                 {3, 12000},
980         },  // 4 bands, cutoff freq not increasing
981         {
982                 {0, 450},
983                 {1, 2000},
984                 {7, 6000},
985                 {3, 10000},
986                 {4, 16000},
987         },  // bad band index
988         {
989                 {0, 1},
990                 {1, 8000},
991         },  // too low cutoff freq
992         {
993                 {0, 1200},
994                 {1, 80000},
995         },  // too high cutoff freq
996 };
997 
998 INSTANTIATE_TEST_SUITE_P(
999         DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
1000         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1001                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1002                            testing::Values(-1, 0, 10),     // channel index
1003                            testing::ValuesIn(kBands),      // band index, cut off frequencies
1004                            testing::Values(-3.14f, 3.14f)  // gain
1005                            ),
__anondf4c0d330d02(const auto& info) 1006         [](const auto& info) {
1007             auto descriptor = std::get<EQ_BAND_INSTANCE_NAME>(info.param).second;
1008             std::vector<DynamicsProcessing::EqBandConfig> cfgs;
1009             fillEqBandConfig(cfgs, info.param);
1010             std::string bands = ::android::internal::ToString(cfgs);
1011             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1012                                descriptor.common.name + "_UUID_" +
1013                                toString(descriptor.common.id.uuid) + "_bands_" + bands;
1014             std::replace_if(
1015                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1016             return name;
1017         });
1018 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEqBandConfig);
1019 
1020 /**
1021  * Test DynamicsProcessing MbcBandConfig
1022  */
1023 
1024 enum MbcBandConfigParamName {
1025     MBC_BAND_INSTANCE_NAME,
1026     MBC_BAND_CHANNEL,
1027     MBC_BAND_CUTOFF_FREQ,
1028     MBC_BAND_ADDITIONAL
1029 };
1030 enum MbcBandConfigAdditional {
1031     MBC_ADD_ATTACK_TIME,
1032     MBC_ADD_RELEASE_TIME,
1033     MBC_ADD_RATIO,
1034     MBC_ADD_THRESHOLD,
1035     MBC_ADD_KNEE_WIDTH,
1036     MBC_ADD_NOISE_GATE_THRESHOLD,
1037     MBC_ADD_EXPENDER_RATIO,
1038     MBC_ADD_PRE_GAIN,
1039     MBC_ADD_POST_GAIN,
1040     MBC_ADD_MAX_NUM
1041 };
1042 using TestParamsMbcBandConfigAdditional = std::array<float, MBC_ADD_MAX_NUM>;
1043 
1044 // attackTime, releaseTime, ratio, thresh, kneeWidth, noise, expander, preGain, postGain
1045 static constexpr std::array<TestParamsMbcBandConfigAdditional, 4> kMbcBandConfigAdditionalParam = {
1046         {{-3, -10, -2, -2, -5, -90, -2.5, -2, -2},
1047          {0, 0, 0, 0, 0, 0, 0, 0, 0},
1048          {-3, 10, -2, 2, -5, 90, -2.5, 2, -2},
1049          {3, 10, 2, -2, -5, 90, 2.5, 2, 2}}};
1050 
1051 using TestParamsMbcBandConfig =
1052         std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
1053                    std::vector<std::pair<int, float>>, TestParamsMbcBandConfigAdditional>;
1054 
fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig> & cfgs,const TestParamsMbcBandConfig & params)1055 void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
1056                        const TestParamsMbcBandConfig& params) {
1057     const std::vector<std::pair<int, float>> cutOffFreqs = std::get<MBC_BAND_CUTOFF_FREQ>(params);
1058     const std::array<float, MBC_ADD_MAX_NUM> additional = std::get<MBC_BAND_ADDITIONAL>(params);
1059     int bandCount = cutOffFreqs.size();
1060     cfgs.resize(bandCount);
1061     for (int i = 0; i < bandCount; i++) {
1062         cfgs[i] = DynamicsProcessing::MbcBandConfig{
1063                 .channel = std::get<MBC_BAND_CHANNEL>(params),
1064                 .band = cutOffFreqs[i].first,
1065                 .enable = true /*Mbc Band Enable*/,
1066                 .cutoffFrequencyHz = cutOffFreqs[i].second,
1067                 .attackTimeMs = additional[MBC_ADD_ATTACK_TIME],
1068                 .releaseTimeMs = additional[MBC_ADD_RELEASE_TIME],
1069                 .ratio = additional[MBC_ADD_RATIO],
1070                 .thresholdDb = additional[MBC_ADD_THRESHOLD],
1071                 .kneeWidthDb = additional[MBC_ADD_KNEE_WIDTH],
1072                 .noiseGateThresholdDb = additional[MBC_ADD_NOISE_GATE_THRESHOLD],
1073                 .expanderRatio = additional[MBC_ADD_EXPENDER_RATIO],
1074                 .preGainDb = additional[MBC_ADD_PRE_GAIN],
1075                 .postGainDb = additional[MBC_ADD_POST_GAIN]};
1076     }
1077 }
1078 
1079 class DynamicsProcessingTestMbcBandConfig
1080     : public ::testing::TestWithParam<TestParamsMbcBandConfig>,
1081       public DynamicsProcessingTestHelper {
1082   public:
DynamicsProcessingTestMbcBandConfig()1083     DynamicsProcessingTestMbcBandConfig()
1084         : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())) {
1085         fillMbcBandConfig(mCfgs, GetParam());
1086     }
1087 
SetUp()1088     void SetUp() override { SetUpDynamicsProcessingEffect(); }
1089 
TearDown()1090     void TearDown() override { TearDownDynamicsProcessingEffect(); }
1091 
1092     std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
1093 };
1094 
TEST_P(DynamicsProcessingTestMbcBandConfig,SetAndGetMbcBandConfig)1095 TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
1096     mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
1097     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
1098     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
1099     for (int i = 0; i < mChannelCount; i++) {
1100         cfgs[i].channel = i;
1101         cfgs[i].enable = true;
1102     }
1103     EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(cfgs));
1104     EXPECT_NO_FATAL_FAILURE(addMbcBandConfigs(mCfgs));
1105     ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
1106 }
1107 
1108 INSTANTIATE_TEST_SUITE_P(
1109         DynamicsProcessingTest, DynamicsProcessingTestMbcBandConfig,
1110         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
1111                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
1112                            testing::Values(-1, 0, 10),  // channel index
1113                            testing::ValuesIn(kBands),   // band index, cut off frequencies
1114                            testing::ValuesIn(kMbcBandConfigAdditionalParam)),  // Additional
__anondf4c0d330f02(const auto& info) 1115         [](const auto& info) {
1116             auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
1117             std::vector<DynamicsProcessing::MbcBandConfig> cfgs;
1118             fillMbcBandConfig(cfgs, info.param);
1119             std::string mbcBands = ::android::internal::ToString(cfgs);
1120             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
1121                                descriptor.common.name + "_UUID_" +
1122                                toString(descriptor.common.id.uuid) + "_bands_" + mbcBands;
1123             std::replace_if(
1124                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
1125             return name;
1126         });
1127 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestMbcBandConfig);
1128 
main(int argc,char ** argv)1129 int main(int argc, char** argv) {
1130     ::testing::InitGoogleTest(&argc, argv);
1131     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
1132     ABinderProcess_setThreadPoolMaxThreadCount(1);
1133     ABinderProcess_startThreadPool();
1134     return RUN_ALL_TESTS();
1135 }
1136