blob: 57c873bbc618b3b73b028940f237c83a0b8c0934 [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
Shunkai Yao725af212023-01-05 23:01:40 +000019#include "DynamicsProcessingContext.h"
Ram Mohanc89817d2023-03-14 21:39:26 +053020#include "DynamicsProcessing.h"
Shunkai Yao725af212023-01-05 23:01:40 +000021
Shunkai Yao725af212023-01-05 23:01:40 +000022#include <sys/param.h>
Ram Mohanc89817d2023-03-14 21:39:26 +053023#include <functional>
Shunkai Yao725af212023-01-05 23:01:40 +000024#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)) {
Ram Mohanc89817d2023-03-14 21:39:26 +053086 // find next highest power of 2.
Shunkai Yao725af212023-01-05 23:01:40 +000087 block = 1 << (32 - __builtin_clz(block));
88 }
89 mDpFreq->configure(block, block >> 1, sampleRate);
90}
91
92RetCode DynamicsProcessingContext::setEngineArchitecture(
93 const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
Shunkai Yao725af212023-01-05 23:01:40 +000094 std::lock_guard lg(mMutex);
95 if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
96 if (engineArchitecture.resolutionPreference ==
97 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION) {
98 dpSetFreqDomainVariant_l(engineArchitecture);
99 } else {
100 LOG(WARNING) << __func__ << toString(engineArchitecture.resolutionPreference)
101 << " not available now";
102 }
103 mEngineInited = true;
104 mEngineArchitecture = engineArchitecture;
105 }
106 LOG(INFO) << __func__ << engineArchitecture.toString();
107 return RetCode::SUCCESS;
108}
109
110RetCode DynamicsProcessingContext::setPreEq(
111 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
112 std::lock_guard lg(mMutex);
113 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
114 StageType::PREEQ);
115}
116
117RetCode DynamicsProcessingContext::setPostEq(
118 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
119 std::lock_guard lg(mMutex);
120 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
121 StageType::POSTEQ);
122}
123
124RetCode DynamicsProcessingContext::setMbc(
125 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
126 std::lock_guard lg(mMutex);
127 return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
128 StageType::MBC);
129}
130
131RetCode DynamicsProcessingContext::setPreEqBand(
132 const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
133 std::lock_guard lg(mMutex);
Ram Mohanc89817d2023-03-14 21:39:26 +0530134 RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
135 "preEqNotInUse");
136 RETURN_VALUE_IF(
137 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
138 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
139 return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::PREEQ);
Shunkai Yao725af212023-01-05 23:01:40 +0000140}
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");
Ram Mohanc89817d2023-03-14 21:39:26 +0530147 RETURN_VALUE_IF(
148 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
149 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
150 return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::POSTEQ);
Shunkai Yao725af212023-01-05 23:01:40 +0000151}
152
153RetCode DynamicsProcessingContext::setMbcBand(
154 const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
155 std::lock_guard lg(mMutex);
156 RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
157 "mbcNotInUse");
Ram Mohanc89817d2023-03-14 21:39:26 +0530158 RETURN_VALUE_IF(
159 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
160 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
161 return setBands_l<DynamicsProcessing::MbcBandConfig>(bands, StageType::MBC);
Shunkai Yao725af212023-01-05 23:01:40 +0000162}
163
164RetCode DynamicsProcessingContext::setLimiter(
165 const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
166 std::lock_guard lg(mMutex);
167 RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
168 "limiterNotInUse");
Ram Mohanc89817d2023-03-14 21:39:26 +0530169 RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
170 RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
171 return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
Shunkai Yao725af212023-01-05 23:01:40 +0000172}
173
174RetCode DynamicsProcessingContext::setInputGain(
175 const std::vector<DynamicsProcessing::InputGain>& inputGains) {
176 std::lock_guard lg(mMutex);
Ram Mohanc89817d2023-03-14 21:39:26 +0530177 RETURN_VALUE_IF(!validateInputGainConfig(inputGains, mChannelCount),
178 RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
179 return setBands_l<DynamicsProcessing::InputGain>(inputGains, StageType::INPUTGAIN);
Shunkai Yao725af212023-01-05 23:01:40 +0000180}
181
182DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
183 std::lock_guard lg(mMutex);
184 LOG(INFO) << __func__ << mEngineArchitecture.toString();
185 return mEngineArchitecture;
186}
187
188std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPreEq() {
189 return getChannelConfig(StageType::PREEQ);
190}
191
192std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPostEq() {
193 return getChannelConfig(StageType::POSTEQ);
194}
195
196std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPreEqBand() {
197 return getEqBandConfigs(StageType::PREEQ);
198}
199
200std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPostEqBand() {
201 return getEqBandConfigs(StageType::POSTEQ);
202}
203
204std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getMbc() {
205 return getChannelConfig(StageType::MBC);
206}
207
208std::vector<DynamicsProcessing::MbcBandConfig> DynamicsProcessingContext::getMbcBand() {
209 std::vector<DynamicsProcessing::MbcBandConfig> bands;
210
211 std::lock_guard lg(mMutex);
212 auto maxBand = mEngineArchitecture.mbcStage.bandCount;
213 for (int32_t ch = 0; ch < mChannelCount; ch++) {
214 auto mbc = getMbc_l(ch);
215 if (!mbc) {
216 continue;
217 }
218 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
219 auto band = mbc->getBand(bandId);
220 if (!band) {
221 continue;
222 }
223 bands.push_back({.channel = ch,
224 .band = bandId,
225 .enable = band->isEnabled(),
226 .cutoffFrequencyHz = band->getCutoffFrequency(),
227 .attackTimeMs = band->getAttackTime(),
228 .releaseTimeMs = band->getReleaseTime(),
229 .ratio = band->getRatio(),
230 .thresholdDb = band->getThreshold(),
231 .kneeWidthDb = band->getKneeWidth(),
232 .noiseGateThresholdDb = band->getNoiseGateThreshold(),
233 .expanderRatio = band->getExpanderRatio(),
234 .preGainDb = band->getPreGain(),
235 .postGainDb = band->getPostGain()});
236 }
237 }
238 return bands;
239}
240
241std::vector<DynamicsProcessing::LimiterConfig> DynamicsProcessingContext::getLimiter() {
242 std::vector<DynamicsProcessing::LimiterConfig> ret;
243
244 std::lock_guard lg(mMutex);
245 for (int32_t ch = 0; ch < mChannelCount; ch++) {
246 auto limiter = getLimiter_l(ch);
247 if (!limiter) {
248 continue;
249 }
250 ret.push_back({.channel = ch,
251 .enable = limiter->isEnabled(),
252 .linkGroup = static_cast<int32_t>(limiter->getLinkGroup()),
253 .attackTimeMs = limiter->getAttackTime(),
254 .releaseTimeMs = limiter->getReleaseTime(),
255 .ratio = limiter->getRatio(),
256 .thresholdDb = limiter->getThreshold(),
257 .postGainDb = limiter->getPostGain()});
258 }
259 return ret;
260}
261
262std::vector<DynamicsProcessing::InputGain> DynamicsProcessingContext::getInputGain() {
263 std::vector<DynamicsProcessing::InputGain> ret;
264
265 std::lock_guard lg(mMutex);
266 for (int32_t ch = 0; ch < mChannelCount; ch++) {
267 auto channel = getChannel_l(ch);
268 if (!channel) {
269 continue;
270 }
271 ret.push_back({.channel = ch, .gainDb = channel->getInputGain()});
272 }
273 return ret;
274}
275
276IEffect::Status DynamicsProcessingContext::lvmProcess(float* in, float* out, int samples) {
277 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
278
279 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
280 RETURN_VALUE_IF(!in, status, "nullInput");
281 RETURN_VALUE_IF(!out, status, "nullOutput");
282 status = {EX_ILLEGAL_STATE, 0, 0};
283
284 LOG(DEBUG) << __func__ << " start processing";
285 {
286 std::lock_guard lg(mMutex);
287 RETURN_VALUE_IF(mState != DynamicsProcessingState::DYNAMICS_PROCESSING_STATE_ACTIVE, status,
288 "notInActiveState");
289 RETURN_VALUE_IF(!mDpFreq, status, "engineNotInited");
290 mDpFreq->processSamples(in, out, samples);
291 }
292 return {STATUS_OK, samples, samples};
293}
294
295void DynamicsProcessingContext::init() {
296 std::lock_guard lg(mMutex);
297 mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
Mikhail Naganov6352e822023-03-09 18:22:36 -0800298 mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
299 mCommon.input.base.channelMask);
Shunkai Yao725af212023-01-05 23:01:40 +0000300}
301
302dp_fx::DPChannel* DynamicsProcessingContext::getChannel_l(int channel) {
303 RETURN_VALUE_IF(mDpFreq == nullptr, nullptr, "DPFreqNotInited");
304
305 return mDpFreq->getChannel(channel);
306}
307
308dp_fx::DPEq* DynamicsProcessingContext::getPreEq_l(int ch) {
309 auto channel = getChannel_l(ch);
310 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
311
312 return channel->getPreEq();
313}
314
315dp_fx::DPEq* DynamicsProcessingContext::getPostEq_l(int ch) {
316 auto channel = getChannel_l(ch);
317 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
318
319 return channel->getPostEq();
320}
321
322dp_fx::DPMbc* DynamicsProcessingContext::getMbc_l(int ch) {
323 auto channel = getChannel_l(ch);
324 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
325
326 return channel->getMbc();
327}
328
329dp_fx::DPLimiter* DynamicsProcessingContext::getLimiter_l(int ch) {
330 auto channel = getChannel_l(ch);
331 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
332
333 return channel->getLimiter();
334}
335
336dp_fx::DPBandStage* DynamicsProcessingContext::getStageWithType_l(
337 DynamicsProcessingContext::StageType type, int ch) {
338 switch (type) {
339 case StageType::PREEQ: {
340 return getEqWithType_l(type, ch);
341 }
342 case StageType::POSTEQ: {
343 return getEqWithType_l(type, ch);
344 }
345 case StageType::MBC: {
346 return getMbc_l(ch);
347 }
348 case StageType::LIMITER:
349 FALLTHROUGH_INTENDED;
350 case StageType::INPUTGAIN: {
351 return nullptr;
352 }
353 }
354}
355
356dp_fx::DPEq* DynamicsProcessingContext::getEqWithType_l(DynamicsProcessingContext::StageType type,
357 int ch) {
358 switch (type) {
359 case StageType::PREEQ: {
360 return getPreEq_l(ch);
361 }
362 case StageType::POSTEQ: {
363 return getPostEq_l(ch);
364 }
365 case StageType::MBC:
366 FALLTHROUGH_INTENDED;
367 case StageType::LIMITER:
368 FALLTHROUGH_INTENDED;
369 case StageType::INPUTGAIN: {
370 return nullptr;
371 }
372 }
373}
374
375std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getChannelConfig(
376 StageType type) {
377 std::vector<DynamicsProcessing::ChannelConfig> ret;
378
379 std::lock_guard lg(mMutex);
380 for (int32_t ch = 0; ch < mChannelCount; ch++) {
381 auto stage = getStageWithType_l(type, ch);
382 if (!stage) {
383 continue;
384 }
385 ret.push_back({.channel = ch, .enable = stage->isEnabled()});
386 }
387 return ret;
388}
389
390std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getEqBandConfigs(
391 StageType type) {
392 std::vector<DynamicsProcessing::EqBandConfig> eqBands;
393
394 std::lock_guard lg(mMutex);
395 auto maxBand = mEngineArchitecture.preEqStage.bandCount;
396 for (int32_t ch = 0; ch < mChannelCount; ch++) {
397 auto eq = getEqWithType_l(type, ch);
398 if (!eq) {
399 continue;
400 }
401 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
402 auto band = eq->getBand(bandId);
403 if (!band) {
404 continue;
405 }
406 eqBands.push_back({.channel = ch,
407 .band = bandId,
408 .enable = band->isEnabled(),
409 .cutoffFrequencyHz = band->getCutoffFrequency(),
410 .gainDb = band->getGain()});
411 }
412 }
413 return eqBands;
414}
415
Ram Mohanc89817d2023-03-14 21:39:26 +0530416template <typename T>
417bool DynamicsProcessingContext::validateBandConfig(const std::vector<T>& bands, int maxChannel,
418 int maxBand) {
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000419 std::map<int, float> freqs;
Ram Mohanc89817d2023-03-14 21:39:26 +0530420 for (auto band : bands) {
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000421 if (!validateChannel(band.channel, maxChannel)) {
422 LOG(ERROR) << __func__ << " " << band.toString() << " invalid, maxCh " << maxChannel;
423 return false;
424 }
425 if (!validateBand(band.band, maxBand)) {
426 LOG(ERROR) << __func__ << " " << band.toString() << " invalid, maxBand " << maxBand;
427 return false;
428 }
429 if (freqs.find(band.band) != freqs.end()) {
430 LOG(ERROR) << __func__ << " " << band.toString() << " found duplicate";
431 return false;
432 }
Ram Mohanc89817d2023-03-14 21:39:26 +0530433 freqs[band.band] = band.cutoffFrequencyHz;
434 }
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000435 return std::is_sorted(freqs.begin(), freqs.end(), [](const auto& a, const auto& b) {
436 return a.second <= b.second; //index is already sorted as map key
437 });
Shunkai Yao725af212023-01-05 23:01:40 +0000438}
439
440bool DynamicsProcessingContext::validateLimiterConfig(
Ram Mohanc89817d2023-03-14 21:39:26 +0530441 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs, int maxChannel) {
442 for (auto cfg : cfgs) {
443 if (!validateChannel(cfg.channel, maxChannel)) return false;
444 }
445 return true;
Shunkai Yao725af212023-01-05 23:01:40 +0000446}
447
Ram Mohanc89817d2023-03-14 21:39:26 +0530448bool DynamicsProcessingContext::validateInputGainConfig(
449 const std::vector<DynamicsProcessing::InputGain>& cfgs, int maxChannel) {
450 for (auto cfg : cfgs) {
451 if (!validateChannel(cfg.channel, maxChannel)) return false;
452 }
453 return true;
Shunkai Yao725af212023-01-05 23:01:40 +0000454}
455
456template <typename D>
457RetCode DynamicsProcessingContext::setDpChannels_l(
458 const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
459 StageType type) {
460 RetCode ret = RetCode::SUCCESS;
461 std::unordered_set<int> channelSet;
462
463 RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
464 for (auto& it : channels) {
465 if (0 != channelSet.count(it.channel)) {
466 LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
467 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
468 } else {
469 channelSet.insert(it.channel);
470 }
471 if (it.channel < 0 || it.channel >= mChannelCount) {
472 LOG(WARNING) << __func__ << " skip illegal ChannelConfig " << it.toString() << " max "
473 << mChannelCount;
474 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
475 continue;
476 }
477 auto dp = getStageWithType_l(type, it.channel);
478 if (!dp) {
479 LOG(WARNING) << __func__ << " channel " << it.channel << " not exist";
480 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
481 continue;
482 }
483 if (dp->isEnabled() != it.enable) {
484 LOG(INFO) << __func__ << it.toString();
485 dp->setEnabled(it.enable);
486 }
487 }
488 return ret;
489}
490
491RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
Shunkai Yao725af212023-01-05 23:01:40 +0000492 std::set<std::pair<int, int>>& chBandSet) {
493 RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
494 RetCode ret = RetCode::SUCCESS;
495 std::pair<int, int> chBandKey;
496 switch (type) {
497 case StageType::PREEQ:
498 FALLTHROUGH_INTENDED;
499 case StageType::POSTEQ: {
500 dp_fx::DPEq* dp;
501 const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000502 RETURN_VALUE_IF(
503 nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
504 RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
505 dp_fx::DPEqBand band;
506 band.init(config.enable, config.cutoffFrequencyHz, config.gainDb);
507 dp->setBand(config.band, band);
508 chBandKey = {config.channel, config.band};
509 break;
510 }
511 case StageType::MBC: {
512 dp_fx::DPMbc* dp;
513 const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000514 RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
515 RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
516 dp_fx::DPMbcBand band;
517 band.init(config.enable, config.cutoffFrequencyHz, config.attackTimeMs,
518 config.releaseTimeMs, config.ratio, config.thresholdDb, config.kneeWidthDb,
519 config.noiseGateThresholdDb, config.expanderRatio, config.preGainDb,
520 config.postGainDb);
521 dp->setBand(config.band, band);
522 chBandKey = {config.channel, config.band};
523 break;
524 }
525 case StageType::LIMITER: {
526 dp_fx::DPChannel* dp;
527 const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000528 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);
Shunkai Yao725af212023-01-05 23:01:40 +0000541 RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
542 RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
543 dp->setInputGain(config.gainDb);
544 chBandKey = {config.channel, 0};
545 break;
546 }
547 }
548 RETURN_VALUE_IF(0 != chBandSet.count(chBandKey), RetCode::ERROR_ILLEGAL_PARAMETER,
549 "duplicatedBand");
550 chBandSet.insert(chBandKey);
551 return ret;
552}
553
554template <typename T /* BandConfig */>
Ram Mohanc89817d2023-03-14 21:39:26 +0530555RetCode DynamicsProcessingContext::setBands_l(const std::vector<T>& bands, StageType type) {
Shunkai Yao725af212023-01-05 23:01:40 +0000556 RetCode ret = RetCode::SUCCESS;
557 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
558
559 for (const auto& it : bands) {
Ram Mohanc89817d2023-03-14 21:39:26 +0530560 if (RetCode::SUCCESS != setDpChannelBand_l(std::make_any<T>(it), type, bandSet)) {
Shunkai Yao725af212023-01-05 23:01:40 +0000561 LOG(WARNING) << __func__ << " skipping band " << it.toString();
562 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
563 continue;
564 }
565 LOG(INFO) << __func__ << it.toString();
566 }
567 return ret;
568}
569
570} // namespace aidl::android::hardware::audio::effect