Removed usage of the the redundant the render alignment headroom in AEC3

Bug: webrtc:8671
Change-Id: I1b7b1bc2f4677bbd375fc206c166b4b9fed3efce
Reviewed-on: https://webrtc-review.googlesource.com/35220
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21392}
This commit is contained in:
Per Åhgren
2017-12-20 18:00:51 +01:00
committed by Commit Bot
parent 60e8965b6b
commit de22a17b43
19 changed files with 47 additions and 168 deletions

View File

@ -389,8 +389,8 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) {
aec_state.HandleEchoPathChange(EchoPathVariability( aec_state.HandleEchoPathChange(EchoPathVariability(
false, EchoPathVariability::DelayAdjustment::kNone, false)); false, EchoPathVariability::DelayAdjustment::kNone, false));
aec_state.Update(filter.FilterFrequencyResponse(), aec_state.Update(filter.FilterFrequencyResponse(),
filter.FilterImpulseResponse(), true, rtc::nullopt, filter.FilterImpulseResponse(), true, *render_buffer,
*render_buffer, E2_main, Y2, x[0], s, false); E2_main, Y2, x[0], s, false);
} }
// Verify that the filter is able to perform well. // Verify that the filter is able to perform well.
EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f), EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f),

View File

@ -109,7 +109,6 @@ void AecState::Update(
adaptive_filter_frequency_response, adaptive_filter_frequency_response,
const std::vector<float>& adaptive_filter_impulse_response, const std::vector<float>& adaptive_filter_impulse_response,
bool converged_filter, bool converged_filter,
const rtc::Optional<size_t>& external_delay_samples,
const RenderBuffer& render_buffer, const RenderBuffer& render_buffer,
const std::array<float, kFftLengthBy2Plus1>& E2_main, const std::array<float, kFftLengthBy2Plus1>& E2_main,
const std::array<float, kFftLengthBy2Plus1>& Y2, const std::array<float, kFftLengthBy2Plus1>& Y2,
@ -134,12 +133,6 @@ void AecState::Update(
// Estimate delays. // Estimate delays.
filter_delay_ = EstimateFilterDelay(adaptive_filter_frequency_response); filter_delay_ = EstimateFilterDelay(adaptive_filter_frequency_response);
// TODO(peah): Remove the dependency on the external delay.
external_delay_ =
external_delay_samples
? rtc::Optional<size_t>(*external_delay_samples / kBlockSize)
: rtc::nullopt;
// Update the ERL and ERLE measures. // Update the ERL and ERLE measures.
if (converged_filter && capture_block_counter_ >= 2 * kNumBlocksPerSecond) { if (converged_filter && capture_block_counter_ >= 2 * kNumBlocksPerSecond) {
const auto& X2 = render_buffer.Spectrum(*filter_delay_); const auto& X2 = render_buffer.Spectrum(*filter_delay_);
@ -165,8 +158,7 @@ void AecState::Update(
usable_linear_estimate_ = usable_linear_estimate_ =
!echo_saturation_ && !echo_saturation_ &&
(converged_filter || filter_has_had_time_to_converge_) && (converged_filter || filter_has_had_time_to_converge_) &&
capture_block_counter_ >= 2 * kNumBlocksPerSecond && external_delay_ && capture_block_counter_ >= 2 * kNumBlocksPerSecond && !TransparentMode();
!TransparentMode();
// After an amount of active render samples for which an echo should have been // After an amount of active render samples for which an echo should have been
// detected in the capture signal if the ERL was not infinite, flag that a // detected in the capture signal if the ERL was not infinite, flag that a

View File

@ -64,9 +64,6 @@ class AecState {
// Returns the delay estimate based on the linear filter. // Returns the delay estimate based on the linear filter.
rtc::Optional<size_t> FilterDelay() const { return filter_delay_; } rtc::Optional<size_t> FilterDelay() const { return filter_delay_; }
// Returns the externally provided delay.
rtc::Optional<size_t> ExternalDelay() const { return external_delay_; }
// Returns whether the capture signal is saturated. // Returns whether the capture signal is saturated.
bool SaturatedCapture() const { return capture_signal_saturation_; } bool SaturatedCapture() const { return capture_signal_saturation_; }
@ -111,7 +108,6 @@ class AecState {
adaptive_filter_frequency_response, adaptive_filter_frequency_response,
const std::vector<float>& adaptive_filter_impulse_response, const std::vector<float>& adaptive_filter_impulse_response,
bool converged_filter, bool converged_filter,
const rtc::Optional<size_t>& external_delay_samples,
const RenderBuffer& render_buffer, const RenderBuffer& render_buffer,
const std::array<float, kFftLengthBy2Plus1>& E2_main, const std::array<float, kFftLengthBy2Plus1>& E2_main,
const std::array<float, kFftLengthBy2Plus1>& Y2, const std::array<float, kFftLengthBy2Plus1>& Y2,
@ -156,7 +152,6 @@ class AecState {
bool render_received_ = false; bool render_received_ = false;
size_t force_zero_gain_counter_ = 0; size_t force_zero_gain_counter_ = 0;
rtc::Optional<size_t> filter_delay_; rtc::Optional<size_t> filter_delay_;
rtc::Optional<size_t> external_delay_;
size_t blocks_since_last_saturation_ = 1000; size_t blocks_since_last_saturation_ = 1000;
float reverb_decay_to_test_ = 0.9f; float reverb_decay_to_test_ = 0.9f;
float reverb_decay_candidate_ = 0.f; float reverb_decay_candidate_ = 0.f;

View File

@ -46,17 +46,16 @@ TEST(AecState, NormalUsage) {
std::vector<float> impulse_response( std::vector<float> impulse_response(
GetTimeDomainLength(config.filter.length_blocks), 0.f); GetTimeDomainLength(config.filter.length_blocks), 0.f);
// Verify that linear AEC usability is false when the filter is diverged and // Verify that linear AEC usability is false when the filter is diverged.
// there is no external delay reported.
state.Update(diverged_filter_frequency_response, impulse_response, true, state.Update(diverged_filter_frequency_response, impulse_response, true,
rtc::nullopt, *render_delay_buffer->GetRenderBuffer(), E2_main, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
Y2, x[0], s, false); false);
EXPECT_FALSE(state.UsableLinearEstimate()); EXPECT_FALSE(state.UsableLinearEstimate());
// Verify that linear AEC usability is true when the filter is converged // Verify that linear AEC usability is true when the filter is converged
std::fill(x[0].begin(), x[0].end(), 101.f); std::fill(x[0].begin(), x[0].end(), 101.f);
for (int k = 0; k < 3000; ++k) { for (int k = 0; k < 3000; ++k) {
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
} }
@ -66,7 +65,7 @@ TEST(AecState, NormalUsage) {
// reported // reported
state.HandleEchoPathChange(EchoPathVariability( state.HandleEchoPathChange(EchoPathVariability(
true, EchoPathVariability::DelayAdjustment::kNone, false)); true, EchoPathVariability::DelayAdjustment::kNone, false));
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
EXPECT_FALSE(state.UsableLinearEstimate()); EXPECT_FALSE(state.UsableLinearEstimate());
@ -75,25 +74,25 @@ TEST(AecState, NormalUsage) {
std::fill(x[0].begin(), x[0].end(), 101.f); std::fill(x[0].begin(), x[0].end(), 101.f);
state.HandleEchoPathChange(EchoPathVariability( state.HandleEchoPathChange(EchoPathVariability(
true, EchoPathVariability::DelayAdjustment::kNewDetectedDelay, false)); true, EchoPathVariability::DelayAdjustment::kNewDetectedDelay, false));
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
EXPECT_FALSE(state.ActiveRender()); EXPECT_FALSE(state.ActiveRender());
for (int k = 0; k < 1000; ++k) { for (int k = 0; k < 1000; ++k) {
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
} }
EXPECT_TRUE(state.ActiveRender()); EXPECT_TRUE(state.ActiveRender());
// Verify that echo leakage is properly reported. // Verify that echo leakage is properly reported.
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
EXPECT_FALSE(state.EchoLeakageDetected()); EXPECT_FALSE(state.EchoLeakageDetected());
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
true); true);
EXPECT_TRUE(state.EchoLeakageDetected()); EXPECT_TRUE(state.EchoLeakageDetected());
@ -115,7 +114,7 @@ TEST(AecState, NormalUsage) {
Y2.fill(10.f * 10000.f * 10000.f); Y2.fill(10.f * 10000.f * 10000.f);
for (size_t k = 0; k < 1000; ++k) { for (size_t k = 0; k < 1000; ++k) {
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
} }
@ -132,7 +131,7 @@ TEST(AecState, NormalUsage) {
E2_main.fill(1.f * 10000.f * 10000.f); E2_main.fill(1.f * 10000.f * 10000.f);
Y2.fill(10.f * E2_main[0]); Y2.fill(10.f * E2_main[0]);
for (size_t k = 0; k < 1000; ++k) { for (size_t k = 0; k < 1000; ++k) {
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
} }
@ -153,7 +152,7 @@ TEST(AecState, NormalUsage) {
E2_main.fill(1.f * 10000.f * 10000.f); E2_main.fill(1.f * 10000.f * 10000.f);
Y2.fill(5.f * E2_main[0]); Y2.fill(5.f * E2_main[0]);
for (size_t k = 0; k < 1000; ++k) { for (size_t k = 0; k < 1000; ++k) {
state.Update(converged_filter_frequency_response, impulse_response, true, 2, state.Update(converged_filter_frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], s,
false); false);
} }
@ -203,7 +202,7 @@ TEST(AecState, ConvergedFilterDelay) {
frequency_response[k].fill(100.f); frequency_response[k].fill(100.f);
frequency_response[k][0] = 0.f; frequency_response[k][0] = 0.f;
state.HandleEchoPathChange(echo_path_variability); state.HandleEchoPathChange(echo_path_variability);
state.Update(frequency_response, impulse_response, true, rtc::nullopt, state.Update(frequency_response, impulse_response, true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x, s, *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x, s,
false); false);
EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay()); EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay());
@ -213,50 +212,4 @@ TEST(AecState, ConvergedFilterDelay) {
} }
} }
// Verify that the externally reported delay is properly reported and converted.
TEST(AecState, ExternalDelay) {
EchoCanceller3Config config;
AecState state(config);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, 3));
std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow;
std::array<float, kFftLengthBy2Plus1> Y2;
std::array<float, kBlockSize> x;
std::array<float, kBlockSize> s;
s.fill(100.f);
E2_main.fill(0.f);
E2_shadow.fill(0.f);
Y2.fill(0.f);
x.fill(0.f);
std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
config.filter.length_blocks);
for (auto& v : frequency_response) {
v.fill(0.01f);
}
std::vector<float> impulse_response(
GetTimeDomainLength(config.filter.length_blocks), 0.f);
for (size_t k = 0; k < frequency_response.size() - 1; ++k) {
state.HandleEchoPathChange(EchoPathVariability(
false, EchoPathVariability::DelayAdjustment::kNone, false));
state.Update(frequency_response, impulse_response, true, k * kBlockSize + 5,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x, s,
false);
EXPECT_TRUE(state.ExternalDelay());
EXPECT_EQ(k, state.ExternalDelay());
}
// Verify that the externally reported delay is properly unset when it is no
// longer present.
state.HandleEchoPathChange(EchoPathVariability(
false, EchoPathVariability::DelayAdjustment::kNone, false));
state.Update(frequency_response, impulse_response, true, rtc::nullopt,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x, s,
false);
EXPECT_FALSE(state.ExternalDelay());
}
} // namespace webrtc } // namespace webrtc

View File

@ -182,9 +182,8 @@ void BlockProcessorImpl::ProcessCapture(
// Remove the echo from the capture signal. // Remove the echo from the capture signal.
echo_remover_->ProcessCapture( echo_remover_->ProcessCapture(
delay_controller_->AlignmentHeadroomSamples(), echo_path_variability, echo_path_variability, capture_signal_saturation,
capture_signal_saturation, render_buffer_->GetRenderBuffer(), render_buffer_->GetRenderBuffer(), capture_block);
capture_block);
// Update the metrics. // Update the metrics.
metrics_.UpdateCapture(false); metrics_.UpdateCapture(false);

View File

@ -167,9 +167,7 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _)) EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _))
.Times(kNumBlocks) .Times(kNumBlocks)
.WillRepeatedly(Return(9)); .WillRepeatedly(Return(9));
EXPECT_CALL(*render_delay_controller_mock, AlignmentHeadroomSamples()) EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _))
.Times(kNumBlocks);
EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _, _))
.Times(kNumBlocks); .Times(kNumBlocks);
EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_)) EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_))
.Times(kNumBlocks); .Times(kNumBlocks);

