diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index a166e61872..486c13d799 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -12,6 +12,9 @@
{
"name": "VtsHalDownmixTargetTest"
},
+ {
+ "name": "VtsHalDynamicProcessingTargetTest"
+ },
{
"name": "VtsHalEnvironmentalReverbTargetTest"
},
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
index 79299eeef5..86b69fa2f2 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
@@ -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,
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl
index 76f8ce50fe..402441dbab 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl
@@ -47,7 +47,7 @@ union Downmix {
}
@VintfStability
enum Type {
- STRIP = 0,
- FOLD = 1,
+ STRIP,
+ FOLD,
}
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl
index ed4dc80dc7..8e5b719f0b 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl
@@ -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;
+ }
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
index 0e61932c96..7f34f334dd 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -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;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
index 959594b988..20f7e024f3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
@@ -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,
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl
index 223d95a7b5..397f89744d 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/NoiseSuppression.aidl
@@ -47,8 +47,8 @@ union NoiseSuppression {
}
@Backing(type="int") @VintfStability
enum Level {
- LOW = 0,
- MEDIUM = 1,
- HIGH = 2,
+ LOW,
+ MEDIUM,
+ HIGH,
}
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
index 24a9ce1ef2..4651742fac 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
@@ -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 {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
index 3176b0103a..17f98142f8 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
@@ -34,7 +34,7 @@
package android.hardware.audio.effect;
@Backing(type="byte") @VintfStability
enum State {
- INIT = 0,
- IDLE = 1,
- PROCESSING = 2,
+ INIT,
+ IDLE,
+ PROCESSING,
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl
index 25f0b736d4..c8cb551b99 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl
@@ -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 {
diff --git a/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl
index ee5dcad9e0..6db3338d73 100644
--- a/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl
+++ b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl
@@ -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;
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 6f23636744..1e6785f940 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -156,7 +156,7 @@ cc_binary {
"libbassboostsw",
"libbundleaidl",
"libdownmixaidl",
- "libdynamicsprocessingsw",
+ "libdynamicsprocessingaidl",
"libenvreverbsw",
"libequalizersw",
"libhapticgeneratoraidl",
diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
index 7f06013ee6..40b46e0642 100644
--- a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
+++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
@@ -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;
}
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 9670e9c08b..e460f89056 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -33,7 +33,7 @@
-
+
@@ -72,7 +72,7 @@
-
+
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
index 39345a9683..0ffbaa11cc 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
#include
+#include
#include
#include
@@ -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();
- 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();
+ auto tag = dpParam.getTag();
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ RETURN_IF(mContext->setEngineArchitecture(
+ dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEq: {
+ RETURN_IF(mContext->setPreEqChannelCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEq: {
+ RETURN_IF(mContext->setPostEqChannelCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbc: {
+ RETURN_IF(mContext->setMbcChannelCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcChannelCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::preEqBand: {
+ RETURN_IF(mContext->setPreEqBandCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPreEqBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::postEqBand: {
+ RETURN_IF(mContext->setPostEqBandCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setPostEqBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::mbcBand: {
+ RETURN_IF(mContext->setMbcBandCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMbcBandCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::limiter: {
+ RETURN_IF(mContext->setLimiterCfgs(dpParam.get()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "limiterCfgsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case DynamicsProcessing::inputGain: {
+ RETURN_IF(mContext->setInputGainCfgs(dpParam.get()) !=
+ 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(mSpecificParam);
+ auto dpId = id.get();
+ auto dpIdTag = dpId.getTag();
+ switch (dpIdTag) {
+ case DynamicsProcessing::Id::commonTag:
+ return getParameterDynamicsProcessing(dpId.get(),
+ 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(mContext->getEngineArchitecture());
+ break;
+ }
+ case DynamicsProcessing::Tag::preEq: {
+ dpParam.set(mContext->getPreEqChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::postEq: {
+ dpParam.set(mContext->getPostEqChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::mbc: {
+ dpParam.set(mContext->getMbcChannelCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::preEqBand: {
+ dpParam.set(mContext->getPreEqBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::postEqBand: {
+ dpParam.set(mContext->getPostEqBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::mbcBand: {
+ dpParam.set(mContext->getMbcBandCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::limiter: {
+ dpParam.set(mContext->getLimiterCfgs());
+ break;
+ }
+ case DynamicsProcessing::Tag::inputGain: {
+ dpParam.set(mContext->getInputGainCfgs());
+ break;
+ }
+ case DynamicsProcessing::vendorExtension: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
+ }
+ }
+
+ specific->set(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& cfgs,
+ std::vector& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage) {
+ RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::unordered_set 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& cfgs) {
+ return setChannelCfgs(cfgs, mPreEqChCfgs, mEngineSettings.preEqStage);
+}
+
+RetCode DynamicsProcessingSwContext::setPostEqChannelCfgs(
+ const std::vector& cfgs) {
+ return setChannelCfgs(cfgs, mPostEqChCfgs, mEngineSettings.postEqStage);
+}
+
+RetCode DynamicsProcessingSwContext::setMbcChannelCfgs(
+ const std::vector& cfgs) {
+ return setChannelCfgs(cfgs, mMbcChCfgs, mEngineSettings.mbcStage);
+}
+
+RetCode DynamicsProcessingSwContext::setEqBandCfgs(
+ const std::vector& cfgs,
+ std::vector& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage,
+ const std::vector& channelConfig) {
+ RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "eqStageNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::set> 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& cfgs) {
+ return setEqBandCfgs(cfgs, mPreEqChBands, mEngineSettings.preEqStage, mPreEqChCfgs);
+}
+
+RetCode DynamicsProcessingSwContext::setPostEqBandCfgs(
+ const std::vector& cfgs) {
+ return setEqBandCfgs(cfgs, mPostEqChBands, mEngineSettings.postEqStage, mPostEqChCfgs);
+}
+
+RetCode DynamicsProcessingSwContext::setMbcBandCfgs(
+ const std::vector& cfgs) {
+ RETURN_VALUE_IF(!mEngineSettings.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "mbcNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::set> bandSet;
+
+ int bandCount = mEngineSettings.mbcStage.bandCount;
+ std::vector 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& cfgs) {
+ RETURN_VALUE_IF(!mEngineSettings.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "limiterNotInUse");
+
+ RetCode ret = RetCode::SUCCESS;
+ std::unordered_set 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& 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 DynamicsProcessingSwContext::getInputGainCfgs() {
+ std::vector 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& 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& 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 2ae46c5ac5..e336df7b8e 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
@@ -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& cfgs,
+ std::vector& targetCfgs,
+ const DynamicsProcessing::StageEnablement& engineSetting);
+
+ RetCode setEqBandCfgs(const std::vector& cfgs,
+ std::vector& targetCfgs,
+ const DynamicsProcessing::StageEnablement& stage,
+ const std::vector& channelConfig);
+
+ // set params
+ RetCode setCommon(const Parameter::Common& common) override;
+ RetCode setEngineArchitecture(const DynamicsProcessing::EngineArchitecture& cfg);
+ RetCode setPreEqChannelCfgs(const std::vector& cfgs);
+ RetCode setPostEqChannelCfgs(const std::vector& cfgs);
+ RetCode setMbcChannelCfgs(const std::vector& cfgs);
+ RetCode setPreEqBandCfgs(const std::vector& cfgs);
+ RetCode setPostEqBandCfgs(const std::vector& cfgs);
+ RetCode setMbcBandCfgs(const std::vector& cfgs);
+ RetCode setLimiterCfgs(const std::vector& cfgs);
+ RetCode setInputGainCfgs(const std::vector& cfgs);
+
+ // get params
+ DynamicsProcessing::EngineArchitecture getEngineArchitecture() { return mEngineSettings; }
+ std::vector getPreEqChannelCfgs() { return mPreEqChCfgs; }
+ std::vector getPostEqChannelCfgs() { return mPostEqChCfgs; }
+ std::vector getMbcChannelCfgs() { return mMbcChCfgs; }
+ std::vector getPreEqBandCfgs() { return mPreEqChBands; }
+ std::vector getPostEqBandCfgs() { return mPostEqChBands; }
+ std::vector getMbcBandCfgs() { return mMbcChBands; }
+ std::vector getLimiterCfgs() { return mLimiterCfgs; }
+ std::vector getInputGainCfgs();
+
+ private:
+ static constexpr int32_t kInvalidChannelId = -1;
+ size_t mChannelCount = 0;
+ DynamicsProcessing::EngineArchitecture mEngineSettings;
+ // Channel config vector with size of mChannelCount
+ std::vector mPreEqChCfgs;
+ std::vector mPostEqChCfgs;
+ std::vector mMbcChCfgs;
+ std::vector mLimiterCfgs;
+ std::vector mInputGainCfgs;
+ // Band config vector with size of mChannelCount * bandCount
+ std::vector mPreEqChBands;
+ std::vector mPostEqChBands;
+ std::vector 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& channelConfig);
+ bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
+ int maxBand,
+ const std::vector& 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 mContext;
- /* parameters */
- DynamicsProcessing mSpecificParam;
-};
+ ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
+ Parameter::Specific* specific);
+
+}; // DynamicsProcessingSw
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 1f39db01e7..a3e7ff2066 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -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;
}
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
index 58c8672145..b100a2ebf3 100644
--- a/audio/aidl/default/include/effect-impl/EffectTypes.h
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -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) \
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 6eec29e036..1a60829ce8 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -135,6 +135,12 @@ static const AudioUuid kDynamicsProcessingSwImplUUID = {static_cast(0xf
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// e0e6539b-1781-7261-676f-6d7573696340
+static const AudioUuid kDynamicsProcessingImplUUID = {static_cast(0xe0e6539b),
+ 0x1781,
+ 0x7261,
+ 0x676f,
+ {0x6d, 0x75, 0x73, 0x69, 0x63, 0x40}};
// 1411e6d6-aecd-4021-a1cf-a6aceb0d71e5
static const AudioUuid kHapticGeneratorTypeUUID = {static_cast(0x1411e6d6),
0xaecd,
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index becdf1bd9f..f9d12ddea0 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -80,6 +80,12 @@ cc_test {
srcs: ["VtsHalDownmixTargetTest.cpp"],
}
+cc_test {
+ name: "VtsHalDynamicsProcessingTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalDynamicsProcessingTest.cpp"],
+}
+
cc_test {
name: "VtsHalEnvironmentalReverbTargetTest",
defaults: ["VtsHalAudioTargetTestDefaults"],
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
new file mode 100644
index 0000000000..9feff911ed
--- /dev/null
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#define LOG_TAG "VtsHalDynamicsProcessingTest"
+
+#include
+#include
+#include
+#include
+
+#include
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DynamicsProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDynamicsProcessingTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+class DynamicsProcessingTestHelper : public EffectHelper {
+ public:
+ DynamicsProcessingTestHelper(std::pair, Descriptor> pair,
+ int32_t channelLayOut = AudioChannelLayout::LAYOUT_STEREO) {
+ std::tie(mFactory, mDescriptor) = pair;
+ mChannelLayout = channelLayOut;
+ mChannelCount = ::android::hardware::audio::common::getChannelCount(
+ AudioChannelLayout::make(mChannelLayout));
+ }
+
+ // setup
+ void SetUpDynamicsProcessingEffect() {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ 0x100 /* iFrameCount */, 0x100 /* oFrameCount */,
+ AudioChannelLayout::make(mChannelLayout),
+ AudioChannelLayout::make(mChannelLayout));
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ mEngineConfigApplied = mEngineConfigPreset;
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ DynamicsProcessing dp = DynamicsProcessing::make(
+ mEngineConfigPreset);
+ Parameter::Specific specific =
+ Parameter::Specific::make(dp);
+ return specific;
+ }
+
+ // teardown
+ void TearDownDynamicsProcessingEffect() {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ // utils functions for parameter checking
+ bool isParamValid(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dp,
+ const Descriptor& desc);
+ bool isParamEqual(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dpRef,
+ const DynamicsProcessing& dpTest);
+
+ bool isEnablementValid(const DynamicsProcessing::StageEnablement& enablement);
+ bool isEngineConfigValid(const DynamicsProcessing::EngineArchitecture& cfg);
+
+ bool isCutoffFrequencyValid(float freq, const DynamicsProcessing::Capability& cap);
+ bool isChannelConfigValid(const std::vector& cfgs,
+ bool stageInUse);
+
+ bool isPreEqBandConfigValid(const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs,
+ bool stageInUse, int bandCount);
+ bool isPostEqBandConfigValid(const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs,
+ bool stageInUse, int bandCount);
+ bool isMbcBandConfigValid(const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs,
+ bool stageInUse, int bandCount);
+ bool isLimiterConfigValid(const std::vector& cfgs,
+ bool stageInUse);
+ bool isInputGainValid(const std::vector& cfgs);
+
+ bool isEngineConfigEqual(const DynamicsProcessing::EngineArchitecture& refCfg,
+ const DynamicsProcessing::EngineArchitecture& testCfg);
+
+ template
+ std::vector filterEnabledVector(const std::vector& vec);
+
+ template
+ bool isAidlVectorEqualAfterFilter(const std::vector& source, const std::vector& target);
+
+ template
+ bool isAidlVectorEqual(const std::vector& source, const std::vector& target);
+
+ // get set params and validate
+ void SetAndGetDynamicsProcessingParameters();
+
+ // enqueue test parameters
+ void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
+ void addPreEqChannelConfig(const std::vector& cfg);
+ void addPostEqChannelConfig(const std::vector& cfg);
+ void addMbcChannelConfig(const std::vector& cfg);
+ void addPreEqBandConfigs(const std::vector& cfgs);
+ void addPostEqBandConfigs(const std::vector& cfgs);
+ void addMbcBandConfigs(const std::vector& cfgs);
+ void addLimiterConfig(const std::vector& cfg);
+ void addInputGain(const std::vector& inputGain);
+
+ static constexpr float kPreferredProcessingDurationMs = 10.0f;
+ static constexpr int kBandCount = 5;
+ std::shared_ptr mFactory;
+ std::shared_ptr mEffect;
+ Descriptor mDescriptor;
+ DynamicsProcessing::EngineArchitecture mEngineConfigApplied;
+ DynamicsProcessing::EngineArchitecture mEngineConfigPreset{
+ .resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
+ .preEqStage = {.inUse = true, .bandCount = kBandCount},
+ .postEqStage = {.inUse = true, .bandCount = kBandCount},
+ .mbcStage = {.inUse = true, .bandCount = kBandCount},
+ .limiterInUse = true,
+ };
+
+ std::unordered_set mPreEqChannelEnable;
+ std::unordered_set mPostEqChannelEnable;
+ std::unordered_set mMbcChannelEnable;
+ std::unordered_set mLimiterChannelEnable;
+ static const std::set> kChannelConfigTestSet;
+ static const std::set kStageEnablementTestSet;
+ static const std::set> kInputGainTestSet;
+
+ private:
+ int32_t mChannelLayout;
+ int mChannelCount;
+ std::vector> mTags;
+ void CleanUp() {
+ mTags.clear();
+ mPreEqChannelEnable.clear();
+ mPostEqChannelEnable.clear();
+ mMbcChannelEnable.clear();
+ mLimiterChannelEnable.clear();
+ }
+};
+
+// test value set for DynamicsProcessing::StageEnablement
+const std::set
+ DynamicsProcessingTestHelper::kStageEnablementTestSet = {
+ {.inUse = true, .bandCount = DynamicsProcessingTestHelper::kBandCount},
+ {.inUse = true, .bandCount = 0},
+ {.inUse = true, .bandCount = -1},
+ {.inUse = false, .bandCount = DynamicsProcessingTestHelper::kBandCount}};
+
+// test value set for DynamicsProcessing::ChannelConfig
+const std::set>
+ DynamicsProcessingTestHelper::kChannelConfigTestSet = {
+ {{.channel = -1, .enable = false},
+ {.channel = 0, .enable = true},
+ {.channel = 1, .enable = false},
+ {.channel = 2, .enable = true}},
+
+ {{.channel = -1, .enable = false}, {.channel = 2, .enable = true}},
+
+ {{.channel = 0, .enable = true}, {.channel = 1, .enable = true}}};
+
+// test value set for DynamicsProcessing::InputGain
+const std::set>
+ DynamicsProcessingTestHelper::kInputGainTestSet = {
+ {{.channel = 0, .gainDb = 10.f},
+ {.channel = 1, .gainDb = 0.f},
+ {.channel = 2, .gainDb = -10.f}},
+
+ {{.channel = -1, .gainDb = -10.f}, {.channel = -2, .gainDb = 10.f}},
+
+ {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}}};
+
+bool DynamicsProcessingTestHelper::isParamValid(const DynamicsProcessing::Tag& tag,
+ const DynamicsProcessing& dp,
+ const Descriptor& desc) {
+ const DynamicsProcessing::Capability& dpCap =
+ desc.capability.get();
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ return isEngineConfigValid(dp.get());
+ }
+ case DynamicsProcessing::preEq: {
+ return isChannelConfigValid(dp.get(),
+ mEngineConfigApplied.preEqStage.inUse);
+ }
+ case DynamicsProcessing::postEq: {
+ return isChannelConfigValid(dp.get(),
+ mEngineConfigApplied.postEqStage.inUse);
+ }
+ case DynamicsProcessing::mbc: {
+ return isChannelConfigValid(dp.get(),
+ mEngineConfigApplied.mbcStage.inUse);
+ }
+ case DynamicsProcessing::preEqBand: {
+ return isPreEqBandConfigValid(dpCap, dp.get(),
+ mEngineConfigApplied.preEqStage.inUse,
+ mEngineConfigApplied.preEqStage.bandCount);
+ }
+ case DynamicsProcessing::postEqBand: {
+ return isPostEqBandConfigValid(dpCap, dp.get(),
+ mEngineConfigApplied.postEqStage.inUse,
+ mEngineConfigApplied.postEqStage.bandCount);
+ }
+ case DynamicsProcessing::mbcBand: {
+ return isMbcBandConfigValid(dpCap, dp.get(),
+ mEngineConfigApplied.mbcStage.inUse,
+ mEngineConfigApplied.mbcStage.bandCount);
+ }
+ case DynamicsProcessing::limiter: {
+ return isLimiterConfigValid(dp.get(),
+ mEngineConfigApplied.limiterInUse);
+ }
+ case DynamicsProcessing::inputGain: {
+ return isInputGainValid(dp.get());
+ }
+ case DynamicsProcessing::vendorExtension: {
+ return true;
+ }
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isParamEqual(const DynamicsProcessing::Tag& tag,
+ const DynamicsProcessing& dpRef,
+ const DynamicsProcessing& dpTest) {
+ switch (tag) {
+ case DynamicsProcessing::engineArchitecture: {
+ return isEngineConfigEqual(dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::preEq: {
+ const auto& source = dpRef.get();
+ const auto& target = dpTest.get();
+ return isAidlVectorEqualAfterFilter(source, target);
+ }
+ case DynamicsProcessing::postEq: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::mbc: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(), dpTest.get());
+ }
+ case DynamicsProcessing::preEqBand: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::postEqBand: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::mbcBand: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::limiter: {
+ return isAidlVectorEqualAfterFilter(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::inputGain: {
+ return isAidlVectorEqual(
+ dpRef.get(),
+ dpTest.get());
+ }
+ case DynamicsProcessing::vendorExtension: {
+ return false;
+ }
+ }
+}
+
+bool DynamicsProcessingTestHelper::isEnablementValid(
+ const DynamicsProcessing::StageEnablement& enablement) {
+ return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
+}
+
+bool DynamicsProcessingTestHelper::isEngineConfigValid(
+ const DynamicsProcessing::EngineArchitecture& cfg) {
+ return cfg.preferredProcessingDurationMs >= 0 && isEnablementValid(cfg.preEqStage) &&
+ isEnablementValid(cfg.postEqStage) && isEnablementValid(cfg.mbcStage);
+}
+
+bool DynamicsProcessingTestHelper::isChannelConfigValid(
+ const std::vector& cfgs, bool stageInUse) {
+ std::unordered_set channelSet;
+ if (!stageInUse) return false;
+ for (auto cfg : cfgs) {
+ if (cfg.channel < 0 || cfg.channel >= mChannelCount || 0 != channelSet.count(cfg.channel)) {
+ return false;
+ }
+ channelSet.insert(cfg.channel);
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isCutoffFrequencyValid(
+ float freq, const DynamicsProcessing::Capability& cap) {
+ return freq >= cap.minCutOffFreq && freq <= cap.maxCutOffFreq;
+}
+
+bool DynamicsProcessingTestHelper::isPreEqBandConfigValid(
+ const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs, bool stageInUse, int bandCount) {
+ std::set> bandSet;
+ if (!stageInUse) return false;
+ for (auto cfg : cfgs) {
+ if (0 == mPreEqChannelEnable.count(cfg.channel) || cfg.channel < 0 ||
+ cfg.channel >= mChannelCount || cfg.band < 0 || cfg.band >= bandCount ||
+ !isCutoffFrequencyValid(cfg.cutoffFrequencyHz, cap) ||
+ 0 != bandSet.count({cfg.channel, cfg.band})) {
+ return false;
+ }
+ bandSet.insert({cfg.channel, cfg.band});
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isPostEqBandConfigValid(
+ const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs, bool stageInUse, int bandCount) {
+ std::set> bandSet;
+ // not able to set/get parameter when stage not in use.
+ if (!stageInUse) return false;
+ for (auto cfg : cfgs) {
+ if (0 == mPostEqChannelEnable.count(cfg.channel) || cfg.channel < 0 ||
+ cfg.channel >= mChannelCount || cfg.band < 0 || cfg.band >= bandCount ||
+ !isCutoffFrequencyValid(cfg.cutoffFrequencyHz, cap) ||
+ 0 != bandSet.count({cfg.channel, cfg.band})) {
+ return false;
+ }
+ bandSet.insert({cfg.channel, cfg.band});
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isMbcBandConfigValid(
+ const DynamicsProcessing::Capability& cap,
+ const std::vector& cfgs, bool stageInUse,
+ int bandCount) {
+ std::set> bandSet;
+ if (!stageInUse) return false;
+ for (auto cfg : cfgs) {
+ if (0 == mMbcChannelEnable.count(cfg.channel) || cfg.channel < 0 ||
+ cfg.channel >= mChannelCount || cfg.band < 0 || cfg.band >= bandCount ||
+ (cfg.attackTimeMs < 0) || cfg.releaseTimeMs < 0 || cfg.ratio < 0 ||
+ cfg.thresholdDb > 0 || cfg.kneeWidthDb < 0 || cfg.noiseGateThresholdDb > 0 ||
+ cfg.expanderRatio < 0 || !isCutoffFrequencyValid(cfg.cutoffFrequencyHz, cap) ||
+ 0 != bandSet.count({cfg.channel, cfg.band})) {
+ return false;
+ }
+ bandSet.insert({cfg.channel, cfg.band});
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isLimiterConfigValid(
+ const std::vector& cfgs, bool stageInUse) {
+ std::set channelSet;
+ if (!stageInUse) return false;
+ for (auto cfg : cfgs) {
+ if (0 == mLimiterChannelEnable.count(cfg.channel) || cfg.channel < 0 ||
+ cfg.channel >= mChannelCount || cfg.attackTimeMs < 0 || cfg.releaseTimeMs < 0 ||
+ cfg.ratio < 0 || cfg.thresholdDb > 0 || 0 != channelSet.count(cfg.channel)) {
+ return false;
+ }
+ channelSet.insert(cfg.channel);
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isInputGainValid(
+ const std::vector& cfgs) {
+ std::set channelSet;
+ for (auto cfg : cfgs) {
+ if (cfg.channel < 0 || cfg.channel >= mChannelCount || 0 != channelSet.count(cfg.channel)) {
+ return false;
+ }
+ channelSet.insert(cfg.channel);
+ }
+ return true;
+}
+
+bool DynamicsProcessingTestHelper::isEngineConfigEqual(
+ const DynamicsProcessing::EngineArchitecture& ref,
+ const DynamicsProcessing::EngineArchitecture& test) {
+ return ref == test;
+}
+
+template
+std::vector DynamicsProcessingTestHelper::filterEnabledVector(const std::vector& vec) {
+ std::vector ret;
+ std::copy_if(vec.begin(), vec.end(), std::back_inserter(ret),
+ [](const auto& v) { return v.enable; });
+ return ret;
+}
+
+template
+bool DynamicsProcessingTestHelper::isAidlVectorEqual(const std::vector& source,
+ const std::vector& target) {
+ if (source.size() != target.size()) return false;
+
+ auto tempS = source;
+ auto tempT = target;
+ std::sort(tempS.begin(), tempS.end());
+ std::sort(tempT.begin(), tempT.end());
+ return tempS == tempT;
+}
+
+template
+bool DynamicsProcessingTestHelper::isAidlVectorEqualAfterFilter(const std::vector& source,
+ const std::vector& target) {
+ return isAidlVectorEqual(filterEnabledVector(source), filterEnabledVector(target));
+}
+
+void DynamicsProcessingTestHelper::SetAndGetDynamicsProcessingParameters() {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& dp = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isParamValid(tag, dp, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set(dp);
+ expectParam.set(specific);
+ ASSERT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // only get if parameter in range and set success
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Id id;
+ DynamicsProcessing::Id dpId;
+ dpId.set(tag);
+ id.set(dpId);
+ // if set success, then get should match
+ EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
+ Parameter::Specific specificTest = getParam.get();
+ const auto& target = specificTest.get();
+ EXPECT_TRUE(isParamEqual(tag, dp, target)) << dp.toString() << "\n"
+ << target.toString();
+ // update mEngineConfigApplied after setting successfully
+ if (tag == DynamicsProcessing::engineArchitecture) {
+ mEngineConfigApplied = target.get();
+ }
+ }
+ }
+}
+
+void DynamicsProcessingTestHelper::addEngineConfig(
+ const DynamicsProcessing::EngineArchitecture& cfg) {
+ DynamicsProcessing dp;
+ dp.set(cfg);
+ mTags.push_back({DynamicsProcessing::engineArchitecture, dp});
+}
+
+void DynamicsProcessingTestHelper::addPreEqChannelConfig(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::preEq, dp});
+ for (auto& cfg : cfgs) {
+ if (cfg.enable) mPreEqChannelEnable.insert(cfg.channel);
+ }
+}
+
+void DynamicsProcessingTestHelper::addPostEqChannelConfig(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::postEq, dp});
+ for (auto& cfg : cfgs) {
+ if (cfg.enable) mPostEqChannelEnable.insert(cfg.channel);
+ }
+}
+
+void DynamicsProcessingTestHelper::addMbcChannelConfig(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::mbc, dp});
+ for (auto& cfg : cfgs) {
+ if (cfg.enable) mMbcChannelEnable.insert(cfg.channel);
+ }
+}
+
+void DynamicsProcessingTestHelper::addPreEqBandConfigs(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::preEqBand, dp});
+}
+
+void DynamicsProcessingTestHelper::addPostEqBandConfigs(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::postEqBand, dp});
+}
+
+void DynamicsProcessingTestHelper::addMbcBandConfigs(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::mbcBand, dp});
+}
+
+void DynamicsProcessingTestHelper::addLimiterConfig(
+ const std::vector& cfgs) {
+ DynamicsProcessing dp;
+ dp.set(cfgs);
+ mTags.push_back({DynamicsProcessing::limiter, dp});
+ for (auto& cfg : cfgs) {
+ if (cfg.enable) mLimiterChannelEnable.insert(cfg.channel);
+ }
+}
+
+void DynamicsProcessingTestHelper::addInputGain(
+ const std::vector& inputGains) {
+ DynamicsProcessing dp;
+ dp.set(inputGains);
+ mTags.push_back({DynamicsProcessing::inputGain, dp});
+}
+
+/**
+ * Test DynamicsProcessing Engine Configuration
+ */
+enum EngineArchitectureTestParamName {
+ ENGINE_TEST_INSTANCE_NAME,
+ ENGINE_TEST_RESOLUTION_PREFERENCE,
+ ENGINE_TEST_PREFERRED_DURATION,
+ ENGINE_TEST_STAGE_ENABLEMENT,
+ ENGINE_TEST_LIMITER_IN_USE
+};
+using EngineArchitectureTestParams = std::tuple, Descriptor>,
+ DynamicsProcessing::ResolutionPreference, float,
+ DynamicsProcessing::StageEnablement, bool>;
+
+void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg,
+ const EngineArchitectureTestParams& params) {
+ cfg.resolutionPreference = std::get(params);
+ cfg.preferredProcessingDurationMs = std::get(params);
+ cfg.preEqStage = cfg.postEqStage = cfg.mbcStage =
+ std::get(params);
+ cfg.limiterInUse = std::get(params);
+}
+
+class DynamicsProcessingTestEngineArchitecture
+ : public ::testing::TestWithParam,
+ public DynamicsProcessingTestHelper {
+ public:
+ DynamicsProcessingTestEngineArchitecture()
+ : DynamicsProcessingTestHelper(std::get(GetParam())) {
+ fillEngineArchConfig(mCfg, GetParam());
+ };
+
+ void SetUp() override { SetUpDynamicsProcessingEffect(); }
+
+ void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+ DynamicsProcessing::EngineArchitecture mCfg;
+};
+
+TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
+ EXPECT_NO_FATAL_FAILURE(addEngineConfig(mCfg));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DynamicsProcessingTest, DynamicsProcessingTestEngineArchitecture,
+ ::testing::Combine(
+ testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kDynamicsProcessingTypeUUID)),
+ testing::Values(DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
+ DynamicsProcessing::ResolutionPreference::
+ FAVOR_FREQUENCY_RESOLUTION), // variant
+ testing::Values(-10.f, 0.f, 10.f), // processing duration
+ testing::ValuesIn(
+ DynamicsProcessingTestHelper::kStageEnablementTestSet), // preEQ/postEQ/mbc
+ testing::Bool()), // limiter enable
+ [](const auto& info) {
+ auto descriptor = std::get(info.param).second;
+ DynamicsProcessing::EngineArchitecture cfg;
+ fillEngineArchConfig(cfg, info.param);
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_Cfg_" + cfg.toString();
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestEngineArchitecture);
+
+/**
+ * Test DynamicsProcessing Input Gain
+ */
+enum InputGainTestParamName {
+ INPUT_GAIN_INSTANCE_NAME,
+ INPUT_GAIN_PARAM,
+};
+class DynamicsProcessingTestInputGain
+ : public ::testing::TestWithParam, Descriptor>,
+ std::vector>>,
+ public DynamicsProcessingTestHelper {
+ public:
+ DynamicsProcessingTestInputGain()
+ : DynamicsProcessingTestHelper(std::get(GetParam())),
+ mInputGain(std::get(GetParam())){};
+
+ void SetUp() override { SetUpDynamicsProcessingEffect(); }
+
+ void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+ const std::vector mInputGain;
+};
+
+TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
+ EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DynamicsProcessingTest, DynamicsProcessingTestInputGain,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kDynamicsProcessingTypeUUID)),
+ testing::ValuesIn(DynamicsProcessingTestInputGain::kInputGainTestSet)),
+ [](const auto& info) {
+ auto descriptor = std::get(info.param).second;
+ std::string gains =
+ ::android::internal::ToString(std::get(info.param));
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_inputGains_" + gains;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestInputGain);
+
+/**
+ * Test DynamicsProcessing Limiter Config
+ */
+enum LimiterConfigTestParamName {
+ LIMITER_INSTANCE_NAME,
+ LIMITER_CHANNEL,
+ LIMITER_ENABLE,
+ LIMITER_LINK_GROUP,
+ LIMITER_ENGINE_IN_USE,
+ LIMITER_ADDITIONAL,
+};
+enum LimiterConfigTestAdditionalParam {
+ LIMITER_ATTACK_TIME,
+ LIMITER_RELEASE_TIME,
+ LIMITER_RATIO,
+ LIMITER_THRESHOLD,
+ LIMITER_POST_GAIN,
+ LIMITER_MAX_NUM,
+};
+using LimiterConfigTestAdditional = std::array;
+// attachTime, releaseTime, ratio, thresh, postGain
+static constexpr std::array kLimiterConfigTestAdditionalParam = {
+ {{-1, -60, -2.5, -2, -3.14},
+ {-1, 60, -2.5, 2, -3.14},
+ {1, -60, 2.5, -2, 3.14},
+ {1, 60, 2.5, 2, 3.14}}};
+
+using LimiterConfigTestParams =
+ std::tuple, Descriptor>, int32_t, bool, int32_t, bool,
+ LimiterConfigTestAdditional>;
+
+void fillLimiterConfig(DynamicsProcessing::LimiterConfig& cfg,
+ const LimiterConfigTestParams& params) {
+ const std::array additional = std::get(params);
+ cfg.channel = std::get(params);
+ cfg.enable = std::get(params);
+ cfg.linkGroup = std::get(params);
+ cfg.attackTimeMs = additional[LIMITER_ATTACK_TIME];
+ cfg.releaseTimeMs = additional[LIMITER_RELEASE_TIME];
+ cfg.ratio = additional[LIMITER_RATIO];
+ cfg.thresholdDb = additional[LIMITER_THRESHOLD];
+ cfg.postGainDb = additional[LIMITER_POST_GAIN];
+}
+
+class DynamicsProcessingTestLimiterConfig
+ : public ::testing::TestWithParam,
+ public DynamicsProcessingTestHelper {
+ public:
+ DynamicsProcessingTestLimiterConfig()
+ : DynamicsProcessingTestHelper(std::get(GetParam())),
+ mLimiterInUseEngine(std::get(GetParam())) {
+ fillLimiterConfig(mCfg, GetParam());
+ }
+
+ void SetUp() override { SetUpDynamicsProcessingEffect(); }
+
+ void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+ DynamicsProcessing::LimiterConfig mCfg;
+ bool mLimiterInUseEngine;
+};
+
+TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
+ mEngineConfigPreset.limiterInUse = mLimiterInUseEngine;
+ EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ EXPECT_NO_FATAL_FAILURE(addLimiterConfig({mCfg}));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kDynamicsProcessingTypeUUID)),
+ testing::Values(-1, 0, 1, 2), // channel count
+ testing::Bool(), // enable
+ testing::Values(3), // link group
+ testing::Bool(), // engine limiter enable
+ testing::ValuesIn(kLimiterConfigTestAdditionalParam)), // Additional
+ [](const auto& info) {
+ auto descriptor = std::get(info.param).second;
+ DynamicsProcessing::LimiterConfig cfg;
+ fillLimiterConfig(cfg, info.param);
+ std::string engineLimiterInUse =
+ std::to_string(std::get(info.param));
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_limiterConfig_" +
+ cfg.toString() + "_engineSetting_" + engineLimiterInUse;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfig);
+
+/**
+ * Test DynamicsProcessing ChannelConfig
+ */
+enum ChannelConfigTestParamName {
+ BAND_CHANNEL_TEST_INSTANCE_NAME,
+ BAND_CHANNEL_TEST_CHANNEL_CONFIG,
+ BAND_CHANNEL_TEST_ENGINE_IN_USE
+};
+using ChannelConfigTestParams = std::tuple, Descriptor>,
+ std::vector, bool>;
+
+class DynamicsProcessingTestChannelConfig
+ : public ::testing::TestWithParam,
+ public DynamicsProcessingTestHelper {
+ public:
+ DynamicsProcessingTestChannelConfig()
+ : DynamicsProcessingTestHelper(std::get(GetParam())),
+ mCfg(std::get(GetParam())),
+ mInUseEngine(std::get(GetParam())) {}
+
+ void SetUp() override { SetUpDynamicsProcessingEffect(); }
+
+ void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+ std::vector mCfg;
+ const bool mInUseEngine;
+};
+
+TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
+ mEngineConfigPreset.preEqStage.inUse = mInUseEngine;
+ EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
+ mEngineConfigPreset.postEqStage.inUse = mInUseEngine;
+ EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
+ mEngineConfigPreset.mbcStage.inUse = mInUseEngine;
+ EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+ EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg));
+ SetAndGetDynamicsProcessingParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DynamicsProcessingTest, DynamicsProcessingTestChannelConfig,
+ ::testing::Combine(
+ testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kDynamicsProcessingTypeUUID)),
+ testing::ValuesIn(
+ DynamicsProcessingTestHelper::kChannelConfigTestSet), // channel config
+ testing::Bool()), // Engine inUse
+ [](const auto& info) {
+ auto descriptor = std::get(info.param).second;
+ std::string engineInUse =
+ std::to_string(std::get(info.param));
+ std::string channelConfig = ::android::internal::ToString(
+ std::get(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_" + channelConfig +
+ "_engineInUse_" + engineInUse;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestChannelConfig);
+
+/**
+ * Test DynamicsProcessing EqBandConfig
+ */
+enum EqBandConfigTestParamName {
+ EQ_BAND_INSTANCE_NAME,
+ EQ_BAND_CHANNEL,
+ EQ_BAND_CHANNEL_ENABLE,
+ EQ_BAND_ENABLE,
+ EQ_BAND_CUT_OFF_FREQ,
+ EQ_BAND_GAIN,
+ EQ_BAND_STAGE_IN_USE
+};
+using EqBandConfigTestParams = std::tuple, Descriptor>, int32_t,
+ std::vector, bool,
+ std::vector>, float, bool>;
+
+void fillEqBandConfig(std::vector& cfgs,
+ const EqBandConfigTestParams& params) {
+ const std::vector> cutOffFreqs = std::get(params);
+ int bandCount = cutOffFreqs.size();
+ cfgs.resize(bandCount);
+ for (int i = 0; i < bandCount; i++) {
+ cfgs[i].channel = std::get