Expose aec3 config
This change exposes the upstream EchoCanceller3Config
and make webrtc_apm_create takes a copy of this struct.
This allows caller to change the parameters for tuning.
BUG=chromium:710465
TEST=None
CQ-DEPEND=CL:1041306
Change-Id: I8337c151d4b7c08bf5dedd4c8833815214b8c058
Reviewed-on: https://chromium-review.googlesource.com/1046726
Commit-Ready: Hsinyu Chao <hychao@chromium.org>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
diff --git a/webrtc_apm.cc b/webrtc_apm.cc
index b92a008..b770ab6 100644
--- a/webrtc_apm.cc
+++ b/webrtc_apm.cc
@@ -13,15 +13,180 @@
extern "C" {
#include "webrtc_apm.h"
+int convert_to_aec3_config(
+ const struct aec_config *config,
+ webrtc::EchoCanceller3Config *aec3_config)
+{
+ aec3_config->delay = {
+ config->delay.default_delay,
+ config->delay.down_sampling_factor,
+ config->delay.num_filters,
+ config->delay.api_call_jitter_blocks,
+ config->delay.min_echo_path_delay_blocks,
+ config->delay.delay_headroom_blocks,
+ config->delay.hysteresis_limit_1_blocks,
+ config->delay.hysteresis_limit_2_blocks,
+ config->delay.skew_hysteresis_blocks
+ };
+ aec3_config->filter.main = {
+ config->filter.main.length_blocks,
+ config->filter.main.leakage_converged,
+ config->filter.main.leakage_diverged,
+ config->filter.main.error_floor,
+ config->filter.main.noise_gate
+ };
+ aec3_config->filter.shadow = {
+ config->filter.shadow.length_blocks,
+ config->filter.shadow.rate,
+ config->filter.shadow.noise_gate
+ };
+ aec3_config->filter.main_initial = {
+ config->filter.main_initial.length_blocks,
+ config->filter.main_initial.leakage_converged,
+ config->filter.main_initial.leakage_diverged,
+ config->filter.main_initial.error_floor,
+ config->filter.main_initial.noise_gate
+ };
+ aec3_config->filter.shadow_initial = {
+ config->filter.shadow_initial.length_blocks,
+ config->filter.shadow_initial.rate,
+ config->filter.shadow_initial.noise_gate
+ };
+ aec3_config->filter.config_change_duration_blocks =
+ config->filter.config_change_duration_blocks;
+ aec3_config->erle = {
+ config->erle.min,
+ config->erle.max_l,
+ config->erle.max_h,
+ };
+ aec3_config->ep_strength = {
+ config->ep_strength.lf,
+ config->ep_strength.mf,
+ config->ep_strength.hf,
+ config->ep_strength.default_len,
+ static_cast<bool>(config->ep_strength.echo_can_saturate),
+ static_cast<bool>(config->ep_strength.bounded_erl)
+ };
+
+ aec3_config->gain_mask.m1 = config->gain_mask.m1;
+ aec3_config->gain_mask.m2 = config->gain_mask.m2;
+ aec3_config->gain_mask.m3 = config->gain_mask.m3;
+ aec3_config->gain_mask.m5 = config->gain_mask.m5;
+ aec3_config->gain_mask.m6 = config->gain_mask.m6;
+ aec3_config->gain_mask.m7 = config->gain_mask.m7;
+ aec3_config->gain_mask.m8 = config->gain_mask.m8;
+ aec3_config->gain_mask.m9 = config->gain_mask.m9;
+ aec3_config->gain_mask.gain_curve_offset =
+ config->gain_mask.gain_curve_offset;
+ aec3_config->gain_mask.gain_curve_slope =
+ config->gain_mask.gain_curve_slope;
+ aec3_config->gain_mask.temporal_masking_lf =
+ config->gain_mask.temporal_masking_lf;
+ aec3_config->gain_mask.temporal_masking_hf =
+ config->gain_mask.temporal_masking_hf;
+ aec3_config->gain_mask.temporal_masking_lf_bands =
+ config->gain_mask.temporal_masking_lf_bands;
+
+ aec3_config->echo_audibility = {
+ config->echo_audibility.low_render_limit,
+ config->echo_audibility.normal_render_limit,
+ config->echo_audibility.floor_power,
+ config->echo_audibility.audibility_threshold_lf,
+ config->echo_audibility.audibility_threshold_mf,
+ config->echo_audibility.audibility_threshold_hf,
+ static_cast<bool>(
+ config->echo_audibility.use_stationary_properties)
+ };
+ aec3_config->render_levels = {
+ config->render_levels.active_render_limit,
+ config->render_levels.poor_excitation_render_limit,
+ };
+ aec3_config->gain_updates.low_noise = {
+ config->gain_updates.low_noise.max_inc,
+ config->gain_updates.low_noise.max_dec,
+ config->gain_updates.low_noise.rate_inc,
+ config->gain_updates.low_noise.rate_dec,
+ config->gain_updates.low_noise.min_inc,
+ config->gain_updates.low_noise.min_dec,
+ };
+ aec3_config->gain_updates.initial = {
+ config->gain_updates.initial.max_inc,
+ config->gain_updates.initial.max_dec,
+ config->gain_updates.initial.rate_inc,
+ config->gain_updates.initial.rate_dec,
+ config->gain_updates.initial.min_inc,
+ config->gain_updates.initial.min_dec,
+ };
+ aec3_config->gain_updates.normal = {
+ config->gain_updates.normal.max_inc,
+ config->gain_updates.normal.max_dec,
+ config->gain_updates.normal.rate_inc,
+ config->gain_updates.normal.rate_dec,
+ config->gain_updates.normal.min_inc,
+ config->gain_updates.normal.min_dec,
+ };
+ aec3_config->gain_updates.saturation = {
+ config->gain_updates.saturation.max_inc,
+ config->gain_updates.saturation.max_dec,
+ config->gain_updates.saturation.rate_inc,
+ config->gain_updates.saturation.rate_dec,
+ config->gain_updates.saturation.min_inc,
+ config->gain_updates.saturation.min_dec,
+ };
+ aec3_config->gain_updates.nonlinear = {
+ config->gain_updates.nonlinear.max_inc,
+ config->gain_updates.nonlinear.max_dec,
+ config->gain_updates.nonlinear.rate_inc,
+ config->gain_updates.nonlinear.rate_dec,
+ config->gain_updates.nonlinear.min_inc,
+ config->gain_updates.nonlinear.min_dec,
+ };
+ aec3_config->gain_updates.floor_first_increase =
+ config->gain_updates.floor_first_increase;
+
+ aec3_config->echo_removal_control = {
+ {
+ config->echo_removal_control.gain_rampup.first_non_zero_gain,
+ config->echo_removal_control.gain_rampup.non_zero_gain_blocks,
+ config->echo_removal_control.gain_rampup.full_gain_blocks
+ },
+ static_cast<bool>(config->echo_removal_control.has_clock_drift)
+ };
+
+ aec3_config->echo_model = {
+ config->echo_model.noise_floor_hold,
+ config->echo_model.min_noise_floor_power,
+ config->echo_model.stationary_gate_slope,
+ config->echo_model.noise_gate_power,
+ config->echo_model.noise_gate_slope,
+ config->echo_model.render_pre_window_size,
+ config->echo_model.render_post_window_size,
+ config->echo_model.nonlinear_hold,
+ config->echo_model.nonlinear_release
+ };
+
+
+ return 0;
+}
+
webrtc_apm webrtc_apm_create(unsigned int num_channels,
- unsigned int frame_rate,
- unsigned int enable_echo_cancellation)
+ unsigned int frame_rate,
+ struct aec_config *config)
{
int err;
webrtc::AudioProcessing *apm;
webrtc::AudioProcessing::ChannelLayout channel_layout;
webrtc::AudioProcessingBuilder apm_builder;
- std::unique_ptr<webrtc::EchoControlFactory> ec3_factory(new webrtc::EchoCanceller3Factory());
+ webrtc::EchoCanceller3Config aec3_config;
+ std::unique_ptr<webrtc::EchoControlFactory> ec3_factory;
+
+ if (config) {
+ convert_to_aec3_config(config, &aec3_config);
+ ec3_factory.reset(
+ new webrtc::EchoCanceller3Factory(aec3_config));
+ } else {
+ ec3_factory.reset(new webrtc::EchoCanceller3Factory());
+ }
switch (num_channels) {
case 1:
diff --git a/webrtc_apm.h b/webrtc_apm.h
index a68e96f..918c4ab 100644
--- a/webrtc_apm.h
+++ b/webrtc_apm.h
@@ -11,6 +11,152 @@
#define WEBRTC_APM_API __attribute__((visibility("default")))
+/*
+ * Structures exposing EchoCanceller3Config from upstream
+ * echo_canceller3_config.h to webrtc-apm library callers for
+ * tuning purpose. We need to update these parameter structures
+ * carefully because changing them could break the caller.
+ */
+struct delay {
+ size_t default_delay;
+ size_t down_sampling_factor;
+ size_t num_filters;
+ size_t api_call_jitter_blocks;
+ size_t min_echo_path_delay_blocks;
+ size_t delay_headroom_blocks;
+ size_t hysteresis_limit_1_blocks;
+ size_t hysteresis_limit_2_blocks;
+ size_t skew_hysteresis_blocks;
+};
+
+struct MainConfiguration {
+ size_t length_blocks;
+ float leakage_converged;
+ float leakage_diverged;
+ float error_floor;
+ float noise_gate;
+};
+
+struct ShadowConfiguration {
+ size_t length_blocks;
+ float rate;
+ float noise_gate;
+};
+
+struct filter {
+ struct MainConfiguration main;
+ struct ShadowConfiguration shadow;
+ struct MainConfiguration main_initial;
+ struct ShadowConfiguration shadow_initial;
+ int config_change_duration_blocks;
+};
+
+struct erle {
+ float min;
+ float max_l;
+ float max_h;
+};
+
+struct ep_strength {
+ float lf;
+ float mf;
+ float hf;
+ float default_len;
+ int echo_can_saturate;
+ int bounded_erl;
+};
+
+struct mask {
+ float m1;
+ float m2;
+ float m3;
+ float m5;
+ float m6;
+ float m7;
+ float m8;
+ float m9;
+
+ float gain_curve_offset;
+ float gain_curve_slope;
+ float temporal_masking_lf;
+ float temporal_masking_hf;
+ size_t temporal_masking_lf_bands;
+};
+
+struct echo_audibility {
+ float low_render_limit;
+ float normal_render_limit;
+ float floor_power;
+ float audibility_threshold_lf;
+ float audibility_threshold_mf;
+ float audibility_threshold_hf;
+ int use_stationary_properties;
+};
+
+struct render_levels {
+ float active_render_limit;
+ float poor_excitation_render_limit;
+};
+
+struct GainChanges {
+ float max_inc;
+ float max_dec;
+ float rate_inc;
+ float rate_dec;
+ float min_inc;
+ float min_dec;
+};
+
+struct gain_updates {
+ struct GainChanges low_noise;
+ struct GainChanges initial;
+ struct GainChanges normal;
+ struct GainChanges saturation;
+ struct GainChanges nonlinear;
+ float floor_first_increase;
+};
+
+struct GainRampup {
+ float first_non_zero_gain;
+ int non_zero_gain_blocks;
+ int full_gain_blocks;
+};
+
+struct echo_removal_control {
+ struct GainRampup gain_rampup;
+ int has_clock_drift;
+};
+
+struct echo_model {
+ size_t noise_floor_hold;
+ float min_noise_floor_power;
+ float stationary_gate_slope;
+ float noise_gate_power;
+ float noise_gate_slope;
+ size_t render_pre_window_size;
+ size_t render_post_window_size;
+ float nonlinear_hold;
+ float nonlinear_release;
+};
+
+struct suppressor {
+ size_t bands_with_reliable_coherence;
+ };
+
+struct aec_config {
+ struct delay delay;
+ struct filter filter;
+ struct erle erle;
+ struct ep_strength ep_strength;
+ struct mask gain_mask;
+ struct echo_audibility echo_audibility;
+ struct render_levels render_levels;
+ struct gain_updates gain_updates;
+ struct echo_removal_control echo_removal_control;
+ struct echo_model echo_model;
+ struct suppressor suppressor;
+};
+
/* Pointer to a webrtc::AudioProcessing instance. */
typedef void* webrtc_apm;
@@ -19,13 +165,12 @@
* Args:
* num_channels - Number of channels of the forward stream.
* frame_rate - Frame rate used by forward stream.
- * enable_echo_cancellation - Set to true to enable echo cancellation in
- * created webrtc_apm instance.
+ * aec_config - Pointer to aec config.
*/
WEBRTC_APM_API webrtc_apm webrtc_apm_create(
unsigned int num_channels,
unsigned int frame_rate,
- unsigned int enable_echo_cancellation);
+ struct aec_config *aec_config);
/* Destroys a webrtc_apm instance. */
WEBRTC_APM_API void webrtc_apm_destroy(webrtc_apm apm);