View File

@ -58,8 +58,7 @@ class EchoRemoverImpl final : public EchoRemover {
// Removes the echo from a block of samples from the capture signal. The // Removes the echo from a block of samples from the capture signal. The
// supplied render signal is assumed to be pre-aligned with the capture // supplied render signal is assumed to be pre-aligned with the capture
// signal. // signal.
void ProcessCapture(const rtc::Optional<size_t>& echo_path_delay_samples, void ProcessCapture(const EchoPathVariability& echo_path_variability,
const EchoPathVariability& echo_path_variability,
bool capture_signal_saturation, bool capture_signal_saturation,
RenderBuffer* render_buffer, RenderBuffer* render_buffer,
std::vector<std::vector<float>>* capture) override; std::vector<std::vector<float>>* capture) override;
@ -120,7 +119,6 @@ void EchoRemoverImpl::GetMetrics(EchoControl::Metrics* metrics) const {
} }
void EchoRemoverImpl::ProcessCapture( void EchoRemoverImpl::ProcessCapture(
const rtc::Optional<size_t>& echo_path_delay_samples,
const EchoPathVariability& echo_path_variability, const EchoPathVariability& echo_path_variability,
bool capture_signal_saturation, bool capture_signal_saturation,
RenderBuffer* render_buffer, RenderBuffer* render_buffer,
@ -179,9 +177,8 @@ void EchoRemoverImpl::ProcessCapture(
// Update the AEC state information. // Update the AEC state information.
aec_state_.Update(subtractor_.FilterFrequencyResponse(), aec_state_.Update(subtractor_.FilterFrequencyResponse(),
subtractor_.FilterImpulseResponse(), subtractor_.FilterImpulseResponse(),
subtractor_.ConvergedFilter(), echo_path_delay_samples, subtractor_.ConvergedFilter(), *render_buffer, E2_main, Y2,
*render_buffer, E2_main, Y2, x0, subtractor_output.s_main, x0, subtractor_output.s_main, echo_leakage_detected_);
echo_leakage_detected_);
// Choose the linear output. // Choose the linear output.
output_selector_.FormLinearOutput(!aec_state_.TransparentMode(), e_main, y0); output_selector_.FormLinearOutput(!aec_state_.TransparentMode(), e_main, y0);
@ -238,9 +235,6 @@ void EchoRemoverImpl::ProcessCapture(
data_dumper_->DumpRaw( data_dumper_->DumpRaw(
"aec3_filter_delay", "aec3_filter_delay",
aec_state_.FilterDelay() ? *aec_state_.FilterDelay() : -1); aec_state_.FilterDelay() ? *aec_state_.FilterDelay() : -1);
data_dumper_->DumpRaw(
"aec3_external_delay",
aec_state_.ExternalDelay() ? *aec_state_.ExternalDelay() : -1);
data_dumper_->DumpRaw("aec3_capture_saturation", data_dumper_->DumpRaw("aec3_capture_saturation",
aec_state_.SaturatedCapture() ? 1 : 0); aec_state_.SaturatedCapture() ? 1 : 0);
} }

View File

@ -34,7 +34,6 @@ class EchoRemover {
// supplied render signal is assumed to be pre-aligned with the capture // supplied render signal is assumed to be pre-aligned with the capture
// signal. // signal.
virtual void ProcessCapture( virtual void ProcessCapture(
const rtc::Optional<size_t>& echo_path_delay_samples,
const EchoPathVariability& echo_path_variability, const EchoPathVariability& echo_path_variability,
bool capture_signal_saturation, bool capture_signal_saturation,
RenderBuffer* render_buffer, RenderBuffer* render_buffer,

View File

@ -60,14 +60,10 @@ TEST(EchoRemover, BasicApiCalls) {
k % 5 == 0 ? EchoPathVariability::DelayAdjustment::kNewDetectedDelay k % 5 == 0 ? EchoPathVariability::DelayAdjustment::kNewDetectedDelay
: EchoPathVariability::DelayAdjustment::kNone, : EchoPathVariability::DelayAdjustment::kNone,
false); false);
rtc::Optional<size_t> echo_path_delay_samples =
(k % 6 == 0 ? rtc::Optional<size_t>(k * 10)
: rtc::nullopt);
render_buffer->Insert(render); render_buffer->Insert(render);
render_buffer->PrepareCaptureProcessing(); render_buffer->PrepareCaptureProcessing();
remover->ProcessCapture(echo_path_delay_samples, echo_path_variability, remover->ProcessCapture(echo_path_variability, k % 2 == 0 ? true : false,
k % 2 == 0 ? true : false,
render_buffer->GetRenderBuffer(), &capture); render_buffer->GetRenderBuffer(), &capture);
} }
} }
@ -96,11 +92,10 @@ TEST(EchoRemover, WrongCaptureBlockSize) {
NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f)); NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f));
EchoPathVariability echo_path_variability( EchoPathVariability echo_path_variability(
false, EchoPathVariability::DelayAdjustment::kNone, false); false, EchoPathVariability::DelayAdjustment::kNone, false);
rtc::Optional<size_t> echo_path_delay_samples; EXPECT_DEATH(
EXPECT_DEATH(remover->ProcessCapture( remover->ProcessCapture(echo_path_variability, false,
echo_path_delay_samples, echo_path_variability, false, render_buffer->GetRenderBuffer(), &capture),
render_buffer->GetRenderBuffer(), &capture), "");
"");
} }
} }
@ -119,11 +114,10 @@ TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
std::vector<float>(kBlockSize, 0.f)); std::vector<float>(kBlockSize, 0.f));
EchoPathVariability echo_path_variability( EchoPathVariability echo_path_variability(
false, EchoPathVariability::DelayAdjustment::kNone, false); false, EchoPathVariability::DelayAdjustment::kNone, false);
rtc::Optional<size_t> echo_path_delay_samples; EXPECT_DEATH(
EXPECT_DEATH(remover->ProcessCapture( remover->ProcessCapture(echo_path_variability, false,
echo_path_delay_samples, echo_path_variability, false, render_buffer->GetRenderBuffer(), &capture),
render_buffer->GetRenderBuffer(), &capture), "");
"");
} }
} }
@ -135,10 +129,9 @@ TEST(EchoRemover, NullCapture) {
RenderDelayBuffer::Create(EchoCanceller3Config(), 3)); RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
EchoPathVariability echo_path_variability( EchoPathVariability echo_path_variability(
false, EchoPathVariability::DelayAdjustment::kNone, false); false, EchoPathVariability::DelayAdjustment::kNone, false);
rtc::Optional<size_t> echo_path_delay_samples;
EXPECT_DEATH( EXPECT_DEATH(
remover->ProcessCapture(echo_path_delay_samples, echo_path_variability, remover->ProcessCapture(echo_path_variability, false,
false, render_buffer->GetRenderBuffer(), nullptr), render_buffer->GetRenderBuffer(), nullptr),
""); "");
} }
@ -194,7 +187,7 @@ TEST(EchoRemover, BasicEchoRemoval) {
render_buffer->Insert(x); render_buffer->Insert(x);
render_buffer->PrepareCaptureProcessing(); render_buffer->PrepareCaptureProcessing();
remover->ProcessCapture(delay_samples, echo_path_variability, false, remover->ProcessCapture(echo_path_variability, false,
render_buffer->GetRenderBuffer(), &y); render_buffer->GetRenderBuffer(), &y);
if (k > kNumBlocksToProcess / 2) { if (k > kNumBlocksToProcess / 2) {

View File

@ -157,7 +157,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
aec_state.HandleEchoPathChange(EchoPathVariability( aec_state.HandleEchoPathChange(EchoPathVariability(
false, EchoPathVariability::DelayAdjustment::kNone, false)); false, EchoPathVariability::DelayAdjustment::kNone, false));
aec_state.Update(main_filter.FilterFrequencyResponse(), aec_state.Update(main_filter.FilterFrequencyResponse(),
main_filter.FilterImpulseResponse(), true, rtc::nullopt, main_filter.FilterImpulseResponse(), true,
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0],
s, false); s, false);
} }

