Change echo detector to scoped_refptr

The echo detector is currently stored as a unique_ptr, but when injecting an echo detector, a scoped_refptr makes more sense since the ownership will be shared.

Bug: webrtc:8732
Change-Id: I2180014acb84f1cd5c361864a444b7b6574520f5
Reviewed-on: https://webrtc-review.googlesource.com/83325
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23610}
This commit is contained in:
Ivo Creusen
2018-06-14 11:02:03 +02:00
committed by Commit Bot
parent 4e952a3f44
commit d1f970dc43
5 changed files with 56 additions and 50 deletions

View File

@ -285,7 +285,7 @@ struct AudioProcessingImpl::ApmPrivateSubmodules {
ApmPrivateSubmodules(NonlinearBeamformer* beamformer, ApmPrivateSubmodules(NonlinearBeamformer* beamformer,
std::unique_ptr<CustomProcessing> capture_post_processor, std::unique_ptr<CustomProcessing> capture_post_processor,
std::unique_ptr<CustomProcessing> render_pre_processor, std::unique_ptr<CustomProcessing> render_pre_processor,
std::unique_ptr<EchoDetector> echo_detector) rtc::scoped_refptr<EchoDetector> echo_detector)
: beamformer(beamformer), : beamformer(beamformer),
echo_detector(std::move(echo_detector)), echo_detector(std::move(echo_detector)),
capture_post_processor(std::move(capture_post_processor)), capture_post_processor(std::move(capture_post_processor)),
@ -295,7 +295,7 @@ struct AudioProcessingImpl::ApmPrivateSubmodules {
std::unique_ptr<AgcManagerDirect> agc_manager; std::unique_ptr<AgcManagerDirect> agc_manager;
std::unique_ptr<GainController2> gain_controller2; std::unique_ptr<GainController2> gain_controller2;
std::unique_ptr<LowCutFilter> low_cut_filter; std::unique_ptr<LowCutFilter> low_cut_filter;
std::unique_ptr<EchoDetector> echo_detector; rtc::scoped_refptr<EchoDetector> echo_detector;
std::unique_ptr<EchoControl> echo_controller; std::unique_ptr<EchoControl> echo_controller;
std::unique_ptr<CustomProcessing> capture_post_processor; std::unique_ptr<CustomProcessing> capture_post_processor;
std::unique_ptr<CustomProcessing> render_pre_processor; std::unique_ptr<CustomProcessing> render_pre_processor;
@ -330,7 +330,7 @@ AudioProcessingBuilder& AudioProcessingBuilder::SetNonlinearBeamformer(
} }
AudioProcessingBuilder& AudioProcessingBuilder::SetEchoDetector( AudioProcessingBuilder& AudioProcessingBuilder::SetEchoDetector(
std::unique_ptr<EchoDetector> echo_detector) { rtc::scoped_refptr<EchoDetector> echo_detector) {
echo_detector_ = std::move(echo_detector); echo_detector_ = std::move(echo_detector);
return *this; return *this;
} }
@ -363,7 +363,7 @@ AudioProcessingImpl::AudioProcessingImpl(
std::unique_ptr<CustomProcessing> capture_post_processor, std::unique_ptr<CustomProcessing> capture_post_processor,
std::unique_ptr<CustomProcessing> render_pre_processor, std::unique_ptr<CustomProcessing> render_pre_processor,
std::unique_ptr<EchoControlFactory> echo_control_factory, std::unique_ptr<EchoControlFactory> echo_control_factory,
std::unique_ptr<EchoDetector> echo_detector, rtc::scoped_refptr<EchoDetector> echo_detector,
NonlinearBeamformer* beamformer) NonlinearBeamformer* beamformer)
: data_dumper_( : data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
@ -422,7 +422,8 @@ AudioProcessingImpl::AudioProcessingImpl(
// If no echo detector is injected, use the ResidualEchoDetector. // If no echo detector is injected, use the ResidualEchoDetector.
if (!private_submodules_->echo_detector) { if (!private_submodules_->echo_detector) {
private_submodules_->echo_detector.reset(new ResidualEchoDetector()); private_submodules_->echo_detector =
new rtc::RefCountedObject<ResidualEchoDetector>();
} }
// TODO(alessiob): Move the injected gain controller once injection is // TODO(alessiob): Move the injected gain controller once injection is

View File

@ -44,7 +44,7 @@ class AudioProcessingImpl : public AudioProcessing {
std::unique_ptr<CustomProcessing> capture_post_processor, std::unique_ptr<CustomProcessing> capture_post_processor,
std::unique_ptr<CustomProcessing> render_pre_processor, std::unique_ptr<CustomProcessing> render_pre_processor,
std::unique_ptr<EchoControlFactory> echo_control_factory, std::unique_ptr<EchoControlFactory> echo_control_factory,
std::unique_ptr<EchoDetector> echo_detector, rtc::scoped_refptr<EchoDetector> echo_detector,
NonlinearBeamformer* beamformer); NonlinearBeamformer* beamformer);
~AudioProcessingImpl() override; ~AudioProcessingImpl() override;
int Initialize() override; int Initialize() override;

View File

@ -678,7 +678,7 @@ class AudioProcessingBuilder {
std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer); std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer);
// The AudioProcessingBuilder takes ownership of the echo_detector. // The AudioProcessingBuilder takes ownership of the echo_detector.
AudioProcessingBuilder& SetEchoDetector( AudioProcessingBuilder& SetEchoDetector(
std::unique_ptr<EchoDetector> echo_detector); rtc::scoped_refptr<EchoDetector> echo_detector);
// This creates an APM instance using the previously set components. Calling // This creates an APM instance using the previously set components. Calling
// the Create function resets the AudioProcessingBuilder to its initial state. // the Create function resets the AudioProcessingBuilder to its initial state.
AudioProcessing* Create(); AudioProcessing* Create();
@ -689,7 +689,7 @@ class AudioProcessingBuilder {
std::unique_ptr<CustomProcessing> capture_post_processing_; std::unique_ptr<CustomProcessing> capture_post_processing_;
std::unique_ptr<CustomProcessing> render_pre_processing_; std::unique_ptr<CustomProcessing> render_pre_processing_;
std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer_; std::unique_ptr<NonlinearBeamformer> nonlinear_beamformer_;
std::unique_ptr<EchoDetector> echo_detector_; rtc::scoped_refptr<EchoDetector> echo_detector_;
RTC_DISALLOW_COPY_AND_ASSIGN(AudioProcessingBuilder); RTC_DISALLOW_COPY_AND_ASSIGN(AudioProcessingBuilder);
}; };
@ -1135,7 +1135,7 @@ class CustomProcessing {
}; };
// Interface for an echo detector submodule. // Interface for an echo detector submodule.
class EchoDetector { class EchoDetector : public rtc::RefCountInterface {
public: public:
// (Re-)Initializes the submodule. // (Re-)Initializes the submodule.
virtual void Initialize(int capture_sample_rate_hz, virtual void Initialize(int capture_sample_rate_hz,
@ -1161,8 +1161,6 @@ class EchoDetector {
// Collect current metrics from the echo detector. // Collect current metrics from the echo detector.
virtual Metrics GetMetrics() const = 0; virtual Metrics GetMetrics() const = 0;
virtual ~EchoDetector() {}
}; };
// The voice activity detection (VAD) component analyzes the stream to // The voice activity detection (VAD) component analyzes the stream to

View File

@ -11,13 +11,15 @@
#include <vector> #include <vector>
#include "modules/audio_processing/residual_echo_detector.h" #include "modules/audio_processing/residual_echo_detector.h"
#include "rtc_base/refcountedobject.h"
#include "test/gtest.h" #include "test/gtest.h"
namespace webrtc { namespace webrtc {
TEST(ResidualEchoDetectorTests, Echo) { TEST(ResidualEchoDetectorTests, Echo) {
ResidualEchoDetector echo_detector; rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
echo_detector.SetReliabilityForTest(1.0f); new rtc::RefCountedObject<ResidualEchoDetector>();
echo_detector->SetReliabilityForTest(1.0f);
std::vector<float> ones(160, 1.f); std::vector<float> ones(160, 1.f);
std::vector<float> zeros(160, 0.f); std::vector<float> zeros(160, 0.f);
@ -26,24 +28,25 @@ TEST(ResidualEchoDetectorTests, Echo) {
// frame interval. // frame interval.
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
if (i % 20 == 0) { if (i % 20 == 0) {
echo_detector.AnalyzeRenderAudio(ones); echo_detector->AnalyzeRenderAudio(ones);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} else if (i % 20 == 10) { } else if (i % 20 == 10) {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(ones); echo_detector->AnalyzeCaptureAudio(ones);
} else { } else {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} }
} }
// We expect to detect echo with near certain likelihood. // We expect to detect echo with near certain likelihood.
auto ed_metrics = echo_detector.GetMetrics(); auto ed_metrics = echo_detector->GetMetrics();
EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f); EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f);
} }
TEST(ResidualEchoDetectorTests, NoEcho) { TEST(ResidualEchoDetectorTests, NoEcho) {
ResidualEchoDetector echo_detector; rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
echo_detector.SetReliabilityForTest(1.0f); new rtc::RefCountedObject<ResidualEchoDetector>();
echo_detector->SetReliabilityForTest(1.0f);
std::vector<float> ones(160, 1.f); std::vector<float> ones(160, 1.f);
std::vector<float> zeros(160, 0.f); std::vector<float> zeros(160, 0.f);
@ -51,20 +54,21 @@ TEST(ResidualEchoDetectorTests, NoEcho) {
// detected. // detected.
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
if (i % 20 == 0) { if (i % 20 == 0) {
echo_detector.AnalyzeRenderAudio(ones); echo_detector->AnalyzeRenderAudio(ones);
} else { } else {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
} }
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} }
// We expect to not detect any echo. // We expect to not detect any echo.
auto ed_metrics = echo_detector.GetMetrics(); auto ed_metrics = echo_detector->GetMetrics();
EXPECT_NEAR(0.f, ed_metrics.echo_likelihood, 0.01f); EXPECT_NEAR(0.f, ed_metrics.echo_likelihood, 0.01f);
} }
TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) { TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) {
ResidualEchoDetector echo_detector; rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
echo_detector.SetReliabilityForTest(1.0f); new rtc::RefCountedObject<ResidualEchoDetector>();
echo_detector->SetReliabilityForTest(1.0f);
std::vector<float> ones(160, 1.f); std::vector<float> ones(160, 1.f);
std::vector<float> zeros(160, 0.f); std::vector<float> zeros(160, 0.f);
@ -74,18 +78,18 @@ TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) {
// the render side producing data slightly faster. // the render side producing data slightly faster.
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
if (i % 20 == 0) { if (i % 20 == 0) {
echo_detector.AnalyzeRenderAudio(ones); echo_detector->AnalyzeRenderAudio(ones);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} else if (i % 20 == 10) { } else if (i % 20 == 10) {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(ones); echo_detector->AnalyzeCaptureAudio(ones);
} else { } else {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} }
if (i % 100 == 0) { if (i % 100 == 0) {
// This is causing the simulated clock drift. // This is causing the simulated clock drift.
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
} }
} }
// We expect to detect echo with high likelihood. Clock drift is harder to // We expect to detect echo with high likelihood. Clock drift is harder to
@ -94,13 +98,14 @@ TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) {
// A growing buffer can be caused by jitter or clock drift and it's not // A growing buffer can be caused by jitter or clock drift and it's not
// possible to make this decision right away. For this reason we only expect // possible to make this decision right away. For this reason we only expect
// an echo likelihood of 75% in this test. // an echo likelihood of 75% in this test.
auto ed_metrics = echo_detector.GetMetrics(); auto ed_metrics = echo_detector->GetMetrics();
EXPECT_GT(ed_metrics.echo_likelihood, 0.75f); EXPECT_GT(ed_metrics.echo_likelihood, 0.75f);
} }
TEST(ResidualEchoDetectorTests, EchoWithCaptureClockDrift) { TEST(ResidualEchoDetectorTests, EchoWithCaptureClockDrift) {
ResidualEchoDetector echo_detector; rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
echo_detector.SetReliabilityForTest(1.0f); new rtc::RefCountedObject<ResidualEchoDetector>();
echo_detector->SetReliabilityForTest(1.0f);
std::vector<float> ones(160, 1.f); std::vector<float> ones(160, 1.f);
std::vector<float> zeros(160, 0.f); std::vector<float> zeros(160, 0.f);
@ -110,22 +115,22 @@ TEST(ResidualEchoDetectorTests, EchoWithCaptureClockDrift) {
// the capture side producing data slightly faster. // the capture side producing data slightly faster.
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
if (i % 20 == 0) { if (i % 20 == 0) {
echo_detector.AnalyzeRenderAudio(ones); echo_detector->AnalyzeRenderAudio(ones);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} else if (i % 20 == 10) { } else if (i % 20 == 10) {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(ones); echo_detector->AnalyzeCaptureAudio(ones);
} else { } else {
echo_detector.AnalyzeRenderAudio(zeros); echo_detector->AnalyzeRenderAudio(zeros);
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} }
if (i % 100 == 0) { if (i % 100 == 0) {
// This is causing the simulated clock drift. // This is causing the simulated clock drift.
echo_detector.AnalyzeCaptureAudio(zeros); echo_detector->AnalyzeCaptureAudio(zeros);
} }
} }
// We expect to detect echo with near certain likelihood. // We expect to detect echo with near certain likelihood.
auto ed_metrics = echo_detector.GetMetrics(); auto ed_metrics = echo_detector->GetMetrics();
EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f); EXPECT_NEAR(1.f, ed_metrics.echo_likelihood, 0.01f);
} }

