DynamicsProcessing: Add AIDL placeholder implementation and its unit test
Update audio_effects_config.xml to use libeffect dynamicsProcessing
implementation.
Bug: 258124419
Test: atest VtsHalDynamicsProcessingTargetTest
Test: atest VtsHalAudioEffectTargetTest
Change-Id: If93d084be383b716ff950faf1c3e23d6c1edaa66
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
index 39345a9..0ffbaa1 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "AHAL_DynamicsProcessingSw"
#include <Utils.h>
#include <algorithm>
+#include <set>
#include <unordered_set>
#include <android-base/logging.h>
@@ -60,7 +61,8 @@
namespace aidl::android::hardware::audio::effect {
const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
-const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability;
+const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability = {.minCutOffFreq = 220,
+ .maxCutOffFreq = 20000};
const Descriptor DynamicsProcessingSw::kDescriptor = {
.common = {.id = {.type = kDynamicsProcessingTypeUUID,
.uuid = kDynamicsProcessingSwImplUUID,
@@ -83,16 +85,143 @@
RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::dynamicsProcessing>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
- return ndk::ScopedAStatus::ok();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ LOG(INFO) << __func__ << specific.toString();
+ auto& dpParam = specific.get<Parameter::Specific::dynamicsProcessing>();
+ auto tag = dpParam.getTag();
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ RETURN_IF(mContext->setEngineArchitecture(
+ dpParam.get<DynamicsProcessing::engineArchitecture>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEq: {
+ RETURN_IF(mContext->setPreEqChannelCfgs(dpParam.get<DynamicsProcessing::preEq>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEq: {
+ RETURN_IF(mContext->setPostEqChannelCfgs(dpParam.get<DynamicsProcessing::postEq>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbc: {
+ RETURN_IF(mContext->setMbcChannelCfgs(dpParam.get<DynamicsProcessing::mbc>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEqBand: {
+ RETURN_IF(mContext->setPreEqBandCfgs(dpParam.get<DynamicsProcessing::preEqBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEqBand: {
+ RETURN_IF(mContext->setPostEqBandCfgs(dpParam.get<DynamicsProcessing::postEqBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbcBand: {
+ RETURN_IF(mContext->setMbcBandCfgs(dpParam.get<DynamicsProcessing::mbcBand>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::limiter: {
+ RETURN_IF(mContext->setLimiterCfgs(dpParam.get<DynamicsProcessing::limiter>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "limiterCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::inputGain: {
+ RETURN_IF(mContext->setInputGainCfgs(dpParam.get<DynamicsProcessing::inputGain>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "inputGainCfgFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::vendorExtension: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
+ }
+ }
}
ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::dynamicsProcessing>(mSpecificParam);
+ auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
+ auto dpIdTag = dpId.getTag();
+ switch (dpIdTag) {
+ case DynamicsProcessing::Id::commonTag:
+ return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
+ specific);
+ case DynamicsProcessing::Id::vendorExtensionTag:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(dpIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DynamicsProcessingSw::getParameterDynamicsProcessing(
+ const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ DynamicsProcessing dpParam;
+ switch (tag) {
+ case DynamicsProcessing::Tag::engineArchitecture: {
+ dpParam.set<DynamicsProcessing::engineArchitecture>(mContext->getEngineArchitecture());
+ break;
+ }
+ case DynamicsProcessing::Tag::preEq: {
+ dpParam.set<DynamicsProcessing::preEq>(mContext->getPreEqChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::postEq: {
+ dpParam.set<DynamicsProcessing::postEq>(mContext->getPostEqChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::mbc: {
+ dpParam.set<DynamicsProcessing::mbc>(mContext->getMbcChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::preEqBand: {
+ dpParam.set<DynamicsProcessing::preEqBand>(mContext->getPreEqBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::postEqBand: {
+ dpParam.set<DynamicsProcessing::postEqBand>(mContext->getPostEqBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::mbcBand: {
+ dpParam.set<DynamicsProcessing::mbcBand>(mContext->getMbcBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::limiter: {
+ dpParam.set<DynamicsProcessing::limiter>(mContext->getLimiterCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::inputGain: {
+ dpParam.set<DynamicsProcessing::inputGain>(mContext->getInputGainCfgs());
+ break;
+ }
+ case DynamicsProcessing::vendorExtension: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::dynamicsProcessing>(dpParam);
+ LOG(INFO) << __func__ << specific->toString();
return ndk::ScopedAStatus::ok();
}
@@ -127,4 +256,252 @@
return {STATUS_OK, samples, samples};
}
+RetCode DynamicsProcessingSwContext::setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ mChannelCount =
+ ::android::hardware::audio::common::getChannelCount(common.input.base.channelMask);
+ resizeChannels();
+ resizeBands();
+ LOG(INFO) << __func__ << mCommon.toString();
+ return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingSwContext::setEngineArchitecture(
+ const DynamicsProcessing::EngineArchitecture& cfg) {
+ RETURN_VALUE_IF(!validateEngineConfig(cfg), RetCode::ERROR_ILLEGAL_PARAMETER,
+ "illegalEngineConfig");
+
+ if (mEngineSettings == cfg) {
+ LOG(INFO) << __func__ << " not change in engine, do nothing";
+ return RetCode::SUCCESS;
+ }
+ mEngineSettings = cfg;
+ resizeBands();
+ return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingSwContext::setChannelCfgs(
+ const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
+ std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage) {
+ RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::unordered_set<int> channelSet;
+ for (auto& cfg : cfgs) {
+ if (cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount) {
+ LOG(ERROR) << __func__ << " skip illegal channel config " << cfg.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ }
+ if (0 != channelSet.count(cfg.channel)) {
+ LOG(WARNING) << __func__ << " duplicated channel " << cfg.channel;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ channelSet.insert(cfg.channel);
+ }
+ targetCfgs[cfg.channel] = cfg;
+ }
+ return ret;
+}
+
+RetCode DynamicsProcessingSwContext::setPreEqChannelCfgs(
+ const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
+ return setChannelCfgs(cfgs, mPreEqChCfgs, mEngineSettings.preEqStage);
+}
+
+RetCode DynamicsProcessingSwContext::setPostEqChannelCfgs(
+ const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
+ return setChannelCfgs(cfgs, mPostEqChCfgs, mEngineSettings.postEqStage);
+}
+
+RetCode DynamicsProcessingSwContext::setMbcChannelCfgs(
+ const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
+ return setChannelCfgs(cfgs, mMbcChCfgs, mEngineSettings.mbcStage);
+}
+
+RetCode DynamicsProcessingSwContext::setEqBandCfgs(
+ const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
+ std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
+ RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "eqStageNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::set<std::pair<int /* channel */, int /* band */>> bandSet;
+
+ for (auto& cfg : cfgs) {
+ if (0 != bandSet.count({cfg.channel, cfg.band})) {
+ LOG(WARNING) << __func__ << " duplicated band " << cfg.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ bandSet.insert({cfg.channel, cfg.band});
+ }
+ if (!validateEqBandConfig(cfg, mChannelCount, stage.bandCount, channelConfig)) {
+ LOG(WARNING) << __func__ << " skip invalid band " << cfg.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ ;
+ }
+ targetCfgs[cfg.channel * stage.bandCount + cfg.band] = cfg;
+ }
+ return ret;
+}
+
+RetCode DynamicsProcessingSwContext::setPreEqBandCfgs(
+ const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
+ return setEqBandCfgs(cfgs, mPreEqChBands, mEngineSettings.preEqStage, mPreEqChCfgs);
+}
+
+RetCode DynamicsProcessingSwContext::setPostEqBandCfgs(
+ const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
+ return setEqBandCfgs(cfgs, mPostEqChBands, mEngineSettings.postEqStage, mPostEqChCfgs);
+}
+
+RetCode DynamicsProcessingSwContext::setMbcBandCfgs(
+ const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
+ RETURN_VALUE_IF(!mEngineSettings.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "mbcNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::set<std::pair<int /* channel */, int /* band */>> bandSet;
+
+ int bandCount = mEngineSettings.mbcStage.bandCount;
+ std::vector<bool> filled(mChannelCount * bandCount, false);
+ for (auto& it : cfgs) {
+ if (0 != bandSet.count({it.channel, it.band})) {
+ LOG(WARNING) << __func__ << " duplicated band " << it.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ bandSet.insert({it.channel, it.band});
+ }
+ if (!validateMbcBandConfig(it, mChannelCount, mEngineSettings.mbcStage.bandCount,
+ mMbcChCfgs)) {
+ LOG(WARNING) << __func__ << " skip invalid band " << it.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ ;
+ }
+ mMbcChBands[it.channel * bandCount + it.band] = it;
+ }
+ return ret;
+}
+
+RetCode DynamicsProcessingSwContext::setLimiterCfgs(
+ const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
+ RETURN_VALUE_IF(!mEngineSettings.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "limiterNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::unordered_set<int> channelSet;
+
+ for (auto& it : cfgs) {
+ if (0 != channelSet.count(it.channel)) {
+ LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ channelSet.insert(it.channel);
+ }
+ if (!validateLimiterConfig(it, mChannelCount)) {
+ LOG(WARNING) << __func__ << " skip invalid limiter " << it.toString();
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ continue;
+ }
+ mLimiterCfgs[it.channel] = it;
+ }
+ return ret;
+}
+
+void DynamicsProcessingSwContext::resizeChannels() {
+ if (mPreEqChCfgs.size() != mChannelCount) {
+ mPreEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
+ }
+ if (mPostEqChCfgs.size() != mChannelCount) {
+ mPostEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
+ }
+ if (mMbcChCfgs.size() != mChannelCount) {
+ mMbcChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
+ }
+ if (mLimiterCfgs.size() != mChannelCount) {
+ mLimiterCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
+ }
+ if (mInputGainCfgs.size() != mChannelCount) {
+ mInputGainCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
+ }
+}
+
+void DynamicsProcessingSwContext::resizeBands() {
+ if (mPreEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.preEqStage.bandCount)) {
+ mPreEqChBands.resize(mChannelCount * mEngineSettings.preEqStage.bandCount,
+ {.channel = kInvalidChannelId});
+ }
+ if (mPostEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.postEqStage.bandCount)) {
+ mPostEqChBands.resize(mChannelCount * mEngineSettings.postEqStage.bandCount,
+ {.channel = kInvalidChannelId});
+ }
+ if (mMbcChBands.size() != (size_t)(mChannelCount * mEngineSettings.mbcStage.bandCount)) {
+ mMbcChBands.resize(mChannelCount * mEngineSettings.mbcStage.bandCount,
+ {.channel = kInvalidChannelId});
+ }
+}
+
+RetCode DynamicsProcessingSwContext::setInputGainCfgs(
+ const std::vector<DynamicsProcessing::InputGain>& cfgs) {
+ for (const auto& cfg : cfgs) {
+ RETURN_VALUE_IF(cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount,
+ RetCode::ERROR_ILLEGAL_PARAMETER, "invalidChannel");
+ mInputGainCfgs[cfg.channel] = cfg;
+ }
+ return RetCode::SUCCESS;
+}
+
+std::vector<DynamicsProcessing::InputGain> DynamicsProcessingSwContext::getInputGainCfgs() {
+ std::vector<DynamicsProcessing::InputGain> ret;
+ std::copy_if(mInputGainCfgs.begin(), mInputGainCfgs.end(), std::back_inserter(ret),
+ [&](const auto& gain) { return gain.channel != kInvalidChannelId; });
+ return ret;
+}
+
+bool DynamicsProcessingSwContext::validateCutoffFrequency(float freq) {
+ return freq >= DynamicsProcessingSw::kCapability.minCutOffFreq &&
+ freq <= DynamicsProcessingSw::kCapability.maxCutOffFreq;
+}
+
+bool DynamicsProcessingSwContext::validateStageEnablement(
+ const DynamicsProcessing::StageEnablement& enablement) {
+ return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
+}
+
+bool DynamicsProcessingSwContext::validateEngineConfig(
+ const DynamicsProcessing::EngineArchitecture& engine) {
+ return engine.preferredProcessingDurationMs >= 0 &&
+ validateStageEnablement(engine.preEqStage) &&
+ validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
+}
+
+bool DynamicsProcessingSwContext::validateEqBandConfig(
+ const DynamicsProcessing::EqBandConfig& band, int maxChannel, int maxBand,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
+ return band.channel >= 0 && band.channel < maxChannel &&
+ (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
+ band.band >= 0 && band.band < maxBand && validateCutoffFrequency(band.cutoffFrequencyHz);
+}
+
+bool DynamicsProcessingSwContext::validateMbcBandConfig(
+ const DynamicsProcessing::MbcBandConfig& band, int maxChannel, int maxBand,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
+ return band.channel >= 0 && band.channel < maxChannel &&
+ (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
+ band.band >= 0 && band.band < maxBand &&
+ validateCutoffFrequency(band.cutoffFrequencyHz) && band.attackTimeMs >= 0 &&
+ band.releaseTimeMs >= 0 && band.ratio >= 0 && band.thresholdDb <= 0 &&
+ band.kneeWidthDb <= 0 && band.noiseGateThresholdDb <= 0 && band.expanderRatio >= 0;
+}
+
+bool DynamicsProcessingSwContext::validateLimiterConfig(
+ const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
+ return limiter.channel >= 0 && limiter.channel < maxChannel && limiter.attackTimeMs >= 0 &&
+ limiter.releaseTimeMs >= 0 && limiter.ratio >= 0 && limiter.thresholdDb <= 0;
+}
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
index 2ae46c5..e336df7 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
@@ -29,11 +29,77 @@
class DynamicsProcessingSwContext final : public EffectContext {
public:
DynamicsProcessingSwContext(int statusDepth, const Parameter::Common& common)
- : EffectContext(statusDepth, common) {
+ : EffectContext(statusDepth, common),
+ mChannelCount(::android::hardware::audio::common::getChannelCount(
+ common.input.base.channelMask)),
+ mPreEqChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
+ mPostEqChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
+ mMbcChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
+ mLimiterCfgs(mChannelCount, {.channel = kInvalidChannelId}) {
LOG(DEBUG) << __func__;
}
- // TODO: add specific context here
-};
+
+ // utils
+ RetCode setChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
+ std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
+ const DynamicsProcessing::StageEnablement& engineSetting);
+
+ RetCode setEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
+ std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
+
+ // set params
+ RetCode setCommon(const Parameter::Common& common) override;
+ RetCode setEngineArchitecture(const DynamicsProcessing::EngineArchitecture& cfg);
+ RetCode setPreEqChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
+ RetCode setPostEqChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
+ RetCode setMbcChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
+ RetCode setPreEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
+ RetCode setPostEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
+ RetCode setMbcBandCfgs(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs);
+ RetCode setLimiterCfgs(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs);
+ RetCode setInputGainCfgs(const std::vector<DynamicsProcessing::InputGain>& cfgs);
+
+ // get params
+ DynamicsProcessing::EngineArchitecture getEngineArchitecture() { return mEngineSettings; }
+ std::vector<DynamicsProcessing::ChannelConfig> getPreEqChannelCfgs() { return mPreEqChCfgs; }
+ std::vector<DynamicsProcessing::ChannelConfig> getPostEqChannelCfgs() { return mPostEqChCfgs; }
+ std::vector<DynamicsProcessing::ChannelConfig> getMbcChannelCfgs() { return mMbcChCfgs; }
+ std::vector<DynamicsProcessing::EqBandConfig> getPreEqBandCfgs() { return mPreEqChBands; }
+ std::vector<DynamicsProcessing::EqBandConfig> getPostEqBandCfgs() { return mPostEqChBands; }
+ std::vector<DynamicsProcessing::MbcBandConfig> getMbcBandCfgs() { return mMbcChBands; }
+ std::vector<DynamicsProcessing::LimiterConfig> getLimiterCfgs() { return mLimiterCfgs; }
+ std::vector<DynamicsProcessing::InputGain> getInputGainCfgs();
+
+ private:
+ static constexpr int32_t kInvalidChannelId = -1;
+ size_t mChannelCount = 0;
+ DynamicsProcessing::EngineArchitecture mEngineSettings;
+ // Channel config vector with size of mChannelCount
+ std::vector<DynamicsProcessing::ChannelConfig> mPreEqChCfgs;
+ std::vector<DynamicsProcessing::ChannelConfig> mPostEqChCfgs;
+ std::vector<DynamicsProcessing::ChannelConfig> mMbcChCfgs;
+ std::vector<DynamicsProcessing::LimiterConfig> mLimiterCfgs;
+ std::vector<DynamicsProcessing::InputGain> mInputGainCfgs;
+ // Band config vector with size of mChannelCount * bandCount
+ std::vector<DynamicsProcessing::EqBandConfig> mPreEqChBands;
+ std::vector<DynamicsProcessing::EqBandConfig> mPostEqChBands;
+ std::vector<DynamicsProcessing::MbcBandConfig> mMbcChBands;
+
+ bool validateCutoffFrequency(float freq);
+ bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
+ bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
+ bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
+ int maxBand,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
+ bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
+ int maxBand,
+ const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
+ bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
+ void resizeChannels();
+ void resizeBands();
+}; // DynamicsProcessingSwContext
class DynamicsProcessingSw final : public EffectImpl {
public:
@@ -60,7 +126,9 @@
private:
std::shared_ptr<DynamicsProcessingSwContext> mContext;
- /* parameters */
- DynamicsProcessing mSpecificParam;
-};
+ ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
+ Parameter::Specific* specific);
+
+}; // DynamicsProcessingSw
+
} // namespace aidl::android::hardware::audio::effect