View File

@ -26,9 +26,8 @@ class MockEchoRemover : public EchoRemover {
public: public:
virtual ~MockEchoRemover() = default; virtual ~MockEchoRemover() = default;
MOCK_METHOD5(ProcessCapture, MOCK_METHOD4(ProcessCapture,
void(const rtc::Optional<size_t>& echo_path_delay_samples, void(const EchoPathVariability& echo_path_variability,
const EchoPathVariability& echo_path_variability,
bool capture_signal_saturation, bool capture_signal_saturation,
RenderBuffer* render_buffer, RenderBuffer* render_buffer,
std::vector<std::vector<float>>* capture)); std::vector<std::vector<float>>* capture));

View File

@ -30,7 +30,6 @@ class MockRenderDelayController : public RenderDelayController {
GetDelay, GetDelay,
rtc::Optional<size_t>(const DownsampledRenderBuffer& render_buffer, rtc::Optional<size_t>(const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture)); rtc::ArrayView<const float> capture));
MOCK_CONST_METHOD0(AlignmentHeadroomSamples, rtc::Optional<size_t>());
}; };
} // namespace test } // namespace test

View File

@ -35,9 +35,6 @@ class RenderDelayControllerImpl final : public RenderDelayController {
void SetDelay(size_t render_delay) override; void SetDelay(size_t render_delay) override;
rtc::Optional<size_t> GetDelay(const DownsampledRenderBuffer& render_buffer, rtc::Optional<size_t> GetDelay(const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) override; rtc::ArrayView<const float> capture) override;
rtc::Optional<size_t> AlignmentHeadroomSamples() const override {
return headroom_samples_;
}
private: private:
static int instance_count_; static int instance_count_;
@ -45,7 +42,6 @@ class RenderDelayControllerImpl final : public RenderDelayController {
rtc::Optional<size_t> delay_; rtc::Optional<size_t> delay_;
EchoPathDelayEstimator delay_estimator_; EchoPathDelayEstimator delay_estimator_;
size_t align_call_counter_ = 0; size_t align_call_counter_ = 0;
rtc::Optional<size_t> headroom_samples_;
std::vector<float> delay_buf_; std::vector<float> delay_buf_;
int delay_buf_index_ = 0; int delay_buf_index_ = 0;
RenderDelayControllerMetrics metrics_; RenderDelayControllerMetrics metrics_;
@ -91,7 +87,6 @@ RenderDelayControllerImpl::~RenderDelayControllerImpl() = default;
void RenderDelayControllerImpl::Reset() { void RenderDelayControllerImpl::Reset() {
delay_ = rtc::nullopt; delay_ = rtc::nullopt;
align_call_counter_ = 0; align_call_counter_ = 0;
headroom_samples_ = rtc::nullopt;
std::fill(delay_buf_.begin(), delay_buf_.end(), 0.f); std::fill(delay_buf_.begin(), delay_buf_.end(), 0.f);
delay_estimator_.Reset(); delay_estimator_.Reset();
} }
@ -126,11 +121,6 @@ rtc::Optional<size_t> RenderDelayControllerImpl::GetDelay(
// Compute and set new render delay buffer delay. // Compute and set new render delay buffer delay.
if (align_call_counter_ > kNumBlocksPerSecond) { if (align_call_counter_ > kNumBlocksPerSecond) {
delay_ = ComputeNewBufferDelay(delay_, static_cast<int>(*delay_samples)); delay_ = ComputeNewBufferDelay(delay_, static_cast<int>(*delay_samples));
// Update render delay buffer headroom.
const int headroom =
static_cast<int>(*delay_samples) - *delay_ * kBlockSize;
RTC_DCHECK_LE(0, headroom);
headroom_samples_ = headroom;
} }
metrics_.Update(static_cast<int>(*delay_samples), delay_ ? *delay_ : 0); metrics_.Update(static_cast<int>(*delay_samples), delay_ ? *delay_ : 0);

View File

@ -38,9 +38,6 @@ class RenderDelayController {
virtual rtc::Optional<size_t> GetDelay( virtual rtc::Optional<size_t> GetDelay(
const DownsampledRenderBuffer& render_buffer, const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) = 0; rtc::ArrayView<const float> capture) = 0;
// Returns an approximate value for the headroom in the buffer alignment.
virtual rtc::Optional<size_t> AlignmentHeadroomSamples() const = 0;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -97,7 +97,6 @@ TEST(RenderDelayController, BasicApiCalls) {
render_delay_buffer->GetDownsampledRenderBuffer(), capture_block); render_delay_buffer->GetDownsampledRenderBuffer(), capture_block);
} }
EXPECT_TRUE(delay_blocks); EXPECT_TRUE(delay_blocks);
EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay_blocks); EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay_blocks);
} }
} }
@ -147,12 +146,6 @@ TEST(RenderDelayController, Alignment) {
kDelayHeadroomBlocks); kDelayHeadroomBlocks);
EXPECT_EQ(expected_delay_blocks, delay_blocks); EXPECT_EQ(expected_delay_blocks, delay_blocks);
const rtc::Optional<size_t> headroom_samples =
delay_controller->AlignmentHeadroomSamples();
ASSERT_TRUE(headroom_samples);
EXPECT_NEAR(delay_samples - *delay_blocks * kBlockSize,
*headroom_samples, 4);
} }
} }
} }
@ -197,10 +190,6 @@ TEST(RenderDelayController, NonCausalAlignment) {
} }
ASSERT_FALSE(delay_blocks); ASSERT_FALSE(delay_blocks);
const rtc::Optional<size_t> headroom_samples =
delay_controller->AlignmentHeadroomSamples();
ASSERT_FALSE(headroom_samples);
} }
} }
} }
@ -262,12 +251,6 @@ TEST(RenderDelayController, AlignmentWithJitter) {
ASSERT_TRUE(delay_blocks); ASSERT_TRUE(delay_blocks);
EXPECT_EQ(expected_delay_blocks, *delay_blocks); EXPECT_EQ(expected_delay_blocks, *delay_blocks);
const rtc::Optional<size_t> headroom_samples =
delay_controller->AlignmentHeadroomSamples();
ASSERT_TRUE(headroom_samples);
EXPECT_NEAR(delay_samples - *delay_blocks * kBlockSize,
*headroom_samples, 4);
} }
} }
} }
@ -292,7 +275,6 @@ TEST(RenderDelayController, InitialHeadroom) {
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create( RenderDelayController::Create(
config, RenderDelayBuffer::DelayEstimatorOffset(config), rate)); config, RenderDelayBuffer::DelayEstimatorOffset(config), rate));
EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
} }
} }
} }

