mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
Increase coverage of AEC3 JSON config unit tests, fix bugs
The new test checks that json strings are unchanged when parsing to a config and back to a string. This ensures that everything in the json representations is parsed when created a config from the json. This CL also adds the render_levels config substruct to the JSON parser. Some issues were surfaced by the new test: - Config validation clamping silently passed NaNs - Config validation only fixed the first out-of-bounds parameter, and not any subsequent ones - Config validation did not check all values in the config Bug: webrtc:9535 Change-Id: Ie7b588731dc1fe26ba71d1eb2f177f3b3b8139e3 Reviewed-on: https://webrtc-review.googlesource.com/c/107120 Commit-Queue: Sam Zackrisson <saza@webrtc.org> Reviewed-by: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25310}
This commit is contained in:
parent
f7a7c8a8bc
commit
8ee06a7b0c
4 changed files with 165 additions and 137 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include "api/audio/echo_canceller3_config.h"
|
#include "api/audio/echo_canceller3_config.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/numerics/safe_minmax.h"
|
#include "rtc_base/numerics/safe_minmax.h"
|
||||||
|
@ -18,6 +19,7 @@ namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
bool Limit(float* value, float min, float max) {
|
bool Limit(float* value, float min, float max) {
|
||||||
float clamped = rtc::SafeClamp(*value, min, max);
|
float clamped = rtc::SafeClamp(*value, min, max);
|
||||||
|
clamped = std::isfinite(clamped) ? clamped : min;
|
||||||
bool res = *value == clamped;
|
bool res = *value == clamped;
|
||||||
*value = clamped;
|
*value = clamped;
|
||||||
return res;
|
return res;
|
||||||
|
@ -85,164 +87,161 @@ bool EchoCanceller3Config::Validate(EchoCanceller3Config* config) {
|
||||||
c->delay.down_sampling_factor = 4;
|
c->delay.down_sampling_factor = 4;
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->delay.num_filters == 0) {
|
|
||||||
c->delay.num_filters = 1;
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
if (c->delay.api_call_jitter_blocks == 0) {
|
|
||||||
c->delay.api_call_jitter_blocks = 1;
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->delay.api_call_jitter_blocks == 0) {
|
|
||||||
c->delay.api_call_jitter_blocks = 1;
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
if (c->delay.delay_headroom_blocks <= 1 &&
|
if (c->delay.delay_headroom_blocks <= 1 &&
|
||||||
c->delay.hysteresis_limit_1_blocks == 1) {
|
c->delay.hysteresis_limit_1_blocks == 1) {
|
||||||
c->delay.hysteresis_limit_1_blocks = 0;
|
c->delay.hysteresis_limit_1_blocks = 0;
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
res = res && Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
|
res = res & Limit(&c->delay.default_delay, 0, 5000);
|
||||||
res = res && Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
|
res = res & Limit(&c->delay.num_filters, 0, 5000);
|
||||||
res = res && Limit(&c->delay.delay_selection_thresholds.initial, 1, 250);
|
res = res & Limit(&c->delay.api_call_jitter_blocks, 1, 5000);
|
||||||
res = res && Limit(&c->delay.delay_selection_thresholds.converged, 1, 250);
|
res = res & Limit(&c->delay.min_echo_path_delay_blocks, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.delay_headroom_blocks, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.hysteresis_limit_1_blocks, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.hysteresis_limit_2_blocks, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.skew_hysteresis_blocks, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000);
|
||||||
|
res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
|
||||||
|
res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
|
||||||
|
res = res & Limit(&c->delay.delay_selection_thresholds.initial, 1, 250);
|
||||||
|
res = res & Limit(&c->delay.delay_selection_thresholds.converged, 1, 250);
|
||||||
|
|
||||||
res = res && Limit(&c->filter.main.length_blocks, 1, 50);
|
res = res & Limit(&c->filter.main.length_blocks, 1, 50);
|
||||||
res = res && Limit(&c->filter.main.leakage_converged, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main.leakage_converged, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main.leakage_diverged, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main.leakage_diverged, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main.error_floor, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main.error_floor, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main.noise_gate, 0.f, 100000000.f);
|
res = res & Limit(&c->filter.main.error_ceil, 0.f, 100000000.f);
|
||||||
|
res = res & Limit(&c->filter.main.noise_gate, 0.f, 100000000.f);
|
||||||
|
|
||||||
res = res && Limit(&c->filter.main_initial.length_blocks, 1, 50);
|
res = res & Limit(&c->filter.main_initial.length_blocks, 1, 50);
|
||||||
res = res && Limit(&c->filter.main_initial.leakage_converged, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main_initial.leakage_converged, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main_initial.leakage_diverged, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main_initial.leakage_diverged, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main_initial.error_floor, 0.f, 1000.f);
|
res = res & Limit(&c->filter.main_initial.error_floor, 0.f, 1000.f);
|
||||||
res = res && Limit(&c->filter.main_initial.noise_gate, 0.f, 100000000.f);
|
res = res & Limit(&c->filter.main_initial.error_ceil, 0.f, 100000000.f);
|
||||||
|
res = res & Limit(&c->filter.main_initial.noise_gate, 0.f, 100000000.f);
|
||||||
|
|
||||||
if (c->filter.main.length_blocks < c->filter.main_initial.length_blocks) {
|
if (c->filter.main.length_blocks < c->filter.main_initial.length_blocks) {
|
||||||
c->filter.main_initial.length_blocks = c->filter.main.length_blocks;
|
c->filter.main_initial.length_blocks = c->filter.main.length_blocks;
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = res && Limit(&c->filter.shadow.length_blocks, 1, 50);
|
res = res & Limit(&c->filter.shadow.length_blocks, 1, 50);
|
||||||
res = res && Limit(&c->filter.shadow.rate, 0.f, 1.f);
|
res = res & Limit(&c->filter.shadow.rate, 0.f, 1.f);
|
||||||
res = res && Limit(&c->filter.shadow.noise_gate, 0.f, 100000000.f);
|
res = res & Limit(&c->filter.shadow.noise_gate, 0.f, 100000000.f);
|
||||||
|
|
||||||
res = res && Limit(&c->filter.shadow_initial.length_blocks, 1, 50);
|
res = res & Limit(&c->filter.shadow_initial.length_blocks, 1, 50);
|
||||||
res = res && Limit(&c->filter.shadow_initial.rate, 0.f, 1.f);
|
res = res & Limit(&c->filter.shadow_initial.rate, 0.f, 1.f);
|
||||||
res = res && Limit(&c->filter.shadow_initial.noise_gate, 0.f, 100000000.f);
|
res = res & Limit(&c->filter.shadow_initial.noise_gate, 0.f, 100000000.f);
|
||||||
|
|
||||||
if (c->filter.shadow.length_blocks < c->filter.shadow_initial.length_blocks) {
|
if (c->filter.shadow.length_blocks < c->filter.shadow_initial.length_blocks) {
|
||||||
c->filter.shadow_initial.length_blocks = c->filter.shadow.length_blocks;
|
c->filter.shadow_initial.length_blocks = c->filter.shadow.length_blocks;
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = res && Limit(&c->filter.config_change_duration_blocks, 0, 100000);
|
res = res & Limit(&c->filter.config_change_duration_blocks, 0, 100000);
|
||||||
res = res && Limit(&c->filter.initial_state_seconds, 0.f, 100.f);
|
res = res & Limit(&c->filter.initial_state_seconds, 0.f, 100.f);
|
||||||
|
|
||||||
res = res && Limit(&c->erle.min, 1.f, 100000.f);
|
res = res & Limit(&c->erle.min, 1.f, 100000.f);
|
||||||
res = res && Limit(&c->erle.max_l, 1.f, 100000.f);
|
res = res & Limit(&c->erle.max_l, 1.f, 100000.f);
|
||||||
res = res && Limit(&c->erle.max_h, 1.f, 100000.f);
|
res = res & Limit(&c->erle.max_h, 1.f, 100000.f);
|
||||||
if (c->erle.min > c->erle.max_l || c->erle.min > c->erle.max_h) {
|
if (c->erle.min > c->erle.max_l || c->erle.min > c->erle.max_h) {
|
||||||
c->erle.min = std::min(c->erle.max_l, c->erle.max_h);
|
c->erle.min = std::min(c->erle.max_l, c->erle.max_h);
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = res && Limit(&c->ep_strength.lf, 0.f, 1000000.f);
|
res = res & Limit(&c->ep_strength.lf, 0.f, 1000000.f);
|
||||||
res = res && Limit(&c->ep_strength.mf, 0.f, 1000000.f);
|
res = res & Limit(&c->ep_strength.mf, 0.f, 1000000.f);
|
||||||
res = res && Limit(&c->ep_strength.hf, 0.f, 1000000.f);
|
res = res & Limit(&c->ep_strength.hf, 0.f, 1000000.f);
|
||||||
res = res && Limit(&c->ep_strength.default_len, 0.f, 1.f);
|
res = res & Limit(&c->ep_strength.default_len, 0.f, 1.f);
|
||||||
|
|
||||||
res = res &&
|
res =
|
||||||
Limit(&c->echo_audibility.low_render_limit, 0.f, 32768.f * 32768.f);
|
res & Limit(&c->echo_audibility.low_render_limit, 0.f, 32768.f * 32768.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->echo_audibility.normal_render_limit, 0.f, 32768.f * 32768.f);
|
Limit(&c->echo_audibility.normal_render_limit, 0.f, 32768.f * 32768.f);
|
||||||
res = res && Limit(&c->echo_audibility.floor_power, 0.f, 32768.f * 32768.f);
|
res = res & Limit(&c->echo_audibility.floor_power, 0.f, 32768.f * 32768.f);
|
||||||
res = res && Limit(&c->echo_audibility.audibility_threshold_lf, 0.f,
|
res = res & Limit(&c->echo_audibility.audibility_threshold_lf, 0.f,
|
||||||
32768.f * 32768.f);
|
32768.f * 32768.f);
|
||||||
res = res && Limit(&c->echo_audibility.audibility_threshold_mf, 0.f,
|
res = res & Limit(&c->echo_audibility.audibility_threshold_mf, 0.f,
|
||||||
32768.f * 32768.f);
|
32768.f * 32768.f);
|
||||||
res = res && Limit(&c->echo_audibility.audibility_threshold_hf, 0.f,
|
res = res & Limit(&c->echo_audibility.audibility_threshold_hf, 0.f,
|
||||||
32768.f * 32768.f);
|
32768.f * 32768.f);
|
||||||
|
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->render_levels.active_render_limit, 0.f, 32768.f * 32768.f);
|
Limit(&c->render_levels.active_render_limit, 0.f, 32768.f * 32768.f);
|
||||||
res = res && Limit(&c->render_levels.poor_excitation_render_limit, 0.f,
|
res = res & Limit(&c->render_levels.poor_excitation_render_limit, 0.f,
|
||||||
32768.f * 32768.f);
|
32768.f * 32768.f);
|
||||||
res = res && Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
|
res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
|
||||||
32768.f * 32768.f);
|
32768.f * 32768.f);
|
||||||
|
|
||||||
res =
|
res =
|
||||||
res && Limit(&c->echo_removal_control.gain_rampup.initial_gain, 0.f, 1.f);
|
res & Limit(&c->echo_removal_control.gain_rampup.initial_gain, 0.f, 1.f);
|
||||||
res = res && Limit(&c->echo_removal_control.gain_rampup.first_non_zero_gain,
|
res = res & Limit(&c->echo_removal_control.gain_rampup.first_non_zero_gain,
|
||||||
0.f, 1.f);
|
0.f, 1.f);
|
||||||
res = res && Limit(&c->echo_removal_control.gain_rampup.non_zero_gain_blocks,
|
res = res & Limit(&c->echo_removal_control.gain_rampup.non_zero_gain_blocks,
|
||||||
0, 100000);
|
0, 100000);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->echo_removal_control.gain_rampup.full_gain_blocks, 0, 100000);
|
Limit(&c->echo_removal_control.gain_rampup.full_gain_blocks, 0, 100000);
|
||||||
|
|
||||||
res = res && Limit(&c->echo_model.noise_floor_hold, 0, 1000);
|
res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000);
|
||||||
res = res && Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
|
res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
|
||||||
res = res && Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
|
res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
|
||||||
res = res && Limit(&c->echo_model.noise_gate_power, 0, 1000000.f);
|
res = res & Limit(&c->echo_model.noise_gate_power, 0, 1000000.f);
|
||||||
res = res && Limit(&c->echo_model.noise_gate_slope, 0, 1000000.f);
|
res = res & Limit(&c->echo_model.noise_gate_slope, 0, 1000000.f);
|
||||||
res = res && Limit(&c->echo_model.render_pre_window_size, 0, 100);
|
res = res & Limit(&c->echo_model.render_pre_window_size, 0, 100);
|
||||||
res = res && Limit(&c->echo_model.render_post_window_size, 0, 100);
|
res = res & Limit(&c->echo_model.render_post_window_size, 0, 100);
|
||||||
res = res && Limit(&c->echo_model.render_pre_window_size_init, 0, 100);
|
res = res & Limit(&c->echo_model.render_pre_window_size_init, 0, 100);
|
||||||
res = res && Limit(&c->echo_model.render_post_window_size_init, 0, 100);
|
res = res & Limit(&c->echo_model.render_post_window_size_init, 0, 100);
|
||||||
res = res && Limit(&c->echo_model.nonlinear_hold, 0, 100);
|
res = res & Limit(&c->echo_model.nonlinear_hold, 0, 100);
|
||||||
res = res && Limit(&c->echo_model.nonlinear_release, 0, 1.f);
|
res = res & Limit(&c->echo_model.nonlinear_release, 0, 1.f);
|
||||||
|
|
||||||
res = res &&
|
res = res & Limit(&c->suppressor.nearend_average_blocks, 1, 5000);
|
||||||
|
|
||||||
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_lf.enr_transparent, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_lf.enr_transparent, 0.f, 100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_lf.emr_transparent, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_lf.emr_transparent, 0.f, 100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_hf.enr_transparent, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_hf.enr_transparent, 0.f, 100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.normal_tuning.mask_hf.emr_transparent, 0.f, 100.f);
|
Limit(&c->suppressor.normal_tuning.mask_hf.emr_transparent, 0.f, 100.f);
|
||||||
res = res && Limit(&c->suppressor.normal_tuning.max_inc_factor, 0.f, 100.f);
|
res = res & Limit(&c->suppressor.normal_tuning.max_inc_factor, 0.f, 100.f);
|
||||||
res =
|
res = res & Limit(&c->suppressor.normal_tuning.max_dec_factor_lf, 0.f, 100.f);
|
||||||
res && Limit(&c->suppressor.normal_tuning.max_dec_factor_lf, 0.f, 100.f);
|
|
||||||
|
|
||||||
res = res && Limit(&c->suppressor.nearend_tuning.mask_lf.enr_transparent, 0.f,
|
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.enr_transparent, 0.f,
|
||||||
100.f);
|
100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.nearend_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
Limit(&c->suppressor.nearend_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
||||||
res = res && Limit(&c->suppressor.nearend_tuning.mask_lf.emr_transparent, 0.f,
|
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.emr_transparent, 0.f,
|
||||||
100.f);
|
100.f);
|
||||||
res = res && Limit(&c->suppressor.nearend_tuning.mask_hf.enr_transparent, 0.f,
|
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.enr_transparent, 0.f,
|
||||||
100.f);
|
100.f);
|
||||||
res = res &&
|
res = res &
|
||||||
Limit(&c->suppressor.nearend_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
Limit(&c->suppressor.nearend_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
||||||
res = res && Limit(&c->suppressor.nearend_tuning.mask_hf.emr_transparent, 0.f,
|
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.emr_transparent, 0.f,
|
||||||
100.f);
|
100.f);
|
||||||
res = res && Limit(&c->suppressor.nearend_tuning.max_inc_factor, 0.f, 100.f);
|
res = res & Limit(&c->suppressor.nearend_tuning.max_inc_factor, 0.f, 100.f);
|
||||||
res =
|
res =
|
||||||
res && Limit(&c->suppressor.nearend_tuning.max_dec_factor_lf, 0.f, 100.f);
|
res & Limit(&c->suppressor.nearend_tuning.max_dec_factor_lf, 0.f, 100.f);
|
||||||
|
|
||||||
res = res && Limit(&c->suppressor.dominant_nearend_detection.enr_threshold,
|
res = res & Limit(&c->suppressor.dominant_nearend_detection.enr_threshold,
|
||||||
0.f, 1000000.f);
|
0.f, 1000000.f);
|
||||||
res = res && Limit(&c->suppressor.dominant_nearend_detection.snr_threshold,
|
res = res & Limit(&c->suppressor.dominant_nearend_detection.snr_threshold,
|
||||||
0.f, 1000000.f);
|
0.f, 1000000.f);
|
||||||
res = res && Limit(&c->suppressor.dominant_nearend_detection.hold_duration, 0,
|
res = res & Limit(&c->suppressor.dominant_nearend_detection.hold_duration, 0,
|
||||||
10000);
|
10000);
|
||||||
res =
|
res = res & Limit(&c->suppressor.dominant_nearend_detection.trigger_threshold,
|
||||||
res && Limit(&c->suppressor.dominant_nearend_detection.trigger_threshold,
|
|
||||||
0, 10000);
|
0, 10000);
|
||||||
|
|
||||||
res = res && Limit(&c->suppressor.high_bands_suppression.enr_threshold, 0.f,
|
res = res & Limit(&c->suppressor.high_bands_suppression.enr_threshold, 0.f,
|
||||||
1000000.f);
|
1000000.f);
|
||||||
res = res && Limit(&c->suppressor.high_bands_suppression.max_gain_during_echo,
|
res = res & Limit(&c->suppressor.high_bands_suppression.max_gain_during_echo,
|
||||||
0.f, 1.f);
|
0.f, 1.f);
|
||||||
|
|
||||||
res = res && Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
|
res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace webrtc {
|
||||||
|
|
||||||
// Configuration struct for EchoCanceller3
|
// Configuration struct for EchoCanceller3
|
||||||
struct RTC_EXPORT EchoCanceller3Config {
|
struct RTC_EXPORT EchoCanceller3Config {
|
||||||
// Checks and updates the parameters in a config to lie within reasonable
|
// Checks and updates the config parameters to lie within (mostly) reasonable
|
||||||
// ranges. Returns true if and only of the config did not need to be changed.
|
// ranges. Returns true if and only of the config did not need to be changed.
|
||||||
static bool Validate(EchoCanceller3Config* config);
|
static bool Validate(EchoCanceller3Config* config);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ void ReadParam(const Json::Value& root, std::string param_name, size_t* param) {
|
||||||
RTC_DCHECK(param);
|
RTC_DCHECK(param);
|
||||||
int v;
|
int v;
|
||||||
if (rtc::GetIntFromJsonObject(root, param_name, &v)) {
|
if (rtc::GetIntFromJsonObject(root, param_name, &v)) {
|
||||||
|
RTC_DCHECK_GE(v, 0);
|
||||||
*param = v;
|
*param = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +217,7 @@ EchoCanceller3Config Aec3ConfigFromJsonString(absl::string_view json_string) {
|
||||||
&cfg.echo_audibility.audibility_threshold_hf);
|
&cfg.echo_audibility.audibility_threshold_hf);
|
||||||
ReadParam(section, "use_stationary_properties",
|
ReadParam(section, "use_stationary_properties",
|
||||||
&cfg.echo_audibility.use_stationary_properties);
|
&cfg.echo_audibility.use_stationary_properties);
|
||||||
ReadParam(section, "use_stationary_properties_at_init",
|
ReadParam(section, "use_stationarity_properties_at_init",
|
||||||
&cfg.echo_audibility.use_stationarity_properties_at_init);
|
&cfg.echo_audibility.use_stationarity_properties_at_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,34 +8,62 @@
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "api/audio/echo_canceller3_config_json.h"
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "api/audio/echo_canceller3_config.h"
|
#include "api/audio/echo_canceller3_config.h"
|
||||||
|
#include "api/audio/echo_canceller3_config_json.h"
|
||||||
|
#include "rtc_base/random.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
EchoCanceller3Config GenerateRandomConfig(Random* prng) {
|
||||||
|
std::array<uint8_t, sizeof(EchoCanceller3Config)> random_bytes;
|
||||||
|
for (uint8_t& byte : random_bytes) {
|
||||||
|
byte = prng->Rand<uint8_t>();
|
||||||
|
}
|
||||||
|
auto* config = reinterpret_cast<EchoCanceller3Config*>(random_bytes.data());
|
||||||
|
EchoCanceller3Config::Validate(config);
|
||||||
|
return *config;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
|
TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
|
||||||
EchoCanceller3Config cfg;
|
Random prng(7297352569823ull);
|
||||||
cfg.delay.down_sampling_factor = 1u;
|
for (int i = 0; i < 10; ++i) {
|
||||||
cfg.filter.shadow_initial.length_blocks = 7u;
|
EchoCanceller3Config cfg = GenerateRandomConfig(&prng);
|
||||||
cfg.suppressor.normal_tuning.mask_hf.enr_suppress = .5f;
|
|
||||||
std::string json_string = Aec3ConfigToJsonString(cfg);
|
std::string json_string = Aec3ConfigToJsonString(cfg);
|
||||||
EchoCanceller3Config cfg_transformed = Aec3ConfigFromJsonString(json_string);
|
EchoCanceller3Config cfg_transformed =
|
||||||
|
Aec3ConfigFromJsonString(json_string);
|
||||||
|
|
||||||
// Expect unchanged values to remain default.
|
// Expect an arbitrary subset of values to carry through the transformation.
|
||||||
EXPECT_EQ(cfg.filter.main.error_floor,
|
constexpr float kEpsilon = 1e-4;
|
||||||
cfg_transformed.filter.main.error_floor);
|
EXPECT_NEAR(cfg.filter.main.error_floor,
|
||||||
EXPECT_EQ(cfg.ep_strength.default_len,
|
cfg_transformed.filter.main.error_floor, kEpsilon);
|
||||||
cfg_transformed.ep_strength.default_len);
|
EXPECT_NEAR(cfg.ep_strength.default_len,
|
||||||
EXPECT_EQ(cfg.suppressor.normal_tuning.mask_lf.enr_suppress,
|
cfg_transformed.ep_strength.default_len, kEpsilon);
|
||||||
cfg_transformed.suppressor.normal_tuning.mask_lf.enr_suppress);
|
EXPECT_NEAR(cfg.suppressor.normal_tuning.mask_lf.enr_suppress,
|
||||||
|
cfg_transformed.suppressor.normal_tuning.mask_lf.enr_suppress,
|
||||||
// Expect changed values to carry through the transformation.
|
kEpsilon);
|
||||||
EXPECT_EQ(cfg.delay.down_sampling_factor,
|
EXPECT_EQ(cfg.delay.down_sampling_factor,
|
||||||
cfg_transformed.delay.down_sampling_factor);
|
cfg_transformed.delay.down_sampling_factor);
|
||||||
EXPECT_EQ(cfg.filter.shadow_initial.length_blocks,
|
EXPECT_EQ(cfg.filter.shadow_initial.length_blocks,
|
||||||
cfg_transformed.filter.shadow_initial.length_blocks);
|
cfg_transformed.filter.shadow_initial.length_blocks);
|
||||||
EXPECT_EQ(cfg.suppressor.normal_tuning.mask_hf.enr_suppress,
|
EXPECT_NEAR(cfg.suppressor.normal_tuning.mask_hf.enr_suppress,
|
||||||
cfg_transformed.suppressor.normal_tuning.mask_hf.enr_suppress);
|
cfg_transformed.suppressor.normal_tuning.mask_hf.enr_suppress,
|
||||||
|
kEpsilon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(EchoCanceller3JsonHelpers, IteratedToStringGivesIdenticalStrings) {
|
||||||
|
Random prng(7297352569824ull);
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
EchoCanceller3Config config = GenerateRandomConfig(&prng);
|
||||||
|
std::string json = Aec3ConfigToJsonString(config);
|
||||||
|
std::string iterated_json =
|
||||||
|
Aec3ConfigToJsonString(Aec3ConfigFromJsonString(json));
|
||||||
|
EXPECT_EQ(json, iterated_json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
Loading…
Reference in a new issue