Merge changes from topic "dynamics_processing_aidl"

* changes:
  DynamicsProcessing: Add AIDL placeholder implementation and its unit test
  DynamicsProcessing: update AIDL interface definition
This commit is contained in:
Shunkai Yao
2023-01-07 02:25:02 +00:00
committed by Gerrit Code Review
21 changed files with 1748 additions and 137 deletions

View File

@@ -12,6 +12,9 @@
{
"name": "VtsHalDownmixTargetTest"
},
{
"name": "VtsHalDynamicProcessingTargetTest"
},
{
"name": "VtsHalEnvironmentalReverbTargetTest"
},

View File

@@ -37,14 +37,14 @@ enum CommandId {
START = 0,
STOP = 1,
RESET = 2,
VENDOR_COMMAND_0 = 256,
VENDOR_COMMAND_1 = 257,
VENDOR_COMMAND_2 = 258,
VENDOR_COMMAND_3 = 259,
VENDOR_COMMAND_4 = 260,
VENDOR_COMMAND_5 = 261,
VENDOR_COMMAND_6 = 262,
VENDOR_COMMAND_7 = 263,
VENDOR_COMMAND_8 = 264,
VENDOR_COMMAND_9 = 265,
VENDOR_COMMAND_0 = 0x100,
VENDOR_COMMAND_1,
VENDOR_COMMAND_2,
VENDOR_COMMAND_3,
VENDOR_COMMAND_4,
VENDOR_COMMAND_5,
VENDOR_COMMAND_6,
VENDOR_COMMAND_7,
VENDOR_COMMAND_8,
VENDOR_COMMAND_9,
}

View File

@@ -47,7 +47,7 @@ union Downmix {
}
@VintfStability
enum Type {
STRIP = 0,
FOLD = 1,
STRIP,
FOLD,
}
}

View File

