Utilizing the AEC3 config struct for constants.

This CL replaces inline constants with config struct
constants.

BUG=webrtc:5298

Review-Url: https://codereview.webrtc.org/3003733002
Cr-Commit-Position: refs/heads/master@{#19507}
This commit is contained in:
peah 2017-08-24 22:36:53 -07:00 committed by Commit Bot
parent 2dbc69fa64
commit 8cee56f254
20 changed files with 193 additions and 94 deletions

View File

@ -305,7 +305,7 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) {
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> n(kBlockSize, 0.f);
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
RenderSignalAnalyzer render_signal_analyzer;
std::vector<float> e(kBlockSize, 0.f);
std::array<float, kFftLength> s_scratch;

View File

@ -75,11 +75,15 @@ constexpr int kEchoPathChangeCounterMax = 2 * kNumBlocksPerSecond;
int AecState::instance_count_ = 0;
AecState::AecState(float reverb_decay)
AecState::AecState(const AudioProcessing::Config::EchoCanceller3& config)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
erle_estimator_(config.param.erle.min,
config.param.erle.max_l,
config.param.erle.max_h),
echo_path_change_counter_(kEchoPathChangeCounterInitial),
reverb_decay_(reverb_decay) {}
config_(config),
reverb_decay_(config_.param.ep_strength.default_len) {}
AecState::~AecState() = default;
@ -252,7 +256,8 @@ void AecState::UpdateReverb(
// Limit the estimated reverb_decay_ to the maximum one needed in practice
// to minimize the impact of incorrect estimates.
reverb_decay_ = std::min(0.8f, reverb_decay_);
reverb_decay_ =
std::min(config_.param.ep_strength.default_len, reverb_decay_);
}
reverb_decay_to_test_ = 0.9f;
reverb_decay_candidate_residual_ = -1.f;
@ -260,7 +265,7 @@ void AecState::UpdateReverb(
// For noisy impulse responses, assume a fixed tail length.
if (tail_power > 0.0005f) {
reverb_decay_ = 0.7f;
reverb_decay_ = config_.param.ep_strength.default_len;
}
data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_);
data_dumper_->DumpRaw("aec3_tail_power", tail_power);

View File

@ -20,6 +20,7 @@
#include "webrtc/modules/audio_processing/aec3/erl_estimator.h"
#include "webrtc/modules/audio_processing/aec3/erle_estimator.h"
#include "webrtc/modules/audio_processing/aec3/render_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/rtc_base/array_view.h"
#include "webrtc/rtc_base/constructormagic.h"
#include "webrtc/rtc_base/optional.h"
@ -31,7 +32,7 @@ class ApmDataDumper;
// Handles the state and the conditions for the echo removal functionality.
class AecState {
public:
explicit AecState(float reverb_decay);
explicit AecState(const AudioProcessing::Config::EchoCanceller3& config);
~AecState();
// Returns whether the linear filter estimate is usable.
@ -140,13 +141,14 @@ class AecState {
rtc::Optional<size_t> filter_delay_;
rtc::Optional<size_t> external_delay_;
size_t blocks_since_last_saturation_ = 1000;
float reverb_decay_;
float reverb_decay_to_test_ = 0.9f;
float reverb_decay_candidate_ = 0.f;
float reverb_decay_candidate_residual_ = -1.f;
EchoAudibility echo_audibility_;
const AudioProcessing::Config::EchoCanceller3 config_;
float reverb_decay_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState);
RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
};
} // namespace webrtc

View File

