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:
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user