blob: 042b0635a5e9ac732f88621bd576b5c8d409d349 [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
David Licb5bcc42023-11-13 16:01:48 +080022#include <audio_utils/power.h>
Shunkai Yao725af212023-01-05 23:01:40 +000023#include <sys/param.h>
Ram Mohanc89817d2023-03-14 21:39:26 +053024#include <functional>
Shunkai Yao725af212023-01-05 23:01:40 +000025#include <unordered_set>
26
27namespace aidl::android::hardware::audio::effect {
28
29DynamicsProcessingContext::DynamicsProcessingContext(int statusDepth,
30 const Parameter::Common& common)
31 : EffectContext(statusDepth, common) {
32 LOG(DEBUG) << __func__;
33 init();
34}
35
36DynamicsProcessingContext::~DynamicsProcessingContext() {
37 LOG(DEBUG) << __func__;
38}
39
40RetCode DynamicsProcessingContext::enable() {
41 std::lock_guard lg(mMutex);
42 if (mState != DYNAMICS_PROCESSING_STATE_INITIALIZED) {
43 return RetCode::ERROR_EFFECT_LIB_ERROR;
44 }
45 mState = DYNAMICS_PROCESSING_STATE_ACTIVE;
46 return RetCode::SUCCESS;
47}
48
49RetCode DynamicsProcessingContext::disable() {
50 std::lock_guard lg(mMutex);
51 if (mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
52 return RetCode::ERROR_EFFECT_LIB_ERROR;
53 }
54 mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
55 return RetCode::SUCCESS;
56}
57
58void DynamicsProcessingContext::reset() {
59 std::lock_guard lg(mMutex);
60 if (mDpFreq != nullptr) {
61 mDpFreq.reset();
62 }
63}
64
65RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
Shunkai Yao1afb46c2024-01-09 20:40:45 +000066 if(auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
67 return ret;
68 }
Shunkai Yao725af212023-01-05 23:01:40 +000069 mCommon = common;
70 init();
Shunkai Yaod86851a2023-03-01 02:49:50 +000071 LOG(INFO) << __func__ << common.toString();
Shunkai Yao725af212023-01-05 23:01:40 +000072 return RetCode::SUCCESS;
73}
74
David Licb5bcc42023-11-13 16:01:48 +080075RetCode DynamicsProcessingContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
76 std::lock_guard lg(mMutex);
77 dp_fx::DPChannel* leftChannel = mDpFreq->getChannel(0);
78 dp_fx::DPChannel* rightChannel = mDpFreq->getChannel(1);
79 if (leftChannel != nullptr) {
80 leftChannel->setOutputGain(audio_utils_power_from_amplitude(volumeStereo.left));
81 }
82 if (rightChannel != nullptr) {
83 rightChannel->setOutputGain(audio_utils_power_from_amplitude(volumeStereo.right));
84 }
85 return RetCode::SUCCESS;
86}
87
88Parameter::VolumeStereo DynamicsProcessingContext::getVolumeStereo() {
89 return {1.0f, 1.0f};
90}
91
Shunkai Yao725af212023-01-05 23:01:40 +000092void DynamicsProcessingContext::dpSetFreqDomainVariant_l(
93 const DynamicsProcessing::EngineArchitecture& engine) {
94 mDpFreq.reset(new dp_fx::DPFrequency());
95 mDpFreq->init(mChannelCount, engine.preEqStage.inUse, engine.preEqStage.bandCount,
96 engine.mbcStage.inUse, engine.mbcStage.bandCount, engine.postEqStage.inUse,
97 engine.postEqStage.bandCount, engine.limiterInUse);
98
99 int32_t sampleRate = mCommon.input.base.sampleRate;
100 int32_t minBlockSize = (int32_t)dp_fx::DPFrequency::getMinBockSize();
101 int32_t block = engine.preferredProcessingDurationMs * sampleRate / 1000.0f;
102 LOG(INFO) << __func__ << " sampleRate " << sampleRate << " block length "
103 << engine.preferredProcessingDurationMs << " ms (" << block << "samples)";
104 if (block < minBlockSize) {
105 block = minBlockSize;
106 } else if (!powerof2(block)) {
Ram Mohanc89817d2023-03-14 21:39:26 +0530107 // find next highest power of 2.
Shunkai Yao725af212023-01-05 23:01:40 +0000108 block = 1 << (32 - __builtin_clz(block));
109 }
110 mDpFreq->configure(block, block >> 1, sampleRate);
111}
112
113RetCode DynamicsProcessingContext::setEngineArchitecture(
114 const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
Shunkai Yao725af212023-01-05 23:01:40 +0000115 std::lock_guard lg(mMutex);
116 if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
117 if (engineArchitecture.resolutionPreference ==
118 DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION) {
119 dpSetFreqDomainVariant_l(engineArchitecture);
120 } else {
121 LOG(WARNING) << __func__ << toString(engineArchitecture.resolutionPreference)
122 << " not available now";
123 }
124 mEngineInited = true;
125 mEngineArchitecture = engineArchitecture;
126 }
127 LOG(INFO) << __func__ << engineArchitecture.toString();
128 return RetCode::SUCCESS;
129}
130
131RetCode DynamicsProcessingContext::setPreEq(
132 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
133 std::lock_guard lg(mMutex);
134 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
135 StageType::PREEQ);
136}
137
138RetCode DynamicsProcessingContext::setPostEq(
139 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
140 std::lock_guard lg(mMutex);
141 return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
142 StageType::POSTEQ);
143}
144
145RetCode DynamicsProcessingContext::setMbc(
146 const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
147 std::lock_guard lg(mMutex);
148 return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
149 StageType::MBC);
150}
151
152RetCode DynamicsProcessingContext::setPreEqBand(
153 const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
154 std::lock_guard lg(mMutex);
Ram Mohanc89817d2023-03-14 21:39:26 +0530155 RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
156 "preEqNotInUse");
157 RETURN_VALUE_IF(
158 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
159 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
160 return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::PREEQ);
Shunkai Yao725af212023-01-05 23:01:40 +0000161}
162
163RetCode DynamicsProcessingContext::setPostEqBand(
164 const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
165 std::lock_guard lg(mMutex);
166 RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
167 "postEqNotInUse");
Ram Mohanc89817d2023-03-14 21:39:26 +0530168 RETURN_VALUE_IF(
169 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
170 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
171 return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::POSTEQ);
Shunkai Yao725af212023-01-05 23:01:40 +0000172}
173
174RetCode DynamicsProcessingContext::setMbcBand(
175 const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
176 std::lock_guard lg(mMutex);
177 RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
178 "mbcNotInUse");
Ram Mohanc89817d2023-03-14 21:39:26 +0530179 RETURN_VALUE_IF(
180 !validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
181 RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
182 return setBands_l<DynamicsProcessing::MbcBandConfig>(bands, StageType::MBC);
Shunkai Yao725af212023-01-05 23:01:40 +0000183}
184
185RetCode DynamicsProcessingContext::setLimiter(
186 const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
187 std::lock_guard lg(mMutex);
188 RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
189 "limiterNotInUse");
Ram Mohanc89817d2023-03-14 21:39:26 +0530190 RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
191 RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
192 return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
Shunkai Yao725af212023-01-05 23:01:40 +0000193}
194
195RetCode DynamicsProcessingContext::setInputGain(
196 const std::vector<DynamicsProcessing::InputGain>& inputGains) {
197 std::lock_guard lg(mMutex);
Ram Mohanc89817d2023-03-14 21:39:26 +0530198 RETURN_VALUE_IF(!validateInputGainConfig(inputGains, mChannelCount),
199 RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
200 return setBands_l<DynamicsProcessing::InputGain>(inputGains, StageType::INPUTGAIN);
Shunkai Yao725af212023-01-05 23:01:40 +0000201}
202
203DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
204 std::lock_guard lg(mMutex);
205 LOG(INFO) << __func__ << mEngineArchitecture.toString();
206 return mEngineArchitecture;
207}
208
209std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPreEq() {
210 return getChannelConfig(StageType::PREEQ);
211}
212
213std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPostEq() {
214 return getChannelConfig(StageType::POSTEQ);
215}
216
217std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPreEqBand() {
218 return getEqBandConfigs(StageType::PREEQ);
219}
220
221std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPostEqBand() {
222 return getEqBandConfigs(StageType::POSTEQ);
223}
224
225std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getMbc() {
226 return getChannelConfig(StageType::MBC);
227}
228
229std::vector<DynamicsProcessing::MbcBandConfig> DynamicsProcessingContext::getMbcBand() {
230 std::vector<DynamicsProcessing::MbcBandConfig> bands;
231
232 std::lock_guard lg(mMutex);
233 auto maxBand = mEngineArchitecture.mbcStage.bandCount;
234 for (int32_t ch = 0; ch < mChannelCount; ch++) {
235 auto mbc = getMbc_l(ch);
236 if (!mbc) {
237 continue;
238 }
239 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
240 auto band = mbc->getBand(bandId);
241 if (!band) {
242 continue;
243 }
244 bands.push_back({.channel = ch,
245 .band = bandId,
246 .enable = band->isEnabled(),
247 .cutoffFrequencyHz = band->getCutoffFrequency(),
248 .attackTimeMs = band->getAttackTime(),
249 .releaseTimeMs = band->getReleaseTime(),
250 .ratio = band->getRatio(),
251 .thresholdDb = band->getThreshold(),
252 .kneeWidthDb = band->getKneeWidth(),
253 .noiseGateThresholdDb = band->getNoiseGateThreshold(),
254 .expanderRatio = band->getExpanderRatio(),
255 .preGainDb = band->getPreGain(),
256 .postGainDb = band->getPostGain()});
257 }
258 }
259 return bands;
260}
261
262std::vector<DynamicsProcessing::LimiterConfig> DynamicsProcessingContext::getLimiter() {
263 std::vector<DynamicsProcessing::LimiterConfig> ret;
264
265 std::lock_guard lg(mMutex);
266 for (int32_t ch = 0; ch < mChannelCount; ch++) {
267 auto limiter = getLimiter_l(ch);
268 if (!limiter) {
269 continue;
270 }
271 ret.push_back({.channel = ch,
272 .enable = limiter->isEnabled(),
273 .linkGroup = static_cast<int32_t>(limiter->getLinkGroup()),
274 .attackTimeMs = limiter->getAttackTime(),
275 .releaseTimeMs = limiter->getReleaseTime(),
276 .ratio = limiter->getRatio(),
277 .thresholdDb = limiter->getThreshold(),
278 .postGainDb = limiter->getPostGain()});
279 }
280 return ret;
281}
282
283std::vector<DynamicsProcessing::InputGain> DynamicsProcessingContext::getInputGain() {
284 std::vector<DynamicsProcessing::InputGain> ret;
285
286 std::lock_guard lg(mMutex);
287 for (int32_t ch = 0; ch < mChannelCount; ch++) {
288 auto channel = getChannel_l(ch);
289 if (!channel) {
290 continue;
291 }
292 ret.push_back({.channel = ch, .gainDb = channel->getInputGain()});
293 }
294 return ret;
295}
296
David Licb5bcc42023-11-13 16:01:48 +0800297IEffect::Status DynamicsProcessingContext::dpeProcess(float* in, float* out, int samples) {
Shunkai Yao725af212023-01-05 23:01:40 +0000298 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
299
300 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
301 RETURN_VALUE_IF(!in, status, "nullInput");
302 RETURN_VALUE_IF(!out, status, "nullOutput");
303 status = {EX_ILLEGAL_STATE, 0, 0};
304
305 LOG(DEBUG) << __func__ << " start processing";
306 {
307 std::lock_guard lg(mMutex);
308 RETURN_VALUE_IF(mState != DynamicsProcessingState::DYNAMICS_PROCESSING_STATE_ACTIVE, status,
309 "notInActiveState");
310 RETURN_VALUE_IF(!mDpFreq, status, "engineNotInited");
311 mDpFreq->processSamples(in, out, samples);
312 }
313 return {STATUS_OK, samples, samples};
314}
315
316void DynamicsProcessingContext::init() {
317 std::lock_guard lg(mMutex);
Shunkai Yao1afb46c2024-01-09 20:40:45 +0000318 if (mState == DYNAMICS_PROCESSING_STATE_UNINITIALIZED) {
319 mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
320 }
Shunkai Yaocbe90d02023-12-14 02:35:55 +0000321 mChannelCount = static_cast<int>(::aidl::android::hardware::audio::common::getChannelCount(
322 mCommon.input.base.channelMask));
Shunkai Yao725af212023-01-05 23:01:40 +0000323}
324
325dp_fx::DPChannel* DynamicsProcessingContext::getChannel_l(int channel) {
326 RETURN_VALUE_IF(mDpFreq == nullptr, nullptr, "DPFreqNotInited");
327
328 return mDpFreq->getChannel(channel);
329}
330
331dp_fx::DPEq* DynamicsProcessingContext::getPreEq_l(int ch) {
332 auto channel = getChannel_l(ch);
333 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
334
335 return channel->getPreEq();
336}
337
338dp_fx::DPEq* DynamicsProcessingContext::getPostEq_l(int ch) {
339 auto channel = getChannel_l(ch);
340 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
341
342 return channel->getPostEq();
343}
344
345dp_fx::DPMbc* DynamicsProcessingContext::getMbc_l(int ch) {
346 auto channel = getChannel_l(ch);
347 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
348
349 return channel->getMbc();
350}
351
352dp_fx::DPLimiter* DynamicsProcessingContext::getLimiter_l(int ch) {
353 auto channel = getChannel_l(ch);
354 RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
355
356 return channel->getLimiter();
357}
358
359dp_fx::DPBandStage* DynamicsProcessingContext::getStageWithType_l(
360 DynamicsProcessingContext::StageType type, int ch) {
361 switch (type) {
362 case StageType::PREEQ: {
363 return getEqWithType_l(type, ch);
364 }
365 case StageType::POSTEQ: {
366 return getEqWithType_l(type, ch);
367 }
368 case StageType::MBC: {
369 return getMbc_l(ch);
370 }
371 case StageType::LIMITER:
372 FALLTHROUGH_INTENDED;
373 case StageType::INPUTGAIN: {
374 return nullptr;
375 }
376 }
377}
378
379dp_fx::DPEq* DynamicsProcessingContext::getEqWithType_l(DynamicsProcessingContext::StageType type,
380 int ch) {
381 switch (type) {
382 case StageType::PREEQ: {
383 return getPreEq_l(ch);
384 }
385 case StageType::POSTEQ: {
386 return getPostEq_l(ch);
387 }
388 case StageType::MBC:
389 FALLTHROUGH_INTENDED;
390 case StageType::LIMITER:
391 FALLTHROUGH_INTENDED;
392 case StageType::INPUTGAIN: {
393 return nullptr;
394 }
395 }
396}
397
398std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getChannelConfig(
399 StageType type) {
400 std::vector<DynamicsProcessing::ChannelConfig> ret;
401
402 std::lock_guard lg(mMutex);
403 for (int32_t ch = 0; ch < mChannelCount; ch++) {
404 auto stage = getStageWithType_l(type, ch);
405 if (!stage) {
406 continue;
407 }
408 ret.push_back({.channel = ch, .enable = stage->isEnabled()});
409 }
410 return ret;
411}
412
413std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getEqBandConfigs(
414 StageType type) {
415 std::vector<DynamicsProcessing::EqBandConfig> eqBands;
416
417 std::lock_guard lg(mMutex);
418 auto maxBand = mEngineArchitecture.preEqStage.bandCount;
419 for (int32_t ch = 0; ch < mChannelCount; ch++) {
420 auto eq = getEqWithType_l(type, ch);
421 if (!eq) {
422 continue;
423 }
424 for (int32_t bandId = 0; bandId < maxBand; bandId++) {
425 auto band = eq->getBand(bandId);
426 if (!band) {
427 continue;
428 }
429 eqBands.push_back({.channel = ch,
430 .band = bandId,
431 .enable = band->isEnabled(),
432 .cutoffFrequencyHz = band->getCutoffFrequency(),
433 .gainDb = band->getGain()});
434 }
435 }
436 return eqBands;
437}
438
Ram Mohanc89817d2023-03-14 21:39:26 +0530439template <typename T>
440bool DynamicsProcessingContext::validateBandConfig(const std::vector<T>& bands, int maxChannel,
441 int maxBand) {
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000442 std::map<int, float> freqs;
Ram Mohanc89817d2023-03-14 21:39:26 +0530443 for (auto band : bands) {
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000444 if (!validateChannel(band.channel, maxChannel)) {
445 LOG(ERROR) << __func__ << " " << band.toString() << " invalid, maxCh " << maxChannel;
446 return false;
447 }
448 if (!validateBand(band.band, maxBand)) {
449 LOG(ERROR) << __func__ << " " << band.toString() << " invalid, maxBand " << maxBand;
450 return false;
451 }
452 if (freqs.find(band.band) != freqs.end()) {
453 LOG(ERROR) << __func__ << " " << band.toString() << " found duplicate";
454 return false;
455 }
Ram Mohanc89817d2023-03-14 21:39:26 +0530456 freqs[band.band] = band.cutoffFrequencyHz;
457 }
Shunkai Yao95c5dea2023-10-18 01:18:23 +0000458 return std::is_sorted(freqs.begin(), freqs.end(), [](const auto& a, const auto& b) {
459 return a.second <= b.second; //index is already sorted as map key
460 });
Shunkai Yao725af212023-01-05 23:01:40 +0000461}
462
463bool DynamicsProcessingContext::validateLimiterConfig(
Ram Mohanc89817d2023-03-14 21:39:26 +0530464 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs, int maxChannel) {
465 for (auto cfg : cfgs) {
466 if (!validateChannel(cfg.channel, maxChannel)) return false;
467 }
468 return true;
Shunkai Yao725af212023-01-05 23:01:40 +0000469}
470
Ram Mohanc89817d2023-03-14 21:39:26 +0530471bool DynamicsProcessingContext::validateInputGainConfig(
472 const std::vector<DynamicsProcessing::InputGain>& cfgs, int maxChannel) {
473 for (auto cfg : cfgs) {
474 if (!validateChannel(cfg.channel, maxChannel)) return false;
475 }
476 return true;
Shunkai Yao725af212023-01-05 23:01:40 +0000477}
478
479template <typename D>
480RetCode DynamicsProcessingContext::setDpChannels_l(
481 const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
482 StageType type) {
483 RetCode ret = RetCode::SUCCESS;
484 std::unordered_set<int> channelSet;
485
David Licb5bcc42023-11-13 16:01:48 +0800486 if (!stageInUse) {
487 LOG(WARNING) << __func__ << " not in use " << ::android::internal::ToString(channels);
488 return RetCode::SUCCESS;
489 }
490
Shunkai Yao725af212023-01-05 23:01:40 +0000491 RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
492 for (auto& it : channels) {
493 if (0 != channelSet.count(it.channel)) {
494 LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
495 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
496 } else {
497 channelSet.insert(it.channel);
498 }
499 if (it.channel < 0 || it.channel >= mChannelCount) {
500 LOG(WARNING) << __func__ << " skip illegal ChannelConfig " << it.toString() << " max "
501 << mChannelCount;
502 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
503 continue;
504 }
505 auto dp = getStageWithType_l(type, it.channel);
506 if (!dp) {
507 LOG(WARNING) << __func__ << " channel " << it.channel << " not exist";
508 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
509 continue;
510 }
511 if (dp->isEnabled() != it.enable) {
512 LOG(INFO) << __func__ << it.toString();
513 dp->setEnabled(it.enable);
514 }
515 }
516 return ret;
517}
518
519RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
Shunkai Yao725af212023-01-05 23:01:40 +0000520 std::set<std::pair<int, int>>& chBandSet) {
521 RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
522 RetCode ret = RetCode::SUCCESS;
523 std::pair<int, int> chBandKey;
524 switch (type) {
525 case StageType::PREEQ:
526 FALLTHROUGH_INTENDED;
527 case StageType::POSTEQ: {
528 dp_fx::DPEq* dp;
529 const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000530 RETURN_VALUE_IF(
531 nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
532 RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
533 dp_fx::DPEqBand band;
534 band.init(config.enable, config.cutoffFrequencyHz, config.gainDb);
535 dp->setBand(config.band, band);
536 chBandKey = {config.channel, config.band};
537 break;
538 }
539 case StageType::MBC: {
540 dp_fx::DPMbc* dp;
541 const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000542 RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
543 RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
544 dp_fx::DPMbcBand band;
545 band.init(config.enable, config.cutoffFrequencyHz, config.attackTimeMs,
546 config.releaseTimeMs, config.ratio, config.thresholdDb, config.kneeWidthDb,
547 config.noiseGateThresholdDb, config.expanderRatio, config.preGainDb,
548 config.postGainDb);
549 dp->setBand(config.band, band);
550 chBandKey = {config.channel, config.band};
551 break;
552 }
553 case StageType::LIMITER: {
554 dp_fx::DPChannel* dp;
555 const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000556 RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
557 RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
558 dp_fx::DPLimiter limiter;
559 limiter.init(mEngineArchitecture.limiterInUse, config.enable, config.linkGroup,
560 config.attackTimeMs, config.releaseTimeMs, config.ratio,
561 config.thresholdDb, config.postGainDb);
562 dp->setLimiter(limiter);
563 chBandKey = {config.channel, 0};
564 break;
565 }
566 case StageType::INPUTGAIN: {
567 dp_fx::DPChannel* dp;
568 const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
Shunkai Yao725af212023-01-05 23:01:40 +0000569 RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
570 RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
571 dp->setInputGain(config.gainDb);
572 chBandKey = {config.channel, 0};
573 break;
574 }
575 }
576 RETURN_VALUE_IF(0 != chBandSet.count(chBandKey), RetCode::ERROR_ILLEGAL_PARAMETER,
577 "duplicatedBand");
578 chBandSet.insert(chBandKey);
579 return ret;
580}
581
582template <typename T /* BandConfig */>
Ram Mohanc89817d2023-03-14 21:39:26 +0530583RetCode DynamicsProcessingContext::setBands_l(const std::vector<T>& bands, StageType type) {
Shunkai Yao725af212023-01-05 23:01:40 +0000584 RetCode ret = RetCode::SUCCESS;
585 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
586
587 for (const auto& it : bands) {
Ram Mohanc89817d2023-03-14 21:39:26 +0530588 if (RetCode::SUCCESS != setDpChannelBand_l(std::make_any<T>(it), type, bandSet)) {
Shunkai Yao725af212023-01-05 23:01:40 +0000589 LOG(WARNING) << __func__ << " skipping band " << it.toString();
590 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
591 continue;
592 }
593 LOG(INFO) << __func__ << it.toString();
594 }
595 return ret;
596}
597
598} // namespace aidl::android::hardware::audio::effect