View File

@ -17,6 +17,7 @@
#include "modules/audio_processing/residual_echo_detector.h" #include "modules/audio_processing/residual_echo_detector.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/refcountedobject.h"
namespace webrtc { namespace webrtc {
@ -42,10 +43,11 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
read_idx += 2; read_idx += 2;
std::bitset<16> call_order(call_order_int); std::bitset<16> call_order(call_order_int);
ResidualEchoDetector echo_detector; rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
new rtc::RefCountedObject<ResidualEchoDetector>();
std::vector<float> input(1); std::vector<float> input(1);
// Call AnalyzeCaptureAudio once to prevent the flushing of the buffer. // Call AnalyzeCaptureAudio once to prevent the flushing of the buffer.
echo_detector.AnalyzeCaptureAudio(input); echo_detector->AnalyzeCaptureAudio(input);
for (size_t i = 0; i < 2 * kNrOfUpdates; ++i) { for (size_t i = 0; i < 2 * kNrOfUpdates; ++i) {
// Convert 4 input bytes to a float. // Convert 4 input bytes to a float.
RTC_DCHECK_LE(read_idx + sizeof(float), size); RTC_DCHECK_LE(read_idx + sizeof(float), size);
@ -56,9 +58,9 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
continue; continue;
} }
if (call_order[i]) { if (call_order[i]) {
echo_detector.AnalyzeRenderAudio(input); echo_detector->AnalyzeRenderAudio(input);
} else { } else {
echo_detector.AnalyzeCaptureAudio(input); echo_detector->AnalyzeCaptureAudio(input);
} }
} }
} }