@ -18,7 +18,7 @@ namespace webrtc {
// Verify the general functionality of AecState
TEST(AecState, NormalUsage) {
ApmDataDumper data_dumper(42);
AecState state(0.f);
AecState state(AudioProcessing::Config::EchoCanceller3{});
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main = {};
@ -163,7 +163,7 @@ TEST(AecState, NormalUsage) {
// Verifies the a non-significant delay is correctly identified.
TEST(AecState, NonSignificantDelay) {
AecState state(0.f);
AecState state(AudioProcessing::Config::EchoCanceller3{});
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main;
@ -192,7 +192,7 @@ TEST(AecState, NonSignificantDelay) {
// Verifies the delay for a converged filter is correctly identified.
TEST(AecState, ConvergedFilterDelay) {
constexpr int kFilterLength = 10;
AecState state(0.f);
AecState state(AudioProcessing::Config::EchoCanceller3{});
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main;
@ -228,7 +228,7 @@ TEST(AecState, ConvergedFilterDelay) {
// Verify that the externally reported delay is properly reported and converted.
TEST(AecState, ExternalDelay) {
AecState state(0.f);
AecState state(AudioProcessing::Config::EchoCanceller3{});
std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow;
std::array<float, kFftLengthBy2Plus1> Y2;

View File

@ -36,7 +36,8 @@ TEST(ComfortNoiseGenerator, NullLowerBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2;
FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
.Compute(AecState(0.f), N2, nullptr, &noise),
.Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
N2, nullptr, &noise),
"");
}
@ -44,7 +45,8 @@ TEST(ComfortNoiseGenerator, NullUpperBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2;
FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
.Compute(AecState(0.f), N2, &noise, nullptr),
.Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
N2, &noise, nullptr),
"");
}
@ -91,7 +93,7 @@ TEST(ComfortNoiseGenerator, TestOptimizations) {
TEST(ComfortNoiseGenerator, CorrectLevel) {
ComfortNoiseGenerator cng(DetectOptimization());
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
std::array<float, kFftLengthBy2Plus1> N2;
N2.fill(1000.f * 1000.f);

View File

@ -72,6 +72,7 @@ class EchoRemoverImpl final : public EchoRemover {
private:
static int instance_count_;
const AudioProcessing::Config::EchoCanceller3 config_;
const Aec3Fft fft_;
std::unique_ptr<ApmDataDumper> data_dumper_;
const Aec3Optimization optimization_;
@ -95,16 +96,18 @@ int EchoRemoverImpl::instance_count_ = 0;
EchoRemoverImpl::EchoRemoverImpl(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz)
: fft_(),
: config_(config),
fft_(),
data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
optimization_(DetectOptimization()),
sample_rate_hz_(sample_rate_hz),
subtractor_(data_dumper_.get(), optimization_),
suppression_gain_(optimization_),
suppression_gain_(config_, optimization_),
cng_(optimization_),
suppression_filter_(sample_rate_hz_),
aec_state_(0.8f) {
residual_echo_estimator_(config_),
aec_state_(config_) {
RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
}

View File

@ -126,7 +126,7 @@ TEST(DbMetric, Constructor) {
// Verify the general functionality of EchoRemoverMetrics.
TEST(EchoRemoverMetrics, NormalUsage) {
EchoRemoverMetrics metrics;
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
std::array<float, kFftLengthBy2Plus1> suppressor_gain;
comfort_noise_spectrum.fill(10.f);

View File

@ -16,16 +16,13 @@
namespace webrtc {
namespace {
constexpr float kMinErle = 1.f;
constexpr float kMaxLfErle = 8.f;
constexpr float kMaxHfErle = 1.5f;
} // namespace
ErleEstimator::ErleEstimator() {
erle_.fill(kMinErle);
ErleEstimator::ErleEstimator(float min_erle,
float max_erle_lf,
float max_erle_hf)
: min_erle_(min_erle),
max_erle_lf_(max_erle_lf),
max_erle_hf_(max_erle_hf) {
erle_.fill(min_erle_);
hold_counters_.fill(0);
}
@ -50,19 +47,19 @@ void ErleEstimator::Update(
if (new_erle > erle_[k]) {
hold_counters_[k - 1] = 100;
erle_[k] += 0.1f * (new_erle - erle_[k]);
erle_[k] = rtc::SafeClamp(erle_[k], kMinErle, max_erle);
erle_[k] = rtc::SafeClamp(erle_[k], min_erle_, max_erle);
}
}
}
};
erle_update(1, kFftLengthBy2 / 2, kMaxLfErle);
erle_update(kFftLengthBy2 / 2, kFftLengthBy2, kMaxHfErle);
erle_update(1, kFftLengthBy2 / 2, max_erle_lf_);
erle_update(kFftLengthBy2 / 2, kFftLengthBy2, max_erle_hf_);
std::for_each(hold_counters_.begin(), hold_counters_.end(),
[](int& a) { --a; });
std::transform(hold_counters_.begin(), hold_counters_.end(),
erle_.begin() + 1, erle_.begin() + 1, [](int a, float b) {
return a > 0 ? b : std::max(kMinErle, 0.97f * b);
erle_.begin() + 1, erle_.begin() + 1, [&](int a, float b) {
return a > 0 ? b : std::max(min_erle_, 0.97f * b);
});
erle_[0] = erle_[1];

View File

@ -21,7 +21,7 @@ namespace webrtc {
// Estimates the echo return loss enhancement based on the signal spectra.
class ErleEstimator {
public:
ErleEstimator();
ErleEstimator(float min_erle, float max_erle_lf, float max_erle_hf);
~ErleEstimator();
// Updates the ERLE estimate.
@ -35,6 +35,9 @@ class ErleEstimator {
private:
std::array<float, kFftLengthBy2Plus1> erle_;
std::array<int, kFftLengthBy2Minus1> hold_counters_;
const float min_erle_;
const float max_erle_lf_;
const float max_erle_hf_;
RTC_DISALLOW_COPY_AND_ASSIGN(ErleEstimator);
};

View File

@ -36,7 +36,7 @@ TEST(ErleEstimator, Estimates) {
std::array<float, kFftLengthBy2Plus1> E2;
std::array<float, kFftLengthBy2Plus1> Y2;
ErleEstimator estimator;
ErleEstimator estimator(1.f, 8.f, 1.5f);
// Verifies that the ERLE estimate is properley increased to higher values.
X2.fill(500 * 1000.f * 1000.f);

View File

@ -53,7 +53,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s_scratch;
std::array<float, kBlockSize> s;

View File

@ -79,7 +79,9 @@ constexpr float kHeadsetEchoPathGain = 0.0005f;
} // namespace
ResidualEchoEstimator::ResidualEchoEstimator() {
ResidualEchoEstimator::ResidualEchoEstimator(
const AudioProcessing::Config::EchoCanceller3& config)
: config_(config) {
Reset();
}
@ -188,11 +190,12 @@ void ResidualEchoEstimator::NonLinearEstimate(
const std::array<float, kFftLengthBy2Plus1>& Y2,
std::array<float, kFftLengthBy2Plus1>* R2) {
// Choose gains.
const float echo_path_gain_lf = headset_detected ? kHeadsetEchoPathGain : 100;
const float echo_path_gain_lf =
headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.lf;
const float echo_path_gain_mf =
headset_detected ? kHeadsetEchoPathGain : 1000;
headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.mf;
const float echo_path_gain_hf =
headset_detected ? kHeadsetEchoPathGain : 5000;
headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.hf;
// Compute preliminary residual echo.
std::transform(

View File

@ -18,6 +18,7 @@
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/aec3/render_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/rtc_base/array_view.h"
#include "webrtc/rtc_base/constructormagic.h"
@ -25,7 +26,8 @@ namespace webrtc {
class ResidualEchoEstimator {
public:
ResidualEchoEstimator();
explicit ResidualEchoEstimator(
const AudioProcessing::Config::EchoCanceller3& config);
~ResidualEchoEstimator();
void Estimate(bool using_subtractor_output,
@ -69,8 +71,9 @@ class ResidualEchoEstimator {
S2_old_;
std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
const AudioProcessing::Config::EchoCanceller3 config_;
RTC_DISALLOW_COPY_AND_ASSIGN(ResidualEchoEstimator);
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
};
} // namespace webrtc

View File

@ -12,6 +12,7 @@
#include "webrtc/modules/audio_processing/aec3/aec3_fft.h"
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h"
#include "webrtc/rtc_base/random.h"
#include "webrtc/test/gtest.h"
@ -22,22 +23,25 @@ namespace webrtc {
// Verifies that the check for non-null output residual echo power works.
TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10));
std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
std::array<float, kFftLengthBy2Plus1> S2_linear;
std::array<float, kFftLengthBy2Plus1> Y2;
EXPECT_DEATH(ResidualEchoEstimator().Estimate(true, aec_state, render_buffer,
S2_linear, Y2, nullptr),
"");
EXPECT_DEATH(
ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{})
.Estimate(true, aec_state, render_buffer, S2_linear, Y2, nullptr),
"");
}
#endif
TEST(ResidualEchoEstimator, BasicTest) {
ResidualEchoEstimator estimator;
AecState aec_state(0.f);
ResidualEchoEstimator estimator(AudioProcessing::Config::EchoCanceller3{});
AudioProcessing::Config::EchoCanceller3 config;
config.param.ep_strength.default_len = 0.f;
AecState aec_state(config);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10));
std::array<float, kFftLengthBy2Plus1> E2_main;

View File

@ -47,7 +47,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s;
FftData S;

View File

@ -40,7 +40,7 @@ float RunSubtractorTest(int num_blocks_to_process,
std::array<float, kFftLengthBy2Plus1> Y2;
std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow;
AecState aec_state(0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
x_old.fill(0.f);
Y2.fill(0.f);
E2_main.fill(0.f);
@ -109,9 +109,11 @@ TEST(Subtractor, DISABLED_NullOutput) {
RenderSignalAnalyzer render_signal_analyzer;
std::vector<float> y(kBlockSize, 0.f);
EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(0.f), nullptr),
"");
EXPECT_DEATH(
subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(AudioProcessing::Config::EchoCanceller3{}),
nullptr),
"");
}
// Verifies the check for the capture signal size.
@ -124,9 +126,11 @@ TEST(Subtractor, WrongCaptureSize) {
std::vector<float> y(kBlockSize - 1, 0.f);
SubtractorOutput output;
EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(0.f), &output),
"");
EXPECT_DEATH(
subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(AudioProcessing::Config::EchoCanceller3{}),
&output),
"");
}
#endif

View File

@ -109,6 +109,7 @@ float UpperBandsGain(
// Limits the gain increase.
void UpdateMaxGainIncrease(
const AudioProcessing::Config::EchoCanceller3& config,
size_t no_saturation_counter,
bool low_noise_render,
const std::array<float, kFftLengthBy2Plus1>& last_echo,
@ -123,27 +124,28 @@ void UpdateMaxGainIncrease(
float min_increasing;
float min_decreasing;
auto& param = config.param.gain_updates;
if (low_noise_render) {
max_increasing = 8.f;
max_decreasing = 8.f;
rate_increasing = 2.f;
rate_decreasing = 2.f;
min_increasing = 4.f;
min_decreasing = 4.f;
max_increasing = param.low_noise.max_inc;
max_decreasing = param.low_noise.max_dec;
rate_increasing = param.low_noise.rate_inc;
rate_decreasing = param.low_noise.rate_dec;
min_increasing = param.low_noise.min_inc;
min_decreasing = param.low_noise.min_dec;
} else if (no_saturation_counter > 10) {
max_increasing = 4.f;
max_decreasing = 4.f;
rate_increasing = 2.f;
rate_decreasing = 2.f;
min_increasing = 1.2f;
min_decreasing = 2.f;
max_increasing = param.normal.max_inc;
max_decreasing = param.normal.max_dec;
rate_increasing = param.normal.rate_inc;
rate_decreasing = param.normal.rate_dec;
min_increasing = param.normal.min_inc;
min_decreasing = param.normal.min_dec;
} else {
max_increasing = 1.2f;
max_decreasing = 1.2f;
rate_increasing = 1.5f;
rate_decreasing = 1.5f;
min_increasing = 1.f;
min_decreasing = 1.f;
max_increasing = param.saturation.max_inc;
max_decreasing = param.saturation.max_dec;
rate_increasing = param.saturation.rate_inc;
rate_decreasing = param.saturation.rate_dec;
min_increasing = param.saturation.min_inc;
min_decreasing = param.saturation.min_dec;
}
for (size_t k = 0; k < new_gain.size(); ++k) {
@ -163,6 +165,7 @@ void UpdateMaxGainIncrease(
// Computes the gain to reduce the echo to a non audible level.
void GainToNoAudibleEcho(
const AudioProcessing::Config::EchoCanceller3& config,
bool low_noise_render,
bool saturated_echo,
const std::array<float, kFftLengthBy2Plus1>& nearend,
@ -172,16 +175,17 @@ void GainToNoAudibleEcho(
const std::array<float, kFftLengthBy2Plus1>& max_gain,
const std::array<float, kFftLengthBy2Plus1>& one_by_echo,
std::array<float, kFftLengthBy2Plus1>* gain) {
constexpr float kEchoMaskingMargin = 1.f / 100.f;
const float nearend_masking_margin =
low_noise_render ? 0.1f : (saturated_echo ? 0.001f : 0.01f);
low_noise_render ? 0.1f
: (saturated_echo ? config.param.gain_mask.m2
: config.param.gain_mask.m3);
for (size_t k = 0; k < gain->size(); ++k) {
RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]);
if (echo[k] <= nearend_masking_margin * nearend[k]) {
(*gain)[k] = 1.f;
} else {
(*gain)[k] = kEchoMaskingMargin * masker[k] * one_by_echo[k];
(*gain)[k] = config.param.gain_mask.m1 * masker[k] * one_by_echo[k];
}
(*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]);
@ -189,7 +193,8 @@ void GainToNoAudibleEcho(
}
// Computes the signal output power that masks the echo signal.
void MaskingPower(const std::array<float, kFftLengthBy2Plus1>& nearend,
void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config,
const std::array<float, kFftLengthBy2Plus1>& nearend,
const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
const std::array<float, kFftLengthBy2Plus1>& last_masker,
const std::array<float, kFftLengthBy2Plus1>& gain,
@ -197,7 +202,8 @@ void MaskingPower(const std::array<float, kFftLengthBy2Plus1>& nearend,
std::array<float, kFftLengthBy2Plus1> side_band_masker;
for (size_t k = 0; k < gain.size(); ++k) {
side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k];
(*masker)[k] = comfort_noise[k] + 0.1f * last_masker[k];
(*masker)[k] =
comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k];
}
for (size_t k = 1; k < gain.size() - 1; ++k) {
(*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]);
@ -227,7 +233,9 @@ void SuppressionGain::LowerBandGain(
// Compute the minimum gain as the attenuating gain to put the signal just
// above the zero sample values.
std::array<float, kFftLengthBy2Plus1> min_gain;
const float min_echo_power = low_noise_render ? 192.f : 64.f;
const float min_echo_power =
low_noise_render ? config_.param.echo_audibility.low_render_limit
: config_.param.echo_audibility.normal_render_limit;
if (no_saturation_counter_ > 10) {
for (size_t k = 0; k < nearend.size(); ++k) {
const float denom = std::min(nearend[k], echo[k]);
@ -243,7 +251,9 @@ void SuppressionGain::LowerBandGain(
std::array<float, kFftLengthBy2Plus1> max_gain;
for (size_t k = 0; k < gain->size(); ++k) {
max_gain[k] =
std::min(std::max(last_gain_[k] * gain_increase_[k], 0.001f), 1.f);
std::min(std::max(last_gain_[k] * gain_increase_[k],
config_.param.gain_updates.floor_first_increase),
1.f);
}
// Iteratively compute the gain required to attenuate the echo to a non
@ -251,9 +261,9 @@ void SuppressionGain::LowerBandGain(
gain->fill(0.f);
for (int k = 0; k < 2; ++k) {
std::array<float, kFftLengthBy2Plus1> masker;
MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker);
GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker,
min_gain, max_gain, one_by_echo, gain);
MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker);
GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend,
echo, masker, min_gain, max_gain, one_by_echo, gain);
AdjustForExternalFilters(gain);
if (narrow_peak_band) {
NarrowBandAttenuation(*narrow_peak_band, gain);
@ -261,18 +271,21 @@ void SuppressionGain::LowerBandGain(
}
// Update the allowed maximum gain increase.
UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_,
echo, last_gain_, *gain, &gain_increase_);
UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render,
last_echo_, echo, last_gain_, *gain, &gain_increase_);
// Store data required for the gain computation of the next block.
std::copy(echo.begin(), echo.end(), last_echo_.begin());
std::copy(gain->begin(), gain->end(), last_gain_.begin());
MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_);
MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain,
&last_masker_);
aec3::VectorMath(optimization_).Sqrt(*gain);
}
SuppressionGain::SuppressionGain(Aec3Optimization optimization)
: optimization_(optimization) {
SuppressionGain::SuppressionGain(
const AudioProcessing::Config::EchoCanceller3& config,
Aec3Optimization optimization)
: optimization_(optimization), config_(config) {
last_gain_.fill(1.f);
last_masker_.fill(0.f);
gain_increase_.fill(1.f);

View File

@ -16,13 +16,15 @@
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
#include "webrtc/modules/audio_processing/aec3/render_signal_analyzer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/rtc_base/constructormagic.h"
namespace webrtc {
class SuppressionGain {
public:
explicit SuppressionGain(Aec3Optimization optimization);
SuppressionGain(const AudioProcessing::Config::EchoCanceller3& config,
Aec3Optimization optimization);
void GetGain(const std::array<float, kFftLengthBy2Plus1>& nearend,
const std::array<float, kFftLengthBy2Plus1>& echo,
const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
@ -58,7 +60,8 @@ class SuppressionGain {
LowNoiseRenderDetector low_render_detector_;
size_t no_saturation_counter_ = 0;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGain);
const AudioProcessing::Config::EchoCanceller3 config_;
RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
};
} // namespace webrtc

View File

@ -29,7 +29,8 @@ TEST(SuppressionGain, NullOutputGains) {
R2.fill(0.f);
N2.fill(0.f);
float high_bands_gain;
EXPECT_DEATH(SuppressionGain(DetectOptimization())
EXPECT_DEATH(SuppressionGain(AudioProcessing::Config::EchoCanceller3{},
DetectOptimization())
.GetGain(E2, R2, N2, RenderSignalAnalyzer(), false,
std::vector<std::vector<float>>(
3, std::vector<float>(kBlockSize, 0.f)),
@ -41,7 +42,8 @@ TEST(SuppressionGain, NullOutputGains) {
// Does a sanity check that the gains are correctly computed.
TEST(SuppressionGain, BasicGainComputation) {
SuppressionGain suppression_gain(DetectOptimization());
SuppressionGain suppression_gain(AudioProcessing::Config::EchoCanceller3(),
DetectOptimization());
RenderSignalAnalyzer analyzer;
float high_bands_gain;
std::array<float, kFftLengthBy2Plus1> E2;

View File

@ -17,6 +17,7 @@
#include <math.h>
#include <stddef.h> // size_t
#include <stdio.h> // FILE
#include <string.h>
#include <vector>
#include "webrtc/modules/audio_processing/beamformer/array_util.h"
@ -267,6 +268,49 @@ class AudioProcessing : public rtc::RefCountInterface {
// The functionality is not yet activated in the code and turning this on
// does not yet have the desired behavior.
struct EchoCanceller3 {
struct Param {
struct Erle {
float min = 1.f;
float max_l = 8.f;
float max_h = 1.5f;
} erle;
struct EpStrength {
float lf = 100.f;
float mf = 1000.f;
float hf = 5000.f;
float default_len = 0.7f;
} ep_strength;
struct Mask {
float m1 = 0.01f;
float m2 = 0.001f;
float m3 = 0.01f;
float m4 = 0.1f;
} gain_mask;
struct EchoAudibility {
float low_render_limit = 192.f;
float normal_render_limit = 64.f;
} echo_audibility;
struct GainUpdates {
struct GainChanges {
float max_inc;
float max_dec;
float rate_inc;
float rate_dec;
float min_inc;
float min_dec;
};
GainChanges low_noise = {8.f, 8.f, 2.f, 2.f, 4.f, 4.f};
GainChanges normal = {4.f, 4.f, 2.f, 2.f, 1.2f, 2.f};
GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
float floor_first_increase = 0.001f;
} gain_updates;
} param;
bool enabled = false;
} echo_canceller3;
@ -277,6 +321,17 @@ class AudioProcessing : public rtc::RefCountInterface {
struct GainController2 {
bool enabled = false;
} gain_controller2;
// Explicit copy assignment implementation to avoid issues with memory
// sanitizer complaints in case of self-assignment.
// TODO(peah): Add buildflag to ensure that this is only included for memory
// sanitizer builds.
Config& operator=(const Config& config) {
if (this != &config) {
memcpy(this, &config, sizeof(*this));
}
return *this;
}
};
// TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.