blob: da6d0c6f5c3c13d7e5269e4a7c358cc80090707c [file] [log] [blame]
Shunkai Yao6afc8552022-10-26 22:47:20 +00001/*
2 * Copyright (C) 2022 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#include <cstddef>
18#define LOG_TAG "AHAL_DynamicsProcessingSw"
19#include <Utils.h>
20#include <algorithm>
Ram Mohane4064ce2022-12-20 18:05:14 +053021#include <set>
Shunkai Yao6afc8552022-10-26 22:47:20 +000022#include <unordered_set>
23
24#include <android-base/logging.h>
25#include <fmq/AidlMessageQueue.h>
26
27#include "DynamicsProcessingSw.h"
28
Shunkai Yaoc12e0822022-12-12 07:13:58 +000029using aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yao6afc8552022-10-26 22:47:20 +000030using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
Shunkai Yao6afc8552022-10-26 22:47:20 +000031using aidl::android::hardware::audio::effect::IEffect;
Shunkai Yao812d5b42022-11-16 18:08:50 +000032using aidl::android::hardware::audio::effect::kDynamicsProcessingSwImplUUID;
Shunkai Yao6afc8552022-10-26 22:47:20 +000033using aidl::android::hardware::audio::effect::State;
34using aidl::android::media::audio::common::AudioUuid;
35
36extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
37 std::shared_ptr<IEffect>* instanceSpp) {
Shunkai Yao812d5b42022-11-16 18:08:50 +000038 if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
Shunkai Yao6afc8552022-10-26 22:47:20 +000039 LOG(ERROR) << __func__ << "uuid not supported";
40 return EX_ILLEGAL_ARGUMENT;
41 }
42 if (instanceSpp) {
43 *instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingSw>();
44 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
45 return EX_NONE;
46 } else {
47 LOG(ERROR) << __func__ << " invalid input parameter!";
48 return EX_ILLEGAL_ARGUMENT;
49 }
50}
51
Shunkai Yaoc12e0822022-12-12 07:13:58 +000052extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
53 if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
54 LOG(ERROR) << __func__ << "uuid not supported";
55 return EX_ILLEGAL_ARGUMENT;
Shunkai Yao6afc8552022-10-26 22:47:20 +000056 }
Shunkai Yaoc12e0822022-12-12 07:13:58 +000057 *_aidl_return = DynamicsProcessingSw::kDescriptor;
Shunkai Yao6afc8552022-10-26 22:47:20 +000058 return EX_NONE;
59}
60
61namespace aidl::android::hardware::audio::effect {
62
Shunkai Yaoc12e0822022-12-12 07:13:58 +000063const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
Shunkai Yao87811022023-02-13 17:40:37 +000064const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::kEqBandConfigMin =
65 DynamicsProcessing::EqBandConfig({.channel = 0,
66 .band = 0,
67 .enable = false,
68 .cutoffFrequencyHz = 220,
69 .gainDb = std::numeric_limits<float>::min()});
70const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::kEqBandConfigMax =
71 DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
72 .band = std::numeric_limits<int>::max(),
73 .enable = true,
74 .cutoffFrequencyHz = 20000,
75 .gainDb = std::numeric_limits<float>::max()});
76const Range::DynamicsProcessingRange DynamicsProcessingSw::kPreEqBandRange = {
77 .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
78 {DynamicsProcessingSw::kEqBandConfigMin}),
79 .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
80 {DynamicsProcessingSw::kEqBandConfigMax})};
81const Range::DynamicsProcessingRange DynamicsProcessingSw::kPostEqBandRange = {
82 .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
83 {DynamicsProcessingSw::kEqBandConfigMin}),
84 .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
85 {DynamicsProcessingSw::kEqBandConfigMax})};
86
87const std::vector<Range::DynamicsProcessingRange> DynamicsProcessingSw::kRanges = {
88 DynamicsProcessingSw::kPreEqBandRange, DynamicsProcessingSw::kPostEqBandRange};
89const Capability DynamicsProcessingSw::kCapability = {.range = DynamicsProcessingSw::kRanges};
90
Shunkai Yaoc12e0822022-12-12 07:13:58 +000091const Descriptor DynamicsProcessingSw::kDescriptor = {
92 .common = {.id = {.type = kDynamicsProcessingTypeUUID,
93 .uuid = kDynamicsProcessingSwImplUUID,
94 .proxy = std::nullopt},
95 .flags = {.type = Flags::Type::INSERT,
96 .insert = Flags::Insert::FIRST,
97 .volume = Flags::Volume::CTRL},
98 .name = DynamicsProcessingSw::kEffectName,
99 .implementor = "The Android Open Source Project"},
Shunkai Yao87811022023-02-13 17:40:37 +0000100 .capability = DynamicsProcessingSw::kCapability};
Shunkai Yaoc12e0822022-12-12 07:13:58 +0000101
Shunkai Yao6afc8552022-10-26 22:47:20 +0000102ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
103 LOG(DEBUG) << __func__ << kDescriptor.toString();
104 *_aidl_return = kDescriptor;
105 return ndk::ScopedAStatus::ok();
106}
107
108ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
109 RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
110 "EffectNotSupported");
Shunkai Yao6afc8552022-10-26 22:47:20 +0000111
Ram Mohane4064ce2022-12-20 18:05:14 +0530112 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
113
114 LOG(INFO) << __func__ << specific.toString();
115 auto& dpParam = specific.get<Parameter::Specific::dynamicsProcessing>();
116 auto tag = dpParam.getTag();
117 switch (tag) {
118 case DynamicsProcessing::engineArchitecture: {
119 RETURN_IF(mContext->setEngineArchitecture(
120 dpParam.get<DynamicsProcessing::engineArchitecture>()) !=
121 RetCode::SUCCESS,
122 EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
123 return ndk::ScopedAStatus::ok();
124 }
125 case DynamicsProcessing::preEq: {
126 RETURN_IF(mContext->setPreEqChannelCfgs(dpParam.get<DynamicsProcessing::preEq>()) !=
127 RetCode::SUCCESS,
128 EX_ILLEGAL_ARGUMENT, "setPreEqChannelCfgsFailed");
129 return ndk::ScopedAStatus::ok();
130 }
131 case DynamicsProcessing::postEq: {
132 RETURN_IF(mContext->setPostEqChannelCfgs(dpParam.get<DynamicsProcessing::postEq>()) !=
133 RetCode::SUCCESS,
134 EX_ILLEGAL_ARGUMENT, "setPostEqChannelCfgsFailed");
135 return ndk::ScopedAStatus::ok();
136 }
137 case DynamicsProcessing::mbc: {
138 RETURN_IF(mContext->setMbcChannelCfgs(dpParam.get<DynamicsProcessing::mbc>()) !=
139 RetCode::SUCCESS,
140 EX_ILLEGAL_ARGUMENT, "setMbcChannelCfgsFailed");
141 return ndk::ScopedAStatus::ok();
142 }
143 case DynamicsProcessing::preEqBand: {
144 RETURN_IF(mContext->setPreEqBandCfgs(dpParam.get<DynamicsProcessing::preEqBand>()) !=
145 RetCode::SUCCESS,
146 EX_ILLEGAL_ARGUMENT, "setPreEqBandCfgsFailed");
147 return ndk::ScopedAStatus::ok();
148 }
149 case DynamicsProcessing::postEqBand: {
150 RETURN_IF(mContext->setPostEqBandCfgs(dpParam.get<DynamicsProcessing::postEqBand>()) !=
151 RetCode::SUCCESS,
152 EX_ILLEGAL_ARGUMENT, "setPostEqBandCfgsFailed");
153 return ndk::ScopedAStatus::ok();
154 }
155 case DynamicsProcessing::mbcBand: {
156 RETURN_IF(mContext->setMbcBandCfgs(dpParam.get<DynamicsProcessing::mbcBand>()) !=
157 RetCode::SUCCESS,
158 EX_ILLEGAL_ARGUMENT, "setMbcBandCfgsFailed");
159 return ndk::ScopedAStatus::ok();
160 }
161 case DynamicsProcessing::limiter: {
162 RETURN_IF(mContext->setLimiterCfgs(dpParam.get<DynamicsProcessing::limiter>()) !=
163 RetCode::SUCCESS,
164 EX_ILLEGAL_ARGUMENT, "limiterCfgsFailed");
165 return ndk::ScopedAStatus::ok();
166 }
167 case DynamicsProcessing::inputGain: {
168 RETURN_IF(mContext->setInputGainCfgs(dpParam.get<DynamicsProcessing::inputGain>()) !=
169 RetCode::SUCCESS,
170 EX_ILLEGAL_ARGUMENT, "inputGainCfgFailed");
171 return ndk::ScopedAStatus::ok();
172 }
173 case DynamicsProcessing::vendorExtension: {
174 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
175 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
176 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
177 }
178 }
Shunkai Yao6afc8552022-10-26 22:47:20 +0000179}
180
181ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
182 Parameter::Specific* specific) {
183 auto tag = id.getTag();
184 RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
Ram Mohane4064ce2022-12-20 18:05:14 +0530185 auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
186 auto dpIdTag = dpId.getTag();
187 switch (dpIdTag) {
188 case DynamicsProcessing::Id::commonTag:
189 return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
190 specific);
191 case DynamicsProcessing::Id::vendorExtensionTag:
192 LOG(ERROR) << __func__ << " unsupported tag: " << toString(dpIdTag);
193 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
194 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
195 }
196}
197
198ndk::ScopedAStatus DynamicsProcessingSw::getParameterDynamicsProcessing(
199 const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
200 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
201
202 DynamicsProcessing dpParam;
203 switch (tag) {
204 case DynamicsProcessing::Tag::engineArchitecture: {
205 dpParam.set<DynamicsProcessing::engineArchitecture>(mContext->getEngineArchitecture());
206 break;
207 }
208 case DynamicsProcessing::Tag::preEq: {
209 dpParam.set<DynamicsProcessing::preEq>(mContext->getPreEqChannelCfgs());
210 break;
211 }
212 case DynamicsProcessing::Tag::postEq: {
213 dpParam.set<DynamicsProcessing::postEq>(mContext->getPostEqChannelCfgs());
214 break;
215 }
216 case DynamicsProcessing::Tag::mbc: {
217 dpParam.set<DynamicsProcessing::mbc>(mContext->getMbcChannelCfgs());
218 break;
219 }
220 case DynamicsProcessing::Tag::preEqBand: {
221 dpParam.set<DynamicsProcessing::preEqBand>(mContext->getPreEqBandCfgs());
222 break;
223 }
224 case DynamicsProcessing::Tag::postEqBand: {
225 dpParam.set<DynamicsProcessing::postEqBand>(mContext->getPostEqBandCfgs());
226 break;
227 }
228 case DynamicsProcessing::Tag::mbcBand: {
229 dpParam.set<DynamicsProcessing::mbcBand>(mContext->getMbcBandCfgs());
230 break;
231 }
232 case DynamicsProcessing::Tag::limiter: {
233 dpParam.set<DynamicsProcessing::limiter>(mContext->getLimiterCfgs());
234 break;
235 }
236 case DynamicsProcessing::Tag::inputGain: {
237 dpParam.set<DynamicsProcessing::inputGain>(mContext->getInputGainCfgs());
238 break;
239 }
240 case DynamicsProcessing::vendorExtension: {
241 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
242 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
243 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
244 }
245 }
246
247 specific->set<Parameter::Specific::dynamicsProcessing>(dpParam);
248 LOG(INFO) << __func__ << specific->toString();
Shunkai Yao6afc8552022-10-26 22:47:20 +0000249 return ndk::ScopedAStatus::ok();
250}
251
252std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
253 const Parameter::Common& common) {
254 if (mContext) {
255 LOG(DEBUG) << __func__ << " context already exist";
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530256 } else {
257 mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000258 }
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530259 return mContext;
260}
261
262std::shared_ptr<EffectContext> DynamicsProcessingSw::getContext() {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000263 return mContext;
264}
265
266RetCode DynamicsProcessingSw::releaseContext() {
267 if (mContext) {
268 mContext.reset();
269 }
270 return RetCode::SUCCESS;
271}
272
273// Processing method running in EffectWorker thread.
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530274IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int samples) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000275 // TODO: get data buffer and process.
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530276 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
277 for (int i = 0; i < samples; i++) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000278 *out++ = *in++;
279 }
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530280 return {STATUS_OK, samples, samples};
Shunkai Yao6afc8552022-10-26 22:47:20 +0000281}
282
Ram Mohane4064ce2022-12-20 18:05:14 +0530283RetCode DynamicsProcessingSwContext::setCommon(const Parameter::Common& common) {
284 mCommon = common;
285 mChannelCount =
286 ::android::hardware::audio::common::getChannelCount(common.input.base.channelMask);
287 resizeChannels();
288 resizeBands();
289 LOG(INFO) << __func__ << mCommon.toString();
290 return RetCode::SUCCESS;
291}
292
293RetCode DynamicsProcessingSwContext::setEngineArchitecture(
294 const DynamicsProcessing::EngineArchitecture& cfg) {
295 RETURN_VALUE_IF(!validateEngineConfig(cfg), RetCode::ERROR_ILLEGAL_PARAMETER,
296 "illegalEngineConfig");
297
298 if (mEngineSettings == cfg) {
299 LOG(INFO) << __func__ << " not change in engine, do nothing";
300 return RetCode::SUCCESS;
301 }
302 mEngineSettings = cfg;
303 resizeBands();
304 return RetCode::SUCCESS;
305}
306
307RetCode DynamicsProcessingSwContext::setChannelCfgs(
308 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
309 std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
310 const DynamicsProcessing::StageEnablement& stage) {
311 RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
312
313 RetCode ret = RetCode::SUCCESS;
314 std::unordered_set<int> channelSet;
315 for (auto& cfg : cfgs) {
316 if (cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount) {
317 LOG(ERROR) << __func__ << " skip illegal channel config " << cfg.toString();
318 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
319 continue;
320 }
321 if (0 != channelSet.count(cfg.channel)) {
322 LOG(WARNING) << __func__ << " duplicated channel " << cfg.channel;
323 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
324 } else {
325 channelSet.insert(cfg.channel);
326 }
327 targetCfgs[cfg.channel] = cfg;
328 }
329 return ret;
330}
331
332RetCode DynamicsProcessingSwContext::setPreEqChannelCfgs(
333 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
334 return setChannelCfgs(cfgs, mPreEqChCfgs, mEngineSettings.preEqStage);
335}
336
337RetCode DynamicsProcessingSwContext::setPostEqChannelCfgs(
338 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
339 return setChannelCfgs(cfgs, mPostEqChCfgs, mEngineSettings.postEqStage);
340}
341
342RetCode DynamicsProcessingSwContext::setMbcChannelCfgs(
343 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
344 return setChannelCfgs(cfgs, mMbcChCfgs, mEngineSettings.mbcStage);
345}
346
347RetCode DynamicsProcessingSwContext::setEqBandCfgs(
348 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
349 std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
350 const DynamicsProcessing::StageEnablement& stage,
351 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
352 RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "eqStageNotInUse");
353
354 RetCode ret = RetCode::SUCCESS;
355 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
356
357 for (auto& cfg : cfgs) {
358 if (0 != bandSet.count({cfg.channel, cfg.band})) {
359 LOG(WARNING) << __func__ << " duplicated band " << cfg.toString();
360 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
361 } else {
362 bandSet.insert({cfg.channel, cfg.band});
363 }
364 if (!validateEqBandConfig(cfg, mChannelCount, stage.bandCount, channelConfig)) {
365 LOG(WARNING) << __func__ << " skip invalid band " << cfg.toString();
366 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
367 continue;
Ram Mohane4064ce2022-12-20 18:05:14 +0530368 }
369 targetCfgs[cfg.channel * stage.bandCount + cfg.band] = cfg;
370 }
371 return ret;
372}
373
374RetCode DynamicsProcessingSwContext::setPreEqBandCfgs(
375 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
376 return setEqBandCfgs(cfgs, mPreEqChBands, mEngineSettings.preEqStage, mPreEqChCfgs);
377}
378
379RetCode DynamicsProcessingSwContext::setPostEqBandCfgs(
380 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
381 return setEqBandCfgs(cfgs, mPostEqChBands, mEngineSettings.postEqStage, mPostEqChCfgs);
382}
383
384RetCode DynamicsProcessingSwContext::setMbcBandCfgs(
385 const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
386 RETURN_VALUE_IF(!mEngineSettings.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
387 "mbcNotInUse");
388
389 RetCode ret = RetCode::SUCCESS;
390 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
391
392 int bandCount = mEngineSettings.mbcStage.bandCount;
393 std::vector<bool> filled(mChannelCount * bandCount, false);
394 for (auto& it : cfgs) {
395 if (0 != bandSet.count({it.channel, it.band})) {
396 LOG(WARNING) << __func__ << " duplicated band " << it.toString();
397 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
398 } else {
399 bandSet.insert({it.channel, it.band});
400 }
401 if (!validateMbcBandConfig(it, mChannelCount, mEngineSettings.mbcStage.bandCount,
402 mMbcChCfgs)) {
403 LOG(WARNING) << __func__ << " skip invalid band " << it.toString();
404 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
405 continue;
Ram Mohane4064ce2022-12-20 18:05:14 +0530406 }
407 mMbcChBands[it.channel * bandCount + it.band] = it;
408 }
409 return ret;
410}
411
412RetCode DynamicsProcessingSwContext::setLimiterCfgs(
413 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
414 RETURN_VALUE_IF(!mEngineSettings.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
415 "limiterNotInUse");
416
417 RetCode ret = RetCode::SUCCESS;
418 std::unordered_set<int> channelSet;
419
420 for (auto& it : cfgs) {
421 if (0 != channelSet.count(it.channel)) {
422 LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
423 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
424 } else {
425 channelSet.insert(it.channel);
426 }
427 if (!validateLimiterConfig(it, mChannelCount)) {
428 LOG(WARNING) << __func__ << " skip invalid limiter " << it.toString();
429 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
430 continue;
431 }
432 mLimiterCfgs[it.channel] = it;
433 }
434 return ret;
435}
436
437void DynamicsProcessingSwContext::resizeChannels() {
438 if (mPreEqChCfgs.size() != mChannelCount) {
439 mPreEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
440 }
441 if (mPostEqChCfgs.size() != mChannelCount) {
442 mPostEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
443 }
444 if (mMbcChCfgs.size() != mChannelCount) {
445 mMbcChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
446 }
447 if (mLimiterCfgs.size() != mChannelCount) {
448 mLimiterCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
449 }
450 if (mInputGainCfgs.size() != mChannelCount) {
451 mInputGainCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
452 }
453}
454
455void DynamicsProcessingSwContext::resizeBands() {
456 if (mPreEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.preEqStage.bandCount)) {
457 mPreEqChBands.resize(mChannelCount * mEngineSettings.preEqStage.bandCount,
458 {.channel = kInvalidChannelId});
459 }
460 if (mPostEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.postEqStage.bandCount)) {
461 mPostEqChBands.resize(mChannelCount * mEngineSettings.postEqStage.bandCount,
462 {.channel = kInvalidChannelId});
463 }
464 if (mMbcChBands.size() != (size_t)(mChannelCount * mEngineSettings.mbcStage.bandCount)) {
465 mMbcChBands.resize(mChannelCount * mEngineSettings.mbcStage.bandCount,
466 {.channel = kInvalidChannelId});
467 }
468}
469
470RetCode DynamicsProcessingSwContext::setInputGainCfgs(
471 const std::vector<DynamicsProcessing::InputGain>& cfgs) {
472 for (const auto& cfg : cfgs) {
473 RETURN_VALUE_IF(cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount,
474 RetCode::ERROR_ILLEGAL_PARAMETER, "invalidChannel");
475 mInputGainCfgs[cfg.channel] = cfg;
476 }
477 return RetCode::SUCCESS;
478}
479
480std::vector<DynamicsProcessing::InputGain> DynamicsProcessingSwContext::getInputGainCfgs() {
481 std::vector<DynamicsProcessing::InputGain> ret;
482 std::copy_if(mInputGainCfgs.begin(), mInputGainCfgs.end(), std::back_inserter(ret),
483 [&](const auto& gain) { return gain.channel != kInvalidChannelId; });
484 return ret;
485}
486
Ram Mohane4064ce2022-12-20 18:05:14 +0530487bool DynamicsProcessingSwContext::validateStageEnablement(
488 const DynamicsProcessing::StageEnablement& enablement) {
489 return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
490}
491
492bool DynamicsProcessingSwContext::validateEngineConfig(
493 const DynamicsProcessing::EngineArchitecture& engine) {
494 return engine.preferredProcessingDurationMs >= 0 &&
495 validateStageEnablement(engine.preEqStage) &&
496 validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
497}
498
499bool DynamicsProcessingSwContext::validateEqBandConfig(
500 const DynamicsProcessing::EqBandConfig& band, int maxChannel, int maxBand,
501 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
502 return band.channel >= 0 && band.channel < maxChannel &&
503 (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
Shunkai Yao87811022023-02-13 17:40:37 +0000504 band.band >= 0 && band.band < maxBand;
Ram Mohane4064ce2022-12-20 18:05:14 +0530505}
506
507bool DynamicsProcessingSwContext::validateMbcBandConfig(
508 const DynamicsProcessing::MbcBandConfig& band, int maxChannel, int maxBand,
509 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
510 return band.channel >= 0 && band.channel < maxChannel &&
511 (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
Shunkai Yao87811022023-02-13 17:40:37 +0000512 band.band >= 0 && band.band < maxBand && band.attackTimeMs >= 0 &&
Ram Mohane4064ce2022-12-20 18:05:14 +0530513 band.releaseTimeMs >= 0 && band.ratio >= 0 && band.thresholdDb <= 0 &&
514 band.kneeWidthDb <= 0 && band.noiseGateThresholdDb <= 0 && band.expanderRatio >= 0;
515}
516
517bool DynamicsProcessingSwContext::validateLimiterConfig(
518 const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
519 return limiter.channel >= 0 && limiter.channel < maxChannel && limiter.attackTimeMs >= 0 &&
520 limiter.releaseTimeMs >= 0 && limiter.ratio >= 0 && limiter.thresholdDb <= 0;
521}
522
Shunkai Yao6afc8552022-10-26 22:47:20 +0000523} // namespace aidl::android::hardware::audio::effect