From 87d1a787547b26fd564b66426116c2252aa8233d Mon Sep 17 00:00:00 2001 From: ivoc Date: Mon, 14 Nov 2016 07:55:03 -0800 Subject: [PATCH] Add support to audioproc_f for running the residual echo detector and producing an echo likelihood graph. This adds two command-line flags to audioproc_f: -red and -red_graph, which can be used to enable/disable the RED, and to set the output path for the graph. The graph is generated as a python script that depends on matplotlib and numpy to display the graph. BUG=webrtc:6525 Review-Url: https://codereview.webrtc.org/2486763002 Cr-Commit-Position: refs/heads/master@{#15069} --- .../audio_processing/audio_processing_impl.cc | 2 + .../test/aec_dump_based_simulator.cc | 4 ++ .../test/audio_processing_simulator.cc | 43 ++++++++++++++++++- .../test/audio_processing_simulator.h | 4 ++ .../audio_processing/test/audioproc_float.cc | 7 +++ 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc index f63cb206b5..90b1f2d631 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.cc +++ b/webrtc/modules/audio_processing/audio_processing_impl.cc @@ -1496,6 +1496,8 @@ AudioProcessing::AudioProcessingStatistics AudioProcessingImpl::GetStatistics() metrics.echo_return_loss_enhancement); stats.residual_echo_return_loss.Set(metrics.residual_echo_return_loss); } + stats.residual_echo_likelihood = + private_submodules_->residual_echo_detector->echo_likelihood(); public_submodules_->echo_cancellation->GetDelayMetrics( &stats.delay_median, &stats.delay_standard_deviation, &stats.fraction_poor_delays); diff --git a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc index 266e649181..a5f248502f 100644 --- a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc +++ b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc @@ -450,6 +450,10 @@ void AecDumpBasedSimulator::HandleMessage( apm_config.level_controller.enabled = *settings_.use_lc; } + if (settings_.use_red) { + apm_config.residual_echo_detector.enabled = *settings_.use_red; + } + ap_->ApplyConfig(apm_config); ap_->SetExtraOptions(config); } diff --git a/webrtc/modules/audio_processing/test/audio_processing_simulator.cc b/webrtc/modules/audio_processing/test/audio_processing_simulator.cc index 778b347091..fbf1937097 100644 --- a/webrtc/modules/audio_processing/test/audio_processing_simulator.cc +++ b/webrtc/modules/audio_processing/test/audio_processing_simulator.cc @@ -16,6 +16,7 @@ #include #include +#include "webrtc/base/checks.h" #include "webrtc/base/stringutils.h" #include "webrtc/common_audio/include/audio_util.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" @@ -42,6 +43,22 @@ std::string GetIndexedOutputWavFilename(const std::string& wav_name, return ss.str(); } +void WriteEchoLikelihoodGraphFileHeader(std::ofstream* output_file) { + (*output_file) << "import numpy as np" << std::endl + << "import matplotlib.pyplot as plt" << std::endl + << "y = np.array(["; +} + +void WriteEchoLikelihoodGraphFileFooter(std::ofstream* output_file) { + (*output_file) << "])" << std::endl + << "x = np.arange(len(y))*.01" << std::endl + << "plt.plot(x, y)" << std::endl + << "plt.ylabel('Echo likelihood')" << std::endl + << "plt.xlabel('Time (s)')" << std::endl + << "plt.ylim([0,1])" << std::endl + << "plt.show()" << std::endl; +} + } // namespace SimulationSettings::SimulationSettings() = default; @@ -61,9 +78,22 @@ void CopyToAudioFrame(const ChannelBuffer& src, AudioFrame* dest) { AudioProcessingSimulator::AudioProcessingSimulator( const SimulationSettings& settings) - : settings_(settings) {} + : settings_(settings) { + if (settings_.red_graph_output_filename && + settings_.red_graph_output_filename->size() > 0) { + residual_echo_likelihood_graph_writer_.open( + *settings_.red_graph_output_filename); + RTC_CHECK(residual_echo_likelihood_graph_writer_.is_open()); + WriteEchoLikelihoodGraphFileHeader(&residual_echo_likelihood_graph_writer_); + } +} -AudioProcessingSimulator::~AudioProcessingSimulator() = default; +AudioProcessingSimulator::~AudioProcessingSimulator() { + if (residual_echo_likelihood_graph_writer_.is_open()) { + WriteEchoLikelihoodGraphFileFooter(&residual_echo_likelihood_graph_writer_); + residual_echo_likelihood_graph_writer_.close(); + } +} AudioProcessingSimulator::ScopedTimer::~ScopedTimer() { int64_t interval = rtc::TimeNanos() - start_time_; @@ -90,6 +120,12 @@ void AudioProcessingSimulator::ProcessStream(bool fixed_interface) { buffer_writer_->Write(*out_buf_); } + if (residual_echo_likelihood_graph_writer_.is_open()) { + auto stats = ap_->GetStatistics(); + residual_echo_likelihood_graph_writer_ << stats.residual_echo_likelihood + << ", "; + } + ++num_process_stream_calls_; } @@ -245,6 +281,9 @@ void AudioProcessingSimulator::CreateAudioProcessor() { !settings_.use_extended_filter || *settings_.use_extended_filter)); config.Set(new DelayAgnostic(!settings_.use_delay_agnostic || *settings_.use_delay_agnostic)); + if (settings_.use_red) { + apm_config.residual_echo_detector.enabled = *settings_.use_red; + } ap_.reset(AudioProcessing::Create(config)); RTC_CHECK(ap_); diff --git a/webrtc/modules/audio_processing/test/audio_processing_simulator.h b/webrtc/modules/audio_processing/test/audio_processing_simulator.h index d1def43b35..832ab10338 100644 --- a/webrtc/modules/audio_processing/test/audio_processing_simulator.h +++ b/webrtc/modules/audio_processing/test/audio_processing_simulator.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_ #include +#include #include #include #include @@ -45,6 +46,8 @@ struct SimulationSettings { rtc::Optional reverse_input_filename; rtc::Optional use_aec; rtc::Optional use_aecm; + rtc::Optional use_red; // Residual Echo Detector. + rtc::Optional red_graph_output_filename; rtc::Optional use_agc; rtc::Optional use_hpf; rtc::Optional use_ns; @@ -168,6 +171,7 @@ class AudioProcessingSimulator { std::unique_ptr buffer_writer_; std::unique_ptr reverse_buffer_writer_; TickIntervalStats proc_time_; + std::ofstream residual_echo_likelihood_graph_writer_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioProcessingSimulator); }; diff --git a/webrtc/modules/audio_processing/test/audioproc_float.cc b/webrtc/modules/audio_processing/test/audioproc_float.cc index 41d6dd1e18..201d0fd5d1 100644 --- a/webrtc/modules/audio_processing/test/audioproc_float.cc +++ b/webrtc/modules/audio_processing/test/audioproc_float.cc @@ -70,6 +70,10 @@ DEFINE_int32(aec, DEFINE_int32(aecm, kParameterNotSpecifiedValue, "Activate (1) or deactivate(0) the mobile echo controller"); +DEFINE_int32(red, + kParameterNotSpecifiedValue, + "Activate (1) or deactivate (0) the residual echo detector"); +DEFINE_string(red_graph, "", "Output filename for graph of echo likelihood"); DEFINE_int32(agc, kParameterNotSpecifiedValue, "Activate (1) or deactivate(0) the AGC"); @@ -196,6 +200,7 @@ SimulationSettings CreateSettings() { settings.use_agc = rtc::Optional(true); settings.use_aec = rtc::Optional(true); settings.use_aecm = rtc::Optional(false); + settings.use_red = rtc::Optional(false); } SetSettingIfSpecified(FLAGS_dump_input, &settings.aec_dump_input_filename); SetSettingIfSpecified(FLAGS_dump_output, &settings.aec_dump_output_filename); @@ -215,6 +220,8 @@ SimulationSettings CreateSettings() { settings.target_angle_degrees = FLAGS_target_angle_degrees; SetSettingIfFlagSet(FLAGS_aec, &settings.use_aec); SetSettingIfFlagSet(FLAGS_aecm, &settings.use_aecm); + SetSettingIfFlagSet(FLAGS_red, &settings.use_red); + SetSettingIfSpecified(FLAGS_red_graph, &settings.red_graph_output_filename); SetSettingIfFlagSet(FLAGS_agc, &settings.use_agc); SetSettingIfFlagSet(FLAGS_hpf, &settings.use_hpf); SetSettingIfFlagSet(FLAGS_ns, &settings.use_ns);