View File

@ -108,17 +108,10 @@ void ResidualEchoEstimator::Estimate(
R2->fill((*std::max_element(R2->begin(), R2->end())) * 100.f); R2->fill((*std::max_element(R2->begin(), R2->end())) * 100.f);
} }
} else { } else {
const rtc::Optional<size_t> delay =
aec_state.ExternalDelay()
? (aec_state.FilterDelay() ? aec_state.FilterDelay()
: aec_state.ExternalDelay())
: rtc::Optional<size_t>();
// Estimate the echo generating signal power. // Estimate the echo generating signal power.
std::array<float, kFftLengthBy2Plus1> X2; std::array<float, kFftLengthBy2Plus1> X2;
if (aec_state.ExternalDelay() && aec_state.FilterDelay()) { if (aec_state.FilterDelay()) {
RTC_DCHECK(delay); const int delay_use = static_cast<int>(*aec_state.FilterDelay());
const int delay_use = static_cast<int>(*delay);
// Computes the spectral power over the blocks surrounding the delay. // Computes the spectral power over the blocks surrounding the delay.
constexpr int kKnownDelayRenderWindowSize = 5; constexpr int kKnownDelayRenderWindowSize = 5;
@ -147,12 +140,9 @@ void ResidualEchoEstimator::Estimate(
config_.ep_strength.bounded_erl, config_.ep_strength.bounded_erl,
aec_state.TransparentMode(), X2, Y2, R2); aec_state.TransparentMode(), X2, Y2, R2);
if (aec_state.ExternalDelay() && aec_state.FilterDelay() && if (aec_state.FilterDelay() && aec_state.SaturatedEcho()) {
aec_state.SaturatedEcho()) {
AddEchoReverb(*R2, aec_state.SaturatedEcho(), AddEchoReverb(*R2, aec_state.SaturatedEcho(),
std::min(static_cast<size_t>(config_.filter.length_blocks), config_.filter.length_blocks, aec_state.ReverbDecay(), R2);
delay.value_or(config_.filter.length_blocks)),
aec_state.ReverbDecay(), R2);
} }
} }

