blob: 7978cc53514d212b671e461e17b8cfa4c9cd4112 [file] [log] [blame]
Shunkai Yao725af212023-01-05 23:01:40 +00001/*
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#define LOG_TAG "AHAL_DPLibEffectsContext"
18
19#include "DynamicsProcessing.h"
20#include "DynamicsProcessingContext.h"
21
22#include <functional>
23#include <sys/param.h>
24#include <unordered_set>
25
26namespace aidl::android::hardware::audio::effect {
27
28DynamicsProcessingContext::DynamicsProcessingContext(int statusDepth,
29 const Parameter::Common& common)
30 : EffectContext(statusDepth, common) {
31 LOG(DEBUG) << __func__;
32 init();
33}
34
35DynamicsProcessingContext::~DynamicsProcessingContext() {
36 LOG(DEBUG) << __func__;
37}
38
39RetCode DynamicsProcessingContext::enable() {
40 std::lock_guard lg(mMutex);
41 if (mState != DYNAMICS_PROCESSING_STATE_INITIALIZED) {
42 return RetCode::ERROR_EFFECT_LIB_ERROR;
43 }
44 mState = DYNAMICS_PROCESSING_STATE_ACTIVE;
45 return RetCode::SUCCESS;
46}
47
48RetCode DynamicsProcessingContext::disable() {
49 std::lock_guard lg(mMutex);
50 if (mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
51 return RetCode::ERROR_EFFECT_LIB_ERROR;
52 }
53 mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
54 return RetCode::SUCCESS;
55}
56
57void DynamicsProcessingContext::reset() {
58 std::lock_guard lg(mMutex);
59 if (mDpFreq != nullptr) {
60 mDpFreq.reset();
61 }
62}
63
64RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
65 mCommon = common;
66 init();
67 return RetCode::SUCCESS;
68}
69
70void DynamicsProcessingContext::dpSetFreqDomainVariant_l(
71 const DynamicsProcessing::EngineArchitecture& engine) {
72 mDpFreq.reset(new dp_fx::DPFrequency());
73 mDpFreq->init(mChannelCount, engine.preEqStage.inUse, engine.preEqStage.bandCount,
74 engine.mbcStage.inUse, engine.mbcStage.bandCount, engine.postEqStage.inUse,
75 engine.postEqStage.bandCount, engine.limiterInUse);
76
77 int32_t sampleRate = mCommon.input.base.sampleRate;
78 int32_t minBlockSize = (int32_t)dp_fx::DPFrequency::getMinBockSize();
79 int32_t block = engine.preferredProcessingDurationMs * sampleRate / 1000.0f;
80 LOG(INFO) << __func__ << " sampleRate " << sampleRate << " block length "
81 << engine.preferredProcessingDurationMs << " ms (" << block << "samples)";
82 if (block < minBlockSize) {
83 block = minBlockSize;
84 } else if (!powerof2(block)) {
85 //find next highest power of 2.
86 block = 1 << (32 - __builtin_clz(block));
87 }
88 mDpFreq->configure(block, block >> 1, sampleRate);
89}
90
91RetCode DynamicsProcessingContext::setEngineArchitecture(
92 const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
93 RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
94 "illegalEngineConfig");
95
96 std::lock_guard lg(mMutex);
97 if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
98 if (engineArchitecture.resolutionPreference ==
99 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION) {
100 dpSetFreqDomainVariant_l(engineArchitecture);
101 } else {
102 LOG(WARNING) << __func__ << toString(engineArchitecture.resolutionPreference)
103 << " not available now";
104 }
105 mEngineInited = true;
106 mEngineArchitecture = engineArchitecture;
107 }
108 LOG(INFO) << __func__ << engineArchitecture.toString();
109 return RetCode::SUCCESS;
110}
111
112RetCode DynamicsProcessingContext::setPreEq(
113 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
114 std::lock_guard lg(mMutex);
115 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
116 StageType::PREEQ);
117}
118
119RetCode DynamicsProcessingContext::setPostEq(
120 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
121 std::lock_guard lg(mMutex);
122 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
123 StageType::POSTEQ);
124}
125
126RetCode DynamicsProcessingContext::setMbc(
127 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
128 std::lock_guard lg(mMutex);
129 return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
130 StageType::MBC);
131}
132
133RetCode DynamicsProcessingContext::setPreEqBand(
134 const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
135 std::lock_guard lg(mMutex);
136 RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
137 "postEqNotInUse");
138 return setBands_l<DynamicsProcessing::EqBandConfig>(
139 bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
140}
141
142RetCode DynamicsProcessingContext::setPostEqBand(
143 const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
144 std::lock_guard lg(mMutex);
145 RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
146 "postEqNotInUse");
147 return setBands_l<DynamicsProcessing::EqBandConfig>(
148 bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
149}
150
151RetCode DynamicsProcessingContext::setMbcBand(
152 const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
153 std::lock_guard lg(mMutex);
154 RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
155 "mbcNotInUse");
156 return setBands_l<DynamicsProcessing::MbcBandConfig>(
157 bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
158}
159
160RetCode DynamicsProcessingContext::setLimiter(
161 const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
162 std::lock_guard lg(mMutex);
163 RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
164 "limiterNotInUse");
165 return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
166}
167
168RetCode DynamicsProcessingContext::setInputGain(
169 const std::vector<DynamicsProcessing::InputGain>& inputGains) {
170 std::lock_guard lg(mMutex);
171 return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
172}
173
174DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
175 std::lock_guard lg(mMutex);
176 LOG(INFO) << __func__ << mEngineArchitecture.toString();
177 return mEngineArchitecture;
178}
179
180std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPreEq() {
181 return getChannelConfig(StageType::PREEQ);
182}
183
184std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPostEq() {
185 return getChannelConfig(StageType::POSTEQ);
186}
187
188std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPreEqBand() {
189 return getEqBandConfigs(StageType::PREEQ);
190}
191
192std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPostEqBand() {
193 return getEqBandConfigs(StageType::POSTEQ);
194}
195
196std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getMbc() {
197 return getChannelConfig(StageType::MBC);
198}
199
200std::vector<DynamicsProcessing::MbcBandConfig> DynamicsProcessingContext::getMbcBand() {
201 std::vector<DynamicsProcessing::MbcBandConfig> bands;
202
203 std::lock_guard lg(mMutex);
204 auto maxBand = mEngineArchitecture.mbcStage.bandCount;
205 for (int32_t ch = 0; ch < mChannelCount; ch++) {
206 auto mbc = getMbc_l(ch);
207 if (!mbc) {
208 continue;
209 }
210 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
211 auto band = mbc->getBand(bandId);
212 if (!band) {
213 continue;
214 }
215 bands.push_back({.channel = ch,
216 .band = bandId,
217 .enable = band->isEnabled(),
218 .cutoffFrequencyHz = band->getCutoffFrequency(),
219 .attackTimeMs = band->getAttackTime(),
220 .releaseTimeMs = band->getReleaseTime(),
221 .ratio = band->getRatio(),
222 .thresholdDb = band->getThreshold(),
223 .kneeWidthDb = band->getKneeWidth(),
224 .noiseGateThresholdDb = band->getNoiseGateThreshold(),
225 .expanderRatio = band->getExpanderRatio(),
226 .preGainDb = band->getPreGain(),
227 .postGainDb = band->getPostGain()});
228 }
229 }
230 return bands;
231}
232
233std::vector<DynamicsProcessing::LimiterConfig> DynamicsProcessingContext::getLimiter() {
234 std::vector<DynamicsProcessing::LimiterConfig> ret;
235
236 std::lock_guard lg(mMutex);
237 for (int32_t ch = 0; ch < mChannelCount; ch++) {
238 auto limiter = getLimiter_l(ch);
239 if (!limiter) {
240 continue;
241 }
242 ret.push_back({.channel = ch,
243 .enable = limiter->isEnabled(),
244 .linkGroup = static_cast<int32_t>(limiter->getLinkGroup()),
245 .attackTimeMs = limiter->getAttackTime(),
246 .releaseTimeMs = limiter->getReleaseTime(),
247 .ratio = limiter->getRatio(),
248 .thresholdDb = limiter->getThreshold(),
249 .postGainDb = limiter->getPostGain()});
250 }
251 return ret;
252}
253
254std::vector<DynamicsProcessing::InputGain> DynamicsProcessingContext::getInputGain() {
255 std::vector<DynamicsProcessing::InputGain> ret;
256
257 std::lock_guard lg(mMutex);
258 for (int32_t ch = 0; ch < mChannelCount; ch++) {
259 auto channel = getChannel_l(ch);
260 if (!channel) {
261 continue;
262 }
263 ret.push_back({.channel = ch, .gainDb = channel->getInputGain()});
264 }
265 return ret;
266}
267
268IEffect::Status DynamicsProcessingContext::lvmProcess(float* in, float* out, int samples) {
269 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
270
271 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
272 RETURN_VALUE_IF(!in, status, "nullInput");
273 RETURN_VALUE_IF(!out, status, "nullOutput");
274 status = {EX_ILLEGAL_STATE, 0, 0};
275
276 LOG(DEBUG) << __func__ << " start processing";
277 {
278 std::lock_guard lg(mMutex);
279 RETURN_VALUE_IF(mState != DynamicsProcessingState::DYNAMICS_PROCESSING_STATE_ACTIVE, status,
280 "notInActiveState");
281 RETURN_VALUE_IF(!mDpFreq, status, "engineNotInited");
282 mDpFreq->processSamples(in, out, samples);
283 }
284 return {STATUS_OK, samples, samples};
285}
286
287void DynamicsProcessingContext::init() {
288 std::lock_guard lg(mMutex);
289 mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
290 mChannelCount =
291 ::android::hardware::audio::common::getChannelCount(mCommon.input.base.channelMask);
292}
293
294dp_fx::DPChannel* DynamicsProcessingContext::getChannel_l(int channel) {
295 RETURN_VALUE_IF(mDpFreq == nullptr, nullptr, "DPFreqNotInited");
296
297 return mDpFreq->getChannel(channel);
298}
299
300dp_fx::DPEq* DynamicsProcessingContext::getPreEq_l(int ch) {
301 auto channel = getChannel_l(ch);
302 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
303
304 return channel->getPreEq();
305}
306
307dp_fx::DPEq* DynamicsProcessingContext::getPostEq_l(int ch) {
308 auto channel = getChannel_l(ch);
309 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
310
311 return channel->getPostEq();
312}
313
314dp_fx::DPMbc* DynamicsProcessingContext::getMbc_l(int ch) {
315 auto channel = getChannel_l(ch);
316 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
317
318 return channel->getMbc();
319}
320
321dp_fx::DPLimiter* DynamicsProcessingContext::getLimiter_l(int ch) {
322 auto channel = getChannel_l(ch);
323 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
324
325 return channel->getLimiter();
326}
327
328dp_fx::DPBandStage* DynamicsProcessingContext::getStageWithType_l(
329 DynamicsProcessingContext::StageType type, int ch) {
330 switch (type) {
331 case StageType::PREEQ: {
332 return getEqWithType_l(type, ch);
333 }
334 case StageType::POSTEQ: {
335 return getEqWithType_l(type, ch);
336 }
337 case StageType::MBC: {
338 return getMbc_l(ch);
339 }
340 case StageType::LIMITER:
341 FALLTHROUGH_INTENDED;
342 case StageType::INPUTGAIN: {
343 return nullptr;
344 }
345 }
346}
347
348dp_fx::DPEq* DynamicsProcessingContext::getEqWithType_l(DynamicsProcessingContext::StageType type,
349 int ch) {
350 switch (type) {
351 case StageType::PREEQ: {
352 return getPreEq_l(ch);
353 }
354 case StageType::POSTEQ: {
355 return getPostEq_l(ch);
356 }
357 case StageType::MBC:
358 FALLTHROUGH_INTENDED;
359 case StageType::LIMITER:
360 FALLTHROUGH_INTENDED;
361 case StageType::INPUTGAIN: {
362 return nullptr;
363 }
364 }
365}
366
367std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getChannelConfig(
368 StageType type) {
369 std::vector<DynamicsProcessing::ChannelConfig> ret;
370
371 std::lock_guard lg(mMutex);
372 for (int32_t ch = 0; ch < mChannelCount; ch++) {
373 auto stage = getStageWithType_l(type, ch);
374 if (!stage) {
375 continue;
376 }
377 ret.push_back({.channel = ch, .enable = stage->isEnabled()});
378 }
379 return ret;
380}
381
382std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getEqBandConfigs(
383 StageType type) {
384 std::vector<DynamicsProcessing::EqBandConfig> eqBands;
385
386 std::lock_guard lg(mMutex);
387 auto maxBand = mEngineArchitecture.preEqStage.bandCount;
388 for (int32_t ch = 0; ch < mChannelCount; ch++) {
389 auto eq = getEqWithType_l(type, ch);
390 if (!eq) {
391 continue;
392 }
393 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
394 auto band = eq->getBand(bandId);
395 if (!band) {
396 continue;
397 }
398 eqBands.push_back({.channel = ch,
399 .band = bandId,
400 .enable = band->isEnabled(),
401 .cutoffFrequencyHz = band->getCutoffFrequency(),
402 .gainDb = band->getGain()});
403 }
404 }
405 return eqBands;
406}
407
408/**
409 * When StageEnablement is in use, bandCount needs to be positive.
410 */
411bool DynamicsProcessingContext::validateStageEnablement(
412 const DynamicsProcessing::StageEnablement& enablement) {
413 return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
414}
415
416bool DynamicsProcessingContext::validateEngineConfig(
417 const DynamicsProcessing::EngineArchitecture& engine) {
418 return engine.preferredProcessingDurationMs >= 0 &&
419 validateStageEnablement(engine.preEqStage) &&
420 validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
421}
422
Shunkai Yao725af212023-01-05 23:01:40 +0000423bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
424 int maxChannel, int maxBand) {
Shunkai Yao6b857c92023-02-13 17:44:52 +0000425 return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
Shunkai Yao725af212023-01-05 23:01:40 +0000426}
427
428bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
429 int maxChannel, int maxBand) {
430 return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
Shunkai Yao6b857c92023-02-13 17:44:52 +0000431 validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
432 validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
433 validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
434 validateRatio(band.expanderRatio);
Shunkai Yao725af212023-01-05 23:01:40 +0000435}
436
437bool DynamicsProcessingContext::validateLimiterConfig(
438 const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
439 return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
440 validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
441 validateBandDb(limiter.thresholdDb);
442}
443
444bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
445 int maxChannel) {
446 return validateChannel(gain.channel, maxChannel);
447}
448
449template <typename D>
450RetCode DynamicsProcessingContext::setDpChannels_l(
451 const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
452 StageType type) {
453 RetCode ret = RetCode::SUCCESS;
454 std::unordered_set<int> channelSet;
455
456 RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
457 for (auto& it : channels) {
458 if (0 != channelSet.count(it.channel)) {
459 LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
460 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
461 } else {
462 channelSet.insert(it.channel);
463 }
464 if (it.channel < 0 || it.channel >= mChannelCount) {
465 LOG(WARNING) << __func__ << " skip illegal ChannelConfig " << it.toString() << " max "
466 << mChannelCount;
467 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
468 continue;
469 }
470 auto dp = getStageWithType_l(type, it.channel);
471 if (!dp) {
472 LOG(WARNING) << __func__ << " channel " << it.channel << " not exist";
473 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
474 continue;
475 }
476 if (dp->isEnabled() != it.enable) {
477 LOG(INFO) << __func__ << it.toString();
478 dp->setEnabled(it.enable);
479 }
480 }
481 return ret;
482}
483
484RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
485 int maxCh, int maxBand,
486 std::set<std::pair<int, int>>& chBandSet) {
487 RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
488 RetCode ret = RetCode::SUCCESS;
489 std::pair<int, int> chBandKey;
490 switch (type) {
491 case StageType::PREEQ:
492 FALLTHROUGH_INTENDED;
493 case StageType::POSTEQ: {
494 dp_fx::DPEq* dp;
495 const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
496 RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
497 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
498 RETURN_VALUE_IF(
499 nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
500 RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
501 dp_fx::DPEqBand band;
502 band.init(config.enable, config.cutoffFrequencyHz, config.gainDb);
503 dp->setBand(config.band, band);
504 chBandKey = {config.channel, config.band};
505 break;
506 }
507 case StageType::MBC: {
508 dp_fx::DPMbc* dp;
509 const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
510 RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
511 RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
512 RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
513 RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
514 dp_fx::DPMbcBand band;
515 band.init(config.enable, config.cutoffFrequencyHz, config.attackTimeMs,
516 config.releaseTimeMs, config.ratio, config.thresholdDb, config.kneeWidthDb,
517 config.noiseGateThresholdDb, config.expanderRatio, config.preGainDb,
518 config.postGainDb);
519 dp->setBand(config.band, band);
520 chBandKey = {config.channel, config.band};
521 break;
522 }
523 case StageType::LIMITER: {
524 dp_fx::DPChannel* dp;
525 const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
526 RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
527 RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
528 RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
529 RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
530 dp_fx::DPLimiter limiter;
531 limiter.init(mEngineArchitecture.limiterInUse, config.enable, config.linkGroup,
532 config.attackTimeMs, config.releaseTimeMs, config.ratio,
533 config.thresholdDb, config.postGainDb);
534 dp->setLimiter(limiter);
535 chBandKey = {config.channel, 0};
536 break;
537 }
538 case StageType::INPUTGAIN: {
539 dp_fx::DPChannel* dp;
540 const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
541 RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
542 RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
543 RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
544 RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
545 dp->setInputGain(config.gainDb);
546 chBandKey = {config.channel, 0};
547 break;
548 }
549 }
550 RETURN_VALUE_IF(0 != chBandSet.count(chBandKey), RetCode::ERROR_ILLEGAL_PARAMETER,
551 "duplicatedBand");
552 chBandSet.insert(chBandKey);
553 return ret;
554}
555
556template <typename T /* BandConfig */>
557RetCode DynamicsProcessingContext::setBands_l(
558 const std::vector<T>& bands, int maxBand, StageType type) {
559 RetCode ret = RetCode::SUCCESS;
560 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
561
562 for (const auto& it : bands) {
563 if (RetCode::SUCCESS !=
564 setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
565 LOG(WARNING) << __func__ << " skipping band " << it.toString();
566 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
567 continue;
568 }
569 LOG(INFO) << __func__ << it.toString();
570 }
571 return ret;
572}
573
574} // namespace aidl::android::hardware::audio::effect