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