View File

@ -91,7 +91,7 @@ TEST(ResidualEchoEstimator, DISABLED_BasicTest) {
render_delay_buffer->PrepareCaptureProcessing(); render_delay_buffer->PrepareCaptureProcessing();
aec_state.HandleEchoPathChange(echo_path_variability); aec_state.HandleEchoPathChange(echo_path_variability);
aec_state.Update(H2, h, true, 2, *render_delay_buffer->GetRenderBuffer(), aec_state.Update(H2, h, true, *render_delay_buffer->GetRenderBuffer(),
E2_main, Y2, x[0], s, false); E2_main, Y2, x[0], s, false);
estimator.Estimate(aec_state, *render_delay_buffer->GetRenderBuffer(), estimator.Estimate(aec_state, *render_delay_buffer->GetRenderBuffer(),

View File

@ -84,7 +84,6 @@ float RunSubtractorTest(int num_blocks_to_process,
aec_state.Update(subtractor.FilterFrequencyResponse(), aec_state.Update(subtractor.FilterFrequencyResponse(),
subtractor.FilterImpulseResponse(), subtractor.FilterImpulseResponse(),
subtractor.ConvergedFilter(), subtractor.ConvergedFilter(),
rtc::Optional<size_t>(delay_samples / kBlockSize),
*render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0], *render_delay_buffer->GetRenderBuffer(), E2_main, Y2, x[0],
output.s_main, false); output.s_main, false);
} }

View File

@ -71,8 +71,8 @@ TEST(SuppressionGain, BasicGainComputation) {
s.fill(10.f); s.fill(10.f);
aec_state.Update( aec_state.Update(
subtractor.FilterFrequencyResponse(), subtractor.FilterImpulseResponse(), subtractor.FilterFrequencyResponse(), subtractor.FilterImpulseResponse(),
subtractor.ConvergedFilter(), 10, *render_delay_buffer->GetRenderBuffer(), subtractor.ConvergedFilter(), *render_delay_buffer->GetRenderBuffer(), E2,
E2, Y2, x[0], s, false); Y2, x[0], s, false);
suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x, &high_bands_gain, suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x, &high_bands_gain,
&g); &g);
std::for_each(g.begin(), g.end(), [](float a) { EXPECT_FLOAT_EQ(0.f, a); }); std::for_each(g.begin(), g.end(), [](float a) { EXPECT_FLOAT_EQ(0.f, a); });
@ -87,14 +87,14 @@ TEST(SuppressionGain, BasicGainComputation) {
for (int k = 0; k <= kNumBlocksPerSecond / 5 + 1; ++k) { for (int k = 0; k <= kNumBlocksPerSecond / 5 + 1; ++k) {
aec_state.Update( aec_state.Update(
subtractor.FilterFrequencyResponse(), subtractor.FilterFrequencyResponse(),
subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(), 10, subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(),
*render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false); *render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false);
} }
for (int k = 0; k < 100; ++k) { for (int k = 0; k < 100; ++k) {
aec_state.Update( aec_state.Update(
subtractor.FilterFrequencyResponse(), subtractor.FilterFrequencyResponse(),
subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(), 10, subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(),
*render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false); *render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false);
suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x, suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x,
&high_bands_gain, &g); &high_bands_gain, &g);
@ -110,7 +110,7 @@ TEST(SuppressionGain, BasicGainComputation) {
for (int k = 0; k < 100; ++k) { for (int k = 0; k < 100; ++k) {
aec_state.Update( aec_state.Update(
subtractor.FilterFrequencyResponse(), subtractor.FilterFrequencyResponse(),
subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(), 10, subtractor.FilterImpulseResponse(), subtractor.ConvergedFilter(),
*render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false); *render_delay_buffer->GetRenderBuffer(), E2, Y2, x[0], s, false);
suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x, suppression_gain.GetGain(E2, R2, N2, analyzer, aec_state, x,
&high_bands_gain, &g); &high_bands_gain, &g);