blob: 0ffbaa11cca8895cc3f380040331d2dd46363a8d [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";
Ram Mohane4064ce2022-12-20 18:05:14 +053064const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability = {.minCutOffFreq = 220,
65 .maxCutOffFreq = 20000};
Shunkai Yaoc12e0822022-12-12 07:13:58 +000066const Descriptor DynamicsProcessingSw::kDescriptor = {
67 .common = {.id = {.type = kDynamicsProcessingTypeUUID,
68 .uuid = kDynamicsProcessingSwImplUUID,
69 .proxy = std::nullopt},
70 .flags = {.type = Flags::Type::INSERT,
71 .insert = Flags::Insert::FIRST,
72 .volume = Flags::Volume::CTRL},
73 .name = DynamicsProcessingSw::kEffectName,
74 .implementor = "The Android Open Source Project"},
75 .capability = Capability::make<Capability::dynamicsProcessing>(
76 DynamicsProcessingSw::kCapability)};
77
Shunkai Yao6afc8552022-10-26 22:47:20 +000078ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
79 LOG(DEBUG) << __func__ << kDescriptor.toString();
80 *_aidl_return = kDescriptor;
81 return ndk::ScopedAStatus::ok();
82}
83
84ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
85 RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
86 "EffectNotSupported");
Shunkai Yao6afc8552022-10-26 22:47:20 +000087
Ram Mohane4064ce2022-12-20 18:05:14 +053088 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
89
90 LOG(INFO) << __func__ << specific.toString();
91 auto& dpParam = specific.get<Parameter::Specific::dynamicsProcessing>();
92 auto tag = dpParam.getTag();
93 switch (tag) {
94 case DynamicsProcessing::engineArchitecture: {
95 RETURN_IF(mContext->setEngineArchitecture(
96 dpParam.get<DynamicsProcessing::engineArchitecture>()) !=
97 RetCode::SUCCESS,
98 EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
99 return ndk::ScopedAStatus::ok();
100 }
101 case DynamicsProcessing::preEq: {
102 RETURN_IF(mContext->setPreEqChannelCfgs(dpParam.get<DynamicsProcessing::preEq>()) !=
103 RetCode::SUCCESS,
104 EX_ILLEGAL_ARGUMENT, "setPreEqChannelCfgsFailed");
105 return ndk::ScopedAStatus::ok();
106 }
107 case DynamicsProcessing::postEq: {
108 RETURN_IF(mContext->setPostEqChannelCfgs(dpParam.get<DynamicsProcessing::postEq>()) !=
109 RetCode::SUCCESS,
110 EX_ILLEGAL_ARGUMENT, "setPostEqChannelCfgsFailed");
111 return ndk::ScopedAStatus::ok();
112 }
113 case DynamicsProcessing::mbc: {
114 RETURN_IF(mContext->setMbcChannelCfgs(dpParam.get<DynamicsProcessing::mbc>()) !=
115 RetCode::SUCCESS,
116 EX_ILLEGAL_ARGUMENT, "setMbcChannelCfgsFailed");
117 return ndk::ScopedAStatus::ok();
118 }
119 case DynamicsProcessing::preEqBand: {
120 RETURN_IF(mContext->setPreEqBandCfgs(dpParam.get<DynamicsProcessing::preEqBand>()) !=
121 RetCode::SUCCESS,
122 EX_ILLEGAL_ARGUMENT, "setPreEqBandCfgsFailed");
123 return ndk::ScopedAStatus::ok();
124 }
125 case DynamicsProcessing::postEqBand: {
126 RETURN_IF(mContext->setPostEqBandCfgs(dpParam.get<DynamicsProcessing::postEqBand>()) !=
127 RetCode::SUCCESS,
128 EX_ILLEGAL_ARGUMENT, "setPostEqBandCfgsFailed");
129 return ndk::ScopedAStatus::ok();
130 }
131 case DynamicsProcessing::mbcBand: {
132 RETURN_IF(mContext->setMbcBandCfgs(dpParam.get<DynamicsProcessing::mbcBand>()) !=
133 RetCode::SUCCESS,
134 EX_ILLEGAL_ARGUMENT, "setMbcBandCfgsFailed");
135 return ndk::ScopedAStatus::ok();
136 }
137 case DynamicsProcessing::limiter: {
138 RETURN_IF(mContext->setLimiterCfgs(dpParam.get<DynamicsProcessing::limiter>()) !=
139 RetCode::SUCCESS,
140 EX_ILLEGAL_ARGUMENT, "limiterCfgsFailed");
141 return ndk::ScopedAStatus::ok();
142 }
143 case DynamicsProcessing::inputGain: {
144 RETURN_IF(mContext->setInputGainCfgs(dpParam.get<DynamicsProcessing::inputGain>()) !=
145 RetCode::SUCCESS,
146 EX_ILLEGAL_ARGUMENT, "inputGainCfgFailed");
147 return ndk::ScopedAStatus::ok();
148 }
149 case DynamicsProcessing::vendorExtension: {
150 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
151 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
152 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
153 }
154 }
Shunkai Yao6afc8552022-10-26 22:47:20 +0000155}
156
157ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
158 Parameter::Specific* specific) {
159 auto tag = id.getTag();
160 RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
Ram Mohane4064ce2022-12-20 18:05:14 +0530161 auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
162 auto dpIdTag = dpId.getTag();
163 switch (dpIdTag) {
164 case DynamicsProcessing::Id::commonTag:
165 return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
166 specific);
167 case DynamicsProcessing::Id::vendorExtensionTag:
168 LOG(ERROR) << __func__ << " unsupported tag: " << toString(dpIdTag);
169 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
170 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
171 }
172}
173
174ndk::ScopedAStatus DynamicsProcessingSw::getParameterDynamicsProcessing(
175 const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
176 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
177
178 DynamicsProcessing dpParam;
179 switch (tag) {
180 case DynamicsProcessing::Tag::engineArchitecture: {
181 dpParam.set<DynamicsProcessing::engineArchitecture>(mContext->getEngineArchitecture());
182 break;
183 }
184 case DynamicsProcessing::Tag::preEq: {
185 dpParam.set<DynamicsProcessing::preEq>(mContext->getPreEqChannelCfgs());
186 break;
187 }
188 case DynamicsProcessing::Tag::postEq: {
189 dpParam.set<DynamicsProcessing::postEq>(mContext->getPostEqChannelCfgs());
190 break;
191 }
192 case DynamicsProcessing::Tag::mbc: {
193 dpParam.set<DynamicsProcessing::mbc>(mContext->getMbcChannelCfgs());
194 break;
195 }
196 case DynamicsProcessing::Tag::preEqBand: {
197 dpParam.set<DynamicsProcessing::preEqBand>(mContext->getPreEqBandCfgs());
198 break;
199 }
200 case DynamicsProcessing::Tag::postEqBand: {
201 dpParam.set<DynamicsProcessing::postEqBand>(mContext->getPostEqBandCfgs());
202 break;
203 }
204 case DynamicsProcessing::Tag::mbcBand: {
205 dpParam.set<DynamicsProcessing::mbcBand>(mContext->getMbcBandCfgs());
206 break;
207 }
208 case DynamicsProcessing::Tag::limiter: {
209 dpParam.set<DynamicsProcessing::limiter>(mContext->getLimiterCfgs());
210 break;
211 }
212 case DynamicsProcessing::Tag::inputGain: {
213 dpParam.set<DynamicsProcessing::inputGain>(mContext->getInputGainCfgs());
214 break;
215 }
216 case DynamicsProcessing::vendorExtension: {
217 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
218 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
219 EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
220 }
221 }
222
223 specific->set<Parameter::Specific::dynamicsProcessing>(dpParam);
224 LOG(INFO) << __func__ << specific->toString();
Shunkai Yao6afc8552022-10-26 22:47:20 +0000225 return ndk::ScopedAStatus::ok();
226}
227
228std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
229 const Parameter::Common& common) {
230 if (mContext) {
231 LOG(DEBUG) << __func__ << " context already exist";
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530232 } else {
233 mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
Shunkai Yao6afc8552022-10-26 22:47:20 +0000234 }
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530235 return mContext;
236}
237
238std::shared_ptr<EffectContext> DynamicsProcessingSw::getContext() {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000239 return mContext;
240}
241
242RetCode DynamicsProcessingSw::releaseContext() {
243 if (mContext) {
244 mContext.reset();
245 }
246 return RetCode::SUCCESS;
247}
248
249// Processing method running in EffectWorker thread.
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530250IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int samples) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000251 // TODO: get data buffer and process.
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530252 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
253 for (int i = 0; i < samples; i++) {
Shunkai Yao6afc8552022-10-26 22:47:20 +0000254 *out++ = *in++;
255 }
Shraddha Basantwanif627d802022-11-08 14:45:07 +0530256 return {STATUS_OK, samples, samples};
Shunkai Yao6afc8552022-10-26 22:47:20 +0000257}
258
Ram Mohane4064ce2022-12-20 18:05:14 +0530259RetCode DynamicsProcessingSwContext::setCommon(const Parameter::Common& common) {
260 mCommon = common;
261 mChannelCount =
262 ::android::hardware::audio::common::getChannelCount(common.input.base.channelMask);
263 resizeChannels();
264 resizeBands();
265 LOG(INFO) << __func__ << mCommon.toString();
266 return RetCode::SUCCESS;
267}
268
269RetCode DynamicsProcessingSwContext::setEngineArchitecture(
270 const DynamicsProcessing::EngineArchitecture& cfg) {
271 RETURN_VALUE_IF(!validateEngineConfig(cfg), RetCode::ERROR_ILLEGAL_PARAMETER,
272 "illegalEngineConfig");
273
274 if (mEngineSettings == cfg) {
275 LOG(INFO) << __func__ << " not change in engine, do nothing";
276 return RetCode::SUCCESS;
277 }
278 mEngineSettings = cfg;
279 resizeBands();
280 return RetCode::SUCCESS;
281}
282
283RetCode DynamicsProcessingSwContext::setChannelCfgs(
284 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
285 std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
286 const DynamicsProcessing::StageEnablement& stage) {
287 RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
288
289 RetCode ret = RetCode::SUCCESS;
290 std::unordered_set<int> channelSet;
291 for (auto& cfg : cfgs) {
292 if (cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount) {
293 LOG(ERROR) << __func__ << " skip illegal channel config " << cfg.toString();
294 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
295 continue;
296 }
297 if (0 != channelSet.count(cfg.channel)) {
298 LOG(WARNING) << __func__ << " duplicated channel " << cfg.channel;
299 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
300 } else {
301 channelSet.insert(cfg.channel);
302 }
303 targetCfgs[cfg.channel] = cfg;
304 }
305 return ret;
306}
307
308RetCode DynamicsProcessingSwContext::setPreEqChannelCfgs(
309 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
310 return setChannelCfgs(cfgs, mPreEqChCfgs, mEngineSettings.preEqStage);
311}
312
313RetCode DynamicsProcessingSwContext::setPostEqChannelCfgs(
314 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
315 return setChannelCfgs(cfgs, mPostEqChCfgs, mEngineSettings.postEqStage);
316}
317
318RetCode DynamicsProcessingSwContext::setMbcChannelCfgs(
319 const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
320 return setChannelCfgs(cfgs, mMbcChCfgs, mEngineSettings.mbcStage);
321}
322
323RetCode DynamicsProcessingSwContext::setEqBandCfgs(
324 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
325 std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
326 const DynamicsProcessing::StageEnablement& stage,
327 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
328 RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "eqStageNotInUse");
329
330 RetCode ret = RetCode::SUCCESS;
331 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
332
333 for (auto& cfg : cfgs) {
334 if (0 != bandSet.count({cfg.channel, cfg.band})) {
335 LOG(WARNING) << __func__ << " duplicated band " << cfg.toString();
336 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
337 } else {
338 bandSet.insert({cfg.channel, cfg.band});
339 }
340 if (!validateEqBandConfig(cfg, mChannelCount, stage.bandCount, channelConfig)) {
341 LOG(WARNING) << __func__ << " skip invalid band " << cfg.toString();
342 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
343 continue;
344 ;
345 }
346 targetCfgs[cfg.channel * stage.bandCount + cfg.band] = cfg;
347 }
348 return ret;
349}
350
351RetCode DynamicsProcessingSwContext::setPreEqBandCfgs(
352 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
353 return setEqBandCfgs(cfgs, mPreEqChBands, mEngineSettings.preEqStage, mPreEqChCfgs);
354}
355
356RetCode DynamicsProcessingSwContext::setPostEqBandCfgs(
357 const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
358 return setEqBandCfgs(cfgs, mPostEqChBands, mEngineSettings.postEqStage, mPostEqChCfgs);
359}
360
361RetCode DynamicsProcessingSwContext::setMbcBandCfgs(
362 const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
363 RETURN_VALUE_IF(!mEngineSettings.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
364 "mbcNotInUse");
365
366 RetCode ret = RetCode::SUCCESS;
367 std::set<std::pair<int /* channel */, int /* band */>> bandSet;
368
369 int bandCount = mEngineSettings.mbcStage.bandCount;
370 std::vector<bool> filled(mChannelCount * bandCount, false);
371 for (auto& it : cfgs) {
372 if (0 != bandSet.count({it.channel, it.band})) {
373 LOG(WARNING) << __func__ << " duplicated band " << it.toString();
374 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
375 } else {
376 bandSet.insert({it.channel, it.band});
377 }
378 if (!validateMbcBandConfig(it, mChannelCount, mEngineSettings.mbcStage.bandCount,
379 mMbcChCfgs)) {
380 LOG(WARNING) << __func__ << " skip invalid band " << it.toString();
381 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
382 continue;
383 ;
384 }
385 mMbcChBands[it.channel * bandCount + it.band] = it;
386 }
387 return ret;
388}
389
390RetCode DynamicsProcessingSwContext::setLimiterCfgs(
391 const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
392 RETURN_VALUE_IF(!mEngineSettings.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
393 "limiterNotInUse");
394
395 RetCode ret = RetCode::SUCCESS;
396 std::unordered_set<int> channelSet;
397
398 for (auto& it : cfgs) {
399 if (0 != channelSet.count(it.channel)) {
400 LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
401 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
402 } else {
403 channelSet.insert(it.channel);
404 }
405 if (!validateLimiterConfig(it, mChannelCount)) {
406 LOG(WARNING) << __func__ << " skip invalid limiter " << it.toString();
407 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
408 continue;
409 }
410 mLimiterCfgs[it.channel] = it;
411 }
412 return ret;
413}
414
415void DynamicsProcessingSwContext::resizeChannels() {
416 if (mPreEqChCfgs.size() != mChannelCount) {
417 mPreEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
418 }
419 if (mPostEqChCfgs.size() != mChannelCount) {
420 mPostEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
421 }
422 if (mMbcChCfgs.size() != mChannelCount) {
423 mMbcChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
424 }
425 if (mLimiterCfgs.size() != mChannelCount) {
426 mLimiterCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
427 }
428 if (mInputGainCfgs.size() != mChannelCount) {
429 mInputGainCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
430 }
431}
432
433void DynamicsProcessingSwContext::resizeBands() {
434 if (mPreEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.preEqStage.bandCount)) {
435 mPreEqChBands.resize(mChannelCount * mEngineSettings.preEqStage.bandCount,
436 {.channel = kInvalidChannelId});
437 }
438 if (mPostEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.postEqStage.bandCount)) {
439 mPostEqChBands.resize(mChannelCount * mEngineSettings.postEqStage.bandCount,
440 {.channel = kInvalidChannelId});
441 }
442 if (mMbcChBands.size() != (size_t)(mChannelCount * mEngineSettings.mbcStage.bandCount)) {
443 mMbcChBands.resize(mChannelCount * mEngineSettings.mbcStage.bandCount,
444 {.channel = kInvalidChannelId});
445 }
446}
447
448RetCode DynamicsProcessingSwContext::setInputGainCfgs(
449 const std::vector<DynamicsProcessing::InputGain>& cfgs) {
450 for (const auto& cfg : cfgs) {
451 RETURN_VALUE_IF(cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount,
452 RetCode::ERROR_ILLEGAL_PARAMETER, "invalidChannel");
453 mInputGainCfgs[cfg.channel] = cfg;
454 }
455 return RetCode::SUCCESS;
456}
457
458std::vector<DynamicsProcessing::InputGain> DynamicsProcessingSwContext::getInputGainCfgs() {
459 std::vector<DynamicsProcessing::InputGain> ret;
460 std::copy_if(mInputGainCfgs.begin(), mInputGainCfgs.end(), std::back_inserter(ret),
461 [&](const auto& gain) { return gain.channel != kInvalidChannelId; });
462 return ret;
463}
464
465bool DynamicsProcessingSwContext::validateCutoffFrequency(float freq) {
466 return freq >= DynamicsProcessingSw::kCapability.minCutOffFreq &&
467 freq <= DynamicsProcessingSw::kCapability.maxCutOffFreq;
468}
469
470bool DynamicsProcessingSwContext::validateStageEnablement(
471 const DynamicsProcessing::StageEnablement& enablement) {
472 return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
473}
474
475bool DynamicsProcessingSwContext::validateEngineConfig(
476 const DynamicsProcessing::EngineArchitecture& engine) {
477 return engine.preferredProcessingDurationMs >= 0 &&
478 validateStageEnablement(engine.preEqStage) &&
479 validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
480}
481
482bool DynamicsProcessingSwContext::validateEqBandConfig(
483 const DynamicsProcessing::EqBandConfig& band, int maxChannel, int maxBand,
484 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
485 return band.channel >= 0 && band.channel < maxChannel &&
486 (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
487 band.band >= 0 && band.band < maxBand && validateCutoffFrequency(band.cutoffFrequencyHz);
488}
489
490bool DynamicsProcessingSwContext::validateMbcBandConfig(
491 const DynamicsProcessing::MbcBandConfig& band, int maxChannel, int maxBand,
492 const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
493 return band.channel >= 0 && band.channel < maxChannel &&
494 (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
495 band.band >= 0 && band.band < maxBand &&
496 validateCutoffFrequency(band.cutoffFrequencyHz) && band.attackTimeMs >= 0 &&
497 band.releaseTimeMs >= 0 && band.ratio >= 0 && band.thresholdDb <= 0 &&
498 band.kneeWidthDb <= 0 && band.noiseGateThresholdDb <= 0 && band.expanderRatio >= 0;
499}
500
501bool DynamicsProcessingSwContext::validateLimiterConfig(
502 const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
503 return limiter.channel >= 0 && limiter.channel < maxChannel && limiter.attackTimeMs >= 0 &&
504 limiter.releaseTimeMs >= 0 && limiter.ratio >= 0 && limiter.thresholdDb <= 0;
505}
506
Shunkai Yao6afc8552022-10-26 22:47:20 +0000507} // namespace aidl::android::hardware::audio::effect