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