From 13b96ba90f72164134019cbfc07d4a47cf1fd091 Mon Sep 17 00:00:00 2001 From: Minyue Date: Sat, 3 Oct 2015 00:39:14 +0200 Subject: [PATCH] Adding APM configuration in AEC dump. The AEC dump was not self-contented enough in the sense that APM configuration is missing, and therefore, given an AEC dump, it is sometimes not clear how to reproduce problems. This CL tries to address the problem. Note that this cannot guarantee a perfect reproduction in all cases. Dumping from the middle of a call makes the initial states unknown and thus may make the result non-reproducible. BUG= TEST= 1. new dump in Chromium and unpack 2. unpack old dump R=andrew@webrtc.org, peah@webrtc.org Review URL: https://codereview.webrtc.org/1348903004 . Cr-Commit-Position: refs/heads/master@{#10155} --- .../audio_processing/audio_processing_impl.cc | 61 +++++++++++++++---- .../audio_processing/audio_processing_impl.h | 9 +++ webrtc/modules/audio_processing/debug.proto | 33 ++++++++++ .../echo_cancellation_impl.cc | 8 +++ .../audio_processing/echo_cancellation_impl.h | 7 ++- .../echo_control_mobile_impl.h | 4 +- .../audio_processing/gain_control_impl.h | 4 +- .../audio_processing/noise_suppression_impl.h | 2 +- .../modules/audio_processing/test/unpack.cc | 34 ++++++++++- 9 files changed, 143 insertions(+), 19 deletions(-) diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc index 0de6bf0396..f3ee0a399d 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.cc +++ b/webrtc/modules/audio_processing/audio_processing_impl.cc @@ -539,6 +539,8 @@ int AudioProcessingImpl::ProcessStream(const float* const* src, #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP if (debug_file_->Open()) { + RETURN_ON_ERR(WriteConfigMessage(false)); + event_msg_->set_type(audioproc::Event::STREAM); audioproc::Stream* msg = event_msg_->mutable_stream(); const size_t channel_size = @@ -920,10 +922,8 @@ int AudioProcessingImpl::StartDebugRecording( return kFileError; } - int err = WriteInitMessage(); - if (err != kNoError) { - return err; - } + RETURN_ON_ERR(WriteConfigMessage(true)); + RETURN_ON_ERR(WriteInitMessage()); return kNoError; #else return kUnsupportedFunctionError; @@ -949,10 +949,8 @@ int AudioProcessingImpl::StartDebugRecording(FILE* handle) { return kFileError; } - int err = WriteInitMessage(); - if (err != kNoError) { - return err; - } + RETURN_ON_ERR(WriteConfigMessage(true)); + RETURN_ON_ERR(WriteInitMessage()); return kNoError; #else return kUnsupportedFunctionError; @@ -1222,11 +1220,52 @@ int AudioProcessingImpl::WriteInitMessage() { msg->set_output_sample_rate(api_format_.output_stream().sample_rate_hz()); // TODO(ekmeyerson): Add reverse output fields to event_msg_. - int err = WriteMessageToDebugFile(); - if (err != kNoError) { - return err; + RETURN_ON_ERR(WriteMessageToDebugFile()); + return kNoError; +} + +int AudioProcessingImpl::WriteConfigMessage(bool forced) { + audioproc::Config config; + + config.set_aec_enabled(echo_cancellation_->is_enabled()); + config.set_aec_delay_agnostic_enabled( + echo_cancellation_->is_delay_agnostic_enabled()); + config.set_aec_drift_compensation_enabled( + echo_cancellation_->is_drift_compensation_enabled()); + config.set_aec_extended_filter_enabled( + echo_cancellation_->is_extended_filter_enabled()); + config.set_aec_suppression_level( + static_cast(echo_cancellation_->suppression_level())); + + config.set_aecm_enabled(echo_control_mobile_->is_enabled()); + config.set_aecm_comfort_noise_enabled( + echo_control_mobile_->is_comfort_noise_enabled()); + config.set_aecm_routing_mode( + static_cast(echo_control_mobile_->routing_mode())); + + config.set_agc_enabled(gain_control_->is_enabled()); + config.set_agc_mode(static_cast(gain_control_->mode())); + config.set_agc_limiter_enabled(gain_control_->is_limiter_enabled()); + config.set_noise_robust_agc_enabled(use_new_agc_); + + config.set_hpf_enabled(high_pass_filter_->is_enabled()); + + config.set_ns_enabled(noise_suppression_->is_enabled()); + config.set_ns_level(static_cast(noise_suppression_->level())); + + config.set_transient_suppression_enabled(transient_suppressor_enabled_); + + std::string serialized_config = config.SerializeAsString(); + if (!forced && last_serialized_config_ == serialized_config) { + return kNoError; } + last_serialized_config_ = serialized_config; + + event_msg_->set_type(audioproc::Event::CONFIG); + event_msg_->mutable_config()->CopyFrom(config); + + RETURN_ON_ERR(WriteMessageToDebugFile()); return kNoError; } #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP diff --git a/webrtc/modules/audio_processing/audio_processing_impl.h b/webrtc/modules/audio_processing/audio_processing_impl.h index eeab34f874..bf29bf3633 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.h +++ b/webrtc/modules/audio_processing/audio_processing_impl.h @@ -162,9 +162,18 @@ class AudioProcessingImpl : public AudioProcessing { // out into a separate class with an "enabled" and "disabled" implementation. int WriteMessageToDebugFile(); int WriteInitMessage(); + + // Writes Config message. If not |forced|, only writes the current config if + // it is different from the last saved one; if |forced|, writes the config + // regardless of the last saved. + int WriteConfigMessage(bool forced); + rtc::scoped_ptr debug_file_; rtc::scoped_ptr event_msg_; // Protobuf message. std::string event_str_; // Memory for protobuf serialization. + + // Serialized string of last saved APM configuration. + std::string last_serialized_config_; #endif // Format of processing streams at input/output call sites. diff --git a/webrtc/modules/audio_processing/debug.proto b/webrtc/modules/audio_processing/debug.proto index dce2f79209..227271298c 100644 --- a/webrtc/modules/audio_processing/debug.proto +++ b/webrtc/modules/audio_processing/debug.proto @@ -2,6 +2,8 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; package webrtc.audioproc; +// Contains the format of input/output/reverse audio. An Init message is added +// when any of the fields are changed. message Init { optional int32 sample_rate = 1; optional int32 device_sample_rate = 2 [deprecated=true]; @@ -39,11 +41,41 @@ message Stream { repeated bytes output_channel = 8; } +// Contains the configurations of various APM component. A Config message is +// added when any of the fields are changed. +message Config { + // Next field number 17. + // Acoustic echo canceler. + optional bool aec_enabled = 1; + optional bool aec_delay_agnostic_enabled = 2; + optional bool aec_drift_compensation_enabled = 3; + optional bool aec_extended_filter_enabled = 4; + optional int32 aec_suppression_level = 5; + // Mobile AEC. + optional bool aecm_enabled = 6; + optional bool aecm_comfort_noise_enabled = 7; + optional int32 aecm_routing_mode = 8; + // Automatic gain controller. + optional bool agc_enabled = 9; + optional int32 agc_mode = 10; + optional bool agc_limiter_enabled = 11; + optional bool noise_robust_agc_enabled = 12; + // High pass filter. + optional bool hpf_enabled = 13; + // Noise suppression. + optional bool ns_enabled = 14; + optional int32 ns_level = 15; + // Transient suppression. + optional bool transient_suppression_enabled = 16; +} + message Event { enum Type { INIT = 0; REVERSE_STREAM = 1; STREAM = 2; + CONFIG = 3; + UNKNOWN_EVENT = 4; } required Type type = 1; @@ -51,4 +83,5 @@ message Event { optional Init init = 2; optional ReverseStream reverse_stream = 3; optional Stream stream = 4; + optional Config config = 5; } diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc index 86ed9234c7..567d9a47f8 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc @@ -280,6 +280,14 @@ bool EchoCancellationImpl::is_delay_logging_enabled() const { return delay_logging_enabled_; } +bool EchoCancellationImpl::is_delay_agnostic_enabled() const { + return delay_agnostic_enabled_; +} + +bool EchoCancellationImpl::is_extended_filter_enabled() const { + return extended_filter_enabled_; +} + // TODO(bjornv): How should we handle the multi-channel case? int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { float fraction_poor_delays = 0; diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.h b/webrtc/modules/audio_processing/echo_cancellation_impl.h index 9c2b32c473..070dcabc5d 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.h +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.h @@ -32,19 +32,22 @@ class EchoCancellationImpl : public EchoCancellation, // EchoCancellation implementation. bool is_enabled() const override; int stream_drift_samples() const override; + SuppressionLevel suppression_level() const override; + bool is_drift_compensation_enabled() const override; // ProcessingComponent implementation. int Initialize() override; void SetExtraOptions(const Config& config) override; + bool is_delay_agnostic_enabled() const; + bool is_extended_filter_enabled() const; + private: // EchoCancellation implementation. int Enable(bool enable) override; int enable_drift_compensation(bool enable) override; - bool is_drift_compensation_enabled() const override; void set_stream_drift_samples(int drift) override; int set_suppression_level(SuppressionLevel level) override; - SuppressionLevel suppression_level() const override; int enable_metrics(bool enable) override; bool are_metrics_enabled() const override; bool stream_has_echo() const override; diff --git a/webrtc/modules/audio_processing/echo_control_mobile_impl.h b/webrtc/modules/audio_processing/echo_control_mobile_impl.h index f399f480b2..da7022545f 100644 --- a/webrtc/modules/audio_processing/echo_control_mobile_impl.h +++ b/webrtc/modules/audio_processing/echo_control_mobile_impl.h @@ -31,6 +31,8 @@ class EchoControlMobileImpl : public EchoControlMobile, // EchoControlMobile implementation. bool is_enabled() const override; + RoutingMode routing_mode() const override; + bool is_comfort_noise_enabled() const override; // ProcessingComponent implementation. int Initialize() override; @@ -39,9 +41,7 @@ class EchoControlMobileImpl : public EchoControlMobile, // EchoControlMobile implementation. int Enable(bool enable) override; int set_routing_mode(RoutingMode mode) override; - RoutingMode routing_mode() const override; int enable_comfort_noise(bool enable) override; - bool is_comfort_noise_enabled() const override; int SetEchoPath(const void* echo_path, size_t size_bytes) override; int GetEchoPath(void* echo_path, size_t size_bytes) const override; diff --git a/webrtc/modules/audio_processing/gain_control_impl.h b/webrtc/modules/audio_processing/gain_control_impl.h index d64894367c..f24d200cf2 100644 --- a/webrtc/modules/audio_processing/gain_control_impl.h +++ b/webrtc/modules/audio_processing/gain_control_impl.h @@ -38,19 +38,19 @@ class GainControlImpl : public GainControl, // GainControl implementation. bool is_enabled() const override; int stream_analog_level() override; + bool is_limiter_enabled() const override; + Mode mode() const override; private: // GainControl implementation. int Enable(bool enable) override; int set_stream_analog_level(int level) override; int set_mode(Mode mode) override; - Mode mode() const override; int set_target_level_dbfs(int level) override; int target_level_dbfs() const override; int set_compression_gain_db(int gain) override; int compression_gain_db() const override; int enable_limiter(bool enable) override; - bool is_limiter_enabled() const override; int set_analog_level_limits(int minimum, int maximum) override; int analog_level_minimum() const override; int analog_level_maximum() const override; diff --git a/webrtc/modules/audio_processing/noise_suppression_impl.h b/webrtc/modules/audio_processing/noise_suppression_impl.h index 33a0e060a6..76a39b8e09 100644 --- a/webrtc/modules/audio_processing/noise_suppression_impl.h +++ b/webrtc/modules/audio_processing/noise_suppression_impl.h @@ -32,12 +32,12 @@ class NoiseSuppressionImpl : public NoiseSuppression, // NoiseSuppression implementation. bool is_enabled() const override; float speech_probability() const override; + Level level() const override; private: // NoiseSuppression implementation. int Enable(bool enable) override; int set_level(Level level) override; - Level level() const override; // ProcessingComponent implementation. void* CreateHandle() const override; diff --git a/webrtc/modules/audio_processing/test/unpack.cc b/webrtc/modules/audio_processing/test/unpack.cc index 2484828bd1..24578e240c 100644 --- a/webrtc/modules/audio_processing/test/unpack.cc +++ b/webrtc/modules/audio_processing/test/unpack.cc @@ -40,6 +40,11 @@ DEFINE_bool(text, false, "Write non-audio files as text files instead of binary files."); +#define PRINT_CONFIG(field_name) \ + if (msg.has_##field_name()) { \ + fprintf(settings_file, " " #field_name ": %d\n", msg.field_name()); \ + } + namespace webrtc { using audioproc::Event; @@ -83,6 +88,9 @@ int do_main(int argc, char* argv[]) { rtc::scoped_ptr reverse_raw_file; rtc::scoped_ptr input_raw_file; rtc::scoped_ptr output_raw_file; + + FILE* settings_file = OpenFile(FLAGS_settings_file, "wb"); + while (ReadMessageFromFile(debug_file, &event_msg)) { if (event_msg.type() == Event::REVERSE_STREAM) { if (!event_msg.has_reverse_stream()) { @@ -217,13 +225,37 @@ int do_main(int argc, char* argv[]) { } } } + } else if (event_msg.type() == Event::CONFIG) { + if (!event_msg.has_config()) { + printf("Corrupt input file: Config missing.\n"); + return 1; + } + const audioproc::Config msg = event_msg.config(); + + fprintf(settings_file, "APM re-config at frame: %d\n", frame_count); + + PRINT_CONFIG(aec_enabled); + PRINT_CONFIG(aec_delay_agnostic_enabled); + PRINT_CONFIG(aec_drift_compensation_enabled); + PRINT_CONFIG(aec_extended_filter_enabled); + PRINT_CONFIG(aec_suppression_level); + PRINT_CONFIG(aecm_enabled); + PRINT_CONFIG(aecm_comfort_noise_enabled); + PRINT_CONFIG(aecm_routing_mode); + PRINT_CONFIG(agc_enabled); + PRINT_CONFIG(agc_mode); + PRINT_CONFIG(agc_limiter_enabled); + PRINT_CONFIG(noise_robust_agc_enabled); + PRINT_CONFIG(hpf_enabled); + PRINT_CONFIG(ns_enabled); + PRINT_CONFIG(ns_level); + PRINT_CONFIG(transient_suppression_enabled); } else if (event_msg.type() == Event::INIT) { if (!event_msg.has_init()) { printf("Corrupt input file: Init missing.\n"); return 1; } - static FILE* settings_file = OpenFile(FLAGS_settings_file, "wb"); const Init msg = event_msg.init(); // These should print out zeros if they're missing. fprintf(settings_file, "Init at frame: %d\n", frame_count);