@@ -36,14 +36,14 @@ package android.hardware.audio.effect;
union DynamicsProcessing {
android.hardware.audio.effect.VendorExtension vendorExtension;
android.hardware.audio.effect.DynamicsProcessing.EngineArchitecture engineArchitecture;
android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig preEq;
android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig postEq;
android.hardware.audio.effect.DynamicsProcessing.EqBandConfig preEqBand;
android.hardware.audio.effect.DynamicsProcessing.EqBandConfig postEqBand;
android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig mbc;
android.hardware.audio.effect.DynamicsProcessing.MbcBandConfig mbcBand;
android.hardware.audio.effect.DynamicsProcessing.LimiterConfig limiter;
float inputGainDb;
android.hardware.audio.effect.DynamicsProcessing.ChannelConfig[] preEq;
android.hardware.audio.effect.DynamicsProcessing.ChannelConfig[] postEq;
android.hardware.audio.effect.DynamicsProcessing.EqBandConfig[] preEqBand;
android.hardware.audio.effect.DynamicsProcessing.EqBandConfig[] postEqBand;
android.hardware.audio.effect.DynamicsProcessing.ChannelConfig[] mbc;
android.hardware.audio.effect.DynamicsProcessing.MbcBandConfig[] mbcBand;
android.hardware.audio.effect.DynamicsProcessing.LimiterConfig[] limiter;
android.hardware.audio.effect.DynamicsProcessing.InputGain[] inputGain;
@VintfStability
union Id {
int vendorExtensionTag;
@@ -52,37 +52,39 @@ union DynamicsProcessing {
@VintfStability
parcelable Capability {
ParcelableHolder extension;
float minCutOffFreq;
float maxCutOffFreq;
}
enum ResolutionPreference {
FAVOR_FREQUENCY_RESOLUTION = 0,
FAVOR_TIME_RESOLUTION = 1,
FAVOR_FREQUENCY_RESOLUTION,
FAVOR_TIME_RESOLUTION,
}
@VintfStability
parcelable BandEnablement {
parcelable StageEnablement {
boolean inUse;
int bandCount;
}
@VintfStability
parcelable EngineArchitecture {
android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference resolutionPreference = android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION;
float preferredFrameDurationMs;
android.hardware.audio.effect.DynamicsProcessing.BandEnablement preEqBand;
android.hardware.audio.effect.DynamicsProcessing.BandEnablement postEqBand;
android.hardware.audio.effect.DynamicsProcessing.BandEnablement mbcBand;
float preferredProcessingDurationMs;
android.hardware.audio.effect.DynamicsProcessing.StageEnablement preEqStage;
android.hardware.audio.effect.DynamicsProcessing.StageEnablement postEqStage;
android.hardware.audio.effect.DynamicsProcessing.StageEnablement mbcStage;
boolean limiterInUse;
}
@VintfStability
parcelable BandChannelConfig {
parcelable ChannelConfig {
int channel;
android.hardware.audio.effect.DynamicsProcessing.BandEnablement enablement;
boolean enable;
}
@VintfStability
parcelable EqBandConfig {
int channel;
int band;
boolean enable;
float cutoffFrequency;
float gain;
float cutoffFrequencyHz;
float gainDb;
}
@VintfStability
parcelable MbcBandConfig {
@@ -90,7 +92,6 @@ union DynamicsProcessing {
int band;
boolean enable;
float cutoffFrequencyHz;
float gainDb;
float attackTimeMs;
float releaseTimeMs;
float ratio;
@@ -105,7 +106,6 @@ union DynamicsProcessing {
parcelable LimiterConfig {
int channel;
boolean enable;
boolean inUse;
int linkGroup;
float attackTimeMs;
float releaseTimeMs;
@@ -113,4 +113,9 @@ union DynamicsProcessing {
float thresholdDb;
float postGainDb;
}
@VintfStability
parcelable InputGain {
int channel;
float gainDb;
}
}

View File

@@ -44,15 +44,15 @@ union EnvironmentalReverb {
int diffusionPm;
int densityPm;
boolean bypass;
const int MIN_ROOM_LEVEL_MB = -6000;
const int MIN_ROOM_LEVEL_MB = (-6000);
const int MAX_ROOM_LEVEL_MB = 0;
const int MIN_ROOM_HF_LEVEL_MB = -4000;
const int MIN_ROOM_HF_LEVEL_MB = (-4000);
const int MAX_ROOM_HF_LEVEL_MB = 0;
const int MIN_DECAY_TIME_MS = 100;
const int MAX_DECAY_TIME_MS = 20000;
const int MIN_DECAY_HF_RATIO_PM = 100;
const int MAX_DECAY_HF_RATIO_PM = 1000;
const int MIN_LEVEL_MB = -6000;
const int MIN_LEVEL_MB = (-6000);
const int MAX_LEVEL_MB = 0;
const int MIN_DELAY_MS = 0;
const int MAX_DELAY_MS = 65;

View File

@@ -48,9 +48,9 @@ union HapticGenerator {
}
@Backing(type="int") @VintfStability
enum VibratorScale {
MUTE = -100,
VERY_LOW = -2,
LOW = -1,
MUTE = (-100),
VERY_LOW = (-2),
LOW = (-1),
NONE = 0,
HIGH = 1,
VERY_HIGH = 2,

View File

@@ -47,8 +47,8 @@ union NoiseSuppression {
}
@Backing(type="int") @VintfStability
enum Level {
LOW = 0,
MEDIUM = 1,
HIGH = 2,
LOW,
MEDIUM,
HIGH,
}
}

View File

@@ -38,13 +38,13 @@ union PresetReverb {
android.hardware.audio.effect.PresetReverb.Presets preset;
@Backing(type="int") @VintfStability
enum Presets {
NONE = 0,
SMALLROOM = 1,
MEDIUMROOM = 2,
LARGEROOM = 3,
MEDIUMHALL = 4,
LARGEHALL = 5,
PLATE = 6,
NONE,
SMALLROOM,
MEDIUMROOM,
LARGEROOM,
MEDIUMHALL,
LARGEHALL,
PLATE,
}
@VintfStability
union Id {

View File

@@ -34,7 +34,7 @@
package android.hardware.audio.effect;
@Backing(type="byte") @VintfStability
enum State {
INIT = 0,
IDLE = 1,
PROCESSING = 2,
INIT,
IDLE,
PROCESSING,
}

View File

@@ -62,12 +62,12 @@ union Visualizer {
@VintfStability
enum ScalingMode {
NORMALIZED = 0,
AS_PLAYED = 1,
AS_PLAYED,
}
@VintfStability
enum MeasurementMode {
NONE = 0,
PEAK_RMS = 1,
PEAK_RMS,
}
@VintfStability
union GetOnlyParameters {

View File

@@ -51,6 +51,14 @@ union DynamicsProcessing {
* capability definition not enough.
*/
ParcelableHolder extension;
/**
* Min Cut off frequency (in Hz) for all Bands.
*/
float minCutOffFreq;
/**
* Max Cut off frequency (in Hz) for all Bands.
*/
float maxCutOffFreq;
}
/**
@@ -68,16 +76,16 @@ union DynamicsProcessing {
}
/**
* Band enablement configuration.
* Stage enablement configuration.
*/
@VintfStability
parcelable BandEnablement {
parcelable StageEnablement {
/**
* True if multi-band stage is in use.
* True if stage is in use.
*/
boolean inUse;
/**
* Number of bands configured for this stage.
* Number of bands configured for this stage. Must be positive when inUse is true.
*/
int bandCount;
}
@@ -92,21 +100,22 @@ union DynamicsProcessing {
*/
ResolutionPreference resolutionPreference = ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION;
/**
* Preferred frame duration in milliseconds (ms).
* Preferred processing duration in milliseconds (ms). Must not be negative, 0 means no
* preference.
*/
float preferredFrameDurationMs;
float preferredProcessingDurationMs;
/**
* PreEq stage (Multi-band Equalizer) configuration.
*/
BandEnablement preEqBand;
StageEnablement preEqStage;
/**
* PostEq stage (Multi-band Equalizer) configuration.
*/
BandEnablement postEqBand;
StageEnablement postEqStage;
/**
* MBC stage (Multi-band Compressor) configuration.
*/
BandEnablement mbcBand;
StageEnablement mbcStage;
/**
* True if Limiter stage is in use.
*/
@@ -114,18 +123,19 @@ union DynamicsProcessing {
}
/**
* Band enablement configuration for a specific channel.
* Enablement configuration for a specific channel.
*/
@VintfStability
parcelable BandChannelConfig {
parcelable ChannelConfig {
/**
* Channel index.
* Channel index. Must not be negative, and not exceed the channel count calculated from
* Parameter.common.input.base.channelMask.
*/
int channel;
/**
* Channel index.
* Channel enablement configuration. Can not be true if corresponding stage is not in use.
*/
BandEnablement enablement;
boolean enable;
}
/**
@@ -134,7 +144,8 @@ union DynamicsProcessing {
@VintfStability
parcelable EqBandConfig {
/**
* Channel index.
* Channel index. Must not be negative, and not exceed the channel count calculated from
* Parameter.common.input.base.channelMask.
*/
int channel;
/**
@@ -142,17 +153,20 @@ union DynamicsProcessing {
*/
int band;
/**
* True if EQ stage is enabled.
* True if EQ band is enabled.
* If EngineArchitecture EQ stage inUse was set to false, then enable can not be set to
* true.
*/
boolean enable;
/**
* Topmost frequency number (in Hz) this band will process.
* Topmost frequency number (in Hz) this band will process. Must be in the range of
* [minCutOffFreq, maxCutOffFreq] defined in Capability.
*/
float cutoffFrequency;
float cutoffFrequencyHz;
/**
* Gain factor in decibels (dB).
*/
float gain;
float gainDb;
}
/**
@@ -161,51 +175,53 @@ union DynamicsProcessing {
@VintfStability
parcelable MbcBandConfig {
/**
* Channel index.
* Channel index. Must not be negative, and not exceed the channel count calculated from
* Parameter.common.input.base.channelMask.
*/
int channel;
/**
* Band index, must in the range of [0, bandCount-1].
* Band index. Must be in the range of [0, bandCount-1].
*/
int band;
/**
* True if MBC stage is enabled.
* True if MBC band is enabled.
* If EngineArchitecture MBC inUse was set to false, then enable here can not be set to
* true.
*/
boolean enable;
/**
* Topmost frequency number (in Hz) this band will process.
* Topmost frequency number (in Hz) this band will process. Must be in the range of
* [minCutOffFreq, maxCutOffFreq] defined in Capability.
*/
float cutoffFrequencyHz;
/**
* Gain factor in decibels (dB).
*/
float gainDb;
/**
* Attack Time for compressor in milliseconds (ms).
* Attack Time for compressor in milliseconds (ms). Must not be negative.
*/
float attackTimeMs;
/**
* Release Time for compressor in milliseconds (ms).
* Release Time for compressor in milliseconds (ms). Must not be negative.
*/
float releaseTimeMs;
/**
* Compressor ratio (N:1) (input:output).
* Compressor ratio (N:1) (input:output). Must not be negative.
*/
float ratio;
/**
* Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS).
* Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS). Must not be
* positive.
*/
float thresholdDb;
/**
* Width in decibels (dB) around compressor threshold point.
* Width in decibels (dB) around compressor threshold point. Must not be negative.
*/
float kneeWidthDb;
/**
* Noise gate threshold in decibels (dB) from 0 dB Full Scale (dBFS).
* Noise gate threshold in decibels (dB) from 0 dB Full Scale (dBFS). Must not be positive.
*/
float noiseGateThresholdDb;
/**
* Expander ratio (1:N) (input:output) for signals below the Noise Gate Threshold.
* Expander ratio (1:N) (input:output) for signals below the Noise Gate Threshold. Must not
* be negative.
*/
float expanderRatio;
/**
@@ -224,36 +240,35 @@ union DynamicsProcessing {
@VintfStability
parcelable LimiterConfig {
/**
* Channel index.
* Channel index. Must not be negative, and not exceed the channel count calculated from
* Parameter.common.input.base.channelMask.
*/
int channel;
/**
* True if Limiter stage is enabled.
* True if Limiter band is enabled.
* If EngineArchitecture limiterInUse was set to false, then enable can not be set to true.
*/
boolean enable;
/**
* True if Limiter stage is in use.
*/
boolean inUse;
/**
* Index of group assigned to this Limiter. Only limiters that share the same linkGroup
* index will react together.
*/
int linkGroup;
/**
* Attack Time for compressor in milliseconds (ms).
* Attack Time for compressor in milliseconds (ms). Must not be negative.
*/
float attackTimeMs;
/**
* Release Time for compressor in milliseconds (ms).
* Release Time for compressor in milliseconds (ms). Must not be negative.
*/
float releaseTimeMs;
/**
* Compressor ratio (N:1) (input:output).
* Compressor ratio (N:1) (input:output). Must not be negative.
*/
float ratio;
/**
* Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS).
* Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS). Must not be
* positive.
*/
float thresholdDb;
/**
@@ -262,40 +277,56 @@ union DynamicsProcessing {
float postGainDb;
}
/**
* Input gain for a channel (specified by the channel index).
*/
@VintfStability
parcelable InputGain {
/**
* Channel index. Must not be negative, and not exceed the channel count calculated from
* Parameter.common.input.base.channelMask.
*/
int channel;
/**
* Gain applied to the input signal in decibels (dB). 0 dB means no change in level.
*/
float gainDb;
}
/**
* Effect engine architecture.
*/
EngineArchitecture engineArchitecture;
/**
* PreEq stage per channel configuration.
* PreEq stage per channel configuration. Only valid when pre EQ stage inUse is true.
*/
BandChannelConfig preEq;
ChannelConfig[] preEq;
/**
* PostEq stage per channel configuration.
* PostEq stage per channel configuration. Only valid when post EQ stage inUse is true.
*/
BandChannelConfig postEq;
ChannelConfig[] postEq;
/**
* PreEq stage per band configuration.
* PreEq stage per band configuration. Only valid when pre EQ stage inUse is true.
*/
EqBandConfig preEqBand;
EqBandConfig[] preEqBand;
/**
* PostEq stage per band configuration.
* PostEq stage per band configuration. Only valid when post EQ stage inUse is true.
*/
EqBandConfig postEqBand;
EqBandConfig[] postEqBand;
/**
* MBC stage per channel configuration.
* MBC stage per channel configuration. Only valid when MBC stage inUse is true.
*/
BandChannelConfig mbc;
ChannelConfig[] mbc;
/**
* PostEq stage per band configuration.
* PostEq stage per band configuration. Only valid when MBC stage inUse is true.
*/
MbcBandConfig mbcBand;
MbcBandConfig[] mbcBand;
/**
* Limiter stage configuration.
* Limiter stage configuration. Only valid when limiter stage inUse is true.
*/
LimiterConfig limiter;
LimiterConfig[] limiter;
/**
* Input gain factor in decibels (dB). 0 dB means no change in level.
* Input gain factor.
*/
float inputGainDb;
InputGain[] inputGain;
}

View File

@@ -156,7 +156,7 @@ cc_binary {
"libbassboostsw",
"libbundleaidl",
"libdownmixaidl",
"libdynamicsprocessingsw",
"libdynamicsprocessingaidl",
"libenvreverbsw",
"libequalizersw",
"libhapticgeneratoraidl",

View File

@@ -54,7 +54,6 @@ extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descrip
return EX_ILLEGAL_ARGUMENT;
}
*_aidl_return = AcousticEchoCancelerSw::kDescriptor;
LOG(ERROR) << __func__ << "xxx " << _aidl_return->toString();
return EX_NONE;
}

View File

@@ -33,7 +33,7 @@
<library name="bassboostsw" path="libbassboostsw.so"/>
<library name="bundle" path="libbundleaidl.so"/>
<library name="downmix" path="libdownmixaidl.so"/>
<library name="dynamics_processingsw" path="libdynamicsprocessingsw.so"/>
<library name="dynamics_processing" path="libdynamicsprocessingaidl.so"/>
<library name="equalizersw" path="libequalizersw.so"/>
<library name="haptic_generator" path="libhapticgeneratoraidl.so"/>
<library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
@@ -72,7 +72,7 @@
<libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
</effectProxy>
<effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
<effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
<effect name="dynamics_processing" library="dynamics_processing" uuid="e0e6539b-1781-7261-676f-6d7573696340"/>
<effect name="haptic_generator" library="haptic_generator" uuid="97c4acd1-8b82-4f2f-832e-c2fe5d7a9931"/>
<effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
<effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>

View File

@@ -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 @@ extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descrip
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 @@ ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::S
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 @@ IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, i
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

View File

@@ -29,11 +29,77 @@ namespace aidl::android::hardware::audio::effect {
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 @@ class DynamicsProcessingSw final : public EffectImpl {
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

View File

@@ -119,11 +119,11 @@ class EffectContext {
virtual RetCode setCommon(const Parameter::Common& common) {
mCommon = common;
LOG(ERROR) << __func__ << mCommon.toString();
LOG(INFO) << __func__ << mCommon.toString();
return RetCode::SUCCESS;
}
virtual Parameter::Common getCommon() {
LOG(ERROR) << __func__ << mCommon.toString();
LOG(INFO) << __func__ << mCommon.toString();
return mCommon;
}

View File

@@ -98,12 +98,13 @@ inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
} \
} while (0)
#define RETURN_VALUE_IF(expr, ret, log) \
do { \
if (expr) { \
LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr << (log); \
return ret; \
} \
#define RETURN_VALUE_IF(expr, ret, log) \
do { \
if (expr) { \
LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr \"" << #expr \
<< "\":" << (log); \
return ret; \
} \
} while (0)
#define RETURN_IF_BINDER_EXCEPTION(functor) \

View File

@@ -135,6 +135,12 @@ static const AudioUuid kDynamicsProcessingSwImplUUID = {static_cast<int32_t>(0xf
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
// e0e6539b-1781-7261-676f-6d7573696340
static const AudioUuid kDynamicsProcessingImplUUID = {static_cast<int32_t>(0xe0e6539b),
0x1781,
0x7261,
0x676f,
{0x6d, 0x75, 0x73, 0x69, 0x63, 0x40}};
// 1411e6d6-aecd-4021-a1cf-a6aceb0d71e5
static const AudioUuid kHapticGeneratorTypeUUID = {static_cast<int32_t>(0x1411e6d6),
0xaecd,

View File

@@ -80,6 +80,12 @@ cc_test {
srcs: ["VtsHalDownmixTargetTest.cpp"],
}
cc_test {
name: "VtsHalDynamicsProcessingTargetTest",
defaults: ["VtsHalAudioTargetTestDefaults"],
srcs: ["VtsHalDynamicsProcessingTest.cpp"],
}
cc_test {
name: "VtsHalEnvironmentalReverbTargetTest",
defaults: ["VtsHalAudioTargetTestDefaults"],

File diff suppressed because it is too large Load Diff